117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package memberlist
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/diamondburned/arikawa/gateway"
|
|
"github.com/diamondburned/cchat"
|
|
"github.com/diamondburned/cchat-discord/internal/discord/channel/shared"
|
|
"github.com/diamondburned/ningen/states/member"
|
|
)
|
|
|
|
func seekPrevGroup(l *member.List, ix int) (item, group gateway.GuildMemberListOpItem) {
|
|
l.ViewItems(func(items []gateway.GuildMemberListOpItem) {
|
|
// Bound check.
|
|
if ix >= len(items) {
|
|
return
|
|
}
|
|
|
|
item = items[ix]
|
|
|
|
// Search backwards.
|
|
for i := ix; i >= 0; i-- {
|
|
if items[i].Group != nil {
|
|
group = items[i]
|
|
return
|
|
}
|
|
}
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
type MemberLister struct {
|
|
*shared.Channel
|
|
}
|
|
|
|
func New(ch *shared.Channel) cchat.MemberLister {
|
|
return MemberLister{ch}
|
|
}
|
|
|
|
func (ml MemberLister) ListMembers(ctx context.Context, c cchat.MemberListContainer) (func(), error) {
|
|
if !ml.GuildID.IsValid() {
|
|
return func() {}, nil
|
|
}
|
|
|
|
cancel := ml.State.AddHandler(func(u *gateway.GuildMemberListUpdate) {
|
|
l, err := ml.State.MemberState.GetMemberList(ml.GuildID, ml.ID)
|
|
if err != nil {
|
|
return // wat
|
|
}
|
|
|
|
if l.GuildID() != u.GuildID || l.ID() != u.ID {
|
|
return
|
|
}
|
|
|
|
for _, ev := range u.Ops {
|
|
switch ev.Op {
|
|
case "SYNC":
|
|
ml.checkSync(c)
|
|
|
|
case "INSERT", "UPDATE":
|
|
item, group := seekPrevGroup(l, ev.Index)
|
|
if item.Member != nil && group.Group != nil {
|
|
c.SetMember(group.Group.ID, NewMember(ml.Channel, item))
|
|
ml.FlushMemberGroups(l, c)
|
|
}
|
|
|
|
case "DELETE":
|
|
_, group := seekPrevGroup(l, ev.Index-1)
|
|
if group.Group != nil && ev.Item.Member != nil {
|
|
c.RemoveMember(group.Group.ID, ev.Item.Member.User.ID.String())
|
|
ml.FlushMemberGroups(l, c)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
ml.checkSync(c)
|
|
|
|
return cancel, nil
|
|
}
|
|
|
|
func (ml MemberLister) checkSync(c cchat.MemberListContainer) {
|
|
l, err := ml.State.MemberState.GetMemberList(ml.GuildID, ml.ID)
|
|
if err != nil {
|
|
ml.State.MemberState.RequestMemberList(ml.GuildID, ml.ID, 0)
|
|
return
|
|
}
|
|
|
|
ml.FlushMemberGroups(l, c)
|
|
|
|
l.ViewItems(func(items []gateway.GuildMemberListOpItem) {
|
|
var group gateway.GuildMemberListGroup
|
|
|
|
for _, item := range items {
|
|
switch {
|
|
case item.Group != nil:
|
|
group = *item.Group
|
|
|
|
case item.Member != nil:
|
|
c.SetMember(group.ID, NewMember(ml.Channel, item))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func (ml MemberLister) FlushMemberGroups(l *member.List, c cchat.MemberListContainer) {
|
|
l.ViewGroups(func(groups []gateway.GuildMemberListGroup) {
|
|
var sections = make([]cchat.MemberSection, len(groups))
|
|
for i, group := range groups {
|
|
sections[i] = NewSection(ml.Channel, l.ID(), group)
|
|
}
|
|
|
|
c.SetSections(sections)
|
|
})
|
|
}
|