1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-12-02 20:02:53 +00:00

Gateway: Added undocumented GuildMemberListUpdate event

This commit is contained in:
diamondburned (Forefront) 2020-03-15 22:55:45 -07:00
parent 1b785b1c38
commit 8899462ff0
5 changed files with 75 additions and 21 deletions

View file

@ -101,9 +101,12 @@ func (g *Gateway) UpdateStatus(data UpdateStatusData) error {
// Undocumented // Undocumented
type GuildSubscribeData struct { type GuildSubscribeData struct {
GuildID discord.Snowflake `json:"guild_id"`
Typing bool `json:"typing"` Typing bool `json:"typing"`
Activities bool `json:"activities"` Activities bool `json:"activities"`
GuildID discord.Snowflake `json:"guild_id"`
// Channels is not documented. It's used to fetch the right members sidebar.
Channels map[discord.Snowflake][][2]int `json:"channels"`
} }
func (g *Gateway) GuildSubscribe(data GuildSubscribeData) error { func (g *Gateway) GuildSubscribe(data GuildSubscribeData) error {

View file

@ -106,6 +106,51 @@ type (
Presences []discord.Presence `json:"presences,omitempty"` Presences []discord.Presence `json:"presences,omitempty"`
} }
// GuildMemberListUpdate is an undocumented event. It's received when the
// client sends over GuildSubscriptions with the Channels field used.
// The State package does not handle this event.
GuildMemberListUpdate struct {
ID string `json:"id"`
GuildID discord.Snowflake `json:"guild_id"`
MemberCount uint64 `json:"member_count"`
OnlineCount uint64 `json:"online_count"`
// Groups is all the visible role sections.
Groups []GuildMemberListGroup `json:"groups"`
Ops []GuildMemberListOp `json:"ops"`
}
GuildMemberListGroup struct {
ID string `json:"id"` // either discord.Snowflake Role IDs or "online"
Count uint64 `json:"count"`
}
GuildMemberListOp struct {
// Mysterious string, so far spotted to be [SYNC, INSERT, UPDATE, DELETE].
Op string `json:"op"`
// NON-SYNC ONLY
// Only available for Ops that aren't "SYNC".
Index int `json:"index,omitempty"`
Item GuildMemberListOpItem `json:"item,omitempty"`
// SYNC ONLY
// Range requested in GuildSubscribeData.
Range [2]int `json:"range,omitempty"`
// Items is basically a linear list of roles and members, similarly to
// how the client renders it. No, it's not nested.
Items []GuildMemberListOpItem `json:"items,omitempty"`
}
// GuildMemberListOpItem is an enum. Either of the fields are provided, but
// never both. Refer to (*GuildMemberListUpdate).Ops for more.
GuildMemberListOpItem struct {
Group *GuildMemberListGroup `json:"group,omitempty"`
Member *struct {
discord.Member
HoistedRole string `json:"hoisted_role"`
Presence discord.Presence `json:"presence"`
} `json:"member,omitempty"`
}
GuildRoleCreateEvent struct { GuildRoleCreateEvent struct {
GuildID discord.Snowflake `json:"guild_id"` GuildID discord.Snowflake `json:"guild_id"`
Role discord.Role `json:"role"` Role discord.Role `json:"role"`

View file

@ -34,6 +34,10 @@ var EventCreator = map[string]func() Event{
"GUILD_MEMBER_UPDATE": func() Event { return new(GuildMemberUpdateEvent) }, "GUILD_MEMBER_UPDATE": func() Event { return new(GuildMemberUpdateEvent) },
"GUILD_MEMBERS_CHUNK": func() Event { return new(GuildMembersChunkEvent) }, "GUILD_MEMBERS_CHUNK": func() Event { return new(GuildMembersChunkEvent) },
"GUILD_MEMBER_LIST_UPDATE": func() Event {
return new(GuildMemberListUpdate)
},
"GUILD_ROLE_CREATE": func() Event { return new(GuildRoleCreateEvent) }, "GUILD_ROLE_CREATE": func() Event { return new(GuildRoleCreateEvent) },
"GUILD_ROLE_UPDATE": func() Event { return new(GuildRoleUpdateEvent) }, "GUILD_ROLE_UPDATE": func() Event { return new(GuildRoleUpdateEvent) },
"GUILD_ROLE_DELETE": func() Event { return new(GuildRoleDeleteEvent) }, "GUILD_ROLE_DELETE": func() Event { return new(GuildRoleDeleteEvent) },

View file

@ -27,6 +27,7 @@ const (
Version = "6" Version = "6"
Encoding = "json" Encoding = "json"
// Compress = "zlib-stream"
) )
var ( var (
@ -135,6 +136,7 @@ func NewGatewayWithDriver(token string, driver json.Driver) (*Gateway, error) {
param := url.Values{} param := url.Values{}
param.Set("v", Version) param.Set("v", Version)
param.Set("encoding", Encoding) param.Set("encoding", Encoding)
// param.Set("compress", Compress)
// Append the form to the URL // Append the form to the URL
URL += "?" + param.Encode() URL += "?" + param.Encode()
@ -249,15 +251,15 @@ func (g *Gateway) start() error {
// This is where we'll get our events // This is where we'll get our events
ch := g.WS.Listen() ch := g.WS.Listen()
// Make a new WaitGroup for use in background loops:
g.waitGroup = new(sync.WaitGroup)
// Wait for an OP 10 Hello // Wait for an OP 10 Hello
var hello HelloEvent var hello HelloEvent
if _, err := AssertEvent(g, <-ch, HelloOP, &hello); err != nil { if _, err := AssertEvent(g, <-ch, HelloOP, &hello); err != nil {
return errors.Wrap(err, "Error at Hello") return errors.Wrap(err, "Error at Hello")
} }
// Make a new WaitGroup for use in background loops:
g.waitGroup = new(sync.WaitGroup)
// Send Discord either the Identify packet (if it's a fresh connection), or // Send Discord either the Identify packet (if it's a fresh connection), or
// a Resume packet (if it's a dead connection). // a Resume packet (if it's a dead connection).
if g.SessionID == "" { if g.SessionID == "" {
@ -375,8 +377,9 @@ func (g *Gateway) send(lock bool, code OPCode, v interface{}) error {
return errors.Wrap(err, "Failed to encode payload") return errors.Wrap(err, "Failed to encode payload")
} }
ctx, cancel := context.WithTimeout(context.Background(), g.WSTimeout) // ctx, cancel := context.WithTimeout(context.Background(), g.WSTimeout)
defer cancel() // defer cancel()
ctx := context.Background()
if lock { if lock {
g.available.RLock() g.available.RLock()

View file

@ -13,21 +13,20 @@ import (
type OPCode uint8 type OPCode uint8
const ( const (
DispatchOP OPCode = iota // recv DispatchOP OPCode = 0 // recv
HeartbeatOP // send/recv HeartbeatOP OPCode = 1 // send/recv
IdentifyOP // send... IdentifyOP OPCode = 2 // send...
StatusUpdateOP // StatusUpdateOP OPCode = 3 //
VoiceStateUpdateOP // VoiceStateUpdateOP OPCode = 4 //
VoiceServerPingOP // VoiceServerPingOP OPCode = 5 //
ResumeOP // ResumeOP OPCode = 6 //
ReconnectOP // recv ReconnectOP OPCode = 7 // recv
RequestGuildMembersOP // send RequestGuildMembersOP OPCode = 8 // send
InvalidSessionOP // recv... InvalidSessionOP OPCode = 9 // recv...
HelloOP HelloOP OPCode = 10
HeartbeatAckOP HeartbeatAckOP OPCode = 11
_ CallConnectOP OPCode = 13
CallConnectOP GuildSubscriptionsOP OPCode = 14
GuildSubscriptionsOP
) )
type OP struct { type OP struct {