feat: async cache
this breaks logging bot permissions to Sentry. we haven't had a need to check those recently (permissions issues were because of broken cache), so this is fine for now this should be re-added in the future though
This commit is contained in:
parent
45258d519e
commit
e7f36eb31f
@ -18,13 +18,13 @@ namespace Myriad.Cache
|
||||
public ValueTask RemoveUser(ulong userId);
|
||||
public ValueTask RemoveRole(ulong guildId, ulong roleId);
|
||||
|
||||
public bool TryGetGuild(ulong guildId, out Guild guild);
|
||||
public bool TryGetChannel(ulong channelId, out Channel channel);
|
||||
public bool TryGetDmChannel(ulong userId, out Channel channel);
|
||||
public bool TryGetUser(ulong userId, out User user);
|
||||
public bool TryGetRole(ulong roleId, out Role role);
|
||||
public Task<bool> TryGetGuild(ulong guildId, out Guild guild);
|
||||
public Task<bool> TryGetChannel(ulong channelId, out Channel channel);
|
||||
public Task<bool> TryGetDmChannel(ulong userId, out Channel channel);
|
||||
public Task<bool> TryGetUser(ulong userId, out User user);
|
||||
public Task<bool> TryGetRole(ulong roleId, out Role role);
|
||||
|
||||
public IAsyncEnumerable<Guild> GetAllGuilds();
|
||||
public IEnumerable<Channel> GetGuildChannels(ulong guildId);
|
||||
public Task<IEnumerable<Channel>> GetGuildChannels(ulong guildId);
|
||||
}
|
||||
}
|
@ -124,34 +124,34 @@ namespace Myriad.Cache
|
||||
return default;
|
||||
}
|
||||
|
||||
public bool TryGetGuild(ulong guildId, out Guild guild)
|
||||
public Task<bool> TryGetGuild(ulong guildId, out Guild guild)
|
||||
{
|
||||
if (_guilds.TryGetValue(guildId, out var cg))
|
||||
{
|
||||
guild = cg.Guild;
|
||||
return true;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
guild = null!;
|
||||
return false;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public bool TryGetChannel(ulong channelId, out Channel channel) =>
|
||||
_channels.TryGetValue(channelId, out channel!);
|
||||
public Task<bool> TryGetChannel(ulong channelId, out Channel channel) =>
|
||||
Task.FromResult(_channels.TryGetValue(channelId, out channel!));
|
||||
|
||||
public bool TryGetDmChannel(ulong userId, out Channel channel)
|
||||
public Task<bool> TryGetDmChannel(ulong userId, out Channel channel)
|
||||
{
|
||||
channel = default!;
|
||||
if (!_dmChannels.TryGetValue(userId, out var channelId))
|
||||
return false;
|
||||
return Task.FromResult(false);
|
||||
return TryGetChannel(channelId, out channel);
|
||||
}
|
||||
|
||||
public bool TryGetUser(ulong userId, out User user) =>
|
||||
_users.TryGetValue(userId, out user!);
|
||||
public Task<bool> TryGetUser(ulong userId, out User user) =>
|
||||
Task.FromResult(_users.TryGetValue(userId, out user!));
|
||||
|
||||
public bool TryGetRole(ulong roleId, out Role role) =>
|
||||
_roles.TryGetValue(roleId, out role!);
|
||||
public Task<bool> TryGetRole(ulong roleId, out Role role) =>
|
||||
Task.FromResult(_roles.TryGetValue(roleId, out role!));
|
||||
|
||||
public IAsyncEnumerable<Guild> GetAllGuilds()
|
||||
{
|
||||
@ -160,12 +160,12 @@ namespace Myriad.Cache
|
||||
.ToAsyncEnumerable();
|
||||
}
|
||||
|
||||
public IEnumerable<Channel> GetGuildChannels(ulong guildId)
|
||||
public Task<IEnumerable<Channel>> GetGuildChannels(ulong guildId)
|
||||
{
|
||||
if (!_guilds.TryGetValue(guildId, out var guild))
|
||||
throw new ArgumentException("Guild not found", nameof(guildId));
|
||||
|
||||
return guild.Channels.Keys.Select(c => _channels[c]);
|
||||
return Task.FromResult(guild.Channels.Keys.Select(c => _channels[c]));
|
||||
}
|
||||
|
||||
private CachedGuild SaveGuildRaw(Guild guild) =>
|
||||
|
@ -9,44 +9,44 @@ namespace Myriad.Extensions
|
||||
{
|
||||
public static class CacheExtensions
|
||||
{
|
||||
public static Guild GetGuild(this IDiscordCache cache, ulong guildId)
|
||||
public static async Task<Guild> GetGuild(this IDiscordCache cache, ulong guildId)
|
||||
{
|
||||
if (!cache.TryGetGuild(guildId, out var guild))
|
||||
if (!await cache.TryGetGuild(guildId, out var guild))
|
||||
throw new KeyNotFoundException($"Guild {guildId} not found in cache");
|
||||
return guild;
|
||||
}
|
||||
|
||||
public static Channel GetChannel(this IDiscordCache cache, ulong channelId)
|
||||
public static async Task<Channel> GetChannel(this IDiscordCache cache, ulong channelId)
|
||||
{
|
||||
if (!cache.TryGetChannel(channelId, out var channel))
|
||||
if (!await cache.TryGetChannel(channelId, out var channel))
|
||||
throw new KeyNotFoundException($"Channel {channelId} not found in cache");
|
||||
return channel;
|
||||
}
|
||||
|
||||
public static Channel? GetChannelOrNull(this IDiscordCache cache, ulong channelId)
|
||||
public static async Task<Channel?> GetChannelOrNull(this IDiscordCache cache, ulong channelId)
|
||||
{
|
||||
if (cache.TryGetChannel(channelId, out var channel))
|
||||
if (await cache.TryGetChannel(channelId, out var channel))
|
||||
return channel;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static User GetUser(this IDiscordCache cache, ulong userId)
|
||||
public static async Task<User> GetUser(this IDiscordCache cache, ulong userId)
|
||||
{
|
||||
if (!cache.TryGetUser(userId, out var user))
|
||||
if (!await cache.TryGetUser(userId, out var user))
|
||||
throw new KeyNotFoundException($"User {userId} not found in cache");
|
||||
return user;
|
||||
}
|
||||
|
||||
public static Role GetRole(this IDiscordCache cache, ulong roleId)
|
||||
public static async Task<Role> GetRole(this IDiscordCache cache, ulong roleId)
|
||||
{
|
||||
if (!cache.TryGetRole(roleId, out var role))
|
||||
if (!await cache.TryGetRole(roleId, out var role))
|
||||
throw new KeyNotFoundException($"Role {roleId} not found in cache");
|
||||
return role;
|
||||
}
|
||||
|
||||
public static async ValueTask<User?> GetOrFetchUser(this IDiscordCache cache, DiscordApiClient rest, ulong userId)
|
||||
{
|
||||
if (cache.TryGetUser(userId, out var cacheUser))
|
||||
if (await cache.TryGetUser(userId, out var cacheUser))
|
||||
return cacheUser;
|
||||
|
||||
var restUser = await rest.GetUser(userId);
|
||||
@ -57,7 +57,7 @@ namespace Myriad.Extensions
|
||||
|
||||
public static async ValueTask<Channel?> GetOrFetchChannel(this IDiscordCache cache, DiscordApiClient rest, ulong channelId)
|
||||
{
|
||||
if (cache.TryGetChannel(channelId, out var cacheChannel))
|
||||
if (await cache.TryGetChannel(channelId, out var cacheChannel))
|
||||
return cacheChannel;
|
||||
|
||||
var restChannel = await rest.GetChannel(channelId);
|
||||
@ -68,7 +68,7 @@ namespace Myriad.Extensions
|
||||
|
||||
public static async Task<Channel> GetOrCreateDmChannel(this IDiscordCache cache, DiscordApiClient rest, ulong recipientId)
|
||||
{
|
||||
if (cache.TryGetDmChannel(recipientId, out var cacheChannel))
|
||||
if (await cache.TryGetDmChannel(recipientId, out var cacheChannel))
|
||||
return cacheChannel;
|
||||
|
||||
var restChannel = await rest.CreateDm(recipientId);
|
||||
@ -76,13 +76,13 @@ namespace Myriad.Extensions
|
||||
return restChannel;
|
||||
}
|
||||
|
||||
public static Channel GetRootChannel(this IDiscordCache cache, ulong channelOrThread)
|
||||
public static async Task<Channel> GetRootChannel(this IDiscordCache cache, ulong channelOrThread)
|
||||
{
|
||||
var channel = cache.GetChannel(channelOrThread);
|
||||
var channel = await cache.GetChannel(channelOrThread);
|
||||
if (!channel.IsThread())
|
||||
return channel;
|
||||
|
||||
var parent = cache.GetChannel(channel.ParentId!.Value);
|
||||
var parent = await cache.GetChannel(channel.ParentId!.Value);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Cache;
|
||||
using Myriad.Gateway;
|
||||
@ -10,24 +11,24 @@ namespace Myriad.Extensions
|
||||
{
|
||||
public static class PermissionExtensions
|
||||
{
|
||||
public static PermissionSet PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) =>
|
||||
public static Task<PermissionSet> PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) =>
|
||||
PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member, isWebhook: message.WebhookId != null);
|
||||
|
||||
public static PermissionSet PermissionsFor(this IDiscordCache cache, ulong channelId, GuildMember member) =>
|
||||
public static Task<PermissionSet> PermissionsFor(this IDiscordCache cache, ulong channelId, GuildMember member) =>
|
||||
PermissionsFor(cache, channelId, member.User.Id, member);
|
||||
|
||||
public static PermissionSet PermissionsFor(this IDiscordCache cache, ulong channelId, ulong userId, GuildMemberPartial? member, bool isWebhook = false)
|
||||
public static async Task<PermissionSet> PermissionsFor(this IDiscordCache cache, ulong channelId, ulong userId, GuildMemberPartial? member, bool isWebhook = false)
|
||||
{
|
||||
if (!cache.TryGetChannel(channelId, out var channel))
|
||||
if (!await cache.TryGetChannel(channelId, out var channel))
|
||||
// todo: handle channel not found better
|
||||
return PermissionSet.Dm;
|
||||
|
||||
if (channel.GuildId == null)
|
||||
return PermissionSet.Dm;
|
||||
|
||||
var rootChannel = cache.GetRootChannel(channelId);
|
||||
var rootChannel = await cache.GetRootChannel(channelId);
|
||||
|
||||
var guild = cache.GetGuild(channel.GuildId.Value);
|
||||
var guild = await cache.GetGuild(channel.GuildId.Value);
|
||||
|
||||
if (isWebhook)
|
||||
return EveryonePermissions(guild);
|
||||
@ -38,12 +39,12 @@ namespace Myriad.Extensions
|
||||
public static PermissionSet EveryonePermissions(this Guild guild) =>
|
||||
guild.Roles.FirstOrDefault(r => r.Id == guild.Id)?.Permissions ?? PermissionSet.Dm;
|
||||
|
||||
public static PermissionSet EveryonePermissions(this IDiscordCache cache, Channel channel)
|
||||
public static async Task<PermissionSet> EveryonePermissions(this IDiscordCache cache, Channel channel)
|
||||
{
|
||||
if (channel.Type == Channel.ChannelType.Dm)
|
||||
return PermissionSet.Dm;
|
||||
|
||||
var defaultPermissions = cache.GetGuild(channel.GuildId!.Value).EveryonePermissions();
|
||||
var defaultPermissions = (await cache.GetGuild(channel.GuildId!.Value)).EveryonePermissions();
|
||||
var overwrite = channel.PermissionOverwrites?.FirstOrDefault(r => r.Id == channel.GuildId);
|
||||
if (overwrite == null)
|
||||
return defaultPermissions;
|
||||
|
@ -78,14 +78,14 @@ namespace PluralKit.Bot
|
||||
}, null, timeTillNextWholeMinute, TimeSpan.FromMinutes(1));
|
||||
}
|
||||
|
||||
public PermissionSet PermissionsIn(ulong channelId)
|
||||
public async Task <PermissionSet> PermissionsIn(ulong channelId)
|
||||
{
|
||||
var channel = _cache.GetRootChannel(channelId);
|
||||
var channel = await _cache.GetRootChannel(channelId);
|
||||
|
||||
if (channel.GuildId != null)
|
||||
{
|
||||
var member = _guildMembers.GetValueOrDefault(channel.GuildId.Value);
|
||||
return _cache.PermissionsFor(channelId, _cluster.User?.Id ?? default, member);
|
||||
return await _cache.PermissionsFor(channelId, _cluster.User?.Id ?? default, member);
|
||||
}
|
||||
|
||||
return PermissionSet.Dm;
|
||||
@ -198,7 +198,7 @@ namespace PluralKit.Bot
|
||||
var queue = serviceScope.ResolveOptional<HandlerQueue<T>>();
|
||||
|
||||
using var _ = LogContext.PushProperty("EventId", Guid.NewGuid());
|
||||
using var __ = LogContext.Push(serviceScope.Resolve<SerilogGatewayEnricherFactory>().GetEnricher(shard, evt));
|
||||
using var __ = LogContext.Push(await serviceScope.Resolve<SerilogGatewayEnricherFactory>().GetEnricher(shard, evt));
|
||||
_logger.Verbose("Received gateway event: {@Event}", evt);
|
||||
|
||||
// Also, find a Sentry enricher for the event type (if one is present), and ask it to put some event data in the Sentry scope
|
||||
@ -263,7 +263,7 @@ namespace PluralKit.Bot
|
||||
if (reportChannel == null)
|
||||
return;
|
||||
|
||||
var botPerms = PermissionsIn(reportChannel.Value);
|
||||
var botPerms = await PermissionsIn(reportChannel.Value);
|
||||
if (botPerms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks))
|
||||
await _errorMessageService.SendErrorMessage(reportChannel.Value, sentryEvent.EventId.ToString());
|
||||
}
|
||||
|
@ -71,8 +71,8 @@ namespace PluralKit.Bot
|
||||
public Cluster Cluster => _cluster;
|
||||
public MessageContext MessageContext => _messageContext;
|
||||
|
||||
public PermissionSet BotPermissions => _provider.Resolve<Bot>().PermissionsIn(_channel.Id);
|
||||
public PermissionSet UserPermissions => _cache.PermissionsFor(_message);
|
||||
public Task<PermissionSet> BotPermissions => _provider.Resolve<Bot>().PermissionsIn(_channel.Id);
|
||||
public Task<PermissionSet> UserPermissions => _cache.PermissionsFor(_message);
|
||||
|
||||
public DiscordApiClient Rest => _rest;
|
||||
|
||||
@ -85,11 +85,13 @@ namespace PluralKit.Bot
|
||||
|
||||
public async Task<Message> Reply(string text = null, Embed embed = null, AllowedMentions? mentions = null)
|
||||
{
|
||||
if (!BotPermissions.HasFlag(PermissionSet.SendMessages))
|
||||
var botPerms = await BotPermissions;
|
||||
|
||||
if (!botPerms.HasFlag(PermissionSet.SendMessages))
|
||||
// Will be "swallowed" during the error handler anyway, this message is never shown.
|
||||
throw new PKError("PluralKit does not have permission to send messages in this channel.");
|
||||
|
||||
if (embed != null && !BotPermissions.HasFlag(PermissionSet.EmbedLinks))
|
||||
if (embed != null && !botPerms.HasFlag(PermissionSet.EmbedLinks))
|
||||
throw new PKError("PluralKit does not have permission to send embeds in this channel. Please ensure I have the **Embed Links** permission enabled.");
|
||||
|
||||
var msg = await _rest.CreateMessage(_channel.Id, new MessageRequest
|
||||
|
@ -52,16 +52,16 @@ namespace PluralKit.Bot
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public static Context CheckAuthorPermission(this Context ctx, PermissionSet neededPerms, string permissionName)
|
||||
public static async Task<Context> CheckAuthorPermission(this Context ctx, PermissionSet neededPerms, string permissionName)
|
||||
{
|
||||
if ((ctx.UserPermissions & neededPerms) != neededPerms)
|
||||
if ((await ctx.UserPermissions & neededPerms) != neededPerms)
|
||||
throw new PKError($"You must have the \"{permissionName}\" permission in this server to use this command.");
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public static async Task<bool> CheckPermissionsInGuildChannel(this Context ctx, Channel channel, PermissionSet neededPerms)
|
||||
{
|
||||
var guild = ctx.Cache.GetGuild(channel.GuildId.Value);
|
||||
var guild = await ctx.Cache.GetGuild(channel.GuildId.Value);
|
||||
if (guild == null)
|
||||
return false;
|
||||
|
||||
|
@ -152,19 +152,19 @@ namespace PluralKit.Bot
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<Channel> MatchChannel(this Context ctx)
|
||||
public static async Task<Channel> MatchChannel(this Context ctx)
|
||||
{
|
||||
if (!MentionUtils.TryParseChannel(ctx.PeekArgument(), out var id))
|
||||
return Task.FromResult<Channel>(null);
|
||||
return null;
|
||||
|
||||
if (!ctx.Cache.TryGetChannel(id, out var channel))
|
||||
return Task.FromResult<Channel>(null);
|
||||
if (!await ctx.Cache.TryGetChannel(id, out var channel))
|
||||
return null;
|
||||
|
||||
if (!DiscordUtils.IsValidGuildChannel(channel))
|
||||
return Task.FromResult<Channel>(null);
|
||||
return null;
|
||||
|
||||
ctx.PopArgument();
|
||||
return Task.FromResult(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
public static Guild MatchGuild(this Context ctx)
|
||||
|
@ -87,8 +87,8 @@ namespace PluralKit.Bot
|
||||
var missingEmojiPermissions = false;
|
||||
foreach (var channel in await _rest.GetGuildChannels(guild.Id))
|
||||
{
|
||||
var botPermissions = _bot.PermissionsIn(channel.Id);
|
||||
var webhookPermissions = _cache.EveryonePermissions(channel);
|
||||
var botPermissions = await _bot.PermissionsIn(channel.Id);
|
||||
var webhookPermissions = await _cache.EveryonePermissions(channel);
|
||||
var userPermissions = PermissionExtensions.PermissionsFor(guild, channel, ctx.Author.Id, senderGuildUser);
|
||||
|
||||
if ((userPermissions & PermissionSet.ViewChannel) == 0)
|
||||
@ -176,8 +176,8 @@ namespace PluralKit.Bot
|
||||
if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
|
||||
throw new PKError(error);
|
||||
|
||||
var botPermissions = _bot.PermissionsIn(channel.Id);
|
||||
var webhookPermissions = _cache.EveryonePermissions(channel);
|
||||
var botPermissions = await _bot.PermissionsIn(channel.Id);
|
||||
var webhookPermissions = await _cache.EveryonePermissions(channel);
|
||||
|
||||
// We use a bitfield so we can set individual permission bits
|
||||
ulong missingPermissions = 0;
|
||||
@ -249,7 +249,7 @@ namespace PluralKit.Bot
|
||||
throw new PKError("You can only check your own messages.");
|
||||
|
||||
// get the channel info
|
||||
var channel = _cache.GetChannel(channelId.Value);
|
||||
var channel = await _cache.GetChannel(channelId.Value);
|
||||
if (channel == null)
|
||||
throw new PKError("Unable to get the channel associated with this message.");
|
||||
|
||||
|
@ -67,7 +67,7 @@ namespace PluralKit.Bot
|
||||
if (ctx.Guild == null)
|
||||
await _rest.CreateReaction(ctx.Channel.Id, ctx.Message.Id, new() { Name = Emojis.Success });
|
||||
|
||||
if (ctx.BotPermissions.HasFlag(PermissionSet.ManageMessages))
|
||||
if ((await ctx.BotPermissions).HasFlag(PermissionSet.ManageMessages))
|
||||
await _rest.DeleteMessage(ctx.Channel.Id, ctx.Message.Id);
|
||||
|
||||
await _logChannel.LogMessage(ctx.MessageContext, msg.Message, ctx.Message, editedMsg, originalMsg!.Content!);
|
||||
@ -109,7 +109,7 @@ namespace PluralKit.Bot
|
||||
{
|
||||
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);
|
||||
var channel = await _cache.GetChannel(msg.Message.Channel);
|
||||
if (channel == null)
|
||||
throw new PKError(error);
|
||||
|
||||
@ -162,7 +162,7 @@ namespace PluralKit.Bot
|
||||
var showContent = true;
|
||||
var noShowContentError = "Message deleted or inaccessible.";
|
||||
|
||||
var channel = _cache.GetChannel(message.Message.Channel);
|
||||
var channel = await _cache.GetChannel(message.Message.Channel);
|
||||
if (channel == null)
|
||||
showContent = false;
|
||||
else if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
|
||||
|
@ -30,7 +30,7 @@ namespace PluralKit.Bot
|
||||
|
||||
public async Task SetLogChannel(Context ctx)
|
||||
{
|
||||
ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
var settings = await _repo.GetGuild(ctx.Guild.Id);
|
||||
|
||||
if (await ctx.MatchClear("the server log channel"))
|
||||
@ -59,7 +59,7 @@ namespace PluralKit.Bot
|
||||
if (channel.Type != Channel.ChannelType.GuildText)
|
||||
throw new PKError("PluralKit cannot log messages to this type of channel.");
|
||||
|
||||
var perms = _bot.PermissionsIn(channel.Id);
|
||||
var perms = await _bot.PermissionsIn(channel.Id);
|
||||
if (!perms.HasFlag(PermissionSet.SendMessages))
|
||||
throw new PKError("PluralKit is missing **Send Messages** permissions in the new log channel.");
|
||||
if (!perms.HasFlag(PermissionSet.EmbedLinks))
|
||||
@ -71,11 +71,11 @@ namespace PluralKit.Bot
|
||||
|
||||
public async Task SetLogEnabled(Context ctx, bool enable)
|
||||
{
|
||||
ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
|
||||
var affectedChannels = new List<Channel>();
|
||||
if (ctx.Match("all"))
|
||||
affectedChannels = _cache.GetGuildChannels(ctx.Guild.Id).Where(x => x.Type == Channel.ChannelType.GuildText).ToList();
|
||||
affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)).Where(x => x.Type == Channel.ChannelType.GuildText).ToList();
|
||||
else if (!ctx.HasNext()) throw new PKSyntaxError("You must pass one or more #channels.");
|
||||
else while (ctx.HasNext())
|
||||
{
|
||||
@ -104,13 +104,13 @@ namespace PluralKit.Bot
|
||||
|
||||
public async Task ShowBlacklisted(Context ctx)
|
||||
{
|
||||
ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
|
||||
var blacklist = await _repo.GetGuild(ctx.Guild.Id);
|
||||
|
||||
// Resolve all channels from the cache and order by position
|
||||
var channels = blacklist.Blacklist
|
||||
.Select(id => _cache.GetChannelOrNull(id))
|
||||
var channels = (await Task.WhenAll(blacklist.Blacklist
|
||||
.Select(id => _cache.GetChannelOrNull(id))))
|
||||
.Where(c => c != null)
|
||||
.OrderBy(c => c.Position)
|
||||
.ToList();
|
||||
@ -124,10 +124,10 @@ namespace PluralKit.Bot
|
||||
await ctx.Paginate(channels.ToAsyncEnumerable(), channels.Count, 25,
|
||||
$"Blacklisted channels for {ctx.Guild.Name}",
|
||||
null,
|
||||
(eb, l) =>
|
||||
async (eb, l) =>
|
||||
{
|
||||
string CategoryName(ulong? id) =>
|
||||
id != null ? _cache.GetChannel(id.Value).Name : "(no category)";
|
||||
async Task<string> CategoryName(ulong? id) =>
|
||||
id != null ? (await _cache.GetChannel(id.Value)).Name : "(no category)";
|
||||
|
||||
ulong? lastCategory = null;
|
||||
|
||||
@ -136,7 +136,7 @@ namespace PluralKit.Bot
|
||||
{
|
||||
if (lastCategory != channel!.ParentId && fieldValue.Length > 0)
|
||||
{
|
||||
eb.Field(new(CategoryName(lastCategory), fieldValue.ToString()));
|
||||
eb.Field(new(await CategoryName(lastCategory), fieldValue.ToString()));
|
||||
fieldValue.Clear();
|
||||
}
|
||||
else fieldValue.Append("\n");
|
||||
@ -145,19 +145,17 @@ namespace PluralKit.Bot
|
||||
lastCategory = channel.ParentId;
|
||||
}
|
||||
|
||||
eb.Field(new(CategoryName(lastCategory), fieldValue.ToString()));
|
||||
|
||||
return Task.CompletedTask;
|
||||
eb.Field(new(await CategoryName(lastCategory), fieldValue.ToString()));
|
||||
});
|
||||
}
|
||||
|
||||
public async Task SetBlacklisted(Context ctx, bool shouldAdd)
|
||||
{
|
||||
ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
|
||||
var affectedChannels = new List<Channel>();
|
||||
if (ctx.Match("all"))
|
||||
affectedChannels = _cache.GetGuildChannels(ctx.Guild.Id).Where(x => x.Type == Channel.ChannelType.GuildText).ToList();
|
||||
affectedChannels = (await _cache.GetGuildChannels(ctx.Guild.Id)).Where(x => x.Type == Channel.ChannelType.GuildText).ToList();
|
||||
else if (!ctx.HasNext()) throw new PKSyntaxError("You must pass one or more #channels.");
|
||||
else while (ctx.HasNext())
|
||||
{
|
||||
@ -182,7 +180,7 @@ namespace PluralKit.Bot
|
||||
|
||||
public async Task SetLogCleanup(Context ctx)
|
||||
{
|
||||
ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
await ctx.CheckGuildContext().CheckAuthorPermission(PermissionSet.ManageGuild, "Manage Server");
|
||||
|
||||
var botList = string.Join(", ", _cleanService.Bots.Select(b => b.Name).OrderBy(x => x.ToLowerInvariant()));
|
||||
|
||||
|
@ -70,9 +70,9 @@ namespace PluralKit.Bot
|
||||
if (evt.Type != Message.MessageType.Default && evt.Type != Message.MessageType.Reply) return;
|
||||
if (IsDuplicateMessage(evt)) return;
|
||||
|
||||
var guild = evt.GuildId != null ? _cache.GetGuild(evt.GuildId.Value) : null;
|
||||
var channel = _cache.GetChannel(evt.ChannelId);
|
||||
var rootChannel = _cache.GetRootChannel(evt.ChannelId);
|
||||
var guild = evt.GuildId != null ? await _cache.GetGuild(evt.GuildId.Value) : null;
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(evt.ChannelId);
|
||||
|
||||
// Log metrics and message info
|
||||
_metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
|
||||
@ -98,7 +98,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async ValueTask<bool> TryHandleLogClean(MessageCreateEvent evt, MessageContext ctx)
|
||||
{
|
||||
var channel = _cache.GetChannel(evt.ChannelId);
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
if (!evt.Author.Bot || channel.Type != Channel.ChannelType.GuildText ||
|
||||
!ctx.LogCleanupEnabled) return false;
|
||||
|
||||
@ -156,7 +156,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async ValueTask<bool> TryHandleProxy(Shard shard, MessageCreateEvent evt, Guild guild, Channel channel, MessageContext ctx)
|
||||
{
|
||||
var botPermissions = _bot.PermissionsIn(channel.Id);
|
||||
var botPermissions = await _bot.PermissionsIn(channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -51,10 +51,10 @@ namespace PluralKit.Bot
|
||||
if (!evt.Content.HasValue || !evt.Author.HasValue || !evt.Member.HasValue)
|
||||
return;
|
||||
|
||||
var channel = _cache.GetChannel(evt.ChannelId);
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
if (!DiscordUtils.IsValidGuildChannel(channel))
|
||||
return;
|
||||
var guild = _cache.GetGuild(channel.GuildId!.Value);
|
||||
var guild = await _cache.GetGuild(channel.GuildId!.Value);
|
||||
var lastMessage = _lastMessageCache.GetLastMessage(evt.ChannelId)?.Current;
|
||||
|
||||
// Only react to the last message in the channel
|
||||
@ -67,7 +67,7 @@ namespace PluralKit.Bot
|
||||
ctx = await _repo.GetMessageContext(evt.Author.Value!.Id, channel.GuildId!.Value, evt.ChannelId);
|
||||
|
||||
var equivalentEvt = await GetMessageCreateEvent(evt, lastMessage, channel);
|
||||
var botPermissions = _bot.PermissionsIn(channel.Id);
|
||||
var botPermissions = await _bot.PermissionsIn(channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
@ -112,7 +112,7 @@ namespace PluralKit.Bot
|
||||
if (referencedMessageId == null)
|
||||
return null;
|
||||
|
||||
var botPermissions = _bot.PermissionsIn(channelId);
|
||||
var botPermissions = await _bot.PermissionsIn(channelId);
|
||||
if (!botPermissions.HasFlag(PermissionSet.ReadMessageHistory))
|
||||
{
|
||||
_logger.Warning("Tried to get referenced message in channel {ChannelId} to reply but bot does not have Read Message History",
|
||||
|
@ -50,7 +50,7 @@ namespace PluralKit.Bot
|
||||
{
|
||||
// Sometimes we get events from users that aren't in the user cache
|
||||
// We just ignore all of those for now, should be quite rare...
|
||||
if (!_cache.TryGetUser(evt.UserId, out var user))
|
||||
if (!await _cache.TryGetUser(evt.UserId, out var user))
|
||||
return;
|
||||
|
||||
// ignore any reactions added by *us*
|
||||
@ -60,7 +60,7 @@ namespace PluralKit.Bot
|
||||
// Ignore reactions from bots (we can't DM them anyway)
|
||||
if (user.Bot) return;
|
||||
|
||||
var channel = _cache.GetChannel(evt.ChannelId);
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
|
||||
// check if it's a command message first
|
||||
// since this can happen in DMs as well
|
||||
@ -121,7 +121,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async ValueTask HandleProxyDeleteReaction(MessageReactionAddEvent evt, FullMessage msg)
|
||||
{
|
||||
if (!_bot.PermissionsIn(evt.ChannelId).HasFlag(PermissionSet.ManageMessages))
|
||||
if (!(await _bot.PermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
return;
|
||||
|
||||
var system = await _repo.GetSystemByAccount(evt.UserId);
|
||||
@ -162,7 +162,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async ValueTask HandleQueryReaction(MessageReactionAddEvent evt, FullMessage msg)
|
||||
{
|
||||
var guild = _cache.GetGuild(evt.GuildId!.Value);
|
||||
var guild = await _cache.GetGuild(evt.GuildId!.Value);
|
||||
|
||||
// Try to DM the user info about the message
|
||||
try
|
||||
@ -185,14 +185,14 @@ namespace PluralKit.Bot
|
||||
|
||||
private async ValueTask HandlePingReaction(MessageReactionAddEvent evt, FullMessage msg)
|
||||
{
|
||||
if (!_bot.PermissionsIn(evt.ChannelId).HasFlag(PermissionSet.ManageMessages))
|
||||
if (!(await _bot.PermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
return;
|
||||
|
||||
// Check if the "pinger" has permission to send messages in this channel
|
||||
// (if not, PK shouldn't send messages on their behalf)
|
||||
var member = await _rest.GetGuildMember(evt.GuildId!.Value, evt.UserId);
|
||||
var requiredPerms = PermissionSet.ViewChannel | PermissionSet.SendMessages;
|
||||
if (member == null || !_cache.PermissionsFor(evt.ChannelId, member).HasFlag(requiredPerms)) return;
|
||||
if (member == null || !(await _cache.PermissionsFor(evt.ChannelId, member)).HasFlag(requiredPerms)) return;
|
||||
|
||||
if (msg.System.PingsEnabled)
|
||||
{
|
||||
@ -240,7 +240,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async Task TryRemoveOriginalReaction(MessageReactionAddEvent evt)
|
||||
{
|
||||
if (_bot.PermissionsIn(evt.ChannelId).HasFlag(PermissionSet.ManageMessages))
|
||||
if ((await _bot.PermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
await _rest.DeleteUserReaction(evt.ChannelId, evt.MessageId, evt.Emoji, evt.UserId);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ namespace PluralKit.Bot
|
||||
};
|
||||
}).AsSelf().SingleInstance();
|
||||
builder.RegisterType<Cluster>().AsSelf().SingleInstance();
|
||||
builder.RegisterType<MemoryDiscordCache>().AsSelf().As<IDiscordCache>().SingleInstance();
|
||||
builder.Register(c => {
|
||||
return new MemoryDiscordCache();
|
||||
}).AsSelf().As<IDiscordCache>().SingleInstance();
|
||||
|
||||
builder.Register(c =>
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ namespace PluralKit.Bot
|
||||
if (!ShouldProxy(channel, message, ctx))
|
||||
return false;
|
||||
|
||||
var rootChannel = _cache.GetRootChannel(message.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(message.ChannelId);
|
||||
|
||||
List<ProxyMember> members;
|
||||
// Fetch members and try to match to a specific member
|
||||
@ -143,10 +143,10 @@ namespace PluralKit.Bot
|
||||
var content = match.ProxyContent;
|
||||
if (!allowEmbeds) content = content.BreakLinkEmbeds();
|
||||
|
||||
var messageChannel = _cache.GetChannel(trigger.ChannelId);
|
||||
var rootChannel = _cache.GetRootChannel(trigger.ChannelId);
|
||||
var messageChannel = await _cache.GetChannel(trigger.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(trigger.ChannelId);
|
||||
var threadId = messageChannel.IsThread() ? messageChannel.Id : (ulong?)null;
|
||||
var guild = _cache.GetGuild(trigger.GuildId.Value);
|
||||
var guild = await _cache.GetGuild(trigger.GuildId.Value);
|
||||
|
||||
var proxyMessage = await _webhookExecutor.ExecuteWebhook(new ProxyRequest
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ namespace PluralKit.Bot
|
||||
if (logChannel == null)
|
||||
return;
|
||||
|
||||
var triggerChannel = _cache.GetChannel(proxiedMessage.Channel);
|
||||
var triggerChannel = await _cache.GetChannel(proxiedMessage.Channel);
|
||||
|
||||
var system = await _repo.GetSystem(ctx.SystemId.Value);
|
||||
var member = await _repo.GetMember(proxiedMessage.Member);
|
||||
@ -78,7 +78,7 @@ namespace PluralKit.Bot
|
||||
if (logChannel == null || logChannel.Type != Channel.ChannelType.GuildText) return null;
|
||||
|
||||
// Check bot permissions
|
||||
var perms = _bot.PermissionsIn(logChannel.Id);
|
||||
var perms = await _bot.PermissionsIn(logChannel.Id);
|
||||
if (!perms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks))
|
||||
{
|
||||
_logger.Information(
|
||||
@ -93,7 +93,7 @@ namespace PluralKit.Bot
|
||||
private async Task<Channel?> FindLogChannel(ulong guildId, ulong channelId)
|
||||
{
|
||||
// TODO: fetch it directly on cache miss?
|
||||
if (_cache.TryGetChannel(channelId, out var channel))
|
||||
if (await _cache.TryGetChannel(channelId, out var channel))
|
||||
return channel;
|
||||
|
||||
// Channel doesn't exist or we don't have permission to access it, let's remove it from the database too
|
||||
|
@ -86,10 +86,10 @@ namespace PluralKit.Bot
|
||||
|
||||
public async ValueTask HandleLoggerBotCleanup(Message msg)
|
||||
{
|
||||
var channel = _cache.GetChannel(msg.ChannelId);
|
||||
var channel = await _cache.GetChannel(msg.ChannelId);
|
||||
|
||||
if (channel.Type != Channel.ChannelType.GuildText) return;
|
||||
if (!_bot.PermissionsIn(channel.Id).HasFlag(PermissionSet.ManageMessages)) return;
|
||||
if (!(await _bot.PermissionsIn(channel.Id)).HasFlag(PermissionSet.ManageMessages)) return;
|
||||
|
||||
// If this message is from a *webhook*, check if the name matches one of the bots we know
|
||||
// TODO: do we need to do a deeper webhook origin check, or would that be too hard on the rate limit?
|
||||
|
@ -52,7 +52,7 @@ namespace PluralKit.Bot
|
||||
await foreach (var guild in _cache.GetAllGuilds())
|
||||
{
|
||||
guildCount++;
|
||||
foreach (var channel in _cache.GetGuildChannels(guild.Id))
|
||||
foreach (var channel in await _cache.GetGuildChannels(guild.Id))
|
||||
{
|
||||
if (DiscordUtils.IsValidGuildChannel(channel))
|
||||
channelCount++;
|
||||
|
@ -89,7 +89,7 @@ namespace PluralKit.Bot
|
||||
};
|
||||
|
||||
ulong? threadId = null;
|
||||
var root = _cache.GetRootChannel(channelId);
|
||||
var root = await _cache.GetRootChannel(channelId);
|
||||
if (root.Id != channelId)
|
||||
threadId = channelId;
|
||||
|
||||
@ -102,7 +102,7 @@ namespace PluralKit.Bot
|
||||
|
||||
private async Task<Message> ExecuteWebhookInner(Webhook webhook, ProxyRequest req, bool hasRetried = false)
|
||||
{
|
||||
var guild = _cache.GetGuild(req.GuildId);
|
||||
var guild = await _cache.GetGuild(req.GuildId);
|
||||
var content = req.Content.Truncate(2000);
|
||||
|
||||
var allowedMentions = content.ParseMentions();
|
||||
|
@ -165,7 +165,7 @@ namespace PluralKit.Bot
|
||||
if (currentPage < 0) currentPage += pageCount;
|
||||
|
||||
// If we can, remove the user's reaction (so they can press again quickly)
|
||||
if (ctx.BotPermissions.HasFlag(PermissionSet.ManageMessages))
|
||||
if ((await ctx.BotPermissions).HasFlag(PermissionSet.ManageMessages))
|
||||
await ctx.Rest.DeleteUserReaction(msg.ChannelId, msg.Id, reaction.Emoji, reaction.UserId);
|
||||
|
||||
// Edit the embed with the new page
|
||||
@ -179,7 +179,7 @@ namespace PluralKit.Bot
|
||||
}
|
||||
|
||||
// todo: re-check
|
||||
if (ctx.BotPermissions.HasFlag(PermissionSet.ManageMessages))
|
||||
if ((await ctx.BotPermissions).HasFlag(PermissionSet.ManageMessages))
|
||||
await ctx.Rest.DeleteAllReactions(msg.ChannelId, msg.Id);
|
||||
}
|
||||
// If we get a "NotFound" error, the message has been deleted and thus not our problem
|
||||
@ -292,7 +292,7 @@ namespace PluralKit.Bot
|
||||
var task = f();
|
||||
|
||||
// If we don't have permission to add reactions, don't bother, and just await the task normally.
|
||||
if (!DiscordUtils.HasReactionPermissions(ctx)) return await task;
|
||||
if (!await DiscordUtils.HasReactionPermissions(ctx)) return await task;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -196,10 +196,10 @@ namespace PluralKit.Bot
|
||||
public static string EventType(this IGatewayEvent evt) =>
|
||||
evt.GetType().Name.Replace("Event", "");
|
||||
|
||||
public static bool HasReactionPermissions(Context ctx)
|
||||
public static async Task<bool> HasReactionPermissions(Context ctx)
|
||||
{
|
||||
var neededPermissions = PermissionSet.AddReactions | PermissionSet.ReadMessageHistory;
|
||||
return ((ctx.BotPermissions & neededPermissions) == neededPermissions);
|
||||
return ((await ctx.BotPermissions & neededPermissions) == neededPermissions);
|
||||
}
|
||||
|
||||
public static bool IsValidGuildChannel(Channel channel) =>
|
||||
|
@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Extensions;
|
||||
using Myriad.Gateway;
|
||||
using Myriad.Types;
|
||||
|
||||
using Sentry;
|
||||
|
||||
@ -42,8 +44,10 @@ namespace PluralKit.Bot
|
||||
|
||||
// Also report information about the bot's permissions in the channel
|
||||
// We get a lot of permission errors so this'll be useful for determining problems
|
||||
var perms = _bot.PermissionsIn(evt.ChannelId);
|
||||
scope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
|
||||
|
||||
// todo: re-add this
|
||||
// var perms = _bot.PermissionsIn(evt.ChannelId);
|
||||
// scope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
|
||||
}
|
||||
|
||||
public void Enrich(Scope scope, Shard shard, MessageDeleteEvent evt)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Cache;
|
||||
using Myriad.Extensions;
|
||||
@ -20,7 +21,7 @@ namespace PluralKit.Bot
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public ILogEventEnricher GetEnricher(Shard shard, IGatewayEvent evt)
|
||||
public async Task<ILogEventEnricher> GetEnricher(Shard shard, IGatewayEvent evt)
|
||||
{
|
||||
var props = new List<LogEventProperty>
|
||||
{
|
||||
@ -38,9 +39,9 @@ namespace PluralKit.Bot
|
||||
{
|
||||
props.Add(new("ChannelId", new ScalarValue(channel.Value)));
|
||||
|
||||
if (_cache.TryGetChannel(channel.Value, out _))
|
||||
if (await _cache.TryGetChannel(channel.Value, out _))
|
||||
{
|
||||
var botPermissions = _bot.PermissionsIn(channel.Value);
|
||||
var botPermissions = await _bot.PermissionsIn(channel.Value);
|
||||
props.Add(new("BotPermissions", new ScalarValue(botPermissions)));
|
||||
}
|
||||
}
|
||||
@ -52,7 +53,7 @@ namespace PluralKit.Bot
|
||||
props.Add(new("UserId", new ScalarValue(user.Value)));
|
||||
|
||||
if (evt is MessageCreateEvent mce)
|
||||
props.Add(new("UserPermissions", new ScalarValue(_cache.PermissionsFor(mce))));
|
||||
props.Add(new("UserPermissions", new ScalarValue(await _cache.PermissionsFor(mce))));
|
||||
|
||||
return new Inner(props);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user