Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for discord forum channels/threads (discord) #1914

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bridge/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ type Protocol struct {
type ChannelOptions struct {
Key string // irc, xmpp
WebhookURL string // discord
ForumID string // discord
Topic string // zulip
}

Expand Down
21 changes: 17 additions & 4 deletions bridge/discord/transmitter/transmitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,38 @@ 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)
}

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
Expand All @@ -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()
Expand Down
29 changes: 22 additions & 7 deletions bridge/discord/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method Bdiscord.webhookSendThread has 52 lines of code (exceeds 50 allowed). Consider refactoring.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think a shorter function (even by two lines) will improve the understanding of this code. Is it possible to ignore the "issue" at this point?

var (
res *discordgo.Message
res2 *discordgo.Message
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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(),
Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion matterbridge.toml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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=""

Expand Down