80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package discord
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
|
|
"github.com/disgoorg/disgo/bot"
|
|
"github.com/disgoorg/disgo/events"
|
|
"github.com/disgoorg/disgolink/v4/disgolink"
|
|
|
|
"discord-music-bot/internal/music"
|
|
)
|
|
|
|
type VoiceForwarder struct {
|
|
client *bot.Client
|
|
lavalink *disgolink.Client
|
|
music *music.Manager
|
|
logger *slog.Logger
|
|
}
|
|
|
|
func NewVoiceForwarder(client *bot.Client, lavalinkClient *disgolink.Client, musicManager *music.Manager, logger *slog.Logger) *VoiceForwarder {
|
|
return &VoiceForwarder{
|
|
client: client,
|
|
lavalink: lavalinkClient,
|
|
music: musicManager,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (f *VoiceForwarder) OnVoiceStateUpdate(event *events.GuildVoiceStateUpdate) {
|
|
if event.VoiceState.UserID == f.client.ApplicationID {
|
|
f.lavalink.OnVoiceStateUpdate(context.Background(), event.VoiceState.GuildID, event.VoiceState.ChannelID, event.VoiceState.SessionID)
|
|
return
|
|
}
|
|
|
|
f.leaveIfNowAlone(event)
|
|
}
|
|
|
|
func (f *VoiceForwarder) leaveIfNowAlone(event *events.GuildVoiceStateUpdate) {
|
|
oldChannelID := event.OldVoiceState.ChannelID
|
|
if oldChannelID == nil {
|
|
return
|
|
}
|
|
if newChannelID := event.VoiceState.ChannelID; newChannelID != nil && *newChannelID == *oldChannelID {
|
|
return
|
|
}
|
|
|
|
guildID := event.VoiceState.GuildID
|
|
|
|
botState, ok := f.client.Caches.VoiceState(guildID, f.client.ApplicationID)
|
|
if !ok || botState.ChannelID == nil || *botState.ChannelID != *oldChannelID {
|
|
return
|
|
}
|
|
|
|
for state := range f.client.Caches.VoiceStates(guildID) {
|
|
if state.UserID != f.client.ApplicationID && state.ChannelID != nil && *state.ChannelID == *oldChannelID {
|
|
return
|
|
}
|
|
}
|
|
|
|
ctx := context.Background()
|
|
if err := f.music.Guild(guildID).Stop(ctx); err != nil {
|
|
f.logger.ErrorContext(ctx, "failed to stop playback after being left alone",
|
|
slog.String("guild_id", guildID.String()), slog.Any("err", err))
|
|
}
|
|
if err := f.client.UpdateVoiceState(ctx, guildID, nil, false, false); err != nil {
|
|
f.logger.ErrorContext(ctx, "failed to leave voice channel after being left alone",
|
|
slog.String("guild_id", guildID.String()), slog.Any("err", err))
|
|
}
|
|
}
|
|
|
|
func (f *VoiceForwarder) OnVoiceServerUpdate(event *events.VoiceServerUpdate) {
|
|
if event.Endpoint == nil {
|
|
f.logger.Warn("received voice server update without an endpoint", slog.String("guild_id", event.GuildID.String()))
|
|
return
|
|
}
|
|
|
|
f.lavalink.OnVoiceServerUpdate(context.Background(), event.GuildID, event.Token, *event.Endpoint)
|
|
}
|