voice

package
v0.19.2 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2026 License: Apache-2.0 Imports: 24 Imported by: 19

README

voice

Voice provides a package to connect and send/receive voice to/from discord servers. For Discords Docs on voice see here. Since DAVE(E2EE) will soon be required you also need https://github.com/disgoorg/godave Please note libdave requires CGO to be enabled. Alternative implementations without CGO support may be available in the future.

Logging

Libdave uses a global logger which is set it slog.LevelError by default. You can change this by calling:

libdave.SetDefaultLogLoggerLevel(slog.LevelInfo)

or set your own logger:

libdave.SetDefaultLogLogger(yourLogger)

Usage

To send audio you need to create a voice connection. When using the bot.Client package you can use client.VoiceManager().CreateConn(guildID)

const (
    guildID = 12345
    channelID = 12345
)

client, err := disgo.New(token,
	bot.WithGatewayConfigOpts(gateway.WithIntents(gateway.IntentGuildVoiceStates)),
	bot.WithVoiceManagerConfigOpts(
		voice.WithDaveSessionCreateFunc(golibdave.NewSession), 
	),
)
// handle err

conn := client.VoiceManager().CreateConn(guildID)

err := conn.Open(context.TODO(), channelID, false, false)
// handle err

// set speaking flag
err := conn.SetSpeaking(ctx, voice.SpeakingFlagMicrophone)

// send opus frame
conn.UDP().Write(frame)

// close connection
conn.Close()

When using the voice package standalone you should create a voice manager. After this you can call voice.Manager.CreateConn(guildID). After this you should send a gateway.OpcodeVoiceStateUpdate packet to the gateway.

Documentation

Index

Constants

View Source
const (
	// OpusFrameSizeMs is the size of an opus frame in milliseconds.
	OpusFrameSizeMs = 20

	// OpusFrameSize is the size of an opus frame in bytes.
	OpusFrameSize = 960

	// OpusFrameSizeBytes is the size of an opus frame in bytes.
	OpusFrameSizeBytes = OpusFrameSize * 2 * 2
)
View Source
const (
	// RTPHeaderSize is the size of the opus packet header.
	RTPHeaderSize = 12

	// RTPVersionPadExtend is the first byte of the RTP header.
	// Bit index 0 and 1 represent the RTP Protocol version used. Discord uses the latest RTP protocol version, 2.
	// Bit index 2 represents whether we pad. Opus uses an internal padding system, so RTP padding is not used.
	// Bit index 3 represents if we use extensions.
	// Bit index 4 to 7 represent the CC or CSRC count. CSRC is Combined SSRC.
	RTPVersionPadExtend = 0x80

	// RTPPayloadType is Discord's RTP Profile Payload type.
	// I've yet to find actual documentation on what the bits inside this value represent.
	RTPPayloadType = 0x78

	// MaxOpusFrameSize is the max size of an opus frame in bytes.
	MaxOpusFrameSize = 1400

	// UDPTimeout is the timeout for UDP connections.
	UDPTimeout = 30 * time.Second
)
View Source
const GatewayVersion = 8

GatewayVersion is the version of the voice gateway we are using.

Variables

