diff --git a/PluralKit.Bot/Bot.cs b/PluralKit.Bot/Bot.cs index 5957b1d4..68a1af4e 100644 --- a/PluralKit.Bot/Bot.cs +++ b/PluralKit.Bot/Bot.cs @@ -155,7 +155,7 @@ namespace PluralKit.Bot if (reportChannel != null && reportChannel.BotHasAllPermissions(Permissions.SendMessages)) { var eid = sentryEvent.EventId; - await reportChannel.SendMessageAsync( + await reportChannel.SendMessageFixedAsync( $"{Emojis.Error} Internal error occurred. Please join the support server (), and send the developer this ID: `{eid}`\nBe sure to include a description of what you were doing to make the error occur."); } } diff --git a/PluralKit.Bot/CommandSystem/Context.cs b/PluralKit.Bot/CommandSystem/Context.cs index 8272178d..499707e4 100644 --- a/PluralKit.Bot/CommandSystem/Context.cs +++ b/PluralKit.Bot/CommandSystem/Context.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -66,7 +67,7 @@ namespace PluralKit.Bot public bool HasNext(bool skipFlags = true) => RemainderOrNull(skipFlags) != null; public string FullCommand => _parameters.FullCommand; - public Task Reply(string text = null, DiscordEmbed embed = null) + public Task Reply(string text = null, DiscordEmbed embed = null, IEnumerable mentions = null) { if (!this.BotHasAllPermissions(Permissions.SendMessages)) // Will be "swallowed" during the error handler anyway, this message is never shown. @@ -74,8 +75,7 @@ namespace PluralKit.Bot if (embed != null && !this.BotHasAllPermissions(Permissions.EmbedLinks)) throw new PKError("PluralKit does not have permission to send embeds in this channel. Please ensure I have the **Embed Links** permission enabled."); - - return Channel.SendMessageAsync(text, embed: embed); + return Channel.SendMessageFixedAsync(text, embed: embed, mentions: mentions); } /// diff --git a/PluralKit.Bot/Commands/SystemLink.cs b/PluralKit.Bot/Commands/SystemLink.cs index 72be74ca..88344660 100644 --- a/PluralKit.Bot/Commands/SystemLink.cs +++ b/PluralKit.Bot/Commands/SystemLink.cs @@ -1,6 +1,8 @@ using System.Linq; using System.Threading.Tasks; +using DSharpPlus.Entities; + using PluralKit.Core; namespace PluralKit.Bot @@ -25,7 +27,8 @@ namespace PluralKit.Bot var existingAccount = await _data.GetSystemByAccount(account.Id); if (existingAccount != null) throw Errors.AccountInOtherSystem(existingAccount); - var msg = await ctx.Reply($"{account.Mention}, please confirm the link by clicking the {Emojis.Success} reaction on this message."); + var msg = await ctx.Reply($"{account.Mention}, please confirm the link by clicking the {Emojis.Success} reaction on this message.", + mentions: new IMention[] { new UserMention(account) }); if (!await ctx.PromptYesNo(msg, user: account)) throw Errors.MemberLinkCancelled; await _data.AddAccount(ctx.System, account.Id); await ctx.Reply($"{Emojis.Success} Account linked to system."); diff --git a/PluralKit.Bot/Commands/Token.cs b/PluralKit.Bot/Commands/Token.cs index c71cd730..6e3074ae 100644 --- a/PluralKit.Bot/Commands/Token.cs +++ b/PluralKit.Bot/Commands/Token.cs @@ -29,8 +29,8 @@ namespace PluralKit.Bot // DM the user a security disclaimer, and then the token in a separate message (for easy copying on mobile) var dm = await ctx.Rest.CreateDmAsync(ctx.Author.Id); - await dm.SendMessageAsync($"{Emojis.Warn} Please note that this grants access to modify (and delete!) all your system data, so keep it safe and secure. If it leaks or you need a new one, you can invalidate this one with `pk;token refresh`.\n\nYour token is below:"); - await dm.SendMessageAsync(token); + await dm.SendMessageFixedAsync($"{Emojis.Warn} Please note that this grants access to modify (and delete!) all your system data, so keep it safe and secure. If it leaks or you need a new one, you can invalidate this one with `pk;token refresh`.\n\nYour token is below:"); + await dm.SendMessageFixedAsync(token); } private async Task MakeAndSetNewToken(PKSystem system) @@ -63,8 +63,8 @@ namespace PluralKit.Bot // DM the user an invalidation disclaimer, and then the token in a separate message (for easy copying on mobile) var dm = await ctx.Rest.CreateDmAsync(ctx.Author.Id); - await dm.SendMessageAsync($"{Emojis.Warn} Your previous API token has been invalidated. You will need to change it anywhere it's currently used.\n\nYour token is below:"); - await dm.SendMessageAsync(token); + await dm.SendMessageFixedAsync($"{Emojis.Warn} Your previous API token has been invalidated. You will need to change it anywhere it's currently used.\n\nYour token is below:"); + await dm.SendMessageFixedAsync(token); } } } \ No newline at end of file diff --git a/PluralKit.Bot/Handlers/MessageCreated.cs b/PluralKit.Bot/Handlers/MessageCreated.cs index cdf778f0..a24deee1 100644 --- a/PluralKit.Bot/Handlers/MessageCreated.cs +++ b/PluralKit.Bot/Handlers/MessageCreated.cs @@ -122,7 +122,7 @@ namespace PluralKit.Bot // User-facing errors, print to the channel properly formatted var msg = evt.Message; if (msg.Channel.Guild == null || msg.Channel.BotHasAllPermissions(Permissions.SendMessages)) - await msg.Channel.SendMessageAsync($"{Emojis.Error} {e.Message}"); + await msg.Channel.SendMessageFixedAsync($"{Emojis.Error} {e.Message}"); } return false; diff --git a/PluralKit.Bot/Handlers/ReactionAdded.cs b/PluralKit.Bot/Handlers/ReactionAdded.cs index f86b54c6..48ebc1f1 100644 --- a/PluralKit.Bot/Handlers/ReactionAdded.cs +++ b/PluralKit.Bot/Handlers/ReactionAdded.cs @@ -108,15 +108,16 @@ namespace PluralKit.Bot { // If the system has pings enabled, go ahead var embed = new DiscordEmbedBuilder().WithDescription($"[Jump to pinged message]({evt.Message.JumpLink})"); - await evt.Channel.SendMessageAsync($"Psst, **{msg.Member.DisplayName()}** (<@{msg.Message.Sender}>), you have been pinged by <@{evt.User.Id}>.", embed: embed.Build()); + await evt.Channel.SendMessageFixedAsync($"Psst, **{msg.Member.DisplayName()}** (<@{msg.Message.Sender}>), you have been pinged by <@{evt.User.Id}>.", embed: embed.Build(), + new IMention[] {new UserMention(msg.Message.Sender) }); } else { // If not, tell them in DMs (if we can) try { - await guildUser.SendMessageAsync($"{Emojis.Error} {msg.Member.DisplayName()}'s system has disabled reaction pings. If you want to mention them anyway, you can copy/paste the following message:"); - await guildUser.SendMessageAsync($"`<@{msg.Message.Sender}>`"); + await guildUser.SendMessageFixedAsync($"{Emojis.Error} {msg.Member.DisplayName()}'s system has disabled reaction pings. If you want to mention them anyway, you can copy/paste the following message:"); + await guildUser.SendMessageFixedAsync($"`<@{msg.Message.Sender}>`"); } catch (UnauthorizedException) { } } diff --git a/PluralKit.Bot/Proxy/ProxyService.cs b/PluralKit.Bot/Proxy/ProxyService.cs index 2f64adc6..0ec95374 100644 --- a/PluralKit.Bot/Proxy/ProxyService.cs +++ b/PluralKit.Bot/Proxy/ProxyService.cs @@ -130,14 +130,14 @@ namespace PluralKit.Bot if ((permissions & Permissions.ManageWebhooks) == 0) { // todo: PKError-ify these - await channel.SendMessageAsync( + await channel.SendMessageFixedAsync( $"{Emojis.Error} PluralKit does not have the *Manage Webhooks* permission in this channel, and thus cannot proxy messages. Please contact a server administrator to remedy this."); return false; } if ((permissions & Permissions.ManageMessages) == 0) { - await channel.SendMessageAsync( + await channel.SendMessageFixedAsync( $"{Emojis.Error} PluralKit does not have the *Manage Messages* permission in this channel, and thus cannot delete the original trigger message. Please contact a server administrator to remedy this."); return false; } diff --git a/PluralKit.Bot/Services/LogChannelService.cs b/PluralKit.Bot/Services/LogChannelService.cs index 20565984..a949bb78 100644 --- a/PluralKit.Bot/Services/LogChannelService.cs +++ b/PluralKit.Bot/Services/LogChannelService.cs @@ -44,7 +44,7 @@ namespace PluralKit.Bot { await conn.QueryMember(proxy.Member.Id), hookMessage, trigger.Id, trigger.Author, proxy.Content, trigger.Channel); var url = $"https://discord.com/channels/{trigger.Channel.GuildId}/{trigger.ChannelId}/{hookMessage}"; - await logChannel.SendMessageAsync(content: url, embed: embed); + await logChannel.SendMessageFixedAsync(content: url, embed: embed); } private async Task FindLogChannel(ulong guild, ulong channel) diff --git a/PluralKit.Bot/Utils/DiscordUtils.cs b/PluralKit.Bot/Utils/DiscordUtils.cs index 77561b59..47cde49d 100644 --- a/PluralKit.Bot/Utils/DiscordUtils.cs +++ b/PluralKit.Bot/Utils/DiscordUtils.cs @@ -105,5 +105,17 @@ namespace PluralKit.Bot // Workaround for https://github.com/DSharpPlus/DSharpPlus/issues/565 return input?.Replace("%20", "+"); } + + // Passing an empty list (counter-intuitively) *allows* all mentions through (even if non-null) + // So we add a single "bogus" user mention for ID=1 that'll never actually resolve, and thus block all (other) mentions + private static readonly IEnumerable DenyAllMentions = new IMention[] {new UserMention(1)}; + + public static Task SendMessageFixedAsync(this DiscordChannel channel, string content = null, DiscordEmbed embed = null, IEnumerable mentions = null) => + channel.SendMessageAsync(content, embed: embed, mentions: mentions ?? DenyAllMentions); + + // This doesn't do anything by itself (DiscordMember.SendMessageAsync doesn't take a mentions argument) + // It's just here for consistency so we don't use the standard SendMessageAsync method >.> + public static Task SendMessageFixedAsync(this DiscordMember member, string content = null, DiscordEmbed embed = null) => + member.SendMessageAsync(content, embed: embed); } } \ No newline at end of file