Pass proper allowed_mentions when sending webhook messages
This commit is contained in:
parent
9420cb56f8
commit
472e556ef0
@ -91,7 +91,7 @@ namespace PluralKit.Bot
|
|||||||
// Check if message starts with the command prefix
|
// Check if message starts with the command prefix
|
||||||
if (content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
|
if (content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
|
||||||
else if (content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
|
else if (content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
|
||||||
else if (StringUtils.HasMentionPrefix(content, ref argPos, out var id)) // Set argPos to the proper value
|
else if (DiscordUtils.HasMentionPrefix(content, ref argPos, out var id)) // Set argPos to the proper value
|
||||||
if (id != _client.CurrentUser.Id) // But undo it if it's someone else's ping
|
if (id != _client.CurrentUser.Id) // But undo it if it's someone else's ping
|
||||||
argPos = -1;
|
argPos = -1;
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DSharpPlus" Version="4.0.0-nightly-00707" />
|
<PackageReference Include="DSharpPlus" Version="4.0.0-nightly-00709" />
|
||||||
<PackageReference Include="DSharpPlus.Rest" Version="4.0.0-nightly-00707" />
|
<PackageReference Include="DSharpPlus.Rest" Version="4.0.0-nightly-00709" />
|
||||||
<PackageReference Include="Humanizer.Core" Version="2.7.9" />
|
<PackageReference Include="Humanizer.Core" Version="2.7.9" />
|
||||||
<PackageReference Include="Sentry" Version="2.0.0-beta7" />
|
<PackageReference Include="Sentry" Version="2.0.0-beta7" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0007" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0007" />
|
||||||
|
@ -57,8 +57,11 @@ namespace PluralKit.Bot
|
|||||||
if (!await CheckBotPermissionsOrError(message.Channel)) return false;
|
if (!await CheckBotPermissionsOrError(message.Channel)) return false;
|
||||||
if (!CheckProxyNameBoundsOrError(match.Member.ProxyName(ctx))) return false;
|
if (!CheckProxyNameBoundsOrError(match.Member.ProxyName(ctx))) return false;
|
||||||
|
|
||||||
|
// Check if we can mention everyone/here
|
||||||
|
var allowEveryone = (message.Channel.PermissionsInSync(message.Author) & Permissions.MentionEveryone) != 0;
|
||||||
|
|
||||||
// Everything's in order, we can execute the proxy!
|
// Everything's in order, we can execute the proxy!
|
||||||
await ExecuteProxy(conn, message, ctx, match);
|
await ExecuteProxy(conn, message, ctx, match, allowEveryone);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,13 +88,12 @@ namespace PluralKit.Bot
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteProxy(IPKConnection conn, DiscordMessage trigger, MessageContext ctx,
|
private async Task ExecuteProxy(IPKConnection conn, DiscordMessage trigger, MessageContext ctx,
|
||||||
ProxyMatch match)
|
ProxyMatch match, bool allowEveryone)
|
||||||
{
|
{
|
||||||
// Send the webhook
|
// Send the webhook
|
||||||
var id = await _webhookExecutor.ExecuteWebhook(trigger.Channel, match.Member.ProxyName(ctx),
|
var id = await _webhookExecutor.ExecuteWebhook(trigger.Channel, match.Member.ProxyName(ctx),
|
||||||
match.Member.ProxyAvatar(ctx),
|
match.Member.ProxyAvatar(ctx),
|
||||||
match.ProxyContent, trigger.Attachments);
|
match.ProxyContent, trigger.Attachments, allowEveryone);
|
||||||
|
|
||||||
|
|
||||||
Task SaveMessage() => _data.AddMessage(conn, trigger.Author.Id, trigger.Channel.GuildId, trigger.Channel.Id, id, trigger.Id, match.Member.Id);
|
Task SaveMessage() => _data.AddMessage(conn, trigger.Author.Id, trigger.Channel.GuildId, trigger.Channel.Id, id, trigger.Id, match.Member.Id);
|
||||||
Task LogMessage() => _logChannel.LogMessage(ctx, match, trigger, id).AsTask();
|
Task LogMessage() => _logChannel.LogMessage(ctx, match, trigger, id).AsTask();
|
||||||
|
@ -80,7 +80,7 @@ namespace PluralKit.Bot
|
|||||||
private string? ExtractLeadingMention(ref string input)
|
private string? ExtractLeadingMention(ref string input)
|
||||||
{
|
{
|
||||||
var mentionPos = 0;
|
var mentionPos = 0;
|
||||||
if (!StringUtils.HasMentionPrefix(input, ref mentionPos, out _)) return null;
|
if (!DiscordUtils.HasMentionPrefix(input, ref mentionPos, out _)) return null;
|
||||||
|
|
||||||
var leadingMention = input.Substring(0, mentionPos);
|
var leadingMention = input.Substring(0, mentionPos);
|
||||||
input = input.Substring(mentionPos);
|
input = input.Substring(mentionPos);
|
||||||
|
@ -42,13 +42,13 @@ namespace PluralKit.Bot
|
|||||||
_logger = logger.ForContext<WebhookExecutorService>();
|
_logger = logger.ForContext<WebhookExecutorService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ulong> ExecuteWebhook(DiscordChannel channel, string name, string avatarUrl, string content, IReadOnlyList<DiscordAttachment> attachments)
|
public async Task<ulong> ExecuteWebhook(DiscordChannel channel, string name, string avatarUrl, string content, IReadOnlyList<DiscordAttachment> attachments, bool allowEveryone)
|
||||||
{
|
{
|
||||||
_logger.Verbose("Invoking webhook in channel {Channel}", channel.Id);
|
_logger.Verbose("Invoking webhook in channel {Channel}", channel.Id);
|
||||||
|
|
||||||
// Get a webhook, execute it
|
// Get a webhook, execute it
|
||||||
var webhook = await _webhookCache.GetWebhook(channel);
|
var webhook = await _webhookCache.GetWebhook(channel);
|
||||||
var id = await ExecuteWebhookInner(channel, webhook, name, avatarUrl, content, attachments);
|
var id = await ExecuteWebhookInner(channel, webhook, name, avatarUrl, content, attachments, allowEveryone);
|
||||||
|
|
||||||
// Log the relevant metrics
|
// Log the relevant metrics
|
||||||
_metrics.Measure.Meter.Mark(BotMetrics.MessagesProxied);
|
_metrics.Measure.Meter.Mark(BotMetrics.MessagesProxied);
|
||||||
@ -59,11 +59,14 @@ namespace PluralKit.Bot
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ulong> ExecuteWebhookInner(DiscordChannel channel, DiscordWebhook webhook, string name, string avatarUrl, string content,
|
private async Task<ulong> ExecuteWebhookInner(DiscordChannel channel, DiscordWebhook webhook, string name, string avatarUrl, string content,
|
||||||
IReadOnlyList<DiscordAttachment> attachments, bool hasRetried = false)
|
IReadOnlyList<DiscordAttachment> attachments, bool allowEveryone, bool hasRetried = false)
|
||||||
{
|
{
|
||||||
|
content = content.Truncate(2000);
|
||||||
|
|
||||||
var dwb = new DiscordWebhookBuilder();
|
var dwb = new DiscordWebhookBuilder();
|
||||||
dwb.WithUsername(FixClyde(name).Truncate(80));
|
dwb.WithUsername(FixClyde(name).Truncate(80));
|
||||||
dwb.WithContent(content.Truncate(2000));
|
dwb.WithContent(content);
|
||||||
|
dwb.AddMentions(content.ParseAllMentions(allowEveryone));
|
||||||
if (avatarUrl != null) dwb.WithAvatarUrl(avatarUrl);
|
if (avatarUrl != null) dwb.WithAvatarUrl(avatarUrl);
|
||||||
|
|
||||||
var attachmentChunks = ChunkAttachmentsOrThrow(attachments, 8 * 1024 * 1024);
|
var attachmentChunks = ChunkAttachmentsOrThrow(attachments, 8 * 1024 * 1024);
|
||||||
@ -95,7 +98,7 @@ namespace PluralKit.Bot
|
|||||||
_logger.Warning("Error invoking webhook {Webhook} in channel {Channel}", webhook.Id, webhook.ChannelId);
|
_logger.Warning("Error invoking webhook {Webhook} in channel {Channel}", webhook.Id, webhook.ChannelId);
|
||||||
|
|
||||||
var newWebhook = await _webhookCache.InvalidateAndRefreshWebhook(channel, webhook);
|
var newWebhook = await _webhookCache.InvalidateAndRefreshWebhook(channel, webhook);
|
||||||
return await ExecuteWebhookInner(channel, newWebhook, name, avatarUrl, content, attachments, hasRetried: true);
|
return await ExecuteWebhookInner(channel, newWebhook, name, avatarUrl, content, attachments, allowEveryone, hasRetried: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using DSharpPlus;
|
using DSharpPlus;
|
||||||
@ -124,6 +126,63 @@ namespace PluralKit.Bot
|
|||||||
.GetProperty("UserCache", BindingFlags.Instance | BindingFlags.NonPublic)
|
.GetProperty("UserCache", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||||
?.GetValue(client);
|
?.GetValue(client);
|
||||||
return cache != null && cache.TryGetValue(id, out user);
|
return cache != null && cache.TryGetValue(id, out user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Regex USER_MENTION = new Regex("<@!?(\\d{17,19})>");
|
||||||
|
private static readonly Regex ROLE_MENTION = new Regex("<@&(\\d{17,19})>");
|
||||||
|
private static readonly Regex EVERYONE_HERE_MENTION = new Regex("@(everyone|here)");
|
||||||
|
public static DiscordColor? ToDiscordColor(this string color)
|
||||||
|
{
|
||||||
|
if (int.TryParse(color, NumberStyles.HexNumber, null, out var colorInt))
|
||||||
|
return new DiscordColor(colorInt);
|
||||||
|
throw new ArgumentException($"Invalid color string '{color}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasMentionPrefix(string content, ref int argPos, out ulong mentionId)
|
||||||
|
{
|
||||||
|
mentionId = 0;
|
||||||
|
|
||||||
|
// Roughly ported from Discord.Commands.MessageExtensions.HasMentionPrefix
|
||||||
|
if (string.IsNullOrEmpty(content) || content.Length <= 3 || (content[0] != '<' || content[1] != '@'))
|
||||||
|
return false;
|
||||||
|
int num = content.IndexOf('>');
|
||||||
|
if (num == -1 || content.Length < num + 2 || content[num + 1] != ' ' || !TryParseMention(content.Substring(0, num + 1), out mentionId))
|
||||||
|
return false;
|
||||||
|
argPos = num + 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParseMention(this string potentialMention, out ulong id)
|
||||||
|
{
|
||||||
|
if (ulong.TryParse(potentialMention, out id)) return true;
|
||||||
|
|
||||||
|
var match = USER_MENTION.Match(potentialMention);
|
||||||
|
if (match.Success && match.Index == 0 && match.Length == potentialMention.Length)
|
||||||
|
{
|
||||||
|
id = ulong.Parse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<IMention> ParseAllMentions(this string input, bool allowEveryone = false)
|
||||||
|
{
|
||||||
|
var mentions = new List<IMention>();
|
||||||
|
mentions.AddRange(USER_MENTION.Matches(input)
|
||||||
|
.Select(x => new UserMention(ulong.Parse(x.Groups[1].Value)) as IMention));
|
||||||
|
mentions.AddRange(ROLE_MENTION.Matches(input)
|
||||||
|
.Select(x => new RoleMention(ulong.Parse(x.Groups[1].Value)) as IMention));
|
||||||
|
if (EVERYONE_HERE_MENTION.IsMatch(input) && allowEveryone)
|
||||||
|
mentions.Add(new EveryoneMention());
|
||||||
|
return mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string EscapeMarkdown(this string input)
|
||||||
|
{
|
||||||
|
Regex pattern = new Regex(@"[*_~>`(||)\\]", RegexOptions.Multiline);
|
||||||
|
if (input != null) return pattern.Replace(input, @"\$&");
|
||||||
|
else return input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
using DSharpPlus.Entities;
|
|
||||||
|
|
||||||
namespace PluralKit.Bot
|
|
||||||
{
|
|
||||||
public static class StringUtils
|
|
||||||
{
|
|
||||||
private static readonly Regex USER_MENTION = new Regex("^<@!?(\\d{17,19})>$");
|
|
||||||
public static DiscordColor? ToDiscordColor(this string color)
|
|
||||||
{
|
|
||||||
if (int.TryParse(color, NumberStyles.HexNumber, null, out var colorInt))
|
|
||||||
return new DiscordColor(colorInt);
|
|
||||||
throw new ArgumentException($"Invalid color string '{color}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasMentionPrefix(string content, ref int argPos, out ulong mentionId)
|
|
||||||
{
|
|
||||||
mentionId = 0;
|
|
||||||
|
|
||||||
// Roughly ported from Discord.Commands.MessageExtensions.HasMentionPrefix
|
|
||||||
if (string.IsNullOrEmpty(content) || content.Length <= 3 || (content[0] != '<' || content[1] != '@'))
|
|
||||||
return false;
|
|
||||||
int num = content.IndexOf('>');
|
|
||||||
if (num == -1 || content.Length < num + 2 || content[num + 1] != ' ' || !TryParseMention(content.Substring(0, num + 1), out mentionId))
|
|
||||||
return false;
|
|
||||||
argPos = num + 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryParseMention(this string potentialMention, out ulong id)
|
|
||||||
{
|
|
||||||
if (ulong.TryParse(potentialMention, out id)) return true;
|
|
||||||
|
|
||||||
var match = USER_MENTION.Match(potentialMention);
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
id = ulong.Parse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string EscapeMarkdown(this string input)
|
|
||||||
{
|
|
||||||
Regex pattern = new Regex(@"[*_~>`(||)\\]", RegexOptions.Multiline);
|
|
||||||
if (input != null) return pattern.Replace(input, @"\$&");
|
|
||||||
else return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user