Documentation ¶
Index ¶
- Constants
- func CmdNameToOpCode(command string, t ClientType) (op opcode.OpCode)
- func ConfigureShardConfig(ctx context.Context, client GatewayBotGetter, conf *ShardConfig) error
- func GetShardForGuildID(guildID Snowflake, shardCount uint) (shardID uint)
- func NewShardMngr(conf ShardManagerConfig) *shardMngr
- type ClientType
- type CloseErr
- type CmdPayload
- type Conn
- type DiscordPacket
- type Event
- type EvtClient
- func (c EvtClient) AllowedToStartPulsating(serviceID uint8) bool
- func (c *EvtClient) Connect() (err error)
- func (c EvtClient) Disconnect() (err error)
- func (c *EvtClient) Emit(command string, data CmdPayload) (err error)
- func (c EvtClient) HeartbeatLatency() (duration time.Duration, err error)
- func (c EvtClient) IsDisconnected() bool
- func (c *EvtClient) SetPresence(data interface{}) (err error)
- func (c EvtClient) StopPulsating(serviceID uint8)
- type EvtConfig
- type Gateway
- type GatewayBot
- type GatewayBotGetter
- type IdentifyMetric
- type Intent
- type Link
- type RequestGuildMembersPayload
- type ShardConfig
- type ShardManager
- type ShardManagerConfig
- type Snowflake
- type UniqueStringSlice
- type UpdateStatusPayload
- type UpdateVoiceStatePayload
- type VoiceClient
- func (c *VoiceClient) Active() <-chan interface{}
- func (c VoiceClient) AllowedToStartPulsating(serviceID uint8) bool
- func (c *VoiceClient) Connect() (rdy *VoiceReady, err error)
- func (c VoiceClient) Disconnect() (err error)
- func (c *VoiceClient) Emit(name string, data interface{}) error
- func (c VoiceClient) HeartbeatLatency() (duration time.Duration, err error)
- func (c VoiceClient) IsDisconnected() bool
- func (c *VoiceClient) SendUDPInfo(data *VoiceSelectProtocolParams) (ret *VoiceSessionDescription, err error)
- func (c VoiceClient) StopPulsating(serviceID uint8)
- type VoiceConfig
- type VoiceReady
- type VoiceSelectProtocolParams
- type VoiceSessionDescription
- type WebsocketErr
Constants ¶
const ( StatusOnline = "online" StatusDND = "dnd" StatusIdle = "idle" StatusInvisible = "invisible" StatusOffline = "offline" )
const DefaultIdentifyRateLimit = 1000
const MetricReconnectPeriod = time.Hour * 48
const SaveIncomingPackets = false
Variables ¶
This section is empty.
Functions ¶
func CmdNameToOpCode ¶
func CmdNameToOpCode(command string, t ClientType) (op opcode.OpCode)
func ConfigureShardConfig ¶
func ConfigureShardConfig(ctx context.Context, client GatewayBotGetter, conf *ShardConfig) error
func GetShardForGuildID ¶
GetShardForGuildID converts a GuildID into a ShardID for correct retrieval of guild information
func NewShardMngr ¶
func NewShardMngr(conf ShardManagerConfig) *shardMngr
Types ¶
type ClientType ¶
type ClientType int
type CmdPayload ¶
type CmdPayload interface {
// contains filtered or unexported methods
}
type DiscordPacket ¶
type DiscordPacket struct { Op opcode.OpCode `json:"op"` Data json.RawMessage `json:"d"` SequenceNumber uint32 `json:"s,omitempty"` EventName string `json:"t,omitempty"` }
DiscordPacket is packets sent by Discord over the socket connection
type Event ¶
Event is dispatched by the socket layer after parsing and extracting Discord data from a incoming packet. This is the data structure used by Disgord for triggering handlers and channels with an event.
type EvtClient ¶
type EvtClient struct { ReadyCounter uint // contains filtered or unexported fields }
func NewEventClient ¶
NewManager creates a new socket client manager for handling behavior and Discord events. Note that this function initiates a go routine.
func (EvtClient) AllowedToStartPulsating ¶
AllowedToStartPulsating you must notify when you are done pulsating!
func (*EvtClient) Connect ¶
////////////////////////////////////////////////////
GENERAL: unique to event
////////////////////////////////////////////////////
func (EvtClient) Disconnect ¶
func (c EvtClient) Disconnect() (err error)
Disconnect disconnects the socket connection
func (EvtClient) HeartbeatLatency ¶
HeartbeatLatency get the time diff between sending a heartbeat and Discord replying with a heartbeat ack
func (EvtClient) IsDisconnected ¶
func (c EvtClient) IsDisconnected() bool
////////////////////////////////////////////////////
LINKING: CONNECTING / DISCONNECTING / RECONNECTING
////////////////////////////////////////////////////
func (*EvtClient) SetPresence ¶
func (EvtClient) StopPulsating ¶
func (c EvtClient) StopPulsating(serviceID uint8)
StopPulsating stops sending heartbeats to Discord
type EvtConfig ¶
type EvtConfig struct { // BotToken Discord bot token BotToken string HTTPClient *http.Client // IgnoreEvents holds a list of predetermined events that should be ignored. IgnoreEvents []string Intents Intent // EventChan can be used to inject a channel instead of letting the ws client construct one // useful in sharding to avoid complicated patterns to handle N channels. EventChan chan<- *Event Presence *UpdateStatusPayload // Endpoint for establishing socket connection. Either endpoints, `Gateway` or `Gateway Bot`, is used to retrieve // a valid socket endpoint from Discord Endpoint string // Encoding make sure we support the correct encoding Encoding string // Version make sure we support the correct Discord version Version int // for identify packets Browser string Device string GuildLargeThreshold uint ShardCount uint DiscordPktPool *sync.Pool // MessageQueueLimit number of outgoing messages that can be queued and sent correctly. MessageQueueLimit uint Logger logger.Logger SystemShutdown chan interface{} // contains filtered or unexported fields }
EvtConfig ws
type Gateway ¶
type Gateway struct {
URL string `json:"url"`
}
Gateway is for parsing the Gateway endpoint response
type GatewayBot ¶
type GatewayBot struct { Gateway Shards uint `json:"shards"` SessionStartLimit struct { Total uint `json:"total"` Remaining uint `json:"remaining"` ResetAfter uint `json:"reset_after"` } `json:"session_start_limit"` }
GatewayBot is for parsing the Gateway Bot endpoint response
type GatewayBotGetter ¶
type GatewayBotGetter interface {
GetGatewayBot(context.Context) (gateway *GatewayBot, err error)
}
type IdentifyMetric ¶
type IdentifyMetric struct { sync.Mutex Reconnects []time.Time // last 48h or (see const ReconnectPeriod) }
TODO-1: make it specific to individual shards for more insight TODO-2: Limit storage period
func (*IdentifyMetric) ReconnectsSince ¶
func (s *IdentifyMetric) ReconnectsSince(d time.Duration) (counter uint)
ReconnectsSince counts the number of reconnects since t, where t can be no more than ReconnectPeriod (48h?)
type Intent ¶
type Intent uint64
const ( // IntentGuilds // - GUILD_CREATE // - GUILD_UPDATE // - GUILD_DELETE // - GUILD_ROLE_CREATE // - GUILD_ROLE_UPDATE // - GUILD_ROLE_DELETE // - CHANNEL_CREATE // - CHANNEL_UPDATE // - CHANNEL_DELETE // - CHANNEL_PINS_UPDATE IntentGuilds Intent = 1 << iota // IntentGuildMembers // - GUILD_MEMBER_ADD // - GUILD_MEMBER_UPDATE // - GUILD_MEMBER_REMOVE IntentGuildMembers // IntentGuildBans // - GUILD_BAN_ADD // - GUILD_BAN_REMOVE IntentGuildBans // IntentGuildEmojis // - GUILD_EMOJIS_UPDATE IntentGuildEmojis // IntentGuildIntegrations // - GUILD_INTEGRATIONS_UPDATE IntentGuildIntegrations IntentGuildWebhooks IntentGuildInvites IntentGuildVoiceStates IntentGuildPresences IntentGuildMessages IntentGuildMessageReactions IntentGuildMessageTyping IntentDirectMessages IntentDirectMessageReactions IntentDirectMessageTyping )
func EventToIntent ¶
type Link ¶
Link is used to establish basic commands to create and destroy a link. See client.Disconnect() and client.Connect() for linking to the Discord servers
type RequestGuildMembersPayload ¶
type RequestGuildMembersPayload struct { // GuildID id of the guild(s) to get offline members for GuildIDs []Snowflake `json:"guild_id"` // Query string that username starts with, or an empty string to return all members Query string `json:"query"` // Limit maximum number of members to send or 0 to request all members matched Limit uint `json:"limit"` Presences bool `json:"presences"` // UserIDs used to specify which users you wish to fetch UserIDs []Snowflake `json:"user_ids,omitempty"` Nonce string `json:"nonce,omitempty"` }
type ShardConfig ¶
type ShardConfig struct { // Specify the shard ids that can be used by this instance. // eg. ShardIds = []uint{0,1,2,3,11,12,13,14,32} // // This control is only useful if you have more than once instance of your bot duo to // high traffic or whatever reason you might possess. // // This also allows you to manually specify the number of shards, you just have to // specify their ID as well. You start from 0 until the number of shards you desire. // // Default value is populated by discord if this slice is nil. ShardIDs []uint // ShardCount should reflect the "total number of shards" across all // instances for your bot. If you run 3 containers with 2 shards each, then // the ShardCount should be 6, while the length of shardIDs would be // two on each container. // // defaults to len(shardIDs) if 0 ShardCount uint // Large bots only. If Discord did not give you a custom rate limit, do not touch this. ShardRateLimit time.Duration // ConnectQueue is used to control how often shards can connect by sending an identify command. // For distributed systems, this must be overwritten as, by default, you can only send one identify // every five seconds. The default implementation can be found in shard_sync.go. ConnectQueue connectQueue // DisableAutoScaling is triggered when at least one shard gets a 4011 websocket // error from Discord. This causes all the shards to disconnect and new ones are created. // // default value is false unless shardIDs or ShardCount is set. DisableAutoScaling bool // OnScalingRequired is triggered when Discord closes the websocket connection // with a 4011 websocket error. It may run multiple times per session. You should // immediately call disconnect and scale your shards, unless you know what you're doing. // // This is triggered when DisableAutoScaling is true. If DisableAutoScaling is true and // OnScalingRequired is nil, this is considered an user error and will panic. // // You must return the new number of total shards and additional shard ids this instance // should setup. If you do not want this instance to gain extra shards, set AdditionalShardIDs // to nil. OnScalingRequired func(shardIDs []uint) (TotalNrOfShards uint, AdditionalShardIDs []uint) // OnScalingDiscardedRequests When scaling is triggered, some of the guilds might have moved to other shards // that do not exist on this disgord instance. This callback will return a list of guild ID that exists in // outgoing requests that were discarded due to no local shard match. // // Note: only regards systems with multiple disgord instances // TODO: return a list of outgoing requests instead such that people can re-trigger these on other instances. OnScalingDiscardedRequests func(unhandledGuildIDs []Snowflake) // IdentifiesPer24H regards how many identify packets a bot can send per a 24h period. Normally this // is 1000, but in some cases discord might allow you to increase it. // // Setting it to 0 will default it to 1000. IdentifiesPer24H uint // URL is fetched from the gateway before initialising a connection URL string }
type ShardManager ¶
type ShardManager interface { Connect() error Disconnect() error Emit(string, CmdPayload) (unhandledGuildIDs []Snowflake, err error) LocalShardCount() uint ShardCount() uint ShardIDs() (shardIDs []uint) GetShard(shardID shardID) (shard *EvtClient, err error) HeartbeatLatencies() (latencies map[shardID]time.Duration, err error) }
ShardManager regards websocket shards.
type ShardManagerConfig ¶
type ShardManagerConfig struct { ShardConfig DisgordInfo string BotToken string HTTPClient *http.Client Logger logger.Logger ShutdownChan chan interface{} // ... IgnoreEvents []string Intents Intent // sync --- EventChan chan<- *Event RESTClient GatewayBotGetter // user specific DefaultBotPresence *UpdateStatusPayload ProjectName string // contains filtered or unexported fields }
ShardManagerConfig all fields, except proxy.Dialer, is required
type UniqueStringSlice ¶
type UniqueStringSlice struct {
// contains filtered or unexported fields
}
UniqueStringSlice a thread safe string slice that does not allow duplicate strings to be stored
func (*UniqueStringSlice) Add ¶
func (s *UniqueStringSlice) Add(id string)
func (*UniqueStringSlice) Contains ¶
func (s *UniqueStringSlice) Contains(id string) (exists bool)
func (*UniqueStringSlice) Len ¶
func (s *UniqueStringSlice) Len() int
func (*UniqueStringSlice) Remove ¶
func (s *UniqueStringSlice) Remove(id string)
type UpdateStatusPayload ¶
type UpdateStatusPayload struct { // Since unix time (in milliseconds) of when the Client went idle, or null if the Client is not idle Since *uint `json:"since"` // Game null, or the user's new activity Game interface{} `json:"activities"` // Status the user's new status Status string `json:"status"` // AFK whether or not the Client is afk AFK bool `json:"afk"` }
type UpdateVoiceStatePayload ¶
type UpdateVoiceStatePayload struct { // GuildID id of the guild GuildID Snowflake `json:"guild_id"` // ChannelID id of the voice channel Client wants to join // (set to 0 if disconnecting) ChannelID Snowflake `json:"channel_id"` // SelfMute is the Client mute SelfMute bool `json:"self_mute"` // SelfDeaf is the Client deafened SelfDeaf bool `json:"self_deaf"` }
type VoiceClient ¶
type VoiceClient struct { SystemShutdown chan interface{} // contains filtered or unexported fields }
func NewVoiceClient ¶
func NewVoiceClient(conf *VoiceConfig) (client *VoiceClient, err error)
func (*VoiceClient) Active ¶
func (c *VoiceClient) Active() <-chan interface{}
func (VoiceClient) AllowedToStartPulsating ¶
AllowedToStartPulsating you must notify when you are done pulsating!
func (*VoiceClient) Connect ¶
func (c *VoiceClient) Connect() (rdy *VoiceReady, err error)
Connect establishes a socket connection with the Discord API
func (VoiceClient) Disconnect ¶
func (c VoiceClient) Disconnect() (err error)
Disconnect disconnects the socket connection
func (*VoiceClient) Emit ¶
func (c *VoiceClient) Emit(name string, data interface{}) error
Emit for voice client needs to bypass the normal Emit restrictions. TODO: put more of the code flow of disgord/voiceclient.go into the websocket pkg.
func (VoiceClient) HeartbeatLatency ¶
HeartbeatLatency get the time diff between sending a heartbeat and Discord replying with a heartbeat ack
func (VoiceClient) IsDisconnected ¶
func (c VoiceClient) IsDisconnected() bool
////////////////////////////////////////////////////
LINKING: CONNECTING / DISCONNECTING / RECONNECTING
////////////////////////////////////////////////////
func (*VoiceClient) SendUDPInfo ¶
func (c *VoiceClient) SendUDPInfo(data *VoiceSelectProtocolParams) (ret *VoiceSessionDescription, err error)
func (VoiceClient) StopPulsating ¶
func (c VoiceClient) StopPulsating(serviceID uint8)
StopPulsating stops sending heartbeats to Discord
type VoiceConfig ¶
type VoiceConfig struct { // Guild ID to connect to GuildID Snowflake // User ID that is connecting UserID Snowflake // Session ID SessionID string // Token to connect with the voice websocket Token string // proxy allows for use of a custom proxy HTTPClient *http.Client // Endpoint for establishing voice connection Endpoint string // MessageQueueLimit number of outgoing messages that can be queued and sent correctly. MessageQueueLimit uint Logger logger.Logger SystemShutdown chan interface{} }
type VoiceReady ¶
type VoiceSessionDescription ¶
type WebsocketErr ¶
type WebsocketErr struct { ID uint // contains filtered or unexported fields }
WebsocketErr is used internally when the websocket package returns an error. It does not represent a Discord error!
func (*WebsocketErr) Error ¶
func (e *WebsocketErr) Error() string