LoBoat is a Discord bot built with C# and .NET. It started as a personal server bot and grew into a small real-time audio system with music playback, text-to-speech, anime image commands, Morse code audio, structured logging, and Docker-based deployment.
This repository documents the architecture and integrations behind the bot, but it is not intended to be a managed public bot service.
- Discord slash-command bot built on
Discord.Net - Music playback and queue control through Lavalink
- Text-to-speech audio generation with FFmpeg normalization
- Source-aware now-playing embeds
- Anime image and roleplay commands backed by third-party APIs
- Morse code translation and audio playback
- Dependency injection, hosted services, typed options, and structured logging
- Docker Compose development setup with a Lavalink sidecar
- GitHub Actions workflow for publishing a Docker image to GHCR
- C# / .NET 10
- Discord.Net
- Lavalink4NET
- FFmpeg / FFMpegCore
- Serilog
- Docker / Docker Compose
- GitHub Actions
LoBoat/
Anime/ Anime image API integrations and commands
Audio/
Features/ Text-to-speech and Morse code features
Player/ Lavalink player, queue, and playback commands
Services/ Audio source helpers
Core/ Host startup, settings, and Discord bot service
Interactions/ Slash-command handling and response helpers
Logging/ Serilog enrichers and Discord error sink
PickupLines/ Small API-backed command feature
Lavalink/ Local Lavalink configuration template
compose.dev.yaml Docker Compose development stack
Runtime secrets and machine-specific values are provided through environment variables. Copy the example file before running locally:
cp .env.example .envRequired values:
BotSettings__DevToken: Discord bot token used for local developmentBotSettings__ProdToken: Discord bot token used when running with--prodBotSettings__DevGuildId: Guild ID used for development command registrationHttpSettings__UserAgent: User-Agent sent to third-party APIsDiscordSinkSettings__UserId: Discord user ID that receives error-log DMsLavalinkSettings__BaseAddress: Lavalink server address, usuallyhttp://lavalink:2333in DockerLavalinkSettings__Passphrase: Lavalink server passwordSpeechNormSettings__Expansion: FFmpeg speech-normalization expansion valueSpeechNormSettings__Raise: FFmpeg speech-normalization raise valueSpeechNormSettings__Link: Whether FFmpeg should link speech-normalization channelsSpeechNormSettings__FFMpegPath: Directory containing the FFmpeg binary
The app uses the standard .NET environment-variable convention: SectionName__PropertyName. The real .env and Lavalink/application.yml files are intentionally ignored.
Create local config files:
cp .env.example .env
cp Lavalink/application.example.yml Lavalink/application.ymlEdit .env with your own Discord bot tokens and guild/user IDs.
Start the app and Lavalink:
docker compose -f compose.dev.yaml up --buildTo register slash commands while developing, run the bot with the --registercommands argument from your preferred local run configuration.
Prerequisites:
- .NET 10 SDK
- FFmpeg installed locally
- A reachable Lavalink server
- The environment variables from
.env.exampleexported in your shell or run configuration
Build the solution:
dotnet build LoBoat.slnxRun the bot:
dotnet run --project LoBoat/LoBoat.csprojFor production token selection, pass --prod:
dotnet run --project LoBoat/LoBoat.csproj -- --prodThis project is most useful as a code sample for:
- long-running .NET worker services
- Discord interaction handling
- real-time audio playback workflows
- external API integration
- Dockerized app/runtime dependency setup
- practical logging and error reporting
Some third-party services require their own accounts, tokens, or Lavalink plugin configuration. Those values are intentionally excluded from the repository.