using System.Text.Json; using System.Text.RegularExpressions; using DSharpPlus.Entities; using DSharpPlus.SlashCommands; namespace CollabBot; public class DiscordCommands : ApplicationCommandModule { [SlashCommand("vnc", "View insecure VNCs around the world!")] public async Task VNC(InteractionContext ctx, [Option("country", "If specified, a random VNC from this country")] string? country = null, [Option("id", "If specified, a specific VNC by ID")] long? id = null) { await ctx.DeferAsync(); VNC vnc; using var http = new HttpClient(); if (id != null) { Console.WriteLine($"Getting VNC ID {id} for {ctx.User.Username}"); try { var response = await http.GetStringAsync($"https://computernewb.com/vncresolver/api/scans/vnc/id/{id}"); vnc = JsonSerializer.Deserialize(response); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"Failed to fetch VNC data ({ex.Message}). Please ping an admin!")); return; } } else if (country != null) { Console.WriteLine($"Getting VNC from {country} for {ctx.User.Username}"); if (!Regex.IsMatch(country, "^[a-zA-Z]{2}$")) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent( "Country name must be ISO code (i.e. GB for England, US for United States)")); return; } var response = await http.GetStringAsync( $"https://computernewb.com/vncresolver/api/scans/vnc/search?country={country}"); var results = JsonSerializer.Deserialize(response); if (results == null || results.error != null) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(results != null ? results.error! : "Failed to fetch VNC data (response was null, please ping an admin!)")); } if (results.count == 0) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(country.ToUpper() == "NK" ? "You wish lol" : "No VNCs from that country found.")); return; } var random = new Random().Next(results.count); try { response = await http.GetStringAsync( $"https://computernewb.com/vncresolver/api/scans/vnc/id/{results.result[random]}"); vnc = JsonSerializer.Deserialize(response); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"Failed to fetch VNC data ({ex.Message}). Please ping an admin!")); return; } } else { Console.WriteLine($"Getting random VNC for {ctx.User.Username}"); try { var response = await http.GetStringAsync("https://computernewb.com/vncresolver/api/scans/vnc/random"); vnc = JsonSerializer.Deserialize(response); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"Failed to fetch VNC data ({ex.Message}). Please ping an admin!")); return; } } if (vnc == null) { Console.WriteLine("Failed to fetch VNC data (response was null)"); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Failed to fetch VNC data (response was null, please ping an admin!)")); return; } if (vnc.error != null) { Console.WriteLine($"Error: {vnc.error}"); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(vnc.error)); return; } var embed = new DiscordEmbedBuilder() .WithTitle($"VNC {vnc.id}").WithUrl($"https://computernewb.com/vncresolver/browse/#id/{vnc.id}") .AddField("Address", $"{vnc.ip}:{vnc.port}") .AddField("Location", $"{vnc.city}, {vnc.country} :flag_{vnc.country.ToLower()}:") .AddField("ASN", vnc.asn) .WithImageUrl($"https://computernewb.com/vncresolver/api/scans/vnc/screenshot/{vnc.id}.jpeg") .WithFooter($"Added to database on {DateTime.UnixEpoch.AddMilliseconds(vnc.createdat):u}"); if (!String.IsNullOrEmpty(vnc.clientname)) embed.AddField("Client", vnc.clientname); if (!String.IsNullOrEmpty(vnc.screenres)) embed.AddField("Screen Resolution", vnc.screenres); if (!String.IsNullOrEmpty(vnc.hostname)) embed.AddField("Hostname", vnc.hostname); await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddEmbed(embed)); } [SlashCommand("report", "Report a user for breaking the rules on the main VMs")] public async Task ReportUser(InteractionContext ctx, [Option("user", "Who is breaking the rules?")] string user, [Option("vm", "Which VM are they on?"), ChoiceProvider(typeof(VMChoiceProvider))] string vm, [Option("rule", "Which rule are they breaking?"), ChoiceProvider(typeof(RulesChoiceProvider))] string rule, [Option("reason", "What exactly are they doing?")] string reason ) { await ctx.DeferAsync(true); await Program.ReportChannel.SendMessageAsync($"<@&{Program.Config.ReportRole}>", new DiscordEmbedBuilder() .WithTitle("User Reported") .AddField("User", user) .AddField("VM", vm) .AddField("Rule", rule) .AddField("Reason", reason) .AddField("Reporter", $"{ctx.User.Mention} ({ctx.User.Username})") .Build()); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Thank you for your report!")); } } public abstract class DictChoiceProvider : ChoiceProvider { public abstract Dictionary Options { get; } public override Task> Provider() { return Task.FromResult(Options.Select(o => new DiscordApplicationCommandOptionChoice(o.Key, o.Value))); } } public class RulesChoiceProvider : DictChoiceProvider { public override Dictionary Options => new() { { "R1. Don't break the law.", "R1" }, { "R2. No running DoS/DDoS tools.", "R2"}, { "R3. No spam distribution.", "R3"}, { "R4. Do not abuse any exploits.", "R4" }, { "R6. One vote per person.", "R6" }, { "R7. No Remote Administration Tools.", "R7" }, { "R8. No bypassing CollabNet.", "R8" }, { "R9. No performing destructive actions constantly.", "R9" }, { "R10. No Cryptomining", "R10" }, { "NSFW Content on Main VMs", "NSFW" } }; } public class VMChoiceProvider : DictChoiceProvider { public override Dictionary Options => new() { { "VM0b0t", "VM0b0t" }, { "VM1", "VM1" }, { "VM2", "VM2" }, { "VM3", "VM3" }, { "VM4", "VM4" }, { "VM5", "VM5" }, { "VM6", "VM6" }, { "VM7", "VM7" }, { "VM8", "VM8" } }; }