discordgateway

package module
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2020 License: MIT Imports: 10 Imported by: 1

README

Code coverage PkgGoDev

Use the existing disgord channels for discussion

Discord Gophers Discord API

Ideology

Discord is a mess. Consistency is a luxury. And simplicity is somewhere over there or here.

This project aims to normalize some namings, make interacting more intuitive and development a smoother experience.

Certain events and intents have been renamed in accordance to the famous CRUD naming scheme.

Philosophy/requirements:

  • Complete control of goroutines (if desired)
  • Events are bit flags and intents are a set of events (bit flags)
  • You're responsible for reading all incoming data
  • Sending gateway commands returns an error on failure
  • You only register for guild events by default (dm events must be stated explicitly)
  • context is supported when it makes sense, via ".WithContext(context.Context)"
  • desired events must be specified in the config, others are ignored (this allows for optimizations behind the scenes)
  • Control over reconnect, disconnect, or behavior for handling discord errors
  • cancellation

Events and intents

I don't agree with the way Discord allows subscribing to specific group of events or the previous "guild subscription" logic of theirs. Nor do I know what they will do in the future. And so I try to abstract this away. You should only worry about the events you want, not intents, guild subscriptions, or whatever else might be introduced later.

Intents are derived from events, except the special case of Direct Messaging capabilities. Those needs to be explicitly defined:

intent.DirectMessages.EventFlags()

Events are defined as bit flags and intents are a bitmask consistent of a range of relevant events.

event.GuildBanCreate = 0b0100000
event.GuildBanDelete = 0b1000000
--------------------------------
intent.GuildBans     = 0b1100000

You can specify a range of events to be ignored using bit operations:

&ShardConfig{
    Events: ^(event.GuildBanCreate | event.GuildBanDelete),
}

Or just state you want whatever a certain intent holds:

&ShardConfig{
    Events: intent.GuildMessages.EventFlags(),
}

Be aware that DM intents holds custom event flags. These are used internally to correctly understand which events you are requesting.

Events not specified are discarded at the package level, and will not trigger the registered handler.

Configuration

Shard

Intents

Intents are derived from event IDs. Intents that deals with DM events or events that can only take place when the shard ID is 0, must be provided explicitly.

Both intents and events are turned on and off by bit flags. Since intents states whether or not a specific range of events should be sent from Discord, we can say that a intent I subsumes a event E, if the bit value of E exists within the bit range of I.

intent.Guilds =

Imagine that each event ID is a bit flag, and that intents

// I don't need direct message capabilities
conf := &discordgateway.ShardConfig{
    Events: event.MessageCreate | event.MessageDelete,
}
// I need to handle direct messages
conf := &discordgateway.ShardConfig{
    Events: event.MessageCreate | event.MessageDelete,
    Intents: intent.DirectMessages, // explicitly stated
}
// I need to handle direct messages
conf := &discordgateway.ShardConfig{
    Events: event.MessageCreate | event.MessageDelete,
    Intents: intent.DirectMessages | intent.GuildBans, // redundant intent, will error
}

// panic: intent.GuildBans does not subsume any given intent IDs 

Support

  • Voice
  • Gateway
    • Intents
    • JSON
    • ETF
    • Rate limit
      • Identify
      • Commands
  • Shard(s) manager
  • Buffer pool

Documentation

Index

Constants

View Source
const (
	VoiceCloseCodeUnknownOpCodeReason         = "VoiceCloseCodeUnknownOpCode You sent an invalid opcode"
	VoiceCloseCodeNotAuthenticatedReason      = "VoiceCloseCodeNotAuthenticated You sent a payload before identifying with the Gateway"
	VoiceCloseCodeAuthenticationFailedReason  = "VoiceCloseCodeAuthenticationFailed The token you sent in your identify payload is incorrect"
	VoiceCloseCodeAlreadyAuthenticatedReason  = "VoiceCloseCodeAlreadyAuthenticated You sent more than one identify payload. Stahp"
	VoiceCloseCodeSessionNoLongerValidReason  = "VoiceCloseCodeSessionNoLongerValid Your session is no longer valid"
	VoiceCloseCodeSessionTimedOutReason       = "VoiceCloseCodeSessionTimedOut Your session has timed out"
	VoiceCloseCodeServerNotFoundReason        = "VoiceCloseCodeServerNotFound We can't find the server you're trying to connect to"
	VoiceCloseCodeUnknownProtocolReason       = "VoiceCloseCodeUnknownProtocol We didn't recognize the protocol you sent"
	VoiceCloseCodeDisconnectedReason          = "VoiceCloseCodeDisconnected Either the channel was deleted or you were kicked. Should not reconnect"
	VoiceCloseCodeVoiceServerCrashedReason    = "VoiceCloseCodeVoiceServerCrashed The server crashed. Our bad! Try resuming"
	VoiceCloseCodeUnknownEncryptionModeReason = "VoiceCloseCodeUnknownEncryptionMode We didn't recognize your encryption"
)

Code generated - This file has been automatically generated by internal/generate/errors/main.go - DO NOT EDIT. Warning: This file is overwritten at "go generate", instead adapt error.go and run go generate

