Compare commits
	
		
			54 Commits
		
	
	
		
			v1.0.0-rc1
			...
			v1.2.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 248d88c849 | ||
|   | d19535fa21 | ||
|   | 49204cafcc | ||
|   | 812db2d267 | ||
|   | 14490bea9f | ||
|   | 0352970051 | ||
|   | ed01820722 | ||
|   | 90a61f15cc | ||
|   | 86cd7f1ba6 | ||
|   | d6ee55e35f | ||
|   | aef64eec32 | ||
|   | c4193d5ccd | ||
|   | 0c94186818 | ||
|   | 9039720013 | ||
|   | a3470f8aec | ||
|   | 01badde21d | ||
|   | a37b232dd9 | ||
|   | 579ee48385 | ||
|   | dd985d1dad | ||
|   | d2caea70a2 | ||
|   | 21143cf5ee | ||
|   | dc2aed698d | ||
|   | 37c350f19f | ||
|   | 9e03fcf162 | ||
|   | 8d4521c1df | ||
|   | 9226252336 | ||
|   | f4fb83e787 | ||
|   | e7fcb25107 | ||
|   | 5a85258f74 | ||
|   | 2f7df2df43 | ||
|   | ad3a753718 | ||
|   | e45c551880 | ||
|   | e59d338d4e | ||
|   | 7a86044f7a | ||
|   | 8b98f605bc | ||
|   | 7c773ebae0 | ||
|   | e84417430d | ||
|   | 5a8d7b5f6d | ||
|   | cfb8107138 | ||
|   | 43bd779fb7 | ||
|   | 7f9a400776 | ||
|   | ce1c5873ac | ||
|   | 85ff1995fd | ||
|   | b963f83c6a | ||
|   | f6297ebbb0 | ||
|   | a5259f56c5 | ||
|   | 3f75ed9c18 | ||
|   | 49ece51167 | ||
|   | e77c3eb20a | ||
|   | 59b2a5f8d0 | ||
|   | 28710d0bc7 | ||
|   | ad4d461606 | ||
|   | 67905089ba | ||
|   | f2483af561 | 
| @@ -1,7 +1,7 @@ | |||||||
| language: go | language: go | ||||||
| go: | go: | ||||||
|     #- 1.7.x |     #- 1.7.x | ||||||
|     - 1.8.x |     - 1.9.x | ||||||
|       # - tip |       # - tip | ||||||
|  |  | ||||||
| # we have everything vendored | # we have everything vendored | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ Has a REST API. | |||||||
|  |  | ||||||
| # Requirements | # Requirements | ||||||
| Accounts to one of the supported bridges | Accounts to one of the supported bridges | ||||||
| * [Mattermost](https://github.com/mattermost/platform/) 3.5.x - 3.10.x, 4.0.x | * [Mattermost](https://github.com/mattermost/platform/) 3.8.x - 3.10.x, 4.0.x - 4.2.x | ||||||
| * [IRC](http://www.mirc.com/servers.html) | * [IRC](http://www.mirc.com/servers.html) | ||||||
| * [XMPP](https://jabber.org) | * [XMPP](https://jabber.org) | ||||||
| * [Gitter](https://gitter.im) | * [Gitter](https://gitter.im) | ||||||
| @@ -53,7 +53,7 @@ See https://github.com/42wim/matterbridge/wiki | |||||||
|  |  | ||||||
| # Installing | # Installing | ||||||
| ## Binaries | ## Binaries | ||||||
| * Latest stable release [v1.0.0-rc1](https://github.com/42wim/matterbridge/releases/latest) | * Latest stable release [v1.2.0](https://github.com/42wim/matterbridge/releases/latest) | ||||||
| * Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)   | * Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)   | ||||||
|  |  | ||||||
| ## Building | ## Building | ||||||
|   | |||||||
| @@ -61,16 +61,20 @@ func (b *Api) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
| } | } | ||||||
| func (b *Api) JoinChannel(channel string) error { | func (b *Api) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Api) Send(msg config.Message) error { | func (b *Api) Send(msg config.Message) (string, error) { | ||||||
| 	b.Lock() | 	b.Lock() | ||||||
| 	defer b.Unlock() | 	defer b.Unlock() | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	b.Messages.Enqueue(&msg) | 	b.Messages.Enqueue(&msg) | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Api) handlePostMessage(c echo.Context) error { | func (b *Api) handlePostMessage(c echo.Context) error { | ||||||
|   | |||||||
| @@ -19,9 +19,9 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type Bridger interface { | type Bridger interface { | ||||||
| 	Send(msg config.Message) error | 	Send(msg config.Message) (string, error) | ||||||
| 	Connect() error | 	Connect() error | ||||||
| 	JoinChannel(channel string) error | 	JoinChannel(channel config.ChannelInfo) error | ||||||
| 	Disconnect() error | 	Disconnect() error | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -92,16 +92,10 @@ func (b *Bridge) JoinChannels() error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map[string]bool) error { | func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map[string]bool) error { | ||||||
| 	mychannel := "" |  | ||||||
| 	for ID, channel := range channels { | 	for ID, channel := range channels { | ||||||
| 		if !exists[ID] { | 		if !exists[ID] { | ||||||
| 			mychannel = channel.Name |  | ||||||
| 			log.Infof("%s: joining %s (%s)", b.Account, channel.Name, ID) | 			log.Infof("%s: joining %s (%s)", b.Account, channel.Name, ID) | ||||||
| 			if b.Protocol == "irc" && channel.Options.Key != "" { | 			err := b.JoinChannel(channel) | ||||||
| 				log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name) |  | ||||||
| 				mychannel = mychannel + " " + channel.Options.Key |  | ||||||
| 			} |  | ||||||
| 			err := b.JoinChannel(mychannel) |  | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ const ( | |||||||
| 	EVENT_FAILURE         = "failure" | 	EVENT_FAILURE         = "failure" | ||||||
| 	EVENT_REJOIN_CHANNELS = "rejoin_channels" | 	EVENT_REJOIN_CHANNELS = "rejoin_channels" | ||||||
| 	EVENT_USER_ACTION     = "user_action" | 	EVENT_USER_ACTION     = "user_action" | ||||||
|  | 	EVENT_MSG_DELETE      = "msg_delete" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type Message struct { | type Message struct { | ||||||
| @@ -27,6 +28,7 @@ type Message struct { | |||||||
| 	Protocol  string    `json:"protocol"` | 	Protocol  string    `json:"protocol"` | ||||||
| 	Gateway   string    `json:"gateway"` | 	Gateway   string    `json:"gateway"` | ||||||
| 	Timestamp time.Time `json:"timestamp"` | 	Timestamp time.Time `json:"timestamp"` | ||||||
|  | 	ID        string    `json:"id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type ChannelInfo struct { | type ChannelInfo struct { | ||||||
| @@ -42,6 +44,7 @@ type Protocol struct { | |||||||
| 	AuthCode               string // steam | 	AuthCode               string // steam | ||||||
| 	BindAddress            string // mattermost, slack // DEPRECATED | 	BindAddress            string // mattermost, slack // DEPRECATED | ||||||
| 	Buffer                 int    // api | 	Buffer                 int    // api | ||||||
|  | 	Charset                string // irc | ||||||
| 	EditSuffix             string // mattermost, slack, discord, telegram, gitter | 	EditSuffix             string // mattermost, slack, discord, telegram, gitter | ||||||
| 	EditDisable            bool   // mattermost, slack, discord, telegram, gitter | 	EditDisable            bool   // mattermost, slack, discord, telegram, gitter | ||||||
| 	IconURL                string // mattermost, slack | 	IconURL                string // mattermost, slack | ||||||
| @@ -77,6 +80,7 @@ type Protocol struct { | |||||||
| 	UseSASL                bool   // IRC | 	UseSASL                bool   // IRC | ||||||
| 	UseTLS                 bool   // IRC | 	UseTLS                 bool   // IRC | ||||||
| 	UseFirstName           bool   // telegram | 	UseFirstName           bool   // telegram | ||||||
|  | 	UseUserName            bool   // discord | ||||||
| 	UseInsecureURL         bool   // telegram | 	UseInsecureURL         bool   // telegram | ||||||
| 	WebhookBindAddress     string // mattermost, slack | 	WebhookBindAddress     string // mattermost, slack | ||||||
| 	WebhookURL             string // mattermost, slack | 	WebhookURL             string // mattermost, slack | ||||||
| @@ -84,7 +88,8 @@ type Protocol struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type ChannelOptions struct { | type ChannelOptions struct { | ||||||
| 	Key string // irc | 	Key        string // irc | ||||||
|  | 	WebhookURL string // discord | ||||||
| } | } | ||||||
|  |  | ||||||
| type Bridge struct { | type Bridge struct { | ||||||
|   | |||||||
| @@ -10,17 +10,18 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type bdiscord struct { | type bdiscord struct { | ||||||
| 	c             *discordgo.Session | 	c              *discordgo.Session | ||||||
| 	Config        *config.Protocol | 	Config         *config.Protocol | ||||||
| 	Remote        chan config.Message | 	Remote         chan config.Message | ||||||
| 	Account       string | 	Account        string | ||||||
| 	Channels      []*discordgo.Channel | 	Channels       []*discordgo.Channel | ||||||
| 	Nick          string | 	Nick           string | ||||||
| 	UseChannelID  bool | 	UseChannelID   bool | ||||||
| 	userMemberMap map[string]*discordgo.Member | 	userMemberMap  map[string]*discordgo.Member | ||||||
| 	guildID       string | 	guildID        string | ||||||
| 	webhookID     string | 	webhookID      string | ||||||
| 	webhookToken  string | 	webhookToken   string | ||||||
|  | 	channelInfoMap map[string]*config.ChannelInfo | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -37,11 +38,10 @@ func New(cfg config.Protocol, account string, c chan config.Message) *bdiscord { | |||||||
| 	b.Remote = c | 	b.Remote = c | ||||||
| 	b.Account = account | 	b.Account = account | ||||||
| 	b.userMemberMap = make(map[string]*discordgo.Member) | 	b.userMemberMap = make(map[string]*discordgo.Member) | ||||||
|  | 	b.channelInfoMap = make(map[string]*config.ChannelInfo) | ||||||
| 	if b.Config.WebhookURL != "" { | 	if b.Config.WebhookURL != "" { | ||||||
| 		flog.Debug("Configuring Discord Incoming Webhook") | 		flog.Debug("Configuring Discord Incoming Webhook") | ||||||
| 		webhookURLSplit := strings.Split(b.Config.WebhookURL, "/") | 		b.webhookID, b.webhookToken = b.splitURL(b.Config.WebhookURL) | ||||||
| 		b.webhookToken = webhookURLSplit[len(webhookURLSplit)-1] |  | ||||||
| 		b.webhookID = webhookURLSplit[len(webhookURLSplit)-2] |  | ||||||
| 	} | 	} | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
| @@ -66,6 +66,7 @@ func (b *bdiscord) Connect() error { | |||||||
| 	b.c.AddHandler(b.messageCreate) | 	b.c.AddHandler(b.messageCreate) | ||||||
| 	b.c.AddHandler(b.memberUpdate) | 	b.c.AddHandler(b.memberUpdate) | ||||||
| 	b.c.AddHandler(b.messageUpdate) | 	b.c.AddHandler(b.messageUpdate) | ||||||
|  | 	b.c.AddHandler(b.messageDelete) | ||||||
| 	err = b.c.Open() | 	err = b.c.Open() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		flog.Debugf("%#v", err) | 		flog.Debugf("%#v", err) | ||||||
| @@ -99,44 +100,75 @@ func (b *bdiscord) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *bdiscord) JoinChannel(channel string) error { | func (b *bdiscord) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	idcheck := strings.Split(channel, "ID:") | 	b.channelInfoMap[channel.ID] = &channel | ||||||
|  | 	idcheck := strings.Split(channel.Name, "ID:") | ||||||
| 	if len(idcheck) > 1 { | 	if len(idcheck) > 1 { | ||||||
| 		b.UseChannelID = true | 		b.UseChannelID = true | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *bdiscord) Send(msg config.Message) error { | func (b *bdiscord) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	channelID := b.getChannelID(msg.Channel) | 	channelID := b.getChannelID(msg.Channel) | ||||||
| 	if channelID == "" { | 	if channelID == "" { | ||||||
| 		flog.Errorf("Could not find channelID for %v", msg.Channel) | 		flog.Errorf("Could not find channelID for %v", msg.Channel) | ||||||
| 		return nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 	if b.Config.WebhookURL == "" { | 	if msg.Event == config.EVENT_USER_ACTION { | ||||||
|  | 		msg.Text = "_" + msg.Text + "_" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wID := b.webhookID | ||||||
|  | 	wToken := b.webhookToken | ||||||
|  | 	if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok { | ||||||
|  | 		if ci.Options.WebhookURL != "" { | ||||||
|  | 			wID, wToken = b.splitURL(ci.Options.WebhookURL) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if wID == "" { | ||||||
| 		flog.Debugf("Broadcasting using token (API)") | 		flog.Debugf("Broadcasting using token (API)") | ||||||
| 		if msg.Event == config.EVENT_USER_ACTION { | 		if msg.Event == config.EVENT_MSG_DELETE { | ||||||
| 			msg.Username = "_" + msg.Username | 			if msg.ID == "" { | ||||||
| 			msg.Text = msg.Text + "_" | 				return "", nil | ||||||
|  | 			} | ||||||
|  | 			err := b.c.ChannelMessageDelete(channelID, msg.ID) | ||||||
|  | 			return "", err | ||||||
| 		} | 		} | ||||||
| 		b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) | 		if msg.ID != "" { | ||||||
| 	} else { | 			_, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text) | ||||||
| 		flog.Debugf("Broadcasting using Webhook") | 			return msg.ID, err | ||||||
| 		if msg.Event == config.EVENT_USER_ACTION { |  | ||||||
| 			msg.Text = "_" + msg.Text + "_" |  | ||||||
| 		} | 		} | ||||||
| 		b.c.WebhookExecute( | 		res, err := b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) | ||||||
| 			b.webhookID, | 		if err != nil { | ||||||
| 			b.webhookToken, | 			return "", err | ||||||
| 			true, | 		} | ||||||
| 			&discordgo.WebhookParams{ | 		return res.ID, err | ||||||
| 				Content:   msg.Text, |  | ||||||
| 				Username:  msg.Username, |  | ||||||
| 				AvatarURL: msg.Avatar, |  | ||||||
| 			}) |  | ||||||
| 	} | 	} | ||||||
| 	return nil | 	flog.Debugf("Broadcasting using Webhook") | ||||||
|  | 	err := b.c.WebhookExecute( | ||||||
|  | 		wID, | ||||||
|  | 		wToken, | ||||||
|  | 		true, | ||||||
|  | 		&discordgo.WebhookParams{ | ||||||
|  | 			Content:   msg.Text, | ||||||
|  | 			Username:  msg.Username, | ||||||
|  | 			AvatarURL: msg.Avatar, | ||||||
|  | 		}) | ||||||
|  | 	return "", err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (b *bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { | ||||||
|  | 	rmsg := config.Message{Account: b.Account, ID: m.ID, Event: config.EVENT_MSG_DELETE, Text: config.EVENT_MSG_DELETE} | ||||||
|  | 	rmsg.Channel = b.getChannelName(m.ChannelID) | ||||||
|  | 	if b.UseChannelID { | ||||||
|  | 		rmsg.Channel = "ID:" + m.ChannelID | ||||||
|  | 	} | ||||||
|  | 	flog.Debugf("Sending message from %s to gateway", b.Account) | ||||||
|  | 	flog.Debugf("Message is %#v", rmsg) | ||||||
|  | 	b.Remote <- rmsg | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) { | func (b *bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) { | ||||||
| @@ -157,7 +189,7 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// if using webhooks, do not relay if it's ours | 	// if using webhooks, do not relay if it's ours | ||||||
| 	if b.Config.WebhookURL != "" && m.Author.Bot && m.Author.ID == b.webhookID { | 	if b.useWebhook() && m.Author.Bot && b.isWebhookID(m.Author.ID) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -179,13 +211,18 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", | 	rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", | ||||||
| 		UserID: m.Author.ID} | 		UserID: m.Author.ID, ID: m.ID} | ||||||
|  |  | ||||||
| 	rmsg.Channel = b.getChannelName(m.ChannelID) | 	rmsg.Channel = b.getChannelName(m.ChannelID) | ||||||
| 	if b.UseChannelID { | 	if b.UseChannelID { | ||||||
| 		rmsg.Channel = "ID:" + m.ChannelID | 		rmsg.Channel = "ID:" + m.ChannelID | ||||||
| 	} | 	} | ||||||
| 	rmsg.Username = b.getNick(m.Author) |  | ||||||
|  | 	if !b.Config.UseUserName { | ||||||
|  | 		rmsg.Username = b.getNick(m.Author) | ||||||
|  | 	} else { | ||||||
|  | 		rmsg.Username = m.Author.Username | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if b.Config.ShowEmbeds && m.Message.Embeds != nil { | 	if b.Config.ShowEmbeds && m.Message.Embeds != nil { | ||||||
| 		for _, embed := range m.Message.Embeds { | 		for _, embed := range m.Message.Embeds { | ||||||
| @@ -205,6 +242,7 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | |||||||
|  |  | ||||||
| 	rmsg.Text = text | 	rmsg.Text = text | ||||||
| 	flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account) | 	flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account) | ||||||
|  | 	flog.Debugf("Message is %#v", rmsg) | ||||||
| 	b.Remote <- rmsg | 	b.Remote <- rmsg | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -309,3 +347,41 @@ func (b *bdiscord) stripCustomoji(text string) string { | |||||||
| 	re := regexp.MustCompile("<(:.*?:)[0-9]+>") | 	re := regexp.MustCompile("<(:.*?:)[0-9]+>") | ||||||
| 	return re.ReplaceAllString(text, `$1`) | 	return re.ReplaceAllString(text, `$1`) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // splitURL splits a webhookURL and returns the id and token | ||||||
|  | func (b *bdiscord) splitURL(url string) (string, string) { | ||||||
|  | 	webhookURLSplit := strings.Split(url, "/") | ||||||
|  | 	return webhookURLSplit[len(webhookURLSplit)-2], webhookURLSplit[len(webhookURLSplit)-1] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // useWebhook returns true if we have a webhook defined somewhere | ||||||
|  | func (b *bdiscord) useWebhook() bool { | ||||||
|  | 	if b.Config.WebhookURL != "" { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	for _, channel := range b.channelInfoMap { | ||||||
|  | 		if channel.Options.WebhookURL != "" { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // isWebhookID returns true if the specified id is used in a defined webhook | ||||||
|  | func (b *bdiscord) isWebhookID(id string) bool { | ||||||
|  | 	if b.Config.WebhookURL != "" { | ||||||
|  | 		wID, _ := b.splitURL(b.Config.WebhookURL) | ||||||
|  | 		if wID == id { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	for _, channel := range b.channelInfoMap { | ||||||
|  | 		if channel.Options.WebhookURL != "" { | ||||||
|  | 			wID, _ := b.splitURL(channel.Options.WebhookURL) | ||||||
|  | 			if wID == id { | ||||||
|  | 				return true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|   | |||||||
| @@ -2,9 +2,9 @@ package bgitter | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"github.com/42wim/go-gitter" | ||||||
| 	"github.com/42wim/matterbridge/bridge/config" | 	"github.com/42wim/matterbridge/bridge/config" | ||||||
| 	log "github.com/Sirupsen/logrus" | 	log "github.com/Sirupsen/logrus" | ||||||
| 	"github.com/sromku/go-gitter" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -13,6 +13,7 @@ type Bgitter struct { | |||||||
| 	Config  *config.Protocol | 	Config  *config.Protocol | ||||||
| 	Remote  chan config.Message | 	Remote  chan config.Message | ||||||
| 	Account string | 	Account string | ||||||
|  | 	User    *gitter.User | ||||||
| 	Users   []gitter.User | 	Users   []gitter.User | ||||||
| 	Rooms   []gitter.Room | 	Rooms   []gitter.Room | ||||||
| } | } | ||||||
| @@ -36,7 +37,7 @@ func (b *Bgitter) Connect() error { | |||||||
| 	var err error | 	var err error | ||||||
| 	flog.Info("Connecting") | 	flog.Info("Connecting") | ||||||
| 	b.c = gitter.New(b.Config.Token) | 	b.c = gitter.New(b.Config.Token) | ||||||
| 	_, err = b.c.GetUser() | 	b.User, err = b.c.GetUser() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		flog.Debugf("%#v", err) | 		flog.Debugf("%#v", err) | ||||||
| 		return err | 		return err | ||||||
| @@ -51,10 +52,10 @@ func (b *Bgitter) Disconnect() error { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bgitter) JoinChannel(channel string) error { | func (b *Bgitter) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	roomID, err := b.c.GetRoomId(channel) | 	roomID, err := b.c.GetRoomId(channel.Name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("Could not find roomID for %v. Please create the room on gitter.im", channel) | 		return fmt.Errorf("Could not find roomID for %v. Please create the room on gitter.im", channel.Name) | ||||||
| 	} | 	} | ||||||
| 	room, err := b.c.GetRoom(roomID) | 	room, err := b.c.GetRoom(roomID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -78,15 +79,16 @@ func (b *Bgitter) JoinChannel(channel string) error { | |||||||
| 		for event := range stream.Event { | 		for event := range stream.Event { | ||||||
| 			switch ev := event.Data.(type) { | 			switch ev := event.Data.(type) { | ||||||
| 			case *gitter.MessageReceived: | 			case *gitter.MessageReceived: | ||||||
| 				// check for ZWSP to see if it's not an echo | 				if ev.Message.From.ID != b.User.ID { | ||||||
| 				if !strings.HasSuffix(ev.Message.Text, "") { |  | ||||||
| 					flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account) | 					flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account) | ||||||
| 					rmsg := config.Message{Username: ev.Message.From.Username, Text: ev.Message.Text, Channel: room, | 					rmsg := config.Message{Username: ev.Message.From.Username, Text: ev.Message.Text, Channel: room, | ||||||
| 						Account: b.Account, Avatar: b.getAvatar(ev.Message.From.Username), UserID: ev.Message.From.ID} | 						Account: b.Account, Avatar: b.getAvatar(ev.Message.From.Username), UserID: ev.Message.From.ID, | ||||||
|  | 						ID: ev.Message.ID} | ||||||
| 					if strings.HasPrefix(ev.Message.Text, "@"+ev.Message.From.Username) { | 					if strings.HasPrefix(ev.Message.Text, "@"+ev.Message.From.Username) { | ||||||
| 						rmsg.Event = config.EVENT_USER_ACTION | 						rmsg.Event = config.EVENT_USER_ACTION | ||||||
| 						rmsg.Text = strings.Replace(rmsg.Text, "@"+ev.Message.From.Username+" ", "", -1) | 						rmsg.Text = strings.Replace(rmsg.Text, "@"+ev.Message.From.Username+" ", "", -1) | ||||||
| 					} | 					} | ||||||
|  | 					flog.Debugf("Message is %#v", rmsg) | ||||||
| 					b.Remote <- rmsg | 					b.Remote <- rmsg | ||||||
| 				} | 				} | ||||||
| 			case *gitter.GitterConnectionClosed: | 			case *gitter.GitterConnectionClosed: | ||||||
| @@ -97,15 +99,37 @@ func (b *Bgitter) JoinChannel(channel string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bgitter) Send(msg config.Message) error { | func (b *Bgitter) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	roomID := b.getRoomID(msg.Channel) | 	roomID := b.getRoomID(msg.Channel) | ||||||
| 	if roomID == "" { | 	if roomID == "" { | ||||||
| 		flog.Errorf("Could not find roomID for %v", msg.Channel) | 		flog.Errorf("Could not find roomID for %v", msg.Channel) | ||||||
| 		return nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 	// add ZWSP because gitter echoes our own messages | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
| 	return b.c.SendMessage(roomID, msg.Username+msg.Text+" ") | 		if msg.ID == "" { | ||||||
|  | 			return "", nil | ||||||
|  | 		} | ||||||
|  | 		// gitter has no delete message api | ||||||
|  | 		_, err := b.c.UpdateMessage(roomID, msg.ID, "") | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  | 	if msg.ID != "" { | ||||||
|  | 		flog.Debugf("updating message with id %s", msg.ID) | ||||||
|  | 		_, err := b.c.UpdateMessage(roomID, msg.ID, msg.Username+msg.Text) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  | 	resp, err := b.c.SendMessage(roomID, msg.Username+msg.Text) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return resp.ID, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bgitter) getRoomID(channel string) string { | func (b *Bgitter) getRoomID(channel string) string { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package birc | package birc | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
| 	"crypto/tls" | 	"crypto/tls" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/42wim/go-ircevent" | 	"github.com/42wim/go-ircevent" | ||||||
| @@ -117,16 +118,38 @@ func (b *Birc) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Birc) JoinChannel(channel string) error { | func (b *Birc) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	b.i.Join(channel) | 	if channel.Options.Key != "" { | ||||||
|  | 		flog.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name) | ||||||
|  | 		b.i.Join(channel.Name + " " + channel.Options.Key) | ||||||
|  | 	} else { | ||||||
|  | 		b.i.Join(channel.Name) | ||||||
|  | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Birc) Send(msg config.Message) error { | func (b *Birc) Send(msg config.Message) (string, error) { | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	if strings.HasPrefix(msg.Text, "!") { | 	if strings.HasPrefix(msg.Text, "!") { | ||||||
| 		b.Command(&msg) | 		b.Command(&msg) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if b.Config.Charset != "" { | ||||||
|  | 		buf := new(bytes.Buffer) | ||||||
|  | 		w, err := charset.NewWriter(b.Config.Charset, buf) | ||||||
|  | 		if err != nil { | ||||||
|  | 			flog.Errorf("charset from utf-8 conversion failed: %s", err) | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		fmt.Fprintf(w, msg.Text) | ||||||
|  | 		w.Close() | ||||||
|  | 		msg.Text = buf.String() | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	for _, text := range strings.Split(msg.Text, "\n") { | 	for _, text := range strings.Split(msg.Text, "\n") { | ||||||
| 		if len(text) > b.Config.MessageLength { | 		if len(text) > b.Config.MessageLength { | ||||||
| 			text = text[:b.Config.MessageLength] + " <message clipped>" | 			text = text[:b.Config.MessageLength] + " <message clipped>" | ||||||
| @@ -140,7 +163,7 @@ func (b *Birc) Send(msg config.Message) error { | |||||||
| 			flog.Debugf("flooding, dropping message (queue at %d)", len(b.Local)) | 			flog.Debugf("flooding, dropping message (queue at %d)", len(b.Local)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Birc) doSend() { | func (b *Birc) doSend() { | ||||||
| @@ -260,20 +283,25 @@ func (b *Birc) handlePrivMsg(event *irc.Event) { | |||||||
| 	re := regexp.MustCompile(`[[:cntrl:]](\d+,|)\d+`) | 	re := regexp.MustCompile(`[[:cntrl:]](\d+,|)\d+`) | ||||||
| 	msg = re.ReplaceAllString(msg, "") | 	msg = re.ReplaceAllString(msg, "") | ||||||
|  |  | ||||||
| 	// detect what were sending so that we convert it to utf-8 |  | ||||||
| 	detector := chardet.NewTextDetector() |  | ||||||
| 	result, err := detector.DetectBest([]byte(msg)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		flog.Infof("detection failed for msg: %#v", msg) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	flog.Debugf("detected %s confidence %#v", result.Charset, result.Confidence) |  | ||||||
| 	var r io.Reader | 	var r io.Reader | ||||||
| 	r, err = charset.NewReader(result.Charset, strings.NewReader(msg)) | 	var err error | ||||||
| 	// if we're not sure, just pick ISO-8859-1 | 	mycharset := b.Config.Charset | ||||||
| 	if result.Confidence < 80 { | 	if mycharset == "" { | ||||||
| 		r, err = charset.NewReader("ISO-8859-1", strings.NewReader(msg)) | 		// detect what were sending so that we convert it to utf-8 | ||||||
|  | 		detector := chardet.NewTextDetector() | ||||||
|  | 		result, err := detector.DetectBest([]byte(msg)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			flog.Infof("detection failed for msg: %#v", msg) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		flog.Debugf("detected %s confidence %#v", result.Charset, result.Confidence) | ||||||
|  | 		mycharset = result.Charset | ||||||
|  | 		// if we're not sure, just pick ISO-8859-1 | ||||||
|  | 		if result.Confidence < 80 { | ||||||
|  | 			mycharset = "ISO-8859-1" | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 	r, err = charset.NewReader(mycharset, strings.NewReader(msg)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		flog.Errorf("charset to utf-8 conversion failed: %s", err) | 		flog.Errorf("charset to utf-8 conversion failed: %s", err) | ||||||
| 		return | 		return | ||||||
|   | |||||||
| @@ -63,28 +63,32 @@ func (b *Bmatrix) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmatrix) JoinChannel(channel string) error { | func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	resp, err := b.mc.JoinRoom(channel, "", nil) | 	resp, err := b.mc.JoinRoom(channel.Name, "", nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	b.Lock() | 	b.Lock() | ||||||
| 	b.RoomMap[resp.RoomID] = channel | 	b.RoomMap[resp.RoomID] = channel.Name | ||||||
| 	b.Unlock() | 	b.Unlock() | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmatrix) Send(msg config.Message) error { | func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	channel := b.getRoomID(msg.Channel) | 	channel := b.getRoomID(msg.Channel) | ||||||
| 	flog.Debugf("Sending to channel %s", channel) | 	flog.Debugf("Sending to channel %s", channel) | ||||||
| 	if msg.Event == config.EVENT_USER_ACTION { | 	if msg.Event == config.EVENT_USER_ACTION { | ||||||
| 		b.mc.SendMessageEvent(channel, "m.room.message", | 		b.mc.SendMessageEvent(channel, "m.room.message", | ||||||
| 			matrix.TextMessage{"m.emote", msg.Username + msg.Text}) | 			matrix.TextMessage{"m.emote", msg.Username + msg.Text}) | ||||||
| 		return nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 	b.mc.SendText(channel, msg.Username+msg.Text) | 	b.mc.SendText(channel, msg.Username+msg.Text) | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmatrix) getRoomID(channel string) string { | func (b *Bmatrix) getRoomID(channel string) string { | ||||||
| @@ -100,7 +104,7 @@ func (b *Bmatrix) getRoomID(channel string) string { | |||||||
| func (b *Bmatrix) handlematrix() error { | func (b *Bmatrix) handlematrix() error { | ||||||
| 	syncer := b.mc.Syncer.(*matrix.DefaultSyncer) | 	syncer := b.mc.Syncer.(*matrix.DefaultSyncer) | ||||||
| 	syncer.OnEventType("m.room.message", func(ev *matrix.Event) { | 	syncer.OnEventType("m.room.message", func(ev *matrix.Event) { | ||||||
| 		if (ev.Content["msgtype"].(string) == "m.text" || ev.Content["msgtype"].(string) == "m.emote") && ev.Sender != b.UserID { | 		if (ev.Content["msgtype"].(string) == "m.text" || ev.Content["msgtype"].(string) == "m.notice" || ev.Content["msgtype"].(string) == "m.emote") && ev.Sender != b.UserID { | ||||||
| 			b.RLock() | 			b.RLock() | ||||||
| 			channel, ok := b.RoomMap[ev.RoomID] | 			channel, ok := b.RoomMap[ev.RoomID] | ||||||
| 			b.RUnlock() | 			b.RUnlock() | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package bmattermost | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| 	"github.com/42wim/matterbridge/bridge/config" | 	"github.com/42wim/matterbridge/bridge/config" | ||||||
| 	"github.com/42wim/matterbridge/matterclient" | 	"github.com/42wim/matterbridge/matterclient" | ||||||
| 	"github.com/42wim/matterbridge/matterhook" | 	"github.com/42wim/matterbridge/matterhook" | ||||||
| @@ -23,6 +24,8 @@ type MMMessage struct { | |||||||
| 	Channel  string | 	Channel  string | ||||||
| 	Username string | 	Username string | ||||||
| 	UserID   string | 	UserID   string | ||||||
|  | 	ID       string | ||||||
|  | 	Event    string | ||||||
| } | } | ||||||
|  |  | ||||||
| type Bmattermost struct { | type Bmattermost struct { | ||||||
| @@ -61,6 +64,12 @@ func (b *Bmattermost) Connect() error { | |||||||
| 			b.mh = matterhook.New(b.Config.WebhookURL, | 			b.mh = matterhook.New(b.Config.WebhookURL, | ||||||
| 				matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify, | 				matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify, | ||||||
| 					BindAddress: b.Config.WebhookBindAddress}) | 					BindAddress: b.Config.WebhookBindAddress}) | ||||||
|  | 		} else if b.Config.Token != "" { | ||||||
|  | 			flog.Info("Connecting using token (sending)") | ||||||
|  | 			err := b.apiLogin() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
| 		} else if b.Config.Login != "" { | 		} else if b.Config.Login != "" { | ||||||
| 			flog.Info("Connecting using login/password (sending)") | 			flog.Info("Connecting using login/password (sending)") | ||||||
| 			err := b.apiLogin() | 			err := b.apiLogin() | ||||||
| @@ -81,7 +90,14 @@ func (b *Bmattermost) Connect() error { | |||||||
| 		b.mh = matterhook.New(b.Config.WebhookURL, | 		b.mh = matterhook.New(b.Config.WebhookURL, | ||||||
| 			matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify, | 			matterhook.Config{InsecureSkipVerify: b.Config.SkipTLSVerify, | ||||||
| 				DisableServer: true}) | 				DisableServer: true}) | ||||||
| 		if b.Config.Login != "" { | 		if b.Config.Token != "" { | ||||||
|  | 			flog.Info("Connecting using token (receiving)") | ||||||
|  | 			err := b.apiLogin() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			go b.handleMatter() | ||||||
|  | 		} else if b.Config.Login != "" { | ||||||
| 			flog.Info("Connecting using login/password (receiving)") | 			flog.Info("Connecting using login/password (receiving)") | ||||||
| 			err := b.apiLogin() | 			err := b.apiLogin() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| @@ -90,6 +106,13 @@ func (b *Bmattermost) Connect() error { | |||||||
| 			go b.handleMatter() | 			go b.handleMatter() | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
|  | 	} else if b.Config.Token != "" { | ||||||
|  | 		flog.Info("Connecting using token (sending and receiving)") | ||||||
|  | 		err := b.apiLogin() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		go b.handleMatter() | ||||||
| 	} else if b.Config.Login != "" { | 	} else if b.Config.Login != "" { | ||||||
| 		flog.Info("Connecting using login/password (sending and receiving)") | 		flog.Info("Connecting using login/password (sending and receiving)") | ||||||
| 		err := b.apiLogin() | 		err := b.apiLogin() | ||||||
| @@ -98,8 +121,8 @@ func (b *Bmattermost) Connect() error { | |||||||
| 		} | 		} | ||||||
| 		go b.handleMatter() | 		go b.handleMatter() | ||||||
| 	} | 	} | ||||||
| 	if b.Config.WebhookBindAddress == "" && b.Config.WebhookURL == "" && b.Config.Login == "" { | 	if b.Config.WebhookBindAddress == "" && b.Config.WebhookURL == "" && b.Config.Login == "" && b.Config.Token == "" { | ||||||
| 		return errors.New("No connection method found. See that you have WebhookBindAddress, WebhookURL or Login/Password/Server/Team configured.") | 		return errors.New("No connection method found. See that you have WebhookBindAddress, WebhookURL or Token/Login/Password/Server/Team configured.") | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -108,15 +131,19 @@ func (b *Bmattermost) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmattermost) JoinChannel(channel string) error { | func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	// we can only join channels using the API | 	// we can only join channels using the API | ||||||
| 	if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { | 	if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { | ||||||
| 		return b.mc.JoinChannel(b.mc.GetChannelId(channel, "")) | 		id := b.mc.GetChannelId(channel.Name, "") | ||||||
|  | 		if id == "" { | ||||||
|  | 			return fmt.Errorf("Could not find channel ID for channel %s", channel.Name) | ||||||
|  | 		} | ||||||
|  | 		return b.mc.JoinChannel(id) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmattermost) Send(msg config.Message) error { | func (b *Bmattermost) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	if msg.Event == config.EVENT_USER_ACTION { | 	if msg.Event == config.EVENT_USER_ACTION { | ||||||
| 		msg.Text = "*" + msg.Text + "*" | 		msg.Text = "*" + msg.Text + "*" | ||||||
| @@ -138,12 +165,20 @@ func (b *Bmattermost) Send(msg config.Message) error { | |||||||
| 		err := b.mh.Send(matterMessage) | 		err := b.mh.Send(matterMessage) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			flog.Info(err) | 			flog.Info(err) | ||||||
| 			return err | 			return "", err | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 	b.mc.PostMessage(b.mc.GetChannelId(channel, ""), message) | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
| 	return nil | 		if msg.ID == "" { | ||||||
|  | 			return "", nil | ||||||
|  | 		} | ||||||
|  | 		return msg.ID, b.mc.DeleteMessage(msg.ID) | ||||||
|  | 	} | ||||||
|  | 	if msg.ID != "" { | ||||||
|  | 		return b.mc.EditMessage(msg.ID, message) | ||||||
|  | 	} | ||||||
|  | 	return b.mc.PostMessage(b.mc.GetChannelId(channel, ""), message) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmattermost) handleMatter() { | func (b *Bmattermost) handleMatter() { | ||||||
| @@ -152,17 +187,22 @@ func (b *Bmattermost) handleMatter() { | |||||||
| 		flog.Debugf("Choosing webhooks based receiving") | 		flog.Debugf("Choosing webhooks based receiving") | ||||||
| 		go b.handleMatterHook(mchan) | 		go b.handleMatterHook(mchan) | ||||||
| 	} else { | 	} else { | ||||||
| 		flog.Debugf("Choosing login/password based receiving") | 		if b.Config.Token != "" { | ||||||
|  | 			flog.Debugf("Choosing token based receiving") | ||||||
|  | 		} else { | ||||||
|  | 			flog.Debugf("Choosing login/password based receiving") | ||||||
|  | 		} | ||||||
| 		go b.handleMatterClient(mchan) | 		go b.handleMatterClient(mchan) | ||||||
| 	} | 	} | ||||||
| 	for message := range mchan { | 	for message := range mchan { | ||||||
| 		rmsg := config.Message{Username: message.Username, Channel: message.Channel, Account: b.Account, UserID: message.UserID} | 		rmsg := config.Message{Username: message.Username, Channel: message.Channel, Account: b.Account, UserID: message.UserID, ID: message.ID, Event: message.Event} | ||||||
| 		text, ok := b.replaceAction(message.Text) | 		text, ok := b.replaceAction(message.Text) | ||||||
| 		if ok { | 		if ok { | ||||||
| 			rmsg.Event = config.EVENT_USER_ACTION | 			rmsg.Event = config.EVENT_USER_ACTION | ||||||
| 		} | 		} | ||||||
| 		rmsg.Text = text | 		rmsg.Text = text | ||||||
| 		flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) | 		flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) | ||||||
|  | 		flog.Debugf("Message is %#v", rmsg) | ||||||
| 		b.Remote <- rmsg | 		b.Remote <- rmsg | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -182,7 +222,7 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) { | |||||||
| 		} | 		} | ||||||
| 		// do not post our own messages back to irc | 		// do not post our own messages back to irc | ||||||
| 		// only listen to message from our team | 		// only listen to message from our team | ||||||
| 		if (message.Raw.Event == "posted" || message.Raw.Event == "post_edited") && | 		if (message.Raw.Event == "posted" || message.Raw.Event == "post_edited" || message.Raw.Event == "post_deleted") && | ||||||
| 			b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId { | 			b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId { | ||||||
| 			// if the message has reactions don't repost it (for now, until we can correlate reaction with message) | 			// if the message has reactions don't repost it (for now, until we can correlate reaction with message) | ||||||
| 			if message.Post.HasReactions { | 			if message.Post.HasReactions { | ||||||
| @@ -194,9 +234,13 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) { | |||||||
| 			m.Username = message.Username | 			m.Username = message.Username | ||||||
| 			m.Channel = message.Channel | 			m.Channel = message.Channel | ||||||
| 			m.Text = message.Text | 			m.Text = message.Text | ||||||
|  | 			m.ID = message.Post.Id | ||||||
| 			if message.Raw.Event == "post_edited" && !b.Config.EditDisable { | 			if message.Raw.Event == "post_edited" && !b.Config.EditDisable { | ||||||
| 				m.Text = message.Text + b.Config.EditSuffix | 				m.Text = message.Text + b.Config.EditSuffix | ||||||
| 			} | 			} | ||||||
|  | 			if message.Raw.Event == "post_deleted" { | ||||||
|  | 				m.Event = config.EVENT_MSG_DELETE | ||||||
|  | 			} | ||||||
| 			if len(message.Post.FileIds) > 0 { | 			if len(message.Post.FileIds) > 0 { | ||||||
| 				for _, link := range b.mc.GetFileLinks(message.Post.FileIds) { | 				for _, link := range b.mc.GetFileLinks(message.Post.FileIds) { | ||||||
| 					m.Text = m.Text + "\n" + link | 					m.Text = m.Text + "\n" + link | ||||||
| @@ -221,7 +265,12 @@ func (b *Bmattermost) handleMatterHook(mchan chan *MMMessage) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bmattermost) apiLogin() error { | func (b *Bmattermost) apiLogin() error { | ||||||
| 	b.mc = matterclient.New(b.Config.Login, b.Config.Password, | 	password := b.Config.Password | ||||||
|  | 	if b.Config.Token != "" { | ||||||
|  | 		password = "MMAUTHTOKEN=" + b.Config.Token | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	b.mc = matterclient.New(b.Config.Login, password, | ||||||
| 		b.Config.Team, b.Config.Server) | 		b.Config.Team, b.Config.Server) | ||||||
| 	b.mc.SkipTLSVerify = b.Config.SkipTLSVerify | 	b.mc.SkipTLSVerify = b.Config.SkipTLSVerify | ||||||
| 	b.mc.NoTLS = b.Config.NoTLS | 	b.mc.NoTLS = b.Config.NoTLS | ||||||
|   | |||||||
| @@ -53,11 +53,15 @@ func (b *Brocketchat) Disconnect() error { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Brocketchat) JoinChannel(channel string) error { | func (b *Brocketchat) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Brocketchat) Send(msg config.Message) error { | func (b *Brocketchat) Send(msg config.Message) (string, error) { | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL} | 	matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL} | ||||||
| 	matterMessage.Channel = msg.Channel | 	matterMessage.Channel = msg.Channel | ||||||
| @@ -67,9 +71,9 @@ func (b *Brocketchat) Send(msg config.Message) error { | |||||||
| 	err := b.mh.Send(matterMessage) | 	err := b.mh.Send(matterMessage) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		flog.Info(err) | 		flog.Info(err) | ||||||
| 		return err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Brocketchat) handleRocketHook() { | func (b *Brocketchat) handleRocketHook() { | ||||||
|   | |||||||
| @@ -108,14 +108,14 @@ func (b *Bslack) Disconnect() error { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bslack) JoinChannel(channel string) error { | func (b *Bslack) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	// we can only join channels using the API | 	// we can only join channels using the API | ||||||
| 	if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { | 	if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { | ||||||
| 		if strings.HasPrefix(b.Config.Token, "xoxb") { | 		if strings.HasPrefix(b.Config.Token, "xoxb") { | ||||||
| 			// TODO check if bot has already joined channel | 			// TODO check if bot has already joined channel | ||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
| 		_, err := b.sc.JoinChannel(channel) | 		_, err := b.sc.JoinChannel(channel.Name) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if err.Error() != "name_taken" { | 			if err.Error() != "name_taken" { | ||||||
| 				return err | 				return err | ||||||
| @@ -125,7 +125,7 @@ func (b *Bslack) JoinChannel(channel string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bslack) Send(msg config.Message) error { | func (b *Bslack) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	if msg.Event == config.EVENT_USER_ACTION { | 	if msg.Event == config.EVENT_USER_ACTION { | ||||||
| 		msg.Text = "_" + msg.Text + "_" | 		msg.Text = "_" + msg.Text + "_" | ||||||
| @@ -145,13 +145,13 @@ func (b *Bslack) Send(msg config.Message) error { | |||||||
| 		err := b.mh.Send(matterMessage) | 		err := b.mh.Send(matterMessage) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			flog.Info(err) | 			flog.Info(err) | ||||||
| 			return err | 			return "", err | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 	schannel, err := b.getChannelByName(channel) | 	schannel, err := b.getChannelByName(channel) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	np := slack.NewPostMessageParameters() | 	np := slack.NewPostMessageParameters() | ||||||
| 	if b.Config.PrefixMessagesWithNick { | 	if b.Config.PrefixMessagesWithNick { | ||||||
| @@ -163,14 +163,30 @@ func (b *Bslack) Send(msg config.Message) error { | |||||||
| 		np.IconURL = msg.Avatar | 		np.IconURL = msg.Avatar | ||||||
| 	} | 	} | ||||||
| 	np.Attachments = append(np.Attachments, slack.Attachment{CallbackID: "matterbridge"}) | 	np.Attachments = append(np.Attachments, slack.Attachment{CallbackID: "matterbridge"}) | ||||||
| 	b.sc.PostMessage(schannel.ID, message, np) | 	// replace mentions | ||||||
|  | 	np.LinkNames = 1 | ||||||
|  |  | ||||||
| 	/* | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
| 	   newmsg := b.rtm.NewOutgoingMessage(message, schannel.ID) | 		// some protocols echo deletes, but with empty ID | ||||||
| 	   b.rtm.SendMessage(newmsg) | 		if msg.ID == "" { | ||||||
| 	*/ | 			return "", nil | ||||||
|  | 		} | ||||||
| 	return nil | 		// we get a "slack <ID>", split it | ||||||
|  | 		ts := strings.Fields(msg.ID) | ||||||
|  | 		b.sc.DeleteMessage(schannel.ID, ts[1]) | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  | 	// if we have no ID it means we're creating a new message, not updating an existing one | ||||||
|  | 	if msg.ID != "" { | ||||||
|  | 		ts := strings.Fields(msg.ID) | ||||||
|  | 		b.sc.UpdateMessage(schannel.ID, ts[1], message) | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  | 	_, id, err := b.sc.PostMessage(schannel.ID, message, np) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return "slack " + id, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bslack) getAvatar(user string) string { | func (b *Bslack) getAvatar(user string) string { | ||||||
| @@ -225,83 +241,90 @@ func (b *Bslack) handleSlack() { | |||||||
| 		if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" && message.Username == b.si.User.Name { | 		if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" && message.Username == b.si.User.Name { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if message.Text == "" || message.Username == "" { | 		if (message.Text == "" || message.Username == "") && message.Raw.SubType != "message_deleted" { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		texts := strings.Split(message.Text, "\n") | 		text := message.Text | ||||||
| 		for _, text := range texts { | 		text = b.replaceURL(text) | ||||||
| 			text = b.replaceURL(text) | 		text = html.UnescapeString(text) | ||||||
| 			text = html.UnescapeString(text) | 		flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) | ||||||
| 			flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) | 		msg := config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username), UserID: message.UserID, ID: "slack " + message.Raw.Timestamp} | ||||||
| 			msg := config.Message{Text: text, Username: message.Username, Channel: message.Channel, Account: b.Account, Avatar: b.getAvatar(message.Username), UserID: message.UserID} | 		if message.Raw.SubType == "me_message" { | ||||||
| 			if message.Raw.SubType == "me_message" { | 			msg.Event = config.EVENT_USER_ACTION | ||||||
| 				msg.Event = config.EVENT_USER_ACTION |  | ||||||
| 			} |  | ||||||
| 			b.Remote <- msg |  | ||||||
| 		} | 		} | ||||||
|  | 		if message.Raw.SubType == "channel_leave" || message.Raw.SubType == "channel_join" { | ||||||
|  | 			msg.Username = "system" | ||||||
|  | 			msg.Event = config.EVENT_JOIN_LEAVE | ||||||
|  | 		} | ||||||
|  | 		// edited messages have a submessage, use this timestamp | ||||||
|  | 		if message.Raw.SubMessage != nil { | ||||||
|  | 			msg.ID = "slack " + message.Raw.SubMessage.Timestamp | ||||||
|  | 		} | ||||||
|  | 		if message.Raw.SubType == "message_deleted" { | ||||||
|  | 			msg.Text = config.EVENT_MSG_DELETE | ||||||
|  | 			msg.Event = config.EVENT_MSG_DELETE | ||||||
|  | 			msg.ID = "slack " + message.Raw.DeletedTimestamp | ||||||
|  | 		} | ||||||
|  | 		flog.Debugf("Message is %#v", msg) | ||||||
|  | 		b.Remote <- msg | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { | func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { | ||||||
| 	count := 0 |  | ||||||
| 	for msg := range b.rtm.IncomingEvents { | 	for msg := range b.rtm.IncomingEvents { | ||||||
| 		switch ev := msg.Data.(type) { | 		switch ev := msg.Data.(type) { | ||||||
| 		case *slack.MessageEvent: | 		case *slack.MessageEvent: | ||||||
| 			// ignore first message | 			flog.Debugf("Receiving from slackclient %#v", ev) | ||||||
| 			if count > 0 { | 			if len(ev.Attachments) > 0 { | ||||||
| 				flog.Debugf("Receiving from slackclient %#v", ev) | 				// skip messages we made ourselves | ||||||
| 				if len(ev.Attachments) > 0 { | 				if ev.Attachments[0].CallbackID == "matterbridge" { | ||||||
| 					// skip messages we made ourselves | 					continue | ||||||
| 					if ev.Attachments[0].CallbackID == "matterbridge" { |  | ||||||
| 						continue |  | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 				if !b.Config.EditDisable && ev.SubMessage != nil && ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp { | 			} | ||||||
| 					flog.Debugf("SubMessage %#v", ev.SubMessage) | 			if !b.Config.EditDisable && ev.SubMessage != nil && ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp { | ||||||
| 					ev.User = ev.SubMessage.User | 				flog.Debugf("SubMessage %#v", ev.SubMessage) | ||||||
| 					ev.Text = ev.SubMessage.Text + b.Config.EditSuffix | 				ev.User = ev.SubMessage.User | ||||||
| 				} | 				ev.Text = ev.SubMessage.Text + b.Config.EditSuffix | ||||||
| 				// use our own func because rtm.GetChannelInfo doesn't work for private channels | 			} | ||||||
| 				channel, err := b.getChannelByID(ev.Channel) | 			// use our own func because rtm.GetChannelInfo doesn't work for private channels | ||||||
|  | 			channel, err := b.getChannelByID(ev.Channel) | ||||||
|  | 			if err != nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			m := &MMMessage{} | ||||||
|  | 			if ev.BotID == "" && ev.SubType != "message_deleted" { | ||||||
|  | 				user, err := b.rtm.GetUserInfo(ev.User) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
| 				m := &MMMessage{} | 				m.UserID = user.ID | ||||||
| 				if ev.BotID == "" { | 				m.Username = user.Name | ||||||
| 					user, err := b.rtm.GetUserInfo(ev.User) |  | ||||||
| 					if err != nil { |  | ||||||
| 						continue |  | ||||||
| 					} |  | ||||||
| 					m.UserID = user.ID |  | ||||||
| 					m.Username = user.Name |  | ||||||
| 				} |  | ||||||
| 				m.Channel = channel.Name |  | ||||||
| 				m.Text = ev.Text |  | ||||||
| 				if m.Text == "" { |  | ||||||
| 					for _, attach := range ev.Attachments { |  | ||||||
| 						if attach.Text != "" { |  | ||||||
| 							m.Text = attach.Text |  | ||||||
| 						} else { |  | ||||||
| 							m.Text = attach.Fallback |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				m.Raw = ev |  | ||||||
| 				m.Text = b.replaceMention(m.Text) |  | ||||||
| 				// when using webhookURL we can't check if it's our webhook or not for now |  | ||||||
| 				if ev.BotID != "" && b.Config.WebhookURL == "" { |  | ||||||
| 					bot, err := b.rtm.GetBotInfo(ev.BotID) |  | ||||||
| 					if err != nil { |  | ||||||
| 						continue |  | ||||||
| 					} |  | ||||||
| 					if bot.Name != "" { |  | ||||||
| 						m.Username = bot.Name |  | ||||||
| 						m.UserID = bot.ID |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				mchan <- m |  | ||||||
| 			} | 			} | ||||||
| 			count++ | 			m.Channel = channel.Name | ||||||
|  | 			m.Text = ev.Text | ||||||
|  | 			if m.Text == "" { | ||||||
|  | 				for _, attach := range ev.Attachments { | ||||||
|  | 					if attach.Text != "" { | ||||||
|  | 						m.Text = attach.Text | ||||||
|  | 					} else { | ||||||
|  | 						m.Text = attach.Fallback | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			m.Raw = ev | ||||||
|  | 			m.Text = b.replaceMention(m.Text) | ||||||
|  | 			// when using webhookURL we can't check if it's our webhook or not for now | ||||||
|  | 			if ev.BotID != "" && b.Config.WebhookURL == "" { | ||||||
|  | 				bot, err := b.rtm.GetBotInfo(ev.BotID) | ||||||
|  | 				if err != nil { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 				if bot.Name != "" { | ||||||
|  | 					m.Username = bot.Name | ||||||
|  | 					m.UserID = bot.ID | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			mchan <- m | ||||||
| 		case *slack.OutgoingErrorEvent: | 		case *slack.OutgoingErrorEvent: | ||||||
| 			flog.Debugf("%#v", ev.Error()) | 			flog.Debugf("%#v", ev.Error()) | ||||||
| 		case *slack.ChannelJoinedEvent: | 		case *slack.ChannelJoinedEvent: | ||||||
|   | |||||||
| @@ -60,8 +60,8 @@ func (b *Bsteam) Disconnect() error { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bsteam) JoinChannel(channel string) error { | func (b *Bsteam) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	id, err := steamid.NewId(channel) | 	id, err := steamid.NewId(channel.Name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -69,13 +69,17 @@ func (b *Bsteam) JoinChannel(channel string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bsteam) Send(msg config.Message) error { | func (b *Bsteam) Send(msg config.Message) (string, error) { | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	id, err := steamid.NewId(msg.Channel) | 	id, err := steamid.NewId(msg.Channel) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text) | 	b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text) | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bsteam) getNick(id steamid.SteamId) string { | func (b *Bsteam) getNick(id steamid.SteamId) string { | ||||||
|   | |||||||
| @@ -53,26 +53,57 @@ func (b *Btelegram) Disconnect() error { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Btelegram) JoinChannel(channel string) error { | func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Btelegram) Send(msg config.Message) error { | func (b *Btelegram) Send(msg config.Message) (string, error) { | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	chatid, err := strconv.ParseInt(msg.Channel, 10, 64) | 	chatid, err := strconv.ParseInt(msg.Channel, 10, 64) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if b.Config.MessageFormat == "HTML" { | 	if b.Config.MessageFormat == "HTML" { | ||||||
| 		msg.Text = makeHTML(msg.Text) | 		msg.Text = makeHTML(msg.Text) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		if msg.ID == "" { | ||||||
|  | 			return "", nil | ||||||
|  | 		} | ||||||
|  | 		msgid, err := strconv.Atoi(msg.ID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		_, err = b.c.DeleteMessage(tgbotapi.DeleteMessageConfig{ChatID: chatid, MessageID: msgid}) | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// edit the message if we have a msg ID | ||||||
|  | 	if msg.ID != "" { | ||||||
|  | 		msgid, err := strconv.Atoi(msg.ID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text) | ||||||
|  | 		_, err = b.c.Send(m) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	m := tgbotapi.NewMessage(chatid, msg.Username+msg.Text) | 	m := tgbotapi.NewMessage(chatid, msg.Username+msg.Text) | ||||||
| 	if b.Config.MessageFormat == "HTML" { | 	if b.Config.MessageFormat == "HTML" { | ||||||
| 		m.ParseMode = tgbotapi.ModeHTML | 		m.ParseMode = tgbotapi.ModeHTML | ||||||
| 	} | 	} | ||||||
| 	_, err = b.c.Send(m) | 	res, err := b.c.Send(m) | ||||||
| 	return err | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return strconv.Itoa(res.MessageID), nil | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | ||||||
| @@ -131,7 +162,7 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | |||||||
| 		} | 		} | ||||||
| 		if text != "" { | 		if text != "" { | ||||||
| 			flog.Debugf("Sending message from %s on %s to gateway", username, b.Account) | 			flog.Debugf("Sending message from %s on %s to gateway", username, b.Account) | ||||||
| 			b.Remote <- config.Message{Username: username, Text: text, Channel: channel, Account: b.Account, UserID: strconv.Itoa(message.From.ID)} | 			b.Remote <- config.Message{Username: username, Text: text, Channel: channel, Account: b.Account, UserID: strconv.Itoa(message.From.ID), ID: strconv.Itoa(message.MessageID)} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -74,15 +74,19 @@ func (b *Bxmpp) Disconnect() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bxmpp) JoinChannel(channel string) error { | func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error { | ||||||
| 	b.xc.JoinMUCNoHistory(channel+"@"+b.Config.Muc, b.Config.Nick) | 	b.xc.JoinMUCNoHistory(channel.Name+"@"+b.Config.Muc, b.Config.Nick) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bxmpp) Send(msg config.Message) error { | func (b *Bxmpp) Send(msg config.Message) (string, error) { | ||||||
|  | 	// ignore delete messages | ||||||
|  | 	if msg.Event == config.EVENT_MSG_DELETE { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
| 	flog.Debugf("Receiving %#v", msg) | 	flog.Debugf("Receiving %#v", msg) | ||||||
| 	b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text}) | 	b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text}) | ||||||
| 	return nil | 	return "", nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Bxmpp) createXMPP() (*xmpp.Client, error) { | func (b *Bxmpp) createXMPP() (*xmpp.Client, error) { | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,3 +1,56 @@ | |||||||
|  | # v1.2.0 | ||||||
|  | ## Breaking changes | ||||||
|  | * If you're running a discord bridge, update to this release before 16 october otherwise | ||||||
|  | it will stop working. (see https://discordapp.com/developers/docs/reference) | ||||||
|  |  | ||||||
|  | ## New features | ||||||
|  | * general: Add delete support. (actually delete the messages on bridges that support it) | ||||||
|  |     (mattermost,discord,gitter,slack,telegram) | ||||||
|  |  | ||||||
|  | ## Bugfix | ||||||
|  | * Do not break messages on newline (slack). Closes #258  | ||||||
|  | * Update telegram library | ||||||
|  | * Update discord library (supports v6 API now). Old API is deprecated on 16 October | ||||||
|  |  | ||||||
|  | # v1.1.2 | ||||||
|  | ## New features | ||||||
|  | * general: also build darwin binaries | ||||||
|  | * mattermost: add support for mattermost 4.2.x | ||||||
|  |  | ||||||
|  | ## Bugfix  | ||||||
|  | * mattermost: Send images when text is empty regression. (mattermost). Closes #254 | ||||||
|  | * slack: also send the first messsage after connect. #252 | ||||||
|  |  | ||||||
|  | # v1.1.1 | ||||||
|  | ## Bugfix | ||||||
|  | * mattermost: fix public links | ||||||
|  |  | ||||||
|  | # v1.1.0 | ||||||
|  | ## New features | ||||||
|  | * general: Add better editing support. (actually edit the messages on bridges that support it) | ||||||
|  | 	(mattermost,discord,gitter,slack,telegram) | ||||||
|  | * mattermost: use API v4 (removes support for mattermost < 3.8) | ||||||
|  | * mattermost: add support for personal access tokens (since mattermost 4.1) | ||||||
|  | 	Use ```Token="yourtoken"``` in mattermost config | ||||||
|  | 	See https://docs.mattermost.com/developer/personal-access-tokens.html for more info | ||||||
|  | * matrix: Relay notices (matrix). Closes #243 | ||||||
|  | * irc: Add a charset option. Closes #247 | ||||||
|  |  | ||||||
|  | ## Bugfix | ||||||
|  | * slack: Handle leave/join events (slack). Closes #246 | ||||||
|  | * slack: Replace mentions from other bridges. (slack). Closes #233 | ||||||
|  | * gitter: remove ZWSP after messages | ||||||
|  |  | ||||||
|  | # v1.0.1 | ||||||
|  | ## New features | ||||||
|  | * mattermost: add support for mattermost 4.1.x | ||||||
|  | * discord: allow a webhookURL per channel #239 | ||||||
|  |  | ||||||
|  | # v1.0.0 | ||||||
|  | ## New features | ||||||
|  | * general: Add action support for slack,mattermost,irc,gitter,matrix,xmpp,discord. #199 | ||||||
|  | * discord: Shows the username instead of the server nickname #234 | ||||||
|  |  | ||||||
| # v1.0.0-rc1 | # v1.0.0-rc1 | ||||||
| ## New features | ## New features | ||||||
| * general: Add action support for slack,mattermost,irc,gitter,matrix,xmpp,discord. #199 | * general: Add action support for slack,mattermost,irc,gitter,matrix,xmpp,discord. #199 | ||||||
|   | |||||||
| @@ -1,10 +1,11 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
| go version |grep go1.8 || exit | go version |grep go1.9 || exit | ||||||
| VERSION=$(git describe --tags) | VERSION=$(git describe --tags) | ||||||
| mkdir ci/binaries | mkdir ci/binaries | ||||||
| GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-win64.exe | GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-windows-amd64.exe | ||||||
| GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux64 | GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux-amd64 | ||||||
| GOOS=linux GOARCH=arm go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux-arm | GOOS=linux GOARCH=arm go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux-arm | ||||||
|  | GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-darwin-amd64 | ||||||
| cd ci | cd ci | ||||||
| cat > deploy.json <<EOF | cat > deploy.json <<EOF | ||||||
| { | { | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import ( | |||||||
| 	"github.com/42wim/matterbridge/bridge/config" | 	"github.com/42wim/matterbridge/bridge/config" | ||||||
| 	log "github.com/Sirupsen/logrus" | 	log "github.com/Sirupsen/logrus" | ||||||
| 	//	"github.com/davecgh/go-spew/spew" | 	//	"github.com/davecgh/go-spew/spew" | ||||||
|  | 	"github.com/hashicorp/golang-lru" | ||||||
| 	"github.com/peterhellberg/emojilib" | 	"github.com/peterhellberg/emojilib" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -21,11 +22,19 @@ type Gateway struct { | |||||||
| 	ChannelOptions map[string]config.ChannelOptions | 	ChannelOptions map[string]config.ChannelOptions | ||||||
| 	Message        chan config.Message | 	Message        chan config.Message | ||||||
| 	Name           string | 	Name           string | ||||||
|  | 	Messages       *lru.Cache | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type BrMsgID struct { | ||||||
|  | 	br *bridge.Bridge | ||||||
|  | 	ID string | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(cfg config.Gateway, r *Router) *Gateway { | func New(cfg config.Gateway, r *Router) *Gateway { | ||||||
| 	gw := &Gateway{Channels: make(map[string]*config.ChannelInfo), Message: r.Message, | 	gw := &Gateway{Channels: make(map[string]*config.ChannelInfo), Message: r.Message, | ||||||
| 		Router: r, Bridges: make(map[string]*bridge.Bridge), Config: r.Config} | 		Router: r, Bridges: make(map[string]*bridge.Bridge), Config: r.Config} | ||||||
|  | 	cache, _ := lru.New(5000) | ||||||
|  | 	gw.Messages = cache | ||||||
| 	gw.AddConfig(&cfg) | 	gw.AddConfig(&cfg) | ||||||
| 	return gw | 	return gw | ||||||
| } | } | ||||||
| @@ -136,15 +145,16 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con | |||||||
| 	return channels | 	return channels | ||||||
| } | } | ||||||
|  |  | ||||||
| func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) { | func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) []*BrMsgID { | ||||||
|  | 	var brMsgIDs []*BrMsgID | ||||||
| 	// only relay join/part when configged | 	// only relay join/part when configged | ||||||
| 	if msg.Event == config.EVENT_JOIN_LEAVE && !gw.Bridges[dest.Account].Config.ShowJoinPart { | 	if msg.Event == config.EVENT_JOIN_LEAVE && !gw.Bridges[dest.Account].Config.ShowJoinPart { | ||||||
| 		return | 		return brMsgIDs | ||||||
| 	} | 	} | ||||||
| 	// broadcast to every out channel (irc QUIT) | 	// broadcast to every out channel (irc QUIT) | ||||||
| 	if msg.Channel == "" && msg.Event != config.EVENT_JOIN_LEAVE { | 	if msg.Channel == "" && msg.Event != config.EVENT_JOIN_LEAVE { | ||||||
| 		log.Debug("empty channel") | 		log.Debug("empty channel") | ||||||
| 		return | 		return brMsgIDs | ||||||
| 	} | 	} | ||||||
| 	originchannel := msg.Channel | 	originchannel := msg.Channel | ||||||
| 	origmsg := msg | 	origmsg := msg | ||||||
| @@ -158,15 +168,29 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) { | |||||||
| 		msg.Channel = channel.Name | 		msg.Channel = channel.Name | ||||||
| 		msg.Avatar = gw.modifyAvatar(origmsg, dest) | 		msg.Avatar = gw.modifyAvatar(origmsg, dest) | ||||||
| 		msg.Username = gw.modifyUsername(origmsg, dest) | 		msg.Username = gw.modifyUsername(origmsg, dest) | ||||||
|  | 		msg.ID = "" | ||||||
|  | 		if res, ok := gw.Messages.Get(origmsg.ID); ok { | ||||||
|  | 			IDs := res.([]*BrMsgID) | ||||||
|  | 			for _, id := range IDs { | ||||||
|  | 				if dest.Protocol == id.br.Protocol { | ||||||
|  | 					msg.ID = id.ID | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		// for api we need originchannel as channel | 		// for api we need originchannel as channel | ||||||
| 		if dest.Protocol == "api" { | 		if dest.Protocol == "api" { | ||||||
| 			msg.Channel = originchannel | 			msg.Channel = originchannel | ||||||
| 		} | 		} | ||||||
| 		err := dest.Send(msg) | 		mID, err := dest.Send(msg) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			fmt.Println(err) | 			fmt.Println(err) | ||||||
| 		} | 		} | ||||||
|  | 		// append the message ID (mID) from this bridge (dest) to our brMsgIDs slice | ||||||
|  | 		if mID != "" { | ||||||
|  | 			brMsgIDs = append(brMsgIDs, &BrMsgID{dest, mID}) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 	return brMsgIDs | ||||||
| } | } | ||||||
|  |  | ||||||
| func (gw *Gateway) ignoreMessage(msg *config.Message) bool { | func (gw *Gateway) ignoreMessage(msg *config.Message) bool { | ||||||
|   | |||||||
| @@ -94,11 +94,17 @@ func (r *Router) handleReceive() { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		for _, gw := range r.Gateways { | 		for _, gw := range r.Gateways { | ||||||
|  | 			// record all the message ID's of the different bridges | ||||||
|  | 			var msgIDs []*BrMsgID | ||||||
| 			if !gw.ignoreMessage(&msg) { | 			if !gw.ignoreMessage(&msg) { | ||||||
| 				msg.Timestamp = time.Now() | 				msg.Timestamp = time.Now() | ||||||
| 				gw.modifyMessage(&msg) | 				gw.modifyMessage(&msg) | ||||||
| 				for _, br := range gw.Bridges { | 				for _, br := range gw.Bridges { | ||||||
| 					gw.handleMessage(msg, br) | 					msgIDs = append(msgIDs, gw.handleMessage(msg, br)...) | ||||||
|  | 				} | ||||||
|  | 				// only add the message ID if it doesn't already exists | ||||||
|  | 				if _, ok := gw.Messages.Get(msg.ID); !ok && msg.ID != "" { | ||||||
|  | 					gw.Messages.Add(msg.ID, msgIDs) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -5,14 +5,13 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/42wim/matterbridge/bridge/config" | 	"github.com/42wim/matterbridge/bridge/config" | ||||||
| 	"github.com/42wim/matterbridge/gateway" | 	"github.com/42wim/matterbridge/gateway" | ||||||
| 	//"github.com/42wim/matterbridge/gateway/samechannel" |  | ||||||
| 	log "github.com/Sirupsen/logrus" | 	log "github.com/Sirupsen/logrus" | ||||||
| 	"github.com/google/gops/agent" | 	"github.com/google/gops/agent" | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	version = "1.0.0-rc1" | 	version = "1.2.0" | ||||||
| 	githash string | 	githash string | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,6 +32,23 @@ UseSASL=false | |||||||
| #OPTIONAL (default false) | #OPTIONAL (default false) | ||||||
| SkipTLSVerify=true | SkipTLSVerify=true | ||||||
|  |  | ||||||
|  | #If you know your charset, you can specify it manually.  | ||||||
|  | #Otherwise it tries to detect this automatically. Select one below | ||||||
|  | # "iso-8859-2:1987", "iso-8859-9:1989", "866", "latin9", "iso-8859-10:1992", "iso-ir-109", "hebrew",  | ||||||
|  | # "cp932", "iso-8859-15", "cp437", "utf-16be", "iso-8859-3:1988", "windows-1251", "utf16", "latin6",  | ||||||
|  | # "latin3", "iso-8859-1:1987", "iso-8859-9", "utf-16le", "big5", "cp819", "asmo-708", "utf-8",  | ||||||
|  | # "ibm437", "iso-ir-157", "iso-ir-144", "latin4", "850", "iso-8859-5", "iso-8859-5:1988", "l3",  | ||||||
|  | # "windows-31j", "utf8", "iso-8859-3", "437", "greek", "iso-8859-8", "l6", "l9-iso-8859-15",  | ||||||
|  | # "iso-8859-2", "latin2", "iso-ir-100", "iso-8859-6", "arabic", "iso-ir-148", "us-ascii", "x-sjis",  | ||||||
|  | # "utf16be", "iso-8859-8:1988", "utf16le", "l4", "utf-16", "iso-ir-138", "iso-8859-7", "iso-8859-7:1987",  | ||||||
|  | # "windows-1252", "l2", "koi8-r", "iso8859-1", "latin1", "ecma-114", "iso-ir-110", "elot-928",  | ||||||
|  | # "iso-ir-126", "iso-8859-1", "iso-ir-127", "cp850", "cyrillic", "greek8", "windows-1250", "iso-latin-1",  | ||||||
|  | # "l5", "ibm866", "cp866", "ms-kanji", "ibm850", "ecma-118", "iso-ir-101", "ibm819", "l1", "iso-8859-6:1987",  | ||||||
|  | # "latin5", "ascii", "sjis", "iso-8859-10", "iso-8859-4", "iso-8859-4:1988", "shift-jis | ||||||
|  | # The select charset will be converted to utf-8 when sent to other bridges. | ||||||
|  | #OPTIONAL (default "") | ||||||
|  | Charset="" | ||||||
|  |  | ||||||
| #Your nick on irc.  | #Your nick on irc.  | ||||||
| #REQUIRED | #REQUIRED | ||||||
| Nick="matterbot" | Nick="matterbot" | ||||||
| @@ -213,6 +230,11 @@ Team="yourteam" | |||||||
| Login="yourlogin" | Login="yourlogin" | ||||||
| Password="yourpass" | Password="yourpass" | ||||||
|  |  | ||||||
|  | #personal access token of the bot. | ||||||
|  | #new feature since mattermost 4.1. See https://docs.mattermost.com/developer/personal-access-tokens.html | ||||||
|  | #OPTIONAL (you can use token instead of login/password) | ||||||
|  | #Token="abcdefghijklm" | ||||||
|  |  | ||||||
| #Enable this to make a http connection (instead of https) to your mattermost.  | #Enable this to make a http connection (instead of https) to your mattermost.  | ||||||
| #OPTIONAL (default false) | #OPTIONAL (default false) | ||||||
| NoTLS=false | NoTLS=false | ||||||
| @@ -361,7 +383,6 @@ WebhookURL="https://hooks.slack.com/services/yourhook" | |||||||
| #AND DEDICATED BOT USER WHEN POSSIBLE! | #AND DEDICATED BOT USER WHEN POSSIBLE! | ||||||
| #Address to listen on for outgoing webhook requests from slack | #Address to listen on for outgoing webhook requests from slack | ||||||
| #See account settings - integrations - outgoing webhooks on slack | #See account settings - integrations - outgoing webhooks on slack | ||||||
| #This setting will not be used when useAPI is eanbled |  | ||||||
| #webhooks | #webhooks | ||||||
| #OPTIONAL | #OPTIONAL | ||||||
| WebhookBindAddress="0.0.0.0:9999" | WebhookBindAddress="0.0.0.0:9999" | ||||||
| @@ -443,7 +464,12 @@ Server="yourservername" | |||||||
| #OPTIONAL (default false) | #OPTIONAL (default false) | ||||||
| ShowEmbeds=false | ShowEmbeds=false | ||||||
|  |  | ||||||
|  | #Shows the username (minus the discriminator) instead of the server nickname | ||||||
|  | #OPTIONAL (default false) | ||||||
|  | UseUserName=false | ||||||
|  |  | ||||||
| #Specify WebhookURL. If given, will relay messages using the Webhook, which gives a better look to messages. | #Specify WebhookURL. If given, will relay messages using the Webhook, which gives a better look to messages. | ||||||
|  | #This only works if you have one discord channel, if you have multiple discord channels you'll have to specify it in the gateway config | ||||||
| #OPTIONAL (default empty) | #OPTIONAL (default empty) | ||||||
| WebhookURL="Yourwebhooktokenhere" | WebhookURL="Yourwebhooktokenhere" | ||||||
|  |  | ||||||
| @@ -829,6 +855,14 @@ enable=true | |||||||
|         #OPTIONAL - your irc channel key |         #OPTIONAL - your irc channel key | ||||||
|         key="yourkey" |         key="yourkey" | ||||||
|  |  | ||||||
|  |     [[gateway.inout]] | ||||||
|  |     account="discord.game" | ||||||
|  |     channel="mygreatgame" | ||||||
|  |  | ||||||
|  |         #OPTIONAL - webhookurl only works for discord (it needs a different URL for each cahnnel) | ||||||
|  |         [gateway.inout.options] | ||||||
|  |         webhookurl=""https://discordapp.com/api/webhooks/123456789123456789/C9WPqExYWONPDZabcdef-def1434FGFjstasJX9pYht73y" | ||||||
|  |  | ||||||
|     #API example |     #API example | ||||||
|     #[[gateway.inout]] |     #[[gateway.inout]] | ||||||
|     #account="api.local" |     #account="api.local" | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
|  |  | ||||||
| [mattermost] | [mattermost] | ||||||
|     [mattermost.work] |     [mattermost.work] | ||||||
|     useAPI=true |  | ||||||
|     #do not prefix it wit http:// or https:// |     #do not prefix it wit http:// or https:// | ||||||
|     Server="yourmattermostserver.domain"  |     Server="yourmattermostserver.domain"  | ||||||
|     Team="yourteam" |     Team="yourteam" | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ import ( | |||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/http/cookiejar" | 	"net/http/cookiejar" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -45,8 +44,8 @@ type Message struct { | |||||||
| type Team struct { | type Team struct { | ||||||
| 	Team         *model.Team | 	Team         *model.Team | ||||||
| 	Id           string | 	Id           string | ||||||
| 	Channels     *model.ChannelList | 	Channels     []*model.Channel | ||||||
| 	MoreChannels *model.ChannelList | 	MoreChannels []*model.Channel | ||||||
| 	Users        map[string]*model.User | 	Users        map[string]*model.User | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -55,7 +54,7 @@ type MMClient struct { | |||||||
| 	*Credentials | 	*Credentials | ||||||
| 	Team          *Team | 	Team          *Team | ||||||
| 	OtherTeams    []*Team | 	OtherTeams    []*Team | ||||||
| 	Client        *model.Client | 	Client        *model.Client4 | ||||||
| 	User          *model.User | 	User          *model.User | ||||||
| 	Users         map[string]*model.User | 	Users         map[string]*model.User | ||||||
| 	MessageChan   chan *Message | 	MessageChan   chan *Message | ||||||
| @@ -109,21 +108,21 @@ func (m *MMClient) Login() error { | |||||||
| 		uriScheme = "http://" | 		uriScheme = "http://" | ||||||
| 	} | 	} | ||||||
| 	// login to mattermost | 	// login to mattermost | ||||||
| 	m.Client = model.NewClient(uriScheme + m.Credentials.Server) | 	m.Client = model.NewAPIv4Client(uriScheme + m.Credentials.Server) | ||||||
| 	m.Client.HttpClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}, Proxy: http.ProxyFromEnvironment} | 	m.Client.HttpClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}, Proxy: http.ProxyFromEnvironment} | ||||||
| 	m.Client.HttpClient.Timeout = time.Second * 10 | 	m.Client.HttpClient.Timeout = time.Second * 10 | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
| 		d := b.Duration() | 		d := b.Duration() | ||||||
| 		// bogus call to get the serverversion | 		// bogus call to get the serverversion | ||||||
| 		_, err := m.Client.GetClientProperties() | 		_, resp := m.Client.Logout() | ||||||
| 		if err != nil { | 		if resp.Error != nil { | ||||||
| 			return fmt.Errorf("%#v", err.Error()) | 			return fmt.Errorf("%#v", resp.Error.Error()) | ||||||
| 		} | 		} | ||||||
| 		if firstConnection && !supportedVersion(m.Client.ServerVersion) { | 		if firstConnection && !supportedVersion(resp.ServerVersion) { | ||||||
| 			return fmt.Errorf("unsupported mattermost version: %s", m.Client.ServerVersion) | 			return fmt.Errorf("unsupported mattermost version: %s", resp.ServerVersion) | ||||||
| 		} | 		} | ||||||
| 		m.ServerVersion = m.Client.ServerVersion | 		m.ServerVersion = resp.ServerVersion | ||||||
| 		if m.ServerVersion == "" { | 		if m.ServerVersion == "" { | ||||||
| 			m.log.Debugf("Server not up yet, reconnecting in %s", d) | 			m.log.Debugf("Server not up yet, reconnecting in %s", d) | ||||||
| 			time.Sleep(d) | 			time.Sleep(d) | ||||||
| @@ -134,30 +133,33 @@ func (m *MMClient) Login() error { | |||||||
| 	} | 	} | ||||||
| 	b.Reset() | 	b.Reset() | ||||||
|  |  | ||||||
| 	var myinfo *model.Result | 	var resp *model.Response | ||||||
|  | 	//var myinfo *model.Result | ||||||
| 	var appErr *model.AppError | 	var appErr *model.AppError | ||||||
| 	var logmsg = "trying login" | 	var logmsg = "trying login" | ||||||
| 	for { | 	for { | ||||||
| 		m.log.Debugf("%s %s %s %s", logmsg, m.Credentials.Team, m.Credentials.Login, m.Credentials.Server) | 		m.log.Debugf("%s %s %s %s", logmsg, m.Credentials.Team, m.Credentials.Login, m.Credentials.Server) | ||||||
| 		if strings.Contains(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN) { | 		if strings.Contains(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN) { | ||||||
| 			m.log.Debugf(logmsg+" with %s", model.SESSION_COOKIE_TOKEN) | 			m.log.Debugf(logmsg + " with token") | ||||||
| 			token := strings.Split(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN+"=") | 			token := strings.Split(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN+"=") | ||||||
| 			if len(token) != 2 { | 			if len(token) != 2 { | ||||||
| 				return errors.New("incorrect MMAUTHTOKEN. valid input is MMAUTHTOKEN=yourtoken") | 				return errors.New("incorrect MMAUTHTOKEN. valid input is MMAUTHTOKEN=yourtoken") | ||||||
| 			} | 			} | ||||||
| 			m.Client.HttpClient.Jar = m.createCookieJar(token[1]) | 			m.Client.HttpClient.Jar = m.createCookieJar(token[1]) | ||||||
| 			m.Client.MockSession(token[1]) | 			m.Client.AuthToken = token[1] | ||||||
| 			myinfo, appErr = m.Client.GetMe("") | 			m.Client.AuthType = model.HEADER_BEARER | ||||||
| 			if appErr != nil { | 			m.User, resp = m.Client.GetMe("") | ||||||
| 				return errors.New(appErr.DetailedError) | 			if resp.Error != nil { | ||||||
|  | 				return resp.Error | ||||||
| 			} | 			} | ||||||
| 			if myinfo.Data.(*model.User) == nil { | 			if m.User == nil { | ||||||
| 				m.log.Errorf("LOGIN TOKEN: %s is invalid", m.Credentials.Pass) | 				m.log.Errorf("LOGIN TOKEN: %s is invalid", m.Credentials.Pass) | ||||||
| 				return errors.New("invalid " + model.SESSION_COOKIE_TOKEN) | 				return errors.New("invalid " + model.SESSION_COOKIE_TOKEN) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			_, appErr = m.Client.Login(m.Credentials.Login, m.Credentials.Pass) | 			m.User, resp = m.Client.Login(m.Credentials.Login, m.Credentials.Pass) | ||||||
| 		} | 		} | ||||||
|  | 		appErr = resp.Error | ||||||
| 		if appErr != nil { | 		if appErr != nil { | ||||||
| 			d := b.Duration() | 			d := b.Duration() | ||||||
| 			m.log.Debug(appErr.DetailedError) | 			m.log.Debug(appErr.DetailedError) | ||||||
| @@ -185,8 +187,6 @@ func (m *MMClient) Login() error { | |||||||
| 	if m.Team == nil { | 	if m.Team == nil { | ||||||
| 		return errors.New("team not found") | 		return errors.New("team not found") | ||||||
| 	} | 	} | ||||||
| 	// set our team id as default route |  | ||||||
| 	m.Client.SetTeamId(m.Team.Id) |  | ||||||
|  |  | ||||||
| 	m.wsConnect() | 	m.wsConnect() | ||||||
|  |  | ||||||
| @@ -207,7 +207,7 @@ func (m *MMClient) wsConnect() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// setup websocket connection | 	// setup websocket connection | ||||||
| 	wsurl := wsScheme + m.Credentials.Server + model.API_URL_SUFFIX_V3 + "/users/websocket" | 	wsurl := wsScheme + m.Credentials.Server + model.API_URL_SUFFIX_V4 + "/websocket" | ||||||
| 	header := http.Header{} | 	header := http.Header{} | ||||||
| 	header.Set(model.HEADER_AUTH, "BEARER "+m.Client.AuthToken) | 	header.Set(model.HEADER_AUTH, "BEARER "+m.Client.AuthToken) | ||||||
|  |  | ||||||
| @@ -241,9 +241,9 @@ func (m *MMClient) Logout() error { | |||||||
| 		m.log.Debug("Not invalidating session in logout, credential is a token") | 		m.log.Debug("Not invalidating session in logout, credential is a token") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	_, err := m.Client.Logout() | 	_, resp := m.Client.Logout() | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return err | 		return resp.Error | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -277,6 +277,13 @@ func (m *MMClient) WsReceiver() { | |||||||
| 			// check if we didn't empty the message | 			// check if we didn't empty the message | ||||||
| 			if msg.Text != "" { | 			if msg.Text != "" { | ||||||
| 				m.MessageChan <- msg | 				m.MessageChan <- msg | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			// if we have file attached but the message is empty, also send it | ||||||
|  | 			if msg.Post != nil { | ||||||
|  | 				if msg.Text != "" || len(msg.Post.FileIds) > 0 { | ||||||
|  | 					m.MessageChan <- msg | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| @@ -292,7 +299,7 @@ func (m *MMClient) WsReceiver() { | |||||||
|  |  | ||||||
| func (m *MMClient) parseMessage(rmsg *Message) { | func (m *MMClient) parseMessage(rmsg *Message) { | ||||||
| 	switch rmsg.Raw.Event { | 	switch rmsg.Raw.Event { | ||||||
| 	case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED: | 	case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED: | ||||||
| 		m.parseActionPost(rmsg) | 		m.parseActionPost(rmsg) | ||||||
| 		/* | 		/* | ||||||
| 			case model.ACTION_USER_REMOVED: | 			case model.ACTION_USER_REMOVED: | ||||||
| @@ -349,33 +356,34 @@ func (m *MMClient) parseActionPost(rmsg *Message) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) UpdateUsers() error { | func (m *MMClient) UpdateUsers() error { | ||||||
| 	mmusers, err := m.Client.GetProfiles(0, 50000, "") | 	mmusers, resp := m.Client.GetUsers(0, 50000, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return errors.New(err.DetailedError) | 		return errors.New(resp.Error.DetailedError) | ||||||
| 	} | 	} | ||||||
| 	m.Lock() | 	m.Lock() | ||||||
| 	m.Users = mmusers.Data.(map[string]*model.User) | 	for _, user := range mmusers { | ||||||
|  | 		m.Users[user.Id] = user | ||||||
|  | 	} | ||||||
| 	m.Unlock() | 	m.Unlock() | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) UpdateChannels() error { | func (m *MMClient) UpdateChannels() error { | ||||||
| 	mmchannels, err := m.Client.GetChannels("") | 	mmchannels, resp := m.Client.GetChannelsForTeamForUser(m.Team.Id, m.User.Id, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return errors.New(err.DetailedError) | 		return errors.New(resp.Error.DetailedError) | ||||||
| 	} |  | ||||||
| 	var mmchannels2 *model.Result |  | ||||||
| 	if m.mmVersion() >= 3.08 { |  | ||||||
| 		mmchannels2, err = m.Client.GetMoreChannelsPage(0, 5000) |  | ||||||
| 	} else { |  | ||||||
| 		mmchannels2, err = m.Client.GetMoreChannels("") |  | ||||||
| 	} |  | ||||||
| 	if err != nil { |  | ||||||
| 		return errors.New(err.DetailedError) |  | ||||||
| 	} | 	} | ||||||
| 	m.Lock() | 	m.Lock() | ||||||
| 	m.Team.Channels = mmchannels.Data.(*model.ChannelList) | 	m.Team.Channels = mmchannels | ||||||
| 	m.Team.MoreChannels = mmchannels2.Data.(*model.ChannelList) | 	m.Unlock() | ||||||
|  |  | ||||||
|  | 	mmchannels, resp = m.Client.GetPublicChannelsForTeam(m.Team.Id, 0, 5000, "") | ||||||
|  | 	if resp.Error != nil { | ||||||
|  | 		return errors.New(resp.Error.DetailedError) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m.Lock() | ||||||
|  | 	m.Team.MoreChannels = mmchannels | ||||||
| 	m.Unlock() | 	m.Unlock() | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -388,14 +396,14 @@ func (m *MMClient) GetChannelName(channelId string) string { | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if t.Channels != nil { | 		if t.Channels != nil { | ||||||
| 			for _, channel := range *t.Channels { | 			for _, channel := range t.Channels { | ||||||
| 				if channel.Id == channelId { | 				if channel.Id == channelId { | ||||||
| 					return channel.Name | 					return channel.Name | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if t.MoreChannels != nil { | 		if t.MoreChannels != nil { | ||||||
| 			for _, channel := range *t.MoreChannels { | 			for _, channel := range t.MoreChannels { | ||||||
| 				if channel.Id == channelId { | 				if channel.Id == channelId { | ||||||
| 					return channel.Name | 					return channel.Name | ||||||
| 				} | 				} | ||||||
| @@ -413,7 +421,7 @@ func (m *MMClient) GetChannelId(name string, teamId string) string { | |||||||
| 	} | 	} | ||||||
| 	for _, t := range m.OtherTeams { | 	for _, t := range m.OtherTeams { | ||||||
| 		if t.Id == teamId { | 		if t.Id == teamId { | ||||||
| 			for _, channel := range append(*t.Channels, *t.MoreChannels...) { | 			for _, channel := range append(t.Channels, t.MoreChannels...) { | ||||||
| 				if channel.Name == name { | 				if channel.Name == name { | ||||||
| 					return channel.Id | 					return channel.Id | ||||||
| 				} | 				} | ||||||
| @@ -427,7 +435,7 @@ func (m *MMClient) GetChannelTeamId(id string) string { | |||||||
| 	m.RLock() | 	m.RLock() | ||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	for _, t := range append(m.OtherTeams, m.Team) { | 	for _, t := range append(m.OtherTeams, m.Team) { | ||||||
| 		for _, channel := range append(*t.Channels, *t.MoreChannels...) { | 		for _, channel := range append(t.Channels, t.MoreChannels...) { | ||||||
| 			if channel.Id == id { | 			if channel.Id == id { | ||||||
| 				return channel.TeamId | 				return channel.TeamId | ||||||
| 			} | 			} | ||||||
| @@ -440,7 +448,7 @@ func (m *MMClient) GetChannelHeader(channelId string) string { | |||||||
| 	m.RLock() | 	m.RLock() | ||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	for _, t := range m.OtherTeams { | 	for _, t := range m.OtherTeams { | ||||||
| 		for _, channel := range append(*t.Channels, *t.MoreChannels...) { | 		for _, channel := range append(t.Channels, t.MoreChannels...) { | ||||||
| 			if channel.Id == channelId { | 			if channel.Id == channelId { | ||||||
| 				return channel.Header | 				return channel.Header | ||||||
| 			} | 			} | ||||||
| @@ -450,55 +458,76 @@ func (m *MMClient) GetChannelHeader(channelId string) string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) PostMessage(channelId string, text string) { | func (m *MMClient) PostMessage(channelId string, text string) (string, error) { | ||||||
| 	post := &model.Post{ChannelId: channelId, Message: text} | 	post := &model.Post{ChannelId: channelId, Message: text} | ||||||
| 	m.Client.CreatePost(post) | 	res, resp := m.Client.CreatePost(post) | ||||||
|  | 	if resp.Error != nil { | ||||||
|  | 		return "", resp.Error | ||||||
|  | 	} | ||||||
|  | 	return res.Id, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MMClient) EditMessage(postId string, text string) (string, error) { | ||||||
|  | 	post := &model.Post{Message: text} | ||||||
|  | 	res, resp := m.Client.UpdatePost(postId, post) | ||||||
|  | 	if resp.Error != nil { | ||||||
|  | 		return "", resp.Error | ||||||
|  | 	} | ||||||
|  | 	return res.Id, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MMClient) DeleteMessage(postId string) error { | ||||||
|  | 	_, resp := m.Client.DeletePost(postId) | ||||||
|  | 	if resp.Error != nil { | ||||||
|  | 		return resp.Error | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) JoinChannel(channelId string) error { | func (m *MMClient) JoinChannel(channelId string) error { | ||||||
| 	m.RLock() | 	m.RLock() | ||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	for _, c := range *m.Team.Channels { | 	for _, c := range m.Team.Channels { | ||||||
| 		if c.Id == channelId { | 		if c.Id == channelId { | ||||||
| 			m.log.Debug("Not joining ", channelId, " already joined.") | 			m.log.Debug("Not joining ", channelId, " already joined.") | ||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	m.log.Debug("Joining ", channelId) | 	m.log.Debug("Joining ", channelId) | ||||||
| 	_, err := m.Client.JoinChannel(channelId) | 	_, resp := m.Client.AddChannelMember(channelId, m.User.Id) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return errors.New("failed to join") | 		return resp.Error | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetPostsSince(channelId string, time int64) *model.PostList { | func (m *MMClient) GetPostsSince(channelId string, time int64) *model.PostList { | ||||||
| 	res, err := m.Client.GetPostsSince(channelId, time) | 	res, resp := m.Client.GetPostsSince(channelId, time) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	return res.Data.(*model.PostList) | 	return res | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) SearchPosts(query string) *model.PostList { | func (m *MMClient) SearchPosts(query string) *model.PostList { | ||||||
| 	res, err := m.Client.SearchPosts(query, false) | 	res, resp := m.Client.SearchPosts(m.Team.Id, query, false) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	return res.Data.(*model.PostList) | 	return res | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { | func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { | ||||||
| 	res, err := m.Client.GetPosts(channelId, 0, limit, "") | 	res, resp := m.Client.GetPostsForChannel(channelId, 0, limit, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	return res.Data.(*model.PostList) | 	return res | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetPublicLink(filename string) string { | func (m *MMClient) GetPublicLink(filename string) string { | ||||||
| 	res, err := m.Client.GetPublicLink(filename) | 	res, resp := m.Client.GetFileLink(filename) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return "" | 		return "" | ||||||
| 	} | 	} | ||||||
| 	return res | 	return res | ||||||
| @@ -507,8 +536,8 @@ func (m *MMClient) GetPublicLink(filename string) string { | |||||||
| func (m *MMClient) GetPublicLinks(filenames []string) []string { | func (m *MMClient) GetPublicLinks(filenames []string) []string { | ||||||
| 	var output []string | 	var output []string | ||||||
| 	for _, f := range filenames { | 	for _, f := range filenames { | ||||||
| 		res, err := m.Client.GetPublicLink(f) | 		res, resp := m.Client.GetFileLink(f) | ||||||
| 		if err != nil { | 		if resp.Error != nil { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		output = append(output, res) | 		output = append(output, res) | ||||||
| @@ -524,8 +553,8 @@ func (m *MMClient) GetFileLinks(filenames []string) []string { | |||||||
|  |  | ||||||
| 	var output []string | 	var output []string | ||||||
| 	for _, f := range filenames { | 	for _, f := range filenames { | ||||||
| 		res, err := m.Client.GetPublicLink(f) | 		res, resp := m.Client.GetFileLink(f) | ||||||
| 		if err != nil { | 		if resp.Error != nil { | ||||||
| 			// public links is probably disabled, create the link ourselves | 			// public links is probably disabled, create the link ourselves | ||||||
| 			output = append(output, uriScheme+m.Credentials.Server+model.API_URL_SUFFIX_V3+"/files/"+f+"/get") | 			output = append(output, uriScheme+m.Credentials.Server+model.API_URL_SUFFIX_V3+"/files/"+f+"/get") | ||||||
| 			continue | 			continue | ||||||
| @@ -536,42 +565,43 @@ func (m *MMClient) GetFileLinks(filenames []string) []string { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) UpdateChannelHeader(channelId string, header string) { | func (m *MMClient) UpdateChannelHeader(channelId string, header string) { | ||||||
| 	data := make(map[string]string) | 	channel := &model.Channel{Id: channelId, Header: header} | ||||||
| 	data["channel_id"] = channelId |  | ||||||
| 	data["channel_header"] = header |  | ||||||
| 	m.log.Debugf("updating channelheader %#v, %#v", channelId, header) | 	m.log.Debugf("updating channelheader %#v, %#v", channelId, header) | ||||||
| 	_, err := m.Client.UpdateChannelHeader(data) | 	_, resp := m.Client.UpdateChannel(channel) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		log.Error(err) | 		log.Error(resp.Error) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) UpdateLastViewed(channelId string) { | func (m *MMClient) UpdateLastViewed(channelId string) { | ||||||
| 	m.log.Debugf("posting lastview %#v", channelId) | 	m.log.Debugf("posting lastview %#v", channelId) | ||||||
| 	if m.mmVersion() >= 3.08 { | 	view := &model.ChannelView{ChannelId: channelId} | ||||||
| 		view := model.ChannelView{ChannelId: channelId} | 	res, _ := m.Client.ViewChannel(m.User.Id, view) | ||||||
| 		res, _ := m.Client.ViewChannel(view) | 	if !res { | ||||||
| 		if !res { | 		m.log.Errorf("ChannelView update for %s failed", channelId) | ||||||
| 			m.log.Errorf("ChannelView update for %s failed", channelId) |  | ||||||
| 		} |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	_, err := m.Client.UpdateLastViewedAt(channelId, true) |  | ||||||
| 	if err != nil { |  | ||||||
| 		m.log.Error(err) |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (m *MMClient) UpdateUserNick(nick string) error { | ||||||
|  | 	user := m.User | ||||||
|  | 	user.Nickname = nick | ||||||
|  | 	_, resp := m.Client.UpdateUser(user) | ||||||
|  | 	if resp.Error != nil { | ||||||
|  | 		return resp.Error | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (m *MMClient) UsernamesInChannel(channelId string) []string { | func (m *MMClient) UsernamesInChannel(channelId string) []string { | ||||||
| 	res, err := m.Client.GetProfilesInChannel(channelId, 0, 50000, "") | 	res, resp := m.Client.GetChannelMembers(channelId, 0, 50000, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		m.log.Errorf("UsernamesInChannel(%s) failed: %s", channelId, err) | 		m.log.Errorf("UsernamesInChannel(%s) failed: %s", channelId, resp.Error) | ||||||
| 		return []string{} | 		return []string{} | ||||||
| 	} | 	} | ||||||
| 	members := res.Data.(map[string]*model.User) | 	allusers := m.GetUsers() | ||||||
| 	result := []string{} | 	result := []string{} | ||||||
| 	for _, member := range members { | 	for _, member := range *res { | ||||||
| 		result = append(result, member.Nickname) | 		result = append(result, allusers[member.UserId].Nickname) | ||||||
| 	} | 	} | ||||||
| 	return result | 	return result | ||||||
| } | } | ||||||
| @@ -595,22 +625,15 @@ func (m *MMClient) createCookieJar(token string) *cookiejar.Jar { | |||||||
| func (m *MMClient) SendDirectMessage(toUserId string, msg string) { | func (m *MMClient) SendDirectMessage(toUserId string, msg string) { | ||||||
| 	m.log.Debugf("SendDirectMessage to %s, msg %s", toUserId, msg) | 	m.log.Debugf("SendDirectMessage to %s, msg %s", toUserId, msg) | ||||||
| 	// create DM channel (only happens on first message) | 	// create DM channel (only happens on first message) | ||||||
| 	_, err := m.Client.CreateDirectChannel(toUserId) | 	_, resp := m.Client.CreateDirectChannel(m.User.Id, toUserId) | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		m.log.Debugf("SendDirectMessage to %#v failed: %s", toUserId, err) | 		m.log.Debugf("SendDirectMessage to %#v failed: %s", toUserId, resp.Error) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	channelName := model.GetDMNameFromIds(toUserId, m.User.Id) | 	channelName := model.GetDMNameFromIds(toUserId, m.User.Id) | ||||||
|  |  | ||||||
| 	// update our channels | 	// update our channels | ||||||
| 	mmchannels, err := m.Client.GetChannels("") | 	m.UpdateChannels() | ||||||
| 	if err != nil { |  | ||||||
| 		m.log.Debug("SendDirectMessage: Couldn't update channels") |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	m.Lock() |  | ||||||
| 	m.Team.Channels = mmchannels.Data.(*model.ChannelList) |  | ||||||
| 	m.Unlock() |  | ||||||
|  |  | ||||||
| 	// build & send the message | 	// build & send the message | ||||||
| 	msg = strings.Replace(msg, "\r", "", -1) | 	msg = strings.Replace(msg, "\r", "", -1) | ||||||
| @@ -636,10 +659,10 @@ func (m *MMClient) GetChannels() []*model.Channel { | |||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	var channels []*model.Channel | 	var channels []*model.Channel | ||||||
| 	// our primary team channels first | 	// our primary team channels first | ||||||
| 	channels = append(channels, *m.Team.Channels...) | 	channels = append(channels, m.Team.Channels...) | ||||||
| 	for _, t := range m.OtherTeams { | 	for _, t := range m.OtherTeams { | ||||||
| 		if t.Id != m.Team.Id { | 		if t.Id != m.Team.Id { | ||||||
| 			channels = append(channels, *t.Channels...) | 			channels = append(channels, t.Channels...) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return channels | 	return channels | ||||||
| @@ -651,7 +674,7 @@ func (m *MMClient) GetMoreChannels() []*model.Channel { | |||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	var channels []*model.Channel | 	var channels []*model.Channel | ||||||
| 	for _, t := range m.OtherTeams { | 	for _, t := range m.OtherTeams { | ||||||
| 		channels = append(channels, *t.MoreChannels...) | 		channels = append(channels, t.MoreChannels...) | ||||||
| 	} | 	} | ||||||
| 	return channels | 	return channels | ||||||
| } | } | ||||||
| @@ -662,9 +685,9 @@ func (m *MMClient) GetTeamFromChannel(channelId string) string { | |||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	var channels []*model.Channel | 	var channels []*model.Channel | ||||||
| 	for _, t := range m.OtherTeams { | 	for _, t := range m.OtherTeams { | ||||||
| 		channels = append(channels, *t.Channels...) | 		channels = append(channels, t.Channels...) | ||||||
| 		if t.MoreChannels != nil { | 		if t.MoreChannels != nil { | ||||||
| 			channels = append(channels, *t.MoreChannels...) | 			channels = append(channels, t.MoreChannels...) | ||||||
| 		} | 		} | ||||||
| 		for _, c := range channels { | 		for _, c := range channels { | ||||||
| 			if c.Id == channelId { | 			if c.Id == channelId { | ||||||
| @@ -678,12 +701,11 @@ func (m *MMClient) GetTeamFromChannel(channelId string) string { | |||||||
| func (m *MMClient) GetLastViewedAt(channelId string) int64 { | func (m *MMClient) GetLastViewedAt(channelId string) int64 { | ||||||
| 	m.RLock() | 	m.RLock() | ||||||
| 	defer m.RUnlock() | 	defer m.RUnlock() | ||||||
| 	res, err := m.Client.GetChannel(channelId, "") | 	res, resp := m.Client.GetChannelMember(channelId, m.User.Id, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return model.GetMillis() | 		return model.GetMillis() | ||||||
| 	} | 	} | ||||||
| 	data := res.Data.(*model.ChannelData) | 	return res.LastViewedAt | ||||||
| 	return data.Member.LastViewedAt |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetUsers() map[string]*model.User { | func (m *MMClient) GetUsers() map[string]*model.User { | ||||||
| @@ -701,12 +723,11 @@ func (m *MMClient) GetUser(userId string) *model.User { | |||||||
| 	defer m.Unlock() | 	defer m.Unlock() | ||||||
| 	_, ok := m.Users[userId] | 	_, ok := m.Users[userId] | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		res, err := m.Client.GetProfilesByIds([]string{userId}) | 		res, resp := m.Client.GetUser(userId, "") | ||||||
| 		if err != nil { | 		if resp.Error != nil { | ||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
| 		u := res.Data.(map[string]*model.User)[userId] | 		m.Users[userId] = res | ||||||
| 		m.Users[userId] = u |  | ||||||
| 	} | 	} | ||||||
| 	return m.Users[userId] | 	return m.Users[userId] | ||||||
| } | } | ||||||
| @@ -720,36 +741,36 @@ func (m *MMClient) GetUserName(userId string) string { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetStatus(userId string) string { | func (m *MMClient) GetStatus(userId string) string { | ||||||
| 	res, err := m.Client.GetStatusesByIds([]string{userId}) | 	res, resp := m.Client.GetUserStatus(userId, "") | ||||||
| 	if err != nil { | 	if resp.Error != nil { | ||||||
| 		return "" | 		return "" | ||||||
| 	} | 	} | ||||||
| 	status := res.Data.(map[string]string) | 	if res.Status == model.STATUS_AWAY { | ||||||
| 	if status[userId] == model.STATUS_AWAY { |  | ||||||
| 		return "away" | 		return "away" | ||||||
| 	} | 	} | ||||||
| 	if status[userId] == model.STATUS_ONLINE { | 	if res.Status == model.STATUS_ONLINE { | ||||||
| 		return "online" | 		return "online" | ||||||
| 	} | 	} | ||||||
| 	return "offline" | 	return "offline" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) GetStatuses() map[string]string { | func (m *MMClient) GetStatuses() map[string]string { | ||||||
| 	var ok bool | 	var ids []string | ||||||
| 	statuses := make(map[string]string) | 	statuses := make(map[string]string) | ||||||
| 	res, err := m.Client.GetStatuses() | 	for id := range m.Users { | ||||||
| 	if err != nil { | 		ids = append(ids, id) | ||||||
|  | 	} | ||||||
|  | 	res, resp := m.Client.GetUsersStatusesByIds(ids) | ||||||
|  | 	if resp.Error != nil { | ||||||
| 		return statuses | 		return statuses | ||||||
| 	} | 	} | ||||||
| 	if statuses, ok = res.Data.(map[string]string); ok { | 	for _, status := range res { | ||||||
| 		for userId, status := range statuses { | 		statuses[status.UserId] = "offline" | ||||||
| 			statuses[userId] = "offline" | 		if status.Status == model.STATUS_AWAY { | ||||||
| 			if status == model.STATUS_AWAY { | 			statuses[status.UserId] = "away" | ||||||
| 				statuses[userId] = "away" | 		} | ||||||
| 			} | 		if status.Status == model.STATUS_ONLINE { | ||||||
| 			if status == model.STATUS_ONLINE { | 			statuses[status.UserId] = "online" | ||||||
| 				statuses[userId] = "online" |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return statuses | 	return statuses | ||||||
| @@ -800,40 +821,39 @@ func (m *MMClient) StatusLoop() { | |||||||
| func (m *MMClient) initUser() error { | func (m *MMClient) initUser() error { | ||||||
| 	m.Lock() | 	m.Lock() | ||||||
| 	defer m.Unlock() | 	defer m.Unlock() | ||||||
| 	initLoad, err := m.Client.GetInitialLoad() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	initData := initLoad.Data.(*model.InitialLoad) |  | ||||||
| 	m.User = initData.User |  | ||||||
| 	// we only load all team data on initial login. | 	// we only load all team data on initial login. | ||||||
| 	// all other updates are for channels from our (primary) team only. | 	// all other updates are for channels from our (primary) team only. | ||||||
| 	//m.log.Debug("initUser(): loading all team data") | 	//m.log.Debug("initUser(): loading all team data") | ||||||
| 	for _, v := range initData.Teams { | 	teams, resp := m.Client.GetTeamsForUser(m.User.Id, "") | ||||||
| 		m.Client.SetTeamId(v.Id) | 	if resp.Error != nil { | ||||||
| 		mmusers, err := m.Client.GetProfiles(0, 50000, "") | 		return resp.Error | ||||||
| 		if err != nil { | 	} | ||||||
| 			return errors.New(err.DetailedError) | 	for _, team := range teams { | ||||||
|  | 		mmusers, resp := m.Client.GetUsersInTeam(team.Id, 0, 50000, "") | ||||||
|  | 		if resp.Error != nil { | ||||||
|  | 			return errors.New(resp.Error.DetailedError) | ||||||
| 		} | 		} | ||||||
| 		t := &Team{Team: v, Users: mmusers.Data.(map[string]*model.User), Id: v.Id} | 		usermap := make(map[string]*model.User) | ||||||
| 		mmchannels, err := m.Client.GetChannels("") | 		for _, user := range mmusers { | ||||||
| 		if err != nil { | 			usermap[user.Id] = user | ||||||
| 			return errors.New(err.DetailedError) |  | ||||||
| 		} | 		} | ||||||
| 		t.Channels = mmchannels.Data.(*model.ChannelList) |  | ||||||
| 		if m.mmVersion() >= 3.08 { | 		t := &Team{Team: team, Users: usermap, Id: team.Id} | ||||||
| 			mmchannels, err = m.Client.GetMoreChannelsPage(0, 5000) |  | ||||||
| 		} else { | 		mmchannels, resp := m.Client.GetChannelsForTeamForUser(team.Id, m.User.Id, "") | ||||||
| 			mmchannels, err = m.Client.GetMoreChannels("") | 		if resp.Error != nil { | ||||||
|  | 			return resp.Error | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		t.Channels = mmchannels | ||||||
| 			return errors.New(err.DetailedError) | 		mmchannels, resp = m.Client.GetPublicChannelsForTeam(team.Id, 0, 5000, "") | ||||||
|  | 		if resp.Error != nil { | ||||||
|  | 			return resp.Error | ||||||
| 		} | 		} | ||||||
| 		t.MoreChannels = mmchannels.Data.(*model.ChannelList) | 		t.MoreChannels = mmchannels | ||||||
| 		m.OtherTeams = append(m.OtherTeams, t) | 		m.OtherTeams = append(m.OtherTeams, t) | ||||||
| 		if v.Name == m.Credentials.Team { | 		if team.Name == m.Credentials.Team { | ||||||
| 			m.Team = t | 			m.Team = t | ||||||
| 			m.log.Debugf("initUser(): found our team %s (id: %s)", v.Name, v.Id) | 			m.log.Debugf("initUser(): found our team %s (id: %s)", team.Name, team.Id) | ||||||
| 		} | 		} | ||||||
| 		// add all users | 		// add all users | ||||||
| 		for k, v := range t.Users { | 		for k, v := range t.Users { | ||||||
| @@ -854,22 +874,13 @@ func (m *MMClient) sendWSRequest(action string, data map[string]interface{}) err | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *MMClient) mmVersion() float64 { |  | ||||||
| 	v, _ := strconv.ParseFloat(string(m.ServerVersion[0:2])+"0"+string(m.ServerVersion[2]), 64) |  | ||||||
| 	if string(m.ServerVersion[4]) == "." { |  | ||||||
| 		v, _ = strconv.ParseFloat(m.ServerVersion[0:4], 64) |  | ||||||
| 	} |  | ||||||
| 	return v |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func supportedVersion(version string) bool { | func supportedVersion(version string) bool { | ||||||
| 	if strings.HasPrefix(version, "3.5.0") || | 	if strings.HasPrefix(version, "3.8.0") || | ||||||
| 		strings.HasPrefix(version, "3.6.0") || |  | ||||||
| 		strings.HasPrefix(version, "3.7.0") || |  | ||||||
| 		strings.HasPrefix(version, "3.8.0") || |  | ||||||
| 		strings.HasPrefix(version, "3.9.0") || | 		strings.HasPrefix(version, "3.9.0") || | ||||||
| 		strings.HasPrefix(version, "3.10.0") || | 		strings.HasPrefix(version, "3.10.0") || | ||||||
| 		strings.HasPrefix(version, "4.0") { | 		strings.HasPrefix(version, "4.0") || | ||||||
|  | 		strings.HasPrefix(version, "4.1") || | ||||||
|  | 		strings.HasPrefix(version, "4.2") { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ type IMessage struct { | |||||||
| 	ServiceId   string `schema:"service_id"` | 	ServiceId   string `schema:"service_id"` | ||||||
| 	Text        string `schema:"text"` | 	Text        string `schema:"text"` | ||||||
| 	TriggerWord string `schema:"trigger_word"` | 	TriggerWord string `schema:"trigger_word"` | ||||||
|  | 	FileIDs     string `schema:"file_ids"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // Client for Mattermost. | // Client for Mattermost. | ||||||
|   | |||||||
| @@ -205,17 +205,43 @@ func (gitter *Gitter) GetMessage(roomID, messageID string) (*Message, error) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SendMessage sends a message to a room | // SendMessage sends a message to a room | ||||||
| func (gitter *Gitter) SendMessage(roomID, text string) error { | func (gitter *Gitter) SendMessage(roomID, text string) (*Message, error) { | ||||||
| 
 | 
 | ||||||
| 	message := Message{Text: text} | 	message := Message{Text: text} | ||||||
| 	body, _ := json.Marshal(message) | 	body, _ := json.Marshal(message) | ||||||
| 	_, err := gitter.post(gitter.config.apiBaseURL+"rooms/"+roomID+"/chatMessages", body) | 	response, err := gitter.post(gitter.config.apiBaseURL+"rooms/"+roomID+"/chatMessages", body) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		gitter.log(err) | 		gitter.log(err) | ||||||
| 		return err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	err = json.Unmarshal(response, &message) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &message, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // UpdateMessage updates a message in a room | ||||||
|  | func (gitter *Gitter) UpdateMessage(roomID, msgID, text string) (*Message, error) { | ||||||
|  | 
 | ||||||
|  | 	message := Message{Text: text} | ||||||
|  | 	body, _ := json.Marshal(message) | ||||||
|  | 	response, err := gitter.put(gitter.config.apiBaseURL+"rooms/"+roomID+"/chatMessages/"+msgID, body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = json.Unmarshal(response, &message) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &message, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // JoinRoom joins a room | // JoinRoom joins a room | ||||||
| @@ -265,7 +291,7 @@ func (gitter *Gitter) SearchRooms(room string) ([]Room, error) { | |||||||
| 		Results []Room `json:"results"` | 		Results []Room `json:"results"` | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	response, err := gitter.get(gitter.config.apiBaseURL + "rooms?q=" + room ) | 	response, err := gitter.get(gitter.config.apiBaseURL + "rooms?q=" + room) | ||||||
| 
 | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		gitter.log(err) | 		gitter.log(err) | ||||||
| @@ -414,6 +440,39 @@ func (gitter *Gitter) post(url string, body []byte) ([]byte, error) { | |||||||
| 	return result, nil | 	return result, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (gitter *Gitter) put(url string, body []byte) ([]byte, error) { | ||||||
|  | 	r, err := http.NewRequest("PUT", url, bytes.NewBuffer(body)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	r.Header.Set("Content-Type", "application/json") | ||||||
|  | 	r.Header.Set("Accept", "application/json") | ||||||
|  | 	r.Header.Set("Authorization", "Bearer "+gitter.config.token) | ||||||
|  | 
 | ||||||
|  | 	resp, err := gitter.config.client.Do(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	defer resp.Body.Close() | ||||||
|  | 
 | ||||||
|  | 	if resp.StatusCode != http.StatusOK { | ||||||
|  | 		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)} | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result, err := ioutil.ReadAll(resp.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		gitter.log(err) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return result, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (gitter *Gitter) delete(url string) ([]byte, error) { | func (gitter *Gitter) delete(url string) ([]byte, error) { | ||||||
| 	r, err := http.NewRequest("delete", url, nil) | 	r, err := http.NewRequest("delete", url, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
							
								
								
									
										3
									
								
								vendor/github.com/bwmarrin/discordgo/discord.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/bwmarrin/discordgo/discord.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) | // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) | ||||||
| const VERSION = "0.16.0" | const VERSION = "0.17.0" | ||||||
|  |  | ||||||
| // ErrMFA will be risen by New when the user has 2FA. | // ErrMFA will be risen by New when the user has 2FA. | ||||||
| var ErrMFA = errors.New("account has 2FA enabled") | var ErrMFA = errors.New("account has 2FA enabled") | ||||||
| @@ -59,6 +59,7 @@ func New(args ...interface{}) (s *Session, err error) { | |||||||
| 		MaxRestRetries:         3, | 		MaxRestRetries:         3, | ||||||
| 		Client:                 &http.Client{Timeout: (20 * time.Second)}, | 		Client:                 &http.Client{Timeout: (20 * time.Second)}, | ||||||
| 		sequence:               new(int64), | 		sequence:               new(int64), | ||||||
|  | 		LastHeartbeatAck:       time.Now().UTC(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// If no arguments are passed return the empty Session interface. | 	// If no arguments are passed return the empty Session interface. | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								vendor/github.com/bwmarrin/discordgo/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/bwmarrin/discordgo/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,6 +11,9 @@ | |||||||
|  |  | ||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
|  | // APIVersion is the Discord API version used for the REST and Websocket API. | ||||||
|  | var APIVersion = "6" | ||||||
|  |  | ||||||
| // Known Discord API Endpoints. | // Known Discord API Endpoints. | ||||||
| var ( | var ( | ||||||
| 	EndpointStatus     = "https://status.discordapp.com/api/v2/" | 	EndpointStatus     = "https://status.discordapp.com/api/v2/" | ||||||
| @@ -18,13 +21,14 @@ var ( | |||||||
| 	EndpointSmActive   = EndpointSm + "active.json" | 	EndpointSmActive   = EndpointSm + "active.json" | ||||||
| 	EndpointSmUpcoming = EndpointSm + "upcoming.json" | 	EndpointSmUpcoming = EndpointSm + "upcoming.json" | ||||||
|  |  | ||||||
| 	EndpointDiscord  = "https://discordapp.com/" | 	EndpointDiscord    = "https://discordapp.com/" | ||||||
| 	EndpointAPI      = EndpointDiscord + "api/" | 	EndpointAPI        = EndpointDiscord + "api/v" + APIVersion + "/" | ||||||
| 	EndpointGuilds   = EndpointAPI + "guilds/" | 	EndpointGuilds     = EndpointAPI + "guilds/" | ||||||
| 	EndpointChannels = EndpointAPI + "channels/" | 	EndpointChannels   = EndpointAPI + "channels/" | ||||||
| 	EndpointUsers    = EndpointAPI + "users/" | 	EndpointUsers      = EndpointAPI + "users/" | ||||||
| 	EndpointGateway  = EndpointAPI + "gateway" | 	EndpointGateway    = EndpointAPI + "gateway" | ||||||
| 	EndpointWebhooks = EndpointAPI + "webhooks/" | 	EndpointGatewayBot = EndpointGateway + "/bot" | ||||||
|  | 	EndpointWebhooks   = EndpointAPI + "webhooks/" | ||||||
|  |  | ||||||
| 	EndpointCDN             = "https://cdn.discordapp.com/" | 	EndpointCDN             = "https://cdn.discordapp.com/" | ||||||
| 	EndpointCDNAttachments  = EndpointCDN + "attachments/" | 	EndpointCDNAttachments  = EndpointCDN + "attachments/" | ||||||
| @@ -54,16 +58,17 @@ var ( | |||||||
| 	EndpointReport       = EndpointAPI + "report" | 	EndpointReport       = EndpointAPI + "report" | ||||||
| 	EndpointIntegrations = EndpointAPI + "integrations" | 	EndpointIntegrations = EndpointAPI + "integrations" | ||||||
|  |  | ||||||
| 	EndpointUser              = func(uID string) string { return EndpointUsers + uID } | 	EndpointUser               = func(uID string) string { return EndpointUsers + uID } | ||||||
| 	EndpointUserAvatar        = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } | 	EndpointUserAvatar         = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } | ||||||
| 	EndpointUserSettings      = func(uID string) string { return EndpointUsers + uID + "/settings" } | 	EndpointUserAvatarAnimated = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".gif" } | ||||||
| 	EndpointUserGuilds        = func(uID string) string { return EndpointUsers + uID + "/guilds" } | 	EndpointUserSettings       = func(uID string) string { return EndpointUsers + uID + "/settings" } | ||||||
| 	EndpointUserGuild         = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } | 	EndpointUserGuilds         = func(uID string) string { return EndpointUsers + uID + "/guilds" } | ||||||
| 	EndpointUserGuildSettings = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID + "/settings" } | 	EndpointUserGuild          = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } | ||||||
| 	EndpointUserChannels      = func(uID string) string { return EndpointUsers + uID + "/channels" } | 	EndpointUserGuildSettings  = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID + "/settings" } | ||||||
| 	EndpointUserDevices       = func(uID string) string { return EndpointUsers + uID + "/devices" } | 	EndpointUserChannels       = func(uID string) string { return EndpointUsers + uID + "/channels" } | ||||||
| 	EndpointUserConnections   = func(uID string) string { return EndpointUsers + uID + "/connections" } | 	EndpointUserDevices        = func(uID string) string { return EndpointUsers + uID + "/devices" } | ||||||
| 	EndpointUserNotes         = func(uID string) string { return EndpointUsers + "@me/notes/" + uID } | 	EndpointUserConnections    = func(uID string) string { return EndpointUsers + uID + "/connections" } | ||||||
|  | 	EndpointUserNotes          = func(uID string) string { return EndpointUsers + "@me/notes/" + uID } | ||||||
|  |  | ||||||
| 	EndpointGuild                = func(gID string) string { return EndpointGuilds + gID } | 	EndpointGuild                = func(gID string) string { return EndpointGuilds + gID } | ||||||
| 	EndpointGuildInivtes         = func(gID string) string { return EndpointGuilds + gID + "/invites" } | 	EndpointGuildInivtes         = func(gID string) string { return EndpointGuilds + gID + "/invites" } | ||||||
| @@ -103,6 +108,9 @@ var ( | |||||||
| 	EndpointWebhook         = func(wID string) string { return EndpointWebhooks + wID } | 	EndpointWebhook         = func(wID string) string { return EndpointWebhooks + wID } | ||||||
| 	EndpointWebhookToken    = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token } | 	EndpointWebhookToken    = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token } | ||||||
|  |  | ||||||
|  | 	EndpointMessageReactionsAll = func(cID, mID string) string { | ||||||
|  | 		return EndpointChannelMessage(cID, mID) + "/reactions" | ||||||
|  | 	} | ||||||
| 	EndpointMessageReactions = func(cID, mID, eID string) string { | 	EndpointMessageReactions = func(cID, mID, eID string) string { | ||||||
| 		return EndpointChannelMessage(cID, mID) + "/reactions/" + eID | 		return EndpointChannelMessage(cID, mID) + "/reactions/" + eID | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								vendor/github.com/bwmarrin/discordgo/event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/bwmarrin/discordgo/event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -156,12 +156,20 @@ func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance | |||||||
| // Handles calling permanent and once handlers for an event type. | // Handles calling permanent and once handlers for an event type. | ||||||
| func (s *Session) handle(t string, i interface{}) { | func (s *Session) handle(t string, i interface{}) { | ||||||
| 	for _, eh := range s.handlers[t] { | 	for _, eh := range s.handlers[t] { | ||||||
| 		go eh.eventHandler.Handle(s, i) | 		if s.SyncEvents { | ||||||
|  | 			eh.eventHandler.Handle(s, i) | ||||||
|  | 		} else { | ||||||
|  | 			go eh.eventHandler.Handle(s, i) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(s.onceHandlers[t]) > 0 { | 	if len(s.onceHandlers[t]) > 0 { | ||||||
| 		for _, eh := range s.onceHandlers[t] { | 		for _, eh := range s.onceHandlers[t] { | ||||||
| 			go eh.eventHandler.Handle(s, i) | 			if s.SyncEvents { | ||||||
|  | 				eh.eventHandler.Handle(s, i) | ||||||
|  | 			} else { | ||||||
|  | 				go eh.eventHandler.Handle(s, i) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		s.onceHandlers[t] = nil | 		s.onceHandlers[t] = nil | ||||||
| 	} | 	} | ||||||
| @@ -216,7 +224,7 @@ func (s *Session) onInterface(i interface{}) { | |||||||
| 	case *VoiceStateUpdate: | 	case *VoiceStateUpdate: | ||||||
| 		go s.onVoiceStateUpdate(t) | 		go s.onVoiceStateUpdate(t) | ||||||
| 	} | 	} | ||||||
| 	err := s.State.onInterface(s, i) | 	err := s.State.OnInterface(s, i) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		s.log(LogDebug, "error dispatching internal event, %s", err) | 		s.log(LogDebug, "error dispatching internal event, %s", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										94
									
								
								vendor/github.com/bwmarrin/discordgo/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										94
									
								
								vendor/github.com/bwmarrin/discordgo/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,9 +10,24 @@ | |||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"regexp" | 	"regexp" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // MessageType is the type of Message | ||||||
|  | type MessageType int | ||||||
|  |  | ||||||
|  | // Block contains the valid known MessageType values | ||||||
|  | const ( | ||||||
|  | 	MessageTypeDefault MessageType = iota | ||||||
|  | 	MessageTypeRecipientAdd | ||||||
|  | 	MessageTypeRecipientRemove | ||||||
|  | 	MessageTypeCall | ||||||
|  | 	MessageTypeChannelNameChange | ||||||
|  | 	MessageTypeChannelIconChange | ||||||
|  | 	MessageTypeChannelPinnedMessage | ||||||
|  | 	MessageTypeGuildMemberJoin | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // A Message stores all data related to a specific Discord message. | // A Message stores all data related to a specific Discord message. | ||||||
| @@ -30,12 +45,14 @@ type Message struct { | |||||||
| 	Embeds          []*MessageEmbed      `json:"embeds"` | 	Embeds          []*MessageEmbed      `json:"embeds"` | ||||||
| 	Mentions        []*User              `json:"mentions"` | 	Mentions        []*User              `json:"mentions"` | ||||||
| 	Reactions       []*MessageReactions  `json:"reactions"` | 	Reactions       []*MessageReactions  `json:"reactions"` | ||||||
|  | 	Type            MessageType          `json:"type"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // File stores info about files you e.g. send in messages. | // File stores info about files you e.g. send in messages. | ||||||
| type File struct { | type File struct { | ||||||
| 	Name   string | 	Name        string | ||||||
| 	Reader io.Reader | 	ContentType string | ||||||
|  | 	Reader      io.Reader | ||||||
| } | } | ||||||
|  |  | ||||||
| // MessageSend stores all parameters you can send with ChannelMessageSendComplex. | // MessageSend stores all parameters you can send with ChannelMessageSendComplex. | ||||||
| @@ -43,7 +60,10 @@ type MessageSend struct { | |||||||
| 	Content string        `json:"content,omitempty"` | 	Content string        `json:"content,omitempty"` | ||||||
| 	Embed   *MessageEmbed `json:"embed,omitempty"` | 	Embed   *MessageEmbed `json:"embed,omitempty"` | ||||||
| 	Tts     bool          `json:"tts"` | 	Tts     bool          `json:"tts"` | ||||||
| 	File    *File         `json:"file"` | 	Files   []*File       `json:"-"` | ||||||
|  |  | ||||||
|  | 	// TODO: Remove this when compatibility is not required. | ||||||
|  | 	File *File `json:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // MessageEdit is used to chain parameters via ChannelMessageEditComplex, which | // MessageEdit is used to chain parameters via ChannelMessageEditComplex, which | ||||||
| @@ -168,13 +188,65 @@ type MessageReactions struct { | |||||||
|  |  | ||||||
| // ContentWithMentionsReplaced will replace all @<id> mentions with the | // ContentWithMentionsReplaced will replace all @<id> mentions with the | ||||||
| // username of the mention. | // username of the mention. | ||||||
| func (m *Message) ContentWithMentionsReplaced() string { | func (m *Message) ContentWithMentionsReplaced() (content string) { | ||||||
| 	if m.Mentions == nil { | 	content = m.Content | ||||||
| 		return m.Content |  | ||||||
| 	} |  | ||||||
| 	content := m.Content |  | ||||||
| 	for _, user := range m.Mentions { | 	for _, user := range m.Mentions { | ||||||
| 		content = regexp.MustCompile(fmt.Sprintf("<@!?(%s)>", user.ID)).ReplaceAllString(content, "@"+user.Username) | 		content = strings.NewReplacer( | ||||||
|  | 			"<@"+user.ID+">", "@"+user.Username, | ||||||
|  | 			"<@!"+user.ID+">", "@"+user.Username, | ||||||
|  | 		).Replace(content) | ||||||
| 	} | 	} | ||||||
| 	return content | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var patternChannels = regexp.MustCompile("<#[^>]*>") | ||||||
|  |  | ||||||
|  | // ContentWithMoreMentionsReplaced will replace all @<id> mentions with the | ||||||
|  | // username of the mention, but also role IDs and more. | ||||||
|  | func (m *Message) ContentWithMoreMentionsReplaced(s *Session) (content string, err error) { | ||||||
|  | 	content = m.Content | ||||||
|  |  | ||||||
|  | 	if !s.StateEnabled { | ||||||
|  | 		content = m.ContentWithMentionsReplaced() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	channel, err := s.State.Channel(m.ChannelID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		content = m.ContentWithMentionsReplaced() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, user := range m.Mentions { | ||||||
|  | 		nick := user.Username | ||||||
|  |  | ||||||
|  | 		member, err := s.State.Member(channel.GuildID, user.ID) | ||||||
|  | 		if err == nil && member.Nick != "" { | ||||||
|  | 			nick = member.Nick | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		content = strings.NewReplacer( | ||||||
|  | 			"<@"+user.ID+">", "@"+user.Username, | ||||||
|  | 			"<@!"+user.ID+">", "@"+nick, | ||||||
|  | 		).Replace(content) | ||||||
|  | 	} | ||||||
|  | 	for _, roleID := range m.MentionRoles { | ||||||
|  | 		role, err := s.State.Role(channel.GuildID, roleID) | ||||||
|  | 		if err != nil || !role.Mentionable { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		content = strings.Replace(content, "<&"+role.ID+">", "@"+role.Name, -1) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	content = patternChannels.ReplaceAllStringFunc(content, func(mention string) string { | ||||||
|  | 		channel, err := s.State.Channel(mention[2 : len(mention)-1]) | ||||||
|  | 		if err != nil || channel.Type == ChannelTypeGuildVoice { | ||||||
|  | 			return mention | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return "#" + channel.Name | ||||||
|  | 	}) | ||||||
|  | 	return | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								vendor/github.com/bwmarrin/discordgo/ratelimit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/bwmarrin/discordgo/ratelimit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,17 +3,26 @@ package discordgo | |||||||
| import ( | import ( | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // customRateLimit holds information for defining a custom rate limit | ||||||
|  | type customRateLimit struct { | ||||||
|  | 	suffix   string | ||||||
|  | 	requests int | ||||||
|  | 	reset    time.Duration | ||||||
|  | } | ||||||
|  |  | ||||||
| // RateLimiter holds all ratelimit buckets | // RateLimiter holds all ratelimit buckets | ||||||
| type RateLimiter struct { | type RateLimiter struct { | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| 	global          *int64 | 	global           *int64 | ||||||
| 	buckets         map[string]*Bucket | 	buckets          map[string]*Bucket | ||||||
| 	globalRateLimit time.Duration | 	globalRateLimit  time.Duration | ||||||
|  | 	customRateLimits []*customRateLimit | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewRatelimiter returns a new RateLimiter | // NewRatelimiter returns a new RateLimiter | ||||||
| @@ -22,6 +31,13 @@ func NewRatelimiter() *RateLimiter { | |||||||
| 	return &RateLimiter{ | 	return &RateLimiter{ | ||||||
| 		buckets: make(map[string]*Bucket), | 		buckets: make(map[string]*Bucket), | ||||||
| 		global:  new(int64), | 		global:  new(int64), | ||||||
|  | 		customRateLimits: []*customRateLimit{ | ||||||
|  | 			&customRateLimit{ | ||||||
|  | 				suffix:   "//reactions//", | ||||||
|  | 				requests: 1, | ||||||
|  | 				reset:    200 * time.Millisecond, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -40,6 +56,14 @@ func (r *RateLimiter) getBucket(key string) *Bucket { | |||||||
| 		global:    r.global, | 		global:    r.global, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Check if there is a custom ratelimit set for this bucket ID. | ||||||
|  | 	for _, rl := range r.customRateLimits { | ||||||
|  | 		if strings.HasSuffix(b.Key, rl.suffix) { | ||||||
|  | 			b.customRateLimit = rl | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	r.buckets[key] = b | 	r.buckets[key] = b | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
| @@ -76,13 +100,28 @@ type Bucket struct { | |||||||
| 	limit     int | 	limit     int | ||||||
| 	reset     time.Time | 	reset     time.Time | ||||||
| 	global    *int64 | 	global    *int64 | ||||||
|  |  | ||||||
|  | 	lastReset       time.Time | ||||||
|  | 	customRateLimit *customRateLimit | ||||||
| } | } | ||||||
|  |  | ||||||
| // Release unlocks the bucket and reads the headers to update the buckets ratelimit info | // Release unlocks the bucket and reads the headers to update the buckets ratelimit info | ||||||
| // and locks up the whole thing in case if there's a global ratelimit. | // and locks up the whole thing in case if there's a global ratelimit. | ||||||
| func (b *Bucket) Release(headers http.Header) error { | func (b *Bucket) Release(headers http.Header) error { | ||||||
|  |  | ||||||
| 	defer b.Unlock() | 	defer b.Unlock() | ||||||
|  |  | ||||||
|  | 	// Check if the bucket uses a custom ratelimiter | ||||||
|  | 	if rl := b.customRateLimit; rl != nil { | ||||||
|  | 		if time.Now().Sub(b.lastReset) >= rl.reset { | ||||||
|  | 			b.remaining = rl.requests - 1 | ||||||
|  | 			b.lastReset = time.Now() | ||||||
|  | 		} | ||||||
|  | 		if b.remaining < 1 { | ||||||
|  | 			b.reset = time.Now().Add(rl.reset) | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if headers == nil { | 	if headers == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										138
									
								
								vendor/github.com/bwmarrin/discordgo/restapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/bwmarrin/discordgo/restapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -23,6 +23,7 @@ import ( | |||||||
| 	"log" | 	"log" | ||||||
| 	"mime/multipart" | 	"mime/multipart" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/textproto" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -309,8 +310,8 @@ func (s *Session) UserUpdate(email, password, username, avatar, newPassword stri | |||||||
| 	// If left blank, avatar will be set to null/blank | 	// If left blank, avatar will be set to null/blank | ||||||
|  |  | ||||||
| 	data := struct { | 	data := struct { | ||||||
| 		Email       string `json:"email"` | 		Email       string `json:"email,omitempty"` | ||||||
| 		Password    string `json:"password"` | 		Password    string `json:"password,omitempty"` | ||||||
| 		Username    string `json:"username,omitempty"` | 		Username    string `json:"username,omitempty"` | ||||||
| 		Avatar      string `json:"avatar,omitempty"` | 		Avatar      string `json:"avatar,omitempty"` | ||||||
| 		NewPassword string `json:"new_password,omitempty"` | 		NewPassword string `json:"new_password,omitempty"` | ||||||
| @@ -763,7 +764,21 @@ func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) { | |||||||
| // userID    : The ID of a User | // userID    : The ID of a User | ||||||
| func (s *Session) GuildMemberDelete(guildID, userID string) (err error) { | func (s *Session) GuildMemberDelete(guildID, userID string) (err error) { | ||||||
|  |  | ||||||
| 	_, err = s.RequestWithBucketID("DELETE", EndpointGuildMember(guildID, userID), nil, EndpointGuildMember(guildID, "")) | 	return s.GuildMemberDeleteWithReason(guildID, userID, "") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GuildMemberDeleteWithReason removes the given user from the given guild. | ||||||
|  | // guildID   : The ID of a Guild. | ||||||
|  | // userID    : The ID of a User | ||||||
|  | // reason    : The reason for the kick | ||||||
|  | func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string) (err error) { | ||||||
|  |  | ||||||
|  | 	uri := EndpointGuildMember(guildID, userID) | ||||||
|  | 	if reason != "" { | ||||||
|  | 		uri += "?reason=" + url.QueryEscape(reason) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointGuildMember(guildID, "")) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1316,6 +1331,8 @@ func (s *Session) ChannelMessageSend(channelID string, content string) (*Message | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") | ||||||
|  |  | ||||||
| // ChannelMessageSendComplex sends a message to the given channel. | // ChannelMessageSendComplex sends a message to the given channel. | ||||||
| // channelID : The ID of a Channel. | // channelID : The ID of a Channel. | ||||||
| // data      : The message struct to send. | // data      : The message struct to send. | ||||||
| @@ -1326,48 +1343,62 @@ func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend) | |||||||
|  |  | ||||||
| 	endpoint := EndpointChannelMessages(channelID) | 	endpoint := EndpointChannelMessages(channelID) | ||||||
|  |  | ||||||
| 	var response []byte | 	// TODO: Remove this when compatibility is not required. | ||||||
|  | 	files := data.Files | ||||||
| 	if data.File != nil { | 	if data.File != nil { | ||||||
|  | 		if files == nil { | ||||||
|  | 			files = []*File{data.File} | ||||||
|  | 		} else { | ||||||
|  | 			err = fmt.Errorf("cannot specify both File and Files") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var response []byte | ||||||
|  | 	if len(files) > 0 { | ||||||
| 		body := &bytes.Buffer{} | 		body := &bytes.Buffer{} | ||||||
| 		bodywriter := multipart.NewWriter(body) | 		bodywriter := multipart.NewWriter(body) | ||||||
|  |  | ||||||
| 		// What's a better way of doing this? Reflect? Generator? I'm open to suggestions | 		var payload []byte | ||||||
|  | 		payload, err = json.Marshal(data) | ||||||
| 		if data.Content != "" { |  | ||||||
| 			if err = bodywriter.WriteField("content", data.Content); err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if data.Embed != nil { |  | ||||||
| 			var embed []byte |  | ||||||
| 			embed, err = json.Marshal(data.Embed) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			err = bodywriter.WriteField("embed", string(embed)) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if data.Tts { |  | ||||||
| 			if err = bodywriter.WriteField("tts", "true"); err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		var writer io.Writer |  | ||||||
| 		writer, err = bodywriter.CreateFormFile("file", data.File.Name) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		_, err = io.Copy(writer, data.File.Reader) | 		var p io.Writer | ||||||
|  |  | ||||||
|  | 		h := make(textproto.MIMEHeader) | ||||||
|  | 		h.Set("Content-Disposition", `form-data; name="payload_json"`) | ||||||
|  | 		h.Set("Content-Type", "application/json") | ||||||
|  |  | ||||||
|  | 		p, err = bodywriter.CreatePart(h) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if _, err = p.Write(payload); err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for i, file := range files { | ||||||
|  | 			h := make(textproto.MIMEHeader) | ||||||
|  | 			h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file%d"; filename="%s"`, i, quoteEscaper.Replace(file.Name))) | ||||||
|  | 			contentType := file.ContentType | ||||||
|  | 			if contentType == "" { | ||||||
|  | 				contentType = "application/octet-stream" | ||||||
|  | 			} | ||||||
|  | 			h.Set("Content-Type", contentType) | ||||||
|  |  | ||||||
|  | 			p, err = bodywriter.CreatePart(h) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if _, err = io.Copy(p, file.Reader); err != nil { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		err = bodywriter.Close() | 		err = bodywriter.Close() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| @@ -1685,6 +1716,28 @@ func (s *Session) Gateway() (gateway string, err error) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GatewayBot returns the websocket Gateway address and the recommended number of shards | ||||||
|  | func (s *Session) GatewayBot() (st *GatewayBotResponse, err error) { | ||||||
|  |  | ||||||
|  | 	response, err := s.RequestWithBucketID("GET", EndpointGatewayBot, nil, EndpointGatewayBot) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = unmarshal(response, &st) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Ensure the gateway always has a trailing slash. | ||||||
|  | 	// MacOS will fail to connect if we add query params without a trailing slash on the base domain. | ||||||
|  | 	if !strings.HasSuffix(st.URL, "/") { | ||||||
|  | 		st.URL += "/" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
| // Functions specific to Webhooks | // Functions specific to Webhooks | ||||||
|  |  | ||||||
| // WebhookCreate returns a new Webhook. | // WebhookCreate returns a new Webhook. | ||||||
| @@ -1810,14 +1863,9 @@ func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string) (s | |||||||
|  |  | ||||||
| // WebhookDelete deletes a webhook for a given ID | // WebhookDelete deletes a webhook for a given ID | ||||||
| // webhookID: The ID of a webhook. | // webhookID: The ID of a webhook. | ||||||
| func (s *Session) WebhookDelete(webhookID string) (st *Webhook, err error) { | func (s *Session) WebhookDelete(webhookID string) (err error) { | ||||||
|  |  | ||||||
| 	body, err := s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks) | 	_, err = s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks) | ||||||
| 	if err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	err = unmarshal(body, &st) |  | ||||||
|  |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @@ -1875,6 +1923,16 @@ func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID st | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // MessageReactionsRemoveAll deletes all reactions from a message | ||||||
|  | // channelID : The channel ID | ||||||
|  | // messageID : The message ID. | ||||||
|  | func (s *Session) MessageReactionsRemoveAll(channelID, messageID string) error { | ||||||
|  |  | ||||||
|  | 	_, err := s.RequestWithBucketID("DELETE", EndpointMessageReactionsAll(channelID, messageID), nil, EndpointMessageReactionsAll(channelID, messageID)) | ||||||
|  |  | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
| // MessageReactions gets all the users reactions for a specific emoji. | // MessageReactions gets all the users reactions for a specific emoji. | ||||||
| // channelID : The channel ID. | // channelID : The channel ID. | ||||||
| // messageID : The message ID. | // messageID : The message ID. | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								vendor/github.com/bwmarrin/discordgo/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								vendor/github.com/bwmarrin/discordgo/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -42,6 +42,7 @@ type State struct { | |||||||
|  |  | ||||||
| 	guildMap   map[string]*Guild | 	guildMap   map[string]*Guild | ||||||
| 	channelMap map[string]*Channel | 	channelMap map[string]*Channel | ||||||
|  | 	memberMap  map[string]map[string]*Member | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewState creates an empty state. | // NewState creates an empty state. | ||||||
| @@ -59,9 +60,18 @@ func NewState() *State { | |||||||
| 		TrackPresences: true, | 		TrackPresences: true, | ||||||
| 		guildMap:       make(map[string]*Guild), | 		guildMap:       make(map[string]*Guild), | ||||||
| 		channelMap:     make(map[string]*Channel), | 		channelMap:     make(map[string]*Channel), | ||||||
|  | 		memberMap:      make(map[string]map[string]*Member), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *State) createMemberMap(guild *Guild) { | ||||||
|  | 	members := make(map[string]*Member) | ||||||
|  | 	for _, m := range guild.Members { | ||||||
|  | 		members[m.User.ID] = m | ||||||
|  | 	} | ||||||
|  | 	s.memberMap[guild.ID] = members | ||||||
|  | } | ||||||
|  |  | ||||||
| // GuildAdd adds a guild to the current world state, or | // GuildAdd adds a guild to the current world state, or | ||||||
| // updates it if it already exists. | // updates it if it already exists. | ||||||
| func (s *State) GuildAdd(guild *Guild) error { | func (s *State) GuildAdd(guild *Guild) error { | ||||||
| @@ -77,6 +87,14 @@ func (s *State) GuildAdd(guild *Guild) error { | |||||||
| 		s.channelMap[c.ID] = c | 		s.channelMap[c.ID] = c | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// If this guild contains a new member slice, we must regenerate the member map so the pointers stay valid | ||||||
|  | 	if guild.Members != nil { | ||||||
|  | 		s.createMemberMap(guild) | ||||||
|  | 	} else if _, ok := s.memberMap[guild.ID]; !ok { | ||||||
|  | 		// Even if we have no new member slice, we still initialize the member map for this guild if it doesn't exist | ||||||
|  | 		s.memberMap[guild.ID] = make(map[string]*Member) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if g, ok := s.guildMap[guild.ID]; ok { | 	if g, ok := s.guildMap[guild.ID]; ok { | ||||||
| 		// We are about to replace `g` in the state with `guild`, but first we need to | 		// We are about to replace `g` in the state with `guild`, but first we need to | ||||||
| 		// make sure we preserve any fields that the `guild` doesn't contain from `g`. | 		// make sure we preserve any fields that the `guild` doesn't contain from `g`. | ||||||
| @@ -271,14 +289,19 @@ func (s *State) MemberAdd(member *Member) error { | |||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	defer s.Unlock() | 	defer s.Unlock() | ||||||
|  |  | ||||||
| 	for i, m := range guild.Members { | 	members, ok := s.memberMap[member.GuildID] | ||||||
| 		if m.User.ID == member.User.ID { | 	if !ok { | ||||||
| 			guild.Members[i] = member | 		return ErrStateNotFound | ||||||
| 			return nil | 	} | ||||||
| 		} |  | ||||||
|  | 	m, ok := members[member.User.ID] | ||||||
|  | 	if !ok { | ||||||
|  | 		members[member.User.ID] = member | ||||||
|  | 		guild.Members = append(guild.Members, member) | ||||||
|  | 	} else { | ||||||
|  | 		*m = *member // Update the actual data, which will also update the member pointer in the slice | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	guild.Members = append(guild.Members, member) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -296,6 +319,17 @@ func (s *State) MemberRemove(member *Member) error { | |||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	defer s.Unlock() | 	defer s.Unlock() | ||||||
|  |  | ||||||
|  | 	members, ok := s.memberMap[member.GuildID] | ||||||
|  | 	if !ok { | ||||||
|  | 		return ErrStateNotFound | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, ok = members[member.User.ID] | ||||||
|  | 	if !ok { | ||||||
|  | 		return ErrStateNotFound | ||||||
|  | 	} | ||||||
|  | 	delete(members, member.User.ID) | ||||||
|  |  | ||||||
| 	for i, m := range guild.Members { | 	for i, m := range guild.Members { | ||||||
| 		if m.User.ID == member.User.ID { | 		if m.User.ID == member.User.ID { | ||||||
| 			guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) | 			guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) | ||||||
| @@ -312,18 +346,17 @@ func (s *State) Member(guildID, userID string) (*Member, error) { | |||||||
| 		return nil, ErrNilState | 		return nil, ErrNilState | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	guild, err := s.Guild(guildID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	s.RLock() | 	s.RLock() | ||||||
| 	defer s.RUnlock() | 	defer s.RUnlock() | ||||||
|  |  | ||||||
| 	for _, m := range guild.Members { | 	members, ok := s.memberMap[guildID] | ||||||
| 		if m.User.ID == userID { | 	if !ok { | ||||||
| 			return m, nil | 		return nil, ErrStateNotFound | ||||||
| 		} | 	} | ||||||
|  |  | ||||||
|  | 	m, ok := members[userID] | ||||||
|  | 	if ok { | ||||||
|  | 		return m, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil, ErrStateNotFound | 	return nil, ErrStateNotFound | ||||||
| @@ -427,7 +460,7 @@ func (s *State) ChannelAdd(channel *Channel) error { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if channel.IsPrivate { | 	if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM { | ||||||
| 		s.PrivateChannels = append(s.PrivateChannels, channel) | 		s.PrivateChannels = append(s.PrivateChannels, channel) | ||||||
| 	} else { | 	} else { | ||||||
| 		guild, ok := s.guildMap[channel.GuildID] | 		guild, ok := s.guildMap[channel.GuildID] | ||||||
| @@ -454,7 +487,7 @@ func (s *State) ChannelRemove(channel *Channel) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if channel.IsPrivate { | 	if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM { | ||||||
| 		s.Lock() | 		s.Lock() | ||||||
| 		defer s.Unlock() | 		defer s.Unlock() | ||||||
|  |  | ||||||
| @@ -735,6 +768,7 @@ func (s *State) onReady(se *Session, r *Ready) (err error) { | |||||||
|  |  | ||||||
| 	for _, g := range s.Guilds { | 	for _, g := range s.Guilds { | ||||||
| 		s.guildMap[g.ID] = g | 		s.guildMap[g.ID] = g | ||||||
|  | 		s.createMemberMap(g) | ||||||
|  |  | ||||||
| 		for _, c := range g.Channels { | 		for _, c := range g.Channels { | ||||||
| 			s.channelMap[c.ID] = c | 			s.channelMap[c.ID] = c | ||||||
| @@ -748,8 +782,8 @@ func (s *State) onReady(se *Session, r *Ready) (err error) { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // onInterface handles all events related to states. | // OnInterface handles all events related to states. | ||||||
| func (s *State) onInterface(se *Session, i interface{}) (err error) { | func (s *State) OnInterface(se *Session, i interface{}) (err error) { | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return ErrNilState | 		return ErrNilState | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								vendor/github.com/bwmarrin/discordgo/structs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										87
									
								
								vendor/github.com/bwmarrin/discordgo/structs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -50,6 +50,10 @@ type Session struct { | |||||||
| 	// active guilds and the members of the guilds. | 	// active guilds and the members of the guilds. | ||||||
| 	StateEnabled bool | 	StateEnabled bool | ||||||
|  |  | ||||||
|  | 	// Whether or not to call event handlers synchronously. | ||||||
|  | 	// e.g false = launch event handlers in their own goroutines. | ||||||
|  | 	SyncEvents bool | ||||||
|  |  | ||||||
| 	// Exposed but should not be modified by User. | 	// Exposed but should not be modified by User. | ||||||
|  |  | ||||||
| 	// Whether the Data Websocket is ready | 	// Whether the Data Websocket is ready | ||||||
| @@ -78,6 +82,9 @@ type Session struct { | |||||||
| 	// The http client used for REST requests | 	// The http client used for REST requests | ||||||
| 	Client *http.Client | 	Client *http.Client | ||||||
|  |  | ||||||
|  | 	// Stores the last HeartbeatAck that was recieved (in UTC) | ||||||
|  | 	LastHeartbeatAck time.Time | ||||||
|  |  | ||||||
| 	// Event handlers | 	// Event handlers | ||||||
| 	handlersMu   sync.RWMutex | 	handlersMu   sync.RWMutex | ||||||
| 	handlers     map[string][]*eventHandlerInstance | 	handlers     map[string][]*eventHandlerInstance | ||||||
| @@ -141,18 +148,30 @@ type Invite struct { | |||||||
| 	Temporary bool      `json:"temporary"` | 	Temporary bool      `json:"temporary"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ChannelType is the type of a Channel | ||||||
|  | type ChannelType int | ||||||
|  |  | ||||||
|  | // Block contains known ChannelType values | ||||||
|  | const ( | ||||||
|  | 	ChannelTypeGuildText ChannelType = iota | ||||||
|  | 	ChannelTypeDM | ||||||
|  | 	ChannelTypeGuildVoice | ||||||
|  | 	ChannelTypeGroupDM | ||||||
|  | 	ChannelTypeGuildCategory | ||||||
|  | ) | ||||||
|  |  | ||||||
| // A Channel holds all data related to an individual Discord channel. | // A Channel holds all data related to an individual Discord channel. | ||||||
| type Channel struct { | type Channel struct { | ||||||
| 	ID                   string                 `json:"id"` | 	ID                   string                 `json:"id"` | ||||||
| 	GuildID              string                 `json:"guild_id"` | 	GuildID              string                 `json:"guild_id"` | ||||||
| 	Name                 string                 `json:"name"` | 	Name                 string                 `json:"name"` | ||||||
| 	Topic                string                 `json:"topic"` | 	Topic                string                 `json:"topic"` | ||||||
| 	Type                 string                 `json:"type"` | 	Type                 ChannelType            `json:"type"` | ||||||
| 	LastMessageID        string                 `json:"last_message_id"` | 	LastMessageID        string                 `json:"last_message_id"` | ||||||
|  | 	NSFW                 bool                   `json:"nsfw"` | ||||||
| 	Position             int                    `json:"position"` | 	Position             int                    `json:"position"` | ||||||
| 	Bitrate              int                    `json:"bitrate"` | 	Bitrate              int                    `json:"bitrate"` | ||||||
| 	IsPrivate            bool                   `json:"is_private"` | 	Recipients           []*User                `json:"recipient"` | ||||||
| 	Recipient            *User                  `json:"recipient"` |  | ||||||
| 	Messages             []*Message             `json:"-"` | 	Messages             []*Message             `json:"-"` | ||||||
| 	PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"` | 	PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"` | ||||||
| } | } | ||||||
| @@ -292,13 +311,14 @@ type Presence struct { | |||||||
| 	Game   *Game    `json:"game"` | 	Game   *Game    `json:"game"` | ||||||
| 	Nick   string   `json:"nick"` | 	Nick   string   `json:"nick"` | ||||||
| 	Roles  []string `json:"roles"` | 	Roles  []string `json:"roles"` | ||||||
|  | 	Since  *int     `json:"since"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // A Game struct holds the name of the "playing .." game for a user | // A Game struct holds the name of the "playing .." game for a user | ||||||
| type Game struct { | type Game struct { | ||||||
| 	Name string `json:"name"` | 	Name string `json:"name"` | ||||||
| 	Type int    `json:"type"` | 	Type int    `json:"type"` | ||||||
| 	URL  string `json:"url"` | 	URL  string `json:"url,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // UnmarshalJSON unmarshals json to Game struct | // UnmarshalJSON unmarshals json to Game struct | ||||||
| @@ -509,6 +529,12 @@ type MessageReaction struct { | |||||||
| 	ChannelID string `json:"channel_id"` | 	ChannelID string `json:"channel_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GatewayBotResponse stores the data for the gateway/bot response | ||||||
|  | type GatewayBotResponse struct { | ||||||
|  | 	URL    string `json:"url"` | ||||||
|  | 	Shards int    `json:"shards"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // Constants for the different bit offsets of text channel permissions | // Constants for the different bit offsets of text channel permissions | ||||||
| const ( | const ( | ||||||
| 	PermissionReadMessages = 1 << (iota + 10) | 	PermissionReadMessages = 1 << (iota + 10) | ||||||
| @@ -579,3 +605,56 @@ const ( | |||||||
| 		PermissionManageServer | | 		PermissionManageServer | | ||||||
| 		PermissionAdministrator | 		PermissionAdministrator | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Block contains Discord JSON Error Response codes | ||||||
|  | const ( | ||||||
|  | 	ErrCodeUnknownAccount     = 10001 | ||||||
|  | 	ErrCodeUnknownApplication = 10002 | ||||||
|  | 	ErrCodeUnknownChannel     = 10003 | ||||||
|  | 	ErrCodeUnknownGuild       = 10004 | ||||||
|  | 	ErrCodeUnknownIntegration = 10005 | ||||||
|  | 	ErrCodeUnknownInvite      = 10006 | ||||||
|  | 	ErrCodeUnknownMember      = 10007 | ||||||
|  | 	ErrCodeUnknownMessage     = 10008 | ||||||
|  | 	ErrCodeUnknownOverwrite   = 10009 | ||||||
|  | 	ErrCodeUnknownProvider    = 10010 | ||||||
|  | 	ErrCodeUnknownRole        = 10011 | ||||||
|  | 	ErrCodeUnknownToken       = 10012 | ||||||
|  | 	ErrCodeUnknownUser        = 10013 | ||||||
|  | 	ErrCodeUnknownEmoji       = 10014 | ||||||
|  |  | ||||||
|  | 	ErrCodeBotsCannotUseEndpoint  = 20001 | ||||||
|  | 	ErrCodeOnlyBotsCanUseEndpoint = 20002 | ||||||
|  |  | ||||||
|  | 	ErrCodeMaximumGuildsReached     = 30001 | ||||||
|  | 	ErrCodeMaximumFriendsReached    = 30002 | ||||||
|  | 	ErrCodeMaximumPinsReached       = 30003 | ||||||
|  | 	ErrCodeMaximumGuildRolesReached = 30005 | ||||||
|  | 	ErrCodeTooManyReactions         = 30010 | ||||||
|  |  | ||||||
|  | 	ErrCodeUnauthorized = 40001 | ||||||
|  |  | ||||||
|  | 	ErrCodeMissingAccess                             = 50001 | ||||||
|  | 	ErrCodeInvalidAccountType                        = 50002 | ||||||
|  | 	ErrCodeCannotExecuteActionOnDMChannel            = 50003 | ||||||
|  | 	ErrCodeEmbedCisabled                             = 50004 | ||||||
|  | 	ErrCodeCannotEditFromAnotherUser                 = 50005 | ||||||
|  | 	ErrCodeCannotSendEmptyMessage                    = 50006 | ||||||
|  | 	ErrCodeCannotSendMessagesToThisUser              = 50007 | ||||||
|  | 	ErrCodeCannotSendMessagesInVoiceChannel          = 50008 | ||||||
|  | 	ErrCodeChannelVerificationLevelTooHigh           = 50009 | ||||||
|  | 	ErrCodeOAuth2ApplicationDoesNotHaveBot           = 50010 | ||||||
|  | 	ErrCodeOAuth2ApplicationLimitReached             = 50011 | ||||||
|  | 	ErrCodeInvalidOAuthState                         = 50012 | ||||||
|  | 	ErrCodeMissingPermissions                        = 50013 | ||||||
|  | 	ErrCodeInvalidAuthenticationToken                = 50014 | ||||||
|  | 	ErrCodeNoteTooLong                               = 50015 | ||||||
|  | 	ErrCodeTooFewOrTooManyMessagesToDelete           = 50016 | ||||||
|  | 	ErrCodeCanOnlyPinMessageToOriginatingChannel     = 50019 | ||||||
|  | 	ErrCodeCannotExecuteActionOnSystemMessage        = 50021 | ||||||
|  | 	ErrCodeMessageProvidedTooOldForBulkDelete        = 50034 | ||||||
|  | 	ErrCodeInvalidFormBody                           = 50035 | ||||||
|  | 	ErrCodeInviteAcceptedToGuildApplicationsBotNotIn = 50036 | ||||||
|  |  | ||||||
|  | 	ErrCodeReactionBlocked = 90001 | ||||||
|  | ) | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								vendor/github.com/bwmarrin/discordgo/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/bwmarrin/discordgo/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,9 @@ | |||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
| import "fmt" | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
| // A User stores all data for an individual Discord user. | // A User stores all data for an individual Discord user. | ||||||
| type User struct { | type User struct { | ||||||
| @@ -24,3 +27,16 @@ func (u *User) String() string { | |||||||
| func (u *User) Mention() string { | func (u *User) Mention() string { | ||||||
| 	return fmt.Sprintf("<@%s>", u.ID) | 	return fmt.Sprintf("<@%s>", u.ID) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // AvatarURL returns a URL to the user's avatar. | ||||||
|  | //		size:     The size of the user's avatar as a power of two | ||||||
|  | func (u *User) AvatarURL(size string) string { | ||||||
|  | 	var URL string | ||||||
|  | 	if strings.HasPrefix(u.Avatar, "a_") { | ||||||
|  | 		URL = EndpointUserAvatarAnimated(u.ID, u.Avatar) | ||||||
|  | 	} else { | ||||||
|  | 		URL = EndpointUserAvatar(u.ID, u.Avatar) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return URL + "?size=" + size | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								vendor/github.com/bwmarrin/discordgo/voice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/bwmarrin/discordgo/voice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -796,7 +796,7 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// For now, skip anything except audio. | 		// For now, skip anything except audio. | ||||||
| 		if rlen < 12 || recvbuf[0] != 0x80 { | 		if rlen < 12 || (recvbuf[0] != 0x80 && recvbuf[0] != 0x90) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -810,8 +810,17 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct | |||||||
| 		copy(nonce[:], recvbuf[0:12]) | 		copy(nonce[:], recvbuf[0:12]) | ||||||
| 		p.Opus, _ = secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey) | 		p.Opus, _ = secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey) | ||||||
|  |  | ||||||
|  | 		if len(p.Opus) > 8 && recvbuf[0] == 0x90 { | ||||||
|  | 			// Extension bit is set, first 8 bytes is the extended header | ||||||
|  | 			p.Opus = p.Opus[8:] | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if c != nil { | 		if c != nil { | ||||||
| 			c <- &p | 			select { | ||||||
|  | 			case c <- &p: | ||||||
|  | 			case <-close: | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								vendor/github.com/bwmarrin/discordgo/wsapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								vendor/github.com/bwmarrin/discordgo/wsapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -15,7 +15,6 @@ import ( | |||||||
| 	"compress/zlib" | 	"compress/zlib" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| @@ -87,7 +86,7 @@ func (s *Session) Open() (err error) { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Add the version and encoding to the URL | 		// Add the version and encoding to the URL | ||||||
| 		s.gateway = fmt.Sprintf("%s?v=5&encoding=json", s.gateway) | 		s.gateway = s.gateway + "?v=" + APIVersion + "&encoding=json" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	header := http.Header{} | 	header := http.Header{} | ||||||
| @@ -131,6 +130,7 @@ func (s *Session) Open() (err error) { | |||||||
| 	// lock. | 	// lock. | ||||||
| 	s.listening = make(chan interface{}) | 	s.listening = make(chan interface{}) | ||||||
| 	go s.listen(s.wsConn, s.listening) | 	go s.listen(s.wsConn, s.listening) | ||||||
|  | 	s.LastHeartbeatAck = time.Now().UTC() | ||||||
|  |  | ||||||
| 	s.Unlock() | 	s.Unlock() | ||||||
|  |  | ||||||
| @@ -199,10 +199,13 @@ type helloOp struct { | |||||||
| 	Trace             []string      `json:"_trace"` | 	Trace             []string      `json:"_trace"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // FailedHeartbeatAcks is the Number of heartbeat intervals to wait until forcing a connection restart. | ||||||
|  | const FailedHeartbeatAcks time.Duration = 5 * time.Millisecond | ||||||
|  |  | ||||||
| // heartbeat sends regular heartbeats to Discord so it knows the client | // heartbeat sends regular heartbeats to Discord so it knows the client | ||||||
| // is still connected.  If you do not send these heartbeats Discord will | // is still connected.  If you do not send these heartbeats Discord will | ||||||
| // disconnect the websocket connection after a few seconds. | // disconnect the websocket connection after a few seconds. | ||||||
| func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}, i time.Duration) { | func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}, heartbeatIntervalMsec time.Duration) { | ||||||
|  |  | ||||||
| 	s.log(LogInformational, "called") | 	s.log(LogInformational, "called") | ||||||
|  |  | ||||||
| @@ -211,20 +214,26 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{} | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var err error | 	var err error | ||||||
| 	ticker := time.NewTicker(i * time.Millisecond) | 	ticker := time.NewTicker(heartbeatIntervalMsec * time.Millisecond) | ||||||
| 	defer ticker.Stop() | 	defer ticker.Stop() | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
|  | 		s.RLock() | ||||||
|  | 		last := s.LastHeartbeatAck | ||||||
|  | 		s.RUnlock() | ||||||
| 		sequence := atomic.LoadInt64(s.sequence) | 		sequence := atomic.LoadInt64(s.sequence) | ||||||
| 		s.log(LogInformational, "sending gateway websocket heartbeat seq %d", sequence) | 		s.log(LogInformational, "sending gateway websocket heartbeat seq %d", sequence) | ||||||
| 		s.wsMutex.Lock() | 		s.wsMutex.Lock() | ||||||
| 		err = wsConn.WriteJSON(heartbeatOp{1, sequence}) | 		err = wsConn.WriteJSON(heartbeatOp{1, sequence}) | ||||||
| 		s.wsMutex.Unlock() | 		s.wsMutex.Unlock() | ||||||
| 		if err != nil { | 		if err != nil || time.Now().UTC().Sub(last) > (heartbeatIntervalMsec*FailedHeartbeatAcks) { | ||||||
| 			s.log(LogError, "error sending heartbeat to gateway %s, %s", s.gateway, err) | 			if err != nil { | ||||||
| 			s.Lock() | 				s.log(LogError, "error sending heartbeat to gateway %s, %s", s.gateway, err) | ||||||
| 			s.DataReady = false | 			} else { | ||||||
| 			s.Unlock() | 				s.log(LogError, "haven't gotten a heartbeat ACK in %v, triggering a reconnection", time.Now().UTC().Sub(last)) | ||||||
|  | 			} | ||||||
|  | 			s.Close() | ||||||
|  | 			s.reconnect() | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		s.Lock() | 		s.Lock() | ||||||
| @@ -241,8 +250,10 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{} | |||||||
| } | } | ||||||
|  |  | ||||||
| type updateStatusData struct { | type updateStatusData struct { | ||||||
| 	IdleSince *int  `json:"idle_since"` | 	IdleSince *int   `json:"since"` | ||||||
| 	Game      *Game `json:"game"` | 	Game      *Game  `json:"game"` | ||||||
|  | 	AFK       bool   `json:"afk"` | ||||||
|  | 	Status    string `json:"status"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type updateStatusOp struct { | type updateStatusOp struct { | ||||||
| @@ -265,7 +276,10 @@ func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err | |||||||
| 		return ErrWSNotFound | 		return ErrWSNotFound | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var usd updateStatusData | 	usd := updateStatusData{ | ||||||
|  | 		Status: "online", | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if idle > 0 { | 	if idle > 0 { | ||||||
| 		usd.IdleSince = &idle | 		usd.IdleSince = &idle | ||||||
| 	} | 	} | ||||||
| @@ -398,7 +412,10 @@ func (s *Session) onEvent(messageType int, message []byte) { | |||||||
| 	// Reconnect | 	// Reconnect | ||||||
| 	// Must immediately disconnect from gateway and reconnect to new gateway. | 	// Must immediately disconnect from gateway and reconnect to new gateway. | ||||||
| 	if e.Operation == 7 { | 	if e.Operation == 7 { | ||||||
| 		// TODO | 		s.log(LogInformational, "Closing and reconnecting in response to Op7") | ||||||
|  | 		s.Close() | ||||||
|  | 		s.reconnect() | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Invalid Session | 	// Invalid Session | ||||||
| @@ -426,6 +443,14 @@ func (s *Session) onEvent(messageType int, message []byte) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if e.Operation == 11 { | ||||||
|  | 		s.Lock() | ||||||
|  | 		s.LastHeartbeatAck = time.Now().UTC() | ||||||
|  | 		s.Unlock() | ||||||
|  | 		s.log(LogInformational, "got heartbeat ACK") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Do not try to Dispatch a non-Dispatch Message | 	// Do not try to Dispatch a non-Dispatch Message | ||||||
| 	if e.Operation != 0 { | 	if e.Operation != 0 { | ||||||
| 		// But we probably should be doing something with them. | 		// But we probably should be doing something with them. | ||||||
| @@ -688,6 +713,13 @@ func (s *Session) reconnect() { | |||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// Certain race conditions can call reconnect() twice. If this happens, we | ||||||
|  | 			// just break out of the reconnect loop | ||||||
|  | 			if err == ErrWSAlreadyOpen { | ||||||
|  | 				s.log(LogInformational, "Websocket already exists, no need to reconnect") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			s.log(LogError, "error reconnecting to gateway, %s", err) | 			s.log(LogError, "error reconnecting to gateway, %s", err) | ||||||
|  |  | ||||||
| 			<-time.After(wait * time.Second) | 			<-time.After(wait * time.Second) | ||||||
|   | |||||||
							
								
								
									
										197
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										197
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -191,7 +191,11 @@ func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldna | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var apiResp APIResponse | 	var apiResp APIResponse | ||||||
| 	json.Unmarshal(bytes, &apiResp) |  | ||||||
|  | 	err = json.Unmarshal(bytes, &apiResp) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return APIResponse{}, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if !apiResp.Ok { | 	if !apiResp.Ok { | ||||||
| 		return APIResponse{}, errors.New(apiResp.Description) | 		return APIResponse{}, errors.New(apiResp.Description) | ||||||
| @@ -438,14 +442,7 @@ func (bot *BotAPI) SetWebhook(config WebhookConfig) (APIResponse, error) { | |||||||
| 		return APIResponse{}, err | 		return APIResponse{}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var apiResp APIResponse | 	return resp, nil | ||||||
| 	json.Unmarshal(resp.Result, &apiResp) |  | ||||||
|  |  | ||||||
| 	if bot.Debug { |  | ||||||
| 		log.Printf("setWebhook resp: %+v\n", apiResp) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return apiResp, nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetWebhookInfo allows you to fetch information about a webhook and if | // GetWebhookInfo allows you to fetch information about a webhook and if | ||||||
| @@ -550,7 +547,7 @@ func (bot *BotAPI) AnswerCallbackQuery(config CallbackConfig) (APIResponse, erro | |||||||
| // KickChatMember kicks a user from a chat. Note that this only will work | // KickChatMember kicks a user from a chat. Note that this only will work | ||||||
| // in supergroups, and requires the bot to be an admin. Also note they | // in supergroups, and requires the bot to be an admin. Also note they | ||||||
| // will be unable to rejoin until they are unbanned. | // will be unable to rejoin until they are unbanned. | ||||||
| func (bot *BotAPI) KickChatMember(config ChatMemberConfig) (APIResponse, error) { | func (bot *BotAPI) KickChatMember(config KickChatMemberConfig) (APIResponse, error) { | ||||||
| 	v := url.Values{} | 	v := url.Values{} | ||||||
|  |  | ||||||
| 	if config.SuperGroupUsername == "" { | 	if config.SuperGroupUsername == "" { | ||||||
| @@ -560,6 +557,10 @@ func (bot *BotAPI) KickChatMember(config ChatMemberConfig) (APIResponse, error) | |||||||
| 	} | 	} | ||||||
| 	v.Add("user_id", strconv.Itoa(config.UserID)) | 	v.Add("user_id", strconv.Itoa(config.UserID)) | ||||||
|  |  | ||||||
|  | 	if config.UntilDate != 0 { | ||||||
|  | 		v.Add("until_date", strconv.FormatInt(config.UntilDate, 10)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	bot.debugLog("kickChatMember", v, nil) | 	bot.debugLog("kickChatMember", v, nil) | ||||||
|  |  | ||||||
| 	return bot.MakeRequest("kickChatMember", v) | 	return bot.MakeRequest("kickChatMember", v) | ||||||
| @@ -677,14 +678,16 @@ func (bot *BotAPI) GetChatMember(config ChatConfigWithUser) (ChatMember, error) | |||||||
| } | } | ||||||
|  |  | ||||||
| // UnbanChatMember unbans a user from a chat. Note that this only will work | // UnbanChatMember unbans a user from a chat. Note that this only will work | ||||||
| // in supergroups, and requires the bot to be an admin. | // in supergroups and channels, and requires the bot to be an admin. | ||||||
| func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) { | func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) { | ||||||
| 	v := url.Values{} | 	v := url.Values{} | ||||||
|  |  | ||||||
| 	if config.SuperGroupUsername == "" { | 	if config.SuperGroupUsername != "" { | ||||||
| 		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) |  | ||||||
| 	} else { |  | ||||||
| 		v.Add("chat_id", config.SuperGroupUsername) | 		v.Add("chat_id", config.SuperGroupUsername) | ||||||
|  | 	} else if config.ChannelUsername != "" { | ||||||
|  | 		v.Add("chat_id", config.ChannelUsername) | ||||||
|  | 	} else { | ||||||
|  | 		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
| 	} | 	} | ||||||
| 	v.Add("user_id", strconv.Itoa(config.UserID)) | 	v.Add("user_id", strconv.Itoa(config.UserID)) | ||||||
|  |  | ||||||
| @@ -693,6 +696,82 @@ func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) | |||||||
| 	return bot.MakeRequest("unbanChatMember", v) | 	return bot.MakeRequest("unbanChatMember", v) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // RestrictChatMember to restrict a user in a supergroup. The bot must be an | ||||||
|  | //administrator in the supergroup for this to work and must have the | ||||||
|  | //appropriate admin rights. Pass True for all boolean parameters to lift | ||||||
|  | //restrictions from a user. Returns True on success. | ||||||
|  | func (bot *BotAPI) RestrictChatMember(config RestrictChatMemberConfig) (APIResponse, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	if config.SuperGroupUsername != "" { | ||||||
|  | 		v.Add("chat_id", config.SuperGroupUsername) | ||||||
|  | 	} else if config.ChannelUsername != "" { | ||||||
|  | 		v.Add("chat_id", config.ChannelUsername) | ||||||
|  | 	} else { | ||||||
|  | 		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  | 	} | ||||||
|  | 	v.Add("user_id", strconv.Itoa(config.UserID)) | ||||||
|  |  | ||||||
|  | 	if &config.CanSendMessages != nil { | ||||||
|  | 		v.Add("can_send_messages", strconv.FormatBool(*config.CanSendMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanSendMediaMessages != nil { | ||||||
|  | 		v.Add("can_send_media_messages", strconv.FormatBool(*config.CanSendMediaMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanSendOtherMessages != nil { | ||||||
|  | 		v.Add("can_send_other_messages", strconv.FormatBool(*config.CanSendOtherMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanAddWebPagePreviews != nil { | ||||||
|  | 		v.Add("can_add_web_page_previews", strconv.FormatBool(*config.CanAddWebPagePreviews)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog("restrictChatMember", v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest("restrictChatMember", v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (bot *BotAPI) PromoteChatMember(config PromoteChatMemberConfig) (APIResponse, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	if config.SuperGroupUsername != "" { | ||||||
|  | 		v.Add("chat_id", config.SuperGroupUsername) | ||||||
|  | 	} else if config.ChannelUsername != "" { | ||||||
|  | 		v.Add("chat_id", config.ChannelUsername) | ||||||
|  | 	} else { | ||||||
|  | 		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  | 	} | ||||||
|  | 	v.Add("user_id", strconv.Itoa(config.UserID)) | ||||||
|  |  | ||||||
|  | 	if &config.CanChangeInfo != nil { | ||||||
|  | 		v.Add("can_change_info", strconv.FormatBool(*config.CanChangeInfo)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanPostMessages != nil { | ||||||
|  | 		v.Add("can_post_messages", strconv.FormatBool(*config.CanPostMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanEditMessages != nil { | ||||||
|  | 		v.Add("can_edit_messages", strconv.FormatBool(*config.CanEditMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanDeleteMessages != nil { | ||||||
|  | 		v.Add("can_delete_messages", strconv.FormatBool(*config.CanDeleteMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanInviteUsers != nil { | ||||||
|  | 		v.Add("can_invite_users", strconv.FormatBool(*config.CanInviteUsers)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanRestrictMembers != nil { | ||||||
|  | 		v.Add("can_restrict_members", strconv.FormatBool(*config.CanRestrictMembers)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanPinMessages != nil { | ||||||
|  | 		v.Add("can_pin_messages", strconv.FormatBool(*config.CanPinMessages)) | ||||||
|  | 	} | ||||||
|  | 	if &config.CanPromoteMembers != nil { | ||||||
|  | 		v.Add("can_promote_members", strconv.FormatBool(*config.CanPromoteMembers)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog("promoteChatMember", v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest("promoteChatMember", v) | ||||||
|  | } | ||||||
|  |  | ||||||
| // GetGameHighScores allows you to get the high scores for a game. | // GetGameHighScores allows you to get the high scores for a game. | ||||||
| func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) { | func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) { | ||||||
| 	v, _ := config.values() | 	v, _ := config.values() | ||||||
| @@ -707,3 +786,93 @@ func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHigh | |||||||
|  |  | ||||||
| 	return highScores, err | 	return highScores, err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // AnswerShippingQuery allows you to reply to Update with shipping_query parameter. | ||||||
|  | func (bot *BotAPI) AnswerShippingQuery(config ShippingConfig) (APIResponse, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	v.Add("shipping_query_id", config.ShippingQueryID) | ||||||
|  | 	v.Add("ok", strconv.FormatBool(config.OK)) | ||||||
|  | 	if config.OK == true { | ||||||
|  | 		data, err := json.Marshal(config.ShippingOptions) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return APIResponse{}, err | ||||||
|  | 		} | ||||||
|  | 		v.Add("shipping_options", string(data)) | ||||||
|  | 	} else { | ||||||
|  | 		v.Add("error_message", config.ErrorMessage) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog("answerShippingQuery", v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest("answerShippingQuery", v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AnswerPreCheckoutQuery allows you to reply to Update with pre_checkout_query. | ||||||
|  | func (bot *BotAPI) AnswerPreCheckoutQuery(config PreCheckoutConfig) (APIResponse, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	v.Add("pre_checkout_query_id", config.PreCheckoutQueryID) | ||||||
|  | 	v.Add("ok", strconv.FormatBool(config.OK)) | ||||||
|  | 	if config.OK != true { | ||||||
|  | 		v.Add("error", config.ErrorMessage) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog("answerPreCheckoutQuery", v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest("answerPreCheckoutQuery", v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeleteMessage deletes a message in a chat | ||||||
|  | func (bot *BotAPI) DeleteMessage(config DeleteMessageConfig) (APIResponse, error) { | ||||||
|  | 	v, err := config.values() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return APIResponse{}, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog(config.method(), v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest(config.method(), v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetInviteLink get InviteLink for a chat | ||||||
|  | func (bot *BotAPI) GetInviteLink(config ChatConfig) (string, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	if config.SuperGroupUsername == "" { | ||||||
|  | 		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  | 	} else { | ||||||
|  | 		v.Add("chat_id", config.SuperGroupUsername) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp, err := bot.MakeRequest("exportChatInviteLink", v) | ||||||
|  |  | ||||||
|  | 	var inviteLink string | ||||||
|  | 	err = json.Unmarshal(resp.Result, &inviteLink) | ||||||
|  |  | ||||||
|  | 	return inviteLink, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Pin message in supergroup | ||||||
|  | func (bot *BotAPI) PinChatMessage(config PinChatMessageConfig) (APIResponse, error) { | ||||||
|  | 	v, err := config.values() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return APIResponse{}, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog(config.method(), v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest(config.method(), v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Unpin message in supergroup | ||||||
|  | func (bot *BotAPI) UnpinChatMessage(config UnpinChatMessageConfig) (APIResponse, error) { | ||||||
|  | 	v, err := config.values() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return APIResponse{}, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bot.debugLog(config.method(), v, nil) | ||||||
|  |  | ||||||
|  | 	return bot.MakeRequest(config.method(), v) | ||||||
|  | } | ||||||
							
								
								
									
										243
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										243
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -349,6 +349,7 @@ func (config AudioConfig) method() string { | |||||||
| // DocumentConfig contains information about a SendDocument request. | // DocumentConfig contains information about a SendDocument request. | ||||||
| type DocumentConfig struct { | type DocumentConfig struct { | ||||||
| 	BaseFile | 	BaseFile | ||||||
|  | 	Caption string | ||||||
| } | } | ||||||
|  |  | ||||||
| // values returns a url.Values representation of DocumentConfig. | // values returns a url.Values representation of DocumentConfig. | ||||||
| @@ -359,6 +360,9 @@ func (config DocumentConfig) values() (url.Values, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v.Add(config.name(), config.FileID) | 	v.Add(config.name(), config.FileID) | ||||||
|  | 	if config.Caption != "" { | ||||||
|  | 		v.Add("caption", config.Caption) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return v, nil | 	return v, nil | ||||||
| } | } | ||||||
| @@ -367,6 +371,10 @@ func (config DocumentConfig) values() (url.Values, error) { | |||||||
| func (config DocumentConfig) params() (map[string]string, error) { | func (config DocumentConfig) params() (map[string]string, error) { | ||||||
| 	params, _ := config.BaseFile.params() | 	params, _ := config.BaseFile.params() | ||||||
|  |  | ||||||
|  | 	if config.Caption != "" { | ||||||
|  | 		params["caption"] = config.Caption | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return params, nil | 	return params, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -443,6 +451,10 @@ func (config VideoConfig) values() (url.Values, error) { | |||||||
| func (config VideoConfig) params() (map[string]string, error) { | func (config VideoConfig) params() (map[string]string, error) { | ||||||
| 	params, _ := config.BaseFile.params() | 	params, _ := config.BaseFile.params() | ||||||
|  |  | ||||||
|  | 	if config.Caption != "" { | ||||||
|  | 		params["caption"] = config.Caption | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return params, nil | 	return params, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -456,6 +468,57 @@ func (config VideoConfig) method() string { | |||||||
| 	return "sendVideo" | 	return "sendVideo" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // VideoNoteConfig contains information about a SendVideoNote request. | ||||||
|  | type VideoNoteConfig struct { | ||||||
|  | 	BaseFile | ||||||
|  | 	Duration int | ||||||
|  | 	Length   int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // values returns a url.Values representation of VideoNoteConfig. | ||||||
|  | func (config VideoNoteConfig) values() (url.Values, error) { | ||||||
|  | 	v, err := config.BaseChat.values() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return v, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	v.Add(config.name(), config.FileID) | ||||||
|  | 	if config.Duration != 0 { | ||||||
|  | 		v.Add("duration", strconv.Itoa(config.Duration)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Telegram API seems to have a bug, if no length is provided or it is 0, it will send an error response | ||||||
|  | 	if config.Length != 0 { | ||||||
|  | 		v.Add("length", strconv.Itoa(config.Length)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return v, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // params returns a map[string]string representation of VideoNoteConfig. | ||||||
|  | func (config VideoNoteConfig) params() (map[string]string, error) { | ||||||
|  | 	params, _ := config.BaseFile.params() | ||||||
|  |  | ||||||
|  | 	if config.Length != 0 { | ||||||
|  | 		params["length"] = strconv.Itoa(config.Length) | ||||||
|  | 	} | ||||||
|  | 	if config.Duration != 0 { | ||||||
|  | 		params["duration"] = strconv.Itoa(config.Duration) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return params, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // name returns the field name for the VideoNote. | ||||||
|  | func (config VideoNoteConfig) name() string { | ||||||
|  | 	return "video_note" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // method returns Telegram API method name for sending VideoNote. | ||||||
|  | func (config VideoNoteConfig) method() string { | ||||||
|  | 	return "sendVideoNote" | ||||||
|  | } | ||||||
|  |  | ||||||
| // VoiceConfig contains information about a SendVoice request. | // VoiceConfig contains information about a SendVoice request. | ||||||
| type VoiceConfig struct { | type VoiceConfig struct { | ||||||
| 	BaseFile | 	BaseFile | ||||||
| @@ -474,6 +537,9 @@ func (config VoiceConfig) values() (url.Values, error) { | |||||||
| 	if config.Duration != 0 { | 	if config.Duration != 0 { | ||||||
| 		v.Add("duration", strconv.Itoa(config.Duration)) | 		v.Add("duration", strconv.Itoa(config.Duration)) | ||||||
| 	} | 	} | ||||||
|  | 	if config.Caption != "" { | ||||||
|  | 		v.Add("caption", config.Caption) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return v, nil | 	return v, nil | ||||||
| } | } | ||||||
| @@ -485,6 +551,9 @@ func (config VoiceConfig) params() (map[string]string, error) { | |||||||
| 	if config.Duration != 0 { | 	if config.Duration != 0 { | ||||||
| 		params["duration"] = strconv.Itoa(config.Duration) | 		params["duration"] = strconv.Itoa(config.Duration) | ||||||
| 	} | 	} | ||||||
|  | 	if config.Caption != "" { | ||||||
|  | 		params["caption"] = config.Caption | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return params, nil | 	return params, nil | ||||||
| } | } | ||||||
| @@ -814,9 +883,39 @@ type CallbackConfig struct { | |||||||
| type ChatMemberConfig struct { | type ChatMemberConfig struct { | ||||||
| 	ChatID             int64 | 	ChatID             int64 | ||||||
| 	SuperGroupUsername string | 	SuperGroupUsername string | ||||||
|  | 	ChannelUsername    string | ||||||
| 	UserID             int | 	UserID             int | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // KickChatMemberConfig contains extra fields to kick user | ||||||
|  | type KickChatMemberConfig struct { | ||||||
|  | 	ChatMemberConfig | ||||||
|  | 	UntilDate int64 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RestrictChatMemberConfig contains fields to restrict members of chat | ||||||
|  | type RestrictChatMemberConfig struct { | ||||||
|  | 	ChatMemberConfig | ||||||
|  | 	UntilDate             int64 | ||||||
|  | 	CanSendMessages       *bool | ||||||
|  | 	CanSendMediaMessages  *bool | ||||||
|  | 	CanSendOtherMessages  *bool | ||||||
|  | 	CanAddWebPagePreviews *bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PromoteChatMemberConfig contains fields to promote members of chat | ||||||
|  | type PromoteChatMemberConfig struct { | ||||||
|  | 	ChatMemberConfig | ||||||
|  | 	CanChangeInfo      *bool | ||||||
|  | 	CanPostMessages    *bool | ||||||
|  | 	CanEditMessages    *bool | ||||||
|  | 	CanDeleteMessages  *bool | ||||||
|  | 	CanInviteUsers     *bool | ||||||
|  | 	CanRestrictMembers *bool | ||||||
|  | 	CanPinMessages     *bool | ||||||
|  | 	CanPromoteMembers  *bool | ||||||
|  | } | ||||||
|  |  | ||||||
| // ChatConfig contains information about getting information on a chat. | // ChatConfig contains information about getting information on a chat. | ||||||
| type ChatConfig struct { | type ChatConfig struct { | ||||||
| 	ChatID             int64 | 	ChatID             int64 | ||||||
| @@ -830,3 +929,147 @@ type ChatConfigWithUser struct { | |||||||
| 	SuperGroupUsername string | 	SuperGroupUsername string | ||||||
| 	UserID             int | 	UserID             int | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // InvoiceConfig contains information for sendInvoice request. | ||||||
|  | type InvoiceConfig struct { | ||||||
|  | 	BaseChat | ||||||
|  | 	Title               string          // required | ||||||
|  | 	Description         string          // required | ||||||
|  | 	Payload             string          // required | ||||||
|  | 	ProviderToken       string          // required | ||||||
|  | 	StartParameter      string          // required | ||||||
|  | 	Currency            string          // required | ||||||
|  | 	Prices              *[]LabeledPrice // required | ||||||
|  | 	PhotoURL            string | ||||||
|  | 	PhotoSize           int | ||||||
|  | 	PhotoWidth          int | ||||||
|  | 	PhotoHeight         int | ||||||
|  | 	NeedName            bool | ||||||
|  | 	NeedPhoneNumber     bool | ||||||
|  | 	NeedEmail           bool | ||||||
|  | 	NeedShippingAddress bool | ||||||
|  | 	IsFlexible          bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config InvoiceConfig) values() (url.Values, error) { | ||||||
|  | 	v, err := config.BaseChat.values() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return v, err | ||||||
|  | 	} | ||||||
|  | 	v.Add("title", config.Title) | ||||||
|  | 	v.Add("description", config.Description) | ||||||
|  | 	v.Add("payload", config.Payload) | ||||||
|  | 	v.Add("provider_token", config.ProviderToken) | ||||||
|  | 	v.Add("start_parameter", config.StartParameter) | ||||||
|  | 	v.Add("currency", config.Currency) | ||||||
|  | 	data, err := json.Marshal(config.Prices) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return v, err | ||||||
|  | 	} | ||||||
|  | 	v.Add("prices", string(data)) | ||||||
|  | 	if config.PhotoURL != "" { | ||||||
|  | 		v.Add("photo_url", config.PhotoURL) | ||||||
|  | 	} | ||||||
|  | 	if config.PhotoSize != 0 { | ||||||
|  | 		v.Add("photo_size", strconv.Itoa(config.PhotoSize)) | ||||||
|  | 	} | ||||||
|  | 	if config.PhotoWidth != 0 { | ||||||
|  | 		v.Add("photo_width", strconv.Itoa(config.PhotoWidth)) | ||||||
|  | 	} | ||||||
|  | 	if config.PhotoHeight != 0 { | ||||||
|  | 		v.Add("photo_height", strconv.Itoa(config.PhotoHeight)) | ||||||
|  | 	} | ||||||
|  | 	if config.NeedName != false { | ||||||
|  | 		v.Add("need_name", strconv.FormatBool(config.NeedName)) | ||||||
|  | 	} | ||||||
|  | 	if config.NeedPhoneNumber != false { | ||||||
|  | 		v.Add("need_phone_number", strconv.FormatBool(config.NeedPhoneNumber)) | ||||||
|  | 	} | ||||||
|  | 	if config.NeedEmail != false { | ||||||
|  | 		v.Add("need_email", strconv.FormatBool(config.NeedEmail)) | ||||||
|  | 	} | ||||||
|  | 	if config.NeedShippingAddress != false { | ||||||
|  | 		v.Add("need_shipping_address", strconv.FormatBool(config.NeedShippingAddress)) | ||||||
|  | 	} | ||||||
|  | 	if config.IsFlexible != false { | ||||||
|  | 		v.Add("is_flexible", strconv.FormatBool(config.IsFlexible)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return v, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config InvoiceConfig) method() string { | ||||||
|  | 	return "sendInvoice" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ShippingConfig contains information for answerShippingQuery request. | ||||||
|  | type ShippingConfig struct { | ||||||
|  | 	ShippingQueryID string // required | ||||||
|  | 	OK              bool   // required | ||||||
|  | 	ShippingOptions *[]ShippingOption | ||||||
|  | 	ErrorMessage    string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PreCheckoutConfig conatins information for answerPreCheckoutQuery request. | ||||||
|  | type PreCheckoutConfig struct { | ||||||
|  | 	PreCheckoutQueryID string // required | ||||||
|  | 	OK                 bool   // required | ||||||
|  | 	ErrorMessage       string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeleteMessageConfig contains information of a message in a chat to delete. | ||||||
|  | type DeleteMessageConfig struct { | ||||||
|  | 	ChatID    int64 | ||||||
|  | 	MessageID int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config DeleteMessageConfig) method() string { | ||||||
|  | 	return "deleteMessage" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config DeleteMessageConfig) values() (url.Values, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  | 	v.Add("message_id", strconv.Itoa(config.MessageID)) | ||||||
|  |  | ||||||
|  | 	return v, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PinChatMessageConfig contains information of a message in a chat to pin. | ||||||
|  | type PinChatMessageConfig struct { | ||||||
|  | 	ChatID int64 | ||||||
|  | 	MessageID int | ||||||
|  | 	DisableNotification bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config PinChatMessageConfig) method() string { | ||||||
|  | 	return "pinChatMessage" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config PinChatMessageConfig) values() (url.Values, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  | 	v.Add("message_id", strconv.Itoa(config.MessageID)) | ||||||
|  | 	v.Add("disable_notification", strconv.FormatBool(config.DisableNotification)) | ||||||
|  |  | ||||||
|  | 	return v, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UnpinChatMessageConfig contains information of chat to unpin. | ||||||
|  | type UnpinChatMessageConfig struct { | ||||||
|  | 	ChatID int64 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config UnpinChatMessageConfig) method() string { | ||||||
|  | 	return "unpinChatMessage" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (config UnpinChatMessageConfig) values() (url.Values, error) { | ||||||
|  | 	v := url.Values{} | ||||||
|  |  | ||||||
|  | 	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) | ||||||
|  |  | ||||||
|  | 	return v, nil | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -194,6 +194,37 @@ func NewVideoShare(chatID int64, fileID string) VideoConfig { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // NewVideoNoteUpload creates a new video note uploader. | ||||||
|  | // | ||||||
|  | // chatID is where to send it, file is a string path to the file, | ||||||
|  | // FileReader, or FileBytes. | ||||||
|  | func NewVideoNoteUpload(chatID int64, length int, file interface{}) VideoNoteConfig { | ||||||
|  | 	return VideoNoteConfig{ | ||||||
|  | 		BaseFile: BaseFile{ | ||||||
|  | 			BaseChat:    BaseChat{ChatID: chatID}, | ||||||
|  | 			File:        file, | ||||||
|  | 			UseExisting: false, | ||||||
|  | 		}, | ||||||
|  | 		Length: length, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewVideoNoteShare shares an existing video. | ||||||
|  | // You may use this to reshare an existing video without reuploading it. | ||||||
|  | // | ||||||
|  | // chatID is where to send it, fileID is the ID of the video | ||||||
|  | // already uploaded. | ||||||
|  | func NewVideoNoteShare(chatID int64, length int, fileID string) VideoNoteConfig { | ||||||
|  | 	return VideoNoteConfig{ | ||||||
|  | 		BaseFile: BaseFile{ | ||||||
|  | 			BaseChat:    BaseChat{ChatID: chatID}, | ||||||
|  | 			FileID:      fileID, | ||||||
|  | 			UseExisting: true, | ||||||
|  | 		}, | ||||||
|  | 		Length: length, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // NewVoiceUpload creates a new voice uploader. | // NewVoiceUpload creates a new voice uploader. | ||||||
| // | // | ||||||
| // chatID is where to send it, file is a string path to the file, | // chatID is where to send it, file is a string path to the file, | ||||||
| @@ -609,3 +640,16 @@ func NewCallbackWithAlert(id, text string) CallbackConfig { | |||||||
| 		ShowAlert:       true, | 		ShowAlert:       true, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // NewInvoice created a new Invoice request to the user. | ||||||
|  | func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices *[]LabeledPrice) InvoiceConfig { | ||||||
|  | 	return InvoiceConfig{ | ||||||
|  | 		BaseChat:       BaseChat{ChatID: chatID}, | ||||||
|  | 		Title:          title, | ||||||
|  | 		Description:    description, | ||||||
|  | 		Payload:        payload, | ||||||
|  | 		ProviderToken:  providerToken, | ||||||
|  | 		StartParameter: startParameter, | ||||||
|  | 		Currency:       currency, | ||||||
|  | 		Prices:         prices} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										205
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										205
									
								
								vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -35,6 +35,8 @@ type Update struct { | |||||||
| 	InlineQuery        *InlineQuery        `json:"inline_query"` | 	InlineQuery        *InlineQuery        `json:"inline_query"` | ||||||
| 	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"` | 	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"` | ||||||
| 	CallbackQuery      *CallbackQuery      `json:"callback_query"` | 	CallbackQuery      *CallbackQuery      `json:"callback_query"` | ||||||
|  | 	ShippingQuery      *ShippingQuery      `json:"shipping_query"` | ||||||
|  | 	PreCheckoutQuery   *PreCheckoutQuery   `json:"pre_checkout_query"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // UpdatesChannel is the channel for getting updates. | // UpdatesChannel is the channel for getting updates. | ||||||
| @@ -49,10 +51,11 @@ func (ch UpdatesChannel) Clear() { | |||||||
|  |  | ||||||
| // User is a user on Telegram. | // User is a user on Telegram. | ||||||
| type User struct { | type User struct { | ||||||
| 	ID        int    `json:"id"` | 	ID           int    `json:"id"` | ||||||
| 	FirstName string `json:"first_name"` | 	FirstName    string `json:"first_name"` | ||||||
| 	LastName  string `json:"last_name"` // optional | 	LastName     string `json:"last_name"`     // optional | ||||||
| 	UserName  string `json:"username"`  // optional | 	UserName     string `json:"username"`      // optional | ||||||
|  | 	LanguageCode string `json:"language_code"` // optional | ||||||
| } | } | ||||||
|  |  | ||||||
| // String displays a simple text version of a user. | // String displays a simple text version of a user. | ||||||
| @@ -78,15 +81,24 @@ type GroupChat struct { | |||||||
| 	Title string `json:"title"` | 	Title string `json:"title"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ChatPhoto represents a chat photo. | ||||||
|  | type ChatPhoto struct { | ||||||
|  | 	SmallFileID string `json:"small_file_id"` | ||||||
|  | 	BigFileID   string `json:"big_file_id"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // Chat contains information about the place a message was sent. | // Chat contains information about the place a message was sent. | ||||||
| type Chat struct { | type Chat struct { | ||||||
| 	ID                  int64  `json:"id"` | 	ID                  int64      `json:"id"` | ||||||
| 	Type                string `json:"type"` | 	Type                string     `json:"type"` | ||||||
| 	Title               string `json:"title"`                          // optional | 	Title               string     `json:"title"`                          // optional | ||||||
| 	UserName            string `json:"username"`                       // optional | 	UserName            string     `json:"username"`                       // optional | ||||||
| 	FirstName           string `json:"first_name"`                     // optional | 	FirstName           string     `json:"first_name"`                     // optional | ||||||
| 	LastName            string `json:"last_name"`                      // optional | 	LastName            string     `json:"last_name"`                      // optional | ||||||
| 	AllMembersAreAdmins bool   `json:"all_members_are_administrators"` // optional | 	AllMembersAreAdmins bool       `json:"all_members_are_administrators"` // optional | ||||||
|  | 	Photo               *ChatPhoto `json:"photo"` | ||||||
|  | 	Description         string     `json:"description,omitempty"` // optional | ||||||
|  | 	InviteLink          string     `json:"invite_link,omitempty"` // optional | ||||||
| } | } | ||||||
|  |  | ||||||
| // IsPrivate returns if the Chat is a private conversation. | // IsPrivate returns if the Chat is a private conversation. | ||||||
| @@ -117,40 +129,43 @@ func (c Chat) ChatConfig() ChatConfig { | |||||||
| // Message is returned by almost every request, and contains data about | // Message is returned by almost every request, and contains data about | ||||||
| // almost anything. | // almost anything. | ||||||
| type Message struct { | type Message struct { | ||||||
| 	MessageID             int              `json:"message_id"` | 	MessageID             int                `json:"message_id"` | ||||||
| 	From                  *User            `json:"from"` // optional | 	From                  *User              `json:"from"` // optional | ||||||
| 	Date                  int              `json:"date"` | 	Date                  int                `json:"date"` | ||||||
| 	Chat                  *Chat            `json:"chat"` | 	Chat                  *Chat              `json:"chat"` | ||||||
| 	ForwardFrom           *User            `json:"forward_from"`            // optional | 	ForwardFrom           *User              `json:"forward_from"`            // optional | ||||||
| 	ForwardFromChat       *Chat            `json:"forward_from_chat"`       // optional | 	ForwardFromChat       *Chat              `json:"forward_from_chat"`       // optional | ||||||
| 	ForwardFromMessageID  int              `json:"forward_from_message_id"` // optional | 	ForwardFromMessageID  int                `json:"forward_from_message_id"` // optional | ||||||
| 	ForwardDate           int              `json:"forward_date"`            // optional | 	ForwardDate           int                `json:"forward_date"`            // optional | ||||||
| 	ReplyToMessage        *Message         `json:"reply_to_message"`        // optional | 	ReplyToMessage        *Message           `json:"reply_to_message"`        // optional | ||||||
| 	EditDate              int              `json:"edit_date"`               // optional | 	EditDate              int                `json:"edit_date"`               // optional | ||||||
| 	Text                  string           `json:"text"`                    // optional | 	Text                  string             `json:"text"`                    // optional | ||||||
| 	Entities              *[]MessageEntity `json:"entities"`                // optional | 	Entities              *[]MessageEntity   `json:"entities"`                // optional | ||||||
| 	Audio                 *Audio           `json:"audio"`                   // optional | 	Audio                 *Audio             `json:"audio"`                   // optional | ||||||
| 	Document              *Document        `json:"document"`                // optional | 	Document              *Document          `json:"document"`                // optional | ||||||
| 	Game                  *Game            `json:"game"`                    // optional | 	Game                  *Game              `json:"game"`                    // optional | ||||||
| 	Photo                 *[]PhotoSize     `json:"photo"`                   // optional | 	Photo                 *[]PhotoSize       `json:"photo"`                   // optional | ||||||
| 	Sticker               *Sticker         `json:"sticker"`                 // optional | 	Sticker               *Sticker           `json:"sticker"`                 // optional | ||||||
| 	Video                 *Video           `json:"video"`                   // optional | 	Video                 *Video             `json:"video"`                   // optional | ||||||
| 	Voice                 *Voice           `json:"voice"`                   // optional | 	VideoNote             *VideoNote         `json:"video_note"`              // optional | ||||||
| 	Caption               string           `json:"caption"`                 // optional | 	Voice                 *Voice             `json:"voice"`                   // optional | ||||||
| 	Contact               *Contact         `json:"contact"`                 // optional | 	Caption               string             `json:"caption"`                 // optional | ||||||
| 	Location              *Location        `json:"location"`                // optional | 	Contact               *Contact           `json:"contact"`                 // optional | ||||||
| 	Venue                 *Venue           `json:"venue"`                   // optional | 	Location              *Location          `json:"location"`                // optional | ||||||
| 	NewChatMember         *User            `json:"new_chat_member"`         // optional | 	Venue                 *Venue             `json:"venue"`                   // optional | ||||||
| 	LeftChatMember        *User            `json:"left_chat_member"`        // optional | 	NewChatMembers        *[]User            `json:"new_chat_members"`        // optional | ||||||
| 	NewChatTitle          string           `json:"new_chat_title"`          // optional | 	LeftChatMember        *User              `json:"left_chat_member"`        // optional | ||||||
| 	NewChatPhoto          *[]PhotoSize     `json:"new_chat_photo"`          // optional | 	NewChatTitle          string             `json:"new_chat_title"`          // optional | ||||||
| 	DeleteChatPhoto       bool             `json:"delete_chat_photo"`       // optional | 	NewChatPhoto          *[]PhotoSize       `json:"new_chat_photo"`          // optional | ||||||
| 	GroupChatCreated      bool             `json:"group_chat_created"`      // optional | 	DeleteChatPhoto       bool               `json:"delete_chat_photo"`       // optional | ||||||
| 	SuperGroupChatCreated bool             `json:"supergroup_chat_created"` // optional | 	GroupChatCreated      bool               `json:"group_chat_created"`      // optional | ||||||
| 	ChannelChatCreated    bool             `json:"channel_chat_created"`    // optional | 	SuperGroupChatCreated bool               `json:"supergroup_chat_created"` // optional | ||||||
| 	MigrateToChatID       int64            `json:"migrate_to_chat_id"`      // optional | 	ChannelChatCreated    bool               `json:"channel_chat_created"`    // optional | ||||||
| 	MigrateFromChatID     int64            `json:"migrate_from_chat_id"`    // optional | 	MigrateToChatID       int64              `json:"migrate_to_chat_id"`      // optional | ||||||
| 	PinnedMessage         *Message         `json:"pinned_message"`          // optional | 	MigrateFromChatID     int64              `json:"migrate_from_chat_id"`    // optional | ||||||
|  | 	PinnedMessage         *Message           `json:"pinned_message"`          // optional | ||||||
|  | 	Invoice               *Invoice           `json:"invoice"`                 // optional | ||||||
|  | 	SuccessfulPayment     *SuccessfulPayment `json:"successful_payment"`      // optional | ||||||
| } | } | ||||||
|  |  | ||||||
| // Time converts the message timestamp into a Time. | // Time converts the message timestamp into a Time. | ||||||
| @@ -263,6 +278,15 @@ type Video struct { | |||||||
| 	FileSize  int        `json:"file_size"` // optional | 	FileSize  int        `json:"file_size"` // optional | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // VideoNote contains information about a video. | ||||||
|  | type VideoNote struct { | ||||||
|  | 	FileID    string     `json:"file_id"` | ||||||
|  | 	Length    int        `json:"length"` | ||||||
|  | 	Duration  int        `json:"duration"` | ||||||
|  | 	Thumbnail *PhotoSize `json:"thumb"`     // optional | ||||||
|  | 	FileSize  int        `json:"file_size"` // optional | ||||||
|  | } | ||||||
|  |  | ||||||
| // Voice contains information about a voice. | // Voice contains information about a voice. | ||||||
| type Voice struct { | type Voice struct { | ||||||
| 	FileID   string `json:"file_id"` | 	FileID   string `json:"file_id"` | ||||||
| @@ -361,6 +385,7 @@ type InlineKeyboardButton struct { | |||||||
| 	SwitchInlineQuery            *string       `json:"switch_inline_query,omitempty"`              // optional | 	SwitchInlineQuery            *string       `json:"switch_inline_query,omitempty"`              // optional | ||||||
| 	SwitchInlineQueryCurrentChat *string       `json:"switch_inline_query_current_chat,omitempty"` // optional | 	SwitchInlineQueryCurrentChat *string       `json:"switch_inline_query_current_chat,omitempty"` // optional | ||||||
| 	CallbackGame                 *CallbackGame `json:"callback_game,omitempty"`                    // optional | 	CallbackGame                 *CallbackGame `json:"callback_game,omitempty"`                    // optional | ||||||
|  | 	Pay                          bool          `json:"pay,omitempty"`			       // optional | ||||||
| } | } | ||||||
|  |  | ||||||
| // CallbackQuery is data sent when a keyboard button with callback data | // CallbackQuery is data sent when a keyboard button with callback data | ||||||
| @@ -384,8 +409,22 @@ type ForceReply struct { | |||||||
|  |  | ||||||
| // ChatMember is information about a member in a chat. | // ChatMember is information about a member in a chat. | ||||||
| type ChatMember struct { | type ChatMember struct { | ||||||
| 	User   *User  `json:"user"` | 	User                  *User  `json:"user"` | ||||||
| 	Status string `json:"status"` | 	Status                string `json:"status"` | ||||||
|  | 	UntilDate             int64  `json:"until_date,omitempty"`                // optional | ||||||
|  | 	CanBeEdited           bool   `json:"can_be_edited,omitempty"`             // optional | ||||||
|  | 	CanChangeInfo         bool   `json:"can_change_info,omitempty"`           // optional | ||||||
|  | 	CanPostMessages       bool   `json:"can_post_messages,omitempty"`         // optional | ||||||
|  | 	CanEditMessages       bool   `json:"can_edit_messages,omitempty"`         // optional | ||||||
|  | 	CanDeleteMessages     bool   `json:"can_delete_messages,omitempty"`       // optional | ||||||
|  | 	CanInviteUsers        bool   `json:"can_invite_users,omitempty"`          // optional | ||||||
|  | 	CanRestrictMembers    bool   `json:"can_restrict_members,omitempty"`      // optional | ||||||
|  | 	CanPinMessages        bool   `json:"can_pin_messages,omitempty"`          // optional | ||||||
|  | 	CanPromoteMembers     bool   `json:"can_promote_members,omitempty"`       // optional | ||||||
|  | 	CanSendMessages       bool   `json:"can_send_messages,omitempty"`         // optional | ||||||
|  | 	CanSendMediaMessages  bool   `json:"can_send_media_messages,omitempty"`   // optional | ||||||
|  | 	CanSendOtherMessages  bool   `json:"can_send_other_messages,omitempty"`   // optional | ||||||
|  | 	CanAddWebPagePreviews bool   `json:"can_add_web_page_previews,omitempty"` // optional | ||||||
| } | } | ||||||
|  |  | ||||||
| // IsCreator returns if the ChatMember was the creator of the chat. | // IsCreator returns if the ChatMember was the creator of the chat. | ||||||
| @@ -493,6 +532,7 @@ type InlineQueryResultGIF struct { | |||||||
| 	URL                 string                `json:"gif_url"` // required | 	URL                 string                `json:"gif_url"` // required | ||||||
| 	Width               int                   `json:"gif_width"` | 	Width               int                   `json:"gif_width"` | ||||||
| 	Height              int                   `json:"gif_height"` | 	Height              int                   `json:"gif_height"` | ||||||
|  | 	Duration            int                   `json:"gif_duration"` | ||||||
| 	ThumbURL            string                `json:"thumb_url"` | 	ThumbURL            string                `json:"thumb_url"` | ||||||
| 	Title               string                `json:"title"` | 	Title               string                `json:"title"` | ||||||
| 	Caption             string                `json:"caption"` | 	Caption             string                `json:"caption"` | ||||||
| @@ -507,6 +547,7 @@ type InlineQueryResultMPEG4GIF struct { | |||||||
| 	URL                 string                `json:"mpeg4_url"` // required | 	URL                 string                `json:"mpeg4_url"` // required | ||||||
| 	Width               int                   `json:"mpeg4_width"` | 	Width               int                   `json:"mpeg4_width"` | ||||||
| 	Height              int                   `json:"mpeg4_height"` | 	Height              int                   `json:"mpeg4_height"` | ||||||
|  | 	Duration            int                   `json:"mpeg4_duration"` | ||||||
| 	ThumbURL            string                `json:"thumb_url"` | 	ThumbURL            string                `json:"thumb_url"` | ||||||
| 	Title               string                `json:"title"` | 	Title               string                `json:"title"` | ||||||
| 	Caption             string                `json:"caption"` | 	Caption             string                `json:"caption"` | ||||||
| @@ -635,3 +676,73 @@ type InputContactMessageContent struct { | |||||||
| 	FirstName   string `json:"first_name"` | 	FirstName   string `json:"first_name"` | ||||||
| 	LastName    string `json:"last_name"` | 	LastName    string `json:"last_name"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Invoice contains basic information about an invoice. | ||||||
|  | type Invoice struct { | ||||||
|  | 	Title          string `json:"title"` | ||||||
|  | 	Description    string `json:"description"` | ||||||
|  | 	StartParameter string `json:"start_parameter"` | ||||||
|  | 	Currency       string `json:"currency"` | ||||||
|  | 	TotalAmount    int    `json:"total_amount"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // LabeledPrice represents a portion of the price for goods or services. | ||||||
|  | type LabeledPrice struct { | ||||||
|  | 	Label  string `json:"label"` | ||||||
|  | 	Amount int    `json:"amount"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ShippingAddress represents a shipping address. | ||||||
|  | type ShippingAddress struct { | ||||||
|  | 	CountryCode string `json:"country_code"` | ||||||
|  | 	State       string `json:"state"` | ||||||
|  | 	City        string `json:"city"` | ||||||
|  | 	StreetLine1 string `json:"street_line1"` | ||||||
|  | 	StreetLine2 string `json:"street_line2"` | ||||||
|  | 	PostCode    string `json:"post_code"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // OrderInfo represents information about an order. | ||||||
|  | type OrderInfo struct { | ||||||
|  | 	Name            string           `json:"name,omitempty"` | ||||||
|  | 	PhoneNumber     string           `json:"phone_number,omitempty"` | ||||||
|  | 	Email           string           `json:"email,omitempty"` | ||||||
|  | 	ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ShippingOption represents one shipping option. | ||||||
|  | type ShippingOption struct { | ||||||
|  | 	ID     string          `json:"id"` | ||||||
|  | 	Title  string          `json:"title"` | ||||||
|  | 	Prices *[]LabeledPrice `json:"prices"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SuccessfulPayment contains basic information about a successful payment. | ||||||
|  | type SuccessfulPayment struct { | ||||||
|  | 	Currency                string     `json:"currency"` | ||||||
|  | 	TotalAmount             int        `json:"total_amount"` | ||||||
|  | 	InvoicePayload          string     `json:"invoice_payload"` | ||||||
|  | 	ShippingOptionID        string     `json:"shipping_option_id,omitempty"` | ||||||
|  | 	OrderInfo               *OrderInfo `json:"order_info,omitempty"` | ||||||
|  | 	TelegramPaymentChargeID string     `json:"telegram_payment_charge_id"` | ||||||
|  | 	ProviderPaymentChargeID string     `json:"provider_payment_charge_id"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ShippingQuery contains information about an incoming shipping query. | ||||||
|  | type ShippingQuery struct { | ||||||
|  | 	ID              string           `json:"id"` | ||||||
|  | 	From            *User            `json:"from"` | ||||||
|  | 	InvoicePayload  string           `json:"invoice_payload"` | ||||||
|  | 	ShippingAddress *ShippingAddress `json:"shipping_address"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PreCheckoutQuery contains information about an incoming pre-checkout query. | ||||||
|  | type PreCheckoutQuery struct { | ||||||
|  | 	ID               string     `json:"id"` | ||||||
|  | 	From             *User      `json:"from"` | ||||||
|  | 	Currency         string     `json:"currency"` | ||||||
|  | 	TotalAmount      int        `json:"total_amount"` | ||||||
|  | 	InvoicePayload   string     `json:"invoice_payload"` | ||||||
|  | 	ShippingOptionID string     `json:"shipping_option_id,omitempty"` | ||||||
|  | 	OrderInfo        *OrderInfo `json:"order_info,omitempty"` | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								vendor/github.com/mattermost/platform/einterfaces/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/mattermost/platform/einterfaces/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,32 +1,32 @@ | |||||||
| Mattermost Licensing | Mattermost Licensing | ||||||
|  |  | ||||||
| SOFTWARE LICENSING  | SOFTWARE LICENSING | ||||||
|  |  | ||||||
| You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE  | You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE | ||||||
|  |  | ||||||
| -	See MIT-COMPILED-LICENSE.md included in compiled versions for details | -	See MIT-COMPILED-LICENSE.md included in compiled versions for details | ||||||
|  |  | ||||||
| You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways: | You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways: | ||||||
|  |  | ||||||
| 1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or  | 1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or | ||||||
| 2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com  | 2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com | ||||||
|  |  | ||||||
| You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/,  | You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/, | ||||||
| webapp/client, webapp/fonts, webapp/i18n, webapp/images and all subdirectories thereof) under the Apache License v2.0. | webapp/client, webapp/fonts, webapp/i18n, webapp/images and all subdirectories thereof) under the Apache License v2.0. | ||||||
|  |  | ||||||
| We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not  | We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not | ||||||
| link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and | link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and | ||||||
| (b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of  | (b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of | ||||||
| a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license. | a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license. | ||||||
|  |  | ||||||
| MATTERMOST TRADEMARK GUIDELINES | MATTERMOST TRADEMARK GUIDELINES | ||||||
|  |  | ||||||
| Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark  | Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark | ||||||
| Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions  | Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions | ||||||
| you have about using these trademarks, please email trademark@mattermost.com  | you have about using these trademarks, please email trademark@mattermost.com | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ||||||
|                                 |  | ||||||
|                                Apache License |                                Apache License | ||||||
|                            Version 2.0, January 2004 |                            Version 2.0, January 2004 | ||||||
|                         http://www.apache.org/licenses/ |                         http://www.apache.org/licenses/ | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								vendor/github.com/mattermost/platform/einterfaces/account_migration.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattermost/platform/einterfaces/account_migration.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
| @@ -6,7 +6,7 @@ package einterfaces | |||||||
| import "github.com/mattermost/platform/model" | import "github.com/mattermost/platform/model" | ||||||
|  |  | ||||||
| type AccountMigrationInterface interface { | type AccountMigrationInterface interface { | ||||||
| 	MigrateToLdap(fromAuthService string, forignUserFieldNameToMatch string) *model.AppError | 	MigrateToLdap(fromAuthService string, forignUserFieldNameToMatch string, force bool) *model.AppError | ||||||
| } | } | ||||||
|  |  | ||||||
| var theAccountMigrationInterface AccountMigrationInterface | var theAccountMigrationInterface AccountMigrationInterface | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/brand.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/brand.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								vendor/github.com/mattermost/platform/einterfaces/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/mattermost/platform/einterfaces/cluster.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
| @@ -7,26 +7,19 @@ import ( | |||||||
| 	"github.com/mattermost/platform/model" | 	"github.com/mattermost/platform/model" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type ClusterMessageHandler func(msg *model.ClusterMessage) | ||||||
|  |  | ||||||
| type ClusterInterface interface { | type ClusterInterface interface { | ||||||
| 	StartInterNodeCommunication() | 	StartInterNodeCommunication() | ||||||
| 	StopInterNodeCommunication() | 	StopInterNodeCommunication() | ||||||
| 	GetClusterInfos() []*model.ClusterInfo | 	RegisterClusterMessageHandler(event string, crm ClusterMessageHandler) | ||||||
| 	GetClusterStats() ([]*model.ClusterStats, *model.AppError) |  | ||||||
| 	ClearSessionCacheForUser(userId string) |  | ||||||
| 	InvalidateCacheForUser(userId string) |  | ||||||
| 	InvalidateCacheForChannel(channelId string) |  | ||||||
| 	InvalidateCacheForChannelByName(teamId, name string) |  | ||||||
| 	InvalidateCacheForChannelMembers(channelId string) |  | ||||||
| 	InvalidateCacheForChannelMembersNotifyProps(channelId string) |  | ||||||
| 	InvalidateCacheForChannelPosts(channelId string) |  | ||||||
| 	InvalidateCacheForWebhook(webhookId string) |  | ||||||
| 	InvalidateCacheForReactions(postId string) |  | ||||||
| 	Publish(event *model.WebSocketEvent) |  | ||||||
| 	UpdateStatus(status *model.Status) |  | ||||||
| 	GetLogs() ([]string, *model.AppError) |  | ||||||
| 	GetClusterId() string | 	GetClusterId() string | ||||||
|  | 	GetClusterInfos() []*model.ClusterInfo | ||||||
|  | 	SendClusterMessage(cluster *model.ClusterMessage) | ||||||
|  | 	NotifyMsg(buf []byte) | ||||||
|  | 	GetClusterStats() ([]*model.ClusterStats, *model.AppError) | ||||||
|  | 	GetLogs(page, perPage int) ([]string, *model.AppError) | ||||||
| 	ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError | 	ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError | ||||||
| 	InvalidateAllCaches() *model.AppError |  | ||||||
| } | } | ||||||
|  |  | ||||||
| var theClusterInterface ClusterInterface | var theClusterInterface ClusterInterface | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/compliance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/compliance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								vendor/github.com/mattermost/platform/einterfaces/elasticsearch.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/mattermost/platform/einterfaces/elasticsearch.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package einterfaces | ||||||
|  |  | ||||||
|  | import "github.com/mattermost/platform/model" | ||||||
|  |  | ||||||
|  | type ElasticsearchInterface interface { | ||||||
|  | 	Start() *model.AppError | ||||||
|  | 	IndexPost(post *model.Post, teamId string) *model.AppError | ||||||
|  | 	SearchPosts(channels *model.ChannelList, searchParams []*model.SearchParams) ([]string, *model.AppError) | ||||||
|  | 	DeletePost(post *model.Post) *model.AppError | ||||||
|  | 	TestConfig(cfg *model.Config) *model.AppError | ||||||
|  | 	PurgeIndexes() *model.AppError | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var theElasticsearchInterface ElasticsearchInterface | ||||||
|  |  | ||||||
|  | func RegisterElasticsearchInterface(newInterface ElasticsearchInterface) { | ||||||
|  | 	theElasticsearchInterface = newInterface | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetElasticsearchInterface() ElasticsearchInterface { | ||||||
|  | 	return theElasticsearchInterface | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								vendor/github.com/mattermost/platform/einterfaces/jobs/data_retention.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/mattermost/platform/einterfaces/jobs/data_retention.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package jobs | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/mattermost/platform/model" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type DataRetentionInterface interface { | ||||||
|  | 	MakeWorker() model.Worker | ||||||
|  | 	MakeScheduler() model.Scheduler | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var theDataRetentionInterface DataRetentionInterface | ||||||
|  |  | ||||||
|  | func RegisterDataRetentionInterface(newInterface DataRetentionInterface) { | ||||||
|  | 	theDataRetentionInterface = newInterface | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetDataRetentionInterface() DataRetentionInterface { | ||||||
|  | 	return theDataRetentionInterface | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								vendor/github.com/mattermost/platform/einterfaces/jobs/elasticsearch.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/mattermost/platform/einterfaces/jobs/elasticsearch.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package jobs | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/mattermost/platform/model" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type ElasticsearchIndexerInterface interface { | ||||||
|  | 	MakeWorker() model.Worker | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var theElasticsearchIndexerInterface ElasticsearchIndexerInterface | ||||||
|  |  | ||||||
|  | func RegisterElasticsearchIndexerInterface(newInterface ElasticsearchIndexerInterface) { | ||||||
|  | 	theElasticsearchIndexerInterface = newInterface | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetElasticsearchIndexerInterface() ElasticsearchIndexerInterface { | ||||||
|  | 	return theElasticsearchIndexerInterface | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								vendor/github.com/mattermost/platform/einterfaces/metrics.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/mattermost/platform/einterfaces/metrics.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
| @@ -33,6 +33,7 @@ type MetricsInterface interface { | |||||||
| 	IncrementMemCacheHitCounterSession() | 	IncrementMemCacheHitCounterSession() | ||||||
|  |  | ||||||
| 	IncrementWebsocketEvent(eventType string) | 	IncrementWebsocketEvent(eventType string) | ||||||
|  | 	IncrementWebSocketBroadcast(eventType string) | ||||||
|  |  | ||||||
| 	AddMemCacheHitCounter(cacheName string, amount float64) | 	AddMemCacheHitCounter(cacheName string, amount float64) | ||||||
| 	AddMemCacheMissCounter(cacheName string, amount float64) | 	AddMemCacheMissCounter(cacheName string, amount float64) | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/mfa.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/mfa.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/oauthproviders.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/einterfaces/oauthproviders.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								vendor/github.com/mattermost/platform/einterfaces/saml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattermost/platform/einterfaces/saml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package einterfaces | package einterfaces | ||||||
| @@ -10,7 +10,7 @@ import ( | |||||||
| type SamlInterface interface { | type SamlInterface interface { | ||||||
| 	ConfigureSP() *model.AppError | 	ConfigureSP() *model.AppError | ||||||
| 	BuildRequest(relayState string) (*model.SamlAuthRequest, *model.AppError) | 	BuildRequest(relayState string) (*model.SamlAuthRequest, *model.AppError) | ||||||
| 	DoLogin(encodedXML string, relayState map[string]string, siteURL string) (*model.User, *model.AppError) | 	DoLogin(encodedXML string, relayState map[string]string) (*model.User, *model.AppError) | ||||||
| 	GetMetadata() (string, *model.AppError) | 	GetMetadata() (string, *model.AppError) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								vendor/github.com/mattermost/platform/model/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/mattermost/platform/model/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,32 +1,32 @@ | |||||||
| Mattermost Licensing | Mattermost Licensing | ||||||
|  |  | ||||||
| SOFTWARE LICENSING  | SOFTWARE LICENSING | ||||||
|  |  | ||||||
| You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE  | You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE | ||||||
|  |  | ||||||
| -	See MIT-COMPILED-LICENSE.md included in compiled versions for details | -	See MIT-COMPILED-LICENSE.md included in compiled versions for details | ||||||
|  |  | ||||||
| You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways: | You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways: | ||||||
|  |  | ||||||
| 1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or  | 1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or | ||||||
| 2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com  | 2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com | ||||||
|  |  | ||||||
| You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/,  | You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/, | ||||||
| webapp/client, webapp/fonts, webapp/i18n, webapp/images and all subdirectories thereof) under the Apache License v2.0. | webapp/client, webapp/fonts, webapp/i18n, webapp/images and all subdirectories thereof) under the Apache License v2.0. | ||||||
|  |  | ||||||
| We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not  | We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not | ||||||
| link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and | link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and | ||||||
| (b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of  | (b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of | ||||||
| a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license. | a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license. | ||||||
|  |  | ||||||
| MATTERMOST TRADEMARK GUIDELINES | MATTERMOST TRADEMARK GUIDELINES | ||||||
|  |  | ||||||
| Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark  | Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark | ||||||
| Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions  | Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions | ||||||
| you have about using these trademarks, please email trademark@mattermost.com  | you have about using these trademarks, please email trademark@mattermost.com | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ||||||
|                                 |  | ||||||
|                                Apache License |                                Apache License | ||||||
|                            Version 2.0, January 2004 |                            Version 2.0, January 2004 | ||||||
|                         http://www.apache.org/licenses/ |                         http://www.apache.org/licenses/ | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								vendor/github.com/mattermost/platform/model/access.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/mattermost/platform/model/access.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -21,6 +21,7 @@ type AccessData struct { | |||||||
| 	RefreshToken string `json:"refresh_token"` | 	RefreshToken string `json:"refresh_token"` | ||||||
| 	RedirectUri  string `json:"redirect_uri"` | 	RedirectUri  string `json:"redirect_uri"` | ||||||
| 	ExpiresAt    int64  `json:"expires_at"` | 	ExpiresAt    int64  `json:"expires_at"` | ||||||
|  | 	Scope        string `json:"scope"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type AccessResponse struct { | type AccessResponse struct { | ||||||
| @@ -51,7 +52,7 @@ func (ad *AccessData) IsValid() *AppError { | |||||||
| 		return NewLocAppError("AccessData.IsValid", "model.access.is_valid.refresh_token.app_error", nil, "") | 		return NewLocAppError("AccessData.IsValid", "model.access.is_valid.refresh_token.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(ad.RedirectUri) > 256 { | 	if len(ad.RedirectUri) == 0 || len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) { | ||||||
| 		return NewLocAppError("AccessData.IsValid", "model.access.is_valid.redirect_uri.app_error", nil, "") | 		return NewLocAppError("AccessData.IsValid", "model.access.is_valid.redirect_uri.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/analytics_row.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/analytics_row.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/audit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/audit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/audits.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/audits.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										116
									
								
								vendor/github.com/mattermost/platform/model/authorization.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										116
									
								
								vendor/github.com/mattermost/platform/model/authorization.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -39,6 +39,7 @@ var PERMISSION_DELETE_PUBLIC_CHANNEL *Permission | |||||||
| var PERMISSION_DELETE_PRIVATE_CHANNEL *Permission | var PERMISSION_DELETE_PRIVATE_CHANNEL *Permission | ||||||
| var PERMISSION_EDIT_OTHER_USERS *Permission | var PERMISSION_EDIT_OTHER_USERS *Permission | ||||||
| var PERMISSION_READ_CHANNEL *Permission | var PERMISSION_READ_CHANNEL *Permission | ||||||
|  | var PERMISSION_READ_PUBLIC_CHANNEL *Permission | ||||||
| var PERMISSION_PERMANENT_DELETE_USER *Permission | var PERMISSION_PERMANENT_DELETE_USER *Permission | ||||||
| var PERMISSION_UPLOAD_FILE *Permission | var PERMISSION_UPLOAD_FILE *Permission | ||||||
| var PERMISSION_GET_PUBLIC_LINK *Permission | var PERMISSION_GET_PUBLIC_LINK *Permission | ||||||
| @@ -47,6 +48,7 @@ var PERMISSION_MANAGE_OTHERS_WEBHOOKS *Permission | |||||||
| var PERMISSION_MANAGE_OAUTH *Permission | var PERMISSION_MANAGE_OAUTH *Permission | ||||||
| var PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH *Permission | var PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH *Permission | ||||||
| var PERMISSION_CREATE_POST *Permission | var PERMISSION_CREATE_POST *Permission | ||||||
|  | var PERMISSION_CREATE_POST_PUBLIC *Permission | ||||||
| var PERMISSION_EDIT_POST *Permission | var PERMISSION_EDIT_POST *Permission | ||||||
| var PERMISSION_EDIT_OTHERS_POSTS *Permission | var PERMISSION_EDIT_OTHERS_POSTS *Permission | ||||||
| var PERMISSION_DELETE_POST *Permission | var PERMISSION_DELETE_POST *Permission | ||||||
| @@ -56,6 +58,11 @@ var PERMISSION_CREATE_TEAM *Permission | |||||||
| var PERMISSION_MANAGE_TEAM *Permission | var PERMISSION_MANAGE_TEAM *Permission | ||||||
| var PERMISSION_IMPORT_TEAM *Permission | var PERMISSION_IMPORT_TEAM *Permission | ||||||
| var PERMISSION_VIEW_TEAM *Permission | var PERMISSION_VIEW_TEAM *Permission | ||||||
|  | var PERMISSION_LIST_USERS_WITHOUT_TEAM *Permission | ||||||
|  | var PERMISSION_MANAGE_JOBS *Permission | ||||||
|  | var PERMISSION_CREATE_USER_ACCESS_TOKEN *Permission | ||||||
|  | var PERMISSION_READ_USER_ACCESS_TOKEN *Permission | ||||||
|  | var PERMISSION_REVOKE_USER_ACCESS_TOKEN *Permission | ||||||
|  |  | ||||||
| // General permission that encompases all system admin functions | // General permission that encompases all system admin functions | ||||||
| // in the future this could be broken up to allow access to some | // in the future this could be broken up to allow access to some | ||||||
| @@ -64,9 +71,14 @@ var PERMISSION_MANAGE_SYSTEM *Permission | |||||||
|  |  | ||||||
| var ROLE_SYSTEM_USER *Role | var ROLE_SYSTEM_USER *Role | ||||||
| var ROLE_SYSTEM_ADMIN *Role | var ROLE_SYSTEM_ADMIN *Role | ||||||
|  | var ROLE_SYSTEM_POST_ALL *Role | ||||||
|  | var ROLE_SYSTEM_POST_ALL_PUBLIC *Role | ||||||
|  | var ROLE_SYSTEM_USER_ACCESS_TOKEN *Role | ||||||
|  |  | ||||||
| var ROLE_TEAM_USER *Role | var ROLE_TEAM_USER *Role | ||||||
| var ROLE_TEAM_ADMIN *Role | var ROLE_TEAM_ADMIN *Role | ||||||
|  | var ROLE_TEAM_POST_ALL *Role | ||||||
|  | var ROLE_TEAM_POST_ALL_PUBLIC *Role | ||||||
|  |  | ||||||
| var ROLE_CHANNEL_USER *Role | var ROLE_CHANNEL_USER *Role | ||||||
| var ROLE_CHANNEL_ADMIN *Role | var ROLE_CHANNEL_ADMIN *Role | ||||||
| @@ -195,6 +207,11 @@ func InitalizePermissions() { | |||||||
| 		"authentication.permissions.read_channel.name", | 		"authentication.permissions.read_channel.name", | ||||||
| 		"authentication.permissions.read_channel.description", | 		"authentication.permissions.read_channel.description", | ||||||
| 	} | 	} | ||||||
|  | 	PERMISSION_READ_PUBLIC_CHANNEL = &Permission{ | ||||||
|  | 		"read_public_channel", | ||||||
|  | 		"authentication.permissions.read_public_channel.name", | ||||||
|  | 		"authentication.permissions.read_public_channel.description", | ||||||
|  | 	} | ||||||
| 	PERMISSION_PERMANENT_DELETE_USER = &Permission{ | 	PERMISSION_PERMANENT_DELETE_USER = &Permission{ | ||||||
| 		"permanent_delete_user", | 		"permanent_delete_user", | ||||||
| 		"authentication.permissions.permanent_delete_user.name", | 		"authentication.permissions.permanent_delete_user.name", | ||||||
| @@ -235,6 +252,11 @@ func InitalizePermissions() { | |||||||
| 		"authentication.permissions.create_post.name", | 		"authentication.permissions.create_post.name", | ||||||
| 		"authentication.permissions.create_post.description", | 		"authentication.permissions.create_post.description", | ||||||
| 	} | 	} | ||||||
|  | 	PERMISSION_CREATE_POST_PUBLIC = &Permission{ | ||||||
|  | 		"create_post_public", | ||||||
|  | 		"authentication.permissions.create_post_public.name", | ||||||
|  | 		"authentication.permissions.create_post_public.description", | ||||||
|  | 	} | ||||||
| 	PERMISSION_EDIT_POST = &Permission{ | 	PERMISSION_EDIT_POST = &Permission{ | ||||||
| 		"edit_post", | 		"edit_post", | ||||||
| 		"authentication.permissions.edit_post.name", | 		"authentication.permissions.edit_post.name", | ||||||
| @@ -280,6 +302,31 @@ func InitalizePermissions() { | |||||||
| 		"authentication.permissions.view_team.name", | 		"authentication.permissions.view_team.name", | ||||||
| 		"authentication.permissions.view_team.description", | 		"authentication.permissions.view_team.description", | ||||||
| 	} | 	} | ||||||
|  | 	PERMISSION_LIST_USERS_WITHOUT_TEAM = &Permission{ | ||||||
|  | 		"list_users_without_team", | ||||||
|  | 		"authentication.permissions.list_users_without_team.name", | ||||||
|  | 		"authentication.permissions.list_users_without_team.description", | ||||||
|  | 	} | ||||||
|  | 	PERMISSION_CREATE_USER_ACCESS_TOKEN = &Permission{ | ||||||
|  | 		"create_user_access_token", | ||||||
|  | 		"authentication.permissions.create_user_access_token.name", | ||||||
|  | 		"authentication.permissions.create_user_access_token.description", | ||||||
|  | 	} | ||||||
|  | 	PERMISSION_READ_USER_ACCESS_TOKEN = &Permission{ | ||||||
|  | 		"read_user_access_token", | ||||||
|  | 		"authentication.permissions.read_user_access_token.name", | ||||||
|  | 		"authentication.permissions.read_user_access_token.description", | ||||||
|  | 	} | ||||||
|  | 	PERMISSION_REVOKE_USER_ACCESS_TOKEN = &Permission{ | ||||||
|  | 		"revoke_user_access_token", | ||||||
|  | 		"authentication.permissions.revoke_user_access_token.name", | ||||||
|  | 		"authentication.permissions.revoke_user_access_token.description", | ||||||
|  | 	} | ||||||
|  | 	PERMISSION_MANAGE_JOBS = &Permission{ | ||||||
|  | 		"manage_jobs", | ||||||
|  | 		"authentication.permisssions.manage_jobs.name", | ||||||
|  | 		"authentication.permisssions.manage_jobs.description", | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func InitalizeRoles() { | func InitalizeRoles() { | ||||||
| @@ -293,7 +340,6 @@ func InitalizeRoles() { | |||||||
| 		[]string{ | 		[]string{ | ||||||
| 			PERMISSION_READ_CHANNEL.Id, | 			PERMISSION_READ_CHANNEL.Id, | ||||||
| 			PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, | 			PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, | ||||||
| 			PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, |  | ||||||
| 			PERMISSION_UPLOAD_FILE.Id, | 			PERMISSION_UPLOAD_FILE.Id, | ||||||
| 			PERMISSION_GET_PUBLIC_LINK.Id, | 			PERMISSION_GET_PUBLIC_LINK.Id, | ||||||
| 			PERMISSION_CREATE_POST.Id, | 			PERMISSION_CREATE_POST.Id, | ||||||
| @@ -326,17 +372,38 @@ func InitalizeRoles() { | |||||||
| 		[]string{ | 		[]string{ | ||||||
| 			PERMISSION_LIST_TEAM_CHANNELS.Id, | 			PERMISSION_LIST_TEAM_CHANNELS.Id, | ||||||
| 			PERMISSION_JOIN_PUBLIC_CHANNELS.Id, | 			PERMISSION_JOIN_PUBLIC_CHANNELS.Id, | ||||||
|  | 			PERMISSION_READ_PUBLIC_CHANNEL.Id, | ||||||
| 			PERMISSION_VIEW_TEAM.Id, | 			PERMISSION_VIEW_TEAM.Id, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER | 	BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER | ||||||
|  |  | ||||||
|  | 	ROLE_TEAM_POST_ALL = &Role{ | ||||||
|  | 		"team_post_all", | ||||||
|  | 		"authentication.roles.team_post_all.name", | ||||||
|  | 		"authentication.roles.team_post_all.description", | ||||||
|  | 		[]string{ | ||||||
|  | 			PERMISSION_CREATE_POST.Id, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	BuiltInRoles[ROLE_TEAM_POST_ALL.Id] = ROLE_TEAM_POST_ALL | ||||||
|  |  | ||||||
|  | 	ROLE_TEAM_POST_ALL_PUBLIC = &Role{ | ||||||
|  | 		"team_post_all_public", | ||||||
|  | 		"authentication.roles.team_post_all_public.name", | ||||||
|  | 		"authentication.roles.team_post_all_public.description", | ||||||
|  | 		[]string{ | ||||||
|  | 			PERMISSION_CREATE_POST_PUBLIC.Id, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	BuiltInRoles[ROLE_TEAM_POST_ALL_PUBLIC.Id] = ROLE_TEAM_POST_ALL_PUBLIC | ||||||
|  |  | ||||||
| 	ROLE_TEAM_ADMIN = &Role{ | 	ROLE_TEAM_ADMIN = &Role{ | ||||||
| 		"team_admin", | 		"team_admin", | ||||||
| 		"authentication.roles.team_admin.name", | 		"authentication.roles.team_admin.name", | ||||||
| 		"authentication.roles.team_admin.description", | 		"authentication.roles.team_admin.description", | ||||||
| 		[]string{ | 		[]string{ | ||||||
| 			PERMISSION_EDIT_OTHERS_POSTS.Id, | 			PERMISSION_EDIT_OTHERS_POSTS.Id, | ||||||
| 			PERMISSION_ADD_USER_TO_TEAM.Id, |  | ||||||
| 			PERMISSION_REMOVE_USER_FROM_TEAM.Id, | 			PERMISSION_REMOVE_USER_FROM_TEAM.Id, | ||||||
| 			PERMISSION_MANAGE_TEAM.Id, | 			PERMISSION_MANAGE_TEAM.Id, | ||||||
| 			PERMISSION_IMPORT_TEAM.Id, | 			PERMISSION_IMPORT_TEAM.Id, | ||||||
| @@ -358,10 +425,42 @@ func InitalizeRoles() { | |||||||
| 			PERMISSION_CREATE_DIRECT_CHANNEL.Id, | 			PERMISSION_CREATE_DIRECT_CHANNEL.Id, | ||||||
| 			PERMISSION_CREATE_GROUP_CHANNEL.Id, | 			PERMISSION_CREATE_GROUP_CHANNEL.Id, | ||||||
| 			PERMISSION_PERMANENT_DELETE_USER.Id, | 			PERMISSION_PERMANENT_DELETE_USER.Id, | ||||||
| 			PERMISSION_MANAGE_OAUTH.Id, |  | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	BuiltInRoles[ROLE_SYSTEM_USER.Id] = ROLE_SYSTEM_USER | 	BuiltInRoles[ROLE_SYSTEM_USER.Id] = ROLE_SYSTEM_USER | ||||||
|  |  | ||||||
|  | 	ROLE_SYSTEM_POST_ALL = &Role{ | ||||||
|  | 		"system_post_all", | ||||||
|  | 		"authentication.roles.system_post_all.name", | ||||||
|  | 		"authentication.roles.system_post_all.description", | ||||||
|  | 		[]string{ | ||||||
|  | 			PERMISSION_CREATE_POST.Id, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	BuiltInRoles[ROLE_SYSTEM_POST_ALL.Id] = ROLE_SYSTEM_POST_ALL | ||||||
|  |  | ||||||
|  | 	ROLE_SYSTEM_POST_ALL_PUBLIC = &Role{ | ||||||
|  | 		"system_post_all_public", | ||||||
|  | 		"authentication.roles.system_post_all_public.name", | ||||||
|  | 		"authentication.roles.system_post_all_public.description", | ||||||
|  | 		[]string{ | ||||||
|  | 			PERMISSION_CREATE_POST_PUBLIC.Id, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	BuiltInRoles[ROLE_SYSTEM_POST_ALL_PUBLIC.Id] = ROLE_SYSTEM_POST_ALL_PUBLIC | ||||||
|  |  | ||||||
|  | 	ROLE_SYSTEM_USER_ACCESS_TOKEN = &Role{ | ||||||
|  | 		"system_user_access_token", | ||||||
|  | 		"authentication.roles.system_user_access_token.name", | ||||||
|  | 		"authentication.roles.system_user_access_token.description", | ||||||
|  | 		[]string{ | ||||||
|  | 			PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, | ||||||
|  | 			PERMISSION_READ_USER_ACCESS_TOKEN.Id, | ||||||
|  | 			PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	BuiltInRoles[ROLE_SYSTEM_USER_ACCESS_TOKEN.Id] = ROLE_SYSTEM_USER_ACCESS_TOKEN | ||||||
|  |  | ||||||
| 	ROLE_SYSTEM_ADMIN = &Role{ | 	ROLE_SYSTEM_ADMIN = &Role{ | ||||||
| 		"system_admin", | 		"system_admin", | ||||||
| 		"authentication.roles.global_admin.name", | 		"authentication.roles.global_admin.name", | ||||||
| @@ -378,6 +477,8 @@ func InitalizeRoles() { | |||||||
| 							PERMISSION_MANAGE_SYSTEM.Id, | 							PERMISSION_MANAGE_SYSTEM.Id, | ||||||
| 							PERMISSION_MANAGE_ROLES.Id, | 							PERMISSION_MANAGE_ROLES.Id, | ||||||
| 							PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, | 							PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id, | ||||||
|  | 							PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, | ||||||
|  | 							PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id, | ||||||
| 							PERMISSION_DELETE_PUBLIC_CHANNEL.Id, | 							PERMISSION_DELETE_PUBLIC_CHANNEL.Id, | ||||||
| 							PERMISSION_CREATE_PUBLIC_CHANNEL.Id, | 							PERMISSION_CREATE_PUBLIC_CHANNEL.Id, | ||||||
| 							PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, | 							PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id, | ||||||
| @@ -391,6 +492,13 @@ func InitalizeRoles() { | |||||||
| 							PERMISSION_DELETE_POST.Id, | 							PERMISSION_DELETE_POST.Id, | ||||||
| 							PERMISSION_DELETE_OTHERS_POSTS.Id, | 							PERMISSION_DELETE_OTHERS_POSTS.Id, | ||||||
| 							PERMISSION_CREATE_TEAM.Id, | 							PERMISSION_CREATE_TEAM.Id, | ||||||
|  | 							PERMISSION_ADD_USER_TO_TEAM.Id, | ||||||
|  | 							PERMISSION_LIST_USERS_WITHOUT_TEAM.Id, | ||||||
|  | 							PERMISSION_MANAGE_JOBS.Id, | ||||||
|  | 							PERMISSION_CREATE_POST_PUBLIC.Id, | ||||||
|  | 							PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, | ||||||
|  | 							PERMISSION_READ_USER_ACCESS_TOKEN.Id, | ||||||
|  | 							PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, | ||||||
| 						}, | 						}, | ||||||
| 						ROLE_TEAM_USER.Permissions..., | 						ROLE_TEAM_USER.Permissions..., | ||||||
| 					), | 					), | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								vendor/github.com/mattermost/platform/model/authorize.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/mattermost/platform/model/authorize.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -6,6 +6,7 @@ package model | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -25,6 +26,14 @@ type AuthData struct { | |||||||
| 	Scope       string `json:"scope"` | 	Scope       string `json:"scope"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type AuthorizeRequest struct { | ||||||
|  | 	ResponseType string `json:"response_type"` | ||||||
|  | 	ClientId     string `json:"client_id"` | ||||||
|  | 	RedirectUri  string `json:"redirect_uri"` | ||||||
|  | 	Scope        string `json:"scope"` | ||||||
|  | 	State        string `json:"state"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // IsValid validates the AuthData and returns an error if it isn't configured | // IsValid validates the AuthData and returns an error if it isn't configured | ||||||
| // correctly. | // correctly. | ||||||
| func (ad *AuthData) IsValid() *AppError { | func (ad *AuthData) IsValid() *AppError { | ||||||
| @@ -49,7 +58,7 @@ func (ad *AuthData) IsValid() *AppError { | |||||||
| 		return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.create_at.app_error", nil, "client_id="+ad.ClientId) | 		return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.create_at.app_error", nil, "client_id="+ad.ClientId) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(ad.RedirectUri) > 256 { | 	if len(ad.RedirectUri) == 0 || len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) { | ||||||
| 		return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ad.ClientId) | 		return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ad.ClientId) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -64,6 +73,33 @@ func (ad *AuthData) IsValid() *AppError { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // IsValid validates the AuthorizeRequest and returns an error if it isn't configured | ||||||
|  | // correctly. | ||||||
|  | func (ar *AuthorizeRequest) IsValid() *AppError { | ||||||
|  |  | ||||||
|  | 	if len(ar.ClientId) != 26 { | ||||||
|  | 		return NewAppError("AuthData.IsValid", "model.authorize.is_valid.client_id.app_error", nil, "", http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ar.ResponseType) == 0 { | ||||||
|  | 		return NewAppError("AuthData.IsValid", "model.authorize.is_valid.response_type.app_error", nil, "", http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ar.RedirectUri) == 0 || len(ar.RedirectUri) > 256 || !IsValidHttpUrl(ar.RedirectUri) { | ||||||
|  | 		return NewAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ar.State) > 128 { | ||||||
|  | 		return NewAppError("AuthData.IsValid", "model.authorize.is_valid.state.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ar.Scope) > 128 { | ||||||
|  | 		return NewAppError("AuthData.IsValid", "model.authorize.is_valid.scope.app_error", nil, "client_id="+ar.ClientId, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ad *AuthData) PreSave() { | func (ad *AuthData) PreSave() { | ||||||
| 	if ad.ExpiresIn == 0 { | 	if ad.ExpiresIn == 0 { | ||||||
| 		ad.ExpiresIn = AUTHCODE_EXPIRE_TIME | 		ad.ExpiresIn = AUTHCODE_EXPIRE_TIME | ||||||
| @@ -98,6 +134,26 @@ func AuthDataFromJson(data io.Reader) *AuthData { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ar *AuthorizeRequest) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(ar) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func AuthorizeRequestFromJson(data io.Reader) *AuthorizeRequest { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var ar AuthorizeRequest | ||||||
|  | 	err := decoder.Decode(&ar) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &ar | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ad *AuthData) IsExpired() bool { | func (ad *AuthData) IsExpired() bool { | ||||||
|  |  | ||||||
| 	if GetMillis() > ad.CreateAt+int64(ad.ExpiresIn*1000) { | 	if GetMillis() > ad.CreateAt+int64(ad.ExpiresIn*1000) { | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								vendor/github.com/mattermost/platform/model/channel.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/mattermost/platform/model/channel.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -46,6 +46,13 @@ type Channel struct { | |||||||
| 	CreatorId     string `json:"creator_id"` | 	CreatorId     string `json:"creator_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type ChannelPatch struct { | ||||||
|  | 	DisplayName *string `json:"display_name"` | ||||||
|  | 	Name        *string `json:"name"` | ||||||
|  | 	Header      *string `json:"header"` | ||||||
|  | 	Purpose     *string `json:"purpose"` | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *Channel) ToJson() string { | func (o *Channel) ToJson() string { | ||||||
| 	b, err := json.Marshal(o) | 	b, err := json.Marshal(o) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -55,6 +62,15 @@ func (o *Channel) ToJson() string { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *ChannelPatch) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(o) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func ChannelFromJson(data io.Reader) *Channel { | func ChannelFromJson(data io.Reader) *Channel { | ||||||
| 	decoder := json.NewDecoder(data) | 	decoder := json.NewDecoder(data) | ||||||
| 	var o Channel | 	var o Channel | ||||||
| @@ -66,6 +82,17 @@ func ChannelFromJson(data io.Reader) *Channel { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func ChannelPatchFromJson(data io.Reader) *ChannelPatch { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var o ChannelPatch | ||||||
|  | 	err := decoder.Decode(&o) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &o | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *Channel) Etag() string { | func (o *Channel) Etag() string { | ||||||
| 	return Etag(o.Id, o.UpdateAt) | 	return Etag(o.Id, o.UpdateAt) | ||||||
| } | } | ||||||
| @@ -137,6 +164,24 @@ func (o *Channel) IsGroupOrDirect() bool { | |||||||
| 	return o.Type == CHANNEL_DIRECT || o.Type == CHANNEL_GROUP | 	return o.Type == CHANNEL_DIRECT || o.Type == CHANNEL_GROUP | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *Channel) Patch(patch *ChannelPatch) { | ||||||
|  | 	if patch.DisplayName != nil { | ||||||
|  | 		o.DisplayName = *patch.DisplayName | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if patch.Name != nil { | ||||||
|  | 		o.Name = *patch.Name | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if patch.Header != nil { | ||||||
|  | 		o.Header = *patch.Header | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if patch.Purpose != nil { | ||||||
|  | 		o.Purpose = *patch.Purpose | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func GetDMNameFromIds(userId1, userId2 string) string { | func GetDMNameFromIds(userId1, userId2 string) string { | ||||||
| 	if userId1 > userId2 { | 	if userId1 > userId2 { | ||||||
| 		return userId2 + "__" + userId1 | 		return userId2 + "__" + userId1 | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_count.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_count.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_data.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_data.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								vendor/github.com/mattermost/platform/model/channel_list.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/mattermost/platform/model/channel_list.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -50,3 +50,14 @@ func ChannelListFromJson(data io.Reader) *ChannelList { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func ChannelSliceFromJson(data io.Reader) []*Channel { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var o []*Channel | ||||||
|  | 	err := decoder.Decode(&o) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return o | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								vendor/github.com/mattermost/platform/model/channel_member.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/mattermost/platform/model/channel_member.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -19,11 +19,11 @@ const ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type ChannelUnread struct { | type ChannelUnread struct { | ||||||
| 	TeamId        string | 	TeamId       string    `json:"team_id"` | ||||||
| 	TotalMsgCount int64 | 	ChannelId    string    `json:"channel_id"` | ||||||
| 	MsgCount      int64 | 	MsgCount     int64     `json:"msg_count"` | ||||||
| 	MentionCount  int64 | 	MentionCount int64     `json:"mention_count"` | ||||||
| 	NotifyProps   StringMap | 	NotifyProps  StringMap `json:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type ChannelMember struct { | type ChannelMember struct { | ||||||
| @@ -47,6 +47,15 @@ func (o *ChannelMembers) ToJson() string { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *ChannelUnread) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(o) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func ChannelMembersFromJson(data io.Reader) *ChannelMembers { | func ChannelMembersFromJson(data io.Reader) *ChannelMembers { | ||||||
| 	decoder := json.NewDecoder(data) | 	decoder := json.NewDecoder(data) | ||||||
| 	var o ChannelMembers | 	var o ChannelMembers | ||||||
| @@ -58,6 +67,17 @@ func ChannelMembersFromJson(data io.Reader) *ChannelMembers { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func ChannelUnreadFromJson(data io.Reader) *ChannelUnread { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var o ChannelUnread | ||||||
|  | 	err := decoder.Decode(&o) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &o | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *ChannelMember) ToJson() string { | func (o *ChannelMember) ToJson() string { | ||||||
| 	b, err := json.Marshal(o) | 	b, err := json.Marshal(o) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_search.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_search.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_view.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/channel_view.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										80
									
								
								vendor/github.com/mattermost/platform/model/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								vendor/github.com/mattermost/platform/model/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -1191,17 +1191,6 @@ func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // SCHEDULED FOR DEPRECATION IN 3.7 - use GetMoreChannelsPage instead |  | ||||||
| func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { |  | ||||||
| 	if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} else { |  | ||||||
| 		defer closeBody(r) |  | ||||||
| 		return &Result{r.Header.Get(HEADER_REQUEST_ID), |  | ||||||
| 			r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // GetMoreChannelsPage will return a page of open channels the user is not in based on | // GetMoreChannelsPage will return a page of open channels the user is not in based on | ||||||
| // the provided offset and limit. Must be authenticated. | // the provided offset and limit. Must be authenticated. | ||||||
| func (c *Client) GetMoreChannelsPage(offset int, limit int) (*Result, *AppError) { | func (c *Client) GetMoreChannelsPage(offset int, limit int) (*Result, *AppError) { | ||||||
| @@ -1333,22 +1322,6 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // UpdateLastViewedAt will mark a channel as read. |  | ||||||
| // The channelId indicates the channel to mark as read. If active is true, push notifications |  | ||||||
| // will be cleared if there are unread messages. The default for active is true. |  | ||||||
| // SCHEDULED FOR DEPRECATION IN 3.8 - use ViewChannel instead |  | ||||||
| func (c *Client) UpdateLastViewedAt(channelId string, active bool) (*Result, *AppError) { |  | ||||||
| 	data := make(map[string]interface{}) |  | ||||||
| 	data["active"] = active |  | ||||||
| 	if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_last_viewed_at", StringInterfaceToJson(data)); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} else { |  | ||||||
| 		defer closeBody(r) |  | ||||||
| 		return &Result{r.Header.Get(HEADER_REQUEST_ID), |  | ||||||
| 			r.Header.Get(HEADER_ETAG_SERVER), nil}, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ViewChannel performs all the actions related to viewing a channel. This includes marking | // ViewChannel performs all the actions related to viewing a channel. This includes marking | ||||||
| // the channel and the previous one as read, and marking the channel as being actively viewed. | // the channel and the previous one as read, and marking the channel as being actively viewed. | ||||||
| // ChannelId is required but may be blank to indicate no channel is being viewed. | // ChannelId is required but may be blank to indicate no channel is being viewed. | ||||||
| @@ -1533,6 +1506,16 @@ func (c *Client) GetFlaggedPosts(offset int, limit int) (*Result, *AppError) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Client) GetPinnedPosts(channelId string) (*Result, *AppError) { | ||||||
|  | 	if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", "", ""); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else { | ||||||
|  | 		defer closeBody(r) | ||||||
|  | 		return &Result{r.Header.Get(HEADER_REQUEST_ID), | ||||||
|  | 			r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *AppError) { | func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *AppError) { | ||||||
| 	return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType) | 	return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType) | ||||||
| } | } | ||||||
| @@ -1782,22 +1765,6 @@ func (c *Client) GetStatusesByIds(userIds []string) (*Result, *AppError) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // SetActiveChannel sets the the channel id the user is currently viewing. |  | ||||||
| // The channelId key is required but the value can be blank. Returns standard |  | ||||||
| // response. |  | ||||||
| // SCHEDULED FOR DEPRECATION IN 3.8 - use ViewChannel instead |  | ||||||
| func (c *Client) SetActiveChannel(channelId string) (*Result, *AppError) { |  | ||||||
| 	data := map[string]string{} |  | ||||||
| 	data["channel_id"] = channelId |  | ||||||
| 	if r, err := c.DoApiPost("/users/status/set_active_channel", MapToJson(data)); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} else { |  | ||||||
| 		defer closeBody(r) |  | ||||||
| 		return &Result{r.Header.Get(HEADER_REQUEST_ID), |  | ||||||
| 			r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { | func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { | ||||||
| 	if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil { | 	if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @@ -1874,15 +1841,14 @@ func (c *Client) GetTeamStats(teamId string) (*Result, *AppError) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetTeamStats will return a team stats object containing the number of users on the team | // GetTeamByName will return a team object based on the team name provided. Must be authenticated. | ||||||
| // based on the team id provided. Must be authenticated. |  | ||||||
| func (c *Client) GetTeamByName(teamName string) (*Result, *AppError) { | func (c *Client) GetTeamByName(teamName string) (*Result, *AppError) { | ||||||
| 	if r, err := c.DoApiGet(fmt.Sprintf("/teams/name/%v", teamName), "", ""); err != nil { | 	if r, err := c.DoApiGet(fmt.Sprintf("/teams/name/%v", teamName), "", ""); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} else { | 	} else { | ||||||
| 		defer closeBody(r) | 		defer closeBody(r) | ||||||
| 		return &Result{r.Header.Get(HEADER_REQUEST_ID), | 		return &Result{r.Header.Get(HEADER_REQUEST_ID), | ||||||
| 			r.Header.Get(HEADER_ETAG_SERVER), TeamStatsFromJson(r.Body)}, nil | 			r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -2389,3 +2355,23 @@ func (c *Client) UpdateChannelRoles(channelId string, userId string, roles strin | |||||||
| 			} | 			} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Client) PinPost(channelId string, postId string) (*Result, *AppError) { | ||||||
|  | 	if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/posts/"+postId+"/pin", ""); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else { | ||||||
|  | 		defer closeBody(r) | ||||||
|  | 		return &Result{r.Header.Get(HEADER_REQUEST_ID), | ||||||
|  | 			r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Client) UnpinPost(channelId string, postId string) (*Result, *AppError) { | ||||||
|  | 	if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/posts/"+postId+"/unpin", ""); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else { | ||||||
|  | 		defer closeBody(r) | ||||||
|  | 		return &Result{r.Header.Get(HEADER_REQUEST_ID), | ||||||
|  | 			r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										2225
									
								
								vendor/github.com/mattermost/platform/model/client4.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2225
									
								
								vendor/github.com/mattermost/platform/model/client4.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										132
									
								
								vendor/github.com/mattermost/platform/model/cluster_discovery.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								vendor/github.com/mattermost/platform/model/cluster_discovery.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | |||||||
|  | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package model | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	CDS_OFFLINE_AFTER_MILLIS = 1000 * 60 * 30 // 30 minutes | ||||||
|  | 	CDS_TYPE_APP             = "mattermost_app" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type ClusterDiscovery struct { | ||||||
|  | 	Id          string `json:"id"` | ||||||
|  | 	Type        string `json:"type"` | ||||||
|  | 	ClusterName string `json:"cluster_name"` | ||||||
|  | 	Hostname    string `json:"hostname"` | ||||||
|  | 	GossipPort  int32  `json:"gossip_port"` | ||||||
|  | 	Port        int32  `json:"port"` | ||||||
|  | 	CreateAt    int64  `json:"create_at"` | ||||||
|  | 	LastPingAt  int64  `json:"last_ping_at"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) PreSave() { | ||||||
|  | 	if o.Id == "" { | ||||||
|  | 		o.Id = NewId() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.CreateAt == 0 { | ||||||
|  | 		o.CreateAt = GetMillis() | ||||||
|  | 		o.LastPingAt = o.CreateAt | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) AutoFillHostname() { | ||||||
|  | 	// attempt to set the hostname from the OS | ||||||
|  | 	if len(o.Hostname) == 0 { | ||||||
|  | 		if hn, err := os.Hostname(); err == nil { | ||||||
|  | 			o.Hostname = hn | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) AutoFillIpAddress() { | ||||||
|  | 	// attempt to set the hostname to the first non-local IP address | ||||||
|  | 	if len(o.Hostname) == 0 { | ||||||
|  | 		o.Hostname = GetServerIpAddress() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) IsEqual(in *ClusterDiscovery) bool { | ||||||
|  | 	if in == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.Type != in.Type { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterName != in.ClusterName { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.Hostname != in.Hostname { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func FilterClusterDiscovery(vs []*ClusterDiscovery, f func(*ClusterDiscovery) bool) []*ClusterDiscovery { | ||||||
|  | 	copy := make([]*ClusterDiscovery, 0) | ||||||
|  | 	for _, v := range vs { | ||||||
|  | 		if f(v) { | ||||||
|  | 			copy = append(copy, v) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return copy | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) IsValid() *AppError { | ||||||
|  | 	if len(o.Id) != 26 { | ||||||
|  | 		return NewLocAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(o.ClusterName) == 0 { | ||||||
|  | 		return NewLocAppError("ClusterDiscovery.IsValid", "ClusterName must be set", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(o.Type) == 0 { | ||||||
|  | 		return NewLocAppError("ClusterDiscovery.IsValid", "Type must be set", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(o.Hostname) == 0 { | ||||||
|  | 		return NewLocAppError("ClusterDiscovery.IsValid", "Hostname must be set", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.CreateAt == 0 { | ||||||
|  | 		return NewLocAppError("ClusterDiscovery.IsValid", "CreateAt must be set", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.LastPingAt == 0 { | ||||||
|  | 		return NewLocAppError("ClusterDiscovery.IsValid", "LastPingAt must be set", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterDiscovery) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(o) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return string(b) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ClusterDiscoveryFromJson(data io.Reader) *ClusterDiscovery { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var me ClusterDiscovery | ||||||
|  | 	err := decoder.Decode(&me) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &me | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								vendor/github.com/mattermost/platform/model/cluster_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/mattermost/platform/model/cluster_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -6,16 +6,14 @@ package model | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ClusterInfo struct { | type ClusterInfo struct { | ||||||
| 	Id                 string `json:"id"` | 	Version    string `json:"version"` | ||||||
| 	Version            string `json:"version"` | 	ConfigHash string `json:"config_hash"` | ||||||
| 	ConfigHash         string `json:"config_hash"` | 	IpAddress  string `json:"ipaddress"` | ||||||
| 	InterNodeUrl       string `json:"internode_url"` | 	Hostname   string `json:"hostname"` | ||||||
| 	Hostname           string `json:"hostname"` |  | ||||||
| 	LastSuccessfulPing int64  `json:"last_ping"` |  | ||||||
| 	IsAlive            bool   `json:"is_alive"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (me *ClusterInfo) ToJson() string { | func (me *ClusterInfo) ToJson() string { | ||||||
| @@ -27,6 +25,11 @@ func (me *ClusterInfo) ToJson() string { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (me *ClusterInfo) Copy() *ClusterInfo { | ||||||
|  | 	json := me.ToJson() | ||||||
|  | 	return ClusterInfoFromJson(strings.NewReader(json)) | ||||||
|  | } | ||||||
|  |  | ||||||
| func ClusterInfoFromJson(data io.Reader) *ClusterInfo { | func ClusterInfoFromJson(data io.Reader) *ClusterInfo { | ||||||
| 	decoder := json.NewDecoder(data) | 	decoder := json.NewDecoder(data) | ||||||
| 	var me ClusterInfo | 	var me ClusterInfo | ||||||
| @@ -38,14 +41,6 @@ func ClusterInfoFromJson(data io.Reader) *ClusterInfo { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (me *ClusterInfo) HaveEstablishedInitialContact() bool { |  | ||||||
| 	if me.Id != "" { |  | ||||||
| 		return true |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func ClusterInfosToJson(objmap []*ClusterInfo) string { | func ClusterInfosToJson(objmap []*ClusterInfo) string { | ||||||
| 	if b, err := json.Marshal(objmap); err != nil { | 	if b, err := json.Marshal(objmap); err != nil { | ||||||
| 		return "" | 		return "" | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								vendor/github.com/mattermost/platform/model/cluster_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/github.com/mattermost/platform/model/cluster_message.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package model | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"io" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	CLUSTER_EVENT_PUBLISH                                           = "publish" | ||||||
|  | 	CLUSTER_EVENT_UPDATE_STATUS                                     = "update_status" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_ALL_CACHES                             = "inv_all_caches" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS                    = "inv_reactions" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOK                      = "inv_webhook" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_POSTS                = "inv_channel_posts" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS_NOTIFY_PROPS = "inv_channel_members_notify_props" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS              = "inv_channel_members" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME              = "inv_channel_name" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL                      = "inv_channel" | ||||||
|  | 	CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER                         = "inv_user" | ||||||
|  | 	CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER                      = "clear_session_user" | ||||||
|  |  | ||||||
|  | 	CLUSTER_SEND_BEST_EFFORT = "best_effort" | ||||||
|  | 	CLUSTER_SEND_RELIABLE    = "reliable" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type ClusterMessage struct { | ||||||
|  | 	Event            string            `json:"event"` | ||||||
|  | 	SendType         string            `json:"-"` | ||||||
|  | 	WaitForAllToSend bool              `json:"-"` | ||||||
|  | 	Data             string            `json:"data,omitempty"` | ||||||
|  | 	Props            map[string]string `json:"props,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *ClusterMessage) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(o) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ClusterMessageFromJson(data io.Reader) *ClusterMessage { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var o ClusterMessage | ||||||
|  | 	err := decoder.Decode(&o) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &o | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/cluster_stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/cluster_stats.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/command.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/command.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								vendor/github.com/mattermost/platform/model/command_args.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/mattermost/platform/model/command_args.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -6,13 +6,20 @@ package model | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"io" | 	"io" | ||||||
|  |  | ||||||
|  | 	goi18n "github.com/nicksnyder/go-i18n/i18n" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type CommandArgs struct { | type CommandArgs struct { | ||||||
| 	ChannelId string `json:"channel_id"` | 	UserId    string               `json:"user_id"` | ||||||
| 	RootId    string `json:"root_id"` | 	ChannelId string               `json:"channel_id"` | ||||||
| 	ParentId  string `json:"parent_id"` | 	TeamId    string               `json:"team_id"` | ||||||
| 	Command   string `json:"command"` | 	RootId    string               `json:"root_id"` | ||||||
|  | 	ParentId  string               `json:"parent_id"` | ||||||
|  | 	Command   string               `json:"command"` | ||||||
|  | 	SiteURL   string               `json:"-"` | ||||||
|  | 	T         goi18n.TranslateFunc `json:"-"` | ||||||
|  | 	Session   Session              `json:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *CommandArgs) ToJson() string { | func (o *CommandArgs) ToJson() string { | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								vendor/github.com/mattermost/platform/model/command_response.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/mattermost/platform/model/command_response.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,11 +1,10 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -40,14 +39,8 @@ func CommandResponseFromJson(data io.Reader) *CommandResponse { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Ensure attachment fields are stored as strings | 	o.Text = ExpandAnnouncement(o.Text) | ||||||
| 	for _, attachment := range o.Attachments { | 	o.Attachments = ProcessSlackAttachments(o.Attachments) | ||||||
| 		for _, field := range attachment.Fields { |  | ||||||
| 			if field.Value != nil { |  | ||||||
| 				field.Value = fmt.Sprintf("%v", field.Value) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return &o | 	return &o | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/compliance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/compliance.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								vendor/github.com/mattermost/platform/model/compliance_post.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/mattermost/platform/model/compliance_post.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,9 +1,10 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"regexp" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -64,6 +65,15 @@ func CompliancePostHeader() []string { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func cleanComplianceStrings(in string) string { | ||||||
|  | 	if matched, _ := regexp.MatchString("^\\s*(=|\\+|\\-)", in); matched { | ||||||
|  | 		return "'" + in | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  | 		return in | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (me *CompliancePost) Row() []string { | func (me *CompliancePost) Row() []string { | ||||||
|  |  | ||||||
| 	postDeleteAt := "" | 	postDeleteAt := "" | ||||||
| @@ -77,15 +87,15 @@ func (me *CompliancePost) Row() []string { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return []string{ | 	return []string{ | ||||||
| 		me.TeamName, | 		cleanComplianceStrings(me.TeamName), | ||||||
| 		me.TeamDisplayName, | 		cleanComplianceStrings(me.TeamDisplayName), | ||||||
|  |  | ||||||
| 		me.ChannelName, | 		cleanComplianceStrings(me.ChannelName), | ||||||
| 		me.ChannelDisplayName, | 		cleanComplianceStrings(me.ChannelDisplayName), | ||||||
|  |  | ||||||
| 		me.UserUsername, | 		cleanComplianceStrings(me.UserUsername), | ||||||
| 		me.UserEmail, | 		cleanComplianceStrings(me.UserEmail), | ||||||
| 		me.UserNickname, | 		cleanComplianceStrings(me.UserNickname), | ||||||
|  |  | ||||||
| 		me.PostId, | 		me.PostId, | ||||||
| 		time.Unix(0, me.PostCreateAt*int64(1000*1000)).Format(time.RFC3339), | 		time.Unix(0, me.PostCreateAt*int64(1000*1000)).Format(time.RFC3339), | ||||||
| @@ -95,7 +105,7 @@ func (me *CompliancePost) Row() []string { | |||||||
| 		me.PostRootId, | 		me.PostRootId, | ||||||
| 		me.PostParentId, | 		me.PostParentId, | ||||||
| 		me.PostOriginalId, | 		me.PostOriginalId, | ||||||
| 		me.PostMessage, | 		cleanComplianceStrings(me.PostMessage), | ||||||
| 		me.PostType, | 		me.PostType, | ||||||
| 		me.PostProps, | 		me.PostProps, | ||||||
| 		me.PostHashtags, | 		me.PostHashtags, | ||||||
|   | |||||||
							
								
								
									
										624
									
								
								vendor/github.com/mattermost/platform/model/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										624
									
								
								vendor/github.com/mattermost/platform/model/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -6,6 +6,7 @@ package model | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -32,12 +33,17 @@ const ( | |||||||
| 	WEBSERVER_MODE_GZIP     = "gzip" | 	WEBSERVER_MODE_GZIP     = "gzip" | ||||||
| 	WEBSERVER_MODE_DISABLED = "disabled" | 	WEBSERVER_MODE_DISABLED = "disabled" | ||||||
|  |  | ||||||
| 	GENERIC_NOTIFICATION = "generic" | 	GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel" | ||||||
| 	FULL_NOTIFICATION    = "full" | 	GENERIC_NOTIFICATION            = "generic" | ||||||
|  | 	FULL_NOTIFICATION               = "full" | ||||||
|  |  | ||||||
| 	DIRECT_MESSAGE_ANY  = "any" | 	DIRECT_MESSAGE_ANY  = "any" | ||||||
| 	DIRECT_MESSAGE_TEAM = "team" | 	DIRECT_MESSAGE_TEAM = "team" | ||||||
|  |  | ||||||
|  | 	SHOW_USERNAME          = "username" | ||||||
|  | 	SHOW_NICKNAME_FULLNAME = "nickname_full_name" | ||||||
|  | 	SHOW_FULLNAME          = "full_name" | ||||||
|  |  | ||||||
| 	PERMISSIONS_ALL           = "all" | 	PERMISSIONS_ALL           = "all" | ||||||
| 	PERMISSIONS_CHANNEL_ADMIN = "channel_admin" | 	PERMISSIONS_CHANNEL_ADMIN = "channel_admin" | ||||||
| 	PERMISSIONS_TEAM_ADMIN    = "team_admin" | 	PERMISSIONS_TEAM_ADMIN    = "team_admin" | ||||||
| @@ -60,6 +66,9 @@ const ( | |||||||
| 	EMAIL_BATCHING_BUFFER_SIZE = 256 | 	EMAIL_BATCHING_BUFFER_SIZE = 256 | ||||||
| 	EMAIL_BATCHING_INTERVAL    = 30 | 	EMAIL_BATCHING_INTERVAL    = 30 | ||||||
|  |  | ||||||
|  | 	EMAIL_NOTIFICATION_CONTENTS_FULL    = "full" | ||||||
|  | 	EMAIL_NOTIFICATION_CONTENTS_GENERIC = "generic" | ||||||
|  |  | ||||||
| 	SITENAME_MAX_LENGTH = 30 | 	SITENAME_MAX_LENGTH = 30 | ||||||
|  |  | ||||||
| 	SERVICE_SETTINGS_DEFAULT_SITE_URL        = "" | 	SERVICE_SETTINGS_DEFAULT_SITE_URL        = "" | ||||||
| @@ -75,12 +84,15 @@ const ( | |||||||
|  |  | ||||||
| 	EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = "" | 	EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = "" | ||||||
|  |  | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK = "https://about.mattermost.com/default-terms/" | 	SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK      = "https://about.mattermost.com/default-terms/" | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK   = "https://about.mattermost.com/default-privacy-policy/" | 	SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK        = "https://about.mattermost.com/default-privacy-policy/" | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK            = "https://about.mattermost.com/default-about/" | 	SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK                 = "https://about.mattermost.com/default-about/" | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_HELP_LINK             = "https://about.mattermost.com/default-help/" | 	SUPPORT_SETTINGS_DEFAULT_HELP_LINK                  = "https://about.mattermost.com/default-help/" | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/" | 	SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK      = "https://about.mattermost.com/default-report-a-problem/" | ||||||
| 	SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL         = "feedback@mattermost.com" | 	SUPPORT_SETTINGS_DEFAULT_ADMINISTRATORS_GUIDE_LINK  = "https://about.mattermost.com/administrators-guide/" | ||||||
|  | 	SUPPORT_SETTINGS_DEFAULT_TROUBLESHOOTING_FORUM_LINK = "https://about.mattermost.com/troubleshooting-forum/" | ||||||
|  | 	SUPPORT_SETTINGS_DEFAULT_COMMERCIAL_SUPPORT_LINK    = "https://about.mattermost.com/commercial-support/" | ||||||
|  | 	SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL              = "feedback@mattermost.com" | ||||||
|  |  | ||||||
| 	LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = "" | 	LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = "" | ||||||
| 	LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE  = "" | 	LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE  = "" | ||||||
| @@ -107,10 +119,20 @@ const ( | |||||||
| 	WEBRTC_SETTINGS_DEFAULT_TURN_URI = "" | 	WEBRTC_SETTINGS_DEFAULT_TURN_URI = "" | ||||||
|  |  | ||||||
| 	ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS = 2500 | 	ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS = 2500 | ||||||
|  |  | ||||||
|  | 	ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR      = "#f2a93b" | ||||||
|  | 	ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR = "#333333" | ||||||
|  |  | ||||||
|  | 	ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL      = "" | ||||||
|  | 	ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME            = "" | ||||||
|  | 	ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD            = "" | ||||||
|  | 	ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS = 1 | ||||||
|  | 	ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS   = 1 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ServiceSettings struct { | type ServiceSettings struct { | ||||||
| 	SiteURL                                  *string | 	SiteURL                                  *string | ||||||
|  | 	LicenseFileLocation                      *string | ||||||
| 	ListenAddress                            string | 	ListenAddress                            string | ||||||
| 	ConnectionSecurity                       *string | 	ConnectionSecurity                       *string | ||||||
| 	TLSCertFile                              *string | 	TLSCertFile                              *string | ||||||
| @@ -121,6 +143,7 @@ type ServiceSettings struct { | |||||||
| 	ReadTimeout                              *int | 	ReadTimeout                              *int | ||||||
| 	WriteTimeout                             *int | 	WriteTimeout                             *int | ||||||
| 	MaximumLoginAttempts                     int | 	MaximumLoginAttempts                     int | ||||||
|  | 	GoroutineHealthThreshold                 *int | ||||||
| 	GoogleDeveloperKey                       string | 	GoogleDeveloperKey                       string | ||||||
| 	EnableOAuthServiceProvider               bool | 	EnableOAuthServiceProvider               bool | ||||||
| 	EnableIncomingWebhooks                   bool | 	EnableIncomingWebhooks                   bool | ||||||
| @@ -129,6 +152,7 @@ type ServiceSettings struct { | |||||||
| 	EnableOnlyAdminIntegrations              *bool | 	EnableOnlyAdminIntegrations              *bool | ||||||
| 	EnablePostUsernameOverride               bool | 	EnablePostUsernameOverride               bool | ||||||
| 	EnablePostIconOverride                   bool | 	EnablePostIconOverride                   bool | ||||||
|  | 	EnableAPIv3                              *bool | ||||||
| 	EnableLinkPreviews                       *bool | 	EnableLinkPreviews                       *bool | ||||||
| 	EnableTesting                            bool | 	EnableTesting                            bool | ||||||
| 	EnableDeveloper                          *bool | 	EnableDeveloper                          *bool | ||||||
| @@ -136,6 +160,7 @@ type ServiceSettings struct { | |||||||
| 	EnableInsecureOutgoingConnections        *bool | 	EnableInsecureOutgoingConnections        *bool | ||||||
| 	EnableMultifactorAuthentication          *bool | 	EnableMultifactorAuthentication          *bool | ||||||
| 	EnforceMultifactorAuthentication         *bool | 	EnforceMultifactorAuthentication         *bool | ||||||
|  | 	EnableUserAccessTokens                   *bool | ||||||
| 	AllowCorsFrom                            *string | 	AllowCorsFrom                            *string | ||||||
| 	SessionLengthWebInDays                   *int | 	SessionLengthWebInDays                   *int | ||||||
| 	SessionLengthMobileInDays                *int | 	SessionLengthMobileInDays                *int | ||||||
| @@ -145,19 +170,28 @@ type ServiceSettings struct { | |||||||
| 	WebsocketPort                            *int | 	WebsocketPort                            *int | ||||||
| 	WebserverMode                            *string | 	WebserverMode                            *string | ||||||
| 	EnableCustomEmoji                        *bool | 	EnableCustomEmoji                        *bool | ||||||
|  | 	EnableEmojiPicker                        *bool | ||||||
| 	RestrictCustomEmojiCreation              *string | 	RestrictCustomEmojiCreation              *string | ||||||
| 	RestrictPostDelete                       *string | 	RestrictPostDelete                       *string | ||||||
| 	AllowEditPost                            *string | 	AllowEditPost                            *string | ||||||
| 	PostEditTimeLimit                        *int | 	PostEditTimeLimit                        *int | ||||||
| 	TimeBetweenUserTypingUpdatesMilliseconds *int64 | 	TimeBetweenUserTypingUpdatesMilliseconds *int64 | ||||||
|  | 	EnablePostSearch                         *bool | ||||||
| 	EnableUserTypingMessages                 *bool | 	EnableUserTypingMessages                 *bool | ||||||
|  | 	EnableChannelViewedMessages              *bool | ||||||
|  | 	EnableUserStatuses                       *bool | ||||||
| 	ClusterLogTimeoutMilliseconds            *int | 	ClusterLogTimeoutMilliseconds            *int | ||||||
| } | } | ||||||
|  |  | ||||||
| type ClusterSettings struct { | type ClusterSettings struct { | ||||||
| 	Enable                 *bool | 	Enable                *bool | ||||||
| 	InterNodeListenAddress *string | 	ClusterName           *string | ||||||
| 	InterNodeUrls          []string | 	OverrideHostname      *string | ||||||
|  | 	UseIpAddress          *bool | ||||||
|  | 	UseExperimentalGossip *bool | ||||||
|  | 	ReadOnlyConfig        *bool | ||||||
|  | 	GossipPort            *int | ||||||
|  | 	StreamingPort         *int | ||||||
| } | } | ||||||
|  |  | ||||||
| type MetricsSettings struct { | type MetricsSettings struct { | ||||||
| @@ -181,13 +215,15 @@ type SSOSettings struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type SqlSettings struct { | type SqlSettings struct { | ||||||
| 	DriverName         string | 	DriverName               string | ||||||
| 	DataSource         string | 	DataSource               string | ||||||
| 	DataSourceReplicas []string | 	DataSourceReplicas       []string | ||||||
| 	MaxIdleConns       int | 	DataSourceSearchReplicas []string | ||||||
| 	MaxOpenConns       int | 	MaxIdleConns             int | ||||||
| 	Trace              bool | 	MaxOpenConns             int | ||||||
| 	AtRestEncryptKey   string | 	Trace                    bool | ||||||
|  | 	AtRestEncryptKey         string | ||||||
|  | 	QueryTimeout             *int | ||||||
| } | } | ||||||
|  |  | ||||||
| type LogSettings struct { | type LogSettings struct { | ||||||
| @@ -210,17 +246,14 @@ type PasswordSettings struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type FileSettings struct { | type FileSettings struct { | ||||||
|  | 	EnableFileAttachments   *bool | ||||||
|  | 	EnableMobileUpload      *bool | ||||||
|  | 	EnableMobileDownload    *bool | ||||||
| 	MaxFileSize             *int64 | 	MaxFileSize             *int64 | ||||||
| 	DriverName              string | 	DriverName              string | ||||||
| 	Directory               string | 	Directory               string | ||||||
| 	EnablePublicLink        bool | 	EnablePublicLink        bool | ||||||
| 	PublicLinkSalt          *string | 	PublicLinkSalt          *string | ||||||
| 	ThumbnailWidth          int |  | ||||||
| 	ThumbnailHeight         int |  | ||||||
| 	PreviewWidth            int |  | ||||||
| 	PreviewHeight           int |  | ||||||
| 	ProfileWidth            int |  | ||||||
| 	ProfileHeight           int |  | ||||||
| 	InitialFont             string | 	InitialFont             string | ||||||
| 	AmazonS3AccessKeyId     string | 	AmazonS3AccessKeyId     string | ||||||
| 	AmazonS3SecretAccessKey string | 	AmazonS3SecretAccessKey string | ||||||
| @@ -228,30 +261,34 @@ type FileSettings struct { | |||||||
| 	AmazonS3Region          string | 	AmazonS3Region          string | ||||||
| 	AmazonS3Endpoint        string | 	AmazonS3Endpoint        string | ||||||
| 	AmazonS3SSL             *bool | 	AmazonS3SSL             *bool | ||||||
|  | 	AmazonS3SignV2          *bool | ||||||
|  | 	AmazonS3SSE             *bool | ||||||
| } | } | ||||||
|  |  | ||||||
| type EmailSettings struct { | type EmailSettings struct { | ||||||
| 	EnableSignUpWithEmail    bool | 	EnableSignUpWithEmail             bool | ||||||
| 	EnableSignInWithEmail    *bool | 	EnableSignInWithEmail             *bool | ||||||
| 	EnableSignInWithUsername *bool | 	EnableSignInWithUsername          *bool | ||||||
| 	SendEmailNotifications   bool | 	SendEmailNotifications            bool | ||||||
| 	RequireEmailVerification bool | 	RequireEmailVerification          bool | ||||||
| 	FeedbackName             string | 	FeedbackName                      string | ||||||
| 	FeedbackEmail            string | 	FeedbackEmail                     string | ||||||
| 	FeedbackOrganization     *string | 	FeedbackOrganization              *string | ||||||
| 	SMTPUsername             string | 	EnableSMTPAuth                    *bool | ||||||
| 	SMTPPassword             string | 	SMTPUsername                      string | ||||||
| 	SMTPServer               string | 	SMTPPassword                      string | ||||||
| 	SMTPPort                 string | 	SMTPServer                        string | ||||||
| 	ConnectionSecurity       string | 	SMTPPort                          string | ||||||
| 	InviteSalt               string | 	ConnectionSecurity                string | ||||||
| 	PasswordResetSalt        string | 	InviteSalt                        string | ||||||
| 	SendPushNotifications    *bool | 	SendPushNotifications             *bool | ||||||
| 	PushNotificationServer   *string | 	PushNotificationServer            *string | ||||||
| 	PushNotificationContents *string | 	PushNotificationContents          *string | ||||||
| 	EnableEmailBatching      *bool | 	EnableEmailBatching               *bool | ||||||
| 	EmailBatchingBufferSize  *int | 	EmailBatchingBufferSize           *int | ||||||
| 	EmailBatchingInterval    *int | 	EmailBatchingInterval             *int | ||||||
|  | 	SkipServerCertificateVerification *bool | ||||||
|  | 	EmailNotificationContentsType     *string | ||||||
| } | } | ||||||
|  |  | ||||||
| type RateLimitSettings struct { | type RateLimitSettings struct { | ||||||
| @@ -269,35 +306,48 @@ type PrivacySettings struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type SupportSettings struct { | type SupportSettings struct { | ||||||
| 	TermsOfServiceLink *string | 	TermsOfServiceLink       *string | ||||||
| 	PrivacyPolicyLink  *string | 	PrivacyPolicyLink        *string | ||||||
| 	AboutLink          *string | 	AboutLink                *string | ||||||
| 	HelpLink           *string | 	HelpLink                 *string | ||||||
| 	ReportAProblemLink *string | 	ReportAProblemLink       *string | ||||||
| 	SupportEmail       *string | 	AdministratorsGuideLink  *string | ||||||
|  | 	TroubleshootingForumLink *string | ||||||
|  | 	CommercialSupportLink    *string | ||||||
|  | 	SupportEmail             *string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type AnnouncementSettings struct { | ||||||
|  | 	EnableBanner         *bool | ||||||
|  | 	BannerText           *string | ||||||
|  | 	BannerColor          *string | ||||||
|  | 	BannerTextColor      *string | ||||||
|  | 	AllowBannerDismissal *bool | ||||||
| } | } | ||||||
|  |  | ||||||
| type TeamSettings struct { | type TeamSettings struct { | ||||||
| 	SiteName                         string | 	SiteName                            string | ||||||
| 	MaxUsersPerTeam                  int | 	MaxUsersPerTeam                     int | ||||||
| 	EnableTeamCreation               bool | 	EnableTeamCreation                  bool | ||||||
| 	EnableUserCreation               bool | 	EnableUserCreation                  bool | ||||||
| 	EnableOpenServer                 *bool | 	EnableOpenServer                    *bool | ||||||
| 	RestrictCreationToDomains        string | 	RestrictCreationToDomains           string | ||||||
| 	EnableCustomBrand                *bool | 	EnableCustomBrand                   *bool | ||||||
| 	CustomBrandText                  *string | 	CustomBrandText                     *string | ||||||
| 	CustomDescriptionText            *string | 	CustomDescriptionText               *string | ||||||
| 	RestrictDirectMessage            *string | 	RestrictDirectMessage               *string | ||||||
| 	RestrictTeamInvite               *string | 	RestrictTeamInvite                  *string | ||||||
| 	RestrictPublicChannelManagement  *string | 	RestrictPublicChannelManagement     *string | ||||||
| 	RestrictPrivateChannelManagement *string | 	RestrictPrivateChannelManagement    *string | ||||||
| 	RestrictPublicChannelCreation    *string | 	RestrictPublicChannelCreation       *string | ||||||
| 	RestrictPrivateChannelCreation   *string | 	RestrictPrivateChannelCreation      *string | ||||||
| 	RestrictPublicChannelDeletion    *string | 	RestrictPublicChannelDeletion       *string | ||||||
| 	RestrictPrivateChannelDeletion   *string | 	RestrictPrivateChannelDeletion      *string | ||||||
| 	UserStatusAwayTimeout            *int64 | 	RestrictPrivateChannelManageMembers *string | ||||||
| 	MaxChannelsPerTeam               *int64 | 	UserStatusAwayTimeout               *int64 | ||||||
| 	MaxNotificationsPerChannel       *int64 | 	MaxChannelsPerTeam                  *int64 | ||||||
|  | 	MaxNotificationsPerChannel          *int64 | ||||||
|  | 	TeammateNameDisplay                 *string | ||||||
| } | } | ||||||
|  |  | ||||||
| type LdapSettings struct { | type LdapSettings struct { | ||||||
| @@ -389,29 +439,58 @@ type WebrtcSettings struct { | |||||||
| 	TurnSharedKey       *string | 	TurnSharedKey       *string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type ElasticsearchSettings struct { | ||||||
|  | 	ConnectionUrl     *string | ||||||
|  | 	Username          *string | ||||||
|  | 	Password          *string | ||||||
|  | 	EnableIndexing    *bool | ||||||
|  | 	EnableSearching   *bool | ||||||
|  | 	Sniff             *bool | ||||||
|  | 	PostIndexReplicas *int | ||||||
|  | 	PostIndexShards   *int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type DataRetentionSettings struct { | ||||||
|  | 	Enable *bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type JobSettings struct { | ||||||
|  | 	RunJobs      *bool | ||||||
|  | 	RunScheduler *bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type PluginSettings struct { | ||||||
|  | 	Plugins map[string]interface{} | ||||||
|  | } | ||||||
|  |  | ||||||
| type Config struct { | type Config struct { | ||||||
| 	ServiceSettings      ServiceSettings | 	ServiceSettings       ServiceSettings | ||||||
| 	TeamSettings         TeamSettings | 	TeamSettings          TeamSettings | ||||||
| 	SqlSettings          SqlSettings | 	SqlSettings           SqlSettings | ||||||
| 	LogSettings          LogSettings | 	LogSettings           LogSettings | ||||||
| 	PasswordSettings     PasswordSettings | 	PasswordSettings      PasswordSettings | ||||||
| 	FileSettings         FileSettings | 	FileSettings          FileSettings | ||||||
| 	EmailSettings        EmailSettings | 	EmailSettings         EmailSettings | ||||||
| 	RateLimitSettings    RateLimitSettings | 	RateLimitSettings     RateLimitSettings | ||||||
| 	PrivacySettings      PrivacySettings | 	PrivacySettings       PrivacySettings | ||||||
| 	SupportSettings      SupportSettings | 	SupportSettings       SupportSettings | ||||||
| 	GitLabSettings       SSOSettings | 	AnnouncementSettings  AnnouncementSettings | ||||||
| 	GoogleSettings       SSOSettings | 	GitLabSettings        SSOSettings | ||||||
| 	Office365Settings    SSOSettings | 	GoogleSettings        SSOSettings | ||||||
| 	LdapSettings         LdapSettings | 	Office365Settings     SSOSettings | ||||||
| 	ComplianceSettings   ComplianceSettings | 	LdapSettings          LdapSettings | ||||||
| 	LocalizationSettings LocalizationSettings | 	ComplianceSettings    ComplianceSettings | ||||||
| 	SamlSettings         SamlSettings | 	LocalizationSettings  LocalizationSettings | ||||||
| 	NativeAppSettings    NativeAppSettings | 	SamlSettings          SamlSettings | ||||||
| 	ClusterSettings      ClusterSettings | 	NativeAppSettings     NativeAppSettings | ||||||
| 	MetricsSettings      MetricsSettings | 	ClusterSettings       ClusterSettings | ||||||
| 	AnalyticsSettings    AnalyticsSettings | 	MetricsSettings       MetricsSettings | ||||||
| 	WebrtcSettings       WebrtcSettings | 	AnalyticsSettings     AnalyticsSettings | ||||||
|  | 	WebrtcSettings        WebrtcSettings | ||||||
|  | 	ElasticsearchSettings ElasticsearchSettings | ||||||
|  | 	DataRetentionSettings DataRetentionSettings | ||||||
|  | 	JobSettings           JobSettings | ||||||
|  | 	PluginSettings        PluginSettings | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Config) ToJson() string { | func (o *Config) ToJson() string { | ||||||
| @@ -453,27 +532,52 @@ func (o *Config) SetDefaults() { | |||||||
| 		o.SqlSettings.AtRestEncryptKey = NewRandomString(32) | 		o.SqlSettings.AtRestEncryptKey = NewRandomString(32) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.SqlSettings.QueryTimeout == nil { | ||||||
|  | 		o.SqlSettings.QueryTimeout = new(int) | ||||||
|  | 		*o.SqlSettings.QueryTimeout = 30 | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.FileSettings.AmazonS3Endpoint == "" { | 	if o.FileSettings.AmazonS3Endpoint == "" { | ||||||
| 		// Defaults to "s3.amazonaws.com" | 		// Defaults to "s3.amazonaws.com" | ||||||
| 		o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com" | 		o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.FileSettings.AmazonS3Region == "" { |  | ||||||
| 		// Defaults to "us-east-1" region. |  | ||||||
| 		o.FileSettings.AmazonS3Region = "us-east-1" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.AmazonS3SSL == nil { | 	if o.FileSettings.AmazonS3SSL == nil { | ||||||
| 		o.FileSettings.AmazonS3SSL = new(bool) | 		o.FileSettings.AmazonS3SSL = new(bool) | ||||||
| 		*o.FileSettings.AmazonS3SSL = true // Secure by default. | 		*o.FileSettings.AmazonS3SSL = true // Secure by default. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.FileSettings.AmazonS3SignV2 == nil { | ||||||
|  | 		o.FileSettings.AmazonS3SignV2 = new(bool) | ||||||
|  | 		// Signature v2 is not enabled by default. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.FileSettings.AmazonS3SSE == nil { | ||||||
|  | 		o.FileSettings.AmazonS3SSE = new(bool) | ||||||
|  | 		*o.FileSettings.AmazonS3SSE = false // Not Encrypted by default. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.FileSettings.EnableFileAttachments == nil { | ||||||
|  | 		o.FileSettings.EnableFileAttachments = new(bool) | ||||||
|  | 		*o.FileSettings.EnableFileAttachments = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.FileSettings.EnableMobileUpload == nil { | ||||||
|  | 		o.FileSettings.EnableMobileUpload = new(bool) | ||||||
|  | 		*o.FileSettings.EnableMobileUpload = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.FileSettings.EnableMobileDownload == nil { | ||||||
|  | 		o.FileSettings.EnableMobileDownload = new(bool) | ||||||
|  | 		*o.FileSettings.EnableMobileDownload = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.FileSettings.MaxFileSize == nil { | 	if o.FileSettings.MaxFileSize == nil { | ||||||
| 		o.FileSettings.MaxFileSize = new(int64) | 		o.FileSettings.MaxFileSize = new(int64) | ||||||
| 		*o.FileSettings.MaxFileSize = 52428800 // 50 MB | 		*o.FileSettings.MaxFileSize = 52428800 // 50 MB | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(*o.FileSettings.PublicLinkSalt) == 0 { | 	if o.FileSettings.PublicLinkSalt == nil || len(*o.FileSettings.PublicLinkSalt) == 0 { | ||||||
| 		o.FileSettings.PublicLinkSalt = new(string) | 		o.FileSettings.PublicLinkSalt = new(string) | ||||||
| 		*o.FileSettings.PublicLinkSalt = NewRandomString(32) | 		*o.FileSettings.PublicLinkSalt = NewRandomString(32) | ||||||
| 	} | 	} | ||||||
| @@ -483,12 +587,12 @@ func (o *Config) SetDefaults() { | |||||||
| 		o.FileSettings.InitialFont = "luximbi.ttf" | 		o.FileSettings.InitialFont = "luximbi.ttf" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.EmailSettings.InviteSalt) == 0 { | 	if o.FileSettings.Directory == "" { | ||||||
| 		o.EmailSettings.InviteSalt = NewRandomString(32) | 		o.FileSettings.Directory = "./data/" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.EmailSettings.PasswordResetSalt) == 0 { | 	if len(o.EmailSettings.InviteSalt) == 0 { | ||||||
| 		o.EmailSettings.PasswordResetSalt = NewRandomString(32) | 		o.EmailSettings.InviteSalt = NewRandomString(32) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.ServiceSettings.SiteURL == nil { | 	if o.ServiceSettings.SiteURL == nil { | ||||||
| @@ -496,6 +600,15 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.ServiceSettings.SiteURL = SERVICE_SETTINGS_DEFAULT_SITE_URL | 		*o.ServiceSettings.SiteURL = SERVICE_SETTINGS_DEFAULT_SITE_URL | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.LicenseFileLocation == nil { | ||||||
|  | 		o.ServiceSettings.LicenseFileLocation = new(string) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnableAPIv3 == nil { | ||||||
|  | 		o.ServiceSettings.EnableAPIv3 = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnableAPIv3 = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.ServiceSettings.EnableLinkPreviews == nil { | 	if o.ServiceSettings.EnableLinkPreviews == nil { | ||||||
| 		o.ServiceSettings.EnableLinkPreviews = new(bool) | 		o.ServiceSettings.EnableLinkPreviews = new(bool) | ||||||
| 		*o.ServiceSettings.EnableLinkPreviews = false | 		*o.ServiceSettings.EnableLinkPreviews = false | ||||||
| @@ -526,6 +639,11 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.ServiceSettings.EnforceMultifactorAuthentication = false | 		*o.ServiceSettings.EnforceMultifactorAuthentication = false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnableUserAccessTokens == nil { | ||||||
|  | 		o.ServiceSettings.EnableUserAccessTokens = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnableUserAccessTokens = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.PasswordSettings.MinimumLength == nil { | 	if o.PasswordSettings.MinimumLength == nil { | ||||||
| 		o.PasswordSettings.MinimumLength = new(int) | 		o.PasswordSettings.MinimumLength = new(int) | ||||||
| 		*o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH | 		*o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH | ||||||
| @@ -594,13 +712,21 @@ func (o *Config) SetDefaults() { | |||||||
| 	if o.TeamSettings.RestrictPublicChannelCreation == nil { | 	if o.TeamSettings.RestrictPublicChannelCreation == nil { | ||||||
| 		o.TeamSettings.RestrictPublicChannelCreation = new(string) | 		o.TeamSettings.RestrictPublicChannelCreation = new(string) | ||||||
| 		// If this setting does not exist, assume migration from <3.6, so use management setting as default. | 		// If this setting does not exist, assume migration from <3.6, so use management setting as default. | ||||||
| 		*o.TeamSettings.RestrictPublicChannelCreation = *o.TeamSettings.RestrictPublicChannelManagement | 		if *o.TeamSettings.RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN { | ||||||
|  | 			*o.TeamSettings.RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN | ||||||
|  | 		} else { | ||||||
|  | 			*o.TeamSettings.RestrictPublicChannelCreation = *o.TeamSettings.RestrictPublicChannelManagement | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.TeamSettings.RestrictPrivateChannelCreation == nil { | 	if o.TeamSettings.RestrictPrivateChannelCreation == nil { | ||||||
| 		o.TeamSettings.RestrictPrivateChannelCreation = new(string) | 		o.TeamSettings.RestrictPrivateChannelCreation = new(string) | ||||||
| 		// If this setting does not exist, assume migration from <3.6, so use management setting as default. | 		// If this setting does not exist, assume migration from <3.6, so use management setting as default. | ||||||
| 		*o.TeamSettings.RestrictPrivateChannelCreation = *o.TeamSettings.RestrictPrivateChannelManagement | 		if *o.TeamSettings.RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN { | ||||||
|  | 			*o.TeamSettings.RestrictPrivateChannelCreation = PERMISSIONS_TEAM_ADMIN | ||||||
|  | 		} else { | ||||||
|  | 			*o.TeamSettings.RestrictPrivateChannelCreation = *o.TeamSettings.RestrictPrivateChannelManagement | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.TeamSettings.RestrictPublicChannelDeletion == nil { | 	if o.TeamSettings.RestrictPublicChannelDeletion == nil { | ||||||
| @@ -615,6 +741,11 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.TeamSettings.RestrictPrivateChannelDeletion = *o.TeamSettings.RestrictPrivateChannelManagement | 		*o.TeamSettings.RestrictPrivateChannelDeletion = *o.TeamSettings.RestrictPrivateChannelManagement | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.TeamSettings.RestrictPrivateChannelManageMembers == nil { | ||||||
|  | 		o.TeamSettings.RestrictPrivateChannelManageMembers = new(string) | ||||||
|  | 		*o.TeamSettings.RestrictPrivateChannelManageMembers = PERMISSIONS_ALL | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.TeamSettings.UserStatusAwayTimeout == nil { | 	if o.TeamSettings.UserStatusAwayTimeout == nil { | ||||||
| 		o.TeamSettings.UserStatusAwayTimeout = new(int64) | 		o.TeamSettings.UserStatusAwayTimeout = new(int64) | ||||||
| 		*o.TeamSettings.UserStatusAwayTimeout = TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT | 		*o.TeamSettings.UserStatusAwayTimeout = TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT | ||||||
| @@ -680,8 +811,31 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.EmailSettings.EmailBatchingInterval = EMAIL_BATCHING_INTERVAL | 		*o.EmailSettings.EmailBatchingInterval = EMAIL_BATCHING_INTERVAL | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.EmailSettings.EnableSMTPAuth == nil { | ||||||
|  | 		o.EmailSettings.EnableSMTPAuth = new(bool) | ||||||
|  | 		if o.EmailSettings.ConnectionSecurity == CONN_SECURITY_NONE { | ||||||
|  | 			*o.EmailSettings.EnableSMTPAuth = false | ||||||
|  | 		} else { | ||||||
|  | 			*o.EmailSettings.EnableSMTPAuth = true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.EmailSettings.ConnectionSecurity == CONN_SECURITY_PLAIN { | ||||||
|  | 		o.EmailSettings.ConnectionSecurity = CONN_SECURITY_NONE | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.EmailSettings.SkipServerCertificateVerification == nil { | ||||||
|  | 		o.EmailSettings.SkipServerCertificateVerification = new(bool) | ||||||
|  | 		*o.EmailSettings.SkipServerCertificateVerification = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.EmailSettings.EmailNotificationContentsType == nil { | ||||||
|  | 		o.EmailSettings.EmailNotificationContentsType = new(string) | ||||||
|  | 		*o.EmailSettings.EmailNotificationContentsType = EMAIL_NOTIFICATION_CONTENTS_FULL | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if !IsSafeLink(o.SupportSettings.TermsOfServiceLink) { | 	if !IsSafeLink(o.SupportSettings.TermsOfServiceLink) { | ||||||
| 		o.SupportSettings.TermsOfServiceLink = nil | 		*o.SupportSettings.TermsOfServiceLink = SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.TermsOfServiceLink == nil { | 	if o.SupportSettings.TermsOfServiceLink == nil { | ||||||
| @@ -690,7 +844,7 @@ func (o *Config) SetDefaults() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !IsSafeLink(o.SupportSettings.PrivacyPolicyLink) { | 	if !IsSafeLink(o.SupportSettings.PrivacyPolicyLink) { | ||||||
| 		o.SupportSettings.PrivacyPolicyLink = nil | 		*o.SupportSettings.PrivacyPolicyLink = "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.PrivacyPolicyLink == nil { | 	if o.SupportSettings.PrivacyPolicyLink == nil { | ||||||
| @@ -699,7 +853,7 @@ func (o *Config) SetDefaults() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !IsSafeLink(o.SupportSettings.AboutLink) { | 	if !IsSafeLink(o.SupportSettings.AboutLink) { | ||||||
| 		o.SupportSettings.AboutLink = nil | 		*o.SupportSettings.AboutLink = "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.AboutLink == nil { | 	if o.SupportSettings.AboutLink == nil { | ||||||
| @@ -708,7 +862,7 @@ func (o *Config) SetDefaults() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !IsSafeLink(o.SupportSettings.HelpLink) { | 	if !IsSafeLink(o.SupportSettings.HelpLink) { | ||||||
| 		o.SupportSettings.HelpLink = nil | 		*o.SupportSettings.HelpLink = "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.HelpLink == nil { | 	if o.SupportSettings.HelpLink == nil { | ||||||
| @@ -717,7 +871,7 @@ func (o *Config) SetDefaults() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !IsSafeLink(o.SupportSettings.ReportAProblemLink) { | 	if !IsSafeLink(o.SupportSettings.ReportAProblemLink) { | ||||||
| 		o.SupportSettings.ReportAProblemLink = nil | 		*o.SupportSettings.ReportAProblemLink = "" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.ReportAProblemLink == nil { | 	if o.SupportSettings.ReportAProblemLink == nil { | ||||||
| @@ -725,11 +879,63 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.SupportSettings.ReportAProblemLink = SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK | 		*o.SupportSettings.ReportAProblemLink = SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if !IsSafeLink(o.SupportSettings.AdministratorsGuideLink) { | ||||||
|  | 		*o.SupportSettings.AdministratorsGuideLink = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.SupportSettings.AdministratorsGuideLink == nil { | ||||||
|  | 		o.SupportSettings.AdministratorsGuideLink = new(string) | ||||||
|  | 		*o.SupportSettings.AdministratorsGuideLink = SUPPORT_SETTINGS_DEFAULT_ADMINISTRATORS_GUIDE_LINK | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !IsSafeLink(o.SupportSettings.TroubleshootingForumLink) { | ||||||
|  | 		*o.SupportSettings.TroubleshootingForumLink = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.SupportSettings.TroubleshootingForumLink == nil { | ||||||
|  | 		o.SupportSettings.TroubleshootingForumLink = new(string) | ||||||
|  | 		*o.SupportSettings.TroubleshootingForumLink = SUPPORT_SETTINGS_DEFAULT_TROUBLESHOOTING_FORUM_LINK | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !IsSafeLink(o.SupportSettings.CommercialSupportLink) { | ||||||
|  | 		*o.SupportSettings.CommercialSupportLink = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.SupportSettings.CommercialSupportLink == nil { | ||||||
|  | 		o.SupportSettings.CommercialSupportLink = new(string) | ||||||
|  | 		*o.SupportSettings.CommercialSupportLink = SUPPORT_SETTINGS_DEFAULT_COMMERCIAL_SUPPORT_LINK | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.SupportSettings.SupportEmail == nil { | 	if o.SupportSettings.SupportEmail == nil { | ||||||
| 		o.SupportSettings.SupportEmail = new(string) | 		o.SupportSettings.SupportEmail = new(string) | ||||||
| 		*o.SupportSettings.SupportEmail = SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL | 		*o.SupportSettings.SupportEmail = SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.AnnouncementSettings.EnableBanner == nil { | ||||||
|  | 		o.AnnouncementSettings.EnableBanner = new(bool) | ||||||
|  | 		*o.AnnouncementSettings.EnableBanner = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.AnnouncementSettings.BannerText == nil { | ||||||
|  | 		o.AnnouncementSettings.BannerText = new(string) | ||||||
|  | 		*o.AnnouncementSettings.BannerText = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.AnnouncementSettings.BannerColor == nil { | ||||||
|  | 		o.AnnouncementSettings.BannerColor = new(string) | ||||||
|  | 		*o.AnnouncementSettings.BannerColor = ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.AnnouncementSettings.BannerTextColor == nil { | ||||||
|  | 		o.AnnouncementSettings.BannerTextColor = new(string) | ||||||
|  | 		*o.AnnouncementSettings.BannerTextColor = ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.AnnouncementSettings.AllowBannerDismissal == nil { | ||||||
|  | 		o.AnnouncementSettings.AllowBannerDismissal = new(bool) | ||||||
|  | 		*o.AnnouncementSettings.AllowBannerDismissal = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.LdapSettings.Enable == nil { | 	if o.LdapSettings.Enable == nil { | ||||||
| 		o.LdapSettings.Enable = new(bool) | 		o.LdapSettings.Enable = new(bool) | ||||||
| 		*o.LdapSettings.Enable = false | 		*o.LdapSettings.Enable = false | ||||||
| @@ -884,7 +1090,12 @@ func (o *Config) SetDefaults() { | |||||||
|  |  | ||||||
| 	if o.ServiceSettings.EnableCustomEmoji == nil { | 	if o.ServiceSettings.EnableCustomEmoji == nil { | ||||||
| 		o.ServiceSettings.EnableCustomEmoji = new(bool) | 		o.ServiceSettings.EnableCustomEmoji = new(bool) | ||||||
| 		*o.ServiceSettings.EnableCustomEmoji = true | 		*o.ServiceSettings.EnableCustomEmoji = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnableEmojiPicker == nil { | ||||||
|  | 		o.ServiceSettings.EnableEmojiPicker = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnableEmojiPicker = true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.ServiceSettings.RestrictCustomEmojiCreation == nil { | 	if o.ServiceSettings.RestrictCustomEmojiCreation == nil { | ||||||
| @@ -907,18 +1118,44 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.ServiceSettings.PostEditTimeLimit = 300 | 		*o.ServiceSettings.PostEditTimeLimit = 300 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.ClusterSettings.InterNodeListenAddress == nil { |  | ||||||
| 		o.ClusterSettings.InterNodeListenAddress = new(string) |  | ||||||
| 		*o.ClusterSettings.InterNodeListenAddress = ":8075" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.ClusterSettings.Enable == nil { | 	if o.ClusterSettings.Enable == nil { | ||||||
| 		o.ClusterSettings.Enable = new(bool) | 		o.ClusterSettings.Enable = new(bool) | ||||||
| 		*o.ClusterSettings.Enable = false | 		*o.ClusterSettings.Enable = false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.ClusterSettings.InterNodeUrls == nil { | 	if o.ClusterSettings.ClusterName == nil { | ||||||
| 		o.ClusterSettings.InterNodeUrls = []string{} | 		o.ClusterSettings.ClusterName = new(string) | ||||||
|  | 		*o.ClusterSettings.ClusterName = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.OverrideHostname == nil { | ||||||
|  | 		o.ClusterSettings.OverrideHostname = new(string) | ||||||
|  | 		*o.ClusterSettings.OverrideHostname = "" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.UseIpAddress == nil { | ||||||
|  | 		o.ClusterSettings.UseIpAddress = new(bool) | ||||||
|  | 		*o.ClusterSettings.UseIpAddress = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.UseExperimentalGossip == nil { | ||||||
|  | 		o.ClusterSettings.UseExperimentalGossip = new(bool) | ||||||
|  | 		*o.ClusterSettings.UseExperimentalGossip = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.ReadOnlyConfig == nil { | ||||||
|  | 		o.ClusterSettings.ReadOnlyConfig = new(bool) | ||||||
|  | 		*o.ClusterSettings.ReadOnlyConfig = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.GossipPort == nil { | ||||||
|  | 		o.ClusterSettings.GossipPort = new(int) | ||||||
|  | 		*o.ClusterSettings.GossipPort = 8074 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ClusterSettings.StreamingPort == nil { | ||||||
|  | 		o.ClusterSettings.StreamingPort = new(int) | ||||||
|  | 		*o.ClusterSettings.StreamingPort = 8075 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.MetricsSettings.ListenAddress == nil { | 	if o.MetricsSettings.ListenAddress == nil { | ||||||
| @@ -978,12 +1215,12 @@ func (o *Config) SetDefaults() { | |||||||
|  |  | ||||||
| 	if o.SamlSettings.Verify == nil { | 	if o.SamlSettings.Verify == nil { | ||||||
| 		o.SamlSettings.Verify = new(bool) | 		o.SamlSettings.Verify = new(bool) | ||||||
| 		*o.SamlSettings.Verify = false | 		*o.SamlSettings.Verify = true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SamlSettings.Encrypt == nil { | 	if o.SamlSettings.Encrypt == nil { | ||||||
| 		o.SamlSettings.Encrypt = new(bool) | 		o.SamlSettings.Encrypt = new(bool) | ||||||
| 		*o.SamlSettings.Encrypt = false | 		*o.SamlSettings.Encrypt = true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.SamlSettings.IdpUrl == nil { | 	if o.SamlSettings.IdpUrl == nil { | ||||||
| @@ -1056,6 +1293,15 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.SamlSettings.LocaleAttribute = SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE | 		*o.SamlSettings.LocaleAttribute = SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.TeamSettings.TeammateNameDisplay == nil { | ||||||
|  | 		o.TeamSettings.TeammateNameDisplay = new(string) | ||||||
|  | 		*o.TeamSettings.TeammateNameDisplay = SHOW_USERNAME | ||||||
|  |  | ||||||
|  | 		if *o.SamlSettings.Enable || *o.LdapSettings.Enable { | ||||||
|  | 			*o.TeamSettings.TeammateNameDisplay = SHOW_FULLNAME | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.NativeAppSettings.AppDownloadLink == nil { | 	if o.NativeAppSettings.AppDownloadLink == nil { | ||||||
| 		o.NativeAppSettings.AppDownloadLink = new(string) | 		o.NativeAppSettings.AppDownloadLink = new(string) | ||||||
| 		*o.NativeAppSettings.AppDownloadLink = NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK | 		*o.NativeAppSettings.AppDownloadLink = NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK | ||||||
| @@ -1076,6 +1322,11 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.RateLimitSettings.Enable = false | 		*o.RateLimitSettings.Enable = false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.GoroutineHealthThreshold == nil { | ||||||
|  | 		o.ServiceSettings.GoroutineHealthThreshold = new(int) | ||||||
|  | 		*o.ServiceSettings.GoroutineHealthThreshold = -1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.RateLimitSettings.MaxBurst == nil { | 	if o.RateLimitSettings.MaxBurst == nil { | ||||||
| 		o.RateLimitSettings.MaxBurst = new(int) | 		o.RateLimitSettings.MaxBurst = new(int) | ||||||
| 		*o.RateLimitSettings.MaxBurst = 100 | 		*o.RateLimitSettings.MaxBurst = 100 | ||||||
| @@ -1131,16 +1382,90 @@ func (o *Config) SetDefaults() { | |||||||
| 		*o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = 5000 | 		*o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = 5000 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnablePostSearch == nil { | ||||||
|  | 		o.ServiceSettings.EnablePostSearch = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnablePostSearch = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.ServiceSettings.EnableUserTypingMessages == nil { | 	if o.ServiceSettings.EnableUserTypingMessages == nil { | ||||||
| 		o.ServiceSettings.EnableUserTypingMessages = new(bool) | 		o.ServiceSettings.EnableUserTypingMessages = new(bool) | ||||||
| 		*o.ServiceSettings.EnableUserTypingMessages = true | 		*o.ServiceSettings.EnableUserTypingMessages = true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnableChannelViewedMessages == nil { | ||||||
|  | 		o.ServiceSettings.EnableChannelViewedMessages = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnableChannelViewedMessages = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ServiceSettings.EnableUserStatuses == nil { | ||||||
|  | 		o.ServiceSettings.EnableUserStatuses = new(bool) | ||||||
|  | 		*o.ServiceSettings.EnableUserStatuses = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.ServiceSettings.ClusterLogTimeoutMilliseconds == nil { | 	if o.ServiceSettings.ClusterLogTimeoutMilliseconds == nil { | ||||||
| 		o.ServiceSettings.ClusterLogTimeoutMilliseconds = new(int) | 		o.ServiceSettings.ClusterLogTimeoutMilliseconds = new(int) | ||||||
| 		*o.ServiceSettings.ClusterLogTimeoutMilliseconds = 2000 | 		*o.ServiceSettings.ClusterLogTimeoutMilliseconds = 2000 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.ConnectionUrl == nil { | ||||||
|  | 		o.ElasticsearchSettings.ConnectionUrl = new(string) | ||||||
|  | 		*o.ElasticsearchSettings.ConnectionUrl = ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.Username == nil { | ||||||
|  | 		o.ElasticsearchSettings.Username = new(string) | ||||||
|  | 		*o.ElasticsearchSettings.Username = ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.Password == nil { | ||||||
|  | 		o.ElasticsearchSettings.Password = new(string) | ||||||
|  | 		*o.ElasticsearchSettings.Password = ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.EnableIndexing == nil { | ||||||
|  | 		o.ElasticsearchSettings.EnableIndexing = new(bool) | ||||||
|  | 		*o.ElasticsearchSettings.EnableIndexing = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.EnableSearching == nil { | ||||||
|  | 		o.ElasticsearchSettings.EnableSearching = new(bool) | ||||||
|  | 		*o.ElasticsearchSettings.EnableSearching = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.Sniff == nil { | ||||||
|  | 		o.ElasticsearchSettings.Sniff = new(bool) | ||||||
|  | 		*o.ElasticsearchSettings.Sniff = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.PostIndexReplicas == nil { | ||||||
|  | 		o.ElasticsearchSettings.PostIndexReplicas = new(int) | ||||||
|  | 		*o.ElasticsearchSettings.PostIndexReplicas = ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.ElasticsearchSettings.PostIndexShards == nil { | ||||||
|  | 		o.ElasticsearchSettings.PostIndexShards = new(int) | ||||||
|  | 		*o.ElasticsearchSettings.PostIndexShards = ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.DataRetentionSettings.Enable == nil { | ||||||
|  | 		o.DataRetentionSettings.Enable = new(bool) | ||||||
|  | 		*o.DataRetentionSettings.Enable = false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.JobSettings.RunJobs == nil { | ||||||
|  | 		o.JobSettings.RunJobs = new(bool) | ||||||
|  | 		*o.JobSettings.RunJobs = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.JobSettings.RunScheduler == nil { | ||||||
|  | 		o.JobSettings.RunScheduler = new(bool) | ||||||
|  | 		*o.JobSettings.RunScheduler = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if o.PluginSettings.Plugins == nil { | ||||||
|  | 		o.PluginSettings.Plugins = make(map[string]interface{}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	o.defaultWebrtcSettings() | 	o.defaultWebrtcSettings() | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1184,6 +1509,10 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if !(*o.TeamSettings.TeammateNameDisplay == SHOW_FULLNAME || *o.TeamSettings.TeammateNameDisplay == SHOW_NICKNAME_FULLNAME || *o.TeamSettings.TeammateNameDisplay == SHOW_USERNAME) { | ||||||
|  | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.teammate_name_display.app_error", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if len(o.SqlSettings.AtRestEncryptKey) < 32 { | 	if len(o.SqlSettings.AtRestEncryptKey) < 32 { | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
| @@ -1196,6 +1525,10 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if *o.SqlSettings.QueryTimeout <= 0 { | ||||||
|  | 		return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if len(o.SqlSettings.DataSource) == 0 { | 	if len(o.SqlSettings.DataSource) == 0 { | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
| @@ -1212,30 +1545,6 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.FileSettings.PreviewHeight < 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_preview_height.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.PreviewWidth <= 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_preview_width.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.ProfileHeight <= 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_profile_height.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.ProfileWidth <= 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_profile_width.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.ThumbnailHeight <= 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_thumb_height.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if o.FileSettings.ThumbnailWidth <= 0 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_thumb_width.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(*o.FileSettings.PublicLinkSalt) < 32 { | 	if len(*o.FileSettings.PublicLinkSalt) < 32 { | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
| @@ -1248,10 +1557,6 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_salt.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_salt.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.EmailSettings.PasswordResetSalt) < 32 { |  | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_reset_salt.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if *o.EmailSettings.EmailBatchingBufferSize <= 0 { | 	if *o.EmailSettings.EmailBatchingBufferSize <= 0 { | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
| @@ -1260,6 +1565,10 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if !(*o.EmailSettings.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_FULL || *o.EmailSettings.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_GENERIC) { | ||||||
|  | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.email_notification_contents_type.app_error", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if o.RateLimitSettings.MemoryStoreSize <= 0 { | 	if o.RateLimitSettings.MemoryStoreSize <= 0 { | ||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.rate_mem.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.rate_mem.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
| @@ -1376,6 +1685,16 @@ func (o *Config) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "") | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if *o.ElasticsearchSettings.EnableIndexing { | ||||||
|  | 		if len(*o.ElasticsearchSettings.ConnectionUrl) == 0 { | ||||||
|  | 			return NewLocAppError("Config.IsValid", "model.config.is_valid.elastic_search.connection_url.app_error", nil, "") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if *o.ElasticsearchSettings.EnableSearching && !*o.ElasticsearchSettings.EnableIndexing { | ||||||
|  | 		return NewLocAppError("Config.IsValid", "model.config.is_valid.elastic_search.enable_searching.app_error", nil, "") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1398,7 +1717,6 @@ func (o *Config) Sanitize() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.EmailSettings.InviteSalt = FAKE_SETTING | 	o.EmailSettings.InviteSalt = FAKE_SETTING | ||||||
| 	o.EmailSettings.PasswordResetSalt = FAKE_SETTING |  | ||||||
| 	if len(o.EmailSettings.SMTPPassword) > 0 { | 	if len(o.EmailSettings.SMTPPassword) > 0 { | ||||||
| 		o.EmailSettings.SMTPPassword = FAKE_SETTING | 		o.EmailSettings.SMTPPassword = FAKE_SETTING | ||||||
| 	} | 	} | ||||||
| @@ -1413,6 +1731,12 @@ func (o *Config) Sanitize() { | |||||||
| 	for i := range o.SqlSettings.DataSourceReplicas { | 	for i := range o.SqlSettings.DataSourceReplicas { | ||||||
| 		o.SqlSettings.DataSourceReplicas[i] = FAKE_SETTING | 		o.SqlSettings.DataSourceReplicas[i] = FAKE_SETTING | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	for i := range o.SqlSettings.DataSourceSearchReplicas { | ||||||
|  | 		o.SqlSettings.DataSourceSearchReplicas[i] = FAKE_SETTING | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*o.ElasticsearchSettings.Password = FAKE_SETTING | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Config) defaultWebrtcSettings() { | func (o *Config) defaultWebrtcSettings() { | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								vendor/github.com/mattermost/platform/model/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattermost/platform/model/emoji.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -34,7 +34,7 @@ func (emoji *Emoji) IsValid() *AppError { | |||||||
| 		return NewLocAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "") | 		return NewLocAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(emoji.Name) == 0 || len(emoji.Name) > 64 { | 	if len(emoji.Name) == 0 || len(emoji.Name) > 64 || !IsValidAlphaNumHyphenUnderscore(emoji.Name, false) { | ||||||
| 		return NewLocAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "") | 		return NewLocAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/file_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/file_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/gitlab.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/gitlab.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/gitlab/gitlab.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/gitlab/gitlab.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package oauthgitlab | package oauthgitlab | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								vendor/github.com/mattermost/platform/model/incoming_webhook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								vendor/github.com/mattermost/platform/model/incoming_webhook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -6,10 +6,9 @@ package model | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"strings" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -81,35 +80,36 @@ func IncomingWebhookListFromJson(data io.Reader) []*IncomingWebhook { | |||||||
| func (o *IncomingWebhook) IsValid() *AppError { | func (o *IncomingWebhook) IsValid() *AppError { | ||||||
|  |  | ||||||
| 	if len(o.Id) != 26 { | 	if len(o.Id) != 26 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", nil, "", http.StatusBadRequest) | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.CreateAt == 0 { | 	if o.CreateAt == 0 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.create_at.app_error", nil, "id="+o.Id) | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.UpdateAt == 0 { | 	if o.UpdateAt == 0 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.update_at.app_error", nil, "id="+o.Id) | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.UserId) != 26 { | 	if len(o.UserId) != 26 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.user_id.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.user_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.ChannelId) != 26 { | 	if len(o.ChannelId) != 26 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.channel_id.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.channel_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.TeamId) != 26 { | 	if len(o.TeamId) != 26 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.team_id.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.team_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.DisplayName) > 64 { | 	if len(o.DisplayName) > 64 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.display_name.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.display_name.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.Description) > 128 { | 	if len(o.Description) > 128 { | ||||||
| 		return NewLocAppError("IncomingWebhook.IsValid", "model.incoming_hook.description.app_error", nil, "") | 		return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.description.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @@ -193,39 +193,6 @@ func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // To mention @channel via a webhook in Slack, the message should contain |  | ||||||
| // <!channel>, as explained at the bottom of this article: |  | ||||||
| // https://get.slack.help/hc/en-us/articles/202009646-Making-announcements |  | ||||||
| func expandAnnouncement(text string) string { |  | ||||||
| 	c1 := "<!channel>" |  | ||||||
| 	c2 := "@channel" |  | ||||||
| 	if strings.Contains(text, c1) { |  | ||||||
| 		return strings.Replace(text, c1, c2, -1) |  | ||||||
| 	} |  | ||||||
| 	return text |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Expand announcements in incoming webhooks from Slack. Those announcements |  | ||||||
| // can be found in the text attribute, or in the pretext, text, title and value |  | ||||||
| // attributes of the attachment structure. The Slack attachment structure is |  | ||||||
| // documented here: https://api.slack.com/docs/attachments |  | ||||||
| func expandAnnouncements(i *IncomingWebhookRequest) { |  | ||||||
| 	i.Text = expandAnnouncement(i.Text) |  | ||||||
|  |  | ||||||
| 	for _, attachment := range i.Attachments { |  | ||||||
| 		attachment.Pretext = expandAnnouncement(attachment.Pretext) |  | ||||||
| 		attachment.Text = expandAnnouncement(attachment.Text) |  | ||||||
| 		attachment.Title = expandAnnouncement(attachment.Title) |  | ||||||
|  |  | ||||||
| 		for _, field := range attachment.Fields { |  | ||||||
| 			if field.Value != nil { |  | ||||||
| 				// Ensure the value is set to a string if it is set |  | ||||||
| 				field.Value = expandAnnouncement(fmt.Sprintf("%v", field.Value)) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { | func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { | ||||||
| 	buf := new(bytes.Buffer) | 	buf := new(bytes.Buffer) | ||||||
| 	buf.ReadFrom(data) | 	buf.ReadFrom(data) | ||||||
| @@ -241,7 +208,8 @@ func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	expandAnnouncements(o) | 	o.Text = ExpandAnnouncement(o.Text) | ||||||
|  | 	o.Attachments = ProcessSlackAttachments(o.Attachments) | ||||||
|  |  | ||||||
| 	return o | 	return o | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/initial_load.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/initial_load.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										159
									
								
								vendor/github.com/mattermost/platform/model/job.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/mattermost/platform/model/job.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,100 +1,117 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"encoding/json" | ||||||
| 	"time" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type TaskFunc func() | const ( | ||||||
|  | 	JOB_TYPE_DATA_RETENTION              = "data_retention" | ||||||
|  | 	JOB_TYPE_ELASTICSEARCH_POST_INDEXING = "elasticsearch_post_indexing" | ||||||
|  |  | ||||||
| type ScheduledTask struct { | 	JOB_STATUS_PENDING          = "pending" | ||||||
| 	Name      string        `json:"name"` | 	JOB_STATUS_IN_PROGRESS      = "in_progress" | ||||||
| 	Interval  time.Duration `json:"interval"` | 	JOB_STATUS_SUCCESS          = "success" | ||||||
| 	Recurring bool          `json:"recurring"` | 	JOB_STATUS_ERROR            = "error" | ||||||
| 	function  TaskFunc | 	JOB_STATUS_CANCEL_REQUESTED = "cancel_requested" | ||||||
| 	timer     *time.Timer | 	JOB_STATUS_CANCELED         = "canceled" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Job struct { | ||||||
|  | 	Id             string                 `json:"id"` | ||||||
|  | 	Type           string                 `json:"type"` | ||||||
|  | 	Priority       int64                  `json:"priority"` | ||||||
|  | 	CreateAt       int64                  `json:"create_at"` | ||||||
|  | 	StartAt        int64                  `json:"start_at"` | ||||||
|  | 	LastActivityAt int64                  `json:"last_activity_at"` | ||||||
|  | 	Status         string                 `json:"status"` | ||||||
|  | 	Progress       int64                  `json:"progress"` | ||||||
|  | 	Data           map[string]interface{} `json:"data"` | ||||||
| } | } | ||||||
|  |  | ||||||
| var tasks = make(map[string]*ScheduledTask) | func (j *Job) IsValid() *AppError { | ||||||
|  | 	if len(j.Id) != 26 { | ||||||
| func addTask(task *ScheduledTask) { | 		return NewAppError("Job.IsValid", "model.job.is_valid.id.app_error", nil, "id="+j.Id, http.StatusBadRequest) | ||||||
| 	tasks[task.Name] = task |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func removeTaskByName(name string) { |  | ||||||
| 	delete(tasks, name) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func GetTaskByName(name string) *ScheduledTask { |  | ||||||
| 	if task, ok := tasks[name]; ok { |  | ||||||
| 		return task |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if j.CreateAt == 0 { | ||||||
|  | 		return NewAppError("Job.IsValid", "model.job.is_valid.create_at.app_error", nil, "id="+j.Id, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch j.Type { | ||||||
|  | 	case JOB_TYPE_DATA_RETENTION: | ||||||
|  | 	case JOB_TYPE_ELASTICSEARCH_POST_INDEXING: | ||||||
|  | 	default: | ||||||
|  | 		return NewAppError("Job.IsValid", "model.job.is_valid.type.app_error", nil, "id="+j.Id, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch j.Status { | ||||||
|  | 	case JOB_STATUS_PENDING: | ||||||
|  | 	case JOB_STATUS_IN_PROGRESS: | ||||||
|  | 	case JOB_STATUS_SUCCESS: | ||||||
|  | 	case JOB_STATUS_ERROR: | ||||||
|  | 	case JOB_STATUS_CANCEL_REQUESTED: | ||||||
|  | 	case JOB_STATUS_CANCELED: | ||||||
|  | 	default: | ||||||
|  | 		return NewAppError("Job.IsValid", "model.job.is_valid.status.app_error", nil, "id="+j.Id, http.StatusBadRequest) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func GetAllTasks() *map[string]*ScheduledTask { | func (js *Job) ToJson() string { | ||||||
| 	return &tasks | 	if b, err := json.Marshal(js); err != nil { | ||||||
| } | 		return "" | ||||||
|  | 	} else { | ||||||
| func CreateTask(name string, function TaskFunc, timeToExecution time.Duration) *ScheduledTask { | 		return string(b) | ||||||
| 	task := &ScheduledTask{ |  | ||||||
| 		Name:      name, |  | ||||||
| 		Interval:  timeToExecution, |  | ||||||
| 		Recurring: false, |  | ||||||
| 		function:  function, |  | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| 	taskRunner := func() { | func JobFromJson(data io.Reader) *Job { | ||||||
| 		go task.function() | 	var job Job | ||||||
| 		removeTaskByName(task.Name) | 	if err := json.NewDecoder(data).Decode(&job); err == nil { | ||||||
|  | 		return &job | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	task.timer = time.AfterFunc(timeToExecution, taskRunner) |  | ||||||
|  |  | ||||||
| 	addTask(task) |  | ||||||
|  |  | ||||||
| 	return task |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func CreateRecurringTask(name string, function TaskFunc, interval time.Duration) *ScheduledTask { | func JobsToJson(jobs []*Job) string { | ||||||
| 	task := &ScheduledTask{ | 	if b, err := json.Marshal(jobs); err != nil { | ||||||
| 		Name:      name, | 		return "" | ||||||
| 		Interval:  interval, | 	} else { | ||||||
| 		Recurring: true, | 		return string(b) | ||||||
| 		function:  function, |  | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| 	taskRecurer := func() { | func JobsFromJson(data io.Reader) []*Job { | ||||||
| 		go task.function() | 	var jobs []*Job | ||||||
| 		task.timer.Reset(task.Interval) | 	if err := json.NewDecoder(data).Decode(&jobs); err == nil { | ||||||
|  | 		return jobs | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	task.timer = time.AfterFunc(interval, taskRecurer) |  | ||||||
|  |  | ||||||
| 	addTask(task) |  | ||||||
|  |  | ||||||
| 	return task |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (task *ScheduledTask) Cancel() { | func (js *Job) DataToJson() string { | ||||||
| 	task.timer.Stop() | 	if b, err := json.Marshal(js.Data); err != nil { | ||||||
| 	removeTaskByName(task.Name) | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Executes the task immediatly. A recurring task will be run regularally after interval. | type Worker interface { | ||||||
| func (task *ScheduledTask) Execute() { | 	Run() | ||||||
| 	task.function() | 	Stop() | ||||||
| 	task.timer.Reset(task.Interval) | 	JobChannel() chan<- Job | ||||||
| } | } | ||||||
|  |  | ||||||
| func (task *ScheduledTask) String() string { | type Scheduler interface { | ||||||
| 	return fmt.Sprintf( | 	Run() | ||||||
| 		"%s\nInterval: %s\nRecurring: %t\n", | 	Stop() | ||||||
| 		task.Name, |  | ||||||
| 		task.Interval.String(), |  | ||||||
| 		task.Recurring, |  | ||||||
| 	) |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/mattermost/platform/model/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattermost/platform/model/ldap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
|   | |||||||
							
								
								
									
										71
									
								
								vendor/github.com/mattermost/platform/model/license.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/mattermost/platform/model/license.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -37,36 +37,42 @@ type Customer struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type Features struct { | type Features struct { | ||||||
| 	Users                *int  `json:"users"` | 	Users                     *int  `json:"users"` | ||||||
| 	LDAP                 *bool `json:"ldap"` | 	LDAP                      *bool `json:"ldap"` | ||||||
| 	MFA                  *bool `json:"mfa"` | 	MFA                       *bool `json:"mfa"` | ||||||
| 	GoogleOAuth          *bool `json:"google_oauth"` | 	GoogleOAuth               *bool `json:"google_oauth"` | ||||||
| 	Office365OAuth       *bool `json:"office365_oauth"` | 	Office365OAuth            *bool `json:"office365_oauth"` | ||||||
| 	Compliance           *bool `json:"compliance"` | 	Compliance                *bool `json:"compliance"` | ||||||
| 	Cluster              *bool `json:"cluster"` | 	Cluster                   *bool `json:"cluster"` | ||||||
| 	Metrics              *bool `json:"metrics"` | 	Metrics                   *bool `json:"metrics"` | ||||||
| 	CustomBrand          *bool `json:"custom_brand"` | 	CustomBrand               *bool `json:"custom_brand"` | ||||||
| 	MHPNS                *bool `json:"mhpns"` | 	MHPNS                     *bool `json:"mhpns"` | ||||||
| 	SAML                 *bool `json:"saml"` | 	SAML                      *bool `json:"saml"` | ||||||
| 	PasswordRequirements *bool `json:"password_requirements"` | 	PasswordRequirements      *bool `json:"password_requirements"` | ||||||
|  | 	Elasticsearch             *bool `json:"elastic_search"` | ||||||
|  | 	Announcement              *bool `json:"announcement"` | ||||||
|  | 	EmailNotificationContents *bool `json:"email_notification_contents"` | ||||||
|  |  | ||||||
| 	// after we enabled more features for webrtc we'll need to control them with this | 	// after we enabled more features for webrtc we'll need to control them with this | ||||||
| 	FutureFeatures *bool `json:"future_features"` | 	FutureFeatures *bool `json:"future_features"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (f *Features) ToMap() map[string]interface{} { | func (f *Features) ToMap() map[string]interface{} { | ||||||
| 	return map[string]interface{}{ | 	return map[string]interface{}{ | ||||||
| 		"ldap":         *f.LDAP, | 		"ldap":                        *f.LDAP, | ||||||
| 		"mfa":          *f.MFA, | 		"mfa":                         *f.MFA, | ||||||
| 		"google":       *f.GoogleOAuth, | 		"google":                      *f.GoogleOAuth, | ||||||
| 		"office365":    *f.Office365OAuth, | 		"office365":                   *f.Office365OAuth, | ||||||
| 		"compliance":   *f.Compliance, | 		"compliance":                  *f.Compliance, | ||||||
| 		"cluster":      *f.Cluster, | 		"cluster":                     *f.Cluster, | ||||||
| 		"metrics":      *f.Metrics, | 		"metrics":                     *f.Metrics, | ||||||
| 		"custom_brand": *f.CustomBrand, | 		"custom_brand":                *f.CustomBrand, | ||||||
| 		"mhpns":        *f.MHPNS, | 		"mhpns":                       *f.MHPNS, | ||||||
| 		"saml":         *f.SAML, | 		"saml":                        *f.SAML, | ||||||
| 		"password":     *f.PasswordRequirements, | 		"password":                    *f.PasswordRequirements, | ||||||
| 		"future":       *f.FutureFeatures, | 		"elastic_search":              *f.Elasticsearch, | ||||||
|  | 		"email_notification_contents": *f.EmailNotificationContents, | ||||||
|  | 		"future":                      *f.FutureFeatures, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -135,6 +141,21 @@ func (f *Features) SetDefaults() { | |||||||
| 		f.PasswordRequirements = new(bool) | 		f.PasswordRequirements = new(bool) | ||||||
| 		*f.PasswordRequirements = *f.FutureFeatures | 		*f.PasswordRequirements = *f.FutureFeatures | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if f.Elasticsearch == nil { | ||||||
|  | 		f.Elasticsearch = new(bool) | ||||||
|  | 		*f.Elasticsearch = *f.FutureFeatures | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if f.Announcement == nil { | ||||||
|  | 		f.Announcement = new(bool) | ||||||
|  | 		*f.Announcement = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if f.EmailNotificationContents == nil { | ||||||
|  | 		f.EmailNotificationContents = new(bool) | ||||||
|  | 		*f.EmailNotificationContents = *f.FutureFeatures | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (l *License) IsExpired() bool { | func (l *License) IsExpired() bool { | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								vendor/github.com/mattermost/platform/model/mfa_secret.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/mattermost/platform/model/mfa_secret.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. | ||||||
|  | // See License.txt for license information. | ||||||
|  |  | ||||||
|  | package model | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"io" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type MfaSecret struct { | ||||||
|  | 	Secret string `json:"secret"` | ||||||
|  | 	QRCode string `json:"qr_code"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (me *MfaSecret) ToJson() string { | ||||||
|  | 	b, err := json.Marshal(me) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "" | ||||||
|  | 	} else { | ||||||
|  | 		return string(b) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MfaSecretFromJson(data io.Reader) *MfaSecret { | ||||||
|  | 	decoder := json.NewDecoder(data) | ||||||
|  | 	var me MfaSecret | ||||||
|  | 	err := decoder.Decode(&me) | ||||||
|  | 	if err == nil { | ||||||
|  | 		return &me | ||||||
|  | 	} else { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								vendor/github.com/mattermost/platform/model/oauth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/mattermost/platform/model/oauth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| 	"unicode/utf8" | 	"unicode/utf8" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -15,6 +16,7 @@ const ( | |||||||
| 	OAUTH_ACTION_LOGIN        = "login" | 	OAUTH_ACTION_LOGIN        = "login" | ||||||
| 	OAUTH_ACTION_EMAIL_TO_SSO = "email_to_sso" | 	OAUTH_ACTION_EMAIL_TO_SSO = "email_to_sso" | ||||||
| 	OAUTH_ACTION_SSO_TO_EMAIL = "sso_to_email" | 	OAUTH_ACTION_SSO_TO_EMAIL = "sso_to_email" | ||||||
|  | 	OAUTH_ACTION_MOBILE       = "mobile" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type OAuthApp struct { | type OAuthApp struct { | ||||||
| @@ -36,50 +38,50 @@ type OAuthApp struct { | |||||||
| func (a *OAuthApp) IsValid() *AppError { | func (a *OAuthApp) IsValid() *AppError { | ||||||
|  |  | ||||||
| 	if len(a.Id) != 26 { | 	if len(a.Id) != 26 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.app_id.app_error", nil, "") | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.app_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if a.CreateAt == 0 { | 	if a.CreateAt == 0 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.create_at.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.create_at.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if a.UpdateAt == 0 { | 	if a.UpdateAt == 0 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.update_at.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.update_at.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.CreatorId) != 26 { | 	if len(a.CreatorId) != 26 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.creator_id.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.creator_id.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.ClientSecret) == 0 || len(a.ClientSecret) > 128 { | 	if len(a.ClientSecret) == 0 || len(a.ClientSecret) > 128 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.client_secret.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.client_secret.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.Name) == 0 || len(a.Name) > 64 { | 	if len(a.Name) == 0 || len(a.Name) > 64 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.name.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.name.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.CallbackUrls) == 0 || len(fmt.Sprintf("%s", a.CallbackUrls)) > 1024 { | 	if len(a.CallbackUrls) == 0 || len(fmt.Sprintf("%s", a.CallbackUrls)) > 1024 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, callback := range a.CallbackUrls { | 	for _, callback := range a.CallbackUrls { | ||||||
| 		if !IsValidHttpUrl(callback) { | 		if !IsValidHttpUrl(callback) { | ||||||
| 			return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "") | 			return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.callback.app_error", nil, "", http.StatusBadRequest) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.Homepage) == 0 || len(a.Homepage) > 256 || !IsValidHttpUrl(a.Homepage) { | 	if len(a.Homepage) == 0 || len(a.Homepage) > 256 || !IsValidHttpUrl(a.Homepage) { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.homepage.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.homepage.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if utf8.RuneCountInString(a.Description) > 512 { | 	if utf8.RuneCountInString(a.Description) > 512 { | ||||||
| 		return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.description.app_error", nil, "app_id="+a.Id) | 		return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.description.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(a.IconURL) > 0 { | 	if len(a.IconURL) > 0 { | ||||||
| 		if len(a.IconURL) > 512 || !IsValidHttpUrl(a.IconURL) { | 		if len(a.IconURL) > 512 || !IsValidHttpUrl(a.IconURL) { | ||||||
| 			return NewLocAppError("OAuthApp.IsValid", "model.oauth.is_valid.icon_url.app_error", nil, "app_id="+a.Id) | 			return NewAppError("OAuthApp.IsValid", "model.oauth.is_valid.icon_url.app_error", nil, "app_id="+a.Id, http.StatusBadRequest) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								vendor/github.com/mattermost/platform/model/outgoing_webhook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/mattermost/platform/model/outgoing_webhook.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||||||
| // See License.txt for license information. | // See License.txt for license information. | ||||||
|  |  | ||||||
| package model | package model | ||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"net/http" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -41,6 +42,7 @@ type OutgoingWebhookPayload struct { | |||||||
| 	PostId      string `json:"post_id"` | 	PostId      string `json:"post_id"` | ||||||
| 	Text        string `json:"text"` | 	Text        string `json:"text"` | ||||||
| 	TriggerWord string `json:"trigger_word"` | 	TriggerWord string `json:"trigger_word"` | ||||||
|  | 	FileIds     string `json:"file_ids"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *OutgoingWebhookPayload) ToJSON() string { | func (o *OutgoingWebhookPayload) ToJSON() string { | ||||||
| @@ -65,6 +67,7 @@ func (o *OutgoingWebhookPayload) ToFormValues() string { | |||||||
| 	v.Set("post_id", o.PostId) | 	v.Set("post_id", o.PostId) | ||||||
| 	v.Set("text", o.Text) | 	v.Set("text", o.Text) | ||||||
| 	v.Set("trigger_word", o.TriggerWord) | 	v.Set("trigger_word", o.TriggerWord) | ||||||
|  | 	v.Set("file_ids", o.FileIds) | ||||||
|  |  | ||||||
| 	return v.Encode() | 	return v.Encode() | ||||||
| } | } | ||||||
| @@ -112,69 +115,69 @@ func OutgoingWebhookListFromJson(data io.Reader) []*OutgoingWebhook { | |||||||
| func (o *OutgoingWebhook) IsValid() *AppError { | func (o *OutgoingWebhook) IsValid() *AppError { | ||||||
|  |  | ||||||
| 	if len(o.Id) != 26 { | 	if len(o.Id) != 26 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.id.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.Token) != 26 { | 	if len(o.Token) != 26 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.token.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.token.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.CreateAt == 0 { | 	if o.CreateAt == 0 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.create_at.app_error", nil, "id="+o.Id) | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.UpdateAt == 0 { | 	if o.UpdateAt == 0 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.update_at.app_error", nil, "id="+o.Id) | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.CreatorId) != 26 { | 	if len(o.CreatorId) != 26 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.user_id.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.ChannelId) != 0 && len(o.ChannelId) != 26 { | 	if len(o.ChannelId) != 0 && len(o.ChannelId) != 26 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.channel_id.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.channel_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.TeamId) != 26 { | 	if len(o.TeamId) != 26 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.team_id.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.team_id.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(fmt.Sprintf("%s", o.TriggerWords)) > 1024 { | 	if len(fmt.Sprintf("%s", o.TriggerWords)) > 1024 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.words.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.words.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.TriggerWords) != 0 { | 	if len(o.TriggerWords) != 0 { | ||||||
| 		for _, triggerWord := range o.TriggerWords { | 		for _, triggerWord := range o.TriggerWords { | ||||||
| 			if len(triggerWord) == 0 { | 			if len(triggerWord) == 0 { | ||||||
| 				return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.trigger_words.app_error", nil, "") | 				return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.trigger_words.app_error", nil, "", http.StatusBadRequest) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.CallbackURLs) == 0 || len(fmt.Sprintf("%s", o.CallbackURLs)) > 1024 { | 	if len(o.CallbackURLs) == 0 || len(fmt.Sprintf("%s", o.CallbackURLs)) > 1024 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.callback.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.callback.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, callback := range o.CallbackURLs { | 	for _, callback := range o.CallbackURLs { | ||||||
| 		if !IsValidHttpUrl(callback) { | 		if !IsValidHttpUrl(callback) { | ||||||
| 			return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.url.app_error", nil, "") | 			return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.url.app_error", nil, "", http.StatusBadRequest) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.DisplayName) > 64 { | 	if len(o.DisplayName) > 64 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.display_name.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.display_name.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.Description) > 128 { | 	if len(o.Description) > 128 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.description.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.description.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(o.ContentType) > 128 { | 	if len(o.ContentType) > 128 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.TriggerWhen > 1 { | 	if o.TriggerWhen > 1 { | ||||||
| 		return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "") | 		return NewAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "", http.StatusBadRequest) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @@ -197,8 +200,8 @@ func (o *OutgoingWebhook) PreUpdate() { | |||||||
| 	o.UpdateAt = GetMillis() | 	o.UpdateAt = GetMillis() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *OutgoingWebhook) HasTriggerWord(word string) bool { | func (o *OutgoingWebhook) TriggerWordExactMatch(word string) bool { | ||||||
| 	if len(o.TriggerWords) == 0 || len(word) == 0 { | 	if len(word) == 0 { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -212,7 +215,7 @@ func (o *OutgoingWebhook) HasTriggerWord(word string) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (o *OutgoingWebhook) TriggerWordStartsWith(word string) bool { | func (o *OutgoingWebhook) TriggerWordStartsWith(word string) bool { | ||||||
| 	if len(o.TriggerWords) == 0 || len(word) == 0 { | 	if len(word) == 0 { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -224,3 +227,27 @@ func (o *OutgoingWebhook) TriggerWordStartsWith(word string) bool { | |||||||
|  |  | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *OutgoingWebhook) GetTriggerWord(word string, isExactMatch bool) (triggerWord string) { | ||||||
|  | 	if len(word) == 0 { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if isExactMatch { | ||||||
|  | 		for _, trigger := range o.TriggerWords { | ||||||
|  | 			if trigger == word { | ||||||
|  | 				triggerWord = trigger | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		for _, trigger := range o.TriggerWords { | ||||||
|  | 			if strings.HasPrefix(word, trigger) { | ||||||
|  | 				triggerWord = trigger | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return triggerWord | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								vendor/github.com/mattermost/platform/model/password_recovery.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/mattermost/platform/model/password_recovery.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | |||||||
| // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. |  | ||||||
| // See License.txt for license information. |  | ||||||
|  |  | ||||||
| package model |  | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	PASSWORD_RECOVERY_CODE_SIZE  = 128 |  | ||||||
| 	PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type PasswordRecovery struct { |  | ||||||
| 	UserId   string |  | ||||||
| 	Code     string |  | ||||||
| 	CreateAt int64 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *PasswordRecovery) IsValid() *AppError { |  | ||||||
|  |  | ||||||
| 	if len(p.UserId) != 26 { |  | ||||||
| 		return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.user_id.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(p.Code) != PASSWORD_RECOVERY_CODE_SIZE { |  | ||||||
| 		return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.code.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if p.CreateAt == 0 { |  | ||||||
| 		return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.create_at.app_error", nil, "") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *PasswordRecovery) PreSave() { |  | ||||||
| 	p.Code = NewRandomString(PASSWORD_RECOVERY_CODE_SIZE) |  | ||||||
| 	p.CreateAt = GetMillis() |  | ||||||
| } |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user