Merge pull request #5 from SkyJoshua/dev

Dev
This commit is contained in:
SkyJoshua
2026-03-20 20:08:44 +00:00
committed by GitHub
3 changed files with 125 additions and 2 deletions

View File

@@ -12,7 +12,7 @@ namespace SkyBot.Commands
public string Name => "cat"; public string Name => "cat";
public string[] Aliases => []; public string[] Aliases => [];
public string Description => "Posts a random cat picture."; public string Description => "Posts a random cat picture.";
public string Section => "Fun"; public string Section => "Chill";
public string Usage => "cat"; public string Usage => "cat";
private static readonly HttpClient _http = new(); private static readonly HttpClient _http = new();

View File

@@ -0,0 +1,123 @@
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 Hug : ICommand
{
public string Name => "hug";
public string[] Aliases => [];
public string Description => "Send a hug with a random gif.";
public string Section => "Chill";
public string Usage => "hug [@user]";
private static readonly HttpClient _http = new()
{
DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0" } }
};
public async Task Execute(CommandContext ctx)
{
ConcurrentDictionary<long, Channel> channelCache = ctx.ChannelCache;
long channelId = ctx.ChannelId;
if (!channelCache.TryGetValue(channelId, out var channel)) return;
await channel.SendIsTyping();
// Fetch a random hug gif from nekos.best
string json;
try
{
json = await _http.GetStringAsync("https://nekos.best/api/v2/hug");
}
catch
{
await MessageHelper.ReplyAsync(ctx, channel, "Could not fetch a hug gif. Try again later.");
return;
}
using var doc = JsonDocument.Parse(json);
var results = doc.RootElement.GetProperty("results");
string gifUrl = results[0].GetProperty("url").GetString()!;
// Download the gif bytes
byte[] gifBytes;
try
{
gifBytes = await _http.GetByteArrayAsync(gifUrl);
}
catch
{
await MessageHelper.ReplyAsync(ctx, channel, "Could not download the hug gif. Try again later.");
return;
}
// Read GIF dimensions from header (bytes 6-9, little-endian)
int width = 0, height = 0;
if (gifBytes.Length >= 10)
{
width = gifBytes[6] | (gifBytes[7] << 8);
height = gifBytes[8] | (gifBytes[9] << 8);
}
// Upload to Valour CDN
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", "hug.gif");
var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse<string>("upload/image", form);
if (!uploadResult.Success)
{
await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the hug gif. Try again later.");
return;
}
cdnUrl = uploadResult.Data!;
}
catch
{
await MessageHelper.ReplyAsync(ctx, channel, "Could not upload the hug gif. Try again later.");
return;
}
// Resolve the hug target: replied-to message author > args > nobody
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} hugs {target}! 🤗"
: $"{sender} wants a hug! 🤗";
var attachment = new MessageAttachment(MessageAttachmentType.Image)
{
Location = cdnUrl,
MimeType = "image/gif",
FileName = "hug.gif",
Width = width,
Height = height
};
await channel.SendMessageAsync(text, attachments: [attachment]);
}
}
}

View File

@@ -11,7 +11,7 @@ namespace SkyBot.Commands
public class GetBans : ICommand public class GetBans : ICommand
{ {
public string Name => "bans"; public string Name => "bans";
public string[] Aliases => [""]; public string[] Aliases => [];
public string Description => "Lists all bans in the planet."; public string Description => "Lists all bans in the planet.";
public string Section => "Mod"; public string Section => "Mod";
public string Usage => "bans [page]"; public string Usage => "bans [page]";