135 lines
5.6 KiB
C#
135 lines
5.6 KiB
C#
|
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)
|
||
|
{
|
||
|
await ctx.DeferAsync();
|
||
|
VNC vnc;
|
||
|
using var http = new HttpClient();
|
||
|
if (country != null)
|
||
|
{
|
||
|
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<VNCSearchResult>(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);
|
||
|
response = await http.GetStringAsync(
|
||
|
$"https://computernewb.com/vncresolver/api/scans/vnc/id/{results.result[random]}");
|
||
|
vnc = JsonSerializer.Deserialize<VNC>(response);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var response = await http.GetStringAsync("https://computernewb.com/vncresolver/api/scans/vnc/random");
|
||
|
vnc = JsonSerializer.Deserialize<VNC>(response);
|
||
|
}
|
||
|
if (vnc == null)
|
||
|
{
|
||
|
await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Failed to fetch VNC data (response was null, please ping an admin!)"));
|
||
|
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 {vnc.createdat}");
|
||
|
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<string,string> Options { get; }
|
||
|
|
||
|
public override Task<IEnumerable<DiscordApplicationCommandOptionChoice>> Provider()
|
||
|
{
|
||
|
return Task.FromResult(Options.Select(o => new DiscordApplicationCommandOptionChoice(o.Key, o.Value)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class RulesChoiceProvider : DictChoiceProvider
|
||
|
{
|
||
|
public override Dictionary<string, string> 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<string, string> Options => new()
|
||
|
{
|
||
|
{ "VM0b0t", "VM0b0t" },
|
||
|
{ "VM1", "VM1" },
|
||
|
{ "VM2", "VM2" },
|
||
|
{ "VM3", "VM3" },
|
||
|
{ "VM4", "VM4" },
|
||
|
{ "VM5", "VM5" },
|
||
|
{ "VM6", "VM6" },
|
||
|
{ "VM7", "VM7" },
|
||
|
{ "VM8", "VM8" }
|
||
|
};
|
||
|
}
|