From ac4aee39e3256f9061d2057bb377862def4dd9d9 Mon Sep 17 00:00:00 2001
From: Alexandre GV <contact@alexandregv.fr>
Date: Thu, 13 May 2021 22:39:25 +0200
Subject: discord: Add AllowMention to restrict allowed mentions (#1462)

* Add DisablePingEveryoneHere/DisablePingRoles/DisablePingUsers keys to config

* Add basic AllowedMentions behavior to discord webhooks

* Initialize b.AllowedMentions on Discord Bridger init

* Call b.getAllowedMentions on each webhook to allow config hot reloading

* Add AllowedMentions on all Discord webhooks/messages

* Add DisablePingEveryoneHere/DisablePingRoles/DisablePingUsers to matterbridge.toml.sample

* Change 'Disable' for 'Allow' and revert logic in Discord AllowedMentions

* Update Discord AllowedMentions in matterbridge.toml.sample

* Fix typo in DisableWebPagePreview

* Replace 'AllowPingEveryoneHere' with 'AllowPingEveryone'

* Replace 3 AllowPingEveryone/Roles/Users bools with an array

* Fix typo
---
 bridge/config/config.go   | 43 ++++++++++++++++++++++---------------------
 bridge/discord/discord.go |  8 +++++---
 bridge/discord/helpers.go | 24 ++++++++++++++++++++++++
 bridge/discord/webhook.go | 21 ++++++++++++---------
 4 files changed, 63 insertions(+), 33 deletions(-)

(limited to 'bridge')

diff --git a/bridge/config/config.go b/bridge/config/config.go
index 98935208..b5e03fcf 100644
--- a/bridge/config/config.go
+++ b/bridge/config/config.go
@@ -85,27 +85,28 @@ type ChannelMember struct {
 type ChannelMembers []ChannelMember
 
 type Protocol struct {
-	AuthCode               string // steam
-	BindAddress            string // mattermost, slack // DEPRECATED
-	Buffer                 int    // api
-	Charset                string // irc
-	ClientID               string // msteams
-	ColorNicks             bool   // only irc for now
-	Debug                  bool   // general
-	DebugLevel             int    // only for irc now
-	DisableWebPagePreview  bool   // telegram
-	EditSuffix             string // mattermost, slack, discord, telegram, gitter
-	EditDisable            bool   // mattermost, slack, discord, telegram, gitter
-	HTMLDisable            bool   // matrix
-	IconURL                string // mattermost, slack
-	IgnoreFailureOnStart   bool   // general
-	IgnoreNicks            string // all protocols
-	IgnoreMessages         string // all protocols
-	Jid                    string // xmpp
-	JoinDelay              string // all protocols
-	Label                  string // all protocols
-	Login                  string // mattermost, matrix
-	LogFile                string // general
+	AllowMention           []string // discord
+	AuthCode               string   // steam
+	BindAddress            string   // mattermost, slack // DEPRECATED
+	Buffer                 int      // api
+	Charset                string   // irc
+	ClientID               string   // msteams
+	ColorNicks             bool     // only irc for now
+	Debug                  bool     // general
+	DebugLevel             int      // only for irc now
+	DisableWebPagePreview  bool     // telegram
+	EditSuffix             string   // mattermost, slack, discord, telegram, gitter
+	EditDisable            bool     // mattermost, slack, discord, telegram, gitter
+	HTMLDisable            bool     // matrix
+	IconURL                string   // mattermost, slack
+	IgnoreFailureOnStart   bool     // general
+	IgnoreNicks            string   // all protocols
+	IgnoreMessages         string   // all protocols
+	Jid                    string   // xmpp
+	JoinDelay              string   // all protocols
+	Label                  string   // all protocols
+	Login                  string   // mattermost, matrix
+	LogFile                string   // general
 	MediaDownloadBlackList []string
 	MediaDownloadPath      string // Basically MediaServerUpload, but instead of uploading it, just write it to a file on the same server.
 	MediaDownloadSize      int    // all protocols
diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go
index 9cc83ddc..2fcf0abc 100644
--- a/bridge/discord/discord.go
+++ b/bridge/discord/discord.go
@@ -304,7 +304,8 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st
 	}
 
 	m := discordgo.MessageSend{
-		Content: msg.Username + msg.Text,
+		Content:         msg.Username + msg.Text,
+		AllowedMentions: b.getAllowedMentions(),
 	}
 
 	if msg.ParentValid() {
@@ -335,8 +336,9 @@ func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (stri
 			Reader:      bytes.NewReader(*fi.Data),
 		}
 		m := discordgo.MessageSend{
-			Content: msg.Username + fi.Comment,
-			Files:   []*discordgo.File{&file},
+			Content:         msg.Username + fi.Comment,
+			Files:           []*discordgo.File{&file},
+			AllowedMentions: b.getAllowedMentions(),
 		}
 		_, err = b.c.ChannelMessageSendComplex(channelID, &m)
 		if err != nil {
diff --git a/bridge/discord/helpers.go b/bridge/discord/helpers.go
index 9545a3ae..4e453ad7 100644
--- a/bridge/discord/helpers.go
+++ b/bridge/discord/helpers.go
@@ -9,6 +9,30 @@ import (
 	"github.com/matterbridge/discordgo"
 )
 
+func (b *Bdiscord) getAllowedMentions() *discordgo.MessageAllowedMentions {
+	// If AllowMention is not specified, then allow all mentions (default Discord behavior)
+	if !b.IsKeySet("AllowMention") {
+		return nil
+	}
+
+	// Otherwise, allow only the mentions that are specified
+	allowedMentionTypes := make([]discordgo.AllowedMentionType, 0, 3)
+	for _, m := range b.GetStringSlice("AllowMention") {
+		switch m {
+		case "everyone":
+			allowedMentionTypes = append(allowedMentionTypes, discordgo.AllowedMentionTypeEveryone)
+		case "roles":
+			allowedMentionTypes = append(allowedMentionTypes, discordgo.AllowedMentionTypeRoles)
+		case "users":
+			allowedMentionTypes = append(allowedMentionTypes, discordgo.AllowedMentionTypeUsers)
+		}
+	}
+
+	return &discordgo.MessageAllowedMentions{
+		Parse: allowedMentionTypes,
+	}
+}
+
 func (b *Bdiscord) getNick(user *discordgo.User, guildID string) string {
 	b.membersMutex.RLock()
 	defer b.membersMutex.RUnlock()
diff --git a/bridge/discord/webhook.go b/bridge/discord/webhook.go
index 7dacc7cd..9177db07 100644
--- a/bridge/discord/webhook.go
+++ b/bridge/discord/webhook.go
@@ -63,9 +63,10 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
 		res, err = b.transmitter.Send(
 			channelID,
 			&discordgo.WebhookParams{
-				Content:   msg.Text,
-				Username:  msg.Username,
-				AvatarURL: msg.Avatar,
+				Content:         msg.Text,
+				Username:        msg.Username,
+				AvatarURL:       msg.Avatar,
+				AllowedMentions: b.getAllowedMentions(),
 			},
 		)
 		if err != nil {
@@ -88,10 +89,11 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
 			_, e2 := b.transmitter.Send(
 				channelID,
 				&discordgo.WebhookParams{
-					Username:  msg.Username,
-					AvatarURL: msg.Avatar,
-					File:      &file,
-					Content:   content,
+					Username:        msg.Username,
+					AvatarURL:       msg.Avatar,
+					File:            &file,
+					Content:         content,
+					AllowedMentions: b.getAllowedMentions(),
 				},
 			)
 			if e2 != nil {
@@ -124,8 +126,9 @@ 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{
-			Content:  msg.Text,
-			Username: msg.Username,
+			Content:         msg.Text,
+			Username:        msg.Username,
+			AllowedMentions: b.getAllowedMentions(),
 		})
 		if err == nil {
 			return msg.ID, nil
-- 
cgit v1.2.3