From 88b647b13473c4c299133ba07d0650a7f81d8779 Mon Sep 17 00:00:00 2001 From: skyjoshua Date: Tue, 31 Mar 2026 20:46:24 +0100 Subject: [PATCH] more roleplay commands --- SkyBot/Commands/{Chill => Fun}/Cat.cs | 2 +- SkyBot/Commands/RP/Angry.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Bite.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Blush.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Bonk.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Cry.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Cuddle.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Facepalm.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Happy.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/{Chill => RP}/Hug.cs | 6 +- SkyBot/Commands/RP/Kiss.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Lurk.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Nom.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/{Chill => RP}/Pat.cs | 6 +- SkyBot/Commands/RP/Poke.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Pout.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Punch.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Run.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Shocked.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Smug.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Tickle.cs | 118 ++++++++++++++++++++++++++ SkyBot/Commands/RP/Yawn.cs | 118 ++++++++++++++++++++++++++ 22 files changed, 2249 insertions(+), 7 deletions(-) rename SkyBot/Commands/{Chill => Fun}/Cat.cs (98%) create mode 100644 SkyBot/Commands/RP/Angry.cs create mode 100644 SkyBot/Commands/RP/Bite.cs create mode 100644 SkyBot/Commands/RP/Blush.cs create mode 100644 SkyBot/Commands/RP/Bonk.cs create mode 100644 SkyBot/Commands/RP/Cry.cs create mode 100644 SkyBot/Commands/RP/Cuddle.cs create mode 100644 SkyBot/Commands/RP/Facepalm.cs create mode 100644 SkyBot/Commands/RP/Happy.cs rename SkyBot/Commands/{Chill => RP}/Hug.cs (96%) create mode 100644 SkyBot/Commands/RP/Kiss.cs create mode 100644 SkyBot/Commands/RP/Lurk.cs create mode 100644 SkyBot/Commands/RP/Nom.cs rename SkyBot/Commands/{Chill => RP}/Pat.cs (96%) create mode 100644 SkyBot/Commands/RP/Poke.cs create mode 100644 SkyBot/Commands/RP/Pout.cs create mode 100644 SkyBot/Commands/RP/Punch.cs create mode 100644 SkyBot/Commands/RP/Run.cs create mode 100644 SkyBot/Commands/RP/Shocked.cs create mode 100644 SkyBot/Commands/RP/Smug.cs create mode 100644 SkyBot/Commands/RP/Tickle.cs create mode 100644 SkyBot/Commands/RP/Yawn.cs diff --git a/SkyBot/Commands/Chill/Cat.cs b/SkyBot/Commands/Fun/Cat.cs similarity index 98% rename from SkyBot/Commands/Chill/Cat.cs rename to SkyBot/Commands/Fun/Cat.cs index dd24f34..186f24c 100644 --- a/SkyBot/Commands/Chill/Cat.cs +++ b/SkyBot/Commands/Fun/Cat.cs @@ -12,7 +12,7 @@ namespace SkyBot.Commands public string Name => "cat"; public string[] Aliases => []; public string Description => "Posts a random cat picture."; - public string Section => "Chill"; + public string Section => "Fun"; public string Usage => "cat"; private static readonly HttpClient _http = new(); diff --git a/SkyBot/Commands/RP/Angry.cs b/SkyBot/Commands/RP/Angry.cs new file mode 100644 index 0000000..9272187 --- /dev/null +++ b/SkyBot/Commands/RP/Angry.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Angry : ICommand + { + public string Name => "angry"; + public string[] Aliases => Array.Empty(); + public string Description => "Express anger with a random gif."; + public string Section => "RP"; + public string Usage => "angry [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/angry"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch an angry gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the angry gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "angry.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the angry gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the angry gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} is angry at {target}! 😠" + : $"{sender} is angry! 😠"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "angry.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Bite.cs b/SkyBot/Commands/RP/Bite.cs new file mode 100644 index 0000000..a7affd7 --- /dev/null +++ b/SkyBot/Commands/RP/Bite.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Bite : ICommand + { + public string Name => "bite"; + public string[] Aliases => ["bites"]; + public string Description => "Bite someone with a random gif."; + public string Section => "RP"; + public string Usage => "bite [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/bite"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a bite gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the bite gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "bite.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the bite gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the bite gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} bites {target}!" + : $"{sender} wants to bite someone!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "bite.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Blush.cs b/SkyBot/Commands/RP/Blush.cs new file mode 100644 index 0000000..412de44 --- /dev/null +++ b/SkyBot/Commands/RP/Blush.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Blush : ICommand + { + public string Name => "blush"; + public string[] Aliases => Array.Empty(); + public string Description => "Blush with a random gif."; + public string Section => "RP"; + public string Usage => "blush [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/blush"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a blush gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the blush gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "blush.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the blush gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the blush gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} is blushing at {target}!" + : $"{sender} is blushing!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "blush.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Bonk.cs b/SkyBot/Commands/RP/Bonk.cs new file mode 100644 index 0000000..e4f50e1 --- /dev/null +++ b/SkyBot/Commands/RP/Bonk.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Bonk : ICommand + { + public string Name => "bonk"; + public string[] Aliases => ["bonks"]; + public string Description => "Bonk someone with a random gif."; + public string Section => "RP"; + public string Usage => "bonk [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/bonk"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a bonk gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the bonk gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "bonk.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the bonk gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the bonk gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} bonks {target}!" + : $"{sender} is bonking!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "bonk.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Cry.cs b/SkyBot/Commands/RP/Cry.cs new file mode 100644 index 0000000..b4efccd --- /dev/null +++ b/SkyBot/Commands/RP/Cry.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Cry : ICommand + { + public string Name => "cry"; + public string[] Aliases => ["cries"]; + public string Description => "Cry with a random gif."; + public string Section => "RP"; + public string Usage => "cry [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/cry"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a cry gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the cry gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "cry.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the cry gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the cry gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} is crying because of {target}!" + : $"{sender} is crying!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "cry.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Cuddle.cs b/SkyBot/Commands/RP/Cuddle.cs new file mode 100644 index 0000000..23d39e4 --- /dev/null +++ b/SkyBot/Commands/RP/Cuddle.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Cuddle : ICommand + { + public string Name => "cuddle"; + public string[] Aliases => ["cuddles"]; + public string Description => "Cuddle someone with a random gif."; + public string Section => "RP"; + public string Usage => "cuddle [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/cuddle"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a cuddle gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the cuddle gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "cuddle.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the cuddle gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the cuddle gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} cuddles with {target}!" + : $"{sender} wants cuddles!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "cuddle.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Facepalm.cs b/SkyBot/Commands/RP/Facepalm.cs new file mode 100644 index 0000000..693e4d3 --- /dev/null +++ b/SkyBot/Commands/RP/Facepalm.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Facepalm : ICommand + { + public string Name => "facepalm"; + public string[] Aliases => Array.Empty(); + public string Description => "Facepalm with a random gif."; + public string Section => "RP"; + public string Usage => "facepalm [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/facepalm"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a facepalm gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the facepalm gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "facepalm.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the facepalm gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the facepalm gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} facepalms at {target}!" + : $"{sender} facepalms!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "facepalm.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Happy.cs b/SkyBot/Commands/RP/Happy.cs new file mode 100644 index 0000000..8b66c23 --- /dev/null +++ b/SkyBot/Commands/RP/Happy.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Happy : ICommand + { + public string Name => "happy"; + public string[] Aliases => Array.Empty(); + public string Description => "Express happiness with a random gif."; + public string Section => "RP"; + public string Usage => "happy [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/happy"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a happy gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the happy gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "happy.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the happy gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the happy gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} is happy with {target}!" + : $"{sender} is happy!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "happy.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/Chill/Hug.cs b/SkyBot/Commands/RP/Hug.cs similarity index 96% rename from SkyBot/Commands/Chill/Hug.cs rename to SkyBot/Commands/RP/Hug.cs index 04e9759..bdd826d 100644 --- a/SkyBot/Commands/Chill/Hug.cs +++ b/SkyBot/Commands/RP/Hug.cs @@ -12,7 +12,7 @@ namespace SkyBot.Commands public string Name => "hug"; public string[] Aliases => ["hugs"]; public string Description => "Send a hug with a random gif."; - public string Section => "Chill"; + public string Section => "RP"; public string Usage => "hug [@user]"; private static readonly HttpClient _http = new() @@ -105,8 +105,8 @@ namespace SkyBot.Commands string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; string text = target is not null - ? $"{sender} hugs {target}! 🤗" - : $"{sender} wants a hug! 🤗"; + ? $"{sender} hugs {target}!" + : $"{sender} wants a hug!"; var attachment = new MessageAttachment(MessageAttachmentType.Image) { diff --git a/SkyBot/Commands/RP/Kiss.cs b/SkyBot/Commands/RP/Kiss.cs new file mode 100644 index 0000000..2c83c2d --- /dev/null +++ b/SkyBot/Commands/RP/Kiss.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Kiss : ICommand + { + public string Name => "kiss"; + public string[] Aliases => ["kisses"]; + public string Description => "Kiss someone with a random gif."; + public string Section => "RP"; + public string Usage => "kiss [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/kiss"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a kiss gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the kiss gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "kiss.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the kiss gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the kiss gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} kisses {target}!" + : $"{sender} wants a kiss!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "kiss.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Lurk.cs b/SkyBot/Commands/RP/Lurk.cs new file mode 100644 index 0000000..b5be608 --- /dev/null +++ b/SkyBot/Commands/RP/Lurk.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Lurk : ICommand + { + public string Name => "lurk"; + public string[] Aliases => ["lurks"]; + public string Description => "Lurk with a random gif."; + public string Section => "RP"; + public string Usage => "lurk [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/lurk"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a lurk gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the lurk gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "lurk.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the lurk gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the lurk gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} lurks around {target}!" + : $"{sender} is lurking!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "lurk.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Nom.cs b/SkyBot/Commands/RP/Nom.cs new file mode 100644 index 0000000..87be9bd --- /dev/null +++ b/SkyBot/Commands/RP/Nom.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Nom : ICommand + { + public string Name => "nom"; + public string[] Aliases => ["noms"]; + public string Description => "Nom on someone with a random gif."; + public string Section => "RP"; + public string Usage => "nom [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/nom"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a nom gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the nom gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "nom.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the nom gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the nom gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} noms on {target}!" + : $"{sender} is nomming!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "nom.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/Chill/Pat.cs b/SkyBot/Commands/RP/Pat.cs similarity index 96% rename from SkyBot/Commands/Chill/Pat.cs rename to SkyBot/Commands/RP/Pat.cs index c023b3d..296aa7b 100644 --- a/SkyBot/Commands/Chill/Pat.cs +++ b/SkyBot/Commands/RP/Pat.cs @@ -12,7 +12,7 @@ namespace SkyBot.Commands public string Name => "pat"; public string[] Aliases => ["pats"]; public string Description => "Give someone headpats with a random gif."; - public string Section => "Chill"; + public string Section => "RP"; public string Usage => "pat [@user]"; private static readonly HttpClient _http = new() @@ -105,8 +105,8 @@ namespace SkyBot.Commands string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; string text = target is not null - ? $"{sender} gives {target} headpats! 🥰" - : $"{sender} wants headpats! 🥰"; + ? $"{sender} gives {target} headpats!" + : $"{sender} wants headpats!"; var attachment = new MessageAttachment(MessageAttachmentType.Image) { diff --git a/SkyBot/Commands/RP/Poke.cs b/SkyBot/Commands/RP/Poke.cs new file mode 100644 index 0000000..571c975 --- /dev/null +++ b/SkyBot/Commands/RP/Poke.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Poke : ICommand + { + public string Name => "poke"; + public string[] Aliases => ["pokes"]; + public string Description => "Poke someone with a random gif."; + public string Section => "RP"; + public string Usage => "poke [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/poke"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a poke gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the poke gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "poke.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the poke gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the poke gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} pokes {target}!" + : $"{sender} is poking around!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "poke.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Pout.cs b/SkyBot/Commands/RP/Pout.cs new file mode 100644 index 0000000..c8a7c94 --- /dev/null +++ b/SkyBot/Commands/RP/Pout.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Pout : ICommand + { + public string Name => "pout"; + public string[] Aliases => ["pouts"]; + public string Description => "Pout with a random gif."; + public string Section => "RP"; + public string Usage => "pout [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/pout"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a pout gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the pout gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "pout.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the pout gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the pout gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} pouts at {target}!" + : $"{sender} is pouting!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "pout.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Punch.cs b/SkyBot/Commands/RP/Punch.cs new file mode 100644 index 0000000..3448d02 --- /dev/null +++ b/SkyBot/Commands/RP/Punch.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Punch : ICommand + { + public string Name => "punch"; + public string[] Aliases => ["punches"]; + public string Description => "Punch someone with a random gif."; + public string Section => "RP"; + public string Usage => "punch [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/punch"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a punch gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the punch gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "punch.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the punch gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the punch gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} punches {target}!" + : $"{sender} is throwing punches!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "punch.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Run.cs b/SkyBot/Commands/RP/Run.cs new file mode 100644 index 0000000..aab30c2 --- /dev/null +++ b/SkyBot/Commands/RP/Run.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Run : ICommand + { + public string Name => "run"; + public string[] Aliases => ["runs"]; + public string Description => "Run away with a random gif."; + public string Section => "RP"; + public string Usage => "run [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/run"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a run gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the run gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "run.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the run gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the run gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} runs away from {target}!" + : $"{sender} runs away!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "run.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Shocked.cs b/SkyBot/Commands/RP/Shocked.cs new file mode 100644 index 0000000..421266a --- /dev/null +++ b/SkyBot/Commands/RP/Shocked.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Shocked : ICommand + { + public string Name => "shocked"; + public string[] Aliases => ["shock"]; + public string Description => "Express shock with a random gif."; + public string Section => "RP"; + public string Usage => "shocked [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/shocked"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a shocked gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the shocked gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "shocked.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the shocked gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the shocked gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} is shocked by {target}!" + : $"{sender} is shocked!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "shocked.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Smug.cs b/SkyBot/Commands/RP/Smug.cs new file mode 100644 index 0000000..bc4c255 --- /dev/null +++ b/SkyBot/Commands/RP/Smug.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Smug : ICommand + { + public string Name => "smug"; + public string[] Aliases => Array.Empty(); + public string Description => "Look smug with a random gif."; + public string Section => "RP"; + public string Usage => "smug [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/smug"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a smug gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the smug gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "smug.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the smug gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the smug gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} looks smug at {target}!" + : $"{sender} is feeling smug!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "smug.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Tickle.cs b/SkyBot/Commands/RP/Tickle.cs new file mode 100644 index 0000000..0d10cb1 --- /dev/null +++ b/SkyBot/Commands/RP/Tickle.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Tickle : ICommand + { + public string Name => "tickle"; + public string[] Aliases => ["tickles"]; + public string Description => "Tickle someone with a random gif."; + public string Section => "RP"; + public string Usage => "tickle [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/tickle"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a tickle gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the tickle gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "tickle.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the tickle gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the tickle gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} tickles {target}!" + : $"{sender} wants to tickle someone!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "tickle.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +} diff --git a/SkyBot/Commands/RP/Yawn.cs b/SkyBot/Commands/RP/Yawn.cs new file mode 100644 index 0000000..edea527 --- /dev/null +++ b/SkyBot/Commands/RP/Yawn.cs @@ -0,0 +1,118 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using SkyBot.Helpers; +using SkyBot.Models; +using Valour.Sdk.Models; +using Valour.Shared.Models; + +namespace SkyBot.Commands +{ + public class Yawn : ICommand + { + public string Name => "yawn"; + public string[] Aliases => ["yawns"]; + public string Description => "Yawn with a random gif."; + public string Section => "RP"; + public string Usage => "yawn [@user]"; + + private static readonly HttpClient _http = new() + { + DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } } + }; + + public async Task Execute(CommandContext ctx) + { + ConcurrentDictionary channelCache = ctx.ChannelCache; + long channelId = ctx.ChannelId; + + if (!channelCache.TryGetValue(channelId, out var channel)) return; + + await channel.SendIsTyping(); + + string json; + try + { + json = await _http.GetStringAsync("https://nekos.best/api/v2/yawn"); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a yawn gif. Try again later."); + return; + } + + using var doc = JsonDocument.Parse(json); + var results = doc.RootElement.GetProperty("results"); + string gifUrl = results[0].GetProperty("url").GetString()!; + + byte[] gifBytes; + try + { + gifBytes = await _http.GetByteArrayAsync(gifUrl); + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not download the yawn gif. Try again later."); + return; + } + + int width = 0, height = 0; + if (gifBytes.Length >= 10) + { + width = gifBytes[6] | (gifBytes[7] << 8); + height = gifBytes[8] | (gifBytes[9] << 8); + } + + string cdnUrl; + try + { + using var form = new MultipartFormDataContent(); + using var fileContent = new ByteArrayContent(gifBytes); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/gif"); + form.Add(fileContent, "file", "yawn.gif"); + + var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse("upload/image", form); + if (!uploadResult.Success) + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the yawn gif. Try again later."); + return; + } + cdnUrl = uploadResult.Data!; + } + catch + { + await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the yawn gif. Try again later."); + return; + } + + string? target = null; + if (ctx.Message.ReplyToId is not null) + { + var replied = await ctx.Message.FetchReplyMessageAsync(); + if (replied is not null) + { + var author = await replied.FetchAuthorAsync(); + if (author is not null) + target = author.Name; + } + } + if (target is null && ctx.Args.Length > 0) + target = string.Join(" ", ctx.Args); + + string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown"; + string text = target is not null + ? $"{sender} yawns at {target}!" + : $"{sender} is yawning!"; + + var attachment = new MessageAttachment(MessageAttachmentType.Image) + { + Location = cdnUrl, + MimeType = "image/gif", + FileName = "yawn.gif", + Width = width, + Height = height + }; + + await MessageHelper.ReplyAsync(ctx, channel, text, [attachment]); + } + } +}