mirror of
https://github.com/DeltaV-Station/Delta-v.git
synced 2026-09-29 23:57:29 +00:00
Added documenation and improved discord bot for local development. Parameterized guild and context.
This commit is contained in:
@@ -312,3 +312,6 @@ Resources/MapImages
|
||||
|
||||
# Changelog package lock
|
||||
package-lock.json
|
||||
|
||||
# Discord Bot Config
|
||||
link-config.json
|
||||
@@ -10,14 +10,14 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Content.DiscordBot;
|
||||
|
||||
public sealed class CommandHandler(DiscordSocketClient client, CommandService commands, InteractionService interaction, ServerDbContext db)
|
||||
public sealed class CommandHandler(DiscordSocketClient client, CommandService commands, InteractionService interaction, ServerDbContext db, Config config)
|
||||
{
|
||||
private const ulong Guild = 1168210010233376858UL;
|
||||
|
||||
private ImmutableDictionary<ulong, DeltaVPatronTier>? _patronTiers;
|
||||
private ImmutableArray<DeltaVPatronTier> _tierPriority;
|
||||
private Task? _refreshPatronsTask;
|
||||
|
||||
private readonly Config _config = config;
|
||||
|
||||
public int Running = 1;
|
||||
|
||||
public async Task InstallCommandsAsync()
|
||||
@@ -229,7 +229,7 @@ public sealed class CommandHandler(DiscordSocketClient client, CommandService co
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await client.Rest.GetGuildUserAsync(Guild, linked.DiscordId);
|
||||
var user = await client.Rest.GetGuildUserAsync(_config.Guild, linked.DiscordId);
|
||||
if (user == null)
|
||||
{
|
||||
if (linked.Player.Patron != null)
|
||||
@@ -271,7 +271,7 @@ public sealed class CommandHandler(DiscordSocketClient client, CommandService co
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
await Task.Delay(60000);
|
||||
await Task.Delay(60000); // 60 seconds
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -5,4 +5,11 @@ public sealed class Config
|
||||
public string Token { get; set; } = string.Empty;
|
||||
|
||||
public string DatabaseString { get; set; } = string.Empty;
|
||||
|
||||
public string DatabaseContext { get; set; } = "postgres";
|
||||
|
||||
/// <summary>
|
||||
/// Discord "guild" ID (which is just the server ID). Default is DeltaV's server ID.
|
||||
/// </summary>
|
||||
public ulong Guild { get; set; } = 1513310351490289834UL;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputPath>..\bin\Content.DiscordBot\</OutputPath>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.Interactions;
|
||||
|
||||
namespace Content.DiscordBot.Modules;
|
||||
|
||||
public sealed class AccountLinkingModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
[Command("create")]
|
||||
[RequireOwner]
|
||||
[SlashCommand("create", "Creates the message with the linking popup. Only has to be run once.")]
|
||||
[Discord.Interactions.RequireOwner]
|
||||
public Task CreateAsync()
|
||||
{
|
||||
var component = new ComponentBuilder()
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace Content.DiscordBot.Modules;
|
||||
|
||||
public class LinkAccountModal : IModal
|
||||
{
|
||||
public string Title => "Link SS14 account";
|
||||
public string Title => "Link SS14 Account";
|
||||
|
||||
[InputLabel("SS14 Linking Code (top left in the lobby)")]
|
||||
[InputLabel("SS14 Linking Code (Top Left in the Lobby)")]
|
||||
[RequiredInput]
|
||||
[ModalTextInput("account_code")]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
|
||||
@@ -11,53 +11,75 @@ using Microsoft.EntityFrameworkCore;
|
||||
var client = new DiscordSocketClient(new DiscordSocketConfig { GatewayIntents = GatewayIntents.All });
|
||||
client.Log += Logger.Log;
|
||||
|
||||
string? token = null;
|
||||
string? connectionString = null;
|
||||
if (File.Exists("config.json"))
|
||||
Console.Out.WriteLine($"[INIT] Working Directory: {Directory.GetCurrentDirectory()}");
|
||||
|
||||
var config = new Config();
|
||||
if (File.Exists("link-config.json"))
|
||||
{
|
||||
var config = await JsonSerializer.DeserializeAsync<Config>(File.OpenRead("config.json")) ?? new Config();
|
||||
token = config.Token;
|
||||
Console.Out.WriteLine("[INIT] link-config.json found. Deserializing.");
|
||||
config = await JsonSerializer.DeserializeAsync<Config>(File.OpenRead("link-config.json")) ?? new Config();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (Environment.GetEnvironmentVariable("DISCORD_TOKEN") is { } envToken)
|
||||
token = envToken;
|
||||
config.Token = envToken;
|
||||
|
||||
if (Environment.GetEnvironmentVariable("DATABASE_STRING") is { } dbString)
|
||||
connectionString = dbString;
|
||||
config.DatabaseString = dbString;
|
||||
|
||||
if (Environment.GetEnvironmentVariable("DATABASE_CONTEXT") is { } context)
|
||||
config.DatabaseContext = context;
|
||||
|
||||
if (Environment.GetEnvironmentVariable("GUILD") is { } guildId)
|
||||
{
|
||||
try
|
||||
{
|
||||
config.Guild = ulong.Parse("guildId");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Out.WriteLine($"[INIT] Unable to parse guild ID. Defaulting to {config.Guild}. Exception: {ex.GetType()} {ex.Message}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
throw new ArgumentException("No token found.");
|
||||
if (string.IsNullOrWhiteSpace(config.Token))
|
||||
throw new ArgumentException("[INIT] No Discord Bot token found.");
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(config.DatabaseString))
|
||||
throw new ArgumentException("[INIT] No database connection string found.");
|
||||
|
||||
// Override for local sqlite development
|
||||
var usePostgres = true;
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(config.DatabaseContext) && config.DatabaseContext.Equals("sqlite"))
|
||||
usePostgres = false;
|
||||
//throw new ArgumentException("No database connection string found. Assuming local development.");
|
||||
}
|
||||
|
||||
await client.LoginAsync(TokenType.Bot, token);
|
||||
Console.Out.WriteLine($"[INIT] Guild ID: {config.Guild}");
|
||||
|
||||
await client.LoginAsync(TokenType.Bot, config.Token);
|
||||
await client.StartAsync();
|
||||
|
||||
ServerDbContext db;
|
||||
if (usePostgres)
|
||||
{
|
||||
Console.Out.WriteLine("[INIT] Connecting to postgres...");
|
||||
var builder = new DbContextOptionsBuilder<PostgresServerDbContext>();
|
||||
builder.UseNpgsql(connectionString);
|
||||
builder.UseNpgsql(config.DatabaseString);
|
||||
db = new PostgresServerDbContext(builder.Options);
|
||||
// await db.Database.MigrateAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
var relativePath = "FIX"; // Gross but whatever, I'm just testing
|
||||
Console.Out.WriteLine("[INIT] Connecting to sqlite...");
|
||||
var builder = new DbContextOptionsBuilder<SqliteServerDbContext>();
|
||||
builder.UseSqlite(new SqliteConnection($"Data Source={relativePath}"));
|
||||
builder.UseSqlite(new SqliteConnection(config.DatabaseString));
|
||||
db = new SqliteServerDbContext(builder.Options);
|
||||
}
|
||||
Console.Out.WriteLine("[INIT] Database connection successful.");
|
||||
|
||||
var interaction = new InteractionService(client);
|
||||
var handler = new CommandHandler(client, new CommandService(), interaction, db);
|
||||
var handler = new CommandHandler(client, new CommandService(), interaction, db, config);
|
||||
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Interlocked.Decrement(ref handler.Running);
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Content.DiscordBot
|
||||
|
||||
|
||||
### Configuration (Debug)
|
||||
* `DISCORD_TOKEN`: Discord application token provided @ `https://discord.com/developers/applications/<APP_ID>/bot`
|
||||
* `DATABASE_STRING`: Connection string to the database
|
||||
* For local development, you'll want it to be `Data Source=./bin/Content.Server/data/preferences.db` if you're using sqlite.
|
||||
* `DATABASE_CONTEXT`: Default is `postgres`. If testing locally with sqlite, use `sqlite`.
|
||||
* `GUILD`: The Discord Server ID. DeltaV's discord is `1513310351490289834`.
|
||||
* You can find this by turning Developer mode on in Discord, right-clicking on a server, and copying the server ID.
|
||||
|
||||
### Configuration (Production)
|
||||
Requires a `link-config.json` file in the working directory.
|
||||
```json
|
||||
{
|
||||
"Token": "DISCORD_BOT_TOKEN",
|
||||
"DatabaseString": "DB_CONNECTION_STRING"
|
||||
}
|
||||
```
|
||||
|
||||
Here's a quick bash command to create it in your current working directory. Windows users will have to fend for themselves.
|
||||
```bash
|
||||
cat << EOF > link-config.json
|
||||
{
|
||||
"Token": "DISCORD_BOT_TOKEN",
|
||||
"DatabaseString": "DB_CONNECTION_STRING"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
You can also override `Guild` and `DatabaseContext` if you wanted to by including those JSON properties.
|
||||
|
||||
Reference in New Issue
Block a user