cchat-discord/internal/discord/channel/message/nickname/nicknamer.go

93 lines
2.2 KiB
Go

package nickname
import (
"context"
"fmt"
"github.com/diamondburned/arikawa/v2/discord"
"github.com/diamondburned/arikawa/v2/gateway"
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat-discord/internal/discord/channel/shared"
"github.com/diamondburned/cchat-discord/internal/funcutil"
"github.com/diamondburned/cchat-discord/internal/segments/colored"
"github.com/diamondburned/cchat/text"
)
type Nicknamer struct {
userID discord.UserID
shared.Channel
}
func New(ch shared.Channel) cchat.Nicknamer {
return NewMember(ch.State.UserID, ch)
}
func NewMember(userID discord.UserID, ch shared.Channel) cchat.Nicknamer {
return Nicknamer{userID, ch}
}
func (nn Nicknamer) Nickname(ctx context.Context, labeler cchat.LabelContainer) (func(), error) {
// We don't have a nickname if we're not in a guild.
if !nn.GuildID.IsValid() {
// Use the current user.
u, err := nn.State.Cabinet.Me()
if err == nil {
labeler.SetLabel(text.Plain(fmt.Sprintf("%s#%s", u.Username, u.Discriminator)))
}
return func() {}, nil
}
return funcutil.JoinCancels(
nn.State.AddHandler(func(chunks *gateway.GuildMembersChunkEvent) {
if chunks.GuildID != nn.GuildID {
return
}
for _, member := range chunks.Members {
if member.User.ID == nn.userID {
nn.setMember(labeler, member)
break
}
}
}),
nn.State.AddHandler(func(g *gateway.GuildMemberUpdateEvent) {
if g.GuildID == nn.GuildID && g.User.ID == nn.userID {
nn.setMember(labeler, discord.Member{
User: g.User,
Nick: g.Nick,
RoleIDs: g.RoleIDs,
})
}
}),
), nil
}
func (nn Nicknamer) tryNicknameLabel(ctx context.Context, labeler cchat.LabelContainer) {
state := nn.State.WithContext(ctx)
m, err := state.Cabinet.Member(nn.GuildID, nn.userID)
if err != nil {
return
}
nn.setMember(labeler, *m)
}
func (nn Nicknamer) setMember(labeler cchat.LabelContainer, m discord.Member) {
var rich = text.Rich{Content: m.User.Username}
if m.Nick != "" {
rich.Content = m.Nick
}
guild, err := nn.State.Cabinet.Guild(nn.GuildID)
if err == nil {
if color := discord.MemberColor(*guild, m); color > 0 {
rich.Segments = []text.Segment{
colored.New(len(rich.Content), color.Uint32()),
}
}
}
labeler.SetLabel(rich)
}