Skip to content

Repository files navigation

UDC-Bot

A Discord.NET bot made for the server Unity Developer Community Join us on Discord !

The code is provided as-is and there will be no guaranteed support to help make it run.

Table Of Contents

Features

FeatureDescription
User ProfilesXP/level system, karma tracking, profile cards with customizable skins
ModerationMute, kick, ban, slowmode, message clearing, audit logging
Slash CommandsModern Discord slash command support alongside text commands
CasinoToken economy with Blackjack, Poker, and Rock Paper Scissors (details)
WeatherTemperature, conditions, air quality, and local time via OpenWeatherMap
RemindersPersistent scheduled reminders with natural time parsing
TipsSearchable tip database with image support
TicketsPrivate complaint/support ticket system
Unity HelpHelp forum thread management, auto-archive, canned responses, FAQ/resources
RecruitmentConfigurable recruitment workflow
Birthday AnnouncementsScheduled birthday notifications
Currency ConversionReal-time currency conversion
Flight DataAirport and flight lookups
RSS FeedsFeed parsing and management
LeaderboardsXP, karma (weekly/monthly/yearly), and casino token leaderboards

Architecture

This bot follows a Service-Module architecture pattern designed for maintainability and separation of concerns.

Services vs Modules

Services (/DiscordBot/Services/) contain the core business logic and data operations:

  • Handle database interactions, API calls, and background tasks
  • Maintain state and provide reusable functionality
  • Examples: UserService, DatabaseService, ModerationService, LoggingService
  • Registered as singletons in the dependency injection container

Modules (/DiscordBot/Modules/) handle Discord command interactions:

  • Expose functionality to users via chat commands
  • Use [Command] attributes to define command behavior
  • Receive services via dependency injection
  • Examples: UserModule, TipModule, ModerationModule

Dependency Injection

The bot uses .NET's built-in dependency injection system:

  • Services are registered in Program.cs using ConfigureServices()
  • Modules receive services via public property injection
  • This allows for loose coupling and easier testing

Command System

The bot supports both text commands and slash commands:

Text Commands (via CommandService):

  • Use attributes like [Command("commandname")] and [Summary("description")]
  • Triggered by the configured prefix (default !)

Slash Commands (via InteractionService):

  • Use [SlashCommand], [Group], and [ComponentInteraction] attributes
  • Registered per-guild using GuildId from settings
  • Support autocomplete, buttons, modals, and select menus

Shared:

  • Custom attributes provide authorization: [RequireModerator], [RequireAdmin]
  • Command routing is handled by CommandHandlingService

Contributing

Adding a New Command

  1. Choose the appropriate module or create a new one in /DiscordBot/Modules/
  2. Add the command method with proper attributes:
[Command("mycommand")][Summary("Description of what this command does")][RequireModerator]// Optional: Add permission requirementspublicasyncTaskMyCommand(stringparameter){// Your command logic hereawaitReplyAsync("Command executed!");}
  1. Inject required services via public properties:
publicUserServiceUserService{get;set;}publicDatabaseServiceDatabaseService{get;set;}

Adding a New Slash Command

  1. Choose an existing interaction module or create a new one in /DiscordBot/Modules/
  2. Add the slash command method with proper attributes:
[SlashCommand("mycommand","Description of what this command does")]publicasyncTaskMyCommand([Summary(description:"A parameter")]stringparameter){awaitRespondAsync("Command executed!");}
  1. For grouped commands, use the [Group] attribute on the class:
[Group("mygroup","Group description")]publicclassMySlashModule:InteractionModuleBase<SocketInteractionContext>{[SlashCommand("subcommand","Subcommand description")]publicasyncTaskSubCommand()=>awaitRespondAsync("Done!");}

Slash commands are registered per-guild on startup using the GuildId setting.

Creating a New Service

  1. Create your service class in /DiscordBot/Services/:
