internal

package
v0.0.0-...-4a3f5b2 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2024 License: MIT Imports: 50 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ShardMaxRetries              = 5
	ShardCompression             = true
	ShardLargeThreshold          = 100
	ShardMaxHeartbeatFailures    = 5
	MessagingMaxClientNameNumber = 9999

	StandardIdentifyLimit = 5
	IdentifyRetry         = (StandardIdentifyLimit * time.Second)
	IdentifyRateLimit     = (StandardIdentifyLimit * time.Second) + (500 * time.Millisecond)
)
View Source
const (
	PermissionsDefault = 0o744
	PermissionWrite    = 0o600
)
View Source
const (
	WebsocketReadLimit          = 512 << 20
	WebsocketReconnectCloseCode = 4000

	// Time required before warning about an event taking too long.
	DispatchWarningTimeout = 30 * time.Second

	MessageChannelBuffer = 64

	// Time necessary to mark chunking as completed when no more events are received in this time frame.
	MemberChunkTimeout = 1 * time.Second

	// Number of retries attempted before considering a shard not working.
	ShardConnectRetries = 3

	ShardWSRateLimit      = 118
	GatewayLargeThreshold = 100

	FirstEventTimeout = 5 * time.Second

	WaitForReadyTimeout = 15 * time.Second
	ReadyTimeout        = 5 * time.Second

	MaxReconnectWait = 60 * time.Second

	WriteJSONRetry = 1 * time.Second
)
View Source
const (
	EmbedColourSandwich = 16701571
	EmbedColourWarning  = 16760839
	EmbedColourDanger   = 14431557

	WebhookRateLimitDuration = 5 * time.Second
	WebhookRateLimitLimit    = 5
)

Embed colours for webhooks.

View Source
const MagicDecimalBase = 10
View Source
const VERSION = "1.13"

VERSION follows semantic versioning.

Variables

View Source
var (
	ErrInvalidManager    = errors.New("no manager with this name exists")
	ErrInvalidShardGroup = errors.New("invalid shard group id specified")
	ErrInvalidShard      = errors.New("invalid shard id specified")
	ErrChunkTimeout      = errors.New("timed out on initial member chunks")
	ErrMissingShards     = errors.New("shardGroup has no shards")
)
View Source
var (
	ErrReadConfigurationFailure        = errors.New("failed to read configuration")
	ErrLoadConfigurationFailure        = errors.New("failed to load configuration")
	ErrConfigurationValidateIdentify   = errors.New("configuration missing valid Identify URI")
	ErrConfigurationValidatePrometheus = errors.New("configuration missing valid Prometheus Host")
	ErrConfigurationValidateGRPC       = errors.New("configuration missing valid GRPC Host")
	ErrConfigurationValidateHTTP       = errors.New("configuration missing valid HTTP Host")
)
View Source
var (
	ErrNoGatewayHandler  = errors.New("no registered handler for gateway event")
	ErrNoDispatchHandler = errors.New("no registered handler for dispatch event")
	ErrProducerMissing   = errors.New("no producer client found")
)
View Source
var (
	ErrNoGuildIDPresent = errors.New("missing guild ID")
	ErrNoUserIDPresent  = errors.New("missing user ID")
	ErrNoQueryPresent   = errors.New("missing query")

	ErrDuplicateManagerPresent = errors.New("duplicate manager identifier passed")
	ErrNoManagerPresent        = errors.New("invalid manager identifier passed")
	ErrNoShardGroupPresent     = errors.New("invalid shard group identifier passed")
	ErrNoShardPresent          = errors.New("invalid shard ID passed")

	ErrCacheMiss = errors.New("item not present in cache")
)
View Source
var (
	ErrUserMissingAccess = errors.New("you are missing access")
	ErrUserNotLoggedIn   = errors.New("you are not logged in")

	DistPath = "web/dist"

	StatusCacheDuration = time.Second * 30
)
View Source
var ErrInvalidToken = errors.New("token passed is not valid")

ErrInvalidToken is returned when an invalid token is used.

View Source
var ErrReconnect = errors.New("reconnect is required")

ErrReconnect is used to distinguish if the shard simply wants to reconnect.

View Source
var ErrSessionLimitExhausted = errors.New("the session limit has been reached")

ErrSessionLimitExhausted is returned when the sessions remaining is less than the ShardGroup is starting with.

Functions

func GatewayDispatch

func GatewayDispatch(ctx context.Context, sh *Shard,
	event discord.GatewayPayload, trace sandwich_structs.SandwichTrace,
) error

GatewayDispatch handles selecting the proper gateway handler and executing it.

func OnApplicationCommandCreate

func OnApplicationCommandCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnApplicationCommandDelete

func OnApplicationCommandDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnApplicationCommandUpdate

func OnApplicationCommandUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnChannelCreate

func OnChannelCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnChannelDelete

func OnChannelDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnChannelPinsUpdate

func OnChannelPinsUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnChannelUpdate

func OnChannelUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildBanRemove

