Fix various issues with proxying and webhook caching
This commit is contained in:
@@ -77,12 +77,19 @@ namespace PluralKit.Bot
|
||||
}
|
||||
|
||||
public async Task HandleMessageAsync(IMessage message) {
|
||||
var results = await _connection.QueryAsync<PKMember, PKSystem, ProxyDatabaseResult>("select members.*, systems.* from members, systems, accounts where members.system = systems.id and accounts.system = systems.id and accounts.uid = @Uid", (member, system) => new ProxyDatabaseResult { Member = member, System = system }, new { Uid = message.Author.Id });
|
||||
var results = await _connection.QueryAsync<PKMember, PKSystem, ProxyDatabaseResult>(
|
||||
"select members.*, systems.* from members, systems, accounts where members.system = systems.id and accounts.system = systems.id and accounts.uid = @Uid",
|
||||
(member, system) =>
|
||||
new ProxyDatabaseResult { Member = member, System = system }, new { Uid = message.Author.Id });
|
||||
|
||||
// Find a member with proxy tags matching the message
|
||||
var match = GetProxyTagMatch(message.Content, results);
|
||||
if (match == null) return;
|
||||
|
||||
// We know message.Channel can only be ITextChannel as PK doesn't work in DMs/groups
|
||||
// Afterwards we ensure the bot has the right permissions, otherwise bail early
|
||||
if (!await EnsureBotPermissions(message.Channel as ITextChannel)) return;
|
||||
|
||||
// Fetch a webhook for this channel, and send the proxied message
|
||||
var webhook = await _webhookCache.GetWebhook(message.Channel as ITextChannel);
|
||||
var hookMessage = await ExecuteWebhook(webhook, match.InnerText, match.ProxyName, match.Member.AvatarUrl, message.Attachments.FirstOrDefault());
|
||||
@@ -96,8 +103,42 @@ namespace PluralKit.Bot
|
||||
await message.DeleteAsync();
|
||||
}
|
||||
|
||||
private async Task<bool> EnsureBotPermissions(ITextChannel channel)
|
||||
{
|
||||
var guildUser = await channel.Guild.GetCurrentUserAsync();
|
||||
var permissions = guildUser.GetPermissions(channel);
|
||||
|
||||
if (!permissions.ManageWebhooks)
|
||||
{
|
||||
await channel.SendMessageAsync(
|
||||
$"{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.ManageMessages)
|
||||
{
|
||||
await channel.SendMessageAsync(
|
||||
$"{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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<IMessage> ExecuteWebhook(IWebhook webhook, string text, string username, string avatarUrl, IAttachment attachment) {
|
||||
var client = new DiscordWebhookClient(webhook);
|
||||
// TODO: DiscordWebhookClient's ctor does a call to GetWebhook that may be unnecessary, see if there's a way to do this The Hard Way :tm:
|
||||
// TODO: this will probably crash if there are multiple consecutive failures, perhaps have a loop instead?
|
||||
DiscordWebhookClient client;
|
||||
try
|
||||
{
|
||||
client = new DiscordWebhookClient(webhook);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// webhook was deleted or invalid
|
||||
webhook = await _webhookCache.InvalidateAndRefreshWebhook(webhook);
|
||||
client = new DiscordWebhookClient(webhook);
|
||||
}
|
||||
|
||||
ulong messageId;
|
||||
if (attachment != null) {
|
||||
@@ -108,6 +149,8 @@ namespace PluralKit.Bot
|
||||
} else {
|
||||
messageId = await client.SendMessageAsync(text, username: username, avatarUrl: avatarUrl);
|
||||
}
|
||||
|
||||
// TODO: SendMessageAsync should return a full object(??), see if there's a way to avoid the extra server call here
|
||||
return await webhook.Channel.GetMessageAsync(messageId);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user