From 28710d0bc7d5bd564d702953c490a865b0cc438d Mon Sep 17 00:00:00 2001 From: Wim Date: Sat, 12 Aug 2017 14:51:41 +0200 Subject: [PATCH] Allow a webhookurl per channel (discord). #239 --- bridge/api/api.go | 2 +- bridge/bridge.go | 10 +--- bridge/config/config.go | 3 +- bridge/discord/discord.go | 84 ++++++++++++++++++++++++--------- bridge/gitter/gitter.go | 6 +-- bridge/irc/irc.go | 9 +++- bridge/matrix/matrix.go | 6 +-- bridge/mattermost/mattermost.go | 4 +- bridge/rocketchat/rocketchat.go | 2 +- bridge/slack/slack.go | 4 +- bridge/steam/steam.go | 4 +- bridge/telegram/telegram.go | 2 +- bridge/xmpp/xmpp.go | 4 +- matterbridge.toml.sample | 9 ++++ 14 files changed, 100 insertions(+), 49 deletions(-) diff --git a/bridge/api/api.go b/bridge/api/api.go index 26ff3327..196be182 100644 --- a/bridge/api/api.go +++ b/bridge/api/api.go @@ -61,7 +61,7 @@ func (b *Api) Disconnect() error { return nil } -func (b *Api) JoinChannel(channel string) error { +func (b *Api) JoinChannel(channel config.ChannelInfo) error { return nil } diff --git a/bridge/bridge.go b/bridge/bridge.go index 8e0fe063..2fe0f076 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -21,7 +21,7 @@ import ( type Bridger interface { Send(msg config.Message) error Connect() error - JoinChannel(channel string) error + JoinChannel(channel config.ChannelInfo) 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 { - mychannel := "" for ID, channel := range channels { if !exists[ID] { - mychannel = channel.Name log.Infof("%s: joining %s (%s)", b.Account, channel.Name, ID) - if b.Protocol == "irc" && channel.Options.Key != "" { - log.Debugf("using key %s for channel %s", channel.Options.Key, channel.Name) - mychannel = mychannel + " " + channel.Options.Key - } - err := b.JoinChannel(mychannel) + err := b.JoinChannel(channel) if err != nil { return err } diff --git a/bridge/config/config.go b/bridge/config/config.go index a90cb9a9..ae937915 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -85,7 +85,8 @@ type Protocol struct { } type ChannelOptions struct { - Key string // irc + Key string // irc + WebhookURL string // discord } type Bridge struct { diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index 4b325653..2868eeb5 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -10,17 +10,18 @@ import ( ) type bdiscord struct { - c *discordgo.Session - Config *config.Protocol - Remote chan config.Message - Account string - Channels []*discordgo.Channel - Nick string - UseChannelID bool - userMemberMap map[string]*discordgo.Member - guildID string - webhookID string - webhookToken string + c *discordgo.Session + Config *config.Protocol + Remote chan config.Message + Account string + Channels []*discordgo.Channel + Nick string + UseChannelID bool + userMemberMap map[string]*discordgo.Member + guildID string + webhookID string + webhookToken string + channelInfoMap map[string]*config.ChannelInfo sync.RWMutex } @@ -37,11 +38,10 @@ func New(cfg config.Protocol, account string, c chan config.Message) *bdiscord { b.Remote = c b.Account = account b.userMemberMap = make(map[string]*discordgo.Member) + b.channelInfoMap = make(map[string]*config.ChannelInfo) if b.Config.WebhookURL != "" { flog.Debug("Configuring Discord Incoming Webhook") - webhookURLSplit := strings.Split(b.Config.WebhookURL, "/") - b.webhookToken = webhookURLSplit[len(webhookURLSplit)-1] - b.webhookID = webhookURLSplit[len(webhookURLSplit)-2] + b.webhookToken, b.webhookID = b.splitURL(b.Config.WebhookURL) } return b } @@ -99,8 +99,9 @@ func (b *bdiscord) Disconnect() error { return nil } -func (b *bdiscord) JoinChannel(channel string) error { - idcheck := strings.Split(channel, "ID:") +func (b *bdiscord) JoinChannel(channel config.ChannelInfo) error { + b.channelInfoMap[channel.ID] = &channel + idcheck := strings.Split(channel.Name, "ID:") if len(idcheck) > 1 { b.UseChannelID = true } @@ -117,14 +118,23 @@ func (b *bdiscord) Send(msg config.Message) error { if msg.Event == config.EVENT_USER_ACTION { msg.Text = "_" + msg.Text + "_" } - if b.Config.WebhookURL == "" { + + wID := b.webhookID + wToken := b.webhookToken + if ci, ok := b.channelInfoMap[msg.Channel+msg.Account]; ok { + if ci.Options.WebhookURL != "" { + wID, wToken = b.splitURL(ci.Options.WebhookURL) + } + } + + if wID == "" { flog.Debugf("Broadcasting using token (API)") b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) } else { - flog.Debugf("Broadcasting using Webhook") + flog.Debugf("Broadcasting using Webhook %#v %#v", wID, wToken) b.c.WebhookExecute( - b.webhookID, - b.webhookToken, + wID, + wToken, true, &discordgo.WebhookParams{ Content: msg.Text, @@ -153,7 +163,7 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat return } // 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 } @@ -310,3 +320,35 @@ func (b *bdiscord) stripCustomoji(text string) string { re := regexp.MustCompile("<(:.*?:)[0-9]+>") 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 { + for _, channel := range b.channelInfoMap { + if channel.Options.WebhookURL != "" { + wID, _ := b.splitURL(channel.Options.WebhookURL) + if wID == id { + return true + } + } + } + return false +} diff --git a/bridge/gitter/gitter.go b/bridge/gitter/gitter.go index 0b8667ea..f234b6bb 100644 --- a/bridge/gitter/gitter.go +++ b/bridge/gitter/gitter.go @@ -51,10 +51,10 @@ func (b *Bgitter) Disconnect() error { } -func (b *Bgitter) JoinChannel(channel string) error { - roomID, err := b.c.GetRoomId(channel) +func (b *Bgitter) JoinChannel(channel config.ChannelInfo) error { + roomID, err := b.c.GetRoomId(channel.Name) 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) if err != nil { diff --git a/bridge/irc/irc.go b/bridge/irc/irc.go index aa46a6f1..6e5839bd 100644 --- a/bridge/irc/irc.go +++ b/bridge/irc/irc.go @@ -117,8 +117,13 @@ func (b *Birc) Disconnect() error { return nil } -func (b *Birc) JoinChannel(channel string) error { - b.i.Join(channel) +func (b *Birc) JoinChannel(channel config.ChannelInfo) error { + 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 } diff --git a/bridge/matrix/matrix.go b/bridge/matrix/matrix.go index 06359855..6cf6a566 100644 --- a/bridge/matrix/matrix.go +++ b/bridge/matrix/matrix.go @@ -63,13 +63,13 @@ func (b *Bmatrix) Disconnect() error { return nil } -func (b *Bmatrix) JoinChannel(channel string) error { - resp, err := b.mc.JoinRoom(channel, "", nil) +func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error { + resp, err := b.mc.JoinRoom(channel.Name, "", nil) if err != nil { return err } b.Lock() - b.RoomMap[resp.RoomID] = channel + b.RoomMap[resp.RoomID] = channel.Name b.Unlock() return err } diff --git a/bridge/mattermost/mattermost.go b/bridge/mattermost/mattermost.go index 7e3e7e2e..54a7efff 100644 --- a/bridge/mattermost/mattermost.go +++ b/bridge/mattermost/mattermost.go @@ -108,10 +108,10 @@ func (b *Bmattermost) Disconnect() error { 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 if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { - return b.mc.JoinChannel(b.mc.GetChannelId(channel, "")) + return b.mc.JoinChannel(b.mc.GetChannelId(channel.Name, "")) } return nil } diff --git a/bridge/rocketchat/rocketchat.go b/bridge/rocketchat/rocketchat.go index 1b731f94..3223a781 100644 --- a/bridge/rocketchat/rocketchat.go +++ b/bridge/rocketchat/rocketchat.go @@ -53,7 +53,7 @@ func (b *Brocketchat) Disconnect() error { } -func (b *Brocketchat) JoinChannel(channel string) error { +func (b *Brocketchat) JoinChannel(channel config.ChannelInfo) error { return nil } diff --git a/bridge/slack/slack.go b/bridge/slack/slack.go index 4c72a90c..f16aa055 100644 --- a/bridge/slack/slack.go +++ b/bridge/slack/slack.go @@ -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 if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { if strings.HasPrefix(b.Config.Token, "xoxb") { // TODO check if bot has already joined channel return nil } - _, err := b.sc.JoinChannel(channel) + _, err := b.sc.JoinChannel(channel.Name) if err != nil { if err.Error() != "name_taken" { return err diff --git a/bridge/steam/steam.go b/bridge/steam/steam.go index ad4b1988..aa125e4a 100644 --- a/bridge/steam/steam.go +++ b/bridge/steam/steam.go @@ -60,8 +60,8 @@ func (b *Bsteam) Disconnect() error { } -func (b *Bsteam) JoinChannel(channel string) error { - id, err := steamid.NewId(channel) +func (b *Bsteam) JoinChannel(channel config.ChannelInfo) error { + id, err := steamid.NewId(channel.Name) if err != nil { return err } diff --git a/bridge/telegram/telegram.go b/bridge/telegram/telegram.go index 4bfbf509..77704ab9 100644 --- a/bridge/telegram/telegram.go +++ b/bridge/telegram/telegram.go @@ -53,7 +53,7 @@ func (b *Btelegram) Disconnect() error { } -func (b *Btelegram) JoinChannel(channel string) error { +func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error { return nil } diff --git a/bridge/xmpp/xmpp.go b/bridge/xmpp/xmpp.go index dfc2967e..56773ef5 100644 --- a/bridge/xmpp/xmpp.go +++ b/bridge/xmpp/xmpp.go @@ -74,8 +74,8 @@ func (b *Bxmpp) Disconnect() error { return nil } -func (b *Bxmpp) JoinChannel(channel string) error { - b.xc.JoinMUCNoHistory(channel+"@"+b.Config.Muc, b.Config.Nick) +func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) error { + b.xc.JoinMUCNoHistory(channel.Name+"@"+b.Config.Muc, b.Config.Nick) return nil } diff --git a/matterbridge.toml.sample b/matterbridge.toml.sample index e31c23e4..9d15efb0 100644 --- a/matterbridge.toml.sample +++ b/matterbridge.toml.sample @@ -448,6 +448,7 @@ ShowEmbeds=false UseUserName=false #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) WebhookURL="Yourwebhooktokenhere" @@ -833,6 +834,14 @@ enable=true #OPTIONAL - your irc channel key 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 #[[gateway.inout]] #account="api.local"