View Source
const (
	CloseCodeUnknownErrorReason         = "CloseCodeUnknownError We're not sure what went wrong. Try reconnecting?"
	CloseCodeUnknownOpCodeReason        = "CloseCodeUnknownOpCode You sent an invalid Gateway opcode or an invalid payload for an opcode. Don't do that!"
	CloseCodeDecodeErrorReason          = "CloseCodeDecodeError You sent an invalid payload to us. Don't do that!"
	CloseCodeNotAuthenticatedReason     = "CloseCodeNotAuthenticated You sent us a payload prior to identifying"
	CloseCodeAuthenticationFailedReason = "CloseCodeAuthenticationFailed The account token sent with your identify payload is incorrect"
	CloseCodeAlreadyAuthenticatedReason = "CloseCodeAlreadyAuthenticated You sent more than one identify payload. Don't do that!"
	CloseCodeInvalidSeqReason           = "CloseCodeInvalidSeq The sequence sent when resuming the session was invalid. Reconnect and start a new session"
	CloseCodeRateLimitedReason          = "" /* 132-byte string literal not displayed */
	CloseCodeSessionTimedOutReason      = "CloseCodeSessionTimedOut Your session timed out. Reconnect and start a new one"
	CloseCodeInvalidShardReason         = "CloseCodeInvalidShard You sent us an invalid shard when identifying"
	CloseCodeShardingRequiredReason     = "" /* 136-byte string literal not displayed */
	CloseCodeInvalidAPIVersionReason    = "CloseCodeInvalidAPIVersion You sent an invalid version for the gateway"
	CloseCodeInvalidIntentsReason       = "" /* 126-byte string literal not displayed */
	CloseCodeDisallowedIntentsReason    = "" /* 170-byte string literal not displayed */
)

Variables

This section is empty.

Functions

func ClientShard

func ClientShard(guildID uint64, totalNumberOfShards uint) (shardID uint)

Types

type ClientState

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

ClientState should be discarded after the connection has closed. reconnect must create a new shard instance.

func NewResumableShard

func NewResumableShard(deadShard *ClientState) *ClientState

NewResumableShard when a client/shard disconnects for whatever reason, you must create a new instance. To utilise the resume logic from discord you must use the new client instance below. Note that it is your responsibility to make sure you are allowed to resume. eg. resuming after a "invalid session" will most likely fail, and you need to create a new shard again.

You must use the newly returned instance. The argument/function input should be left for garbage collection.

func NewShard

func NewShard(conf *ClientStateConfig) *ClientState

func NewShardFromPrevious

func NewShardFromPrevious(deadShard *ClientState) *ClientState

func (*ClientState) Closed

func (c *ClientState) Closed() bool

func (*ClientState) HaveIdentified

func (c *ClientState) HaveIdentified() bool

func (*ClientState) HaveSessionID

func (c *ClientState) HaveSessionID() bool

func (*ClientState) Heartbeat

func (c *ClientState) Heartbeat(client IOFlushWriter) error

Heartbeat Close method may be used if Write fails

func (*ClientState) Identify

func (c *ClientState) Identify(client IOFlushWriter) error

Identify Close method may be used if Write fails

func (*ClientState) Read

func (c *ClientState) Read(client IOReader) (*GatewayPayload, int, error)

Read until a new data frame with updated info comes in, or fails.

func (*ClientState) Resume

func (c *ClientState) Resume(client IOFlushWriter) error

Resume Close method may be used if Write fails

func (*ClientState) WriteClose

func (c *ClientState) WriteClose(client IOFlushWriter) error

type ClientStateConfig

type ClientStateConfig struct {
	Token               string
	Intents             intent.Flag
	ShardID             uint
	TotalNumberOfShards uint
	Properties          GatewayIdentifyProperties
}

type CloseCode

type CloseCode DiscordErrorCode
const (
	// CloseCodeUnknownError We're not sure what went wrong. Try reconnecting?
	CloseCodeUnknownError CloseCode = 4000 + iota
	// CloseCodeUnknownOpCode You sent an invalid Gateway opcode or an invalid payload for an opcode. Don't do that!
	CloseCodeUnknownOpCode
	// CloseCodeDecodeError You sent an invalid payload to us. Don't do that!
	CloseCodeDecodeError
	// CloseCodeNotAuthenticated You sent us a payload prior to identifying
	CloseCodeNotAuthenticated
	// CloseCodeAuthenticationFailed The account token sent with your identify payload is incorrect
	CloseCodeAuthenticationFailed
	// CloseCodeAlreadyAuthenticated You sent more than one identify payload. Don't do that!
	CloseCodeAlreadyAuthenticated

	// CloseCodeInvalidSeq The sequence sent when resuming the session was invalid. Reconnect and start a new session
	CloseCodeInvalidSeq
	// CloseCodeRateLimited Woah nelly! You're sending payloads to us too quickly. Slow it down! You will be disconnected on receiving this
	CloseCodeRateLimited
	// CloseCodeSessionTimedOut Your session timed out. Reconnect and start a new one
	CloseCodeSessionTimedOut
	// CloseCodeInvalidShard You sent us an invalid shard when identifying
	CloseCodeInvalidShard
	// CloseCodeShardingRequired The session would have handled too many guilds - you are required to shard your connection in order to connect
	CloseCodeShardingRequired
	// CloseCodeInvalidAPIVersion You sent an invalid version for the gateway
	CloseCodeInvalidAPIVersion
	// CloseCodeInvalidIntents You sent an invalid intent for a Gateway Intent. You may have incorrectly calculated the bitwise value
	CloseCodeInvalidIntents
	// CloseCodeDisallowedIntents You sent a disallowed intent for a Gateway Intent. You may have tried to specify an intent that you have not enabled or are not whitelisted for
	CloseCodeDisallowedIntents
)

