gateway

package
v0.0.0-...-670ff13 Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2021 License: BSD-3-Clause Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	StatusOnline    = "online"
	StatusDND       = "dnd"
	StatusIdle      = "idle"
	StatusInvisible = "invisible"
	StatusOffline   = "offline"
)
View Source
const DefaultIdentifyRateLimit = 1000
View Source
const MetricReconnectPeriod = time.Hour * 48
View Source
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

func GetShardForGuildID(guildID Snowflake, shardCount uint) (shardID uint)

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 CloseErr

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

func (*CloseErr) Error

func (e *CloseErr) Error() string

type CmdPayload

type CmdPayload interface {
	// contains filtered or unexported methods
}

type Conn

type Conn interface {
	Close() error
	Open(ctx context.Context, endpoint string, requestHeader http.Header) error
	WriteJSON(v interface{}) error
	Read(ctx context.Context) (packet []byte, err error)

	Disconnected() bool
}

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

type Event struct {
	Name    string
	Data    []byte
	ShardID uint
}

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

	EventChan chan<- *Event
	// contains filtered or unexported fields
}

func NewEventClient

func NewEventClient(shardID uint, conf *EvtConfig) (client *EvtClient, err error)

NewManager creates a new socket client manager for handling behavior and Discord events. Note that this function initiates a go routine.

func (EvtClient) AllowedToStartPulsating

func (c EvtClient) AllowedToStartPulsating(serviceID uint8) bool

AllowedToStartPulsating you must notify when you are done pulsating!

func (*EvtClient) Connect

func (c *EvtClient) Connect() (err error)

////////////////////////////////////////////////////

GENERAL: unique to event

////////////////////////////////////////////////////

func (EvtClient) Disconnect

func (c EvtClient) Disconnect() (err error)

Disconnect disconnects the socket connection

func (*EvtClient) Emit

func (c *EvtClient) Emit(command string, data CmdPayload) (err error)

func (EvtClient) HeartbeatLatency

func (c EvtClient) HeartbeatLatency() (duration time.Duration, err error)

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 (c *EvtClient) SetPresence(data interface{}) (err error)

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

func EventToIntent(evt string, direct bool) Intent

func (Intent) String

func (intents Intent) String() string
type Link interface {
	Connect() error
	Disconnect() error
}

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 disgd 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 disgd 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 Snowflake

type Snowflake = util.Snowflake

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:"game"`

	// 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

func (c VoiceClient) AllowedToStartPulsating(serviceID uint8) bool

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 disgd/voiceclient.go into the websocket pkg.

func (VoiceClient) HeartbeatLatency

func (c VoiceClient) HeartbeatLatency() (duration time.Duration, err error)

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 VoiceReady struct {
	SSRC  uint32   `json:"ssrc"`
	IP    string   `json:"ip"`
	Port  int      `json:"port"`
	Modes []string `json:"modes"`
}

type VoiceSelectProtocolParams

type VoiceSelectProtocolParams struct {
	Address string `json:"address"`
	Port    uint16 `json:"port"`
	Mode    string `json:"mode"`
}

type VoiceSessionDescription

type VoiceSessionDescription struct {
	Mode      string   `json:"mode"`
	SecretKey [32]byte `json:"secret_key"`
}

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

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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