From e3d40acda06b845b74f30c0c9140d66c0a69ebdc Mon Sep 17 00:00:00 2001 From: Jerry Heiselman Date: Thu, 30 Aug 2018 20:20:48 -0500 Subject: [PATCH 1/2] Added check for @-mention pattern and replacing it with a user with a matching Nick on incoming messages --- bridge/discord/discord.go | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index b424e4b0..fa47ff12 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -2,6 +2,7 @@ package bdiscord import ( "bytes" + "errors" "fmt" "regexp" "strings" @@ -181,6 +182,8 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { } msg.Text = helper.ClipMessage(msg.Text, MessageLength) + msg.Text = b.replaceUserMentions(msg.Text) + // Edit message if msg.ID != "" { _, err := b.c.ChannelMessageEdit(channelID, msg.ID, msg.Username+msg.Text) @@ -323,6 +326,37 @@ func (b *Bdiscord) getNick(user *discordgo.User) string { return user.Username } +func (b *Bdiscord) getGuildMemberByNick(nick string) (*discordgo.Member, error) { + // Check to see if we have the nick in userMemberMap + b.Log.Debugln("Checking the userMemberMap for cached user information") + for uid := range b.userMemberMap { + if b.getNick(b.userMemberMap[uid].User) == nick { + b.Log.Debugf("Found user with nick '" + nick + " in userMemberMap at uid=" + uid + "\n") + return b.userMemberMap[uid], nil + } + } + + // The user wasn't in the map, so go ahead an make the API call to get it + members, err := b.c.GuildMembers(b.guildID, "", 1000) + if err != nil { + b.Log.Error("Error obtaining guild members", err) + return nil, err + } + for _, member := range members { + if member.User == nil { + member.User, err = b.c.User(nick) + if err != nil { + return nil, errors.New("Couldn't find guild member with nick " + nick) + } + } + b.Log.Debugf("Checking %s == %s", b.getNick(member.User), nick) + if b.getNick(member.User) == nick { + return member, nil + } + } + return nil, errors.New("Couldn't find guild member with nick " + nick) // This will most likely get ignored by the caller +} + func (b *Bdiscord) getChannelID(name string) string { idcheck := strings.Split(name, "ID:") if len(idcheck) > 1 { @@ -364,6 +398,21 @@ func (b *Bdiscord) replaceChannelMentions(text string) string { return text } +func (b *Bdiscord) replaceUserMentions(text string) string { + re := regexp.MustCompile("@[^ ]+") + text = re.ReplaceAllStringFunc(text, func(m string) string { + mention := m[1:] + b.Log.Debugf("Testing mention: '%s'", mention) + member, err := b.getGuildMemberByNick(mention) + if err != nil { + return m + } + return member.User.Mention() + }) + b.Log.Debugf("Message with mention replaced: %s", text) + return text +} + func (b *Bdiscord) replaceAction(text string) (string, bool) { if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") { return strings.Replace(text, "_", "", -1), true From 8274f85feb0f4448d5ce770a4561b68e20c94a72 Mon Sep 17 00:00:00 2001 From: Jerry Heiselman Date: Tue, 4 Sep 2018 11:31:49 -0500 Subject: [PATCH 2/2] Create new nickMemberMap field and lock in getGuildMemberByNick --- bridge/discord/discord.go | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/bridge/discord/discord.go b/bridge/discord/discord.go index fa47ff12..fe956b9c 100644 --- a/bridge/discord/discord.go +++ b/bridge/discord/discord.go @@ -22,6 +22,7 @@ type Bdiscord struct { Nick string UseChannelID bool userMemberMap map[string]*discordgo.Member + nickMemberMap map[string]*discordgo.Member guildID string webhookID string webhookToken string @@ -319,6 +320,7 @@ func (b *Bdiscord) getNick(user *discordgo.User) string { return user.Username } b.userMemberMap[user.ID] = member + b.nickMemberMap[member.Nick] = member // only return if nick is set if b.userMemberMap[user.ID].Nick != "" { return b.userMemberMap[user.ID].Nick @@ -327,33 +329,14 @@ func (b *Bdiscord) getNick(user *discordgo.User) string { } func (b *Bdiscord) getGuildMemberByNick(nick string) (*discordgo.Member, error) { - // Check to see if we have the nick in userMemberMap - b.Log.Debugln("Checking the userMemberMap for cached user information") - for uid := range b.userMemberMap { - if b.getNick(b.userMemberMap[uid].User) == nick { - b.Log.Debugf("Found user with nick '" + nick + " in userMemberMap at uid=" + uid + "\n") - return b.userMemberMap[uid], nil + b.Lock() + defer b.Unlock() + if _, ok := b.nickMemberMap[nick]; ok { + if b.nickMemberMap[nick] != nil { + return b.nickMemberMap[nick], nil } } - // The user wasn't in the map, so go ahead an make the API call to get it - members, err := b.c.GuildMembers(b.guildID, "", 1000) - if err != nil { - b.Log.Error("Error obtaining guild members", err) - return nil, err - } - for _, member := range members { - if member.User == nil { - member.User, err = b.c.User(nick) - if err != nil { - return nil, errors.New("Couldn't find guild member with nick " + nick) - } - } - b.Log.Debugf("Checking %s == %s", b.getNick(member.User), nick) - if b.getNick(member.User) == nick { - return member, nil - } - } return nil, errors.New("Couldn't find guild member with nick " + nick) // This will most likely get ignored by the caller }