diff --git a/message.go b/message.go index 34303b7..d46f3f3 100644 --- a/message.go +++ b/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 @ mentions with the // username of the mention. -func (m *Message) ContentWithMentionsReplaced() string { - if m.Mentions == nil { - return m.Content - } - content := m.Content +func (m *Message) ContentWithMentionsReplaced() (content string) { + content = m.Content + for _, user := range m.Mentions { - content = regexp.MustCompile(fmt.Sprintf("<@!?(%s)>", user.ID)).ReplaceAllString(content, "@"+user.Username) + content = strings.NewReplacer( + "<@"+user.ID+">", "@"+user.Username, + "<@!"+user.ID+">", "@"+user.Username, + ).Replace(content) } - return content + return +} + +var patternChannels = regexp.MustCompile("<#[^>]*>") + +// ContentWithMoreMentionsReplaced will replace all @ 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 + } + + for _, user := range m.Mentions { + 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) + } + 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 } diff --git a/message_test.go b/message_test.go new file mode 100644 index 0000000..fd2f133 --- /dev/null +++ b/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) + } +}