commit 139fc375e424830924d5806ce4d6bfc1975a5a55 Author: femsci Date: Wed Feb 22 22:03:01 2023 +0100 Initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afec7c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/obj/ +**/bin/ diff --git a/.nyoki b/.nyoki new file mode 100644 index 0000000..470667a --- /dev/null +++ b/.nyoki @@ -0,0 +1,3 @@ +{ + "instanceId": "4676232f-d0d1-4991-9f13-65b4f3593d80" +} \ No newline at end of file diff --git a/Delete.cs b/Delete.cs new file mode 100644 index 0000000..133dbf6 --- /dev/null +++ b/Delete.cs @@ -0,0 +1,37 @@ +namespace Disforget; + +public class Delete +{ + public Delete(List messages) + { + _messages = messages; + _cli = Utils.CreateClient(); + } + + private HttpClient _cli; + private List _messages; + + public async Task StartDeletion() + { + int cnt = 1; + int repeats = 0; + foreach (var msg in _messages) + { + await Task.Delay(1500); + + REQ: + var resp = await _cli.DeleteAsync($"https://discord.com/api/v9/channels/{msg.ChannelId}/messages/{msg.Id}"); + + Console.Write($"\x1b[2K\rRequest {cnt}/{_messages.Count} Status: {resp.StatusCode} [{(resp.IsSuccessStatusCode ? "OK" : "REPEATING")}] ... ({_messages.Count - cnt} left)"); + if (!resp.IsSuccessStatusCode) + { + await Task.Delay(30000); + repeats++; + goto REQ; + } + cnt++; + } + + return repeats; + } +} diff --git a/Disforget.csproj b/Disforget.csproj new file mode 100644 index 0000000..c58d21f --- /dev/null +++ b/Disforget.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + true + true + linux-x64 + true + + + diff --git a/Model.cs b/Model.cs new file mode 100644 index 0000000..52a4932 --- /dev/null +++ b/Model.cs @@ -0,0 +1,34 @@ +using System.Text.Json.Serialization; + +namespace Disforget; + +public record Response +{ + [JsonPropertyName("total_results")] + public int TotalResults { get; set; } + + [JsonPropertyName("messages")] + public IEnumerable> MessagesInternal { get; set; } = null!; + + [JsonIgnore] + public ICollection Messages => MessagesInternal.Select(m => m.First()).ToList(); +} + +public record Message +{ + [JsonPropertyName("id")] + public ulong Id { get; set; } + [JsonPropertyName("channel_id")] + public ulong ChannelId { get; set; } + + [JsonPropertyName("content")] + public string Content { get; set; } = null!; +} + +public record IdChn +{ + [JsonPropertyName("id")] + public ulong Id { get; set; } + [JsonPropertyName("chn")] + public ulong Channel { get; set; } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..a4ed7b6 --- /dev/null +++ b/Program.cs @@ -0,0 +1,15 @@ +using Disforget; + +int pages = int.Parse(args[0]); +ulong channel = ulong.Parse(args[1]); + +Console.WriteLine("Starting..."); + +Search search = new(channel, pages); + +var messages = await search.Perform(); + +Delete deletion = new(messages); +int reps = await deletion.StartDeletion(); + +Console.WriteLine($"\n\nDeleted {messages.Count} messages.\nResent {reps} deletion requests."); diff --git a/Search.cs b/Search.cs new file mode 100644 index 0000000..1f59615 --- /dev/null +++ b/Search.cs @@ -0,0 +1,64 @@ +using System.Net; +using System.Net.Http.Json; + +namespace Disforget; + +public class Search +{ + public Search(ulong channel, int pages) + { + _channel = channel; + _pages = pages; + _cli = Utils.CreateClient(); + } + + private HttpClient _cli; + private List _messages = new(); + private ulong _channel; + private int _pages, _total; + + public async Task> Perform() + { + int page = 0; + + while (page < _pages) + { + await DoSearch(page); + await Task.Delay(1500); + page++; + } + + Console.WriteLine($"\nFound and processed {_messages.Count} messages."); + + return _messages; + } + + private async Task DoSearch(int page) + { + var reqstr = $"https://discord.com/api/v9/guilds/790954455621304330/messages/search?author_id=340510759588986882&channel_id={_channel}&include_nsfw=true{(page > 0 ? $"&offset={page * 25}" : "")}"; + + REQ: + var resp = await _cli.GetAsync(reqstr); + + if (resp.StatusCode == HttpStatusCode.TooManyRequests) + { + await Task.Delay(30000); + Console.Write($"\x1b[2K\rRequest {++page}/{_pages} FAILED [REPEATING] ({_messages.Count}/{_total})"); + goto REQ; + } + + Response? result = await resp.Content.ReadFromJsonAsync(); + + if (result == null) + { + Console.WriteLine("Failed (null)..."); + Environment.Exit(3); + } + + _total = result.TotalResults; + + _messages.AddRange(result.Messages); + + Console.Write($"\x1b[2K\rRequest {++page}/{_pages} Status: {resp.StatusCode} ({_messages.Count}/{_total})"); + } +} diff --git a/Utils.cs b/Utils.cs new file mode 100644 index 0000000..b852b85 --- /dev/null +++ b/Utils.cs @@ -0,0 +1,28 @@ +namespace Disforget; + +public static class Utils +{ + public static void AddHeader(this HttpClient client, string h, string v) + { + if (!client.DefaultRequestHeaders.TryAddWithoutValidation(h, v)) + { + Console.Error.WriteLine($"Cannot add {h}: {v}"); + Environment.Exit(-3); + + } + } + + public static HttpClient CreateClient() + { + HttpClient cli = new(); + cli.AddHeader("authority", "discord.com"); + cli.AddHeader("x-discord-locale", "en-US"); + cli.AddHeader("accept-language", "en-US"); + cli.AddHeader("authorization", $""); + cli.AddHeader("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.21 Chrome/91.0.4472.164 Electron/13.6.6 Safari/537.36"); + cli.AddHeader("accept", "*/*"); + cli.AddHeader("cookie", ""); + + return cli; + } +}