feat: respect Discord permissions in pk;message and pk;edit

This commit is contained in:
spiral 2021-11-10 23:46:16 -05:00
parent 48d4009c69
commit 343fafe9f0
No known key found for this signature in database
GPG Key ID: A6059F0CA0E1BD31
5 changed files with 64 additions and 24 deletions

View File

@ -1,7 +1,9 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Autofac; using Autofac;
using Myriad.Extensions;
using Myriad.Types; using Myriad.Types;
using PluralKit.Core; using PluralKit.Core;
@ -57,6 +59,28 @@ namespace PluralKit.Bot
return ctx; return ctx;
} }
public static async Task<bool> CheckPermissionsInGuildChannel(this Context ctx, Channel channel, PermissionSet neededPerms)
{
var guild = ctx.Cache.GetGuild(channel.GuildId.Value);
if (guild == null)
return false;
var guildMember = ctx.Member;
if (ctx.Guild?.Id != channel.GuildId)
{
guildMember = await ctx.Rest.GetGuildMember(channel.GuildId.Value, ctx.Author.Id);
if (guildMember == null)
return false;
}
var userPermissions = PermissionExtensions.PermissionsFor(guild, channel, ctx.Author.Id, guildMember);
if ((userPermissions & neededPerms) == 0)
return false;
return true;
}
public static bool CheckBotAdmin(this Context ctx) public static bool CheckBotAdmin(this Context ctx)
{ {
var botConfig = ctx.Services.Resolve<BotConfig>(); var botConfig = ctx.Services.Resolve<BotConfig>();

View File

@ -169,29 +169,15 @@ namespace PluralKit.Bot
throw new PKSyntaxError("You need to specify a channel."); throw new PKSyntaxError("You need to specify a channel.");
var error = "Channel not found or you do not have permissions to access it."; var error = "Channel not found or you do not have permissions to access it.";
var channel = await ctx.MatchChannel(); var channel = await ctx.MatchChannel();
if (channel == null || channel.GuildId == null) if (channel == null || channel.GuildId == null)
throw new PKError(error); throw new PKError(error);
var guild = _cache.GetGuild(channel.GuildId.Value); if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
if (guild == null)
throw new PKError(error); throw new PKError(error);
var guildMember = await _rest.GetGuildMember(channel.GuildId.Value, ctx.Author.Id);
if (guildMember == null)
throw new PKError(error);
var botPermissions = _bot.PermissionsIn(channel.Id); var botPermissions = _bot.PermissionsIn(channel.Id);
var webhookPermissions = _cache.EveryonePermissions(channel); var webhookPermissions = _cache.EveryonePermissions(channel);
var userPermissions = PermissionExtensions.PermissionsFor(guild, channel, ctx.Author.Id, guildMember);
if ((userPermissions & PermissionSet.ViewChannel) == 0)
throw new PKError(error);
// We use a bitfield so we can set individual permission bits // We use a bitfield so we can set individual permission bits
ulong missingPermissions = 0; ulong missingPermissions = 0;

View File

@ -105,6 +105,20 @@ namespace PluralKit.Bot
throw new PKError("Could not find a recent message to edit."); throw new PKError("Could not find a recent message to edit.");
} }
if (msg.Message.Channel != ctx.Channel.Id)
{
var error = "The channel where the message was sent does not exist anymore, or you are missing permissions to access it.";
var channel = _cache.GetChannel(msg.Message.Channel);
if (channel == null)
throw new PKError(error);
if (!await ctx.CheckPermissionsInGuildChannel(channel,
PermissionSet.ViewChannel | PermissionSet.SendMessages
))
throw new PKError(error);
}
return msg; return msg;
} }
@ -145,11 +159,20 @@ namespace PluralKit.Bot
throw Errors.MessageNotFound(messageId.Value); throw Errors.MessageNotFound(messageId.Value);
} }
var showContent = true;
var noShowContentError = "Message deleted or inaccessible.";
var channel = _cache.GetChannel(message.Message.Channel);
if (channel == null)
showContent = false;
else if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
showContent = false;
if (ctx.MatchRaw()) if (ctx.MatchRaw())
{ {
var discordMessage = await _rest.GetMessageOrNull(message.Message.Channel, message.Message.Mid); var discordMessage = await _rest.GetMessageOrNull(message.Message.Channel, message.Message.Mid);
if (discordMessage == null) if (discordMessage == null || !showContent)
throw new PKError("Message deleted or inaccessible."); throw new PKError(noShowContentError);
var content = discordMessage.Content; var content = discordMessage.Content;
if (content == null || content == "") if (content == null || content == "")
@ -174,12 +197,15 @@ namespace PluralKit.Bot
if (isDelete) if (isDelete)
{ {
if (!showContent)
throw new PKError(noShowContentError);
if (message.System.Id != ctx.System.Id) if (message.System.Id != ctx.System.Id)
throw new PKError("You can only delete your own messages."); throw new PKError("You can only delete your own messages.");
await ctx.Rest.DeleteMessage(message.Message.Channel, message.Message.Mid); await ctx.Rest.DeleteMessage(message.Message.Channel, message.Message.Mid);
if (ctx.Guild != null) if (ctx.Channel.Id == message.Message.Channel)
await ctx.Rest.DeleteMessage(ctx.Message); await ctx.Rest.DeleteMessage(ctx.Message);
else else
await ctx.Rest.CreateReaction(ctx.Message.ChannelId, ctx.Message.Id, new() { Name = Emojis.Success }); await ctx.Rest.CreateReaction(ctx.Message.ChannelId, ctx.Message.Id, new() { Name = Emojis.Success });
@ -197,7 +223,7 @@ namespace PluralKit.Bot
return; return;
} }
await ctx.Reply(embed: await _embeds.CreateMessageInfoEmbed(message)); await ctx.Reply(embed: await _embeds.CreateMessageInfoEmbed(message, showContent));
} }
private async Task DeleteCommandMessage(Context ctx, ulong messageId) private async Task DeleteCommandMessage(Context ctx, ulong messageId)