View Source
var (
	// ErrGatewayNotConnected is returned when the gateway is not connected and a message is attempted to be sent.
	ErrGatewayNotConnected = fmt.Errorf("voice gateway not connected")

	// ErrGatewayAlreadyConnected is returned when the gateway is already connected and a connection is attempted to be opened.
	ErrGatewayAlreadyConnected = fmt.Errorf("voice gateway already connected")
)
View Source
var (
	GatewayCloseEventCodeHeartbeatTimeout = GatewayCloseEventCode{
		Code:        1000,
		Description: "Heartbeat timeout",
		Explanation: "We did not heartbeat in time.",
		Reconnect:   true,
	}

	GatewayCloseEventCodeUnknownError = GatewayCloseEventCode{
		Code:        4000,
		Description: "Unknown error",
		Explanation: "We're not sure what went wrong. Try reconnecting?",
		Reconnect:   true,
	}

	GatewayCloseEventCodeUnknownOpcode = GatewayCloseEventCode{
		Code:        4001,
		Description: "Unknown opcode",
		Explanation: "You sent an invalid opcode.",
		Reconnect:   true,
	}

	GatewayCloseEventCodeFailedDecode = GatewayCloseEventCode{
		Code:        4002,
		Description: "Failed to decode payload",
		Explanation: "You sent a invalid payload in your identifying to the Gateway.",
		Reconnect:   true,
	}

	GatewayCloseEventCodeNotAuthenticated = GatewayCloseEventCode{
		Code:        4003,
		Description: "Not authenticated",
		Explanation: "You sent a payload before identifying with the Gateway.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeAuthenticationFailed = GatewayCloseEventCode{
		Code:        4004,
		Description: "Authentication failed",
		Explanation: "The token you sent in your identify payload is incorrect.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeAlreadyAuthenticated = GatewayCloseEventCode{
		Code:        4005,
		Description: "Already authenticated",
		Explanation: "You sent more than one identify payload. Stahp.",
		Reconnect:   true,
	}

	GatewayCloseEventCodeSessionNoLongerValid = GatewayCloseEventCode{
		Code:        4006,
		Description: "Session no longer valid",
		Explanation: "Your session is no longer valid.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeSessionTimeout = GatewayCloseEventCode{
		Code:        4009,
		Description: "Session timeout",
		Explanation: "Your session has timed out.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeServerNotFound = GatewayCloseEventCode{
		Code:        4011,
		Description: "Server not found",
		Explanation: "We can't find the server you're trying to connect to.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeUnknownProtocol = GatewayCloseEventCode{
		Code:        4012,
		Description: "Unknown protocol",
		Explanation: "We didn't recognize the protocol you sent.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeDisconnected = GatewayCloseEventCode{
		Code:        4014,
		Description: "Disconnected",
		Explanation: "Channel was deleted, you were kicked, voice server changed, or the main voicegateway session was dropped. Don't reconnect.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeVoiceServerCrash = GatewayCloseEventCode{
		Code:        4015,
		Description: "Voice server crashed",
		Explanation: "The server crashed. Our bad! Try resuming.",
		Reconnect:   true,
	}

	GatewayCloseEventCodeUnknownEncryptionMode = GatewayCloseEventCode{
		Code:        4016,
		Description: "Unknown encryption mode",
		Explanation: "We didn't recognize your encryption.",
		Reconnect:   false,
	}

	GatewayCloseEventCodeUnknown = GatewayCloseEventCode{
		Code:        0,
		Description: "Unknown",
		Explanation: "Unknown Voice Close Event Code",
		Reconnect:   true,
	}

	GatewayCloseEventCodes = map[int]GatewayCloseEventCode{
		GatewayCloseEventCodeHeartbeatTimeout.Code:      GatewayCloseEventCodeHeartbeatTimeout,
		GatewayCloseEventCodeUnknownError.Code:          GatewayCloseEventCodeUnknownError,
		GatewayCloseEventCodeUnknownOpcode.Code:         GatewayCloseEventCodeUnknownOpcode,
		GatewayCloseEventCodeFailedDecode.Code:          GatewayCloseEventCodeFailedDecode,
		GatewayCloseEventCodeNotAuthenticated.Code:      GatewayCloseEventCodeNotAuthenticated,
		GatewayCloseEventCodeAuthenticationFailed.Code:  GatewayCloseEventCodeAuthenticationFailed,
		GatewayCloseEventCodeAlreadyAuthenticated.Code:  GatewayCloseEventCodeAlreadyAuthenticated,
		GatewayCloseEventCodeSessionNoLongerValid.Code:  GatewayCloseEventCodeSessionNoLongerValid,
		GatewayCloseEventCodeSessionTimeout.Code:        GatewayCloseEventCodeSessionTimeout,
		GatewayCloseEventCodeServerNotFound.Code:        GatewayCloseEventCodeServerNotFound,
		GatewayCloseEventCodeUnknownProtocol.Code:       GatewayCloseEventCodeUnknownProtocol,
		GatewayCloseEventCodeDisconnected.Code:          GatewayCloseEventCodeDisconnected,
		GatewayCloseEventCodeVoiceServerCrash.Code:      GatewayCloseEventCodeVoiceServerCrash,
		GatewayCloseEventCodeUnknownEncryptionMode.Code: GatewayCloseEventCodeUnknownEncryptionMode,
	}
)

AllEncryptionModes is a list of all supported EncryptionMode(s).

View Source
var ErrDecryptionFailed = errors.New("decryption failed")

ErrDecryptionFailed is returned when the packet decryption fails.

View Source
var SilenceAudioFrame = []byte{0xF8, 0xFF, 0xFE}

SilenceAudioFrame is a 20ms opus frame of silence.

Functions

This section is empty.

Types

type AEADEncrypter added in v0.19.0

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

AEADEncrypter is used to encrypt RTP packets using AEAD ciphers.

func NewAEADEncrypter added in v0.19.0

func NewAEADEncrypter(encryptionMode EncryptionMode, secretKey []byte) (*AEADEncrypter, error)

NewAEADEncrypter creates a new AEADEncrypter with the given encryption mode and secret key.

func (*AEADEncrypter) Decrypt added in v0.19.0

func (a *AEADEncrypter) Decrypt(rtpHeaderSize int, packet []byte) ([]byte, error)

func (*AEADEncrypter) Encrypt added in v0.19.0

func (a *AEADEncrypter) Encrypt(header [RTPHeaderSize]byte, data []byte) []byte

type AudioReceiver

