0.3.3.0
This commit is contained in:
@@ -57,7 +57,7 @@ namespace SkyBot.Commands
|
||||
builder.embed.HideChangePageArrows = true;
|
||||
|
||||
// Home page
|
||||
builder.AddPage("✦ Help Menu", $"Prefix: {Config.Prefix}");
|
||||
builder.AddPage("✦ Help Menu", $"Prefix: {Config.Prefix} | <> = required [] = optional");
|
||||
builder.AddRow()
|
||||
.AddText("Select a Category")
|
||||
.WithStyles(EmbedStyles.LabelText)
|
||||
@@ -77,15 +77,15 @@ namespace SkyBot.Commands
|
||||
foreach (var (categoryName, cmds, chunkIndex, totalChunks) in allChunks)
|
||||
{
|
||||
string? footer = totalChunks > 1
|
||||
? $"Page {chunkIndex + 1}/{totalChunks} | Prefix: {Config.Prefix}"
|
||||
: $"Prefix: {Config.Prefix}";
|
||||
? $"Page {chunkIndex + 1}/{totalChunks} | Prefix: {Config.Prefix} | <> = required [] = optional"
|
||||
: $"Prefix: {Config.Prefix} | <> = required [] = optional";
|
||||
|
||||
builder.AddPage($"✦ {categoryName.ToTitleCase()} Commands", footer);
|
||||
|
||||
foreach (var cmd in cmds)
|
||||
{
|
||||
builder.AddRow()
|
||||
.AddButton(cmd.Name)
|
||||
.AddButton(cmd.Name.ToTitleCase())
|
||||
.WithStyles(EmbedStyles.CommandBtn)
|
||||
.OnClickGoToEmbedPage(cmdDetailPage[cmd.Name])
|
||||
.CloseRow();
|
||||
@@ -118,7 +118,7 @@ namespace SkyBot.Commands
|
||||
// Command detail pages
|
||||
foreach (var cmd in allCmds)
|
||||
{
|
||||
builder.AddPage($"✦ {cmd.Name.ToTitleCase()}", $"Prefix: {Config.Prefix}");
|
||||
builder.AddPage($"✦ {cmd.Name.ToTitleCase()}", $"Prefix: {Config.Prefix} | <> = required [] = optional");
|
||||
|
||||
builder.AddRow()
|
||||
.AddText("Description", cmd.Description)
|
||||
@@ -141,7 +141,7 @@ namespace SkyBot.Commands
|
||||
if (cmd.SubCommands.Length > 0)
|
||||
{
|
||||
builder.AddRow()
|
||||
.AddText("Sub-commands", string.Join(", ", cmd.SubCommands.Select(s => s.ToTitleCase())))
|
||||
.AddText("Sub-commands", string.Join(", ", cmd.SubCommands.Select(s => s)))
|
||||
.CloseRow();
|
||||
}
|
||||
|
||||
|
||||
107
SkyBot/Commands/Info/Info.cs
Normal file
107
SkyBot/Commands/Info/Info.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using SkyBot.Helpers;
|
||||
using SkyBot.Models;
|
||||
using Superpower.Model;
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Sdk.Models.Messages.Embeds;
|
||||
using Valour.Sdk.Models.Messages.Embeds.Styles;
|
||||
using Valour.Sdk.Models.Messages.Embeds.Styles.Basic;
|
||||
using Valour.Sdk.Models.Messages.Embeds.Styles.Flex;
|
||||
using Valour.Shared.Models;
|
||||
|
||||
namespace SkyBot.Commands
|
||||
{
|
||||
public class Info : ICommand
|
||||
{
|
||||
public string Name => "info";
|
||||
public string[] Aliases => [];
|
||||
public string Description => "Shows info about a Planet or User";
|
||||
public string Category => "Info";
|
||||
public string Usage => "info <sub> [user]";
|
||||
public string[] SubCommands => ["planet", "user"];
|
||||
|
||||
public async Task Execute(CommandContext ctx)
|
||||
{
|
||||
if (ctx.Args.Length == 0)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "Please specify `planet` or `user`.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ctx.Args[0].ToLower())
|
||||
{
|
||||
case "user":
|
||||
case "u":
|
||||
await HandleUserInfo(ctx);
|
||||
break;
|
||||
|
||||
case "planet":
|
||||
case "p":
|
||||
await HandlePlanetInfo(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
await MessageHelper.ReplyAsync(ctx, "Invalid Option. Use either `planet` or `user`.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleUserInfo(CommandContext ctx)
|
||||
{
|
||||
long memberId = ctx.Message.Mentions?.Any() == true
|
||||
? ctx.Message.Mentions.First().TargetId
|
||||
: long.TryParse(ctx.Args.ElementAtOrDefault(1), out var parsed)
|
||||
? parsed
|
||||
: ctx.Member.Id;
|
||||
PlanetMember member = await ctx.Planet.FetchMemberAsync(memberId);
|
||||
if (member is null)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "Could not find member.");
|
||||
return;
|
||||
}
|
||||
|
||||
var b = new EmbedBuilder()
|
||||
.AddPage($"{member.Name.Trim()}'s Info")
|
||||
.WithTitleStyles(new TextColor(member.PrimaryRole.Color))
|
||||
// .AddMedia(MessageAttachmentType.Image, 64, 64, "image/webp", "avatar.webp", member.GetAvatar(AvatarFormat.Webp64))
|
||||
// .WithStyles(
|
||||
// new Position(right: new Size(Unit.Pixels, 8), top: new Size(Unit.Pixels, 8)),
|
||||
// new Width(new Size(Unit.Pixels, 64)),
|
||||
// new Height(new Size(Unit.Pixels, 64)),
|
||||
// new BorderRadius(new Size(Unit.Percent, 50))
|
||||
// )
|
||||
.AddRow().AddText("Member ID", member.Id.ToString()).WithStyles(new TextColor("#ff9d00")).CloseRow()
|
||||
.AddRow().AddText("User ID", member.UserId.ToString()).WithStyles(new TextColor("#ff9d00")).CloseRow()
|
||||
.AddRow().AddText("Nickname", string.IsNullOrWhiteSpace(member.Nickname) ? "None" : member.Nickname).WithStyles(new TextColor(string.IsNullOrWhiteSpace(member.Nickname) ? "#ffed4a" : member.PrimaryRole.Color)).CloseRow()
|
||||
.AddRow().AddText("Subscription", string.IsNullOrWhiteSpace(member.User.SubscriptionType) ? "None" : member.User.SubscriptionType).WithStyles(new TextColor(member.User.HasStargazer ? member.User.GetStarColor1() : "#ffed4a")).CloseRow()
|
||||
.AddRow().AddText("Status", string.IsNullOrWhiteSpace(member.Status) ? "None" : member.Status).WithStyles(new TextColor("#ffed4a")).CloseRow()
|
||||
.AddRow().AddText("Primary Role", member.PrimaryRole.Name).WithStyles(new TextColor(member.PrimaryRole.Color)).CloseRow()
|
||||
.AddRow().AddText("Roles", string.Join(", ", member.Roles.Select(r => r.Name))).WithStyles(new TextColor(member.Roles[Random.Shared.Next(member.Roles.Count)].Color)).CloseRow()
|
||||
.AddRow().AddText("Account Created", member.User.TimeJoined.ToString()).WithStyles(new TextColor("#979797")).CloseRow();
|
||||
|
||||
await MessageHelper.ReplyAsync(ctx, null, b.embed);
|
||||
}
|
||||
|
||||
private async Task HandlePlanetInfo(CommandContext ctx)
|
||||
{
|
||||
PlanetMember pOwner = await ctx.Planet.FetchMemberByUserAsync(ctx.Planet.OwnerId);
|
||||
EmbedBuilder b = new EmbedBuilder()
|
||||
.AddPage($"{ctx.Planet.Name}'s Info")
|
||||
.AddRow().AddText("Planet ID", ctx.Planet.Id.ToString()).CloseRow()
|
||||
.AddRow().AddText("Planet Description", ctx.Planet.Description).CloseRow()
|
||||
.AddRow().AddText("State", ctx.Planet.Public ? ctx.Planet.Discoverable ? "Public (Discoverable)" : "Public (Not Discoverable)" : "Private").CloseRow()
|
||||
.AddRow().AddText("NSFW", ctx.Planet.Nsfw.ToString()).CloseRow()
|
||||
.AddRow().AddText("Owner Name (ID)", $"{pOwner.Name} ({pOwner.Id})").CloseRow()
|
||||
.AddRow().AddText("Members", ctx.Planet.Members.Count.ToString())
|
||||
.AddText("Channels", ctx.Planet.Channels.Count.ToString())
|
||||
.AddText("Roles", ctx.Planet.Roles.Count.ToString()).CloseRow()
|
||||
;
|
||||
|
||||
await MessageHelper.ReplyAsync(ctx, null, b.embed);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
53
SkyBot/Commands/Mods/Ban.cs
Normal file
53
SkyBot/Commands/Mods/Ban.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
using SkyBot.Helpers;
|
||||
using SkyBot.Models;
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Shared.Authorization;
|
||||
|
||||
namespace SkyBot.Commands
|
||||
{
|
||||
public class Ban : ICommand
|
||||
{
|
||||
public string Name => "ban";
|
||||
public string[] Aliases => [];
|
||||
public string Description => "Bans a member from the planet.";
|
||||
public string Category => "Mod";
|
||||
public string Usage => "ban <@member> [reason]";
|
||||
public string[] SubCommands => [];
|
||||
|
||||
public async Task Execute(CommandContext ctx)
|
||||
{
|
||||
if (!await PermissionHelper.HasPermAsync(ctx.Member, [PlanetPermissions.Ban]))
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"You dont have permission to execute this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await PermissionHelper.HasPermAsync(ctx.Planet.MyMember, [PlanetPermissions.Ban]))
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"I don't have permission to ban members.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.Message.Mentions?.Any() != true && ctx.Args.Length < 1)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "Mention a member or enter their ID to ban them.");
|
||||
return;
|
||||
}
|
||||
|
||||
long? targetId = ctx.Message.Mentions?.Any() == true ? ctx.Message.Mentions.First().TargetId : long.TryParse(ctx.Args.ElementAtOrDefault(0), out long parsed) ? parsed : null;
|
||||
if (targetId is null) {await MessageHelper.ReplyAsync(ctx, "Could not find user."); return;};
|
||||
|
||||
User victim = await ctx.Client.UserService.FetchUserAsync(targetId.Value);
|
||||
if (victim is null) {await MessageHelper.ReplyAsync(ctx, "Could not find user."); return;};
|
||||
|
||||
DateTime? expires = ctx.Args.Select(MessageHelper.ParseDuration).FirstOrDefault(x => x != null);
|
||||
|
||||
string reason = string.Join(" ", ctx.Args.Skip(1).Where(a => MessageHelper.ParseDuration(a) is null));
|
||||
if (string.IsNullOrWhiteSpace(reason)) reason = "No reason provided";
|
||||
|
||||
await ctx.Planet.BanAsync(victim.Id, reason, expires);
|
||||
await MessageHelper.ReplyAsync(ctx, $"Banned {victim.NameAndTag}. Reason: `{reason}`. Expires: `{(expires.HasValue ? expires + " UTC" : "Never")}`");
|
||||
}
|
||||
}
|
||||
}
|
||||
83
SkyBot/Commands/Mods/Kick.cs
Normal file
83
SkyBot/Commands/Mods/Kick.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Drawing;
|
||||
using SkyBot.Helpers;
|
||||
using SkyBot.Models;
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Sdk.Models.Messages.Embeds;
|
||||
using Valour.Sdk.Models.Messages.Embeds.Styles.Basic;
|
||||
using Valour.Shared.Authorization;
|
||||
|
||||
namespace SkyBot.Commands
|
||||
{
|
||||
public class Kick : ICommand
|
||||
{
|
||||
public string Name => "Kick";
|
||||
public string[] Aliases => [];
|
||||
public string Description => "Kicks a member from the planet.";
|
||||
public string Category => "Mod";
|
||||
public string Usage => "kick <@member> [reason]";
|
||||
public string[] SubCommands => [];
|
||||
|
||||
public async Task Execute(CommandContext ctx)
|
||||
{
|
||||
if (!await PermissionHelper.HasPermAsync(ctx.Member, [PlanetPermissions.Kick]))
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "You don't have permission to execute this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await PermissionHelper.HasPermAsync(ctx.Planet.MyMember, [PlanetPermissions.Kick]))
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "I don't have permission to kick members.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.Message.Mentions?.Any() != true && ctx.Args.Length < 1)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, "Mention a member or enter their ID to kick them.");
|
||||
return;
|
||||
}
|
||||
|
||||
long? targetId = ctx.Message.Mentions?.Any() == true ? ctx.Message.Mentions.First().TargetId : long.TryParse(ctx.Args.ElementAtOrDefault(0), out long parsed) ? parsed : null;
|
||||
if (targetId is null) {await MessageHelper.ReplyAsync(ctx, "Could not find member."); return;};
|
||||
|
||||
PlanetMember offender = await ctx.Planet.FetchMemberAsync(targetId.Value);
|
||||
if (offender is null) {await MessageHelper.ReplyAsync(ctx, "Could not find member."); return;};
|
||||
|
||||
string reason = string.Join(" ", ctx.Args.Skip(1));
|
||||
if (string.IsNullOrWhiteSpace(reason)) reason = "No reason provided";
|
||||
|
||||
EmbedBuilder p = new EmbedBuilder()
|
||||
.AddPage("Member Kick", DateTime.UtcNow.ToString())
|
||||
.WithTitleStyles(new TextColor("#ff9900"))
|
||||
.WithFooterStyles(new TextColor("#555555"))
|
||||
.AddRow()
|
||||
.AddText("Offender", offender.User.NameAndTag)
|
||||
.WithStyles(new TextColor("#ff9900"))
|
||||
.CloseRow()
|
||||
.AddRow()
|
||||
.AddText("Issuer", ctx.Member.User.NameAndTag)
|
||||
.WithStyles(new TextColor("#ff9900"))
|
||||
.CloseRow()
|
||||
.AddText("Reason", reason)
|
||||
.WithStyles(new TextColor("#ff9900"))
|
||||
.CloseRow();
|
||||
|
||||
EmbedBuilder d = new EmbedBuilder()
|
||||
.AddPage("Kicked from Planet", DateTime.UtcNow.ToString())
|
||||
.WithTitleStyles(new TextColor("#ff9900"))
|
||||
.WithFooterStyles(new TextColor("#555555"))
|
||||
.AddRow()
|
||||
.AddText("Planet (ID)", $"{ctx.Planet.Name} ({ctx.Planet.Id})")
|
||||
.WithStyles(new TextColor("#ff9900"))
|
||||
.CloseRow()
|
||||
.AddRow()
|
||||
.AddText("Reason", reason)
|
||||
.WithStyles(new TextColor("#ff9900"))
|
||||
.CloseRow();
|
||||
|
||||
await offender.User.SendDirectMessageAsync(ctx.Client, null, d.embed);
|
||||
await offender.DeleteAsync();
|
||||
await MessageHelper.ReplyAsync(ctx, null, p.embed);
|
||||
}
|
||||
};
|
||||
}
|
||||
163
SkyBot/Commands/RP/Emote.cs
Normal file
163
SkyBot/Commands/RP/Emote.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System.Text.Json;
|
||||
using SkyBot.Helpers;
|
||||
using SkyBot.Models;
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Shared.Models;
|
||||
|
||||
namespace SkyBot.Commands
|
||||
{
|
||||
public class Emote : ICommand
|
||||
{
|
||||
public string Name => "emote";
|
||||
public string[] Aliases => ["e", "action"];
|
||||
public string Description => "RP emote actions.";
|
||||
public string Category => "RP";
|
||||
public string Usage => "emote <action> [@user]";
|
||||
public string[] SubCommands => ["angry", "baka", "bite", "blowkiss", "blush", "bonk", "carry", "clap", "cry", "cuddle", "dance", "facepalm", "happy", "holdhand", "hug", "kiss", "laugh", "lurk", "nom", "nya", "pat", "poke", "pout", "punch", "run", "shocked", "sleep", "smug", "spin", "tableflip", "teehee", "tickle", "wave", "wink", "yawn"];
|
||||
|
||||
private static readonly HttpClient _http = new()
|
||||
{
|
||||
DefaultRequestHeaders = { { "User-Agent", "SkyBot/1.0 (https://skyjoshua.xyz, https://valour.gg)" } }
|
||||
};
|
||||
|
||||
public async Task Execute(CommandContext ctx)
|
||||
{
|
||||
switch (ctx.Args.ElementAtOrDefault(0)?.ToLower())
|
||||
{
|
||||
case "angry": await SendAction(ctx, "angry", "{0} is angry at {1}! 😠", "{0} is angry! 😠", false); break;
|
||||
case "baka": await SendAction(ctx, "baka", "{0} calls {1} a baka!", "Please mention someone who is a baka!", true); break;
|
||||
case "bite": await SendAction(ctx, "bite", "{0} bites {1}!", "Please mention someone to bite!", true); break;
|
||||
case "blowkiss": await SendAction(ctx, "blowkiss", "{0} blows a kiss to {1}!", "Please mention someone to blow a kiss too!", true); break;
|
||||
case "blush": await SendAction(ctx, "blush", "{0} is blushing at {1}!", "{0} is blushing!", false); break;
|
||||
case "bonk": await SendAction(ctx, "bonk", "{0} bonks {1}!", "Please mention someone to bonk!", true); break;
|
||||
case "carry": await SendAction(ctx, "carry", "{0} carries {1}!", "Please mention someone to carry!", true); break;
|
||||
case "clap": await SendAction(ctx, "clap", "{0} claps for {1}!", "{0} is clapping!", false); break;
|
||||
case "cry": await SendAction(ctx, "cry", "{0} is crying because of {1}!", "{0} is crying!", false); break;
|
||||
case "cuddle": await SendAction(ctx, "cuddle", "{0} cuddles with {1}!", "Please mention someone to cuddle!", true); break;
|
||||
case "dance": await SendAction(ctx, "dance", "{0} dances with {1}!", "{0} is dancing!", false); break;
|
||||
case "facepalm": await SendAction(ctx, "facepalm", "{0} facepalms at {1}!", "{0} facepalms!", false); break;
|
||||
case "happy": await SendAction(ctx, "happy", "{0} is happy with {1}!", "{0} is happy!", false); break;
|
||||
case "holdhand": await SendAction(ctx, "handhold", "{0} holds hands with {1}!", "Please mention someone to hold hands with!", true); break;
|
||||
case "hug": await SendAction(ctx, "hug", "{0} hugs {1}!", "Please mention someone to hug!", true); break;
|
||||
case "kiss": await SendAction(ctx, "kiss", "{0} kisses {1}!", "Please mention someone to kiss!", true); break;
|
||||
case "laugh": await SendAction(ctx, "laugh", "{0} laughs at {1}!", "{0} is laughing!", false); break;
|
||||
case "lurk": await SendAction(ctx, "lurk", "{0} lurks around {1}!", "{0} is lurking!", false); break;
|
||||
case "nom": await SendAction(ctx, "nom", "{0} noms on {1}!", "{0} is nomming!", false); break;
|
||||
case "nya": await SendAction(ctx, "nya", "{0} nyas at {1}!", "{0} nyas!", false); break;
|
||||
case "pat": await SendAction(ctx, "pat", "{0} gives {1} headpats!", "Please mention someone to give heatpats too!", true); break;
|
||||
case "poke": await SendAction(ctx, "poke", "{0} pokes {1}!", "Please mention someone to poke!", true); break;
|
||||
case "pout": await SendAction(ctx, "pout", "{0} pouts at {1}!", "{0} is pouting!", false); break;
|
||||
case "punch": await SendAction(ctx, "punch", "{0} punches {1}!", "Please mention someone to punch!", true); break;
|
||||
case "run": await SendAction(ctx, "run", "{0} runs away from {1}!", "{0} runs away!", false); break;
|
||||
case "shocked": await SendAction(ctx, "shocked", "{0} is shocked by {1}!", "{0} is shocked!", false); break;
|
||||
case "sleep": await SendAction(ctx, "sleep", "{0} falls asleep on {1}!", "{0} is sleeping! zzz...", false); break;
|
||||
case "smug": await SendAction(ctx, "smug", "{0} looks smug at {1}!", "{0} is feeling smug!", false); break;
|
||||
case "spin": await SendAction(ctx, "spin", "{0} spins {1} around!", "{0} is spinning!", false); break;
|
||||
case "tableflip": await SendAction(ctx, "tableflip", "{0} flips the table at {1}! (╯°□°)╯︵ ┻━┻", "{0} flips the table! (╯°□°)╯︵ ┻━┻", false); break;
|
||||
case "teehee": await SendAction(ctx, "teehee", "{0} teehees at {1}!", "{0} teehees~", false); break;
|
||||
case "tickle": await SendAction(ctx, "tickle", "{0} tickles {1}!", "Please mention someone to tickle!", true); break;
|
||||
case "wave": await SendAction(ctx, "wave", "{0} waves at {1}!", "{0} waves!", false); break;
|
||||
case "wink": await SendAction(ctx, "wink", "{0} winks at {1}! ;)", "{0} winks! ;)", false); break;
|
||||
case "yawn": await SendAction(ctx, "yawn", "{0} yawns at {1}!", "{0} is yawning!", false); break;
|
||||
default:
|
||||
await MessageHelper.ReplyAsync(ctx, $"Unknown emote. Usage: `{Config.Prefix}emote <action>`\nActions: {string.Join(", ", SubCommands)}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task SendAction(CommandContext ctx, string apiAction, string withTarget, string withoutTarget, bool requiresTarget = false)
|
||||
{
|
||||
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 > 1)
|
||||
target = string.Join(" ", ctx.Args[1..]);
|
||||
|
||||
if (requiresTarget && target is null)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, withoutTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.Channel.SendIsTyping();
|
||||
|
||||
string json;
|
||||
try
|
||||
{
|
||||
json = await _http.GetStringAsync($"https://nekos.best/api/v2/{apiAction}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"Could not fetch a {apiAction} gif. Try again later.");
|
||||
return;
|
||||
}
|
||||
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
string gifUrl = doc.RootElement.GetProperty("results")[0].GetProperty("url").GetString()!;
|
||||
|
||||
byte[] gifBytes;
|
||||
try
|
||||
{
|
||||
gifBytes = await _http.GetByteArrayAsync(gifUrl);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"Could not download the {apiAction} 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", $"{apiAction}.gif");
|
||||
|
||||
var uploadResult = await ctx.Planet.Node.PostMultipartDataWithResponse<string>("upload/image", form);
|
||||
if (!uploadResult.Success)
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"Could not upload the {apiAction} gif. Try again later.");
|
||||
return;
|
||||
}
|
||||
cdnUrl = uploadResult.Data!;
|
||||
}
|
||||
catch
|
||||
{
|
||||
await MessageHelper.ReplyAsync(ctx, $"Could not upload the {apiAction} gif. Try again later.");
|
||||
return;
|
||||
}
|
||||
|
||||
string sender = ctx.Member.Nickname ?? ctx.Member.User?.Name ?? "Unknown";
|
||||
string text = target is not null
|
||||
? string.Format(withTarget, sender, target)
|
||||
: string.Format(withoutTarget, sender);
|
||||
|
||||
var attachment = new MessageAttachment(MessageAttachmentType.Image)
|
||||
{
|
||||
Location = cdnUrl,
|
||||
MimeType = "image/gif",
|
||||
FileName = $"{apiAction}.gif",
|
||||
Width = width,
|
||||
Height = height
|
||||
};
|
||||
|
||||
await MessageHelper.ReplyAsync(ctx, text, attachments: [attachment]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace SkyBot.Commands
|
||||
public string[] Aliases => ["marry"];
|
||||
public string Description => "Marriage system — propose, check status, or divorce.";
|
||||
public string Category => "RP";
|
||||
public string Usage => "marriage <sub>";
|
||||
public string Usage => "marriage <action>";
|
||||
public string[] SubCommands => ["propose", "status", "divorce", "force"];
|
||||
|
||||
public async Task Execute(CommandContext ctx)
|
||||
@@ -130,7 +130,7 @@ namespace SkyBot.Commands
|
||||
long partnerId = marriage.SpouseId;
|
||||
DateTimeOffset dt = DateTimeOffset.FromUnixTimeMilliseconds(marriage.MarriedAt);
|
||||
string marriedAt = $"{dt.OrdinalDay()} {dt:MMMM yyyy HH:mm} UTC";
|
||||
await MessageHelper.ReplyAsync(ctx, $"{name} is married to «@u-{partnerId}»!\nThey got married: {marriedAt}");
|
||||
await MessageHelper.ReplyAsync(ctx, $"{name} is married to «@u-{partnerId}»!\nThey got married: `{marriedAt}`");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SkyBot.Helpers
|
||||
private static readonly Size PadH = new(Unit.Pixels, 6);
|
||||
private static readonly Size FitContent = new(Unit.FitContent);
|
||||
|
||||
|
||||
public static StyleBase[] LabelText => [
|
||||
new TextColor("#a0a0b8"),
|
||||
new FontWeight(600),
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace SkyBot.Helpers
|
||||
return $"{dt.Day}{suffix}";
|
||||
}
|
||||
|
||||
public static async Task<TaskResult<Message>> ReplyAsync(CommandContext ctx, string? content, Embed? embed = null, bool reply = false)
|
||||
public static async Task<TaskResult<Message>> ReplyAsync(CommandContext ctx, string? content, Embed? embed = null, bool reply = false, IEnumerable<MessageAttachment>? attachments = null)
|
||||
{
|
||||
long? replyToId = reply ? ctx.Message.ReplyToId : ctx.Message.Id;
|
||||
|
||||
@@ -46,6 +46,12 @@ namespace SkyBot.Helpers
|
||||
if (embed is not null)
|
||||
msg.SetEmbed(embed);
|
||||
|
||||
if (attachments is not null)
|
||||
{
|
||||
msg.Attachments ??= [];
|
||||
msg.Attachments.AddRange(attachments);
|
||||
}
|
||||
|
||||
return await ctx.Client.MessageService.SendMessage(msg);
|
||||
}
|
||||
|
||||
@@ -56,5 +62,24 @@ namespace SkyBot.Helpers
|
||||
return await channel.Planet.Node.PutAsyncWithResponse<Message>($"api/messages/{message.Id}", message);
|
||||
}
|
||||
|
||||
public static DateTime? ParseDuration(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input)) return null;
|
||||
|
||||
var unit = input[^1];
|
||||
if (!int.TryParse(input[..^1], out int value)) return null;
|
||||
|
||||
return unit switch
|
||||
{
|
||||
'm' => DateTime.UtcNow.AddMinutes(value),
|
||||
'h' => DateTime.UtcNow.AddHours(value),
|
||||
'd' => DateTime.UtcNow.AddDays(value),
|
||||
'w' => DateTime.UtcNow.AddDays(value * 7),
|
||||
'M' => DateTime.UtcNow.AddMonths(value),
|
||||
'y' => DateTime.UtcNow.AddYears(value),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
33
SkyBot/Helpers/PlanetHelper.cs
Normal file
33
SkyBot/Helpers/PlanetHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Shared;
|
||||
|
||||
namespace SkyBot.Helpers
|
||||
{
|
||||
public static class PlanetHelper
|
||||
{
|
||||
public static Task<TaskResult<PlanetBan>> BanAsync(this Planet planet, long targetUserId, string reason, DateTime? expires = null)
|
||||
{
|
||||
var ban = new PlanetBan(planet.Client)
|
||||
{
|
||||
PlanetId = planet.Id,
|
||||
IssuerId = planet.Client.Me.Id,
|
||||
TargetId = targetUserId,
|
||||
Reason = reason,
|
||||
TimeCreated = DateTime.UtcNow,
|
||||
TimeExpires = expires
|
||||
};
|
||||
return ban.CreateAsync();
|
||||
}
|
||||
|
||||
public static async Task<PlanetBan?> FindBanAsync(this Planet planet, long targetUserId)
|
||||
{
|
||||
var engine = planet.GetBanQueryEngine();
|
||||
await foreach (var ban in engine)
|
||||
{
|
||||
if (ban.TargetId == targetUserId)
|
||||
return ban;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
SkyBot/Helpers/UserHelper.cs
Normal file
29
SkyBot/Helpers/UserHelper.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using SkyBot.Models;
|
||||
using Valour.Sdk.Client;
|
||||
using Valour.Sdk.Models;
|
||||
using Valour.Sdk.Models.Messages.Embeds;
|
||||
using Valour.Shared;
|
||||
|
||||
namespace SkyBot.Helpers
|
||||
{
|
||||
public static class UserHelper
|
||||
{
|
||||
public static async Task<TaskResult<Message>> SendDirectMessageAsync(this User user, ValourClient client, string? content, Embed? embed = null)
|
||||
{
|
||||
var channelResult = await client.PrimaryNode.GetJsonAsync<Channel>($"api/channels/direct/byUser/{user.Id}");
|
||||
if (!channelResult.Success)
|
||||
return new TaskResult<Message>(false, "Could not open DM channel.");
|
||||
|
||||
var msg = new Message(client)
|
||||
{
|
||||
Content = content,
|
||||
ChannelId = channelResult.Data.Id,
|
||||
AuthorUserId = client.Me.Id,
|
||||
Fingerprint = Guid.NewGuid().ToString()
|
||||
};
|
||||
msg.SetEmbed(embed);
|
||||
|
||||
return await client.MessageService.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.3.2.0</Version>
|
||||
<Version>0.3.3.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user