/ InfoService.cs
InfoService.cs
1 using _5uhr.Data; 2 using Discord; 3 using Discord.WebSocket; 4 using Microsoft.EntityFrameworkCore; 5 6 namespace _5uhr; 7 8 public class InfoService(DiscordSocketClient client, IServiceProvider serviceProvider, ILogger<InfoService> logger) 9 { 10 public void UpdateInfoAsync() 11 { 12 Task.Run(async () => 13 { 14 try 15 { 16 await using var scope = serviceProvider.CreateAsyncScope(); 17 await using var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); 18 var ts = DateTime.UtcNow; 19 var day = await RegistrationModule.GetGangDay(db, ts); 20 var nextDay = await RegistrationModule.GetGangDay(db, ts.AddDays(1)); 21 var mainConfig = await db.Configurations 22 .Where(x => x.GuildId == DiscordBotService.MAIN_GUILD_ID) 23 .SingleOrDefaultAsync(); 24 25 if (mainConfig == null) 26 { 27 logger.LogError("No main config!!"); 28 } 29 30 var guild = client.GetGuild(DiscordBotService.MAIN_GUILD_ID); 31 var leaderboardChannel = guild.GetTextChannel(mainConfig!.LeaderboardChannelId); 32 var checkinChannel = guild.GetTextChannel(mainConfig.CheckInChannelId); 33 34 var leaderboardMessageR = 35 (await leaderboardChannel.GetPinnedMessagesAsync()).FirstOrDefault(x => 36 x.Author.Id == client.CurrentUser.Id); 37 Embed[] embeds = await GetLeaderboardEmbed(db); 38 if (leaderboardMessageR is not null) 39 { 40 var leaderboardMessage = 41 (await leaderboardChannel.GetMessageAsync(leaderboardMessageR.Id)) as IUserMessage; 42 logger.LogInformation("Existing message found {LeaderboardMessageId}. Updating.", 43 leaderboardMessage?.Id); 44 await leaderboardMessage!.ModifyAsync(x => { x.Embeds = embeds; }); 45 } 46 else 47 { 48 logger.LogInformation("No existing message found. Sending new one to {Channel}.", 49 leaderboardChannel.Mention); 50 var message = await leaderboardChannel.SendMessageAsync(embeds: embeds); 51 // var message = await leaderboardChannel.SendMessageAsync("Deine fucking mutter"); 52 await message.PinAsync(); 53 } 54 55 var dayInfo = await db.Days 56 .Where(x => x.Id == day.Id) 57 .Select(x => new 58 { 59 MissingPreCheckIns = x.PreCheckIns.Where(p => 60 x.CheckIns.All(c => c.MemberThatCheckedIn.Id != p.MemberThatPreCheckedIn.Id)).ToList(), 61 }) 62 .SingleAsync(); 63 64 var tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); 65 var localTime = TimeZoneInfo.ConvertTime(ts, tz); 66 67 if (localTime.Hour >= 4) 68 { 69 var message4 = "AUFSTEHEN! Es ist 4 Uhr! ⏰🌅\n" + 70 "Klicke auf den Button unten, um deinen Check-In zu bestätigen und deinen Tag richtig zu starten! 💪☕\n"; 71 72 var missing4 = dayInfo.MissingPreCheckIns.Where(x => x.ClaimedCheckpoint == TimeCheckpoint.Uhr4) 73 .ToList(); 74 if (missing4.Count > 0) 75 { 76 message4 += "Es fehlen noch:\n - " 77 + String.Join("\n - ", 78 missing4.Select(x => $"<@{x.MemberThatPreCheckedIn.DiscordUserId}>")); 79 80 if (localTime.Hour > 4 || localTime.Minute > 10) 81 { 82 message4 += "\n\n AN ALLE: Die fehlenden jetzt aus dem Bett schmeissen!"; 83 } 84 } 85 86 if (!day.MessageForCheckIn4.HasValue) 87 { 88 var message = await checkinChannel.SendMessageAsync(message4, 89 components: new ComponentBuilder() 90 .AddRow(new ActionRowBuilder() 91 .AddComponent(new ButtonBuilder() 92 .WithStyle(ButtonStyle.Primary) 93 .WithLabel("Check-In - 4 Uhr") 94 .WithCustomId("checkin_button_4:" + day.Id))) 95 .Build()); 96 day.MessageForCheckIn4 = message.Id; 97 } 98 else 99 { 100 await checkinChannel.ModifyMessageAsync(day.MessageForCheckIn4.Value, 101 x => { x.Content = message4; }); 102 } 103 } 104 105 if (localTime.Hour >= 5) 106 { 107 var message5 = "AUFSTEHEN! Es ist 5 Uhr! ⏰🌅\n" + 108 "Klicke auf den Button unten, um deinen Check-In zu bestätigen und deinen Tag richtig zu starten! 💪☕\n"; 109 110 var missing5 = dayInfo.MissingPreCheckIns.Where(x => x.ClaimedCheckpoint == TimeCheckpoint.Uhr5) 111 .ToList(); 112 if (missing5.Count > 0) 113 { 114 message5 += "Es fehlen noch:\n - " 115 + String.Join("\n - ", 116 missing5.Select(x => $"<@{x.MemberThatPreCheckedIn.DiscordUserId}>")); 117 118 if (localTime.Hour > 5 || localTime.Minute > 10) 119 { 120 message5 += "\n\n AN ALLE: Die fehlenden jetzt aus dem Bett schmeissen!"; 121 } 122 } 123 124 if (!day.MessageForCheckIn5.HasValue) 125 { 126 var message = await checkinChannel.SendMessageAsync(message5, 127 components: new ComponentBuilder() 128 .AddRow(new ActionRowBuilder() 129 .AddComponent(new ButtonBuilder() 130 .WithStyle(ButtonStyle.Primary) 131 .WithLabel("Check-In - 5 Uhr") 132 .WithCustomId("checkin_button_5:" + day.Id))) 133 .Build()); 134 day.MessageForCheckIn5 = message.Id; 135 } 136 else 137 { 138 await checkinChannel.ModifyMessageAsync(day.MessageForCheckIn5.Value, 139 x => { x.Content = message5; }); 140 } 141 } 142 143 if (localTime.Hour >= 12) 144 { 145 var messageText = 146 "12Uhr geschafft. Bitte denkt dran andere zu verifizieren / zu reporten. 👍\n" + 147 "Ab jetzt kann sich hier für morgen vorregistriert werden.\n"; 148 149 var infos = await db.Days 150 .Where(x => x.Id == nextDay.Id) 151 .Select(x => new 152 { 153 PreCheckIns = x.PreCheckIns 154 .OrderBy(p => p.Timestamp) 155 .Select(p => new 156 { 157 p.MemberThatPreCheckedIn, 158 p.ClaimedCheckpoint 159 }), 160 Midnight = x.Start, 161 }) 162 .SingleAsync(); 163 164 messageText += String.Join('\n', infos.PreCheckIns.Select(x => 165 { 166 var mention = x.MemberThatPreCheckedIn.DiscordUserId.HasValue 167 ? $"<@{x.MemberThatPreCheckedIn.DiscordUserId}>" 168 : x.MemberThatPreCheckedIn.FriendlyName ?? "???"; 169 return $"- {mention} um {(x.ClaimedCheckpoint == TimeCheckpoint.Uhr4 ? "4" : "5")} Uhr"; 170 })); 171 172 if (!nextDay.MessageForPreCheckInsId.HasValue) 173 { 174 var message = await checkinChannel.SendMessageAsync(messageText, 175 components: new ComponentBuilder() 176 .AddRow(new ActionRowBuilder() 177 .AddComponent(new ButtonBuilder() 178 .WithStyle(ButtonStyle.Primary) 179 .WithLabel("Vorregistrieren - 4 Uhr") 180 .WithCustomId("precheckin_button_4:" + nextDay.Id)) 181 .AddComponent(new ButtonBuilder() 182 .WithStyle(ButtonStyle.Primary) 183 .WithLabel("Vorregistrieren - 5 Uhr") 184 .WithCustomId("precheckin_button_5:" + nextDay.Id))) 185 .Build()); 186 nextDay.MessageForPreCheckInsId = message.Id; 187 } 188 else 189 { 190 await checkinChannel.ModifyMessageAsync(nextDay.MessageForPreCheckInsId.Value, 191 x => { x.Content = messageText; }); 192 } 193 } 194 await db.SaveChangesAsync(); 195 } 196 catch (Exception e) 197 { 198 logger.LogError("During refreshing info: {Exception}", e); 199 } 200 } 201 ); 202 } 203 204 private async Task<Embed[]> GetLeaderboardEmbed(ApplicationDbContext db) 205 { 206 var leaderboard = (await Task.WhenAll((await db.Member 207 .Select(x => new 208 { 209 x.DiscordUserId, x.FriendlyName, 210 Uhr4 = x.CheckIns 211 .Where(c => c.Verifications.Count > c.Reports.Count) 212 .Where(c => c.ClaimedCheckpoint == TimeCheckpoint.Uhr4) 213 .Count() 214 + x.ImportedCheckIns4Uhr, 215 Uhr5 = x.CheckIns 216 .Where(c => c.Verifications.Count > c.Reports.Count) 217 .Where(c => c.ClaimedCheckpoint == TimeCheckpoint.Uhr5) 218 .Count() 219 + x.ImportedCheckIns5Uhr, 220 }) 221 .Select(x => new 222 { 223 x.Uhr4, 224 x.Uhr5, 225 x.DiscordUserId, 226 x.FriendlyName, 227 Groschen = x.Uhr4 * 2 + x.Uhr5 * 1 228 }) 229 .Where(x => x.Groschen > 0) 230 .OrderByDescending(x => x.Groschen) 231 .ToListAsync()) 232 .Select(async x => new 233 { 234 x.Uhr4, 235 x.Uhr5, 236 DiscordUser = x.DiscordUserId.HasValue 237 ? await client.GetUserAsync(x.DiscordUserId.Value) 238 : null, 239 x.FriendlyName, 240 x.Groschen, 241 }))) 242 .Index() 243 .ToArray(); 244 245 if (leaderboard.Length == 0) 246 return []; 247 248 return 249 [ 250 new EmbedBuilder() 251 .WithTitle("Groschen(G) Leaderboard") 252 .WithCurrentTimestamp() 253 .AddField("#", String.Join('\n', leaderboard.Select(x => x.Index)), true) 254 .AddField("Name", String.Join('\n', leaderboard.Select(x => x.Item.DiscordUser?.Mention ?? x.Item.FriendlyName ?? "???")), true) 255 .AddField("G", String.Join('\n', leaderboard.Select(x => x.Item.Groschen)), true) 256 .Build(), 257 new EmbedBuilder() 258 .WithTitle("# Aufgestanden um 4/5 Uhr") 259 .WithCurrentTimestamp() 260 .AddField("Name", String.Join('\n',leaderboard.Select(x => x.Item.DiscordUser?.Mention ?? x.Item.FriendlyName ?? "???")), true) 261 .AddField("4", String.Join('\n', leaderboard.Select(x => x.Item.Uhr4)), true) 262 .AddField("5", String.Join('\n', leaderboard.Select(x => x.Item.Uhr5)), true) 263 .Build() 264 ]; 265 } 266 267 // private async Task<MessageComponent> GetLeaderboardComponents(ApplicationDbContext db) 268 // { 269 // var leaderboard = (await db.Member 270 // .Select(x => new 271 // { 272 // x.DiscordUserId, x.FriendlyName, 273 // Groschen = x.CheckIns.Count(c => c.Verifications.Count > c.Reports.Count) 274 // }) 275 // .Where(x => x.Groschen > 0) 276 // .OrderByDescending(x => x.Groschen) 277 // .ToListAsync()) 278 // .Index(); 279 // 280 // // markdown table 281 // var leaderboardTable = """ 282 // | Range | Name | Groschen | 283 // |-------|------|----------| 284 // 285 // """ 286 // + String.Join('\n', leaderboard.Select(x => 287 // { 288 // string mention; 289 // if (x.Item.DiscordUserId.HasValue) 290 // { 291 // mention = client.GetUser(x.Item.DiscordUserId.Value).Mention; 292 // } 293 // else if (x.Item.FriendlyName is not null) 294 // { 295 // mention = x.Item.FriendlyName; 296 // } 297 // else 298 // { 299 // mention = "???"; 300 // } 301 // 302 // return $"| {x.Index + 1} | {mention} | {x.Item.Groschen} |"; 303 // })); 304 // return 305 // new ComponentBuilderV2() 306 // .AddComponent(new TextDisplayBuilder() 307 // .WithContent(leaderboardTable)) 308 // .Build(); 309 // } 310 }