type AudioReceiver interface {
	// Open starts receiving audio from the voice connection.
	Open()

	// CleanupUser cleans up any audio resources for the given user.
	CleanupUser(userID snowflake.ID)

	// Close stops receiving audio from the voice connection.
	Close()
}

AudioReceiver is used to receive audio from a voice connection and pass it to an OpusFrameReceiver.

func NewAudioReceiver

func NewAudioReceiver(logger *slog.Logger, opusReceiver OpusFrameReceiver, conn Conn) AudioReceiver

NewAudioReceiver creates a new AudioReceiver reading audio to the given OpusFrameReceiver from the given Conn.

type AudioReceiverCreateFunc

type AudioReceiverCreateFunc func(logger *slog.Logger, receiver OpusFrameReceiver, connection Conn) AudioReceiver

AudioReceiverCreateFunc is used to create a new AudioReceiver reading audio from the given Conn.

type AudioSender

type AudioSender interface {
	Open()
	Close()
}

AudioSender is used to send audio to a Conn.

func NewAudioSender

func NewAudioSender(logger *slog.Logger, opusProvider OpusFrameProvider, conn Conn) AudioSender

NewAudioSender creates a new AudioSender sending audio from the given OpusFrameProvider to the given Conn.

type AudioSenderCreateFunc

type AudioSenderCreateFunc func(logger *slog.Logger, provider OpusFrameProvider, conn Conn) AudioSender

AudioSenderCreateFunc is used to create a new AudioSender sending audio to the given Conn.

type CloseHandlerFunc

type CloseHandlerFunc func(gateway Gateway, err error, reconnect bool)

CloseHandlerFunc is a function that handles a voice gateway close.

type Conn

type Conn interface {
	// Gateway returns the voice Gateway used by the voice Conn.
	Gateway() Gateway

	// UDP returns the voice UDPConn conn used by the voice Conn.
	UDP() UDPConn

	// ChannelID returns the ID of the voice channel the voice Conn is openedChan to.
	ChannelID() *snowflake.ID

	// GuildID returns the ID of the guild the voice Conn is openedChan to.
	GuildID() snowflake.ID

	// UserIDBySSRC returns the ID of the user for the given SSRC.
	UserIDBySSRC(ssrc uint32) snowflake.ID

	// SetSpeaking sends a speaking packet to the Conn socket discord.
	SetSpeaking(ctx context.Context, flags SpeakingFlags) error

	// SetOpusFrameProvider lets you inject your own OpusFrameProvider.
	SetOpusFrameProvider(handler OpusFrameProvider)

	// SetOpusFrameReceiver lets you inject your own OpusFrameReceiver.
	SetOpusFrameReceiver(handler OpusFrameReceiver)

	// SetEventHandlerFunc lets listen for voice gateway events.
	SetEventHandlerFunc(eventHandlerFunc EventHandlerFunc)

	// Open opens the voice conn. It will connect to the voice gateway and start the Conn conn after it receives the Gateway events.
	Open(ctx context.Context, channelID snowflake.ID, selfMute bool, selfDeaf bool) error

	// Close closes the voice conn. It will close the Conn conn and disconnect from the voice gateway.
	Close(ctx context.Context)

	// HandleVoiceStateUpdate provides the gateway.EventVoiceStateUpdate to the voice conn. Which is needed to connect to the voice Gateway.
	HandleVoiceStateUpdate(update botgateway.EventVoiceStateUpdate)

	// HandleVoiceServerUpdate provides the gateway.EventVoiceServerUpdate to the voice conn. Which is needed to connect to the voice Gateway.
	HandleVoiceServerUpdate(update botgateway.EventVoiceServerUpdate)
}

Conn is a complete voice conn to discord. It holds the Gateway and voiceudp.UDPConn conn and combines them.

func NewConn

func NewConn(guildID snowflake.ID, userID snowflake.ID, voiceStateUpdateFunc StateUpdateFunc, removeConnFunc func(), opts ...ConnConfigOpt) Conn

NewConn returns a new default voice conn.

type ConnConfigOpt

type ConnConfigOpt func(config *connConfig)

ConnConfigOpt is used to functionally configure a connConfig.

func WithConnAudioReceiverCreateFunc

func WithConnAudioReceiverCreateFunc(audioReceiverCreateFunc AudioReceiverCreateFunc) ConnConfigOpt

WithConnAudioReceiverCreateFunc sets the Conn(s) used AudioReceiverCreateFunc.

func WithConnAudioSenderCreateFunc

func WithConnAudioSenderCreateFunc(audioSenderCreateFunc AudioSenderCreateFunc) ConnConfigOpt

WithConnAudioSenderCreateFunc sets the Conn(s) used AudioSenderCreateFunc.

func WithConnDaveSessionCreateFunc added in v0.19.0

func WithConnDaveSessionCreateFunc(sessionCreateFunc godave.SessionCreateFunc) ConnConfigOpt

