Add support for discord forum channels/threads (discord)
Messages send to forum threads need to use the ID of the forum for the webhook but also need to set an additional parameter during the API call to specify the destination thread. Receiving messages from threads works by using the thread ID. The forum ID is not required. This commit adds an optional channel option "ForumID" which can be used to supply the forum ID of a thread (= channel). When sending/editing messages the ForumID will be used for the webhook and the channel ID will be supplied as the additional parameter "thread_id". Fixes #1908
This commit is contained in:
@@ -181,6 +181,7 @@ type Protocol struct {
|
||||
type ChannelOptions struct {
|
||||
Key string // irc, xmpp
|
||||
WebhookURL string // discord
|
||||
ForumID string // discord
|
||||
Topic string // zulip
|
||||
}
|
||||
|
||||
|
||||
@@ -63,13 +63,13 @@ func New(session *discordgo.Session, guild string, title string, autoCreate bool
|
||||
}
|
||||
|
||||
// Send transmits a message to the given channel with the provided webhook data, and waits until Discord responds with message data.
|
||||
func (t *Transmitter) Send(channelID string, params *discordgo.WebhookParams) (*discordgo.Message, error) {
|
||||
func (t *Transmitter) SendThread(channelID string, threadID string, params *discordgo.WebhookParams) (*discordgo.Message, error) {
|
||||
wh, err := t.getOrCreateWebhook(channelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg, err := t.session.WebhookExecute(wh.ID, wh.Token, true, params)
|
||||
msg, err := t.session.WebhookThreadExecute(wh.ID, wh.Token, true, threadID, params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("execute failed: %w", err)
|
||||
}
|
||||
@@ -77,15 +77,24 @@ func (t *Transmitter) Send(channelID string, params *discordgo.WebhookParams) (*
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (t *Transmitter) Send(channelID string, params *discordgo.WebhookParams) (*discordgo.Message, error) {
|
||||
return t.SendThread(channelID, "", params)
|
||||
}
|
||||
|
||||
// Edit will edit a message in a channel, if possible.
|
||||
func (t *Transmitter) Edit(channelID string, messageID string, params *discordgo.WebhookParams) error {
|
||||
func (t *Transmitter) EditThread(channelID string, threadID string, messageID string, params *discordgo.WebhookParams) error {
|
||||
wh := t.getWebhook(channelID)
|
||||
|
||||
if wh == nil {
|
||||
return ErrWebhookNotFound
|
||||
}
|
||||
|
||||
uri := discordgo.EndpointWebhookToken(wh.ID, wh.Token) + "/messages/" + messageID
|
||||
threadParam := ""
|
||||
if threadID != "" {
|
||||
threadParam = "?thread_id=" + threadID
|
||||
}
|
||||
|
||||
uri := discordgo.EndpointWebhookToken(wh.ID, wh.Token) + "/messages/" + messageID + threadParam
|
||||
_, err := t.session.RequestWithBucketID("PATCH", uri, params, discordgo.EndpointWebhookToken("", ""))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -94,6 +103,10 @@ func (t *Transmitter) Edit(channelID string, messageID string, params *discordgo
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transmitter) Edit(channelID string, messageID string, params *discordgo.WebhookParams) error {
|
||||
return t.EditThread(channelID, "", messageID, params)
|
||||
}
|
||||
|
||||
// HasWebhook checks whether the transmitter is using a particular webhook.
|
||||
func (t *Transmitter) HasWebhook(id string) bool {
|
||||
t.mutex.RLock()
|
||||
|
||||
@@ -42,10 +42,10 @@ func (b *Bdiscord) maybeGetLocalAvatar(msg *config.Message) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// webhookSend send one or more message via webhook, taking care of file
|
||||
// uploads (from slack, telegram or mattermost).
|
||||
// webhookSendThread send one or more message via webhook, taking care of file
|
||||
// uploads (from slack, telegram or mattermost) and forum threads.
|
||||
// Returns messageID and error.
|
||||
func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordgo.Message, error) {
|
||||
func (b *Bdiscord) webhookSendThread(msg *config.Message, channelID string, threadID string) (*discordgo.Message, error) {
|
||||
var (
|
||||
res *discordgo.Message
|
||||
res2 *discordgo.Message
|
||||
@@ -61,8 +61,9 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
|
||||
|
||||
// We can't send empty messages.
|
||||
if msg.Text != "" {
|
||||
res, err = b.transmitter.Send(
|
||||
res, err = b.transmitter.SendThread(
|
||||
channelID,
|
||||
threadID,
|
||||
&discordgo.WebhookParams{
|
||||
Content: msg.Text,
|
||||
Username: msg.Username,
|
||||
@@ -85,8 +86,9 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
|
||||
}
|
||||
content := fi.Comment
|
||||
|
||||
res2, err = b.transmitter.Send(
|
||||
res2, err = b.transmitter.SendThread(
|
||||
channelID,
|
||||
threadID,
|
||||
&discordgo.WebhookParams{
|
||||
Username: msg.Username,
|
||||
AvatarURL: msg.Avatar,
|
||||
@@ -108,6 +110,10 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordgo.Message, error) {
|
||||
return b.webhookSendThread(msg, channelID, "")
|
||||
}
|
||||
|
||||
func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (string, error) {
|
||||
// skip events
|
||||
if msg.Event != "" && msg.Event != config.EventUserAction && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange {
|
||||
@@ -120,6 +126,15 @@ func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (st
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// If ForumID is set, it should be used as channelID for the webhook and the channelID is used as the thread_id
|
||||
threadID := ""
|
||||
if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok {
|
||||
if ci.Options.ForumID != "" {
|
||||
threadID = channelID
|
||||
channelID = ci.Options.ForumID
|
||||
}
|
||||
}
|
||||
|
||||
msg.Text = helper.ClipMessage(msg.Text, MessageLength, b.GetString("MessageClipped"))
|
||||
msg.Text = b.replaceUserMentions(msg.Text)
|
||||
// discord username must be [0..32] max
|
||||
@@ -129,7 +144,7 @@ func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (st
|
||||
|
||||
if msg.ID != "" {
|
||||
b.Log.Debugf("Editing webhook message")
|
||||
err := b.transmitter.Edit(channelID, msg.ID, &discordgo.WebhookParams{
|
||||
err := b.transmitter.EditThread(channelID, threadID, msg.ID, &discordgo.WebhookParams{
|
||||
Content: msg.Text,
|
||||
Username: msg.Username,
|
||||
AllowedMentions: b.getAllowedMentions(),
|
||||
@@ -141,7 +156,7 @@ func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (st
|
||||
}
|
||||
|
||||
b.Log.Debugf("Processing webhook sending for message %#v", msg)
|
||||
discordMsg, err := b.webhookSend(msg, channelID)
|
||||
discordMsg, err := b.webhookSendThread(msg, channelID, threadID)
|
||||
if err != nil {
|
||||
b.Log.Errorf("Could not broadcast via webhook for message %#v: %s", msg, err)
|
||||
return "", err
|
||||
|
||||
@@ -1928,8 +1928,13 @@ enable=true
|
||||
channel="mygreatgame"
|
||||
|
||||
[gateway.inout.options]
|
||||
# WebhookURL sends messages in the style of "puppets". You must configure a webhook URL for each channel you want to bridge.
|
||||
# OPTIONAL - ForumID: the ID of the forum channel containing the thread. The thread ID should be used for "channel" then.
|
||||
# Note: Do not add "ID:" at the beginning of the ForumID.
|
||||
# Example: "123456789"
|
||||
ForumID=""
|
||||
# OPTIONAL - WebhookURL sends messages in the style of "puppets". You must configure a webhook URL for each channel you want to bridge.
|
||||
# If you have more than one channel and don't wnat to configure each channel manually, see the "AutoWebhooks" option in the gateway config.
|
||||
# WebhookURL does not support forum channels (URLs containing "?thread_id="), see "ForumID"
|
||||
# Example: "https://discord.com/api/webhooks/1234/abcd_xyzw"
|
||||
WebhookURL=""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user