refactor: change ulong[] to List<ulong> for better ergonomics

This commit is contained in:
sam 2024-11-18 21:01:52 +01:00
parent e12bd6194b
commit 4eb5c16451
Signed by: sam
GPG key ID: 5F3C3C1B3166639D
8 changed files with 37 additions and 46 deletions

View file

@ -116,7 +116,7 @@ public partial class GuildsController
if (channel == null) if (channel == null)
return NoContent(); return NoContent();
guildConfig.IgnoredChannels = [.. guildConfig.IgnoredChannels, channelId]; guildConfig.IgnoredChannels.Add(channelId);
await guildRepository.UpdateConfigAsync(guildId, guildConfig); await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();
@ -128,9 +128,7 @@ public partial class GuildsController
var (guildId, _) = await ParseGuildAsync(id); var (guildId, _) = await ParseGuildAsync(id);
var guildConfig = await guildRepository.GetAsync(guildId); var guildConfig = await guildRepository.GetAsync(guildId);
var channels = guildConfig.IgnoredChannels.ToList(); guildConfig.IgnoredChannels.Remove(channelId);
channels.Remove(channelId);
guildConfig.IgnoredChannels = channels.ToArray();
await guildRepository.UpdateConfigAsync(guildId, guildConfig); await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();
@ -148,7 +146,7 @@ public partial class GuildsController
if (roleCache.GuildRoles(guildId).All(r => r.ID.Value != roleId)) if (roleCache.GuildRoles(guildId).All(r => r.ID.Value != roleId))
return NoContent(); return NoContent();
guildConfig.IgnoredRoles = [.. guildConfig.IgnoredRoles, roleId]; guildConfig.IgnoredRoles.Add(roleId);
await guildRepository.UpdateConfigAsync(guildId, guildConfig); await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();
@ -160,9 +158,7 @@ public partial class GuildsController
var (guildId, _) = await ParseGuildAsync(id); var (guildId, _) = await ParseGuildAsync(id);
var guildConfig = await guildRepository.GetAsync(guildId); var guildConfig = await guildRepository.GetAsync(guildId);
var roles = guildConfig.IgnoredRoles.ToList(); guildConfig.IgnoredRoles.Remove(roleId);
roles.Remove(roleId);
guildConfig.IgnoredRoles = roles.ToArray();
await guildRepository.UpdateConfigAsync(guildId, guildConfig); await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();

View file

@ -38,7 +38,8 @@ public partial class GuildsController
"Role is already a key role" "Role is already a key role"
); );
await guildRepository.AddKeyRoleAsync(guildId, DiscordSnowflake.New(roleId)); guildConfig.KeyRoles.Add(roleId);
await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();
} }
@ -55,7 +56,8 @@ public partial class GuildsController
"Role is already not a key role" "Role is already not a key role"
); );
await guildRepository.RemoveKeyRoleAsync(guildId, DiscordSnowflake.New(roleId)); guildConfig.KeyRoles.Remove(roleId);
await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return NoContent(); return NoContent();
} }
} }

View file

@ -140,11 +140,11 @@ public partial class GuildsController(
IEnumerable<GuildCategory> Categories, IEnumerable<GuildCategory> Categories,
IEnumerable<GuildChannel> ChannelsWithoutCategory, IEnumerable<GuildChannel> ChannelsWithoutCategory,
IEnumerable<GuildRole> Roles, IEnumerable<GuildRole> Roles,
ulong[] IgnoredChannels, List<ulong> IgnoredChannels,
ulong[] IgnoredRoles, List<ulong> IgnoredRoles,
Database.Models.Guild.MessageConfig Messages, Database.Models.Guild.MessageConfig Messages,
Database.Models.Guild.ChannelConfig Channels, Database.Models.Guild.ChannelConfig Channels,
ulong[] KeyRoles List<ulong> KeyRoles
); );
private record GuildCategory(string Id, string Name, IEnumerable<GuildChannel> Channels); private record GuildCategory(string Id, string Name, IEnumerable<GuildChannel> Channels);

View file

