Add super basic group model/command

This commit is contained in:
Ske
2020-06-29 23:51:12 +02:00
parent 0fadc81cda
commit 253ae43c7f
15 changed files with 199 additions and 2 deletions

View File

@@ -20,7 +20,7 @@ namespace PluralKit.Core
internal class Database: IDatabase
{
private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
private const int TargetSchemaVersion = 8;
private const int TargetSchemaVersion = 9;
private readonly CoreConfig _config;
private readonly ILogger _logger;
@@ -58,9 +58,11 @@ namespace PluralKit.Core
SqlMapper.AddTypeHandler(new NumericIdHandler<SystemId, int>(i => new SystemId(i)));
SqlMapper.AddTypeHandler(new NumericIdHandler<MemberId, int>(i => new MemberId(i)));
SqlMapper.AddTypeHandler(new NumericIdHandler<SwitchId, int>(i => new SwitchId(i)));
SqlMapper.AddTypeHandler(new NumericIdHandler<GroupId, int>(i => new GroupId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<SystemId, int>(i => new SystemId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<MemberId, int>(i => new MemberId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<SwitchId, int>(i => new SwitchId(i)));
SqlMapper.AddTypeHandler(new NumericIdArrayHandler<GroupId, int>(i => new GroupId(i)));
// Register our custom types to Npgsql
// Without these it'll still *work* but break at the first launch + probably cause other small issues

View File

@@ -111,4 +111,14 @@ begin
if not exists (select 1 from members where hid = new_hid) then return new_hid; end if;
end loop;
end
$$ language plpgsql volatile;
create function find_free_group_hid() returns char(5) as $$
declare new_hid char(5);
begin
loop
new_hid := generate_hid();
if not exists (select 1 from groups where hid = new_hid) then return new_hid; end if;
end loop;
end
$$ language plpgsql volatile;

View File

@@ -0,0 +1,17 @@
-- SCHEMA VERSION 9: 2020-xx-xx --
create table groups (
id int primary key generated always as identity,
hid char(5) unique not null,
system int not null references systems(id) on delete cascade,
name text not null,
description text,
created timestamp with time zone not null default (current_timestamp at time zone 'utc')
);
create table group_members (
group_id int not null references groups(id) on delete cascade,
member_id int not null references members(id) on delete cascade
);
update info set schema_version = 9;

View File

@@ -10,4 +10,5 @@ drop function if exists message_context;
drop function if exists proxy_members;
drop function if exists generate_hid;
drop function if exists find_free_system_hid;
drop function if exists find_free_member_hid;
drop function if exists find_free_member_hid;
drop function if exists find_free_group_hid;

View File

@@ -0,0 +1,26 @@
namespace PluralKit.Core
{
public readonly struct GroupId: INumericId<GroupId, int>
{
public int Value { get; }
public GroupId(int value)
{
Value = value;
}
public bool Equals(GroupId other) => Value == other.Value;
public override bool Equals(object obj) => obj is GroupId other && Equals(other);
public override int GetHashCode() => Value;
public static bool operator ==(GroupId left, GroupId right) => left.Equals(right);
public static bool operator !=(GroupId left, GroupId right) => !left.Equals(right);
public int CompareTo(GroupId other) => Value.CompareTo(other.Value);
public override string ToString() => $"Member #{Value}";
}
}

View File

@@ -29,6 +29,12 @@ namespace PluralKit.Core
public static Task<PKMember?> QueryMemberByHid(this IPKConnection conn, string hid) =>
conn.QueryFirstOrDefaultAsync<PKMember?>("select * from members where hid = @hid", new {hid = hid.ToLowerInvariant()});
public static Task<PKGroup?> QueryGroupByName(this IPKConnection conn, string name) =>
conn.QueryFirstOrDefaultAsync<PKGroup?>("select * from groups where lower(name) = lower(@name)", new {name = name});
public static Task<PKGroup?> QueryGroupByHid(this IPKConnection conn, string hid) =>
conn.QueryFirstOrDefaultAsync<PKGroup?>("select * from groups where hid = @hid", new {hid = hid.ToLowerInvariant()});
public static Task<GuildConfig> QueryOrInsertGuildConfig(this IPKConnection conn, ulong guild) =>
conn.QueryFirstAsync<GuildConfig>("insert into servers (id) values (@guild) on conflict (id) do update set id = @guild returning *", new {guild});

View File

@@ -0,0 +1,17 @@
using NodaTime;
#nullable enable
namespace PluralKit.Core
{
public class PKGroup
{
public GroupId Id { get; }
public string Hid { get; } = null!;
public SystemId System { get; }
public string Name { get; } = null!;
public string? Description { get; }
public Instant Created { get; }
}
}

View File

@@ -0,0 +1,13 @@
#nullable enable
namespace PluralKit.Core
{
public class GroupPatch: PatchObject
{
public Partial<string> Name { get; set; }
public Partial<string?> Description { get; set; }
public override UpdateQueryBuilder Apply(UpdateQueryBuilder b) => b
.With("name", Name)
.With("description", Description);
}
}

View File

@@ -60,5 +60,10 @@ namespace PluralKit.Core
.Build();
return conn.ExecuteAsync(query, pms);
}
public static Task<PKGroup> CreateGroup(this IPKConnection conn, SystemId system, string name) =>
conn.QueryFirstAsync<PKGroup>(
"insert into groups (hid, system, name) values (find_free_group_hid(), @System, @Name) returning *",
new {System = system, Name = name});
}
}

View File

@@ -9,6 +9,7 @@ namespace PluralKit.Core {
public static readonly int MaxMembersWarnThreshold = MaxMemberCount - 50;
public static readonly int MaxDescriptionLength = 1000;
public static readonly int MaxMemberNameLength = 100; // Fair bit larger than MaxProxyNameLength for bookkeeping
public static readonly int MaxGroupNameLength = 100;
public static readonly int MaxPronounsLength = 100;
public static readonly int MaxUriLength = 256; // May need to be set higher, I know there are URLs longer than this in prod (they can rehost, I guess...)
public static readonly long AvatarFileSizeLimit = 1024 * 1024;