summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWim <wim@42.be>2017-09-11 22:45:15 +0200
committerWim <wim@42.be>2017-09-11 22:45:15 +0200
commited018207226912ee57ecaae06c539aea37e7bb96 (patch)
tree4426d2bfd3041c9110b9b2e4ad38c35e9e918bff
parent90a61f15cc93ddca78f598dc6856c759a91bd96a (diff)
downloadmatterbridge-msglm-ed018207226912ee57ecaae06c539aea37e7bb96.tar.gz
matterbridge-msglm-ed018207226912ee57ecaae06c539aea37e7bb96.tar.bz2
matterbridge-msglm-ed018207226912ee57ecaae06c539aea37e7bb96.zip
Add support for deleting messages across bridges.
Currently fully support mattermost,slack and discord. Message deleted on the bridge or received from other bridges will be deleted. Partially support for Gitter. Gitter bridge will delete messages received from other bridges. But if you delete a message on gitter, this deletion will not be sent to other bridges (this is a gitter API limitation, it doesn't propogate edits or deletes via the API)
-rw-r--r--bridge/api/api.go4
-rw-r--r--bridge/config/config.go1
-rw-r--r--bridge/discord/discord.go20
-rw-r--r--bridge/gitter/gitter.go11
-rw-r--r--bridge/irc/irc.go4
-rw-r--r--bridge/matrix/matrix.go4
-rw-r--r--bridge/mattermost/mattermost.go14
-rw-r--r--bridge/rocketchat/rocketchat.go4
-rw-r--r--bridge/slack/slack.go20
-rw-r--r--bridge/steam/steam.go4
-rw-r--r--bridge/xmpp/xmpp.go4
-rw-r--r--changelog.md3
-rw-r--r--matterclient/matterclient.go10
13 files changed, 98 insertions, 5 deletions
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 <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)
@@ -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()