@ -49,7 +49,7 @@ public class KeyRoleCommands(
var guildRoles = roleCache.GuildRoles(guildId).ToList(); var guildRoles = roleCache.GuildRoles(guildId).ToList();
var guildConfig = await guildRepository.GetAsync(guildId); var guildConfig = await guildRepository.GetAsync(guildId);
if (guildConfig.KeyRoles.Length == 0) if (guildConfig.KeyRoles.Count == 0)
return await feedbackService.ReplyAsync( return await feedbackService.ReplyAsync(
"There are no key roles to list. Add some with `/key-roles add`.", "There are no key roles to list. Add some with `/key-roles add`.",
isEphemeral: true isEphemeral: true
@ -94,7 +94,8 @@ public class KeyRoleCommands(
isEphemeral: true isEphemeral: true
); );
await guildRepository.AddKeyRoleAsync(guildId, role.ID); guildConfig.KeyRoles.Add(role.ID.Value);
await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return await feedbackService.ReplyAsync($"Added {role.Name} to this server's key roles!"); return await feedbackService.ReplyAsync($"Added {role.Name} to this server's key roles!");
} }
@ -119,7 +120,8 @@ public class KeyRoleCommands(
isEphemeral: true isEphemeral: true
); );
await guildRepository.RemoveKeyRoleAsync(guildId, role.ID); guildConfig.KeyRoles.Remove(role.ID.Value);
await guildRepository.UpdateConfigAsync(guildId, guildConfig);
return await feedbackService.ReplyAsync( return await feedbackService.ReplyAsync(
$"Removed {role.Name} from this server's key roles!" $"Removed {role.Name} from this server's key roles!"
); );

View file

@ -112,11 +112,12 @@ public class DatabasePool
SqlMapper.RemoveTypeMap(typeof(ulong)); SqlMapper.RemoveTypeMap(typeof(ulong));
SqlMapper.AddTypeHandler(new UlongEncodeAsLongHandler()); SqlMapper.AddTypeHandler(new UlongEncodeAsLongHandler());
SqlMapper.AddTypeHandler(new UlongArrayHandler());
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>()); SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>());
SqlMapper.AddTypeHandler(new JsonTypeHandler<Guild.ChannelConfig>()); SqlMapper.AddTypeHandler(new JsonTypeHandler<Guild.ChannelConfig>());
SqlMapper.AddTypeHandler(new JsonTypeHandler<Guild.MessageConfig>()); SqlMapper.AddTypeHandler(new JsonTypeHandler<Guild.MessageConfig>());
SqlMapper.AddTypeHandler(new UlongListHandler());
} }
// Copied from PluralKit: // Copied from PluralKit:
@ -132,34 +133,34 @@ public class DatabasePool
private class UlongEncodeAsLongHandler : SqlMapper.TypeHandler<ulong> private class UlongEncodeAsLongHandler : SqlMapper.TypeHandler<ulong>
{ {
public override void SetValue(IDbDataParameter parameter, ulong value) =>
parameter.Value = (long)value;
public override ulong Parse(object value) => public override ulong Parse(object value) =>
// Cast to long to unbox, then to ulong (???) // Cast to long to unbox, then to ulong (???)
(ulong)(long)value; (ulong)(long)value;
public override void SetValue(IDbDataParameter parameter, ulong value) =>
parameter.Value = (long)value;
} }
private class UlongArrayHandler : SqlMapper.TypeHandler<ulong[]> private class UlongListHandler : SqlMapper.TypeHandler<List<ulong>>
{ {
public override void SetValue(IDbDataParameter parameter, ulong[]? value) => public override void SetValue(IDbDataParameter parameter, List<ulong>? value) =>
parameter.Value = value != null ? Array.ConvertAll(value, i => (long)i) : null; parameter.Value = value?.Select(i => (long)i).ToArray();
public override ulong[] Parse(object value) => public override List<ulong>? Parse(object value) =>
Array.ConvertAll((long[])value, i => (ulong)i); ((long[])value).Select(i => (ulong)i).ToList();
} }
private class JsonTypeHandler<T> : SqlMapper.TypeHandler<T> private class JsonTypeHandler<T> : SqlMapper.TypeHandler<T>
{ {
public override void SetValue(IDbDataParameter parameter, T? value) =>
parameter.Value = JsonSerializer.Serialize(value);
public override T Parse(object value) public override T Parse(object value)
{ {
var json = (string)value; var json = (string)value;
return JsonSerializer.Deserialize<T>(json) return JsonSerializer.Deserialize<T>(json)
?? throw new CataloggerError("JsonTypeHandler<T> returned null"); ?? throw new CataloggerError("JsonTypeHandler<T> returned null");
} }
public override void SetValue(IDbDataParameter parameter, T? value) =>
parameter.Value = JsonSerializer.Serialize(value);
} }
} }

