From f8e6a69d6e8453de0b700b6e9a3eedeec0b1f0a5 Mon Sep 17 00:00:00 2001 From: Wim Date: Sun, 30 Jul 2017 17:48:23 +0200 Subject: Add action support for slack,mattermost,irc,gitter,matrix,xmpp,discord. #199 --- bridge/config/config.go | 1 + bridge/discord/discord.go | 33 +++++++++++++++++++++++++++------ bridge/gitter/gitter.go | 7 ++++++- bridge/irc/irc.go | 15 +++++++++++---- bridge/matrix/matrix.go | 13 +++++++++++-- bridge/mattermost/mattermost.go | 19 ++++++++++++++++++- bridge/slack/slack.go | 6 ++++++ bridge/telegram/telegram.go | 1 + bridge/xmpp/xmpp.go | 15 ++++++++++++++- 9 files changed, 95 insertions(+), 15 deletions(-) diff --git a/bridge/config/config.go b/bridge/config/config.go index b390c72b..c03a3ab5 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -13,6 +13,7 @@ const ( EVENT_JOIN_LEAVE = "join_leave" EVENT_FAILURE = "failure" EVENT_REJOIN_CHANNELS = "rejoin_channels" + EVENT_USER_ACTION = "user_action" ) type Message struct { diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index e2e25989..c74cf902 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -116,9 +116,16 @@ func (b *bdiscord) Send(msg config.Message) error { } if b.Config.WebhookURL == "" { flog.Debugf("Broadcasting using token (API)") + if msg.Event == config.EVENT_USER_ACTION { + msg.Username = "_" + msg.Username + msg.Text = msg.Text + "_" + } b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) } else { flog.Debugf("Broadcasting using Webhook") + if msg.Event == config.EVENT_USER_ACTION { + msg.Text = "_" + msg.Text + "_" + } b.c.WebhookExecute( b.webhookID, b.webhookToken, @@ -171,11 +178,14 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat text = m.ContentWithMentionsReplaced() } - channelName := b.getChannelName(m.ChannelID) + rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", + UserID: m.Author.ID} + + rmsg.Channel = b.getChannelName(m.ChannelID) if b.UseChannelID { - channelName = "ID:" + m.ChannelID + rmsg.Channel = "ID:" + m.ChannelID } - username := b.getNick(m.Author) + rmsg.Username = b.getNick(m.Author) if b.Config.ShowEmbeds && m.Message.Embeds != nil { for _, embed := range m.Message.Embeds { @@ -188,10 +198,14 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat return } + text, ok := b.replaceAction(text) + if ok { + rmsg.Event = config.EVENT_USER_ACTION + } + + rmsg.Text = text flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account) - b.Remote <- config.Message{Username: username, Text: text, Channel: channelName, - Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", - UserID: m.Author.ID} + b.Remote <- rmsg } func (b *bdiscord) memberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) { @@ -283,6 +297,13 @@ func (b *bdiscord) replaceChannelMentions(text string) string { return text } +func (b *bdiscord) replaceAction(text string) (string, bool) { + if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") { + return strings.Replace(text, "_", "", -1), true + } + return text, false +} + func (b *bdiscord) stripCustomoji(text string) string { // <:doge:302803592035958784> re := regexp.MustCompile("<(:.*?:)[0-9]+>") diff --git a/bridge/gitter/gitter.go b/bridge/gitter/gitter.go index 973a7300..0b8667ea 100644 --- a/bridge/gitter/gitter.go +++ b/bridge/gitter/gitter.go @@ -81,8 +81,13 @@ func (b *Bgitter) JoinChannel(channel string) error { // check for ZWSP to see if it's not an echo if !strings.HasSuffix(ev.Message.Text, "​") { flog.Debugf("Sending message from %s on %s to gateway", ev.Message.From.Username, b.Account) - b.Remote <- 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} + if strings.HasPrefix(ev.Message.Text, "@"+ev.Message.From.Username) { + rmsg.Event = config.EVENT_USER_ACTION + rmsg.Text = strings.Replace(rmsg.Text, "@"+ev.Message.From.Username+" ", "", -1) + } + b.Remote <- rmsg } case *gitter.GitterConnectionClosed: flog.Errorf("connection with gitter closed for room %s", room) diff --git a/bridge/irc/irc.go b/bridge/irc/irc.go index 86ed6974..aa46a6f1 100644 --- a/bridge/irc/irc.go +++ b/bridge/irc/irc.go @@ -135,7 +135,7 @@ func (b *Birc) Send(msg config.Message) error { if len(b.Local) == b.Config.MessageQueue-1 { text = text + " " } - b.Local <- config.Message{Text: text, Username: msg.Username, Channel: msg.Channel} + b.Local <- config.Message{Text: text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event} } else { flog.Debugf("flooding, dropping message (queue at %d)", len(b.Local)) } @@ -148,7 +148,11 @@ func (b *Birc) doSend() { throttle := time.NewTicker(rate) for msg := range b.Local { <-throttle.C - b.i.Privmsg(msg.Channel, msg.Username+msg.Text) + if msg.Event == config.EVENT_USER_ACTION { + b.i.Action(msg.Channel, msg.Username+msg.Text) + } else { + b.i.Privmsg(msg.Channel, msg.Username+msg.Text) + } } } @@ -244,10 +248,12 @@ func (b *Birc) handlePrivMsg(event *irc.Event) { if event.Nick == b.Nick { return } + rmsg := config.Message{Username: event.Nick, Channel: event.Arguments[0], Account: b.Account, UserID: event.User + "@" + event.Host} flog.Debugf("handlePrivMsg() %s %s %#v", event.Nick, event.Message(), event) msg := "" if event.Code == "CTCP_ACTION" { - msg = event.Nick + " " + // msg = event.Nick + " " + rmsg.Event = config.EVENT_USER_ACTION } msg += event.Message() // strip IRC colors @@ -276,7 +282,8 @@ func (b *Birc) handlePrivMsg(event *irc.Event) { msg = string(output) flog.Debugf("Sending message from %s on %s to gateway", event.Arguments[0], b.Account) - b.Remote <- config.Message{Username: event.Nick, Text: msg, Channel: event.Arguments[0], Account: b.Account, UserID: event.User + "@" + event.Host} + rmsg.Text = msg + b.Remote <- rmsg } func (b *Birc) handleTopicWhoTime(event *irc.Event) { diff --git a/bridge/matrix/matrix.go b/bridge/matrix/matrix.go index 2fd91b32..06359855 100644 --- a/bridge/matrix/matrix.go +++ b/bridge/matrix/matrix.go @@ -78,6 +78,11 @@ func (b *Bmatrix) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) channel := b.getRoomID(msg.Channel) flog.Debugf("Sending to channel %s", channel) + if msg.Event == config.EVENT_USER_ACTION { + b.mc.SendMessageEvent(channel, "m.room.message", + matrix.TextMessage{"m.emote", msg.Username + msg.Text}) + return nil + } b.mc.SendText(channel, msg.Username+msg.Text) return nil } @@ -95,7 +100,7 @@ func (b *Bmatrix) getRoomID(channel string) string { func (b *Bmatrix) handlematrix() error { syncer := b.mc.Syncer.(*matrix.DefaultSyncer) syncer.OnEventType("m.room.message", func(ev *matrix.Event) { - if ev.Content["msgtype"].(string) == "m.text" && ev.Sender != b.UserID { + if (ev.Content["msgtype"].(string) == "m.text" || ev.Content["msgtype"].(string) == "m.emote") && ev.Sender != b.UserID { b.RLock() channel, ok := b.RoomMap[ev.RoomID] b.RUnlock() @@ -108,8 +113,12 @@ func (b *Bmatrix) handlematrix() error { re := regexp.MustCompile("(.*?):.*") username = re.ReplaceAllString(username, `$1`) } + rmsg := config.Message{Username: username, Text: ev.Content["body"].(string), Channel: channel, Account: b.Account, UserID: ev.Sender} + if ev.Content["msgtype"].(string) == "m.emote" { + rmsg.Event = config.EVENT_USER_ACTION + } flog.Debugf("Sending message from %s on %s to gateway", ev.Sender, b.Account) - b.Remote <- config.Message{Username: username, Text: ev.Content["body"].(string), Channel: channel, Account: b.Account, UserID: ev.Sender} + b.Remote <- rmsg } flog.Debugf("Received: %#v", ev) }) diff --git a/bridge/mattermost/mattermost.go b/bridge/mattermost/mattermost.go index 67dc7b5b..7e3e7e2e 100644 --- a/bridge/mattermost/mattermost.go +++ b/bridge/mattermost/mattermost.go @@ -6,6 +6,7 @@ import ( "github.com/42wim/matterbridge/matterclient" "github.com/42wim/matterbridge/matterhook" log "github.com/Sirupsen/logrus" + "strings" ) type MMhook struct { @@ -117,6 +118,9 @@ func (b *Bmattermost) JoinChannel(channel string) error { func (b *Bmattermost) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) + if msg.Event == config.EVENT_USER_ACTION { + msg.Text = "*" + msg.Text + "*" + } nick := msg.Username message := msg.Text channel := msg.Channel @@ -152,8 +156,14 @@ func (b *Bmattermost) handleMatter() { go b.handleMatterClient(mchan) } for message := range mchan { + rmsg := config.Message{Username: message.Username, Channel: message.Channel, Account: b.Account, UserID: message.UserID} + text, ok := b.replaceAction(message.Text) + if ok { + rmsg.Event = config.EVENT_USER_ACTION + } + rmsg.Text = text flog.Debugf("Sending message from %s on %s to gateway", message.Username, b.Account) - b.Remote <- config.Message{Text: message.Text, Username: message.Username, Channel: message.Channel, Account: b.Account, UserID: message.UserID} + b.Remote <- rmsg } } @@ -226,3 +236,10 @@ func (b *Bmattermost) apiLogin() error { go b.mc.StatusLoop() return nil } + +func (b *Bmattermost) replaceAction(text string) (string, bool) { + if strings.HasPrefix(text, "*") && strings.HasSuffix(text, "*") { + return strings.Replace(text, "*", "", -1), true + } + return text, false +} diff --git a/bridge/slack/slack.go b/bridge/slack/slack.go index 6617f823..4c72a90c 100644 --- a/bridge/slack/slack.go +++ b/bridge/slack/slack.go @@ -127,6 +127,9 @@ func (b *Bslack) JoinChannel(channel string) error { func (b *Bslack) Send(msg config.Message) error { flog.Debugf("Receiving %#v", msg) + if msg.Event == config.EVENT_USER_ACTION { + msg.Text = "_" + msg.Text + "_" + } nick := msg.Username message := msg.Text channel := msg.Channel @@ -231,6 +234,9 @@ func (b *Bslack) handleSlack() { text = html.UnescapeString(text) 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} + if message.Raw.SubType == "me_message" { + msg.Event = config.EVENT_USER_ACTION + } b.Remote <- msg } } diff --git a/bridge/telegram/telegram.go b/bridge/telegram/telegram.go index ce43b344..4bfbf509 100644 --- a/bridge/telegram/telegram.go +++ b/bridge/telegram/telegram.go @@ -77,6 +77,7 @@ func (b *Btelegram) Send(msg config.Message) error { func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { for update := range updates { + flog.Debugf("Receiving from telegram: %#v", update.Message) var message *tgbotapi.Message username := "" channel := "" diff --git a/bridge/xmpp/xmpp.go b/bridge/xmpp/xmpp.go index 504b9747..dfc2967e 100644 --- a/bridge/xmpp/xmpp.go +++ b/bridge/xmpp/xmpp.go @@ -133,6 +133,7 @@ func (b *Bxmpp) xmppKeepAlive() chan bool { } func (b *Bxmpp) handleXmpp() error { + var ok bool done := b.xmppKeepAlive() defer close(done) nodelay := time.Time{} @@ -154,8 +155,13 @@ func (b *Bxmpp) handleXmpp() error { nick = s[1] } if nick != b.Config.Nick && v.Stamp == nodelay && v.Text != "" { + rmsg := config.Message{Username: nick, Text: v.Text, Channel: channel, Account: b.Account, UserID: v.Remote} + rmsg.Text, ok = b.replaceAction(rmsg.Text) + if ok { + rmsg.Event = config.EVENT_USER_ACTION + } flog.Debugf("Sending message from %s on %s to gateway", nick, b.Account) - b.Remote <- config.Message{Username: nick, Text: v.Text, Channel: channel, Account: b.Account, UserID: v.Remote} + b.Remote <- rmsg } } case xmpp.Presence: @@ -163,3 +169,10 @@ func (b *Bxmpp) handleXmpp() error { } } } + +func (b *Bxmpp) replaceAction(text string) (string, bool) { + if strings.HasPrefix(text, "/me ") { + return strings.Replace(text, "/me ", "", -1), true + } + return text, false +} -- cgit v1.2.3