almost there...
This commit is contained in:
parent
3e9bed8273
commit
7bfe466482
|
@ -0,0 +1,83 @@
|
|||
package folder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/diamondburned/arikawa/v2/gateway"
|
||||
"github.com/diamondburned/cchat"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/guild"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/shared/state"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/colored"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
)
|
||||
|
||||
type GuildFolder struct {
|
||||
empty.Server
|
||||
gateway.GuildFolder
|
||||
state *state.Instance
|
||||
}
|
||||
|
||||
func New(s *state.Instance, gf gateway.GuildFolder) cchat.Server {
|
||||
// Name should never be empty.
|
||||
if gf.Name == "" {
|
||||
var names = make([]string, 0, len(gf.GuildIDs))
|
||||
|
||||
for _, id := range gf.GuildIDs {
|
||||
g, err := s.Cabinet.Guild(id)
|
||||
if err == nil {
|
||||
names = append(names, g.Name)
|
||||
}
|
||||
}
|
||||
|
||||
gf.Name = strings.Join(names, ", ")
|
||||
}
|
||||
|
||||
return &GuildFolder{
|
||||
GuildFolder: gf,
|
||||
state: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (gf *GuildFolder) ID() cchat.ID {
|
||||
return strconv.FormatInt(int64(gf.GuildFolder.ID), 10)
|
||||
}
|
||||
|
||||
func (gf *GuildFolder) Name(ctx context.Context, l cchat.LabelContainer) (func(), error) {
|
||||
var name = text.Rich{
|
||||
Content: gf.GuildFolder.Name,
|
||||
}
|
||||
|
||||
if gf.GuildFolder.Color > 0 {
|
||||
name.Segments = []text.Segment{
|
||||
colored.New(len(name.Content), gf.GuildFolder.Color.Uint32()),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add folder updater from setting update events.
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
// IsLister returns true.
|
||||
func (gf *GuildFolder) AsLister() cchat.Lister { return gf }
|
||||
|
||||
func (gf *GuildFolder) Servers(container cchat.ServersContainer) (func(), error) {
|
||||
var servers = make([]cchat.Server, 0, len(gf.GuildIDs))
|
||||
|
||||
for _, id := range gf.GuildIDs {
|
||||
g, err := gf.state.Cabinet.Guild(id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
servers = append(servers, guild.New(gf.state, g))
|
||||
}
|
||||
|
||||
container.SetServers(servers)
|
||||
|
||||
// Return an empty callback. We're lazily redoing the whole list when a
|
||||
// guild moves for now.
|
||||
return func() {}, nil
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package guild
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/cchat"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/category"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/channel"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/shared/funcutil"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/state"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Guild struct {
|
||||
empty.Server
|
||||
id discord.GuildID
|
||||
state *state.Instance
|
||||
}
|
||||
|
||||
func New(s *state.Instance, g *discord.Guild) cchat.Server {
|
||||
return &Guild{
|
||||
id: g.ID,
|
||||
state: s,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFromID(s *state.Instance, gID discord.GuildID) (cchat.Server, error) {
|
||||
g, err := s.Cabinet.Guild(gID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return New(s, g), nil
|
||||
}
|
||||
|
||||
func (g *Guild) self() (*discord.Guild, error) {
|
||||
return g.state.Cabinet.Guild(g.id)
|
||||
}
|
||||
|
||||
func (g *Guild) ID() cchat.ID {
|
||||
return g.id.String()
|
||||
}
|
||||
|
||||
func (g *Guild) Name(ctx context.Context, l cchat.LabelContainer) (func(), error) {
|
||||
return g.state.Labels.AddGuildLabel(g.id, l)
|
||||
}
|
||||
|
||||
func (g *Guild) AsLister() cchat.Lister { return g }
|
||||
|
||||
func (g *Guild) Servers(container cchat.ServersContainer) (func(), error) {
|
||||
c, err := g.state.Channels(g.id)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get channels")
|
||||
}
|
||||
|
||||
// Only get top-level channels (those with category ID being null).
|
||||
var toplevels = category.FilterAccessible(g.state, category.FilterCategory(c, 0))
|
||||
|
||||
// Sort so that positions are correct.
|
||||
sort.SliceStable(toplevels, func(i, j int) bool {
|
||||
return toplevels[i].Position < toplevels[j].Position
|
||||
})
|
||||
|
||||
// Sort so that channels are before categories.
|
||||
sort.SliceStable(toplevels, func(i, _ int) bool {
|
||||
return toplevels[i].Type != discord.GuildCategory
|
||||
})
|
||||
|
||||
chs := make([]cchat.Server, 0, len(toplevels))
|
||||
// ids := make(map[discord.ChannelID]struct{}, len(toplevels))
|
||||
|
||||
for _, ch := range toplevels {
|
||||
switch ch.Type {
|
||||
case discord.GuildCategory:
|
||||
chs = append(chs, category.New(g.state, ch))
|
||||
case discord.GuildText:
|
||||
c, err := channel.New(g.state, ch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to make channel %q: %v", ch.Name, err)
|
||||
}
|
||||
chs = append(chs, c)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
container.SetServers(chs)
|
||||
|
||||
// TODO: RACEEEEEEEEEEEEEEEEEEEEEEE CONDITION!!!!!!!!!!!!
|
||||
|
||||
// TODO: Add channel stuff.
|
||||
|
||||
stop := funcutil.JoinCancels()
|
||||
|
||||
// TODO: account for insertion/deletion.
|
||||
|
||||
return stop, nil
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v2/gateway"
|
||||
"github.com/diamondburned/arikawa/v2/session"
|
||||
"github.com/diamondburned/cchat"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/folder"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/guild"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/private"
|
||||
"github.com/diamondburned/cchat-discord/internal/discord/shared/state"
|
||||
"github.com/diamondburned/cchat-discord/internal/funcutil"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/mention"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var ErrMFA = session.ErrMFA
|
||||
|
||||
type Session struct {
|
||||
empty.Session
|
||||
private cchat.Server
|
||||
state *state.Instance
|
||||
}
|
||||
|
||||
func NewFromInstance(i *state.Instance) (cchat.Session, error) {
|
||||
priv, err := private.New(i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to make main private server")
|
||||
}
|
||||
|
||||
return &Session{
|
||||
private: priv,
|
||||
state: i,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Session) ID() cchat.ID {
|
||||
return s.state.UserID.String()
|
||||
}
|
||||
|
||||
func (s *Session) Name(ctx context.Context, l cchat.LabelContainer) (func(), error) {
|
||||
u, err := s.state.Cabinet.Me()
|
||||
if err != nil {
|
||||
l.SetLabel(text.Plain("<@" + s.state.UserID.String() + ">"))
|
||||
} else {
|
||||
user := mention.NewUser(*u)
|
||||
user.WithState(s.state.State)
|
||||
user.Prefetch()
|
||||
|
||||
rich := text.Plain(user.DisplayName())
|
||||
rich.Segments = []text.Segment{
|
||||
mention.Segment{
|
||||
End: len(rich.Content),
|
||||
User: user,
|
||||
},
|
||||
}
|
||||
|
||||
l.SetLabel(rich)
|
||||
}
|
||||
|
||||
// TODO.
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
func (s *Session) Disconnect() error {
|
||||
return s.state.CloseGracefully()
|
||||
}
|
||||
|
||||
func (s *Session) AsSessionSaver() cchat.SessionSaver { return s.state }
|
||||
|
||||
func (s *Session) Servers(container cchat.ServersContainer) (func(), error) {
|
||||
if err := s.servers(container); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
retryFn := func() {
|
||||
// We should set up a back-off here.
|
||||
for s.servers(container) != nil {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
stop := funcutil.JoinCancels(
|
||||
// Reset the entire container when the session is closed.
|
||||
s.state.AddHandler(func(*session.Closed) {
|
||||
container.SetServers(nil)
|
||||
}),
|
||||
|
||||
// Set the entire container again once reconnected.
|
||||
s.state.AddHandler(func(*ningen.Connected) {
|
||||
retryFn()
|
||||
}),
|
||||
|
||||
// Update the entire container when we update the guild list. Blame
|
||||
// Discord on this one.
|
||||
s.state.AddHandler(func(update *gateway.UserSettingsUpdateEvent) {
|
||||
if update.GuildFolders != nil || update.GuildPositions != nil {
|
||||
retryFn()
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
return stop, nil
|
||||
}
|
||||
|
||||
func (s *Session) servers(container cchat.ServersContainer) error {
|
||||
ready := s.state.Ready()
|
||||
|
||||
// If the user has guild folders:
|
||||
if len(ready.UserSettings.GuildFolders) > 0 {
|
||||
// TODO: account for missing guilds.
|
||||
toplevels := make([]cchat.Server, 1, len(ready.UserSettings.GuildFolders)+1)
|
||||
toplevels[0] = s.private
|
||||
|
||||
for _, guildFolder := range ready.UserSettings.GuildFolders {
|
||||
// TODO: correct.
|
||||
// TODO: correct how? What did I mean by this?
|
||||
switch {
|
||||
case guildFolder.ID != 0:
|
||||
fallthrough
|
||||
case len(guildFolder.GuildIDs) > 1:
|
||||
toplevels = append(toplevels, folder.New(s.state, guildFolder))
|
||||
|
||||
case len(guildFolder.GuildIDs) == 1:
|
||||
g, err := guild.NewFromID(s.state, guildFolder.GuildIDs[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
toplevels = append(toplevels, g)
|
||||
}
|
||||
}
|
||||
|
||||
container.SetServers(toplevels)
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the user doesn't have guild folders but has sorted their guilds
|
||||
// before:
|
||||
if len(ready.UserSettings.GuildPositions) > 0 {
|
||||
guilds := make([]cchat.Server, 1, len(ready.UserSettings.GuildPositions)+1)
|
||||
guilds[0] = s.private
|
||||
|
||||
for _, id := range ready.UserSettings.GuildPositions {
|
||||
g, err := guild.NewFromID(s.state, id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
guilds = append(guilds, g)
|
||||
}
|
||||
|
||||
container.SetServers(guilds)
|
||||
return nil
|
||||
}
|
||||
|
||||
// None of the above:
|
||||
g, err := s.state.Guilds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servers := make([]cchat.Server, len(g)+1)
|
||||
servers[0] = s.private
|
||||
|
||||
for i := range g {
|
||||
servers[i+1] = guild.New(s.state, &g[i])
|
||||
}
|
||||
|
||||
container.SetServers(servers)
|
||||
return nil
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/arikawa/v2/gateway"
|
||||
"github.com/diamondburned/cchat"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/mention"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
)
|
||||
|
||||
|
@ -54,7 +55,7 @@ func (r *Repository) onGuildUpdate(ev *gateway.GuildUpdateEvent) {
|
|||
return
|
||||
}
|
||||
|
||||
rich := labelGuild(r.state, ev.ID)
|
||||
rich := mention.NewGuildText(r.state, ev.ID)
|
||||
|
||||
for labeler := range guild.guild {
|
||||
labeler.SetLabel(rich)
|
||||
|
@ -64,7 +65,7 @@ func (r *Repository) onGuildUpdate(ev *gateway.GuildUpdateEvent) {
|
|||
// AddGuildLabel adds a label to display the given guild ID. Refer to Repository
|
||||
// for more documentation.
|
||||
func (r *Repository) AddGuildLabel(guildID discord.GuildID, l cchat.LabelContainer) func() {
|
||||
l.SetLabel(labelGuild(r.state, guildID))
|
||||
l.SetLabel(mention.NewGuildText(r.state, guildID))
|
||||
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
@ -89,16 +90,37 @@ func (r *Repository) AddGuildLabel(guildID discord.GuildID, l cchat.LabelContain
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Repository) onMemberRemove(ev *gateway.GuildMemberRemoveEvent) {}
|
||||
func (r *Repository) onMemberRemove(ev *gateway.GuildMemberRemoveEvent) {
|
||||
// Not sure what to do.
|
||||
}
|
||||
|
||||
func (r *Repository) onMemberUpdate(ev *gateway.GuildMemberUpdateEvent) {}
|
||||
func (r *Repository) onMemberUpdate(ev *gateway.GuildMemberUpdateEvent) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
if r.stopped {
|
||||
return
|
||||
}
|
||||
|
||||
guild, _ := r.stores.guilds[ev.GuildID]
|
||||
member, ok := guild.members[ev.User.ID]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
rich := mention.NewMemberText(r.state, ev.GuildID, ev.User.ID)
|
||||
|
||||
for labeler := range member {
|
||||
labeler.SetLabel(rich)
|
||||
}
|
||||
}
|
||||
|
||||
// AddMemberLabel adds a label to display the given member live. Refer to
|
||||
// Repository for more documentation.
|
||||
func (r *Repository) AddMemberLabel(
|
||||
guildID discord.GuildID, userID discord.UserID, l cchat.LabelContainer) func() {
|
||||
|
||||
l.SetLabel(labelMember(r.state, guildID, userID))
|
||||
l.SetLabel(mention.NewMemberText(r.state, guildID, userID))
|
||||
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
@ -134,13 +156,34 @@ func (r *Repository) AddMemberLabel(
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Repository) onChannelUpdate(ev *gateway.ChannelUpdateEvent) {}
|
||||
func (r *Repository) onChannelDelete(ev *gateway.ChannelDeleteEvent) {}
|
||||
func (r *Repository) onChannelDelete(ev *gateway.ChannelDeleteEvent) {
|
||||
// Not sure what to do.
|
||||
}
|
||||
|
||||
func (r *Repository) onChannelUpdate(ev *gateway.ChannelUpdateEvent) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
if r.stopped {
|
||||
return
|
||||
}
|
||||
|
||||
channel, ok := r.stores.channels[ev.ID]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
rich := mention.NewChannelText(r.state, ev.ID)
|
||||
|
||||
for labeler := range channel {
|
||||
labeler.SetLabel(rich)
|
||||
}
|
||||
}
|
||||
|
||||
// AddChannelLabel adds a label to display the given channel live. Refer to
|
||||
// Repository for more documentation.
|
||||
func (r *Repository) AddChannelLabel(chID discord.ChannelID, l cchat.LabelContainer) func() {
|
||||
l.SetLabel(labelChannel(r.state, chID))
|
||||
l.SetLabel(mention.NewChannelText(r.state, chID))
|
||||
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
|
@ -3,7 +3,9 @@ package state
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/diamondburned/arikawa/utils/httputil/httpdriver"
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/arikawa/v2/session"
|
||||
"github.com/diamondburned/arikawa/v2/state"
|
||||
|
@ -66,12 +68,12 @@ func New(s *state.State) (*Instance, error) {
|
|||
return nil, errors.Wrap(err, "failed to create a state wrapper")
|
||||
}
|
||||
|
||||
// n.Client.OnRequest = append(n.Client.OnRequest,
|
||||
// func(r httpdriver.Request) error {
|
||||
// log.Println("[Discord] Request", r.GetPath())
|
||||
// return nil
|
||||
// },
|
||||
// )
|
||||
n.Client.OnRequest = append(n.Client.OnRequest,
|
||||
func(r httpdriver.Request) error {
|
||||
log.Println("[Discord] Request", r.GetPath())
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err := n.Open(); err != nil {
|
||||
return nil, err
|
|
@ -1,73 +0,0 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/avatar"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/colored"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/mention"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/segutil"
|
||||
"github.com/diamondburned/cchat-discord/internal/urlutils"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
)
|
||||
|
||||
// TODO: these functions should probably be its own package.
|
||||
|
||||
func labelGuild(s *ningen.State, guildID discord.GuildID) text.Rich {
|
||||
g, err := s.Cabinet.Guild(guildID)
|
||||
if err != nil {
|
||||
return text.Plain(guildID.String())
|
||||
}
|
||||
|
||||
return text.Rich{
|
||||
Content: g.Name,
|
||||
Segments: []text.Segment{
|
||||
avatar.Segment{
|
||||
URL: urlutils.AvatarURL(g.IconURL()),
|
||||
Size: urlutils.AvatarSize,
|
||||
Text: g.Name,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func labelMember(s *ningen.State, g discord.GuildID, u discord.UserID) text.Rich {
|
||||
m, err := s.Cabinet.Member(g, u)
|
||||
if err != nil {
|
||||
s.MemberState.RequestMember(g, u)
|
||||
return text.Plain(u.Mention())
|
||||
}
|
||||
|
||||
user := mention.NewUser(m.User)
|
||||
user.WithMember(*m)
|
||||
user.WithGuildID(g)
|
||||
user.WithState(s)
|
||||
user.Prefetch()
|
||||
|
||||
rich := text.Rich{Content: user.DisplayName()}
|
||||
rich.Segments = []text.Segment{
|
||||
mention.NewSegment(0, len(rich.Content), user),
|
||||
}
|
||||
|
||||
if m.User.Bot {
|
||||
rich.Content += " "
|
||||
rich.Segments = append(rich.Segments,
|
||||
colored.NewBlurple(segutil.Write(&rich, "[BOT]")),
|
||||
)
|
||||
}
|
||||
|
||||
return rich
|
||||
}
|
||||
|
||||
func labelChannel(s *ningen.State, chID discord.ChannelID) text.Rich {
|
||||
var rich text.Rich
|
||||
|
||||
ch, err := s.Cabinet.Channel(chID)
|
||||
if err != nil {
|
||||
rich = text.Plain(ch.Mention())
|
||||
} else {
|
||||
rich = text.Plain(mention.ChannelName(*ch))
|
||||
}
|
||||
|
||||
return rich
|
||||
}
|
|
@ -54,6 +54,26 @@ func FormatRecipients(users []discord.User) string {
|
|||
return strings.Join(usernames, ", ") + " and " + users[len(users)-1].Username
|
||||
}
|
||||
|
||||
// NewChannelText creates a new rich text describing the given channel fetched
|
||||
// from the state.
|
||||
func NewChannelText(s *ningen.State, chID discord.ChannelID) text.Rich {
|
||||
ch, err := s.Cabinet.Channel(chID)
|
||||
if err != nil {
|
||||
return text.Plain(ch.Mention())
|
||||
}
|
||||
|
||||
rich := text.Rich{Content: ChannelName(*ch)}
|
||||
rich.Segments = []text.Segment{
|
||||
Segment{
|
||||
Start: 0,
|
||||
End: len(rich.Content),
|
||||
Channel: NewChannel(*ch),
|
||||
},
|
||||
}
|
||||
|
||||
return rich
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
discord.Channel
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package mention
|
||||
|
||||
import (
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/avatar"
|
||||
"github.com/diamondburned/cchat-discord/internal/urlutils"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
)
|
||||
|
||||
// NewGuildText creates a new rich text describing the given member fetched from
|
||||
// the state.
|
||||
func NewGuildText(s *ningen.State, guildID discord.GuildID) text.Rich {
|
||||
g, err := s.Cabinet.Guild(guildID)
|
||||
if err != nil {
|
||||
return text.Plain(guildID.String())
|
||||
}
|
||||
|
||||
return text.Rich{
|
||||
Content: g.Name,
|
||||
Segments: []text.Segment{
|
||||
avatar.Segment{
|
||||
URL: urlutils.AvatarURL(g.IconURL()),
|
||||
Size: urlutils.AvatarSize,
|
||||
Text: g.Name,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
|
@ -12,41 +12,41 @@ import (
|
|||
"github.com/diamondburned/cchat-discord/internal/segments/segutil"
|
||||
"github.com/diamondburned/cchat-discord/internal/urlutils"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
)
|
||||
|
||||
// NameSegment represents a clickable member name.
|
||||
type NameSegment struct {
|
||||
empty.TextSegment
|
||||
start int
|
||||
end int
|
||||
um User
|
||||
}
|
||||
|
||||
var _ text.Segment = (*NameSegment)(nil)
|
||||
|
||||
func NewSegment(start, end int, user *User) NameSegment {
|
||||
return NameSegment{
|
||||
start: start,
|
||||
end: end,
|
||||
um: *user,
|
||||
// NewMemberText creates a new rich text describing the given member fetched
|
||||
// from the state.
|
||||
func NewMemberText(s *ningen.State, g discord.GuildID, u discord.UserID) text.Rich {
|
||||
m, err := s.Cabinet.Member(g, u)
|
||||
if err != nil {
|
||||
s.MemberState.RequestMember(g, u)
|
||||
return text.Plain(u.Mention())
|
||||
}
|
||||
}
|
||||
|
||||
func (m NameSegment) Bounds() (start, end int) {
|
||||
return m.start, m.end
|
||||
}
|
||||
user := NewUser(m.User)
|
||||
user.WithMember(*m)
|
||||
user.WithGuildID(g)
|
||||
user.WithState(s)
|
||||
user.Prefetch()
|
||||
|
||||
func (m NameSegment) AsMentioner() text.Mentioner { return &m.um }
|
||||
func (m NameSegment) AsAvatarer() text.Avatarer { return &m.um }
|
||||
|
||||
// AsColorer only returns User if the user actually has a colored role.
|
||||
func (m NameSegment) AsColorer() text.Colorer {
|
||||
if m.um.HasColor() {
|
||||
return &m.um
|
||||
rich := text.Rich{Content: user.DisplayName()}
|
||||
rich.Segments = []text.Segment{
|
||||
Segment{
|
||||
Start: 0,
|
||||
End: len(rich.Content),
|
||||
User: user,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
|
||||
if m.User.Bot {
|
||||
rich.Content += " "
|
||||
rich.Segments = append(rich.Segments,
|
||||
colored.NewBlurple(segutil.Write(&rich, "[BOT]")),
|
||||
)
|
||||
}
|
||||
|
||||
return rich
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
|
Loading…
Reference in New Issue