mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-01 04:24:19 +00:00
17b9c73ce3
This commit refactors the whole package gateway as well as utils/ws (formerly utils/wsutil) and voice/voicegateway. The new refactor utilizes a design pattern involving a concurrent loop and an arriving event channel. An additional change was made to the way gateway events are typed. Before, pretty much any type will satisfy a gateway event type, since the actual type was just interface{}. The new refactor defines a concrete interface that events can implement: type Event interface { Op() OpCode EventType() EventType } Using this interface, the user can easily add custom gateway events independently of the library without relying on string maps. This adds a lot of type safety into the library and makes type-switching on Event types much more reasonable. Gateway error callbacks are also almost entirely removed in favor of custom gateway events. A catch-all can easily be added like this: s.AddHandler(func(err error) { log.Println("gateway error:, err") })
134 lines
4.5 KiB
Go
134 lines
4.5 KiB
Go
package voicegateway
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"github.com/diamondburned/arikawa/v3/discord"
|
|
"github.com/diamondburned/arikawa/v3/utils/ws"
|
|
)
|
|
|
|
//go:generate go run ../../utils/cmd/genevent -p voicegateway -o event_methods.go
|
|
|
|
// OpUnmarshalers contains the Op unmarshalers for the voice gateway events.
|
|
var OpUnmarshalers = ws.NewOpUnmarshalers()
|
|
|
|
// IdentifyCommand is a command for Op 0.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload
|
|
type IdentifyCommand struct {
|
|
GuildID discord.GuildID `json:"server_id"` // yes, this should be "server_id"
|
|
UserID discord.UserID `json:"user_id"`
|
|
SessionID string `json:"session_id"`
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// SelectProtocolCommand is a command for Op 1.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload
|
|
type SelectProtocolCommand struct {
|
|
Protocol string `json:"protocol"`
|
|
Data SelectProtocolData `json:"data"`
|
|
}
|
|
|
|
// SelectProtocolData is the data inside a SelectProtocolCommand.
|
|
type SelectProtocolData struct {
|
|
Address string `json:"address"`
|
|
Port uint16 `json:"port"`
|
|
Mode string `json:"mode"`
|
|
}
|
|
|
|
// ReadyEvent is an event for Op 2.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload
|
|
type ReadyEvent struct {
|
|
SSRC uint32 `json:"ssrc"`
|
|
IP string `json:"ip"`
|
|
Port int `json:"port"`
|
|
Modes []string `json:"modes"`
|
|
Experiments []string `json:"experiments"`
|
|
|
|
// From Discord's API Docs:
|
|
//
|
|
// `heartbeat_interval` here is an erroneous field and should be ignored.
|
|
// The correct `heartbeat_interval` value comes from the Hello payload.
|
|
|
|
// HeartbeatInterval discord.Milliseconds `json:"heartbeat_interval"`
|
|
}
|
|
|
|
// Addr formats the URL inside Ready to be of format "host:port".
|
|
func (r ReadyEvent) Addr() string {
|
|
return r.IP + ":" + strconv.Itoa(r.Port)
|
|
}
|
|
|
|
// HeartbeatCommand is a command for Op 3.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#heartbeating-example-heartbeat-payload
|
|
type HeartbeatCommand uint64
|
|
|
|
// SessionDescriptionEvent is an event for Op 4.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-session-description-payload
|
|
type SessionDescriptionEvent struct {
|
|
Mode string `json:"mode"`
|
|
SecretKey [32]byte `json:"secret_key"`
|
|
}
|
|
|
|
// https://discord.com/developers/docs/topics/voice-connections#speaking
|
|
type SpeakingFlag uint64
|
|
|
|
const (
|
|
NotSpeaking SpeakingFlag = 0
|
|
Microphone SpeakingFlag = 1 << iota
|
|
Soundshare
|
|
Priority
|
|
)
|
|
|
|
// SpeakingEvent is an event for Op 5. It is also a command.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#speaking-example-speaking-payload
|
|
type SpeakingEvent struct {
|
|
Speaking SpeakingFlag `json:"speaking"`
|
|
Delay int `json:"delay"`
|
|
SSRC uint32 `json:"ssrc"`
|
|
UserID discord.UserID `json:"user_id,omitempty"`
|
|
}
|
|
|
|
// HeartbeatAckEvent is an event for Op 6.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#heartbeating-example-heartbeat-ack-payload
|
|
type HeartbeatAckEvent uint64
|
|
|
|
// ResumeCommand is a command for Op 7.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload
|
|
type ResumeCommand struct {
|
|
GuildID discord.GuildID `json:"server_id"` // yes, this should be "server_id"
|
|
SessionID string `json:"session_id"`
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// HelloEvent is an event for Op 8.
|
|
//
|
|
// https://discord.com/developers/docs/topics/voice-connections#heartbeating-example-hello-payload-since-v3
|
|
type HelloEvent struct {
|
|
HeartbeatInterval discord.Milliseconds `json:"heartbeat_interval"`
|
|
}
|
|
|
|
// ResumedEvent is an event for Op 9.
|
|
// https://discord.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resumed-payload
|
|
type ResumedEvent struct{}
|
|
|
|
// ClientConnectEvent is an event for Op 12. It is undocumented.
|
|
type ClientConnectEvent struct {
|
|
UserID discord.UserID `json:"user_id"`
|
|
AudioSSRC uint32 `json:"audio_ssrc"`
|
|
VideoSSRC uint32 `json:"video_ssrc"`
|
|
}
|
|
|
|
// ClientDisconnectEvent is an event for Op 13. It is undocumented, but its
|
|
// existence is mentioned in this issue:
|
|
// https://github.com/discord/discord-api-docs/issues/510.
|
|
type ClientDisconnectEvent struct {
|
|
UserID discord.UserID `json:"user_id"`
|
|
}
|