From 2e4c7c1510ef0cb0435f49f50a87524820860409 Mon Sep 17 00:00:00 2001 From: Pythonic-Rainbow Date: Thu, 19 Sep 2024 23:58:24 +0800 Subject: [PATCH] [Bot] Completed db pattern redesign --- Bot/Clash/Coc.cs | 2 +- Bot/Clash/Phaser.cs | 4 ++-- Bot/Discord/Cmds.cs | 8 +++---- Bot/Discord/MemberConverter.cs | 4 ++-- Bot/Program.cs | 2 +- Bot/Sql/Alias.cs | 15 ------------- Bot/Sql/Alt.cs | 10 ++++----- Bot/Sql/BotAdmin.cs | 2 +- Bot/Sql/CocAlias.cs | 27 ++++++++++++++++++++++ Bot/Sql/Db.cs | 41 +++++++++++++++++++++------------- Bot/Sql/DbObj.cs | 32 -------------------------- Bot/Sql/Main.cs | 7 +++--- Bot/Sql/Member.cs | 6 ++--- 13 files changed, 72 insertions(+), 88 deletions(-) delete mode 100644 Bot/Sql/Alias.cs create mode 100644 Bot/Sql/CocAlias.cs delete mode 100644 Bot/Sql/DbObj.cs diff --git a/Bot/Clash/Coc.cs b/Bot/Clash/Coc.cs index a48b054..42bf0c6 100644 --- a/Bot/Clash/Coc.cs +++ b/Bot/Clash/Coc.cs @@ -41,7 +41,7 @@ private static void CheckMembersJoined(ClanUtil clan) string[] members = [.. clan._joiningMembers.Keys]; Member[] memberObjects = [.. members.Select(memberId => new Member(memberId))]; - DbObj.InsertAll(memberObjects); + Db.InsertAll(memberObjects); string membersMsg = string.Join(", ", members); Console.WriteLine($"{membersMsg} joined"); diff --git a/Bot/Clash/Phaser.cs b/Bot/Clash/Phaser.cs index 8bf1a40..7daff81 100644 --- a/Bot/Clash/Phaser.cs +++ b/Bot/Clash/Phaser.cs @@ -57,7 +57,7 @@ private static void ProcessRaid(ClanCapitalRaidSeason season) private static void Init() { - IEnumerable> donationGroups = Db.GetDonations() + IEnumerable> donationGroups = Main.FetchAll() .GroupBy(d => d.Checked) .OrderBy(g => g.Key); DateTimeOffset now = DateTimeOffset.UtcNow; @@ -103,7 +103,7 @@ private static void DonationChanged(IEnumerable> donations) Main main = new Member(tag).GetEffectiveMain(); main.Donated += (uint)donated; Console.WriteLine($"[Donate25] {tag} {donated}"); - Db.UpdateMain(main); + main.Update(); } } diff --git a/Bot/Discord/Cmds.cs b/Bot/Discord/Cmds.cs index 4b90471..7f5c2af 100644 --- a/Bot/Discord/Cmds.cs +++ b/Bot/Discord/Cmds.cs @@ -16,7 +16,7 @@ public async Task ShutdownAsync(bool commit = true) { if (commit) { - DbObj.Commit(); + Db.Commit(); } await RespondAsync("Ok", ephemeral: true); Environment.Exit(0); @@ -26,7 +26,7 @@ public async Task ShutdownAsync(bool commit = true) [SlashCommand("commit", "[Owner] Commits db")] public async Task CommitAsync() { - DbObj.Commit(); + Db.Commit(); await RespondAsync("Committed", ephemeral: true); } @@ -134,7 +134,7 @@ public async Task InfoAsync(Member clanMember) [SlashCommand("alias", "[Admin] Sets an alias for a Coc member")] public async Task AliasAsync(string alias, Member member) { - bool success = Db.AddAlias(alias, member); + bool success = new CocAlias(alias, member.CocId).Insert() == 1; if (success) { await RespondAsync($"`{alias}` is now an alias of `{member.GetName()}`"); @@ -149,7 +149,7 @@ public async Task AliasAsync(string alias, Member member) public async Task AliasesAsync() { string msg = ""; - foreach (CocMemberAlias alias in Db.GetAliases()) + foreach (CocAlias alias in CocAlias.FetchAll()) { ClanMember? clanMember = Coc.TryGetMember(alias.CocId); string name = clanMember == null ? "" : clanMember.Name; diff --git a/Bot/Discord/MemberConverter.cs b/Bot/Discord/MemberConverter.cs index fd32a77..8f2c39d 100644 --- a/Bot/Discord/MemberConverter.cs +++ b/Bot/Discord/MemberConverter.cs @@ -25,7 +25,7 @@ public override Task ReadAsync(IInteractionContext context, ulong uid = Convert.ToUInt64(captured[2..^1].ToString()); // 123 // Checks whether this Discord user is linked to a main - Main? main = Db.GetMainByDiscord(uid); + Main? main = Main.TryFetchByDiscord(uid); if (main == null) { return TypeConverters.Error("This Discord user isn't linked to any CoC account."); @@ -47,7 +47,7 @@ public override Task ReadAsync(IInteractionContext context, } // Check whether input matches an alias - CocMemberAlias? dbAlias = Db.TryGetAlias(input); + CocAlias? dbAlias = CocAlias.TryFetch(input); if (dbAlias != null) { // Check whether the coc account of the alias is still in the clan diff --git a/Bot/Program.cs b/Bot/Program.cs index d7b4994..aaab536 100644 --- a/Bot/Program.cs +++ b/Bot/Program.cs @@ -98,5 +98,5 @@ internal static async Task TryUntilAsync(Func tryFunc, Func - await Task.WhenAll(Discord.Dc.InitAsync(), Clash.Coc.InitAsync(), Sql.DbObj.InitAsync()); + await Task.WhenAll(Discord.Dc.InitAsync(), Clash.Coc.InitAsync(), Sql.Db.InitAsync()); } diff --git a/Bot/Sql/Alias.cs b/Bot/Sql/Alias.cs deleted file mode 100644 index f310b81..0000000 --- a/Bot/Sql/Alias.cs +++ /dev/null @@ -1,15 +0,0 @@ -using SQLite; - -namespace Hyperstellar.Sql; - -[Table("Alias")] -public sealed class CocMemberAlias(string alias, string cocId) -{ - [PrimaryKey, NotNull] - public string Alias { get; set; } = alias; - - [NotNull] - public string CocId { get; set; } = cocId; - - public CocMemberAlias() : this("", "") { } -} diff --git a/Bot/Sql/Alt.cs b/Bot/Sql/Alt.cs index f1849b8..c2adb4a 100644 --- a/Bot/Sql/Alt.cs +++ b/Bot/Sql/Alt.cs @@ -2,7 +2,7 @@ namespace Hyperstellar.Sql; -public sealed class Alt(string altId, string mainId) +public sealed class Alt(string altId, string mainId) : DbObj { [PrimaryKey, NotNull] public string AltId { get; set; } = altId; @@ -12,15 +12,13 @@ public sealed class Alt(string altId, string mainId) public Alt() : this("", "") { } - public TableQuery GetOtherAlts() => Db.s_db.Table().Where(a => a.MainId == MainId && a.AltId != AltId); + public TableQuery GetOtherAlts() => FetchAll().Where(a => a.MainId == MainId && a.AltId != AltId); - public Main GetMain() => Db.s_db.Table
().Where(m => m.MainId == MainId).First(); + public Main GetMain() => Main.FetchAll().First(m => m.MainId == MainId); public bool UpdateMain(string id) { MainId = id; - return Db.s_db.Update(this) == 1; + return s_db.Update(this) == 1; } - - public bool Delete() => Db.s_db.Delete(this) == 1; } diff --git a/Bot/Sql/BotAdmin.cs b/Bot/Sql/BotAdmin.cs index a9f6aa1..fc51704 100644 --- a/Bot/Sql/BotAdmin.cs +++ b/Bot/Sql/BotAdmin.cs @@ -2,7 +2,7 @@ namespace Hyperstellar.Sql; -internal sealed class BotAdmin(ulong id) : DbObj +internal sealed class BotAdmin(ulong id) : DbObj { internal static readonly HashSet s_admins = s_db.Table().Select(a => a.Id).ToHashSet(); diff --git a/Bot/Sql/CocAlias.cs b/Bot/Sql/CocAlias.cs new file mode 100644 index 0000000..750e67c --- /dev/null +++ b/Bot/Sql/CocAlias.cs @@ -0,0 +1,27 @@ +using SQLite; + +namespace Hyperstellar.Sql; + +[Table("Alias")] +public sealed class CocAlias(string alias, string cocId) : DbObj +{ + private string _alias = alias.ToLower(); + + [PrimaryKey, NotNull] + public string Alias + { + get => _alias; + set => _alias = value.ToLower(); + } + + [NotNull] + public string CocId { get; set; } = cocId; + + public CocAlias() : this("", "") { } + + internal static CocAlias? TryFetch(string alias) + { + alias = alias.ToLower(); + return FetchAll().FirstOrDefault(a => a.Alias == alias); + } +} diff --git a/Bot/Sql/Db.cs b/Bot/Sql/Db.cs index 131f18a..f567acb 100644 --- a/Bot/Sql/Db.cs +++ b/Bot/Sql/Db.cs @@ -1,29 +1,38 @@ +using System.Collections; using SQLite; namespace Hyperstellar.Sql; -internal static class Db +public abstract class Db { - internal static readonly SQLiteConnection s_db = DbObj.s_db; + private protected static readonly SQLiteConnection s_db = new("Hyperstellar.db"); - internal static Main? GetMainByDiscord(ulong uid) => s_db.Table
().FirstOrDefault(m => m.Discord == uid); - - internal static IEnumerable
GetDonations() => s_db.Table
(); - - internal static bool UpdateMain(Main main) => s_db.Update(main) == 1; - - internal static CocMemberAlias? TryGetAlias(string alias) + internal static void Commit() { - alias = alias.ToLower(); - return s_db.Table().FirstOrDefault(a => a.Alias == alias); + s_db.Commit(); + s_db.BeginTransaction(); } - internal static IEnumerable GetAliases() => s_db.Table(); + internal static int InsertAll(IEnumerable objects) => s_db.InsertAll(objects); - internal static bool AddAlias(string alias, Member member) + internal static async Task InitAsync() { - CocMemberAlias cocMemberAlias = new(alias.ToLower(), member.CocId); - int count = s_db.Insert(cocMemberAlias); - return count == 1; + s_db.BeginTransaction(); + await Program.TryUntilAsync(async () => + { + await Task.Delay(5 * 60 * 1000); + Commit(); + }, runForever: true); } + + internal virtual int Insert() => s_db.Insert(this); + + internal int Delete() => s_db.Delete(this); + + internal int Update() => s_db.Update(this); +} + +public abstract class DbObj : Db where T : DbObj, new() +{ + internal static TableQuery FetchAll() => s_db.Table(); } diff --git a/Bot/Sql/DbObj.cs b/Bot/Sql/DbObj.cs deleted file mode 100644 index 3dce9db..0000000 --- a/Bot/Sql/DbObj.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections; -using SQLite; - -namespace Hyperstellar.Sql; - -public abstract class DbObj -{ - // Make this private after migration - internal static readonly SQLiteConnection s_db = new("Hyperstellar.db"); - - internal static void Commit() - { - s_db.Commit(); - s_db.BeginTransaction(); - } - - internal static int InsertAll(IEnumerable objects) => s_db.InsertAll(objects); - - internal static async Task InitAsync() - { - s_db.BeginTransaction(); - await Program.TryUntilAsync(async () => - { - await Task.Delay(5 * 60 * 1000); - Commit(); - }, runForever: true); - } - - internal virtual int Insert() => s_db.Insert(this); - - internal int Delete() => s_db.Delete(this); -} diff --git a/Bot/Sql/Main.cs b/Bot/Sql/Main.cs index 056161e..02c2e2f 100644 --- a/Bot/Sql/Main.cs +++ b/Bot/Sql/Main.cs @@ -1,8 +1,7 @@ using SQLite; namespace Hyperstellar.Sql; - -public sealed class Main(string id) : DbObj +public sealed class Main(string id) : DbObj
{ [PrimaryKey, NotNull] public string MainId { get; set; } = id; @@ -21,7 +20,7 @@ public sealed class Main(string id) : DbObj public Main() : this("") { } - internal static Main? TryFetch(string id) => s_db.Table
().FirstOrDefault(d => d.MainId == id); + internal static Main? TryFetch(string id) => FetchAll().FirstOrDefault(d => d.MainId == id); - public bool Update() => Db.s_db.Update(this) == 1; + internal static Main? TryFetchByDiscord(ulong uid) => FetchAll().FirstOrDefault(m => m.Discord == uid); } diff --git a/Bot/Sql/Member.cs b/Bot/Sql/Member.cs index a30e0cc..01aa86c 100644 --- a/Bot/Sql/Member.cs +++ b/Bot/Sql/Member.cs @@ -2,7 +2,7 @@ using SQLite; namespace Hyperstellar.Sql; -public class Member(string cocId) : DbObj +public class Member(string cocId) : DbObj { internal static event Action? EventAltAdded; @@ -11,14 +11,12 @@ public class Member(string cocId) : DbObj public Member() : this("") { } - internal static IEnumerable FetchAll() => s_db.Table(); - internal static Member? TryFetch(string cocId) => s_db.Table().FirstOrDefault(m => m.CocId == cocId); public void AddAlt(Member altMember) { Alt alt = new(altMember.CocId, CocId); - s_db.Insert(alt); + alt.Insert(); Main altMain = Main.TryFetch(altMember.CocId)!; Main mainMain = Main.TryFetch(CocId)!; EventAltAdded!(altMain, mainMain);