WithConnDaveSessionCreateFunc sets the Conn(s) used godave.SessionCreateFunc.

func WithConnDaveSessionLogger added in v0.19.0

func WithConnDaveSessionLogger(logger *slog.Logger) ConnConfigOpt

WithConnDaveSessionLogger sets the Conn(s) used godave.Session logger.

func WithConnEventHandlerFunc

func WithConnEventHandlerFunc(eventHandlerFunc EventHandlerFunc) ConnConfigOpt

WithConnEventHandlerFunc sets the Conn(s) used EventHandlerFunc.

func WithConnGatewayConfigOpts

func WithConnGatewayConfigOpts(opts ...GatewayConfigOpt) ConnConfigOpt

WithConnGatewayConfigOpts sets the Conn(s) used GatewayConfigOpt(s).

func WithConnGatewayCreateFunc

func WithConnGatewayCreateFunc(gatewayCreateFunc GatewayCreateFunc) ConnConfigOpt

WithConnGatewayCreateFunc sets the Conn(s) used GatewayCreateFunc.

func WithConnLogger

func WithConnLogger(logger *slog.Logger) ConnConfigOpt

WithConnLogger sets the Conn(s) used Logger.

func WithUDPConnConfigOpts

func WithUDPConnConfigOpts(opts ...UDPConnConfigOpt) ConnConfigOpt

WithUDPConnConfigOpts sets the Conn(s) used UDPConnConfigOpt(s).

func WithUDPConnCreateFunc

func WithUDPConnCreateFunc(udpConnCreateFunc UDPConnCreateFunc) ConnConfigOpt

WithUDPConnCreateFunc sets the Conn(s) used UDPConnCreateFunc.

type ConnCreateFunc

type ConnCreateFunc func(guildID snowflake.ID, userID snowflake.ID, voiceStateUpdateFunc StateUpdateFunc, removeConnFunc func(), opts ...ConnConfigOpt) Conn

ConnCreateFunc is a type alias for a function that creates a new Conn.

type Encrypter added in v0.19.0

type Encrypter interface {
	// Encrypt encrypts the given RTP header and opus data and returns the encrypted packet.
	Encrypt(header [RTPHeaderSize]byte, data []byte) []byte

	// Decrypt decrypts the given packet and returns the RTP header and opus data.
	Decrypt(rtpHeaderSize int, packet []byte) ([]byte, error)
}

Encrypter is used to encrypt RTP packets before sending them to Discord.

The header is the 12 byte RTP header. The data is the opus encoded audio data.

The returned byte slice is the encrypted packet ready to be sent to Discord.

NoopEncrypter does not encrypt the data and is used for testing purposes only. AEADEncrypter is the required aead_xchacha20_poly1305_rtpsize encryption mode by Discord. [AEADAES256GCMRTPSize] is the preferred aead_aes256_gcm_rtpsize encryption mode by Discord. See https://discord.com/developers/docs/topics/voice-connections#transport-encryption-and-sending-voice for more information.

func NewEncrypter added in v0.19.0

func NewEncrypter(encryptionMode EncryptionMode, secretKey []byte) (Encrypter, error)

NewEncrypter creates a new Encrypter based on the given encryption mode and secret key. If the encryption mode is not supported, an error is returned.

type EncryptionMode

type EncryptionMode string

EncryptionMode is the encryption mode used for voice data.

const (
	// EncryptionModeNone is no encryption. This mode is not supported by Discord.
	EncryptionModeNone EncryptionMode = ""
	// EncryptionModeAEADAES256GCMRTPSize is the preferred encryption mode.
	EncryptionModeAEADAES256GCMRTPSize EncryptionMode = "aead_aes256_gcm_rtpsize"
	// EncryptionModeAEADXChaCha20Poly1305RTPSize is the required encryption mode.
	EncryptionModeAEADXChaCha20Poly1305RTPSize EncryptionMode = "aead_xchacha20_poly1305_rtpsize"
)

All possible EncryptionMode(s) https://discord.com/developers/docs/topics/voice-connections#transport-encryption-and-sending-voice.

func ChooseEncryptionMode added in v0.19.0

func ChooseEncryptionMode(modes []EncryptionMode) (EncryptionMode, error)

ChooseEncryptionMode chooses the best supported encryption mode from the given list of modes. It returns an error if no supported mode is found.

type EventHandlerFunc

type EventHandlerFunc func(gateway Gateway, opCode Opcode, sequenceNumber int, data GatewayMessageData)

EventHandlerFunc is a function that handles a voice gateway event.

type Gateway