type CloseErr

type CloseErr struct {
	Code CloseCode
	Err  error
}

func (*CloseErr) Error

func (e *CloseErr) Error() string

type CloseError

type CloseError struct {
	Code   uint
	Reason string
}

func (*CloseError) Error

func (c *CloseError) Error() string

type DiscordErrorCode

type DiscordErrorCode uint32
const (
	HeartbeatAckNotReceived DiscordErrorCode = 3000
)

custom codes

type DiscordVoiceCloseErr

type DiscordVoiceCloseErr struct {
	Code VoiceCloseEventCode
}

func (*DiscordVoiceCloseErr) Error

func (e *DiscordVoiceCloseErr) Error() string

type GatewayHello

type GatewayHello struct {
	HeartbeatIntervalMilli int64 `json:"heartbeat_interval"`
}

type GatewayIdentify

type GatewayIdentify struct {
	Token          string      `json:"token"`
	Properties     interface{} `json:"properties"`
	Compress       bool        `json:"compress,omitempty"`
	LargeThreshold uint8       `json:"large_threshold,omitempty"`
	Shard          [2]uint     `json:"shard"`
	Presence       interface{} `json:"presence"`
	Intents        intent.Flag `json:"intents"`
}

type GatewayIdentifyProperties

type GatewayIdentifyProperties struct {
	OS      string `json:"$os"`
	Browser string `json:"$browser"`
	Device  string `json:"$device"`
}

type GatewayPayload

type GatewayPayload struct {
	Op        uint8      `json:"op"`
	Data      RawMessage `json:"d"`
	Seq       int64      `json:"s,omitempty"`
	EventName string     `json:"t,omitempty"`
	// EventID   event.Flag `json:"-"`
	Outdated bool `json:"-"`
}

type GatewayResume

type GatewayResume struct {
	Token          string `json:"token"`
	SessionID      string `json:"session_id"`
	SequenceNumber int64  `json:"seq"`
}

type Handler

type Handler func(ShardID, event.Flag, RawMessage)

type IOFlushReadWriter

type IOFlushReadWriter interface {
	IOFlusher
	IOReader
	IOWriter
}

type IOFlushWriter

type IOFlushWriter interface {
	IOFlusher
	IOWriter
}

type IOFlusher

type IOFlusher interface {
	Flush() error
}

type IOReadWriter

type IOReadWriter interface {
	IOWriter
	IOReader
}

type IOReader

type IOReader interface {
	io.Reader
}

type IOWriter

type IOWriter interface {
	io.Writer
}

type RawMessage

type RawMessage = json.RawMessage

type ShardID

type ShardID uint16

type VoiceCloseEventCode

type VoiceCloseEventCode DiscordErrorCode
const (

	// VoiceCloseCodeUnknownOpCode You sent an invalid opcode
	VoiceCloseCodeUnknownOpCode VoiceCloseEventCode

	// VoiceCloseCodeNotAuthenticated You sent a payload before identifying with the Gateway
	VoiceCloseCodeNotAuthenticated
	// VoiceCloseCodeAuthenticationFailed The token you sent in your identify payload is incorrect
	VoiceCloseCodeAuthenticationFailed
	// VoiceCloseCodeAlreadyAuthenticated You sent more than one identify payload. Stahp
	VoiceCloseCodeAlreadyAuthenticated
	// VoiceCloseCodeSessionNoLongerValid Your session is no longer valid
	VoiceCloseCodeSessionNoLongerValid

	// VoiceCloseCodeSessionTimedOut Your session has timed out
	VoiceCloseCodeSessionTimedOut

	// VoiceCloseCodeServerNotFound We can't find the server you're trying to connect to
	VoiceCloseCodeServerNotFound
	// VoiceCloseCodeUnknownProtocol We didn't recognize the protocol you sent
	VoiceCloseCodeUnknownProtocol

	// VoiceCloseCodeDisconnected Either the channel was deleted or you were kicked. Should not reconnect
	VoiceCloseCodeDisconnected
	// VoiceCloseCodeVoiceServerCrashed The server crashed. Our bad! Try resuming
	VoiceCloseCodeVoiceServerCrashed
	// VoiceCloseCodeUnknownEncryptionMode We didn't recognize your encryption
	VoiceCloseCodeUnknownEncryptionMode
)

Directories

Path Synopsis
cmd
internal

Jump to

Keyboard shortcuts

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