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.Threading.Tasks;
using Autofac;
using Myriad.Extensions;
using Myriad.Types;
using PluralKit.Core;
@ -57,6 +59,28 @@ namespace PluralKit.Bot
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)
{
var botConfig = ctx.Services.Resolve<BotConfig>();

View File

@ -169,29 +169,15 @@ namespace PluralKit.Bot
throw new PKSyntaxError("You need to specify a channel.");
var error = "Channel not found or you do not have permissions to access it.";
var channel = await ctx.MatchChannel();
if (channel == null || channel.GuildId == null)
throw new PKError(error);
var guild = _cache.GetGuild(channel.GuildId.Value);
if (guild == null)
if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
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 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
ulong missingPermissions = 0;

View File

@ -105,6 +105,20 @@ namespace PluralKit.Bot
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;
}
@ -145,11 +159,20 @@ namespace PluralKit.Bot
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())
{
var discordMessage = await _rest.GetMessageOrNull(message.Message.Channel, message.Message.Mid);
if (discordMessage == null)
throw new PKError("Message deleted or inaccessible.");
if (discordMessage == null || !showContent)
throw new PKError(noShowContentError);
var content = discordMessage.Content;
if (content == null || content == "")
@ -174,12 +197,15 @@ namespace PluralKit.Bot
if (isDelete)
{
if (!showContent)
throw new PKError(noShowContentError);
if (message.System.Id != ctx.System.Id)
throw new PKError("You can only delete your own messages.");
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);
else
await ctx.Rest.CreateReaction(ctx.Message.ChannelId, ctx.Message.Id, new() { Name = Emojis.Success });
@ -197,7 +223,7 @@ namespace PluralKit.Bot
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)

View File

@ -175,7 +175,7 @@ namespace PluralKit.Bot
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 :(

View File

@ -275,7 +275,7 @@ namespace PluralKit.Bot
.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 ctx = LookupContext.ByNonOwner;
@ -317,11 +317,15 @@ namespace PluralKit.Bot
else if (userInfo != null) userStr = userInfo.NameAndMention();
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
var eb = new EmbedBuilder()
.Author(new(msg.Member.NameFor(ctx), IconUrl: msg.Member.AvatarFor(ctx).TryGetCleanCdnUrl()))
.Description(serverMsg?.Content?.NormalizeLineEndSpacing() ?? "*(message contents deleted or inaccessible)*")
.Image(new(serverMsg?.Attachments?.FirstOrDefault()?.Url))
.Description(content)
.Image(showContent ? new(serverMsg?.Attachments?.FirstOrDefault()?.Url) : null)
.Field(new("System",
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))
@ -329,7 +333,7 @@ namespace PluralKit.Bot
.Timestamp(DiscordUtils.SnowflakeToInstant(msg.Message.Mid).ToDateTimeOffset().ToString("O"));
var roles = memberInfo?.Roles?.ToList();
if (roles != null && roles.Count > 0)
if (roles != null && roles.Count > 0 && showContent)
{
var rolesString = string.Join(", ", roles
.Select(id =>