type Gateway interface {
	// SSRC returns the SSRC of the current voice connection.
	SSRC() uint32

	// Open opens a new websocket connection to the voice gateway.
	Open(ctx context.Context, state State) error

	// Close closes the websocket connection to the voice gateway.
	Close()

	// CloseWithCode closes the websocket connection to the voice gateway with a specific close code.
	CloseWithCode(code int, message string)

	// Status returns the Status of the Gateway.
	Status() Status

	// Send sends a message to the voice gateway.
	Send(ctx context.Context, opCode Opcode, data GatewayMessageData) error

	// Latency returns the current latency of the voice gateway connection.
	Latency() time.Duration
}

Gateway is a websocket connection to the Discord voice gateway.

func NewGateway

func NewGateway(daveSession godave.Session, eventHandlerFunc EventHandlerFunc, closeHandlerFunc CloseHandlerFunc, opts ...GatewayConfigOpt) Gateway

NewGateway creates a new voice Gateway.

type GatewayBinaryMessageUnknown added in v0.19.0

type GatewayBinaryMessageUnknown []byte

type GatewayCloseEventCode

type GatewayCloseEventCode struct {
	Code        int
	Description string
	Explanation string
	Reconnect   bool
}

func GatewayCloseEventCodeByCode

func GatewayCloseEventCodeByCode(code int) GatewayCloseEventCode

type GatewayConfigOpt

type GatewayConfigOpt func(config *gatewayConfig)

GatewayConfigOpt is used to functionally configure a gatewayConfig.

func WithGatewayAutoReconnect

func WithGatewayAutoReconnect(autoReconnect bool) GatewayConfigOpt

WithGatewayAutoReconnect sets the Gateway(s) used AutoReconnect.

func WithGatewayDialer

func WithGatewayDialer(dialer *websocket.Dialer) GatewayConfigOpt

WithGatewayDialer sets the Gateway(s) used websocket.Dialer.

func WithGatewayLogger

func WithGatewayLogger(logger *slog.Logger) GatewayConfigOpt

WithGatewayLogger sets the Gateway(s) used Logger.

type GatewayCreateFunc

type GatewayCreateFunc func(daveManager godave.Session, eventHandlerFunc EventHandlerFunc, closeHandlerFunc CloseHandlerFunc, opts ...GatewayConfigOpt) Gateway

GatewayCreateFunc is a function that creates a new voice gateway.

type GatewayMessage

type GatewayMessage struct {
	Op   Opcode             `json:"op"`
	D    GatewayMessageData `json:"d,omitempty"`
	RawD json.RawMessage    `json:"-"`
	Seq  int                `json:"s,omitempty"`
}

GatewayMessage represents a voice gateway message

func (*GatewayMessage) UnmarshalBinary added in v0.19.0

func (m *GatewayMessage) UnmarshalBinary(r io.Reader) error

func (*GatewayMessage) UnmarshalJSON

