5
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2024-11-24 21:21:34 +00:00

Support webhook message deletions (discord) (#853)

* Support webhook message deletions (discord)

Messages sent via webhook can now be deleted. It seems it can do this
without any special permissions.

This copies discordgo.WebhookExecute and makes it support the returning
of discordgo.Message.

A pull request has been sent upstream, so we should use that if
@bwmariin accepts the pull request:

https://github.com/bwmarrin/discordgo/pull/663

Changes in behaviour (webhook mode only):
- Previously messages *edited* on other platforms would just be
retransmitted as a brand new message to Discord.
- Message *edits* will now be ignored.
- Debug: message edits will now print out a "permission error".

In the future it may be good to send an "message edited" react to those
webhook messages, so at least people know that the message was edited on
other platforms. (Even though it can't actually show the new message.)

Alternatively, message edits could just send a brand new message with a
link back to the old one. This is a little ugly but it would ensure that
Discord users are able to see the edited message. These "message edit
notifications" would be sent from the bot user (not from a webhook), so
we could edit the "edit notification" if subsequent edits to the
original message are made.
This commit is contained in:
Qais Patankar 2019-07-09 05:18:37 +09:00 committed by Wim
parent 278a3c6890
commit e60949ff3f
3 changed files with 53 additions and 9 deletions

View File

@ -209,11 +209,21 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
b.channelsMutex.RUnlock() b.channelsMutex.RUnlock()
// Use webhook to send the message // Use webhook to send the message
if wID != "" { if wID != "" && msg.Event != config.EventMsgDelete {
// skip events // skip events
if msg.Event != "" && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange { if msg.Event != "" && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange {
return "", nil return "", nil
} }
// If we are editing a message, delete the old message
if msg.ID != "" {
b.Log.Debugf("Deleting edited webhook message")
err := b.c.ChannelMessageDelete(channelID, msg.ID)
if err != nil {
b.Log.Errorf("Could not delete edited webhook message: %s", err)
}
}
b.Log.Debugf("Broadcasting using Webhook") b.Log.Debugf("Broadcasting using Webhook")
for _, f := range msg.Extra["file"] { for _, f := range msg.Extra["file"] {
fi := f.(config.FileInfo) fi := f.(config.FileInfo)
@ -251,7 +261,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
return "", err return "", err
} }
} }
err := b.c.WebhookExecute( msg, err := b.webhookExecute(
wID, wID,
wToken, wToken,
true, true,
@ -260,7 +270,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
Username: msg.Username, Username: msg.Username,
AvatarURL: msg.Avatar, AvatarURL: msg.Avatar,
}) })
return "", err return msg.ID, err
} }
b.Log.Debugf("Broadcasting using token (API)") b.Log.Debugf("Broadcasting using token (API)")

View File

@ -1,6 +1,7 @@
package bdiscord package bdiscord
import ( import (
"encoding/json"
"errors" "errors"
"regexp" "regexp"
"strings" "strings"
@ -187,3 +188,26 @@ func enumerateUsernames(s string) []string {
} }
return usernames return usernames
} }
// webhookExecute executes a webhook.
// webhookID: The ID of a webhook.
// token : The auth token for the webhook
// wait : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
func (b *Bdiscord) webhookExecute(webhookID, token string, wait bool, data *discordgo.WebhookParams) (st *discordgo.Message, err error) {
uri := discordgo.EndpointWebhookToken(webhookID, token)
if wait {
uri += "?wait=true"
}
response, err := b.c.RequestWithBucketID("POST", uri, data, discordgo.EndpointWebhookToken("", ""))
if !wait || err != nil {
return nil, err
}
err = json.Unmarshal(response, &st)
if err != nil {
return nil, discordgo.ErrJSONUnmarshal
}
return st, nil
}

View File

@ -125,7 +125,8 @@ func (r *Router) handleReceive() {
r.handleEventGetChannelMembers(&msg) r.handleEventGetChannelMembers(&msg)
r.handleEventFailure(&msg) r.handleEventFailure(&msg)
r.handleEventRejoinChannels(&msg) r.handleEventRejoinChannels(&msg)
idx := 0
filesHandled := false
for _, gw := range r.Gateways { for _, gw := range r.Gateways {
// record all the message ID's of the different bridges // record all the message ID's of the different bridges
var msgIDs []*BrMsgID var msgIDs []*BrMsgID
@ -134,17 +135,26 @@ func (r *Router) handleReceive() {
} }
msg.Timestamp = time.Now() msg.Timestamp = time.Now()
gw.modifyMessage(&msg) gw.modifyMessage(&msg)
if idx == 0 { if !filesHandled {
gw.handleFiles(&msg) gw.handleFiles(&msg)
filesHandled = true
} }
for _, br := range gw.Bridges { for _, br := range gw.Bridges {
msgIDs = append(msgIDs, 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.Protocol + " " + msg.ID); !ok && msg.ID != "" { if msg.ID != "" {
gw.Messages.Add(msg.Protocol+" "+msg.ID, msgIDs) _, exists := gw.Messages.Get(msg.Protocol + " " + msg.ID)
// Only add the message ID if it doesn't already exist
//
// For some bridges we always add/update the message ID.
// This is necessary as msgIDs will change if a bridge returns
// a different ID in response to edits.
if !exists || msg.Protocol == "discord" {
gw.Messages.Add(msg.Protocol+" "+msg.ID, msgIDs)
}
} }
idx++
} }
} }
} }