View File

@ -175,7 +175,7 @@ namespace PluralKit.Bot
await _rest.CreateMessage(dm.Id, new MessageRequest await _rest.CreateMessage(dm.Id, new MessageRequest
{ {
Embed = await _embeds.CreateMessageInfoEmbed(msg) Embed = await _embeds.CreateMessageInfoEmbed(msg, true)
}); });
} }
catch (ForbiddenException) { } // No permissions to DM, can't check for this :( catch (ForbiddenException) { } // No permissions to DM, can't check for this :(

View File

@ -275,7 +275,7 @@ namespace PluralKit.Bot
.Build(); .Build();
} }
public async Task<Embed> CreateMessageInfoEmbed(FullMessage msg) public async Task<Embed> CreateMessageInfoEmbed(FullMessage msg, bool showContent)
{ {
var channel = await _cache.GetOrFetchChannel(_rest, msg.Message.Channel); var channel = await _cache.GetOrFetchChannel(_rest, msg.Message.Channel);
var ctx = LookupContext.ByNonOwner; var ctx = LookupContext.ByNonOwner;
@ -317,11 +317,15 @@ namespace PluralKit.Bot
else if (userInfo != null) userStr = userInfo.NameAndMention(); else if (userInfo != null) userStr = userInfo.NameAndMention();
else userStr = $"*(deleted user {msg.Message.Sender})*"; else userStr = $"*(deleted user {msg.Message.Sender})*";
var content = serverMsg?.Content?.NormalizeLineEndSpacing();
if (content == null || !showContent)
content = "*(message contents deleted or inaccessible)*";
// Put it all together // Put it all together
var eb = new EmbedBuilder() var eb = new EmbedBuilder()
.Author(new(msg.Member.NameFor(ctx), IconUrl: msg.Member.AvatarFor(ctx).TryGetCleanCdnUrl())) .Author(new(msg.Member.NameFor(ctx), IconUrl: msg.Member.AvatarFor(ctx).TryGetCleanCdnUrl()))
.Description(serverMsg?.Content?.NormalizeLineEndSpacing() ?? "*(message contents deleted or inaccessible)*") .Description(content)
.Image(new(serverMsg?.Attachments?.FirstOrDefault()?.Url)) .Image(showContent ? new(serverMsg?.Attachments?.FirstOrDefault()?.Url) : null)
.Field(new("System", .Field(new("System",
msg.System.Name != null ? $"{msg.System.Name} (`{msg.System.Hid}`)" : $"`{msg.System.Hid}`", true)) msg.System.Name != null ? $"{msg.System.Name} (`{msg.System.Hid}`)" : $"`{msg.System.Hid}`", true))
.Field(new("Member", $"{msg.Member.NameFor(ctx)} (`{msg.Member.Hid}`)", true)) .Field(new("Member", $"{msg.Member.NameFor(ctx)} (`{msg.Member.Hid}`)", true))
@ -329,7 +333,7 @@ namespace PluralKit.Bot
.Timestamp(DiscordUtils.SnowflakeToInstant(msg.Message.Mid).ToDateTimeOffset().ToString("O")); .Timestamp(DiscordUtils.SnowflakeToInstant(msg.Message.Mid).ToDateTimeOffset().ToString("O"));
var roles = memberInfo?.Roles?.ToList(); var roles = memberInfo?.Roles?.ToList();
if (roles != null && roles.Count > 0) if (roles != null && roles.Count > 0 && showContent)
{ {
var rolesString = string.Join(", ", roles var rolesString = string.Join(", ", roles
.Select(id => .Select(id =>