func (m *GatewayMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshalls the GatewayMessage from json

type GatewayMessageData

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

GatewayMessageData represents a voice gateway text message data.

type GatewayMessageDataClientConnect

type GatewayMessageDataClientConnect struct {
	UserID     snowflake.ID `json:"user_id"`
	AudioCodec string       `json:"audio_codec"`
	VideoCodec string       `json:"video_codec"`
}

type GatewayMessageDataClientDisconnect

type GatewayMessageDataClientDisconnect struct {
	UserID snowflake.ID `json:"user_id"`
}

type GatewayMessageDataClientsConnect added in v0.19.0

type GatewayMessageDataClientsConnect struct {
	UserIDs []snowflake.ID `json:"user_ids"`
}

type GatewayMessageDataDaveInvalidCommitWelcome added in v0.19.0

type GatewayMessageDataDaveInvalidCommitWelcome struct {
	TransitionID uint16 `json:"transition_id"`
}

type GatewayMessageDataDaveMLSAnnounceCommitTransition added in v0.19.0

type GatewayMessageDataDaveMLSAnnounceCommitTransition struct {
	TransitionID  uint16
	CommitMessage []byte
}

type GatewayMessageDataDaveMLSCommitWelcome added in v0.19.0

type GatewayMessageDataDaveMLSCommitWelcome []byte

type GatewayMessageDataDaveMLSExternalSenderPackage added in v0.19.0

type GatewayMessageDataDaveMLSExternalSenderPackage []byte

type GatewayMessageDataDaveMLSKeyPackage added in v0.19.0

type GatewayMessageDataDaveMLSKeyPackage []byte

type GatewayMessageDataDaveMLSProposals added in v0.19.0

type GatewayMessageDataDaveMLSProposals []byte

type GatewayMessageDataDaveMLSWelcome added in v0.19.0

type GatewayMessageDataDaveMLSWelcome struct {
	TransitionID   uint16
	WelcomeMessage []byte
}

type GatewayMessageDataDaveProtocolExecuteTransition added in v0.19.0

type GatewayMessageDataDaveProtocolExecuteTransition struct {
	TransitionID uint16 `json:"transition_id"`
}

type GatewayMessageDataDaveProtocolPrepareEpoch added in v0.19.0

type GatewayMessageDataDaveProtocolPrepareEpoch struct {
	ProtocolVersion uint16 `json:"protocol_version"`
	Epoch           int    `json:"epoch"`
}

type GatewayMessageDataDaveProtocolPrepareTransition added in v0.19.0

type GatewayMessageDataDaveProtocolPrepareTransition struct {
	ProtocolVersion uint16 `json:"protocol_version"`
	TransitionID    uint16 `json:"transition_id"`
}

type GatewayMessageDataDaveProtocolReadyForTransition added in v0.19.0

type GatewayMessageDataDaveProtocolReadyForTransition struct {
	TransitionID uint16 `json:"transition_id"`
}

type GatewayMessageDataGuildSync added in v0.19.0

type GatewayMessageDataGuildSync struct{}

type GatewayMessageDataHeartbeat

type GatewayMessageDataHeartbeat struct {
	T      int64 `json:"t"`
	SeqAck int   `json:"seq_ack"`
}

type GatewayMessageDataHeartbeatACK

type GatewayMessageDataHeartbeatACK struct {
	T int64 `json:"t"`
}

type GatewayMessageDataHello

type GatewayMessageDataHello struct {
	HeartbeatInterval float64 `json:"heartbeat_interval"`
}

type GatewayMessageDataIdentify

type GatewayMessageDataIdentify struct {
	GuildID                snowflake.ID `json:"server_id"`
	UserID                 snowflake.ID `json:"user_id"`
	SessionID              string       `json:"session_id"`
	Token                  string       `json:"token"`
	MaxDaveProtocolVersion int          `json:"max_dave_protocol_version"`
}

type GatewayMessageDataReady

type GatewayMessageDataReady struct {
	SSRC  uint32           `json:"ssrc"`
	IP    string           `json:"ip"`
	Port  int              `json:"port"`
	Modes []EncryptionMode `json:"modes"`
}

type GatewayMessageDataResume

type GatewayMessageDataResume struct {
	GuildID   snowflake.ID `json:"server_id"` // wtf is this?
	SessionID string       `json:"session_id"`
	Token     string       `json:"token"`
	SeqAck    int          `json:"seq"`
}

type GatewayMessageDataResumed added in v0.19.0

type GatewayMessageDataResumed struct{}

type GatewayMessageDataSelectProtocol

type GatewayMessageDataSelectProtocol struct {
	Protocol Protocol                             `json:"protocol"`
	Data     GatewayMessageDataSelectProtocolData `json:"data"`
}

type GatewayMessageDataSelectProtocolData

type GatewayMessageDataSelectProtocolData struct {
	Address string         `json:"address"`
	Port    int            `json:"port"`
	Mode    EncryptionMode `json:"mode"`
}

type GatewayMessageDataSessionDescription

type GatewayMessageDataSessionDescription struct {
	Mode                EncryptionMode `json:"mode"`
	SecretKey           []byte         `json:"secret_key"`
	DaveProtocolVersion int            `json:"dave_protocol_version"`
}

type GatewayMessageDataSpeaking

type GatewayMessageDataSpeaking struct {
	Speaking SpeakingFlags `json:"speaking"`
	Delay    int           `json:"delay"`
	SSRC     uint32        `json:"ssrc"`
	UserID   snowflake.ID  `json:"user_id,omitempty"`
}

type GatewayMessageDataUnknown added in v0.16.5

type GatewayMessageDataUnknown json.RawMessage

func (GatewayMessageDataUnknown) MarshalJSON added in v0.16.8

func (m GatewayMessageDataUnknown) MarshalJSON() ([]byte, error)

func (*GatewayMessageDataUnknown) UnmarshalJSON added in v0.16.8

func (m *GatewayMessageDataUnknown) UnmarshalJSON(data []byte) error

type Manager

type Manager interface {
	// HandleVoiceStateUpdate handles a gateway.EventVoiceStateUpdate
	HandleVoiceStateUpdate(update gateway.EventVoiceStateUpdate)

	// HandleVoiceServerUpdate handles a gateway.EventVoiceServerUpdate
	HandleVoiceServerUpdate(update gateway.EventVoiceServerUpdate)

	// CreateConn creates a new voice connection for the given guild.
	CreateConn(guildID snowflake.ID) Conn

	// GetConn returns the voice connection for the given guild.
	GetConn(guildID snowflake.ID) Conn

	// Conns returns all voice connections. This function is thread-safe.
	Conns() iter.Seq[Conn]

	// RemoveConn removes the voice connection for the given guild.
	RemoveConn(guildID snowflake.ID)

	// Close closes all voice connections.
	Close(ctx context.Context)
}

Manager manages all voice connections.

func NewManager

func NewManager(voiceStateUpdateFunc StateUpdateFunc, userID snowflake.ID, opts ...ManagerConfigOpt) Manager

NewManager creates a new Manager.

type ManagerConfigOpt

type ManagerConfigOpt func(config *managerConfig)

ManagerConfigOpt is used to functionally configure a managerConfig.

func WithConnConfigOpts

func WithConnConfigOpts(opts ...ConnConfigOpt) ManagerConfigOpt

WithConnConfigOpts sets the ConnConfigOpt(s) for the Manager.

func WithConnCreateFunc

func WithConnCreateFunc(connectionCreateFunc ConnCreateFunc) ManagerConfigOpt

WithConnCreateFunc sets the ConnCreateFunc for the Manager.

func WithDaveSessionCreateFunc added in v0.19.0

func WithDaveSessionCreateFunc(sessionCreateFunc godave.SessionCreateFunc) ManagerConfigOpt

WithDaveSessionCreateFunc sets the godave.SessionCreateFunc for the Manager.

func WithDaveSessionLogger added in v0.19.0

func WithDaveSessionLogger(logger *slog.Logger) ManagerConfigOpt

WithDaveSessionLogger sets the slog.Logger for godave sessions created by the Manager.

func WithLogger

func WithLogger(logger *slog.Logger) ManagerConfigOpt

WithLogger sets the logger for the webhook client.

type NoopEncrypter added in v0.19.0

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

NoopEncrypter is used to not encrypt RTP packets. This is only for testing purposes. Do not use this in production as Discord requires encryption.

func NewNoopEncrypter added in v0.19.0

func NewNoopEncrypter() *NoopEncrypter

NewNoopEncrypter creates a new NoopEncrypter.

func (*NoopEncrypter) Decrypt added in v0.19.0

func (n *NoopEncrypter) Decrypt(rtpHeaderSize int, packet []byte) ([]byte, error)

func (*NoopEncrypter) Encrypt added in v0.19.0

func (n *NoopEncrypter) Encrypt(header [RTPHeaderSize]byte, data []byte) []byte

type Opcode

type Opcode int
const (
	OpcodeIdentify Opcode = iota
	OpcodeSelectProtocol
	OpcodeReady
	OpcodeHeartbeat
	OpcodeSessionDescription
	OpcodeSpeaking
	OpcodeHeartbeatACK
	OpcodeResume
	OpcodeHello
	OpcodeResumed

	OpcodeClientsConnect

	OpcodeClientDisconnect
	OpcodeGuildSync

	OpcodeDavePrepareTransition
	OpcodeDaveExecuteTransition
	OpcodeDaveTransitionReady
	OpcodeDavePrepareEpoch
	OpcodeDaveMLSExternalSenderPackage
	OpcodeDaveMLSKeyPackage
	OpcodeDaveMLSProposals
	OpcodeDaveMLSCommitWelcome
	OpcodeDaveMLSPrepareCommitTransition
	OpcodeDaveMLSWelcome
	OpcodeDaveMLSInvalidCommitWelcome
)

func (Opcode) IsBinary added in v0.19.0

func (o Opcode) IsBinary() bool

type OpusFrameProvider

type OpusFrameProvider interface {
	// ProvideOpusFrame provides an opus frame to the AudioSender.
	ProvideOpusFrame() ([]byte, error)

	// Close closes the OpusFrameProvider.
	Close()
}

OpusFrameProvider is used to provide opus frames to an AudioSender.

type OpusFrameReceiver

type OpusFrameReceiver interface {
	// ReceiveOpusFrame receives an opus frame.
	ReceiveOpusFrame(userID snowflake.ID, packet *Packet) error

	// CleanupUser cleans up any audio resources for the given user.
	CleanupUser(userID snowflake.ID)

	// Close stops receiving audio from the voice connection.
	Close()
}

OpusFrameReceiver is an interface used to receive opus frames from an AudioReceiver.

type OpusReader added in v0.16.8

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

OpusReader is an OpusFrameProvider that reads opus frames from the given io.Reader. Each opus frame is prefixed with a 4 byte little endian uint32 that represents the length of the frame.

func NewOpusReader

func NewOpusReader(r io.Reader) *OpusReader

NewOpusReader returns a new OpusFrameProvider that reads opus frames from the given io.Reader.

func (*OpusReader) Close added in v0.16.8

func (*OpusReader) Close()

Close is a no-op.

func (*OpusReader) ProvideOpusFrame added in v0.16.8

func (h *OpusReader) ProvideOpusFrame() ([]byte, error)

ProvideOpusFrame reads the next opus frame from the underlying io.Reader.

type OpusWriter added in v0.16.8

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

OpusWriter is an OpusFrameReceiver that writes opus frames to the given io.Writer. Each opus frame is prefixed with a 4 byte little endian uint32 that represents the length of the frame.

func NewOpusWriter

func NewOpusWriter(w io.Writer, userFilter UserFilterFunc) *OpusWriter

NewOpusWriter returns a new OpusFrameReceiver that writes opus frames to the given io.Writer.

func (*OpusWriter) CleanupUser added in v0.16.8

func (*OpusWriter) CleanupUser(_ snowflake.ID)

CleanupUser is a no-op.

func (*OpusWriter) Close added in v0.16.8

func (*OpusWriter) Close()

Close is a no-op.

func (*OpusWriter) ReceiveOpusFrame added in v0.16.8

func (r *OpusWriter) ReceiveOpusFrame(userID snowflake.ID, packet *Packet) error

ReceiveOpusFrame writes the given opus frame to the underlying io.Writer.

type Packet

type Packet struct {
	Type byte
	// Sequence is the sequence number of the packet.
	Sequence uint16
	// Timestamp is the timestamp of the packet.
	Timestamp uint32
	// SSRC is the users SSRC of the packet.
	SSRC         uint32
	HasExtension bool
	ExtensionID  int
	Extension    []byte
	CSRC         []uint32
	HeaderSize   int
	// Opus is the actual opus data of the packet.
	Opus []byte
}

Packet is a voice packet received from discord.

type Protocol added in v0.16.9

type Protocol string
const (
	ProtocolUDP Protocol = "udp"
)

type SpeakingFlags

type SpeakingFlags int
const (
	SpeakingFlagMicrophone SpeakingFlags = 1 << iota
	SpeakingFlagSoundshare
	SpeakingFlagPriority
	SpeakingFlagNone SpeakingFlags = 0
)

type SsrcLookupFunc added in v0.19.0

type SsrcLookupFunc func(ssrc uint32) snowflake.ID

type State

type State struct {
	GuildID snowflake.ID
	UserID  snowflake.ID

	ChannelID *snowflake.ID
	SessionID string
	Token     string
	Endpoint  string
}

State is the current state of the voice conn.

type StateProviderFunc

type StateProviderFunc func() State

StateProviderFunc is a function that provides the current conn state of the voice gateway.

type StateUpdateFunc

type StateUpdateFunc func(ctx context.Context, guildID snowflake.ID, channelID *snowflake.ID, selfMute bool, selfDeaf bool) error

StateUpdateFunc is used to update the voice state of the bot from the Manager.

type Status

type Status int

Status returns the current status of the gateway.

const (
	StatusUnconnected Status = iota
	StatusConnecting
	StatusWaitingForHello
	StatusIdentifying
	StatusResuming
	StatusWaitingForReady
	StatusReady
	StatusDisconnected
)

type UDPConn

type UDPConn interface {
	// LocalAddr returns the local network address, if known.
	LocalAddr() net.Addr

	// RemoteAddr returns the remote network address, if known.
	RemoteAddr() net.Addr

	// SetSecretKey sets the secret key used to encrypt packets.
	SetSecretKey(encryptionMode EncryptionMode, secretKey []byte) error

	SetDeadline(t time.Time) error

	// SetReadDeadline sets the read deadline for the UDPConn connection.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the write deadline for the UDPConn connection.
	SetWriteDeadline(t time.Time) error

	// Open opens the UDPConn connection.
	Open(ctx context.Context, ip string, port int, ssrc uint32) (string, int, error)

	// Close closes the UDPConn connection.
	Close() error

	// Read reads a packet from the UDPConn connection. This implements the io.Reader interface.
	Read(p []byte) (int, error)

	// ReadPacket reads a packet from the UDPConn connection.
	ReadPacket() (*Packet, error)

	// Write writes a packet to the UDPConn connection. This implements the io.Writer interface.
	Write(p []byte) (int, error)
}

UDPConn represents a UDP connection to discord voice servers. It is used to send/receive voice packets to/from discord. It implements the io.Reader, io.Writer and io.Closer interface.

func NewUDPConn

func NewUDPConn(daveSession godave.Session, ssrcLookup SsrcLookupFunc, opts ...UDPConnConfigOpt) UDPConn

NewUDPConn creates a new voice UDPConn with the given configuration.

type UDPConnConfigOpt

type UDPConnConfigOpt func(config *udpConnConfig)

UDPConnConfigOpt is a function that modifies the udpConnConfig.

func WithUDPConnDialer

func WithUDPConnDialer(dialer *net.Dialer) UDPConnConfigOpt

func WithUDPConnLogger

func WithUDPConnLogger(logger *slog.Logger) UDPConnConfigOpt

type UDPConnCreateFunc

type UDPConnCreateFunc func(daveSession godave.Session, ssrcLookup SsrcLookupFunc, opts ...UDPConnConfigOpt) UDPConn

UDPConnCreateFunc is a function that creates a UDPConn.

type UserFilterFunc

type UserFilterFunc func(userID snowflake.ID) bool

UserFilterFunc is used as a filter for which users to receive audio from.

Jump to

Keyboard shortcuts

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