From 8bca02032f53bd4f1d25519e285f5a850830e0d1 Mon Sep 17 00:00:00 2001 From: asleepyskye Date: Tue, 9 Sep 2025 10:43:00 -0400 Subject: [PATCH 1/2] feat(bot): add utility admin command --- PluralKit.Bot/CommandMeta/CommandTree.cs | 2 ++ PluralKit.Bot/Commands/Admin.cs | 30 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/PluralKit.Bot/CommandMeta/CommandTree.cs b/PluralKit.Bot/CommandMeta/CommandTree.cs index 67379fe1..d1ab6da0 100644 --- a/PluralKit.Bot/CommandMeta/CommandTree.cs +++ b/PluralKit.Bot/CommandMeta/CommandTree.cs @@ -181,6 +181,8 @@ public partial class CommandTree await ctx.Execute(Admin, a => a.SystemRecover(ctx)); else if (ctx.Match("sd", "systemdelete")) await ctx.Execute(Admin, a => a.SystemDelete(ctx)); + else if (ctx.Match("sendmsg", "sendmessage")) + await ctx.Execute(Admin, a => a.SendAdminMessage(ctx)); else if (ctx.Match("al", "abuselog")) await HandleAdminAbuseLogCommand(ctx); else diff --git a/PluralKit.Bot/Commands/Admin.cs b/PluralKit.Bot/Commands/Admin.cs index a31b0dd0..da859616 100644 --- a/PluralKit.Bot/Commands/Admin.cs +++ b/PluralKit.Bot/Commands/Admin.cs @@ -9,6 +9,7 @@ using Myriad.Extensions; using Myriad.Cache; using Myriad.Rest; using Myriad.Types; +using Myriad.Rest.Types.Requests; using PluralKit.Core; @@ -496,4 +497,33 @@ public class Admin await ctx.Repository.DeleteAbuseLog(abuseLog.Id); await ctx.Reply($"{Emojis.Success} Successfully deleted abuse log entry."); } + + public async Task SendAdminMessage(Context ctx) + { + ctx.AssertBotAdmin(); + + var account = await ctx.MatchUser(); + if (account == null) + throw new PKError("You must pass an account to send an admin message to (either ID or @mention)."); + if (!ctx.HasNext()) + throw new PKError("You must provide a message to send."); + + var content = ctx.RemainderOrNull(false).NormalizeLineEndSpacing(); + var messageContent = $"## [Admin Message]\n\n{content}\n\nWe cannot read replies sent to this DM. If you wish to contact the staff team, please join the support server () or send us an email at ."; + + try + { + var dm = await _rest.CreateDm(account.Id); + var msg = await ctx.Rest.CreateMessage(dm.Id, + new MessageRequest { Content = messageContent } + ); + } + catch (Exception) + { + await ctx.Reply( + $"{Emojis.Error} Error while sending DM."); + } + + await ctx.Reply($"{Emojis.Success} Successfully sent message."); + } } \ No newline at end of file From ebf8a403695f10a947430aa59e90fe99d708c2bd Mon Sep 17 00:00:00 2001 From: asleepyskye Date: Tue, 9 Sep 2025 11:32:13 -0400 Subject: [PATCH 2/2] fix(bot): fix utility admin command --- PluralKit.Bot/Commands/Admin.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/PluralKit.Bot/Commands/Admin.cs b/PluralKit.Bot/Commands/Admin.cs index da859616..44171345 100644 --- a/PluralKit.Bot/Commands/Admin.cs +++ b/PluralKit.Bot/Commands/Admin.cs @@ -10,6 +10,7 @@ using Myriad.Cache; using Myriad.Rest; using Myriad.Types; using Myriad.Rest.Types.Requests; +using Myriad.Rest.Exceptions; using PluralKit.Core; @@ -20,12 +21,14 @@ public class Admin private readonly BotConfig _botConfig; private readonly DiscordApiClient _rest; private readonly IDiscordCache _cache; + private readonly PrivateChannelService _dmCache; - public Admin(BotConfig botConfig, DiscordApiClient rest, IDiscordCache cache) + public Admin(BotConfig botConfig, DiscordApiClient rest, IDiscordCache cache, PrivateChannelService dmCache) { _botConfig = botConfig; _rest = rest; _cache = cache; + _dmCache = dmCache; } private Task<(ulong Id, User? User)[]> GetUsers(IEnumerable ids) @@ -513,15 +516,16 @@ public class Admin try { - var dm = await _rest.CreateDm(account.Id); - var msg = await ctx.Rest.CreateMessage(dm.Id, + var dm = await _dmCache.GetOrCreateDmChannel(account.Id); + var msg = await ctx.Rest.CreateMessage(dm, new MessageRequest { Content = messageContent } ); } - catch (Exception) + catch (ForbiddenException) { await ctx.Reply( $"{Emojis.Error} Error while sending DM."); + return; } await ctx.Reply($"{Emojis.Success} Successfully sent message.");