Documentation ¶
Overview ¶
Animus Magic is the internal redis IPC system for internal communications between the bot and the server
Format of payloads: <target [from]: u8><target [to]: u8><cluster id from: u16><cluster id to: u16><op: 8 bits><command id: alphanumeric string>/<cbor payload>
This package defines all possible responses to an action
Index ¶
- Constants
- Variables
- func DeserializeData[T any](data []byte, d *T) error
- func NewCommandId() string
- func ParseClientRequest[T AnimusMessage](c *ClientRequest) (*T, error)
- func SerializeData[T any](data T) ([]byte, error)
- type AnimusErrorResponse
- type AnimusMagicClient
- func (c *AnimusMagicClient) CloseNotifier(commandId string)
- func (c *AnimusMagicClient) CreateNotifier(commandId string, expectedResponseCount uint32) chan *ClientResponse
- func (c *AnimusMagicClient) CreatePayload(from, to AnimusTarget, clusterIdFrom uint16, clusterIdTo uint16, op AnimusOp, ...) ([]byte, error)
- func (c *AnimusMagicClient) GatherResponses(ctx context.Context, opts *RequestOptions, notify chan *ClientResponse) (r []*ClientResponse, err error)
- func (c *AnimusMagicClient) GetPayloadMeta(payload []byte) (*AnimusMessageMetadata, error)
- func (c *AnimusMagicClient) Listen(ctx context.Context, redis rueidis.Client, l *zap.Logger) error
- func (c *AnimusMagicClient) ListenOnce(ctx context.Context, r rueidis.Client, l *zap.Logger) error
- func (c *AnimusMagicClient) Publish(ctx context.Context, redis rueidis.Client, payload []byte) error
- func (c *AnimusMagicClient) RawRequest(ctx context.Context, redis rueidis.Client, msg []byte, data *RequestOptions) ([]*ClientResponse, error)
- func (c *AnimusMagicClient) Request(ctx context.Context, redis rueidis.Client, msg AnimusMessage, ...) ([]*ClientResponse, error)
- type AnimusMessage
- type AnimusMessageMetadata
- type AnimusOp
- type AnimusResponse
- type AnimusTarget
- type BotAnimusMessage
- type BotAnimusResponse
- type ClientRequest
- type ClientResponse
- type ClusterModules
- type JobserverMessage
- type JobserverResponse
- type NotifyWrapper
- type ParsedClientResponse
- type RequestOptions
Constants ¶
const (
WildcardClusterID = 0xFFFF // top means wildcard/all clusters
)
Variables ¶
var ErrInvalidPayload = errors.New("request validation error: invalid payload")
var ErrInvalidTarget = errors.New("request validation error: message target and payload.To mismatch")
var ErrNilClusterID = errors.New("request validation error: nil cluster id")
var ErrNilExpectedResponseCount = errors.New("request validation error: nil expected response count")
var ErrNilMessage = errors.New("request validation error: nil message")
var ErrNilRequestData = errors.New("request validation error: nil request data")
var ErrOpError = errors.New("request validation error: op is OpError")
Functions ¶
func DeserializeData ¶
Helper function to deserialize data from the correct/current format
func ParseClientRequest ¶
func ParseClientRequest[T AnimusMessage](c *ClientRequest) (*T, error)
func SerializeData ¶
Helper function to serialize data to the correct/current format
Types ¶
type AnimusErrorResponse ¶
type AnimusMagicClient ¶
type AnimusMagicClient struct { // Target / who the client is for From AnimusTarget // The cluster id ClusterID uint16 // On request function, if set, will be called upon recieving op of type OpRequest OnRequest func(*ClientRequest) (AnimusResponse, error) // On response function, if set, will be called upon recieving op of type OpResponse OnResponse func(*ClientResponse) error // Middleware function, will be called regardless of the op // // If bool is false, the message will be ignored/dropped for further processing OnMiddleware func(*AnimusMessageMetadata, []byte) (bool, error) // Allow all requests AllowAll bool // Set of notifiers Notify syncmap.Map[string, *NotifyWrapper] // The redis channel to use Channel string }
func New ¶
func New(channel string, from AnimusTarget, clusterId uint16) *AnimusMagicClient
New returns a new AnimusMagicClient
func (*AnimusMagicClient) CloseNotifier ¶
func (c *AnimusMagicClient) CloseNotifier(commandId string)
CloseNotifier closes the notifier for the given command id
func (*AnimusMagicClient) CreateNotifier ¶
func (c *AnimusMagicClient) CreateNotifier(commandId string, expectedResponseCount uint32) chan *ClientResponse
CreateNotifier adds a notifier to the map and returns the channel
This channel will receive the response for the given command id
func (*AnimusMagicClient) CreatePayload ¶
func (c *AnimusMagicClient) CreatePayload( from, to AnimusTarget, clusterIdFrom uint16, clusterIdTo uint16, op AnimusOp, commandId string, data any, ) ([]byte, error)
CreatePayload creates a payload for the given command id and message
func (*AnimusMagicClient) GatherResponses ¶
func (c *AnimusMagicClient) GatherResponses( ctx context.Context, opts *RequestOptions, notify chan *ClientResponse, ) (r []*ClientResponse, err error)
GatherResponses gathers responses from the given notifier
This waits for the expected number of responses or until the context is done
func (*AnimusMagicClient) GetPayloadMeta ¶
func (c *AnimusMagicClient) GetPayloadMeta(payload []byte) (*AnimusMessageMetadata, error)
GetPayloadMeta parses the payload metadata from a message
func (*AnimusMagicClient) Listen ¶
Listen starts listening for messages from redis and restarts the listener if it dies
func (*AnimusMagicClient) ListenOnce ¶
ListenOnce starts listening for messages from redis
This is *blocking* and should be run in a goroutine
func (*AnimusMagicClient) RawRequest ¶
func (c *AnimusMagicClient) RawRequest( ctx context.Context, redis rueidis.Client, msg []byte, data *RequestOptions, ) ([]*ClientResponse, error)
RawRequest sends a raw request to the given cluster id and waits for a response
func (*AnimusMagicClient) Request ¶
func (c *AnimusMagicClient) Request( ctx context.Context, redis rueidis.Client, msg AnimusMessage, data *RequestOptions, ) ([]*ClientResponse, error)
Request sends a request to the given cluster id and waits for a response
type AnimusMessage ¶
type AnimusMessage interface { Message() // Marker method Target() AnimusTarget // Who the message is for }
type AnimusMessageMetadata ¶
type AnimusMessageMetadata struct { From AnimusTarget To AnimusTarget ClusterIDFrom uint16 ClusterIDTo uint16 Op AnimusOp CommandID string PayloadOffset uint }
type AnimusResponse ¶
type AnimusResponse interface { Response() // Marker method Target() AnimusTarget // Who can create a response should be from }
type AnimusTarget ¶
type AnimusTarget byte
const ( AnimusTargetBot AnimusTarget = 0x0 AnimusTargetJobserver AnimusTarget = 0x1 AnimusTargetWebserver AnimusTarget = 0x2 AnimusTargetInfra AnimusTarget = 0x3 AnimusTargetWildcard AnimusTarget = 0xFF )
func ByteToAnimusTarget ¶
func ByteToAnimusTarget(b uint8) (AnimusTarget, bool)
func StringToAnimusTarget ¶
func StringToAnimusTarget(s string) (AnimusTarget, bool)
func (AnimusTarget) String ¶
func (a AnimusTarget) String() string
type BotAnimusMessage ¶
type BotAnimusMessage struct { Modules *struct{} `json:"Modules,omitempty"` GuildsExist *struct { Guilds []string `json:"guilds"` } `json:"GuildsExist,omitempty"` BaseGuildUserInfo *struct { GuildID string `json:"guild_id"` UserID string `json:"user_id"` } `json:"BaseGuildUserInfo,omitempty"` CheckCommandPermission *struct { GuildID string `json:"guild_id"` UserID string `json:"user_id"` Command string `json:"command"` CheckCommandOptions silverpelt.CheckCommandOptions `json:"opts"` } `json:"CheckCommandPermission,omitempty"` TogglePerModuleCache *struct { Module string `json:"module"` Toggle string `json:"toggle"` Options map[string]any `json:"options,omitempty"` } `json:"TogglePerModuleCache,omitempty"` GetSerenityPermissionList *struct{} `json:"GetSerenityPermissionList,omitempty"` }
func (BotAnimusMessage) Message ¶
func (b BotAnimusMessage) Message()
func (BotAnimusMessage) Target ¶
func (b BotAnimusMessage) Target() AnimusTarget
type BotAnimusResponse ¶
type BotAnimusResponse struct { OK *struct { Message string `json:"message"` } `json:"OK,omitempty"` Modules *struct { Modules ClusterModules `json:"modules"` } `json:"Modules,omitempty"` GuildsExist *struct { GuildsExist []uint8 `json:"guilds_exist"` } BaseGuildUserInfo *types.UserGuildBaseData /// Returns the response of a command permission check CheckCommandPermission *struct { PermRes silverpelt.PermissionResult `json:"perm_res"` IsOk bool `json:"is_ok"` } GetSerenityPermissionList *struct { Permissions map[string]uint64 `json:"perms"` } `json:"GetSerenityPermissionList,omitempty"` }
func (BotAnimusResponse) Response ¶
func (b BotAnimusResponse) Response()
func (BotAnimusResponse) Target ¶
func (b BotAnimusResponse) Target() AnimusTarget
type ClientRequest ¶
type ClientRequest struct { Meta *AnimusMessageMetadata // The raw payload RawPayload []byte }
A ClientResponse contains the request from animus magic
type ClientResponse ¶
type ClientResponse struct { Meta *AnimusMessageMetadata // The raw payload RawPayload []byte }
A ClientResponse contains the response from animus magic
type ClusterModules ¶
type ClusterModules = []silverpelt.CanonicalModule
type JobserverMessage ¶
type JobserverMessage struct { // spawns a task and executes it if the execute argument is set. // If you already have both a task and a task create response, consider execute_task SpawnTask *struct { Name string `json:"name"` Data map[string]interface{} `json:"data"` Create bool `json:"create"` Execute bool `json:"execute"` // If create is false, then task id must be set TaskID string `json:"task_id"` // The User ID who initiated the action UserID string `json:"user_id"` } `json:"SpawnTask,omitempty"` }
func (JobserverMessage) Message ¶
func (b JobserverMessage) Message()
func (JobserverMessage) Target ¶
func (b JobserverMessage) Target() AnimusTarget
type JobserverResponse ¶
type JobserverResponse struct { SpawnTask *struct { TaskID string `json:"task_id"` } `json:"SpawnTask,omitempty"` }
func (JobserverResponse) Response ¶
func (b JobserverResponse) Response()
func (JobserverResponse) Target ¶
func (b JobserverResponse) Target() AnimusTarget
type NotifyWrapper ¶
type NotifyWrapper struct { Chan chan *ClientResponse ExpectedCount uint32 ResponseCount atomic.Uint32 }
type ParsedClientResponse ¶
type ParsedClientResponse[T AnimusResponse] struct { Err *AnimusErrorResponse Resp *T ClientResp *ClientResponse }
func ParseClientResponse ¶
func ParseClientResponse[T AnimusResponse]( cr *ClientResponse, ) (*ParsedClientResponse[T], error)
func ParseClientResponses ¶
func ParseClientResponses[T AnimusResponse]( cr []*ClientResponse, ) ([]*ParsedClientResponse[T], error)
type RequestOptions ¶
type RequestOptions struct { ClusterID *uint16 // the cluster id to send to, must be set, also ExpectedResponseCount must be set if wildcard ExpectedResponseCount uint32 // must be set if wildcard. this is the number of responses expected CommandID string // if unset, will be randomly generated To AnimusTarget // if unset, is set to AnimusTargetBot Op AnimusOp // if unset is OpRequest IgnoreOpError bool // if true, will ignore OpError responses }
RequestOptions stores the data for a request