func OnGuildBanRemove(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildEmojisUpdate

func OnGuildEmojisUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildIntegrationsUpdate

func OnGuildIntegrationsUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildJoinRequestDelete

func OnGuildJoinRequestDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildMemberAdd

func OnGuildMemberAdd(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildMemberRemove

func OnGuildMemberRemove(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildMemberUpdate

func OnGuildMemberUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildMembersChunk

func OnGuildMembersChunk(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildRoleCreate

func OnGuildRoleCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildRoleDelete

func OnGuildRoleDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildRoleUpdate

func OnGuildRoleUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnGuildStickersUpdate

func OnGuildStickersUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnIntegrationCreate

func OnIntegrationCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnIntegrationDelete

func OnIntegrationDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnIntegrationUpdate

func OnIntegrationUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnInteractionCreate

func OnInteractionCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageCreate

func OnMessageCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageDelete

func OnMessageDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageDeleteBulk

func OnMessageDeleteBulk(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageReactionAdd

func OnMessageReactionAdd(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageReactionRemove

func OnMessageReactionRemove(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageReactionRemoveAll

func OnMessageReactionRemoveAll(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageReactionRemoveEmoji

func OnMessageReactionRemoveEmoji(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnMessageUpdate

func OnMessageUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnPresenceUpdate

func OnPresenceUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnReady

OnReady handles the READY event. It will go and mark guilds as unavailable and go through any GUILD_CREATE events for the next few seconds.

func OnStageInstanceCreate

func OnStageInstanceCreate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnStageInstanceDelete

func OnStageInstanceDelete(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnStageInstanceUpdate

func OnStageInstanceUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnThreadListSync

func OnThreadListSync(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnThreadMemberUpdate

func OnThreadMemberUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnThreadMembersUpdate

func OnThreadMembersUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnVoiceServerUpdate

func OnVoiceServerUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnVoiceStateUpdate

func OnVoiceStateUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func OnWebhookUpdate

func OnWebhookUpdate(ctx *StateCtx, msg discord.GatewayPayload, trace sandwich_structs.SandwichTrace) (result sandwich_structs.StateResult, ok bool, err error)

func StateDispatch

func StateDispatch(ctx *StateCtx,
	event discord.GatewayPayload, trace sandwich_structs.SandwichTrace,
) (result sandwich_structs.StateResult, ok bool, err error)

StateDispatch handles selecting the proper state handler and executing it.

Types

type Client

type Client struct {
	Token string

	HTTP *http.Client

	// We will manually add the API version
	APIVersion string

	// Used to safely create URLs and is filled if empty
	URLHost   string
	URLScheme string
	UserAgent string
	// contains filtered or unexported fields
}

Client represents the REST client.

func NewClient

func NewClient(baseURL url.URL, token string) *Client

NewClient makes a new client.

func (*Client) Fetch

func (c *Client) Fetch(ctx context.Context, method string, url string,
	body io.Reader, headers map[string]string,
) ([]byte, int, error)

Fetch returns the response. Passing any headers will be sent to the request however Authorization will be overwrote.

func (*Client) FetchJSON

func (c *Client) FetchJSON(ctx context.Context, method string, url string, body io.Reader,
	headers map[string]string, structure interface{},
) (int, error)

FetchJSON attempts to convert the response into a JSON structure. Passing any headers will be sent to the request however Authorization will be overwrote.

func (*Client) HandleRequest

func (c *Client) HandleRequest(req *http.Request, retry bool) (*http.Response, error)

HandleRequest makes a request to the Discord API.

type GuildChunkPartial

type GuildChunkPartial struct {
	ChunkIndex int32
	ChunkCount int32
	Nonce      string
}

type GuildChunks

type GuildChunks struct {
	// Indicates if all chunks have been received.
	Complete atomic.Bool

	// Channel for receiving when chunks have been received.
	ChunkingChannel chan GuildChunkPartial

	StartedAt   atomic.Time
	CompletedAt atomic.Time
}

type MQClient

type MQClient interface {
	String() string
	Channel() string
	Cluster() string

	Connect(ctx context.Context, clientName string, args map[string]interface{}) error
	Publish(ctx context.Context, channel string, data []byte) error
}

func NewMQClient

func NewMQClient(mqType string) (MQClient, error)

type Manager

type Manager struct {
	Error *atomic.String `json:"error" yaml:"error"`

	Identifier *atomic.String `json:"-"`

	Sandwich *Sandwich      `json:"-"`
	Logger   zerolog.Logger `json:"-"`

	Configuration *ManagerConfiguration `json:"configuration" yaml:"configuration"`

	Gateway discord.GatewayBotResponse `json:"gateway" yaml:"gateway"`

	ShardGroups map[int32]*ShardGroup `json:"shard_groups" yaml:"shard_groups"`

	ProducerClient MQClient `json:"-"`

	Client *Client `json:"-"`

	UserID *atomic.Int64 `json:"id"`

	User discord.User `json:"user"`
	// contains filtered or unexported fields
}

Manager represents a single application.

func (*Manager) Close

func (mg *Manager) Close()

func (*Manager) GetGateway

func (mg *Manager) GetGateway() (resp discord.GatewayBotResponse, err error)

GetGateway returns the response from /gateway/bot.

func (*Manager) Initialize

func (mg *Manager) Initialize() error

Initialize handles the start up process including connecting the message queue client.

func (*Manager) NewShardGroup

func (mg *Manager) NewShardGroup(shardGroupID int32, shardIDs []int32, shardCount int32) (sg *ShardGroup)

NewShardGroup creates a new shardgroup.

func (*Manager) Open

func (mg *Manager) Open() error

Open handles retrieving shard counts and scaling.

func (*Manager) PublishEvent

func (mg *Manager) PublishEvent(ctx context.Context, eventType string, eventData jsoniter.RawMessage) error

PublishEvent sends an event to consumers.

func (*Manager) Scale

func (mg *Manager) Scale(shardIDs []int32, shardCount int32) (sg *ShardGroup)

Scale handles the creation of new ShardGroups with a specified shard count and IDs.

func (*Manager) WaitForIdentify

func (mg *Manager) WaitForIdentify(shardID int32, shardCount int32) error

WaitForIdentify blocks until a shard can identify.

type ManagerConfiguration

type ManagerConfiguration struct {
	// Unique name that will be referenced internally
	Identifier string `json:"identifier" yaml:"identifier"`
	// Non-unique name that is sent to consumers.
	ProducerIdentifier string `json:"producer_identifier" yaml:"producer_identifier"`

	FriendlyName string `json:"friendly_name" yaml:"friendly_name"`

	Token     string `json:"token" yaml:"token"`
	AutoStart bool   `json:"auto_start" yaml:"auto_start"`

	// Bot specific configuration
	Bot struct {
		DefaultPresence      discord.UpdateStatus `json:"default_presence" yaml:"default_presence"`
		Intents              int32                `json:"intents" yaml:"intents"`
		ChunkGuildsOnStartup bool                 `json:"chunk_guilds_on_startup" yaml:"chunk_guilds_on_startup"`
	} `json:"bot" yaml:"bot"`

	Caching struct {
		CacheUsers   bool `json:"cache_users" yaml:"cache_users"`
		CacheMembers bool `json:"cache_members" yaml:"cache_members"`
		StoreMutuals bool `json:"store_mutuals" yaml:"store_mutuals"`
	} `json:"caching" yaml:"caching"`

	Events struct {
		EventBlacklist   []string `json:"event_blacklist" yaml:"event_blacklist"`
		ProduceBlacklist []string `json:"produce_blacklist" yaml:"produce_blacklist"`
	} `json:"events" yaml:"events"`

	Messaging struct {
		ClientName      string `json:"client_name" yaml:"client_name"`
		ChannelName     string `json:"channel_name" yaml:"channel_name"`
		UseRandomSuffix bool   `json:"use_random_suffix" yaml:"use_random_suffix"`
	} `json:"messaging" yaml:"messaging"`

	Sharding struct {
		AutoSharded bool   `json:"auto_sharded" yaml:"auto_sharded"`
		ShardCount  int32  `json:"shard_count" yaml:"shard_count"`
		ShardIDs    string `json:"shard_ids" yaml:"shard_ids"`
	} `json:"sharding" yaml:"sharding"`
}

ManagerConfiguration represents the configuration for the manager.

type Sandwich

type Sandwich struct {
	sync.Mutex

	ConfigurationLocation string `json:"configuration_location"`

	Logger    zerolog.Logger `json:"-"`
	StartTime time.Time      `json:"start_time" yaml:"start_time"`

	Configuration *SandwichConfiguration `json:"configuration" yaml:"configuration"`

	Options SandwichOptions `json:"options" yaml:"options"`

	ProducerClient *MQClient `json:"-"`

	IdentifyBuckets *bucketstore.BucketStore `json:"-"`

	EventsInflight *atomic.Int32 `json:"-"`

	Managers map[string]*Manager `json:"managers" yaml:"managers"`

	Dedupe map[string]int64

	State  *SandwichState `json:"-"`
	Client *Client        `json:"-"`

	SessionProvider *session.Session

	RouterHandler fasthttp.RequestHandler `json:"-"`
	DistHandler   fasthttp.RequestHandler `json:"-"`
	// contains filtered or unexported fields
}

func NewSandwich

func NewSandwich(logger io.Writer, options SandwichOptions) (sg *Sandwich, err error)

NewSandwich creates the application state and initializes it.

func (*Sandwich) AddDedupe

func (sg *Sandwich) AddDedupe(key string)

AddMemberDedupe creates a new dedupe.

func (*Sandwich) CallbackEndpoint

func (sg *Sandwich) CallbackEndpoint(ctx *fasthttp.RequestCtx)

/callback: Handles oauth callback.

func (*Sandwich) CheckDedupe

func (sg *Sandwich) CheckDedupe(key string) bool

CheckMemberDedupe returns if a dedupe is set. If true, event should be ignored.

func (*Sandwich) Close

func (sg *Sandwich) Close() error

Close closes all managers gracefully.

func (*Sandwich) HandleRequest

func (sg *Sandwich) HandleRequest(ctx *fasthttp.RequestCtx)

func (*Sandwich) LoadConfiguration

func (sg *Sandwich) LoadConfiguration(path string) (configuration *SandwichConfiguration, err error)

LoadConfiguration handles loading the configuration file.

func (*Sandwich) LoginEndpoint

func (sg *Sandwich) LoginEndpoint(ctx *fasthttp.RequestCtx)

/login: Handles logging in a user.

func (*Sandwich) LogoutEndpoint

func (sg *Sandwich) LogoutEndpoint(ctx *fasthttp.RequestCtx)

/logout: Clears session.

func (*Sandwich) ManagerCreateEndpoint

func (sg *Sandwich) ManagerCreateEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) ManagerDeleteEndpoint

func (sg *Sandwich) ManagerDeleteEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) ManagerInitializeEndpoint

func (sg *Sandwich) ManagerInitializeEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) ManagerUpdateEndpoint

func (sg *Sandwich) ManagerUpdateEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) NewManager

func (sg *Sandwich) NewManager(configuration *ManagerConfiguration) (mg *Manager)

NewManager creates a new manager.

func (*Sandwich) NewRestRouter

func (sg *Sandwich) NewRestRouter() (routerHandler fasthttp.RequestHandler, fsHandler fasthttp.RequestHandler)

func (*Sandwich) Open

func (sg *Sandwich) Open()

Open starts up any listeners, configures services and starts up managers.

func (*Sandwich) PublishGlobalEvent

func (sg *Sandwich) PublishGlobalEvent(eventType string, data jsoniter.RawMessage) error

PublishGlobalEvent publishes an event to all Consumers.

func (*Sandwich) PublishSimpleWebhook

func (sg *Sandwich) PublishSimpleWebhook(title string, description string, footer string, colour int32)

PublishSimpleWebhook is a helper function for creating quicker webhook messages.

func (*Sandwich) PublishWebhook

func (sg *Sandwich) PublishWebhook(message discord.WebhookMessageParams)

PublishWebhook sends a webhook message to all added webhooks in the configuration.

func (*Sandwich) RemoveDedupe

func (sg *Sandwich) RemoveDedupe(key string)

RemoveMemberDedupe removes a dedupe.

func (*Sandwich) SandwichGetEndpoint

func (sg *Sandwich) SandwichGetEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) SandwichUpdateEndpoint

func (sg *Sandwich) SandwichUpdateEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) SaveConfiguration

func (sg *Sandwich) SaveConfiguration(configuration *SandwichConfiguration, path string) error

SaveConfiguration handles saving the configuration file.

func (*Sandwich) SendWebhook

func (sg *Sandwich) SendWebhook(webhookURL string, message discord.WebhookMessageParams) (status int, err error)

func (*Sandwich) ShardGroupCreateEndpoint

func (sg *Sandwich) ShardGroupCreateEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) ShardGroupStopEndpoint

func (sg *Sandwich) ShardGroupStopEndpoint(ctx *fasthttp.RequestCtx)

func (*Sandwich) StatusEndpoint

func (sg *Sandwich) StatusEndpoint(ctx *fasthttp.RequestCtx)

/api/status: Returns managers, shardgroups and shard status.

func (*Sandwich) UserEndpoint

func (sg *Sandwich) UserEndpoint(ctx *fasthttp.RequestCtx)

type SandwichConfiguration

type SandwichConfiguration struct {
	Identify struct {
		// URL allows for variables:
		// {shard_id}, {shard_count}, {token} {token_hash}, {max_concurrency}
		URL string `json:"url" yaml:"url"`

		Headers map[string]string `json:"headers" yaml:"headers"`
	} `json:"identify" yaml:"identify"`

	Producer struct {
		Type          string                 `json:"type" yaml:"type"`
		Configuration map[string]interface{} `json:"configuration" yaml:"configuration"`
	} `json:"producer" yaml:"producer"`

	HTTP struct {
		// OAuth config used to identification.
		OAuth *oauth2.Config `json:"oauth" yaml:"oauth"`

		// List of discord user IDs that can access the dashboard.
		UserAccess []string `json:"user_access" yaml:"user_access"`
	} `json:"http" yaml:"http"`

	Webhooks []string `json:"webhooks" yaml:"webhooks"`

	Managers []*ManagerConfiguration `json:"managers" yaml:"managers"`
}

SandwichConfiguration represents the configuration file.

type SandwichOptions

type SandwichOptions struct {
	ConfigurationLocation string  `json:"configuration_location" yaml:"configuration_location"`
	PrometheusAddress     string  `json:"prometheus_address" yaml:"prometheus_address"`
	GatewayURL            url.URL `json:"gateway_url" yaml:"gateway_url"`

	// BaseURL to send HTTP requests to. If empty, will use https://discord.com
	BaseURL url.URL `json:"base_url" yaml:"base_url"`

	GRPCNetwork            string `json:"grpc_network" yaml:"grpc_network"`
	GRPCHost               string `json:"grpc_host" yaml:"grpc_host"`
	GRPCCertFile           string `json:"grpc_cert_file" yaml:"grpc_cert_file"`
	GRPCServerNameOverride string `json:"grpc_server_name_override" yaml:"grpc_server_name_override"`

	HTTPHost    string `json:"http_host" yaml:"http_host"`
	HTTPEnabled bool   `json:"http_enabled" yaml:"http_enabled"`
}

SandwichOptions represents any options passable when creating the sandwich service.

type SandwichState

SandwichState stores the collective state of all ShardGroups across all Managers.

func NewSandwichState

func NewSandwichState() *SandwichState

func (*SandwichState) AddDMChannel

func (ss *SandwichState) AddDMChannel(userID discord.Snowflake, channel *discord.Channel)

AddDMChannel adds a DM channel to a user.

func (*SandwichState) AddUserMutualGuild

func (ss *SandwichState) AddUserMutualGuild(ctx *StateCtx, userID discord.Snowflake, guildID discord.Snowflake)

AddUserMutualGuild adds a mutual guild to a user.

func (*SandwichState) ChannelFromState

func (ss *SandwichState) ChannelFromState(guildChannelState *sandwich_structs.StateChannel) (guildChannel *discord.Channel)

ChannelFromState converts the structs.StateChannel into a discord.Channel, for use within the application. This will not populate the recipient user object from cache.

func (*SandwichState) ChannelToState

func (ss *SandwichState) ChannelToState(guildChannel *discord.Channel) (guildChannelState *sandwich_structs.StateChannel)

ChannelFromState converts from discord.Channel to structs.StateChannel, for storing in cache. This does not add the recipients to the cache.

func (*SandwichState) CountMembersForVoiceChannel

func (ss *SandwichState) CountMembersForVoiceChannel(guildID discord.Snowflake, channelID discord.Snowflake) int32

func (*SandwichState) EmojiFromState

func (ss *SandwichState) EmojiFromState(guildState *sandwich_structs.StateEmoji) (guild *discord.Emoji)

EmojiFromState converts the structs.StateEmoji into a discord.Emoji, for use within the application.

func (*SandwichState) EmojiToState

func (ss *SandwichState) EmojiToState(emoji *discord.Emoji) (guildState *sandwich_structs.StateEmoji)

EmojiFromState converts from discord.Emoji to structs.StateEmoji, for storing in cache. This does not add the user to the cache. This will not populate the user object from cache, it will be an empty object with only an ID.

func (*SandwichState) GetAllGuildChannels

func (ss *SandwichState) GetAllGuildChannels(guildID discord.Snowflake) (guildChannelsList []*discord.Channel, ok bool)

GetAllGuildChannels returns all guildChannels of a specific guild from the cache.

func (*SandwichState) GetAllGuildEmojis

func (ss *SandwichState) GetAllGuildEmojis(guildID discord.Snowflake) (guildEmojisList []*discord.Emoji, ok bool)

GetAllGuildEmojis returns all guildEmojis on a specific guild from the cache.

func (*SandwichState) GetAllGuildMembers

func (ss *SandwichState) GetAllGuildMembers(guildID discord.Snowflake) (guildMembersList []*discord.GuildMember, ok bool)

GetAllGuildMembers returns all guildMembers of a specific guild from the cache.

func (*SandwichState) GetAllGuildRoles

func (ss *SandwichState) GetAllGuildRoles(guildID discord.Snowflake) (guildRolesList []*discord.Role, ok bool)

GetAllGuildRoles returns all guildRoles of a specific guild from the cache.

func (*SandwichState) GetDMChannel

func (ss *SandwichState) GetDMChannel(userID discord.Snowflake) (channel *discord.Channel, ok bool)

GetDMChannel returns the DM channel of a user.

func (*SandwichState) GetGuild

func (ss *SandwichState) GetGuild(guildID discord.Snowflake) (guild *discord.Guild, ok bool)

GetGuild returns the guild with the same ID from the cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetGuildChannel

func (ss *SandwichState) GetGuildChannel(guildIDPtr *discord.Snowflake, channelID discord.Snowflake) (guildChannel *discord.Channel, ok bool)

GetGuildChannel returns the channel with the same ID from the cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetGuildEmoji

func (ss *SandwichState) GetGuildEmoji(guildID discord.Snowflake, emojiID discord.Snowflake) (guildEmoji *discord.Emoji, ok bool)

GetGuildEmoji returns the emoji with the same ID from the cache. Populated user field from cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetGuildMember

func (ss *SandwichState) GetGuildMember(guildID discord.Snowflake, guildMemberID discord.Snowflake) (guildMember *discord.GuildMember, ok bool)

GetGuildMember returns the guildMember with the same ID from the cache. Populated user field from cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetGuildRole

func (ss *SandwichState) GetGuildRole(guildID discord.Snowflake, roleID discord.Snowflake) (role *discord.Role, ok bool)

GetGuildRole returns the role with the same ID from the cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetUser

func (ss *SandwichState) GetUser(userID discord.Snowflake) (user *discord.User, ok bool)

GetUser returns the user with the same ID from the cache. Returns a boolean to signify a match or not.

func (*SandwichState) GetUserMutualGuilds

func (ss *SandwichState) GetUserMutualGuilds(userID discord.Snowflake) (guildIDs []discord.Snowflake, ok bool)

GetUserMutualGuilds returns a list of snowflakes of mutual guilds a member is seen on.

func (*SandwichState) GetVoiceState

func (ss *SandwichState) GetVoiceState(guildID discord.Snowflake, userID discord.Snowflake) (voiceState *discord.VoiceState, ok bool)

func (*SandwichState) GuildFromState

func (ss *SandwichState) GuildFromState(guildState *sandwich_structs.StateGuild) (guild *discord.Guild)

GuildFromState converts the structs.StateGuild into a discord.Guild, for use within the application. Channels, Roles, Members and Emoji lists will not be populated.

func (*SandwichState) GuildMemberFromState

func (ss *SandwichState) GuildMemberFromState(guildMemberState *sandwich_structs.StateGuildMember) (guildMember *discord.GuildMember)

GuildMemberFromState converts the structs.StateGuildMembers into a discord.GuildMember, for use within the application. This will not populate the user object from cache, it will be an empty object with only an ID.

func (*SandwichState) GuildMemberToState

func (ss *SandwichState) GuildMemberToState(guildMember *discord.GuildMember) (guildMemberState *sandwich_structs.StateGuildMember)

GuildMemberFromState converts from discord.GuildMember to structs.StateGuildMembers, for storing in cache. This does not add the user to the cache.

func (*SandwichState) GuildToState

func (ss *SandwichState) GuildToState(guild *discord.Guild) (guildState *sandwich_structs.StateGuild)

GuildFromState converts from discord.Guild to structs.StateGuild, for storing in cache. Does not add Channels, Roles, Members and Emojis to state.

func (*SandwichState) RemoveAllGuildChannels

func (ss *SandwichState) RemoveAllGuildChannels(guildID discord.Snowflake)

RemoveAllGuildChannels removes all guildChannels of a specific guild from the cache.

func (*SandwichState) RemoveAllGuildEmojis

func (ss *SandwichState) RemoveAllGuildEmojis(guildID discord.Snowflake)

RemoveGuildEmojis removes all guildEmojis of a specific guild from the cache.

func (*SandwichState) RemoveAllGuildMembers

func (ss *SandwichState) RemoveAllGuildMembers(guildID discord.Snowflake)

RemoveAllGuildMembers removes all guildMembers of a specific guild from the cache.

func (*SandwichState) RemoveAllGuildRoles

func (ss *SandwichState) RemoveAllGuildRoles(guildID discord.Snowflake)

RemoveGuildRoles removes all guild roles of a specifi guild from the cache.

func (*SandwichState) RemoveDMChannel

func (ss *SandwichState) RemoveDMChannel(userID discord.Snowflake)

RemoveDMChannel removes a DM channel from a user.

func (*SandwichState) RemoveGuild

func (ss *SandwichState) RemoveGuild(ctx *StateCtx, guildID discord.Snowflake)

RemoveGuild removes a guild from the cache.

func (*SandwichState) RemoveGuildChannel

func (ss *SandwichState) RemoveGuildChannel(guildIDPtr *discord.Snowflake, channelID discord.Snowflake)

RemoveGuildChannel removes a channel from the cache.

func (*SandwichState) RemoveGuildEmoji

func (ss *SandwichState) RemoveGuildEmoji(guildID discord.Snowflake, emojiID discord.Snowflake)

RemoveGuildEmoji removes a emoji from the cache.

func (*SandwichState) RemoveGuildMember

func (ss *SandwichState) RemoveGuildMember(guildID discord.Snowflake, guildMemberID discord.Snowflake)

RemoveGuildMember removes a guildMember from the cache.

func (*SandwichState) RemoveGuildRole

func (ss *SandwichState) RemoveGuildRole(guildID discord.Snowflake, roleID discord.Snowflake)

RemoveGuildRole removes a role from the cache.

func (*SandwichState) RemoveUser

func (ss *SandwichState) RemoveUser(userID discord.Snowflake)

RemoveUser removes a user from the cache.

func (*SandwichState) RemoveUserMutualGuild

func (ss *SandwichState) RemoveUserMutualGuild(userID discord.Snowflake, guildID discord.Snowflake)

RemoveUserMutualGuild removes a mutual guild from a user.

func (*SandwichState) RoleFromState

func (ss *SandwichState) RoleFromState(guildState *sandwich_structs.StateRole) (guild *discord.Role)

RoleFromState converts the structs.StateRole into a discord.Role, for use within the application.

func (*SandwichState) RoleToState

func (ss *SandwichState) RoleToState(guild *discord.Role) (guildState *sandwich_structs.StateRole)

RoleFromState converts from discord.Role to structs.StateRole, for storing in cache.

func (*SandwichState) SetGuild

func (ss *SandwichState) SetGuild(ctx *StateCtx, guild *discord.Guild)

SetGuild creates or updates a guild entry in the cache.

func (*SandwichState) SetGuildChannel

func (ss *SandwichState) SetGuildChannel(ctx *StateCtx, guildIDPtr *discord.Snowflake, channel *discord.Channel)

SetGuildChannel creates or updates a channel entry in the cache.

func (*SandwichState) SetGuildEmoji

func (ss *SandwichState) SetGuildEmoji(ctx *StateCtx, guildID discord.Snowflake, emoji *discord.Emoji)

SetGuildEmoji creates or updates a emoji entry in the cache. Adds user in user object to cache.

func (*SandwichState) SetGuildMember

func (ss *SandwichState) SetGuildMember(ctx *StateCtx, guildID discord.Snowflake, guildMember *discord.GuildMember)

SetGuildMember creates or updates a guildMember entry in the cache. Adds user in guildMember object to cache.

func (*SandwichState) SetGuildRole

func (ss *SandwichState) SetGuildRole(ctx *StateCtx, guildID discord.Snowflake, role *discord.Role)

SetGuildRole creates or updates a role entry in the cache.

func (*SandwichState) SetUser

func (ss *SandwichState) SetUser(ctx *StateCtx, user *discord.User)

SetUser creates or updates a user entry in the cache.

func (*SandwichState) UpdateVoiceState

func (ss *SandwichState) UpdateVoiceState(ctx *StateCtx, voiceState discord.VoiceState)

func (*SandwichState) UserFromState

func (ss *SandwichState) UserFromState(userState *sandwich_structs.StateUser) (user *discord.User)

UserFromState converts the structs.StateUser into a discord.User, for use within the application.

func (*SandwichState) UserToState

func (ss *SandwichState) UserToState(user *discord.User) (userState *sandwich_structs.StateUser)

UserFromState converts from discord.User to structs.StateUser, for storing in cache.

func (*SandwichState) VoiceStateFromState

func (ss *SandwichState) VoiceStateFromState(guildID discord.Snowflake, userID discord.Snowflake, voiceStateState *sandwich_structs.StateVoiceState) (voiceState *discord.VoiceState)

func (*SandwichState) VoiceStateToState

func (ss *SandwichState) VoiceStateToState(voiceState *discord.VoiceState) (voiceStateState *sandwich_structs.StateVoiceState)

type Shard

type Shard struct {
	RoutineDeadSignal   deadlock.DeadSignal `json:"-"`
	HeartbeatDeadSignal deadlock.DeadSignal `json:"-"`

	Start            *atomic.Time  `json:"start"`
	Init             *atomic.Time  `json:"init"`
	RetriesRemaining *atomic.Int32 `json:"-"`

	Logger zerolog.Logger `json:"-"`

	ShardID int32 `json:"shard_id"`

	Sandwich   *Sandwich   `json:"-"`
	Manager    *Manager    `json:"-"`
	ShardGroup *ShardGroup `json:"-"`

	HeartbeatActive   *atomic.Bool `json:"-"`
	LastHeartbeatAck  *atomic.Time `json:"-"`
	LastHeartbeatSent *atomic.Time `json:"-"`

	Heartbeater       *time.Ticker  `json:"-"`
	HeartbeatInterval time.Duration `json:"-"`

	// Duration since last heartbeat Ack before reconnecting.
	HeartbeatFailureInterval time.Duration `json:"-"`

	Unavailable map[discord.Snowflake]bool `json:"unavailable"`

	Lazy map[discord.Snowflake]bool `json:"lazy"`

	Guilds map[discord.Snowflake]bool `json:"guilds"`

	Status sandwich_structs.ShardStatus `json:"status"`

	MessageCh chan discord.GatewayPayload `json:"-"`
	ErrorCh   chan error                  `json:"-"`

	Sequence  *atomic.Int32  `json:"-"`
	SessionID *atomic.String `json:"-"`
	// contains filtered or unexported fields
}

Shard represents the shard object.

func (*Shard) ChunkAllGuilds

func (sh *Shard) ChunkAllGuilds()

func (*Shard) ChunkGuild

func (sh *Shard) ChunkGuild(guildID discord.Snowflake, alwaysChunk bool) error

ChunkGuilds chunks guilds to discord. It will wait for the operation to complete, or timeout.

func (*Shard) Close

func (sh *Shard) Close(code websocket.StatusCode)

Close closes the shard connection.

func (*Shard) CloseWS

func (sh *Shard) CloseWS(statusCode websocket.StatusCode) error

CloseWS closes the websocket. This will always return 0 as the error is suppressed.

func (*Shard) Connect

func (sh *Shard) Connect() error

Connect connects to the gateway and handles identifying.

func (*Shard) FeedWebsocket

func (sh *Shard) FeedWebsocket(ctx context.Context, u string,
	opts *websocket.DialOptions,
) (errorCh chan error, messageCh chan discord.GatewayPayload, err error)

FeedWebsocket reads websocket events and feeds them through a channel.

func (*Shard) GetStatus

func (sh *Shard) GetStatus() (status sandwich_structs.ShardStatus)

GetStatus returns the status of a ShardGroup.

func (*Shard) Heartbeat

func (sh *Shard) Heartbeat(ctx context.Context)

Heartbeat maintains a heartbeat with discord.

func (*Shard) Identify

func (sh *Shard) Identify(ctx context.Context) error

Identify sends the identify packet to discord.

func (*Shard) Listen

func (sh *Shard) Listen(ctx context.Context) error

Listen to gateway and process accordingly.

func (*Shard) OnDispatch

OnDispatch handles routing of discord event.

func (*Shard) OnDispatchEvent

func (sh *Shard) OnDispatchEvent(eventType string)

OnDispatchEvent is called during the dispatch event to call analytics.

func (*Shard) OnEvent

func (*Shard) OnGuildDispatchEvent

func (sh *Shard) OnGuildDispatchEvent(eventType string, guildID discord.Snowflake)

OnGuildDispatchEvent is called during the dispatch event to call analytics with a guild Id.

func (*Shard) Open

func (sh *Shard) Open()

Open starts listening to the gateway.

func (*Shard) PublishEvent

func (sh *Shard) PublishEvent(ctx context.Context, packet *sandwich_structs.SandwichPayload) error

PublishEvent publishes a SandwichPayload.

func (*Shard) Reconnect

func (sh *Shard) Reconnect(code websocket.StatusCode) error

Reconnect attempts to reconnect to the gateway.

func (*Shard) Resume

func (sh *Shard) Resume(ctx context.Context) error

Resume sends the resume packet to discord.

func (*Shard) SafeOnGuildDispatchEvent

func (sh *Shard) SafeOnGuildDispatchEvent(eventType string, guildIDPtr *discord.Snowflake)

SafeOnGuildDispatchEvent takes a guildID pointer and does handle guild event count if nil.

func (*Shard) SendEvent

func (sh *Shard) SendEvent(ctx context.Context, op discord.GatewayOp, data interface{}) error

SendEvent sends an event to discord.

func (*Shard) SetStatus

func (sh *Shard) SetStatus(status sandwich_structs.ShardStatus)

SetStatus sets the status of the ShardGroup.

func (*Shard) WaitForReady

func (sh *Shard) WaitForReady()

WaitForReady blocks until the shard is ready.

func (*Shard) WriteJSON

func (sh *Shard) WriteJSON(ctx context.Context, op discord.GatewayOp, i interface{}) error

WriteJSON writes json data to the websocket.

type ShardGroup

type ShardGroup struct {
	Error *atomic.String `json:"error"`

	Manager *Manager       `json:"-"`
	Logger  zerolog.Logger `json:"-"`

	Start *atomic.Time `json:"start"`

	WaitingFor *atomic.Int32 `json:"-"`

	User *discord.User `json:"user"`

	ID int32 `json:"id"`

	ShardCount int32   `json:"shard_count"`
	ShardIDs   []int32 `json:"shard_ids"`

	Shards map[int32]*Shard `json:"shards"`

	Guilds map[discord.Snowflake]bool `json:"guilds"`

	ReadyWait *sync.WaitGroup `json:"-"`

	Status sandwich_structs.ShardGroupStatus `json:"status"`
	// contains filtered or unexported fields
}

ShardGroup represents a group of shards.

func (*ShardGroup) Close

func (sg *ShardGroup) Close()

Close closes all shards in a shardgroup.

func (*ShardGroup) GetStatus

func (sg *ShardGroup) GetStatus() (status sandwich_structs.ShardGroupStatus)

GetStatus returns the status of a ShardGroup.

func (*ShardGroup) NewShard

func (sg *ShardGroup) NewShard(shardID int32) (sh *Shard)

NewShard creates a new shard object.

func (*ShardGroup) Open

func (sg *ShardGroup) Open() (ready chan bool, err error)

Open handles the startup of a shard group. On startup of a shard group, the first shard is connected and ran to confirm token and such are valid. If an issue occurs starting the first shard, open will return an error. Other shards will then connect concurrently and will attempt to reconnect on error. Once the shardgroup has fully finished connecting and are ready, then floodgate will be enabled allowing their events to be handled.

func (*ShardGroup) SetStatus

func (sg *ShardGroup) SetStatus(status sandwich_structs.ShardGroupStatus)

SetStatus sets the status of the ShardGroup.

type StateCtx

type StateCtx struct {
	CacheUsers   bool
	CacheMembers bool
	Stateless    bool
	StoreMutuals bool

	*Shard
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

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