publicclassMyNewService{privatereadonlyDatabaseService_databaseService;publicMyNewService(DatabaseServicedatabaseService){_databaseService=databaseService;}publicasyncTaskDoSomethingAsync(){// Your service logic here}}
  1. Register the service in Program.cs within ConfigureServices():
.AddSingleton<MyNewService>()
  1. Inject it into modules that need it:
publicMyNewServiceMyNewService{get;set;}

Custom Attributes

Create custom precondition attributes in /DiscordBot/Attributes/:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]publicclassRequireMyRoleAttribute:PreconditionAttribute{publicoverrideTask<PreconditionResult>CheckPermissionsAsync(ICommandContextcontext,CommandInfocommand,IServiceProviderservices){varuser=(SocketGuildUser)context.Message.Author;varsettings=services.GetRequiredService<BotSettings>();if(user.Roles.Any(x =>x.Id==settings.MyRoleId))returnTask.FromResult(PreconditionResult.FromSuccess());returnTask.FromResult(PreconditionResult.FromError("Access denied!"));}}

Compiling

Dependencies

To successfully compile you will need the following:

Required:

Recommended for Development:

Build the project:

dotnet restore
dotnet build

Note: Docker is highly recommended for local development as it simplifies database setup and ensures consistency across development environments.

Running

Quick Setup

  1. Copy required folders:

    • Copy the DiscordBot/SERVER folder to your build output directory
    • If unsure of the location, run the bot once - it will show an error with the expected path
  2. Configure settings:

    • Copy DiscordBot/Settings folder to the SERVER folder (exclude the Deserialized subfolder)
    • Copy Settings.example.json and rename it to Settings.json
    • Edit Settings.json and configure:
      • Bot Token: Get this from the Discord Developer Portal
      • DbConnectionString: Database connection details (see database setup below)
  3. Choose your database setup:Docker (recommended) or Manual setup

Important: Read the comments in Settings.json carefully - they explain which settings need to be changed and which are optional.

For production deployment, see the Deployment Guide.

Docker

Recommended for development: Docker simplifies database setup and ensures consistency.

To run with Docker:

# Start both database and bot
docker-compose up
# Start only the database (run bot from IDE for faster development)
docker-compose up db

Development workflow:

  1. Start the database container: docker-compose up db
  2. Update the DbConnectionString in Settings.json to match your docker-compose configuration
  3. Run the bot from your IDE for faster development iteration

Full Docker deployment:

# Build and start everything
docker-compose up --build --remove-orphans
# Run in background
docker-compose up -d

Tip: For active development, use Docker only for the database and run the bot from your IDE - this gives you faster restart times and better debugging capabilities.

Runtime Dependencies

Manual Database Setup (Alternative to Docker):

If you prefer not to use Docker, you'll need to set up a PostgreSQL database manually:

  1. Install PostgreSQL:

    • Windows:PostgreSQL Installer
    • macOS:brew install postgresql@16
    • Linux:sudo apt install postgresql or equivalent
  2. Create database and user:

    • Create a new database for the bot
    • Create a user with full permissions to that database
    • Update the DbConnectionString in Settings.json with your connection details (e.g. Host=localhost;Port=5432;Database=udcbot;Username=udcbot;Password=YOUR_PASSWORD)
  3. Initialize database schema:

    • The bot will attempt to create necessary tables on first run
    • If it fails due to permissions, you may need to run it with elevated database privileges initially

Additional Linux Requirements: For image processing functionality, install Microsoft Core Fonts:

sudo apt install ttf-mscorefonts-installer

Connection String Format:

"DbConnectionString": "Host=localhost;Port=5432;Database=your_db_name;Username=your_username;Password=your_password"

Notes

Logging

The bot includes comprehensive logging to help with troubleshooting:

Log Levels and Colors:

  • Critical/Error: Red text - Something is broken and needs immediate attention
  • Warning: Yellow text - Potential issues that should be investigated
  • Info: White text - General operational information
  • Verbose/Debug: Gray text - Detailed information for development

During startup: Any yellow or red messages likely indicate configuration or connectivity issues.

Log Locations:

  • Console output for immediate feedback
  • Channel logging (if configured) for persistent records
  • See LoggingService for implementation details

Discord.Net Framework

This bot is built on Discord.Net, a powerful .NET library for Discord bots.

Key Concepts to Understand:

  • Asynchronous Programming: Extensive use of async/await patterns
  • Event-Driven Architecture: Reactions to Discord events (messages, user joins, etc.)
  • Polymorphism: Rich type hierarchy for Discord entities (users, channels, guilds)

Helpful Resources:

Common Patterns in this Bot:

  • Commands return Task for async operations
  • Heavy use of dependency injection for service access
  • Event handlers for background functionality (user joins, message processing)

FAQ

Common Setup Issues

Q: The bot won't start - what should I check? A: Verify these in order:

  1. Bot token is correctly set in Settings.json
  2. Database connection string is correct and database is accessible
  3. All required folders (SERVER, Settings) are in the right location
  4. Check console output for red/yellow log messages indicating specific errors

Q: "Unable to load the service index" or NuGet restore errors A: This is usually a temporary network issue with package sources. Try: Warning: Clearing NuGet locals will remove all cached packages and temporary files. This may require re-downloading dependencies, which could take significant time on slower connections.

dotnet nuget locals all --clear
dotnet restore

Q: Database connection fails A: Common causes:

  • Incorrect connection string format
  • Database server not running
  • User permissions insufficient
  • Firewall blocking database port

Q: How do I get a Discord bot token? A:

  1. Go to Discord Developer Portal
  2. Create a new application
  3. Go to "Bot" section
  4. Click "Add Bot" and copy the token
  5. Invite the bot to your server with appropriate permissions

Q: What permissions does the bot need? A: The bot requires:

  • Read Messages
  • Send Messages
  • Manage Messages (for moderation features)
  • Add Reactions
  • Use Slash Commands
  • Additional permissions based on enabled features

Q: How can I contribute or report bugs? A:

  • Check existing issues on GitHub
  • For bugs: provide console logs and steps to reproduce
  • For contributions: see the Contributing section above

Development Tips

Q: How do I debug commands? A:

  • Use the logging system: LoggingService.LogToConsole(message, ExtendedLogSeverity.Info)
  • Set breakpoints in your IDE when running the bot locally
  • Check the command history in CommandHandlingService

Q: My command isn't working A: Common issues:

  • Missing [Command] attribute
  • Incorrect parameter types
  • Missing dependency injection setup
  • Permission attribute blocking execution

About

Bot of the Unity Developer Community Discord server

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages