Various small fixes, setting guild config now works
This commit is contained in:
		| @@ -86,7 +86,7 @@ namespace PluralKit.API | ||||
|         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | ||||
|         public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||||
|         { | ||||
|             Schemas.Initialize(); | ||||
|             Database.InitStatic(); | ||||
|  | ||||
|             if (env.IsDevelopment()) | ||||
|             { | ||||
|   | ||||
| @@ -67,7 +67,7 @@ namespace PluralKit.Bot | ||||
|                 else | ||||
|                     blacklist.UnionWith(affectedChannels.Select(c => c.Id)); | ||||
|                 await conn.ExecuteAsync("update servers set log_blacklist = @LogBlacklist where id = @Id", | ||||
|                     new {ctx.Guild.Id, LogBlacklist = blacklist}); | ||||
|                     new {ctx.Guild.Id, LogBlacklist = blacklist.ToArray()}); | ||||
|             } | ||||
|  | ||||
|             await ctx.Reply( | ||||
| @@ -99,7 +99,7 @@ namespace PluralKit.Bot | ||||
|                 else | ||||
|                     blacklist.UnionWith(affectedChannels.Select(c => c.Id)); | ||||
|                 await conn.ExecuteAsync("update servers set blacklist = @Blacklist where id = @Id", | ||||
|                     new {ctx.Guild.Id, Blacklist = blacklist}); | ||||
|                     new {ctx.Guild.Id, Blacklist = blacklist.ToArray()}); | ||||
|             } | ||||
|  | ||||
|             await ctx.Reply($"{Emojis.Success} Channels {(onBlacklist ? "added to" : "removed from")} the proxy blacklist."); | ||||
|   | ||||
| @@ -21,7 +21,7 @@ namespace PluralKit.Bot | ||||
|         { | ||||
|             // Load configuration and run global init stuff | ||||
|             var config = InitUtils.BuildConfiguration(args).Build(); | ||||
|             InitUtils.Init(); | ||||
|             Database.InitStatic(); | ||||
|              | ||||
|             // Set up DI container and modules | ||||
|             var services = BuildContainer(config); | ||||
|   | ||||
| @@ -1,8 +1,13 @@ | ||||
| using System; | ||||
| using System.Data; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| using App.Metrics; | ||||
|  | ||||
| using Dapper; | ||||
|  | ||||
| using NodaTime; | ||||
|  | ||||
| using Npgsql; | ||||
|  | ||||
| using Serilog; | ||||
| @@ -24,6 +29,29 @@ namespace PluralKit.Core | ||||
|             _metrics = metrics; | ||||
|             _logger = logger; | ||||
|         } | ||||
|          | ||||
|         public static void InitStatic() | ||||
|         { | ||||
|             // Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically | ||||
|             // doesn't support unsigned types on its own. | ||||
|             // Instead we add a custom mapper to encode them as signed integers instead, converting them back and forth. | ||||
|             SqlMapper.RemoveTypeMap(typeof(ulong)); | ||||
|             SqlMapper.AddTypeHandler(new UlongEncodeAsLongHandler()); | ||||
|             SqlMapper.AddTypeHandler(new UlongArrayHandler()); | ||||
|             DefaultTypeMap.MatchNamesWithUnderscores = true; | ||||
|  | ||||
|             NpgsqlConnection.GlobalTypeMapper.UseNodaTime(); | ||||
|             // With the thing we add above, Npgsql already handles NodaTime integration | ||||
|             // This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types | ||||
|             // So we add a custom type handler that literally just passes the type through to Npgsql | ||||
|             SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>()); | ||||
|             SqlMapper.AddTypeHandler(new PassthroughTypeHandler<LocalDate>()); | ||||
|              | ||||
|             // Register our custom types to Npgsql | ||||
|             // Without these it'll still *work* but break at the first launch + probably cause other small issues | ||||
|             NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag"); | ||||
|             NpgsqlConnection.GlobalTypeMapper.MapEnum<PrivacyLevel>("privacy_level"); | ||||
|         } | ||||
|  | ||||
|         public async Task<IPKConnection> Obtain() | ||||
|         { | ||||
| @@ -48,5 +76,27 @@ namespace PluralKit.Core | ||||
|             await using var conn = await Obtain(); | ||||
|             return await func(conn); | ||||
|         } | ||||
|  | ||||
|         private class PassthroughTypeHandler<T>: SqlMapper.TypeHandler<T> | ||||
|         { | ||||
|             public override void SetValue(IDbDataParameter parameter, T value) => parameter.Value = value; | ||||
|             public override T Parse(object value) => (T) value; | ||||
|         } | ||||
|  | ||||
|         private class UlongEncodeAsLongHandler: SqlMapper.TypeHandler<ulong> | ||||
|         { | ||||
|             public override ulong Parse(object value) => | ||||
|                 // Cast to long to unbox, then to ulong (???) | ||||
|                 (ulong) (long) value; | ||||
|  | ||||
|             public override void SetValue(IDbDataParameter parameter, ulong value) => parameter.Value = (long) value; | ||||
|         } | ||||
|  | ||||
|         private class UlongArrayHandler: SqlMapper.TypeHandler<ulong[]> | ||||
|         { | ||||
|             public override void SetValue(IDbDataParameter parameter, ulong[] value) => parameter.Value = Array.ConvertAll(value, i => (long) i); | ||||
|  | ||||
|             public override ulong[] Parse(object value) => Array.ConvertAll((long[]) value, i => (ulong) i); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -25,13 +25,6 @@ namespace PluralKit.Core | ||||
|             _logger = logger.ForContext<Schemas>(); | ||||
|         } | ||||
|  | ||||
|         public static void Initialize() | ||||
|         { | ||||
|             // Without these it'll still *work* but break at the first launch + probably cause other small issues | ||||
|             NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag"); | ||||
|             NpgsqlConnection.GlobalTypeMapper.MapEnum<PrivacyLevel>("privacy_level"); | ||||
|         } | ||||
|  | ||||
|         public async Task InitializeDatabase() | ||||
|         { | ||||
|             // Run everything in a transaction | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| { | ||||
|     public class GuildConfig | ||||
|     { | ||||
|         public int Id { get; } | ||||
|         public ulong Id { get; } | ||||
|         public ulong? LogChannel { get; } | ||||
|         public ulong[] LogBlacklist { get; } | ||||
|         public ulong[] Blacklist { get; } | ||||
|   | ||||
| @@ -12,7 +12,7 @@ namespace PluralKit.Core | ||||
|             conn.QueryFirstOrDefaultAsync<PKMember?>("select * from members where id = @id", new {id}); | ||||
|          | ||||
|         public static Task<GuildConfig> QueryOrInsertGuildConfig(this IPKConnection conn, ulong guild) => | ||||
|             conn.QueryFirstAsync<GuildConfig>("insert into servers (id) values (@Guild) on conflict do nothing returning *", new {Guild = guild}); | ||||
|             conn.QueryFirstAsync<GuildConfig>("insert into servers (id) values (@guild) on conflict (id) do update set id = @guild returning *", new {guild}); | ||||
|  | ||||
|         public static Task<SystemGuildSettings> QueryOrInsertSystemGuildConfig(this IPKConnection conn, ulong guild, int system) => | ||||
|             conn.QueryFirstAsync<SystemGuildSettings>( | ||||
|   | ||||
| @@ -20,31 +20,4 @@ namespace PluralKit.Core | ||||
|             Interlocked.Decrement(ref _connectionCount); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public class PassthroughTypeHandler<T>: SqlMapper.TypeHandler<T> | ||||
|     { | ||||
|         public override void SetValue(IDbDataParameter parameter, T value) | ||||
|         { | ||||
|             parameter.Value = value; | ||||
|         } | ||||
|  | ||||
|         public override T Parse(object value) | ||||
|         { | ||||
|             return (T) value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public class UlongEncodeAsLongHandler: SqlMapper.TypeHandler<ulong> | ||||
|     { | ||||
|         public override ulong Parse(object value) | ||||
|         { | ||||
|             // Cast to long to unbox, then to ulong (???) | ||||
|             return (ulong) (long) value; | ||||
|         } | ||||
|  | ||||
|         public override void SetValue(IDbDataParameter parameter, ulong value) | ||||
|         { | ||||
|             parameter.Value = (long) value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,5 @@ | ||||
| using System.IO; | ||||
|  | ||||
| using Dapper; | ||||
|  | ||||
| using Microsoft.Extensions.Configuration; | ||||
|  | ||||
| using Newtonsoft.Json; | ||||
| @@ -9,8 +7,6 @@ using Newtonsoft.Json; | ||||
| using NodaTime; | ||||
| using NodaTime.Serialization.JsonNet; | ||||
|  | ||||
| using Npgsql; | ||||
|  | ||||
| namespace PluralKit.Core { | ||||
|     public static class InitUtils | ||||
|     { | ||||
| @@ -19,32 +15,6 @@ namespace PluralKit.Core { | ||||
|             .AddJsonFile("pluralkit.conf", true) | ||||
|             .AddEnvironmentVariables() | ||||
|             .AddCommandLine(args); | ||||
|  | ||||
|         public static void Init() | ||||
|         { | ||||
|             InitDatabase(); | ||||
|         } | ||||
|          | ||||
|         private static void InitDatabase() | ||||
|         { | ||||
|             // Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically | ||||
|             // doesn't support unsigned types on its own. | ||||
|             // Instead we add a custom mapper to encode them as signed integers instead, converting them back and forth. | ||||
|             SqlMapper.RemoveTypeMap(typeof(ulong)); | ||||
|             SqlMapper.AddTypeHandler<ulong>(new UlongEncodeAsLongHandler()); | ||||
|             Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; | ||||
|  | ||||
|             // Also, use NodaTime. it's good. | ||||
|             NpgsqlConnection.GlobalTypeMapper.UseNodaTime(); | ||||
|             // With the thing we add above, Npgsql already handles NodaTime integration | ||||
|             // This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types | ||||
|             // So we add a custom type handler that literally just passes the type through to Npgsql | ||||
|             SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>()); | ||||
|             SqlMapper.AddTypeHandler(new PassthroughTypeHandler<LocalDate>()); | ||||
|  | ||||
|             // Add global type mapper for ProxyTag compound type in Postgres | ||||
|             NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag"); | ||||
|         } | ||||
|          | ||||
|         public static JsonSerializerSettings BuildSerializerSettings() => new JsonSerializerSettings().BuildSerializerSettings(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user