using CommandLine; using DiscordClient; using DiscordClient.Data; using DiscordDelete; string? token = Environment.GetEnvironmentVariable("DISCORD_TOKEN"); if (token == null) { // Exit. Console.WriteLine("Token is null. Make sure you set the DISCORD_TOKEN environmental variable."); return; } DiscordContext db = new DiscordContext(); DiscordUserClient client = new DiscordUserClient(token); static async Task TooManyRequestsDelay() { int seconds = 60; Console.WriteLine($"Too many requests. Sleeping for extra {seconds} seconds."); await Task.Delay(TimeSpan.FromSeconds(seconds)); } int finalCode = await CommandLine .Parser.Default.ParseArguments(args) .MapResult( async (DeleteOptions opt) => { foreach ( Message message in db .Messages // Skip ones that are already deleted. .Where(message => message.LastHttpCode != 204) // Skip BadRequest (such as archived thread). .Where(message => message.LastHttpCode != 400) // Skip NotFound. .Where(message => message.LastHttpCode != 404) ) { // If required data is null, continue to next message. if (message.MessageId is null || message.ChannelId is null) continue; HttpResponseMessage response = await client.DeleteMessage( message.ChannelId, message.MessageId ); message.LastHttpCode = (int)response.StatusCode; Console.WriteLine( $"{(response.IsSuccessStatusCode ? "✅" : "❌")} {message.Id} - Deleting {message.MessageId} - {response.StatusCode}" ); if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) { await TooManyRequestsDelay(); } db.Update(message); await db.SaveChangesAsync(); await Task.Delay(TimeSpan.FromSeconds(2)); } return 0; }, async (ScanOptions opt) => { // This should never happen author required. if (opt.Author is null) { Console.WriteLine("Author ID is null."); return 1; } int totalMessages = 1; int offset = 0; while (offset < totalMessages) { var searchResponse = opt.GuildId is null ? await client.GetChannelMessages(opt.ChannelId, offset, opt.Author) : await client.SearchGuildMessages(opt.GuildId, offset, opt.Author); Console.WriteLine( $"Scan code at offset {offset}: {searchResponse.Response.StatusCode}." ); if (!searchResponse.Response.IsSuccessStatusCode) { continue; } if (searchResponse.Response.StatusCode == System.Net.HttpStatusCode.TooManyRequests) { await TooManyRequestsDelay(); continue; } if (searchResponse.JsonData is null) return 2; totalMessages = searchResponse.JsonData.TotalMessages; IEnumerable newMessages = searchResponse.JsonData.Messages.SelectMany( message => message.Select(messagePart => new Message { ChannelId = messagePart.ChannelId, MessageId = messagePart.Id, Content = messagePart.Content }) ); foreach (var newMessage in newMessages) { if (!db.Messages.Any(message => message.MessageId == newMessage.MessageId)) await db.AddAsync(newMessage); } await db.SaveChangesAsync(); offset += searchResponse.JsonData.Messages.Length; Console.WriteLine( $"Written {searchResponse.JsonData.Messages.Length} messages. {offset} / {totalMessages}" ); await Task.Delay(TimeSpan.FromSeconds(2)); } return 0; }, errs => Task.FromResult(0) );