feat: add nicknames and role colors to usernames (#531)
This commit is contained in:
parent
ab78e85d1b
commit
edd3523514
4 changed files with 120 additions and 7 deletions
|
|
@ -1,12 +1,14 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
|
|
@ -14,6 +16,7 @@ import (
|
|||
"github.com/ayn2op/discordo/internal/markdown"
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/ningen/v3/discordmd"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
|
|
@ -29,6 +32,11 @@ type MessagesText struct {
|
|||
cfg *config.Config
|
||||
app *tview.Application
|
||||
selectedMessageID discord.MessageID
|
||||
fetchingMembers struct {
|
||||
value bool
|
||||
done chan struct{}
|
||||
mu sync.Mutex
|
||||
}
|
||||
}
|
||||
|
||||
func newMessagesText(app *tview.Application, cfg *config.Config) *MessagesText {
|
||||
|
|
@ -57,6 +65,7 @@ func newMessagesText(app *tview.Application, cfg *config.Config) *MessagesText {
|
|||
markdown.DefaultRenderer.AddOptions(
|
||||
renderer.WithOption("emojiColor", t.MessagesText.EmojiColor),
|
||||
renderer.WithOption("linkColor", t.MessagesText.LinkColor),
|
||||
renderer.WithOption("showNicknames", t.MessagesText.ShowNicknames),
|
||||
)
|
||||
|
||||
return mt
|
||||
|
|
@ -69,6 +78,12 @@ func (mt *MessagesText) drawMsgs(cID discord.ChannelID) {
|
|||
return
|
||||
}
|
||||
|
||||
if app.cfg.Theme.MessagesText.ShowNicknames || app.cfg.Theme.MessagesText.ShowUsernameColors {
|
||||
if ch, _ := discordState.Cabinet.Channel(cID); ch.GuildID.IsValid() {
|
||||
mt.fetchMembers(ch.GuildID, ms)
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range slices.Backward(ms) {
|
||||
app.messagesText.createMessage(m)
|
||||
}
|
||||
|
|
@ -111,23 +126,23 @@ func (mt *MessagesText) createMessage(m discord.Message) {
|
|||
fmt.Fprint(mt, "["+mt.cfg.Theme.MessagesText.ContentColor+"]"+m.Author.Username+" pinned a message"+"[-:-:-]")
|
||||
case discord.DefaultMessage, discord.InlinedReplyMessage:
|
||||
if m.ReferencedMessage != nil {
|
||||
mt.createHeader(mt, *m.ReferencedMessage, true)
|
||||
mt.createHeader(mt, *m.ReferencedMessage, m.GuildID, true)
|
||||
mt.createBody(mt, *m.ReferencedMessage, true)
|
||||
|
||||
fmt.Fprint(mt, "[::-]\n")
|
||||
}
|
||||
|
||||
mt.createHeader(mt, m, false)
|
||||
mt.createHeader(mt, m, m.GuildID, false)
|
||||
mt.createBody(mt, m, false)
|
||||
mt.createFooter(mt, m)
|
||||
default:
|
||||
mt.createHeader(mt, m, false)
|
||||
mt.createHeader(mt, m, m.GuildID, false)
|
||||
}
|
||||
|
||||
fmt.Fprintln(mt)
|
||||
}
|
||||
|
||||
func (mt *MessagesText) createHeader(w io.Writer, m discord.Message, isReply bool) {
|
||||
func (mt *MessagesText) createHeader(w io.Writer, m discord.Message, gID discord.GuildID, isReply bool) {
|
||||
if mt.cfg.Timestamps.Enabled {
|
||||
time := m.Timestamp.Time().In(time.Local).Format(mt.cfg.Timestamps.Format)
|
||||
fmt.Fprintf(w, "[::d]%s[::-] ", time)
|
||||
|
|
@ -137,7 +152,10 @@ func (mt *MessagesText) createHeader(w io.Writer, m discord.Message, isReply boo
|
|||
fmt.Fprintf(mt, "[::d]%s", mt.cfg.Theme.MessagesText.ReplyIndicator)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "[%s]%s[-:-:-] ", mt.cfg.Theme.MessagesText.AuthorColor, m.Author.Username)
|
||||
displayName := mt.getAuthorDisplayName(m, gID)
|
||||
displayColor := mt.getAuthorDisplayColor(m, gID)
|
||||
|
||||
fmt.Fprintf(w, "[%s]%s[-:-:-] ", displayColor, displayName)
|
||||
}
|
||||
|
||||
func (mt *MessagesText) createBody(w io.Writer, m discord.Message, isReply bool) {
|
||||
|
|
@ -193,6 +211,32 @@ func (mt *MessagesText) getSelectedMessageIndex() (int, error) {
|
|||
return -1, nil
|
||||
}
|
||||
|
||||
func (mt *MessagesText) getAuthorDisplayName(m discord.Message, gID discord.GuildID) string {
|
||||
name := m.Author.DisplayOrUsername()
|
||||
|
||||
if app.cfg.Theme.MessagesText.ShowNicknames && gID.IsValid() {
|
||||
// Use guild nickname if present
|
||||
if member, _ := discordState.Cabinet.Member(gID, m.Author.ID); member != nil && member.Nick != "" {
|
||||
name = member.Nick
|
||||
}
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (mt *MessagesText) getAuthorDisplayColor(m discord.Message, gID discord.GuildID) string {
|
||||
color := mt.cfg.Theme.MessagesText.AuthorColor
|
||||
|
||||
if app.cfg.Theme.MessagesText.ShowUsernameColors && gID.IsValid() {
|
||||
// Use color from highest role in guild
|
||||
if c, ok := discordState.MemberColor(gID, m.Author.ID); ok {
|
||||
color = c.String()
|
||||
}
|
||||
}
|
||||
|
||||
return color
|
||||
}
|
||||
|
||||
func (mt *MessagesText) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||
switch event.Name() {
|
||||
case mt.cfg.Keys.MessagesText.Cancel:
|
||||
|
|
@ -460,7 +504,7 @@ func (mt *MessagesText) reply(mention bool) {
|
|||
return
|
||||
}
|
||||
|
||||
title += msg.Author.Tag()
|
||||
title += mt.getAuthorDisplayName(*msg, msg.GuildID)
|
||||
app.messageInput.SetTitle(title)
|
||||
app.messageInput.replyMessageID = mt.selectedMessageID
|
||||
mt.app.SetFocus(app.messageInput)
|
||||
|
|
@ -511,3 +555,57 @@ func (mt *MessagesText) delete() {
|
|||
app.messagesText.createMessage(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *MessagesText) fetchMembers(gID discord.GuildID, ms []discord.Message) {
|
||||
var usersToFetch []discord.UserID
|
||||
for _, m := range ms {
|
||||
if member, _ := discordState.Cabinet.Member(gID, m.Author.ID); member == nil {
|
||||
usersToFetch = append(usersToFetch, m.Author.ID)
|
||||
}
|
||||
}
|
||||
|
||||
if usersToFetch != nil {
|
||||
err := discordState.Gateway().Send(context.Background(), &gateway.RequestGuildMembersCommand{
|
||||
GuildIDs: []discord.GuildID{gID},
|
||||
UserIDs: slices.Compact(usersToFetch),
|
||||
})
|
||||
if err != nil {
|
||||
slog.Error("Failed to request guild members", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
mt.setFetchingChunk(true)
|
||||
mt.waitForChunkEvent()
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *MessagesText) setFetchingChunk(value bool) {
|
||||
mt.fetchingMembers.mu.Lock()
|
||||
if mt.fetchingMembers.value == value {
|
||||
mt.fetchingMembers.mu.Unlock()
|
||||
return
|
||||
}
|
||||
mt.fetchingMembers.value = value
|
||||
mt.fetchingMembers.mu.Unlock()
|
||||
|
||||
if value {
|
||||
mt.fetchingMembers.done = make(chan struct{})
|
||||
} else {
|
||||
close(mt.fetchingMembers.done)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *MessagesText) waitForChunkEvent() {
|
||||
mt.fetchingMembers.mu.Lock()
|
||||
if !mt.fetchingMembers.value {
|
||||
mt.fetchingMembers.mu.Unlock()
|
||||
return
|
||||
}
|
||||
mt.fetchingMembers.mu.Unlock()
|
||||
|
||||
select {
|
||||
case <-mt.fetchingMembers.done:
|
||||
default:
|
||||
<-mt.fetchingMembers.done
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ func openState(token string) error {
|
|||
discordState.AddHandler(discordState.onReady)
|
||||
discordState.AddHandler(discordState.onMessageCreate)
|
||||
discordState.AddHandler(discordState.onMessageDelete)
|
||||
discordState.AddHandler(discordState.onGetMemberChunk)
|
||||
|
||||
discordState.OnRequest = append(discordState.OnRequest, discordState.onRequest)
|
||||
return discordState.Open(context.TODO())
|
||||
|
|
@ -106,3 +107,7 @@ func (s *State) onMessageDelete(m *gateway.MessageDeleteEvent) {
|
|||
app.messagesText.drawMsgs(m.ChannelID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) onGetMemberChunk(g *gateway.GuildMembersChunkEvent) {
|
||||
app.messagesText.setFetchingChunk(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ type (
|
|||
}
|
||||
|
||||
MessagesTextTheme struct {
|
||||
ShowNicknames bool `toml:"show_user_nicks"`
|
||||
ShowUsernameColors bool `toml:"show_user_colors"`
|
||||
|
||||
ReplyIndicator string `toml:"reply_indicator"`
|
||||
|
||||
AuthorColor string `toml:"author_color"`
|
||||
|
|
@ -92,6 +95,9 @@ func defaultTheme() Theme {
|
|||
PrivateChannelColor: tview.Styles.PrimaryTextColor.String(),
|
||||
},
|
||||
MessagesText: MessagesTextTheme{
|
||||
ShowNicknames: true,
|
||||
ShowUsernameColors: true,
|
||||
|
||||
ReplyIndicator: string(tview.BoxDrawingsLightArcDownAndRight) + " ",
|
||||
|
||||
AuthorColor: "aqua",
|
||||
|
|
|
|||
|
|
@ -96,7 +96,11 @@ func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
|
|||
case n.Channel != nil:
|
||||
io.WriteString(w, "#"+n.Channel.Name)
|
||||
case n.GuildUser != nil:
|
||||
io.WriteString(w, "@"+n.GuildUser.Username)
|
||||
username := n.GuildUser.DisplayOrUsername()
|
||||
if r.config.Options["showNicknames"].(bool) && n.GuildUser.Member != nil && n.GuildUser.Member.Nick != "" {
|
||||
username = n.GuildUser.Member.Nick
|
||||
}
|
||||
io.WriteString(w, "@"+username)
|
||||
case n.GuildRole != nil:
|
||||
io.WriteString(w, "@"+n.GuildRole.Name)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue