diff --git a/PluralKit/Bot.cs b/PluralKit/Bot.cs index 02e12e63..c004900c 100644 --- a/PluralKit/Bot.cs +++ b/PluralKit/Bot.cs @@ -38,6 +38,7 @@ namespace PluralKit var connection = services.GetRequiredService() as NpgsqlConnection; connection.ConnectionString = Environment.GetEnvironmentVariable("PK_DATABASE_URI"); await connection.OpenAsync(); + await Schema.CreateTables(connection); Console.WriteLine("- Connecting to Discord..."); var client = services.GetRequiredService() as DiscordSocketClient; @@ -127,9 +128,9 @@ namespace PluralKit { // If it does, fetch the sender's system (because most commands need that) into the context, // and start command execution - var system = await _connection.QueryFirstAsync("select systems.* from systems, accounts where accounts.uid = @Id and systems.id = accounts.system", new { Id = arg.Author.Id }); - await _commands.ExecuteAsync(new PKCommandContext(_client, arg as SocketUserMessage, _connection, system), argPos, _services); - + // Note system may be null if user has no system, hence `OrDefault` + var system = await _connection.QueryFirstOrDefaultAsync("select systems.* from systems, accounts where accounts.uid = @Id and systems.id = accounts.system", new { Id = arg.Author.Id }); + await _commands.ExecuteAsync(new PKCommandContext(_client, arg as SocketUserMessage, _connection, system), argPos, _services); } else { diff --git a/PluralKit/Schema.cs b/PluralKit/Schema.cs new file mode 100644 index 00000000..7dbc2f01 --- /dev/null +++ b/PluralKit/Schema.cs @@ -0,0 +1,64 @@ +using System.Data; +using System.Threading.Tasks; +using Dapper; + +namespace PluralKit { + public static class Schema { + public static async Task CreateTables(IDbConnection connection) { + await connection.ExecuteAsync(@"create table if not exists systems ( + id serial primary key, + hid char(5) unique not null, + name text, + description text, + tag text, + avatar_url text, + token text, + created timestamp not null default (current_timestamp at time zone 'utc'), + ui_tz text not null default 'UTC' + )"); + await connection.ExecuteAsync(@"create table if not exists members ( + id serial primary key, + hid char(5) unique not null, + system serial not null references systems(id) on delete cascade, + color char(6), + avatar_url text, + name text not null, + birthday date, + pronouns text, + description text, + prefix text, + suffix text, + created timestamp not null default (current_timestamp at time zone 'utc') + )"); + await connection.ExecuteAsync(@"create table if not exists accounts ( + uid bigint primary key, + system serial not null references systems(id) on delete cascade + )"); + await connection.ExecuteAsync(@"create table if not exists messages ( + mid bigint primary key, + channel bigint not null, + member serial not null references members(id) on delete cascade, + sender bigint not null + )"); + await connection.ExecuteAsync(@"create table if not exists switches ( + id serial primary key, + system serial not null references systems(id) on delete cascade, + timestamp timestamp not null default (current_timestamp at time zone 'utc') + )"); + await connection.ExecuteAsync(@"create table if not exists switch_members ( + id serial primary key, + switch serial not null references switches(id) on delete cascade, + member serial not null references members(id) on delete cascade + )"); + await connection.ExecuteAsync(@"create table if not exists webhooks ( + channel bigint primary key, + webhook bigint not null, + token text not null + )"); + await connection.ExecuteAsync(@"create table if not exists servers ( + id bigint primary key, + log_channel bigint + )"); + } + } +} \ No newline at end of file