diff --git a/Conversion/Converter.cs b/Conversion/Converter.cs index c295e49..531e2b6 100644 --- a/Conversion/Converter.cs +++ b/Conversion/Converter.cs @@ -40,7 +40,7 @@ namespace silverworker_discord.Conversion decimal asNumeric = 0; if (decimal.TryParse(theseMatches[0].Groups[1].Value, out asNumeric)) { - return actualConvert(asNumeric, theseMatches[0].Groups[2].Value, theseMatches[0].Groups[4].Value.ToLower()); + return Convert(asNumeric, theseMatches[0].Groups[2].Value, theseMatches[0].Groups[4].Value.ToLower()); } return "mysteriously semi-parsable"; } @@ -91,17 +91,17 @@ namespace silverworker_discord.Conversion } } - private static string actualConvert(decimal numericTerm, string sourceunit, string destinationUnit) + public static string Convert(decimal numericTerm, string sourceunit, string destinationUnit) { var normalizedSourceUnit = normalizeUnit(sourceunit); if (string.IsNullOrWhiteSpace(normalizedSourceUnit)) { - return $"what's {sourceunit}?"; + return $"parse failure: what's {sourceunit}?"; } var normalizedDestUnit = normalizeUnit(destinationUnit); if (string.IsNullOrWhiteSpace(normalizedDestUnit)) { - return $"what's {destinationUnit}?"; + return $"parse failure: what's {destinationUnit}?"; } if (normalizedSourceUnit == normalizedDestUnit) { @@ -134,7 +134,7 @@ namespace silverworker_discord.Conversion return $"{String.Format("{0:G4}", accumulator)} {normalizedDestUnit}"; } } - return "no conversion known"; + return "dimensional analysis failure - I know those units but can't find a path between them."; } private static string normalizeUnit(string unit) { diff --git a/Program.cs b/Program.cs index 29c8137..1753e6b 100644 --- a/Program.cs +++ b/Program.cs @@ -13,6 +13,7 @@ using Newtonsoft.Json; using System.Text; using System.Threading; using System.Diagnostics; +using Discord.Net; namespace silverworker_discord { @@ -54,9 +55,6 @@ namespace silverworker_discord _client.Log += Log; - await _client.LoginAsync(TokenType.Bot, config["token"]); - await _client.StartAsync(); - _client.Ready += () => Task.Run(() => { if (!eventsSignedUp) @@ -66,12 +64,19 @@ namespace silverworker_discord _client.MessageReceived += MessageReceived; _client.UserJoined += UserJoined; + //_client.ButtonExecuted += MyButtonHandler; + _client.SlashCommandExecuted += SlashCommandsHelper.SlashCommandHandler; + SlashCommandsHelper.Register(_client).GetAwaiter().GetResult(); } else { Console.WriteLine("bot appears to be RE connected, so I'm not going to sign up twice"); } }); + + await _client.LoginAsync(TokenType.Bot, config["token"]); + await _client.StartAsync(); + // Block this task until the program is closed. await Task.Delay(-1); @@ -293,6 +298,11 @@ namespace silverworker_discord didThing = true; #pragma warning restore 4014 } + // if (didThing == false && mentionedMe && contentWithoutMention.Contains("how long has that been there?")) + // { + // await message.Channel.SendMessageAsync("text", false, null, null, null, null, new ComponentBuilder().WithButton("label", "custom-id").Build()); + // didThing = true; + // } if (didThing == false && mentionedMe && contentWithoutMention.Contains('?')) { Console.WriteLine("providing bullshit nonanswer / admitting uselessness"); @@ -317,5 +327,15 @@ namespace silverworker_discord Console.WriteLine($"imma call him {abbreviatedNickname}"); return arg.Guild.DefaultChannel.SendMessageAsync($"oh hey {abbreviatedNickname}- IPLAYTHESEALOFORICHALCOS <:ORICHALCOS:852749196633309194>"); } + private async Task ButtonHandler(SocketMessageComponent component) + { + switch(component.Data.CustomId) + { + case "custom-id": + await component.RespondAsync($"{component.User.Mention}, it's been here the whole time!"); + break; + } + } + } } \ No newline at end of file diff --git a/SlashCommandsHelper.cs b/SlashCommandsHelper.cs new file mode 100644 index 0000000..2efb419 --- /dev/null +++ b/SlashCommandsHelper.cs @@ -0,0 +1,149 @@ +namespace silverworker_discord +{ + using System; + using System.Linq; + using System.Collections.Generic; + using System.Threading.Tasks; + using Discord.WebSocket; + using Discord.Net; + using Discord; + using Newtonsoft.Json; + + public static class SlashCommandsHelper + { + private static List slashCommands = new List() + { + new CommandSetup(){ + Id = "freedomunits", + UpdatedAt = new DateTime(2023, 5, 21, 13, 3, 0), + guild = 825293851110801428, + register = register_FreedomUnits + } + }; + public static async Task Register(DiscordSocketClient client) + { + var commandsInContext = await client.GetGlobalApplicationCommandsAsync(); + await Register(client, commandsInContext, null); + foreach (var guild in client.Guilds) + { + try + { + await Register(client, await guild.GetApplicationCommandsAsync(), guild); + } + catch (Discord.Net.HttpException ex) + { + Console.Error.WriteLine($"error registering slash commands for guild {guild.Name} (id {guild.Id}) - {ex.Message}"); + } + } + } + + private static async Task Register(DiscordSocketClient client, IEnumerable commandsInContext, SocketGuild guild) + { + foreach (var existingCommand in commandsInContext) + { + var myVersion = slashCommands.FirstOrDefault(c => c.Id == existingCommand.Name && c.guild == guild?.Id); + if (myVersion == null) + { + Console.WriteLine($"deleting command {existingCommand.Name} - (created at {existingCommand.CreatedAt}, it's in guild {existingCommand.Guild?.Id} while I'm in {guild?.Id})"); + await existingCommand.DeleteAsync(); + Console.WriteLine("survived"); + } + else + { + Console.WriteLine(existingCommand.CreatedAt); + if (myVersion.UpdatedAt > existingCommand.CreatedAt) + { + Console.WriteLine($"overwriting command {existingCommand.Name}"); + await myVersion.register(false, client, guild); + Console.WriteLine($"survived"); + } + myVersion.alreadyRegistered = true; + } + } + foreach (var remaining in slashCommands.Where(sc => sc.alreadyRegistered == false && sc.guild == guild?.Id)) + { + Console.WriteLine($"creating new command {remaining.Id} ({(remaining.guild == null ? "global" : $"for guild {remaining.guild}")})"); + await remaining.register(true, client, guild); + Console.WriteLine($"survived"); + } + } + + private static async Task register_FreedomUnits(bool isNew, DiscordSocketClient client, SocketGuild guild) + { + var builtCommand = new SlashCommandBuilder() + .WithName("freedomunits") + .WithDescription("convert between misc units (currency: iso 4217 code)") + .AddOption("amount", ApplicationCommandOptionType.Number, "source amount", isRequired: true) + .AddOption(new SlashCommandOptionBuilder() + .WithName("src-unit") + .WithDescription("unit converting FROM") + .WithRequired(true) + .WithType(ApplicationCommandOptionType.String)) + .AddOption(new SlashCommandOptionBuilder() + .WithName("dest-unit") + .WithDescription("unit converting TO") + .WithRequired(true) + .WithType(ApplicationCommandOptionType.String)) + .Build(); + try + { + if (guild != null) + { + if (isNew) + await guild.CreateApplicationCommandAsync(builtCommand); + else + await guild.BulkOverwriteApplicationCommandAsync(new ApplicationCommandProperties[] { builtCommand }); + } + else + { + if (isNew) + await client.CreateGlobalApplicationCommandAsync(builtCommand); + else + await client.BulkOverwriteGlobalApplicationCommandsAsync(new ApplicationCommandProperties[] { builtCommand }); + } + } + catch (HttpException exception) + { + var json = JsonConvert.SerializeObject(exception.Errors, Formatting.Indented); + Console.Error.WriteLine(json); + } + } + public static async Task SlashCommandHandler(SocketSlashCommand command) + { + switch(command.CommandName) + { + case "freedomunits": + try + { + var amt = Convert.ToDecimal((double)(command.Data.Options.First(o => o.Name == "amount").Value)); + var src = (string)command.Data.Options.First(o => o.Name == "src-unit").Value; + var dest = (string)command.Data.Options.First(o => o.Name == "dest-unit").Value; + var conversionResult = Conversion.Converter.Convert(amt, src, dest); + + await command.RespondAsync($"> {amt} {src} -> {dest}\n{conversionResult}"); + } + catch(Exception e) + { + await command.RespondAsync($"error: {e.Message}. aaadam!"); + } + break; + default: + await command.RespondAsync($"\\*smiles and nods*\n"); + await command.Channel.SendFileAsync($"assets/loud sweating.gif"); + Console.Error.WriteLine($"can't understand command name: {command.CommandName}"); + break; + } + } + private class CommandSetup + { + public string Id { get; set; } + //the date/time you updated yours IN UTC. + public DateTimeOffset UpdatedAt { get; set; } + public Registration register { get; set; } + public ulong? guild { get; set; } + public bool alreadyRegistered {get;set; } = false; + + public delegate Task Registration(bool isNew, DiscordSocketClient client, SocketGuild guild); + } + } +} \ No newline at end of file diff --git a/assets/loud sweating.gif b/assets/loud sweating.gif new file mode 100644 index 0000000..0845939 Binary files /dev/null and b/assets/loud sweating.gif differ diff --git a/shtikbot-discord.csproj b/shtikbot-discord.csproj index 108e1f5..f49c06c 100644 --- a/shtikbot-discord.csproj +++ b/shtikbot-discord.csproj @@ -28,6 +28,9 @@ Always + + Always + Never