Cleanup message receive code in order to make it more concise and faster
ADD
discordutil/message.go
+package discordutil
+
+import "github.com/Bios-Marcel/discordgo"
+
+func MentionsCurrentUserExplicitly(state *discordgo.State, message *discordgo.Message) bool {
+ for _, user := range message.Mentions {
+ if user.ID == state.User.ID {
+ return true
+ break
+ }
+ }
+
+ return false
+}

ADD
discordutil/message_test.go
+package discordutil
+
+import (
+ "github.com/Bios-Marcel/discordgo"
+ "testing"
+)
+
+func Test_MentionsCurrentUserExplicitly(t *testing.T) {
+ state := &discordgo.State{
+ Ready: discordgo.Ready{
+ User: &discordgo.User{
+ ID: "123",
+ },
+ },
+ }
+
+ tests := []struct {
+ name string
+ message *discordgo.Message
+ want bool
+ }{
+ {
+ name: "no mentions",
+ message: &discordgo.Message{},
+ want: false,
+ }, {
+ name: "one foreign mention",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "1"},
+ },
+ },
+ want: false,
+ }, {
+ name: "multiple foreign mention",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "1"},
+ &discordgo.User{ID: "2"},
+ &discordgo.User{ID: "3"},
+ &discordgo.User{ID: "4"},
+ },
+ },
+ want: false,
+ },{
+ name: "one mention for current user",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "123"},
+ },
+ },
+ want: true,
+ }, {
+ name: "multiple mentions containing one for current user in the middle",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "1"},
+ &discordgo.User{ID: "2"},
+ &discordgo.User{ID: "123"},
+ &discordgo.User{ID: "4"},
+ &discordgo.User{ID: "5"},
+ },
+ },
+ want: true,
+ }, {
+ name: "multiple mentions containing one for current user in the end",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "1"},
+ &discordgo.User{ID: "2"},
+ &discordgo.User{ID: "3"},
+ &discordgo.User{ID: "4"},
+ &discordgo.User{ID: "123"},
+ },
+ },
+ want: true,
+ }, {
+ name: "multiple mentions containing one for current user in the beginning",
+ message: &discordgo.Message{
+ Mentions: []*discordgo.User{
+ &discordgo.User{ID: "123"},
+ &discordgo.User{ID: "2"},
+ &discordgo.User{ID: "3"},
+ &discordgo.User{ID: "4"},
+ &discordgo.User{ID: "5"},
+ },
+ },
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := MentionsCurrentUserExplicitly(state, tt.message); got != tt.want {
+ t.Errorf("MentionsCurrentUserExplicitly() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}

MODIFY
ui/window.go
ui/window.go
@@ -220,7 +220,6 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
window.privateList.Load()
window.registerPrivateChatsHandler()
-
if config.GetConfig().MouseEnabled {
privatePage := tview.NewFlex().SetDirection(tview.FlexRow)
switchToGuildButton := tview.NewButton("Show Guilds")
@@ -1284,31 +1283,31 @@ func (window *Window) registerMessageEventHandler(input, edit, delete chan *disc
// events. It updates the cache and the UI if necessary.
func (window *Window) startMessageHandlerRoutines(input, edit, delete chan *discordgo.Message, bulkDelete chan *discordgo.MessageDeleteBulk) {
go func() {
- for message := range input {
- tempMessage := message
- window.session.State.MessageAdd(tempMessage)
+ for tempMessage := range input {
+ message := tempMessage
+ window.session.State.MessageAdd(message)
- channel, stateError := window.session.State.Channel(tempMessage.ChannelID)
+ channel, stateError := window.session.State.Channel(message.ChannelID)
if stateError != nil {
continue
}
window.chatView.Lock()
- if window.selectedChannel != nil && tempMessage.ChannelID == window.selectedChannel.ID {
- if tempMessage.Author.ID != window.session.State.User.ID {
- readstate.UpdateReadBuffered(window.session, channel, tempMessage.ID)
+ if window.selectedChannel != nil && message.ChannelID == window.selectedChannel.ID {
+ if message.Author.ID != window.session.State.User.ID {
+ readstate.UpdateReadBuffered(window.session, channel, message.ID)
}
window.app.QueueUpdateDraw(func() {
- window.chatView.AddMessage(tempMessage)
+ window.chatView.AddMessage(message)
})
}
window.chatView.Unlock()
- if channel.Type == discordgo.ChannelTypeGuildText {
+ if channel.Type == discordgo.ChannelTypeGuildText && window.selectedGuild == nil ||
+ window.selectedGuild.ID != channel.GuildID {
for _, guildNode := range window.guildList.GetRoot().GetChildren() {
- if guildNode.GetReference() == channel.GuildID &&
- (window.selectedGuild == nil || window.selectedGuild.ID != channel.GuildID) {
+ if guildNode.GetReference() == channel.GuildID {
window.app.QueueUpdateDraw(func() {
window.updateServerReadStatus(channel.GuildID, guildNode, false)
})
@@ -1317,44 +1316,38 @@ func (window *Window) startMessageHandlerRoutines(input, edit, delete chan *disc
}
}
- if channel.Type == discordgo.ChannelTypeGuildText || channel.Type == discordgo.ChannelTypeDM ||
- channel.Type == discordgo.ChannelTypeGroupDM {
// TODO,HACK.FIXME Since the cache is inconsistent, I have to
// update it myself. This should be moved over into the
// discordgo code ASAP.
channel.LastMessageID = message.ID
+
+ if channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM {
+ //Avoid unnecessary drawing if the updates wouldn't be visible either way.
+ //FIXME Useful to use locking here?
+ if window.leftArea.GetCurrentPage() == privatePageName {
window.app.QueueUpdateDraw(func() {
window.privateList.ReorderChannelList()
})
+ } else {
+ window.privateList.ReorderChannelList()
}
-
- if tempMessage.Author.ID == window.session.State.User.ID {
- readstate.UpdateReadLocal(tempMessage.ChannelID, tempMessage.ID)
- continue
}
- if (window.selectedChannel == nil || tempMessage.ChannelID != window.selectedChannel.ID) ||
- !window.userActive {
- mentionsYou := false
- for _, user := range tempMessage.Mentions {
- if user.ID == window.session.State.User.ID {
- mentionsYou = true
- break
- }
+ if message.Author.ID == window.session.State.User.ID {
+ readstate.UpdateReadLocal(message.ChannelID, message.ID)
+ continue
}
- if config.GetConfig().DesktopNotifications {
- if !mentionsYou {
- if channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM {
- mentionsYou = true
- }
- }
+ if window.selectedChannel == nil || message.ChannelID != window.selectedChannel.ID {
+ mentionsCurrentUser := discordutil.MentionsCurrentUserExplicitly(window.session.State, message)
+ if !window.userActive && config.GetConfig().DesktopNotifications {
+ if mentionsCurrentUser ||
+ //Always show notification for private messages
+ channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM {
- if mentionsYou {
var notificationLocation string
-
if channel.Type == discordgo.ChannelTypeDM {
- notificationLocation = tempMessage.Author.Username
+ notificationLocation = message.Author.Username
} else if channel.Type == discordgo.ChannelTypeGroupDM {
notificationLocation = channel.Name
if notificationLocation == "" {
@@ -1367,32 +1360,23 @@ func (window *Window) startMessageHandlerRoutines(input, edit, delete chan *disc
}
}
- notificationLocation = tempMessage.Author.Username + " - " + notificationLocation
+ notificationLocation = message.Author.Username + " - " + notificationLocation
} else if channel.Type == discordgo.ChannelTypeGuildText {
- if tempMessage.GuildID != "" {
- guild, cacheError := window.session.State.Guild(tempMessage.GuildID)
+ guild, cacheError := window.session.State.Guild(message.GuildID)
if guild != nil && cacheError == nil {
- notificationLocation = fmt.Sprintf("%s - %s - %s", guild.Name, channel.Name, tempMessage.Author.Username)
+ notificationLocation = fmt.Sprintf("%s - %s - %s", guild.Name, channel.Name, message.Author.Username)
} else {
- notificationLocation = fmt.Sprintf("%s - %s", tempMessage.Author.Username, channel.Name)
- }
- } else {
- notificationLocation = fmt.Sprintf("%s - %s", tempMessage.Author.Username, channel.Name)
+ notificationLocation = fmt.Sprintf("%s - %s", message.Author.Username, channel.Name)
}
}
- notifyError := beeep.Notify("Cordless - "+notificationLocation, tempMessage.ContentWithMentionsReplaced(), "assets/information.png")
+ notifyError := beeep.Notify("Cordless - "+notificationLocation, message.ContentWithMentionsReplaced(), "assets/information.png")
if notifyError != nil {
log.Printf("["+tviewutil.ColorToHex(config.GetTheme().ErrorColor)+"]Error sending notification:\n\t[%s]%s\n", tviewutil.ColorToHex(config.GetTheme().ErrorColor), notifyError)
}
}
}
- //We needn't adjust the text of the currently selected channel.
- if window.selectedChannel == nil || tempMessage.ChannelID == window.selectedChannel.ID {
- continue
- }
-
if channel.Type == discordgo.ChannelTypeDM || channel.Type == discordgo.ChannelTypeGroupDM {
if !readstate.IsChannelMuted(channel) {
window.app.QueueUpdateDraw(func() {
@@ -1400,7 +1384,7 @@ func (window *Window) startMessageHandlerRoutines(input, edit, delete chan *disc
})
}
} else if channel.Type == discordgo.ChannelTypeGuildText {
- if mentionsYou {
+ if mentionsCurrentUser {
window.app.QueueUpdateDraw(func() {
window.channelTree.MarkChannelAsMentioned(channel.ID)
})

Cleanup message receive code in order to make it more concise and faster