fix(bot): generate and attach color previews

This commit is contained in:
asleepyskye 2025-07-16 11:48:48 -04:00
parent 497bee9487
commit 3ad28eb15f
5 changed files with 47 additions and 15 deletions

View file

@ -82,7 +82,7 @@ public class Context
internal readonly ModelRepository Repository;
internal readonly RedisService Redis;
public async Task<Message> Reply(string text = null, Embed embed = null, AllowedMentions? mentions = null)
public async Task<Message> Reply(string text = null, Embed embed = null, AllowedMentions? mentions = null, MultipartFile[]? files = null)
{
var botPerms = await BotPermissions;
@ -92,6 +92,9 @@ public class Context
if (embed != null && !botPerms.HasFlag(PermissionSet.EmbedLinks))
throw new PKError("PluralKit does not have permission to send embeds in this channel. Please ensure I have the **Embed Links** permission enabled.");
if (files != null && !botPerms.HasFlag(PermissionSet.AttachFiles))
throw new PKError("PluralKit does not have permission to attach files in this channel. Please ensure I have the **Attach Files** permission enabled.");
var msg = await Rest.CreateMessage(Channel.Id, new MessageRequest
{
@ -99,7 +102,7 @@ public class Context
Embeds = embed != null ? new[] { embed } : null,
// Default to an empty allowed mentions object instead of null (which means no mentions allowed)
AllowedMentions = mentions ?? new AllowedMentions()
});
}, files: files);
// store log of sent message, so it can be queried or deleted later
// skip DMs as DM messages can always be deleted

View file

@ -443,10 +443,11 @@ public class Groups
await ctx.Reply(embed: new EmbedBuilder()
.Title("Group color")
.Color(target.Color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{target.Color}/?text=%20"))
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Description($"This group's color is **#{target.Color}**."
+ (isOwnSystem ? $" To clear it, type `{ctx.DefaultPrefix}group {target.Reference(ctx)} color -clear`." : ""))
.Build());
.Build(),
files: [MiscUtils.GenerateColorPreview(target.Color)]);
return;
}
@ -471,8 +472,9 @@ public class Groups
await ctx.Reply(embed: new EmbedBuilder()
.Title($"{Emojis.Success} Group color changed.")
.Color(color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{color}/?text=%20"))
.Build());
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Build(),
files: [MiscUtils.GenerateColorPreview(color)]);
}
}

View file

@ -308,10 +308,11 @@ public class MemberEdit
await ctx.Reply(embed: new EmbedBuilder()
.Title("Member color")
.Color(target.Color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{target.Color}/?text=%20"))
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Description($"This member's color is **#{target.Color}**."
+ (isOwnSystem ? $" To clear it, type `{ctx.DefaultPrefix}member {target.Reference(ctx)} color -clear`." : ""))
.Build());
.Build(),
files: [MiscUtils.GenerateColorPreview(target.Color)]);
return;
}
@ -336,8 +337,9 @@ public class MemberEdit
await ctx.Reply(embed: new EmbedBuilder()
.Title($"{Emojis.Success} Member color changed.")
.Color(color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{color}/?text=%20"))
.Build());
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Build(),
files: [MiscUtils.GenerateColorPreview(color)]);
}
}

View file

@ -241,10 +241,11 @@ public class SystemEdit
await ctx.Reply(embed: new EmbedBuilder()
.Title("System color")
.Color(target.Color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{target.Color}/?text=%20"))
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Description(
$"This system's color is **#{target.Color}**." + (isOwnSystem ? $" To clear it, type `{ctx.DefaultPrefix}s color -clear`." : ""))
.Build());
.Build(),
files: [MiscUtils.GenerateColorPreview(target.Color)]);
return;
}
@ -269,8 +270,9 @@ public class SystemEdit
await ctx.Reply(embed: new EmbedBuilder()
.Title($"{Emojis.Success} System color changed.")
.Color(color.ToDiscordColor())
.Thumbnail(new Embed.EmbedThumbnail($"https://fakeimg.pl/256x256/{color}/?text=%20"))
.Build());
.Thumbnail(new Embed.EmbedThumbnail($"attachment://color.gif"))
.Build(),
files: [MiscUtils.GenerateColorPreview(color)]);
}
}

View file

@ -1,7 +1,8 @@
using System.Net;
using System.Net.Sockets;
using System.Globalization;
using Myriad.Rest.Exceptions;
using Myriad.Rest.Types;
using Newtonsoft.Json;
@ -102,4 +103,26 @@ public static class MiscUtils
return true;
}
public static MultipartFile GenerateColorPreview(string color)
{
//generate a 128x128 solid color gif from bytes
//image data is a 1x1 pixel, using the background color to fill the rest of the canvas
var imgBytes = new byte[]
{
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // Header
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, // Logical Screen Descriptor
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, // Global Color Table
0x21, 0xF9, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, // Graphics Control Extension
0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, // Image Descriptor
0x02, 0x02, 0x4C, 0x01, 0x00, // Image Data
0x3B // Trailer
}; //indices 13, 14 and 15 are the R, G, and B values respectively
imgBytes[13] = byte.Parse(color.Substring(0, 2), NumberStyles.HexNumber);
imgBytes[14] = byte.Parse(color.Substring(2, 2), NumberStyles.HexNumber);
imgBytes[15] = byte.Parse(color.Substring(4, 2), NumberStyles.HexNumber);
return new MultipartFile("color.gif", new MemoryStream(imgBytes), null, null, null);
}
}