diff --git a/Bot/Bot.csproj b/Bot/Bot.csproj
index 88a9141..2da1cca 100644
--- a/Bot/Bot.csproj
+++ b/Bot/Bot.csproj
@@ -11,6 +11,7 @@
+
diff --git a/Bot/Coc.cs b/Bot/Coc.cs
index f17b7b8..90828fd 100644
--- a/Bot/Coc.cs
+++ b/Bot/Coc.cs
@@ -1,4 +1,4 @@
-using ClashOfClans;
+using ClashOfClans;
using ClashOfClans.Models;
namespace Hyperstellar;
@@ -6,50 +6,41 @@ namespace Hyperstellar;
internal class Coc
{
- internal readonly struct DonationTuple
+ internal readonly struct DonationTuple(int donated, int received)
{
- internal readonly int Donated;
- internal readonly int Received;
-
- public DonationTuple(int donated, int received)
- {
- Donated = donated;
- Received = received;
- }
+ internal readonly int Donated = donated;
+ internal readonly int Received = received;
}
- internal readonly struct ClanMemberInfo
+ private class ClanUtil
{
- internal readonly string Name;
- internal readonly DonationTuple Donation;
+ internal readonly Dictionary Members = [];
+ internal readonly Clan Clan;
+ internal readonly IEnumerable existingMembers;
- public ClanMemberInfo(string name, DonationTuple donation)
+ public ClanUtil(Clan clan)
{
- Name = name;
- Donation = donation;
+ foreach (var member in clan.MemberList!)
+ {
+ Members[member.Tag] = member;
+ }
+ Clan = clan;
+ existingMembers = clan.MemberList!.Intersect(_prevClan.Clan.MemberList!, new MemberComparer());
}
-
- internal readonly int Donated => Donation.Donated;
- internal readonly int Received => Donation.Received;
}
- private readonly struct ClanInfo
+ private class MemberComparer : IEqualityComparer
{
- internal readonly Dictionary Members = new();
+ public bool Equals(ClanMember? x, ClanMember? y) => x!.Tag.Equals(y!.Tag);
- public ClanInfo(Clan clan)
- {
- foreach (var member in clan.MemberList!)
- {
- DonationTuple donation = new(member.Donations, member.DonationsReceived);
- Members[member.Tag] = new(member.Name, donation);
- }
- }
+ public int GetHashCode(ClanMember obj) => obj.Tag.GetHashCode();
}
const string CLAN_ID = "#2QU2UCJJC";
const string DIM_ID = "#28QL0CJV2";
- private static ClanInfo _prevClan;
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+ private static ClanUtil _prevClan;
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
internal static readonly ClashOfClansClient Client = new(Secrets.Coc);
private static async Task GetClanAsync() => await Client.Clans.GetClanAsync(CLAN_ID);
@@ -57,24 +48,25 @@ public ClanInfo(Clan clan)
private static async Task PollAsync()
{
var clan = await GetClanAsync();
- ClanInfo clanInfo = new(clan);
- await CheckDonations(clanInfo, clan);
- _prevClan = clanInfo;
+ if (clan == null) return;
+ if (clan.MemberList == null) return;
+ ClanUtil clanUtil = new(clan);
+ await CheckDonations(clanUtil);
+
+ _prevClan = clanUtil;
}
- private static async Task CheckDonations(ClanInfo clan, Clan c)
+ private static async Task CheckDonations(ClanUtil clan)
{
- Dictionary donationsDelta = new();
- foreach (var memberTag in clan.Members.Keys)
+ Dictionary donationsDelta = [];
+ var existingMemberTags = clan.existingMembers.Select(x => x.Tag);
+ foreach (var tag in existingMemberTags)
{
- bool existsInPrevClan = _prevClan.Members.TryGetValue(memberTag, out ClanMemberInfo previous);
- if (existsInPrevClan)
+ var current = clan.Members[tag];
+ var previous = _prevClan.Members[tag];
+ if (current.Donations > previous.Donations || current.DonationsReceived > previous.DonationsReceived)
{
- ClanMemberInfo current = clan.Members[memberTag];
- if (current.Donated > previous.Donated || current.Received > previous.Received)
- {
- donationsDelta[current.Name] = new(current.Donated - previous.Donated, current.Received - previous.Received);
- }
+ donationsDelta[current.Name] = new(current.Donations - previous.Donations, current.DonationsReceived - previous.DonationsReceived);
}
}
if (donationsDelta.Count > 0)
@@ -83,10 +75,7 @@ private static async Task CheckDonations(ClanInfo clan, Clan c)
}
}
- internal static async Task InitAsync()
- {
- _prevClan = new(await GetClanAsync());
- }
+ internal static async Task InitAsync() => _prevClan = new(await GetClanAsync());
internal static async Task BotReadyAsync()
{
diff --git a/Bot/Discord.cs b/Bot/Discord.cs
index 2027b53..e1212b6 100644
--- a/Bot/Discord.cs
+++ b/Bot/Discord.cs
@@ -12,7 +12,7 @@ internal class Discord
const ulong BOT_LOG_ID = 1099026457268863017;
#endif
- private static DiscordSocketClient _bot = new();
+ private static readonly DiscordSocketClient _bot = new();
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private static SocketTextChannel _botLog;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
@@ -26,7 +26,7 @@ private static Task Log(LogMessage msg)
private static Task Ready()
{
_botLog = (SocketTextChannel)_bot.GetChannel(BOT_LOG_ID);
- Task.Run(Coc.BotReadyAsync);
+ Task.Run(BotReadyAsync);
return Task.CompletedTask;
}
diff --git a/Bot/Program.cs b/Bot/Program.cs
index 5028ef8..7170c59 100644
--- a/Bot/Program.cs
+++ b/Bot/Program.cs
@@ -1,11 +1,12 @@
-using Hyperstellar;
-
-public class Program
+namespace Hyperstellar
{
- public static async Task Main(string[] args)
+ public class Program
{
- await Hyperstellar.Discord.InitAsync();
- await Coc.InitAsync();
- await Task.Delay(-1);
+ public static async Task Main()
+ {
+ await Discord.InitAsync();
+ await Coc.InitAsync();
+ await Task.Delay(-1);
+ }
}
}
\ No newline at end of file
diff --git a/Bot/Sql/Db.cs b/Bot/Sql/Db.cs
new file mode 100644
index 0000000..4474ae4
--- /dev/null
+++ b/Bot/Sql/Db.cs
@@ -0,0 +1,9 @@
+using SQLite;
+
+namespace Hyperstellar.Sql
+{
+ internal class Db
+ {
+ private static readonly SQLiteConnection _db = new("Hyperstellar.db");
+ }
+}