View file

@ -6,7 +6,7 @@ public record ConfigExport(
ulong Id, ulong Id,
ChannelsBackup Channels, ChannelsBackup Channels,
string[] BannedSystems, string[] BannedSystems,
ulong[] KeyRoles, List<ulong> KeyRoles,
IEnumerable<InviteExport> Invites, IEnumerable<InviteExport> Invites,
IEnumerable<WatchlistExport> Watchlist IEnumerable<WatchlistExport> Watchlist
); );

View file

@ -26,11 +26,11 @@ public class Guild
public ChannelConfig Channels { get; init; } = new(); public ChannelConfig Channels { get; init; } = new();
public MessageConfig Messages { get; init; } = new(); public MessageConfig Messages { get; init; } = new();
public string[] BannedSystems { get; set; } = []; public string[] BannedSystems { get; set; } = [];
public ulong[] KeyRoles { get; set; } = []; public List<ulong> KeyRoles { get; set; } = [];
// These channels and roles are ignored for channel/role update/delete events. // These channels and roles are ignored for channel/role update/delete events.
public ulong[] IgnoredChannels { get; set; } = []; public List<ulong> IgnoredChannels { get; set; } = [];
public ulong[] IgnoredRoles { get; set; } = []; public List<ulong> IgnoredRoles { get; set; } = [];
public bool IsSystemBanned(PluralkitApiService.PkSystem system) => public bool IsSystemBanned(PluralkitApiService.PkSystem system) =>
BannedSystems.Contains(system.Id) || BannedSystems.Contains(system.Uuid.ToString()); BannedSystems.Contains(system.Id) || BannedSystems.Contains(system.Uuid.ToString());

View file

@ -119,25 +119,14 @@ public class GuildRepository(ILogger logger, DatabaseConnection conn)
private record BannedSystem(Guid SystemId, ulong UserId, ulong GuildId); private record BannedSystem(Guid SystemId, ulong UserId, ulong GuildId);
public async Task AddKeyRoleAsync(Snowflake guildId, Snowflake roleId) =>
await conn.ExecuteAsync(
"update guilds set key_roles = array_append(key_roles, @RoleId) where id = @GuildId",
new { GuildId = guildId.Value, RoleId = roleId.Value }
);
public async Task RemoveKeyRoleAsync(Snowflake guildId, Snowflake roleId) =>
await conn.ExecuteAsync(
"update guilds set key_roles = array_remove(key_roles, @RoleId) where id = @GuildId",
new { GuildId = guildId.Value, RoleId = roleId.Value }
);
public async Task UpdateConfigAsync(Snowflake id, Guild config) => public async Task UpdateConfigAsync(Snowflake id, Guild config) =>
await conn.ExecuteAsync( await conn.ExecuteAsync(
""" """
update guilds set channels = @Channels::jsonb, update guilds set channels = @Channels::jsonb,
messages = @Messages::jsonb, messages = @Messages::jsonb,
ignored_channels = @IgnoredChannels, ignored_channels = @IgnoredChannels,
ignored_roles = @IgnoredRoles ignored_roles = @IgnoredRoles,
key_roles = @KeyRoles
where id = @Id where id = @Id
""", """,
new new
@ -147,6 +136,7 @@ public class GuildRepository(ILogger logger, DatabaseConnection conn)
config.Messages, config.Messages,
config.IgnoredChannels, config.IgnoredChannels,
config.IgnoredRoles, config.IgnoredRoles,
config.KeyRoles,
} }
); );
@ -155,7 +145,7 @@ public class GuildRepository(ILogger logger, DatabaseConnection conn)
Guild.ChannelConfig channels, Guild.ChannelConfig channels,
Guild.MessageConfig messages, Guild.MessageConfig messages,
string[] bannedSystems, string[] bannedSystems,
ulong[] keyRoles List<ulong> keyRoles
) => ) =>
await conn.ExecuteAsync( await conn.ExecuteAsync(
"update guilds set channels = @channels::jsonb, messages = @messages::jsonb, banned_systems = @bannedSystems, key_roles = @keyRoles where id = @id", "update guilds set channels = @channels::jsonb, messages = @messages::jsonb, banned_systems = @bannedSystems, key_roles = @keyRoles where id = @id",