diff --git a/bridge/api/api.go b/bridge/api/api.go index ca28d904..ab473afc 100644 --- a/bridge/api/api.go +++ b/bridge/api/api.go @@ -69,6 +69,10 @@ func (b *Api) JoinChannel(channel config.ChannelInfo) error { func (b *Api) Send(msg config.Message) (string, error) { b.Lock() defer b.Unlock() + // ignore delete messages + if msg.Event == config.EVENT_MSG_DELETE { + return "", nil + } b.Messages.Enqueue(&msg) return "", nil } diff --git a/bridge/config/config.go b/bridge/config/config.go index c5925a1d..812ce18e 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -14,6 +14,7 @@ const ( EVENT_FAILURE = "failure" EVENT_REJOIN_CHANNELS = "rejoin_channels" EVENT_USER_ACTION = "user_action" + EVENT_MSG_DELETE = "msg_delete" ) type Message struct { diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index ffbada40..d8320c76 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -66,6 +66,7 @@ func (b *bdiscord) Connect() error { b.c.AddHandler(b.messageCreate) b.c.AddHandler(b.memberUpdate) b.c.AddHandler(b.messageUpdate) + b.c.AddHandler(b.messageDelete) err = b.c.Open() if err != nil { flog.Debugf("%#v", err) @@ -129,6 +130,13 @@ func (b *bdiscord) Send(msg config.Message) (string, error) { if wID == "" { flog.Debugf("Broadcasting using token (API)") + if msg.Event == config.EVENT_MSG_DELETE { + if msg.ID == "" { + return "", nil + } + err := b.c.ChannelMessageDelete(channelID, msg.ID) + return "", err + } if msg.ID != "" { _, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text) return msg.ID, err @@ -152,6 +160,17 @@ func (b *bdiscord) Send(msg config.Message) (string, error) { 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) { if b.Config.EditDisable { return @@ -223,6 +242,7 @@ func (b *bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat rmsg.Text = text flog.Debugf("Sending message from %s on %s to gateway", m.Author.Username, b.Account) + flog.Debugf("Message is %#v", rmsg) b.Remote <- rmsg } diff --git a/bridge/gitter/gitter.go b/bridge/gitter/gitter.go index 9a7b3bf9..b1d68733 100644 --- a/bridge/gitter/gitter.go +++ b/bridge/gitter/gitter.go @@ -106,6 +106,17 @@ func (b *Bgitter) Send(msg config.Message) (string, error) { flog.Errorf("Could not find roomID for %v", msg.Channel) return "", nil } + if msg.Event == config.EVENT_MSG_DELETE { + 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) diff --git a/bridge/irc/irc.go b/bridge/irc/irc.go index d62fe31a..1e0101fa 100644 --- a/bridge/irc/irc.go +++ b/bridge/irc/irc.go @@ -129,6 +129,10 @@ func (b *Birc) JoinChannel(channel config.ChannelInfo) 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) if strings.HasPrefix(msg.Text, "!") { b.Command(&msg) diff --git a/bridge/matrix/matrix.go b/bridge/matrix/matrix.go index 1cad6221..bbf85e9b 100644 --- a/bridge/matrix/matrix.go +++ b/bridge/matrix/matrix.go @@ -76,6 +76,10 @@ func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error { func (b *Bmatrix) Send(msg config.Message) (string, error) { flog.Debugf("Receiving %#v", msg) + // ignore delete messages + if msg.Event == config.EVENT_MSG_DELETE { + return "", nil + } channel := b.getRoomID(msg.Channel) flog.Debugf("Sending to channel %s", channel) if msg.Event == config.EVENT_USER_ACTION { diff --git a/bridge/mattermost/mattermost.go b/bridge/mattermost/mattermost.go index 30e38042..6e5b3d38 100644 --- a/bridge/mattermost/mattermost.go +++ b/bridge/mattermost/mattermost.go @@ -25,6 +25,7 @@ type MMMessage struct { Username string UserID string ID string + Event string } type Bmattermost struct { @@ -168,6 +169,12 @@ func (b *Bmattermost) Send(msg config.Message) (string, error) { } return "", nil } + if msg.Event == config.EVENT_MSG_DELETE { + if msg.ID == "" { + return "", nil + } + return msg.ID, b.mc.DeleteMessage(msg.ID) + } if msg.ID != "" { return b.mc.EditMessage(msg.ID, message) } @@ -188,7 +195,7 @@ 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, ID: message.ID} + 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) if ok { rmsg.Event = config.EVENT_USER_ACTION @@ -215,7 +222,7 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) { } // do not post our own messages back to irc // 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 { // if the message has reactions don't repost it (for now, until we can correlate reaction with message) if message.Post.HasReactions { @@ -231,6 +238,9 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) { if message.Raw.Event == "post_edited" && !b.Config.EditDisable { 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 { for _, link := range b.mc.GetFileLinks(message.Post.FileIds) { m.Text = m.Text + "\n" + link diff --git a/bridge/rocketchat/rocketchat.go b/bridge/rocketchat/rocketchat.go index 1e534c20..eac754f5 100644 --- a/bridge/rocketchat/rocketchat.go +++ b/bridge/rocketchat/rocketchat.go @@ -58,6 +58,10 @@ func (b *Brocketchat) JoinChannel(channel config.ChannelInfo) 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) matterMessage := matterhook.OMessage{IconURL: b.Config.IconURL} matterMessage.Channel = msg.Channel diff --git a/bridge/slack/slack.go b/bridge/slack/slack.go index c7205464..fa847db9 100644 --- a/bridge/slack/slack.go +++ b/bridge/slack/slack.go @@ -166,6 +166,16 @@ func (b *Bslack) Send(msg config.Message) (string, error) { // replace mentions np.LinkNames = 1 + if msg.Event == config.EVENT_MSG_DELETE { + // some protocols echo deletes, but with empty ID + if msg.ID == "" { + return "", nil + } + // we get a "slack ", 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) @@ -231,7 +241,7 @@ func (b *Bslack) handleSlack() { if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" && message.Username == b.si.User.Name { continue } - if message.Text == "" || message.Username == "" { + if (message.Text == "" || message.Username == "") && message.Raw.SubType != "message_deleted" { continue } text := message.Text @@ -250,6 +260,12 @@ func (b *Bslack) handleSlack() { 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 } } @@ -276,7 +292,7 @@ func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { continue } m := &MMMessage{} - if ev.BotID == "" { + if ev.BotID == "" && ev.SubType != "message_deleted" { user, err := b.rtm.GetUserInfo(ev.User) if err != nil { continue diff --git a/bridge/steam/steam.go b/bridge/steam/steam.go index 25291ff4..60b2f1bf 100644 --- a/bridge/steam/steam.go +++ b/bridge/steam/steam.go @@ -70,6 +70,10 @@ func (b *Bsteam) JoinChannel(channel config.ChannelInfo) 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) if err != nil { return "", err diff --git a/bridge/xmpp/xmpp.go b/bridge/xmpp/xmpp.go index d453706a..6999e801 100644 --- a/bridge/xmpp/xmpp.go +++ b/bridge/xmpp/xmpp.go @@ -80,6 +80,10 @@ func (b *Bxmpp) JoinChannel(channel config.ChannelInfo) 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) b.xc.Send(xmpp.Chat{Type: "groupchat", Remote: msg.Channel + "@" + b.Config.Muc, Text: msg.Username + msg.Text}) return "", nil diff --git a/changelog.md b/changelog.md index 9171658e..882878b4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,9 @@ # 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 diff --git a/matterclient/matterclient.go b/matterclient/matterclient.go index e348b760..732c9e30 100644 --- a/matterclient/matterclient.go +++ b/matterclient/matterclient.go @@ -299,7 +299,7 @@ func (m *MMClient) WsReceiver() { func (m *MMClient) parseMessage(rmsg *Message) { 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) /* case model.ACTION_USER_REMOVED: @@ -476,6 +476,14 @@ func (m *MMClient) EditMessage(postId string, text string) (string, 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 { m.RLock() defer m.RUnlock()