Browse Source

ContentWithMoreMentionsReplaced for roles and nicks (Fixes #208) (#375)

* ContentWithMentionReplaced on roles and nicks (Fixes #208)

* Compatibility

* Like this? :thinking:

* More efficient regexp

* Tweaked a little

* Tweaked a little more

* Tweaked even more

* Removed unessecary crap condition that is useless

* Disallow voice channel

* Moved regexp declaration
legolord208 7 years ago
parent
commit
5a02430c02
2 changed files with 100 additions and 7 deletions
  1. 59 7
      message.go
  2. 41 0
      message_test.go

+ 59 - 7
message.go

@@ -10,9 +10,9 @@
 package discordgo
 
 import (
-	"fmt"
 	"io"
 	"regexp"
+	"strings"
 )
 
 // A Message stores all data related to a specific Discord message.
@@ -172,13 +172,65 @@ type MessageReactions struct {
 
 // ContentWithMentionsReplaced will replace all @<id> mentions with the
 // username of the mention.
-func (m *Message) ContentWithMentionsReplaced() string {
-	if m.Mentions == nil {
-		return m.Content
+func (m *Message) ContentWithMentionsReplaced() (content string) {
+	content = m.Content
+
+	for _, user := range m.Mentions {
+		content = strings.NewReplacer(
+			"<@"+user.ID+">", "@"+user.Username,
+			"<@!"+user.ID+">", "@"+user.Username,
+		).Replace(content)
+	}
+	return
+}
+
+var patternChannels = regexp.MustCompile("<#[^>]*>")
+
+// ContentWithMoreMentionsReplaced will replace all @<id> mentions with the
+// username of the mention, but also role IDs and more.
+func (m *Message) ContentWithMoreMentionsReplaced(s *Session) (content string, err error) {
+	content = m.Content
+
+	if !s.StateEnabled {
+		content = m.ContentWithMentionsReplaced()
+		return
+	}
+
+	channel, err := s.State.Channel(m.ChannelID)
+	if err != nil {
+		content = m.ContentWithMentionsReplaced()
+		return
 	}
-	content := m.Content
+
 	for _, user := range m.Mentions {
-		content = regexp.MustCompile(fmt.Sprintf("<@!?(%s)>", user.ID)).ReplaceAllString(content, "@"+user.Username)
+		nick := user.Username
+
+		member, err := s.State.Member(channel.GuildID, user.ID)
+		if err == nil && member.Nick != "" {
+			nick = member.Nick
+		}
+
+		content = strings.NewReplacer(
+			"<@"+user.ID+">", "@"+user.Username,
+			"<@!"+user.ID+">", "@"+nick,
+		).Replace(content)
 	}
-	return content
+	for _, roleID := range m.MentionRoles {
+		role, err := s.State.Role(channel.GuildID, roleID)
+		if err != nil || !role.Mentionable {
+			continue
+		}
+
+		content = strings.Replace(content, "<&"+role.ID+">", "@"+role.Name, -1)
+	}
+
+	content = patternChannels.ReplaceAllStringFunc(content, func(mention string) string {
+		channel, err := s.State.Channel(mention[2 : len(mention)-1])
+		if err != nil || channel.Type == "voice" {
+			return mention
+		}
+
+		return "#" + channel.Name
+	})
+	return
 }

+ 41 - 0
message_test.go

@@ -0,0 +1,41 @@
+package discordgo
+
+import (
+	"testing"
+)
+
+func TestContentWithMoreMentionsReplaced(t *testing.T) {
+	s := &Session{StateEnabled: true, State: NewState()}
+
+	user := &User{
+		ID:       "user",
+		Username: "User Name",
+	}
+
+	s.StateEnabled = true
+	s.State.GuildAdd(&Guild{ID: "guild"})
+	s.State.RoleAdd("guild", &Role{
+		ID:          "role",
+		Name:        "Role Name",
+		Mentionable: true,
+	})
+	s.State.MemberAdd(&Member{
+		User:    user,
+		Nick:    "User Nick",
+		GuildID: "guild",
+	})
+	s.State.ChannelAdd(&Channel{
+		Name:    "Channel Name",
+		GuildID: "guild",
+		ID:      "channel",
+	})
+	m := &Message{
+		Content:      "<&role> <@!user> <@user> <#channel>",
+		ChannelID:    "channel",
+		MentionRoles: []string{"role"},
+		Mentions:     []*User{user},
+	}
+	if result, _ := m.ContentWithMoreMentionsReplaced(s); result != "@Role Name @User Nick @User Name #Channel Name" {
+		t.Error(result)
+	}
+}