summaryrefslogtreecommitdiffstats
path: root/bridge/discord/helpers.go
diff options
context:
space:
mode:
Diffstat (limited to 'bridge/discord/helpers.go')
-rw-r--r--bridge/discord/helpers.go189
1 files changed, 189 insertions, 0 deletions
diff --git a/bridge/discord/helpers.go b/bridge/discord/helpers.go
new file mode 100644
index 00000000..e693498c
--- /dev/null
+++ b/bridge/discord/helpers.go
@@ -0,0 +1,189 @@
+package bdiscord
+
+import (
+ "errors"
+ "regexp"
+ "strings"
+ "unicode"
+
+ "github.com/bwmarrin/discordgo"
+)
+
+func (b *Bdiscord) getNick(user *discordgo.User) string {
+ b.membersMutex.RLock()
+ defer b.membersMutex.RUnlock()
+
+ if member, ok := b.userMemberMap[user.ID]; ok {
+ if member.Nick != "" {
+ // Only return if nick is set.
+ return member.Nick
+ }
+ // Otherwise return username.
+ return user.Username
+ }
+
+ // If we didn't find nick, search for it.
+ member, err := b.c.GuildMember(b.guildID, user.ID)
+ if err != nil {
+ b.Log.Warnf("Failed to fetch information for member %#v: %#v", user, err)
+ return user.Username
+ } else if member == nil {
+ b.Log.Warnf("Got no information for member %#v", user)
+ return user.Username
+ }
+ b.userMemberMap[user.ID] = member
+ b.nickMemberMap[member.User.Username] = member
+ if member.Nick != "" {
+ b.nickMemberMap[member.Nick] = member
+ return member.Nick
+ }
+ return user.Username
+}
+
+func (b *Bdiscord) getGuildMemberByNick(nick string) (*discordgo.Member, error) {
+ b.membersMutex.RLock()
+ defer b.membersMutex.RUnlock()
+
+ if member, ok := b.nickMemberMap[nick]; ok {
+ 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 {
+ b.channelsMutex.RLock()
+ defer b.channelsMutex.RUnlock()
+
+ idcheck := strings.Split(name, "ID:")
+ if len(idcheck) > 1 {
+ return idcheck[1]
+ }
+ for _, channel := range b.channels {
+ if channel.Name == name {
+ return channel.ID
+ }
+ }
+ return ""
+}
+
+func (b *Bdiscord) getChannelName(id string) string {
+ b.channelsMutex.RLock()
+ defer b.channelsMutex.RUnlock()
+
+ for _, channel := range b.channels {
+ if channel.ID == id {
+ return channel.Name
+ }
+ }
+ return ""
+}
+
+var (
+ // See https://discordapp.com/developers/docs/reference#message-formatting.
+ channelMentionRE = regexp.MustCompile("<#[0-9]+>")
+ emojiRE = regexp.MustCompile("<(:.*?:)[0-9]+>")
+ userMentionRE = regexp.MustCompile("@[^@\n]{1,32}")
+)
+
+func (b *Bdiscord) replaceChannelMentions(text string) string {
+ replaceChannelMentionFunc := func(match string) string {
+ var err error
+ channelID := match[2 : len(match)-1]
+
+ channelName := b.getChannelName(channelID)
+ // If we don't have the channel refresh our list.
+ if channelName == "" {
+ b.channels, err = b.c.GuildChannels(b.guildID)
+ if err != nil {
+ return "#unknownchannel"
+ }
+ channelName = b.getChannelName(channelID)
+ }
+ return "#" + channelName
+ }
+ return channelMentionRE.ReplaceAllStringFunc(text, replaceChannelMentionFunc)
+}
+
+func (b *Bdiscord) replaceUserMentions(text string) string {
+ replaceUserMentionFunc := func(match string) string {
+ var (
+ err error
+ member *discordgo.Member
+ username string
+ )
+
+ usernames := enumerateUsernames(match[1:])
+ for _, username = range usernames {
+ b.Log.Debugf("Testing mention: '%s'", username)
+ member, err = b.getGuildMemberByNick(username)
+ if err == nil {
+ break
+ }
+ }
+ if member == nil {
+ return match
+ }
+ return strings.Replace(match, "@"+username, member.User.Mention(), 1)
+ }
+ return userMentionRE.ReplaceAllStringFunc(text, replaceUserMentionFunc)
+}
+
+func (b *Bdiscord) stripCustomoji(text string) string {
+ return emojiRE.ReplaceAllString(text, `$1`)
+}
+
+func (b *Bdiscord) replaceAction(text string) (string, bool) {
+ if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") {
+ return text[1:], true
+ }
+ return text, false
+}
+
+// splitURL splits a webhookURL and returns the ID and token.
+func (b *Bdiscord) splitURL(url string) (string, string) {
+ const (
+ expectedWebhookSplitCount = 7
+ webhookIdxID = 5
+ webhookIdxToken = 6
+ )
+ webhookURLSplit := strings.Split(url, "/")
+ if len(webhookURLSplit) != expectedWebhookSplitCount {
+ b.Log.Fatalf("%s is no correct discord WebhookURL", url)
+ }
+ return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken]
+}
+
+func enumerateUsernames(s string) []string {
+ onlySpace := true
+ for _, r := range s {
+ if !unicode.IsSpace(r) {
+ onlySpace = false
+ break
+ }
+ }
+ if onlySpace {
+ return nil
+ }
+
+ var username, endSpace string
+ var usernames []string
+ skippingSpace := true
+ for _, r := range s {
+ if unicode.IsSpace(r) {
+ if !skippingSpace {
+ usernames = append(usernames, username)
+ skippingSpace = true
+ }
+ endSpace += string(r)
+ username += string(r)
+ } else {
+ endSpace = ""
+ username += string(r)
+ skippingSpace = false
+ }
+ }
+ if endSpace == "" {
+ usernames = append(usernames, username)
+ }
+ return usernames
+}