diff --git a/EntityCache/Module.cs b/EntityCache/Module.cs index d2cb8dd..2726237 100644 --- a/EntityCache/Module.cs +++ b/EntityCache/Module.cs @@ -2,9 +2,6 @@ using Newtonsoft.Json.Linq; using Noikoio.RegexBot.ConfigItem; using Npgsql; -using NpgsqlTypes; -using System; -using System.Collections.Generic; using System.Threading.Tasks; namespace Noikoio.RegexBot.EntityCache @@ -12,7 +9,7 @@ namespace Noikoio.RegexBot.EntityCache /// /// Bot module portion of the entity cache. Caches information regarding all known guilds, channels, and users. /// The function of this module should be transparent to the user, and thus no configuration is needed. - /// This module should be initialized BEFORE any other modules that make use of guild and user cache. + /// This module should be initialized BEFORE any other modules that make use of the entity cache. /// class Module : BotModule { @@ -26,7 +23,7 @@ namespace Noikoio.RegexBot.EntityCache if (_db.Available) { - SqlHelper.CreateCacheTables(); + SqlHelper.CreateCacheTablesAsync().Wait(); client.GuildAvailable += Client_GuildAvailable; client.GuildUpdated += Client_GuildUpdated; @@ -48,110 +45,66 @@ namespace Noikoio.RegexBot.EntityCache { await Task.Run(async () => { - await UpdateGuild(arg); - await UpdateGuildMember(arg.Users); - } - ); + try + { + await SqlHelper.UpdateGuildAsync(arg); + await SqlHelper.UpdateGuildMemberAsync(arg.Users); + } + catch (NpgsqlException ex) + { + await Log($"SQL error in {nameof(Client_GuildAvailable)}: {ex.Message}"); + } + }); } // Guild information has changed private async Task Client_GuildUpdated(SocketGuild arg1, SocketGuild arg2) { - await Task.Run(() => UpdateGuild(arg2)); + await Task.Run(async () => + { + try + { + await SqlHelper.UpdateGuildAsync(arg2); + } + catch (NpgsqlException ex) + { + await Log($"SQL error in {nameof(Client_GuildUpdated)}: {ex.Message}"); + } + }); } // Guild member information has changed private async Task Client_GuildMemberUpdated(SocketGuildUser arg1, SocketGuildUser arg2) { - await Task.Run(() => UpdateGuildMember(arg2)); + await Task.Run(async () => + { + try + { + await SqlHelper.UpdateGuildMemberAsync(arg2); + } + catch (NpgsqlException ex) + { + await Log($"SQL error in {nameof(Client_GuildMemberUpdated)}: {ex.Message}"); + } + }); } // A new guild member has appeared private async Task Client_UserJoined(SocketGuildUser arg) { - await UpdateGuildMember(arg); + await Task.Run(async () => + { + try + { + await SqlHelper.UpdateGuildMemberAsync(arg); + } + catch (NpgsqlException ex) + { + await Log($"SQL error in {nameof(Client_UserJoined)}: {ex.Message}"); + } + }); } #endregion - - private async Task UpdateGuild(SocketGuild g) - { - try - { - using (var db = await _db.GetOpenConnectionAsync()) - { - using (var c = db.CreateCommand()) - { - c.CommandText = "INSERT INTO " + Sql.TableGuild + " (guild_id, current_name) " - + "VALUES (@GuildId, @CurrentName) " - + "ON CONFLICT (guild_id) DO UPDATE SET " - + "current_name = EXCLUDED.current_name"; - c.Parameters.Add("@GuildId", NpgsqlDbType.Bigint).Value = g.Id; - c.Parameters.Add("@CurrentName", NpgsqlDbType.Text).Value = g.Name; - c.Prepare(); - await c.ExecuteNonQueryAsync(); - } - } - } - catch (NpgsqlException ex) - { - await Log($"SQL error in {nameof(UpdateGuild)}: " + ex.Message); - } - } - - private async Task UpdateGuildMember(IEnumerable users) - { - try - { - using (var db = await _db.GetOpenConnectionAsync()) - { - using (var c = db.CreateCommand()) - { - c.CommandText = "INSERT INTO " + Sql.TableUser - + " (user_id, guild_id, cache_date, username, discriminator, nickname, avatar_url)" - + " VALUES (@Uid, @Gid, @Date, @Uname, @Disc, @Nname, @Url) " - + "ON CONFLICT (user_id, guild_id) DO UPDATE SET " - + "cache_date = EXCLUDED.cache_date, username = EXCLUDED.username, " - + "discriminator = EXCLUDED.discriminator, " // I've seen someone's discriminator change this one time... - + "nickname = EXCLUDED.nickname, avatar_url = EXCLUDED.avatar_url"; - - var uid = c.Parameters.Add("@Uid", NpgsqlDbType.Bigint); - var gid = c.Parameters.Add("@Gid", NpgsqlDbType.Bigint); - c.Parameters.Add("@Date", NpgsqlDbType.TimestampTZ).Value = DateTime.Now; - var uname = c.Parameters.Add("@Uname", NpgsqlDbType.Text); - var disc = c.Parameters.Add("@Disc", NpgsqlDbType.Text); - var nname = c.Parameters.Add("@Nname", NpgsqlDbType.Text); - var url = c.Parameters.Add("@Url", NpgsqlDbType.Text); - c.Prepare(); - - foreach (var item in users) - { - if (item.IsBot || item.IsWebhook) continue; - - uid.Value = item.Id; - gid.Value = item.Guild.Id; - uname.Value = item.Username; - disc.Value = item.Discriminator; - nname.Value = item.Nickname; - if (nname.Value == null) nname.Value = DBNull.Value; // why can't ?? work here? - url.Value = item.GetAvatarUrl(); - if (url.Value == null) url.Value = DBNull.Value; - - await c.ExecuteNonQueryAsync(); - } - } - } - } - catch (NpgsqlException ex) - { - await Log($"SQL error in {nameof(UpdateGuildMember)}: " + ex.Message); - } - } - - private Task UpdateGuildMember(SocketGuildUser user) - { - var gid = user.Guild.Id; - var ml = new SocketGuildUser[] { user }; - return UpdateGuildMember(ml); - } + } } diff --git a/EntityCache/SqlHelper.cs b/EntityCache/SqlHelper.cs index 39d3270..c68a8e7 100644 --- a/EntityCache/SqlHelper.cs +++ b/EntityCache/SqlHelper.cs @@ -1,13 +1,15 @@ -using Npgsql; +using Discord.WebSocket; +using Npgsql; +using NpgsqlTypes; using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace Noikoio.RegexBot.EntityCache { /// /// Helper methods for database operations. + /// Exceptions are not handled within methods of this class. /// static class SqlHelper { @@ -21,7 +23,7 @@ namespace Noikoio.RegexBot.EntityCache return await RegexBot.Config.Database.GetOpenConnectionAsync(); } - public static async Task CreateCacheTables() + internal static async Task CreateCacheTablesAsync() { var db = await OpenDB(); if (db == null) return; @@ -84,13 +86,72 @@ namespace Noikoio.RegexBot.EntityCache } #region Insertions and updates - static async Task UpdateGuild() + internal static async Task UpdateGuildAsync(SocketGuild g) { var db = await OpenDB(); if (db == null) return; using (db) { + using (var c = db.CreateCommand()) + { + c.CommandText = "INSERT INTO " + Sql.TableGuild + " (guild_id, current_name) " + + "VALUES (@GuildId, @CurrentName) " + + "ON CONFLICT (guild_id) DO UPDATE SET " + + "current_name = EXCLUDED.current_name"; + c.Parameters.Add("@GuildId", NpgsqlDbType.Bigint).Value = g.Id; + c.Parameters.Add("@CurrentName", NpgsqlDbType.Text).Value = g.Name; + c.Prepare(); + await c.ExecuteNonQueryAsync(); + } + } + } + internal static Task UpdateGuildMemberAsync(SocketGuildUser user) + { + var ml = new SocketGuildUser[] { user }; + return UpdateGuildMemberAsync(ml); + } + internal static async Task UpdateGuildMemberAsync(IEnumerable users) + { + var db = await OpenDB(); + if (db == null) return; + using (db) + { + using (var c = db.CreateCommand()) + { + c.CommandText = "INSERT INTO " + Sql.TableUser + + " (user_id, guild_id, cache_date, username, discriminator, nickname, avatar_url)" + + " VALUES (@Uid, @Gid, @Date, @Uname, @Disc, @Nname, @Url) " + + "ON CONFLICT (user_id, guild_id) DO UPDATE SET " + + "cache_date = EXCLUDED.cache_date, username = EXCLUDED.username, " + + "discriminator = EXCLUDED.discriminator, " // I've seen someone's discriminator change this one time... + + "nickname = EXCLUDED.nickname, avatar_url = EXCLUDED.avatar_url"; + + var uid = c.Parameters.Add("@Uid", NpgsqlDbType.Bigint); + var gid = c.Parameters.Add("@Gid", NpgsqlDbType.Bigint); + c.Parameters.Add("@Date", NpgsqlDbType.TimestampTZ).Value = DateTime.Now; + var uname = c.Parameters.Add("@Uname", NpgsqlDbType.Text); + var disc = c.Parameters.Add("@Disc", NpgsqlDbType.Text); + var nname = c.Parameters.Add("@Nname", NpgsqlDbType.Text); + var url = c.Parameters.Add("@Url", NpgsqlDbType.Text); + c.Prepare(); + + foreach (var item in users) + { + if (item.IsBot || item.IsWebhook) continue; + + uid.Value = item.Id; + gid.Value = item.Guild.Id; + uname.Value = item.Username; + disc.Value = item.Discriminator; + nname.Value = item.Nickname; + if (nname.Value == null) nname.Value = DBNull.Value; // why can't ?? work here? + url.Value = item.GetAvatarUrl(); + if (url.Value == null) url.Value = DBNull.Value; + + await c.ExecuteNonQueryAsync(); + } + } } } #endregion