package main import ( "context" "log/slog" "os" "os/signal" "syscall" "github.com/disgoorg/disgo/bot" "github.com/disgoorg/disgolink/v4/disgolink" "github.com/joho/godotenv" "discord-music-bot/internal/commands" "discord-music-bot/internal/config" "discord-music-bot/internal/discord" "discord-music-bot/internal/lavalink" "discord-music-bot/internal/logging" "discord-music-bot/internal/music" ) func main() { _ = godotenv.Load() cfg, err := config.Load() if err != nil { slog.Error("invalid configuration", slog.Any("err", err)) os.Exit(1) } logger := logging.New(cfg.Debug) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() discordClient, err := discord.NewClient(cfg.DiscordToken, logger) if err != nil { logger.Error("failed to build discord client", slog.Any("err", err)) os.Exit(1) } defer discordClient.Close(context.Background()) lavalinkClient, err := lavalink.Connect(ctx, discordClient.ApplicationID, logger, disgolink.NodeConfig{ Name: cfg.LavalinkNodeName, Address: cfg.LavalinkAddress, Password: cfg.LavalinkPassword, Secure: cfg.LavalinkSecure, }) if err != nil { logger.Error("failed to connect to lavalink", slog.Any("err", err)) os.Exit(1) } defer lavalinkClient.Close() musicManager := music.NewManager(lavalinkClient, logger) lavalinkClient.AddListeners(disgolink.NewListenerFunc(musicManager.OnTrackEnd)) deps := &commands.Dependencies{ Discord: discordClient, Lavalink: lavalinkClient, Music: musicManager, } registry := commands.NewRegistry( commands.NewPlayCommand(deps), commands.NewSkipCommand(deps), commands.NewStopCommand(deps), commands.NewPauseCommand(deps), commands.NewResumeCommand(deps), commands.NewQueueCommand(deps), commands.NewNowPlayingCommand(deps), commands.NewSeekCommand(deps), commands.NewVolumeCommand(deps), commands.NewLoopCommand(deps), commands.NewShuffleCommand(deps), commands.NewRemoveCommand(deps), ) router := discord.NewRouter(registry, logger) voiceForwarder := discord.NewVoiceForwarder(discordClient, lavalinkClient, musicManager, logger) discordClient.AddEventListeners( bot.NewListenerFunc(router.OnApplicationCommand), bot.NewListenerFunc(voiceForwarder.OnVoiceStateUpdate), bot.NewListenerFunc(voiceForwarder.OnVoiceServerUpdate), ) if err := discord.RegisterCommands(discordClient, registry.Definitions()); err != nil { logger.Error("failed to register commands", slog.Any("err", err)) os.Exit(1) } if err := discordClient.OpenGateway(ctx); err != nil { logger.Error("failed to open gateway", slog.Any("err", err)) os.Exit(1) } logger.Info("bot is running", slog.String("application_id", discordClient.ApplicationID.String())) <-ctx.Done() logger.Info("shutting down") }