Documentation ¶
Index ¶
- Constants
- Variables
- func ChunkFromIndex(index int) int
- func ComputeListID(overrides []discord.Overwrite) string
- func ListItemIsNil(it gateway.GuildMemberListOpItem) bool
- func ListItemSeek(items []gateway.GuildMemberListOpItem, offset int) int
- type Guild
- type List
- func (l *List) CountNil() (nils int)
- func (l *List) GuildID() discord.GuildID
- func (l *List) ID() string
- func (l *List) MaxChunk() int
- func (l *List) MemberCount() int
- func (l *List) OnlineCount() int
- func (l *List) TotalVisible() int
- func (l *List) ViewGroups(fn func(gruops []gateway.GuildMemberListGroup))
- func (l *List) ViewItems(fn func(items []gateway.GuildMemberListOpItem))
- type ListOP
- type State
- func (m *State) GetMemberList(guildID discord.GuildID, channelID discord.ChannelID) (*List, error)
- func (m *State) GetMemberListChunk(guildID discord.GuildID, channelID discord.ChannelID) int
- func (m *State) GetMemberListDirect(guildID discord.GuildID, id string) (*List, error)
- func (m *State) RequestMember(guildID discord.GuildID, memberID discord.UserID)
- func (m *State) RequestMemberList(guildID discord.GuildID, channelID discord.ChannelID, chunk int) [][2]int
- func (m *State) SearchMember(guildID discord.GuildID, query string)
- func (m *State) Subscribe(guildID discord.GuildID)
Examples ¶
Constants ¶
const MaxMemberChunk = 3 - 1
MaxMemberChunk indicates the number of chunks the member list might have active at once. The 3 means that there can be 300 simultaneous active users. 1 is subtracted to always keep the first chunk alive.
Variables ¶
var ( // ErrListNotFound is returned if GetMemberList can't find the list. ErrListNotFound = errors.New("List not found.") )
Functions ¶
func ChunkFromIndex ¶
ChunkFromIndex calculates the chunk number from the index of Items in List.
func ComputeListID ¶
func ListItemIsNil ¶
func ListItemIsNil(it gateway.GuildMemberListOpItem) bool
ListItemIsNil returns true if the item has nothing in it. This might be an uninitialized item.
func ListItemSeek ¶
func ListItemSeek(items []gateway.GuildMemberListOpItem, offset int) int
ListItemSeek seeks to the first non-nil item. -1 is returned if there are no non-nil items.
Types ¶
type List ¶
type List struct {
// contains filtered or unexported fields
}
List is the local state of the member list. The function is safe to be used thread-safe.
func (*List) ID ¶
ID returns the list's ID. The ID is made by hashing roles. The list's ID is constant.
func (*List) MemberCount ¶
MemberCount returns the total number of members.
func (*List) OnlineCount ¶
OnlineCount returns the total number of online users.
func (*List) TotalVisible ¶
TotalVisible returns the total number of members visible.
func (*List) ViewGroups ¶
func (l *List) ViewGroups(fn func(gruops []gateway.GuildMemberListGroup))
ViewGroups acquires the list's mutex and views the current groups. The function must not mutate nor reference the slice nor any of its items. The given callback must not call any other method except for ID and GuildID.
func (*List) ViewItems ¶
func (l *List) ViewItems(fn func(items []gateway.GuildMemberListOpItem))
ViewItems acquires the list's mutex and views the current items. The function must not mutate nor reference the slice nor any of its items. The given callback must not call any other method except for ID and GuildID.
type ListOP ¶
type ListOP struct { gateway.GuildMemberListOp List *List }
type State ¶
type State struct { OnError func(error) // RequestFrequency is the duration before the next SearchMember is allowed // to do anything else. Default is 1s. SearchFrequency time.Duration SearchLimit uint // 50 // RequestPresences, when true, will make RequestMember ask for the // presences as well. RequestPresences bool // true // contains filtered or unexported fields }
State handles members and the member list.
Members ¶
Discord wants all clients to request member information over the gateway instead of using the usual member API endpoint. This makes sense, as it reduces the load onto the server, but it also makes it a lot more painful to efficiently request members.
The state helps abstract this away by allowing the caller to request multiple times the same member. If the gateway has yet to reply or if the state already has the member, the function will not send a command over.
Member List ¶
Discord also wants all clients to not use the members (plural) endpoint. In fact, calling this endpoint will immediately unverify the user's email.
The state helps abstract this by keeping a local state of all member lists as well as providing APIs to query the member list. Keep in mind that since most channels typically have its own member list, this might be pretty hefty on memory.
With ningen's default handler,
For reference, go to https://luna.gitlab.io/discord-unofficial-docs/lazy_guilds.html.
func NewState ¶
func NewState(state *state.State, h handlerrepo.AddHandler) *State
func (*State) GetMemberList ¶
GetMemberList looks up for the member list. It returns an error if no list is found.
Reference: https://luna.gitlab.io/discord-unofficial-docs/lazy_guilds.html
func (*State) GetMemberListChunk ¶
GetMemberListChunk returns the current member list chunk. It returns -1 if there is none.
func (*State) GetMemberListDirect ¶
GetMemberListDirect gets the guild's member list directly from the list's ID.
func (*State) RequestMember ¶
RequestMember tries to ask the gateway for a member from the ID. This method will not send the command if the member is already in the state or it's already being requested.
func (*State) RequestMemberList ¶
func (m *State) RequestMemberList( guildID discord.GuildID, channelID discord.ChannelID, chunk int) [][2]int
RequestMemberList tries to ask the gateway for a chunk (or many) of the members list. Chunk is an integer (0, 1, ...), which indicates the maximum number of chunks from 0 that the API should return. The function returns the chunks to be fetched.
Specifically, this method guarantees that the current chunk and the next chunk will always be alive, as well as the first chunk.
If the given guild is not subscribed already, then it will subscribe automatically.
Example ¶
s, err := state.New(os.Getenv("TOKEN")) if err != nil { log.Fatalln("Failed to create a state:", err) } // Replace with the actual ningen.FromState function. n, err := ningenFromState(s) if err != nil { log.Fatalln("Failed to create a ningen state:", err) } updates := make(chan *gateway.GuildMemberListUpdate, 1) n.AddHandler(updates) if err := n.Open(); err != nil { panic(err) } defer n.Close() for i := 0; ; i++ { c := n.MemberState.RequestMemberList(GuildID, ChannelID, i) if c == nil { break } <-updates log.Println("Received", i) } l, err := n.MemberState.GetMemberList(GuildID, ChannelID) if err != nil { panic(err) } l.ViewGroups(func(groups []gateway.GuildMemberListGroup) { for _, group := range groups { var name = group.ID if p, err := discord.ParseSnowflake(name); err == nil { r, err := s.Role(GuildID, discord.RoleID(p)) if err != nil { log.Fatalln("Failed to get role:", err) } name = r.Name } fmt.Println("Group:", name, group.Count) } }) l.ViewItems(func(items []gateway.GuildMemberListOpItem) { for i := 0; i < len(items); i += 100 { for j := 0; j < 99 && i+j < len(items); j++ { if ListItemIsNil(items[i+j]) { fmt.Print(" ") } else { fmt.Print("O") } } fmt.Println("|") } var firstNonNil = ListItemSeek(items, 100) fmt.Println("First non-nil past 100:", firstNonNil) fmt.Println("Above member:", items[firstNonNil].Member) fmt.Println("Last member:", items[len(items)-1].Member.User.Username) })
Output:
func (*State) SearchMember ¶
SearchMember queries Discord for a list of members with the given query string.