member

package
v2.0.0-...-9d96e6b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2021 License: ISC Imports: 12 Imported by: 0

Documentation

Index

Examples

Constants

View Source
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

View Source
var (
	// ErrListNotFound is returned if GetMemberList can't find the list.
	ErrListNotFound = errors.New("List not found.")
)

Functions

func ChunkFromIndex

func ChunkFromIndex(index int) int

ChunkFromIndex calculates the chunk number from the index of Items in List.

func ComputeListID

func ComputeListID(overrides []discord.Overwrite) string

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 Guild

type Guild struct {
	// contains filtered or unexported fields
}

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 NewList

func NewList(id string, guild discord.GuildID) *List

func (*List) CountNil

func (l *List) CountNil() (nils int)

CountNils returns the number of nil items.

func (*List) GuildID

func (l *List) GuildID() discord.GuildID

GuildID returns the list's guild ID. This ID is constant.

func (*List) ID

func (l *List) ID() string

ID returns the list's ID. The ID is made by hashing roles. The list's ID is constant.

func (*List) MaxChunk

func (l *List) MaxChunk() int

MaxChunk returns the maximum complete chunk from Items.

func (*List) MemberCount

func (l *List) MemberCount() int

MemberCount returns the total number of members.

func (*List) OnlineCount

func (l *List) OnlineCount() int

OnlineCount returns the total number of online users.

func (*List) TotalVisible

func (l *List) TotalVisible() int

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 600ms.
	SearchFrequency time.Duration
	SearchLimit     uint // 50
	// 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

func (m *State) GetMemberList(guildID discord.GuildID, channelID discord.ChannelID) (*List, error)

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

func (m *State) GetMemberListChunk(guildID discord.GuildID, channelID discord.ChannelID) int

GetMemberListChunk returns the current member list chunk. It returns -1 if there is none.

func (*State) GetMemberListDirect

func (m *State) GetMemberListDirect(guildID discord.GuildID, id string) (*List, error)

GetMemberListDirect gets the guild's member list directly from the list's ID.

func (*State) RequestMember

func (m *State) RequestMember(guildID discord.GuildID, memberID discord.UserID)

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

func (m *State) SearchMember(guildID discord.GuildID, query string)

SearchMember queries Discord for a list of members with the given query string.

func (*State) Subscribe

func (m *State) Subscribe(guildID discord.GuildID)

Subscribe subscribes the guild to typing events and activities. Callers cal call this multiple times concurrently. The state will ensure that only one command is sent to the gateway.

The gateway command will be sent asynchronously.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL