refactor(bot): remove saving own user ID from ready event, rely on ID in config

This commit is contained in:
spiral
2022-09-06 09:52:37 +00:00
parent aeb6411b6c
commit 9303dbb91e
17 changed files with 51 additions and 69 deletions

View File

@@ -94,8 +94,7 @@ public class Bot
// we HandleGatewayEvent **before** getting the own user, because the own user is set in HandleGatewayEvent for ReadyEvent
await _cache.HandleGatewayEvent(evt);
var userId = await _cache.GetOwnUser();
await _cache.TryUpdateSelfMember(userId, evt);
await _cache.TryUpdateSelfMember(_config.ClientId, evt);
await OnEventReceivedInner(shardId, evt);
}
@@ -200,13 +199,11 @@ public class Bot
{
_metrics.Measure.Meter.Mark(BotMetrics.BotErrors, exc.GetType().FullName);
var ourUserId = await _cache.GetOwnUser();
// Make this beforehand so we can access the event ID for logging
var sentryEvent = new SentryEvent(exc);
// If the event is us responding to our own error messages, don't bother logging
if (evt is MessageCreateEvent mc && mc.Author.Id == ourUserId)
if (evt is MessageCreateEvent mc && mc.Author.Id == _config.ClientId)
return;
var shouldReport = exc.IsOurProblem();
@@ -235,7 +232,7 @@ public class Bot
return;
// Once we've sent it to Sentry, report it to the user (if we have permission to)
var reportChannel = handler.ErrorChannelFor(evt, ourUserId);
var reportChannel = handler.ErrorChannelFor(evt, _config.ClientId);
if (reportChannel == null)
return;

View File

@@ -5,7 +5,7 @@ public class BotConfig
public static readonly string[] DefaultPrefixes = { "pk;", "pk!" };
public string Token { get; set; }
public ulong? ClientId { get; set; }
public ulong ClientId { get; set; }
// ASP.NET configuration merges arrays with defaults, so we leave this field nullable
// and fall back to the separate default array at the use site :)

View File

@@ -14,8 +14,6 @@ namespace PluralKit.Bot;
public class Checks
{
private readonly BotConfig _botConfig;
// this must ONLY be used to get the bot's user ID
private readonly IDiscordCache _cache;
private readonly ProxyMatcher _matcher;
private readonly ProxyService _proxy;
private readonly DiscordApiClient _rest;
@@ -28,10 +26,9 @@ public class Checks
};
// todo: make sure everything uses the minimum amount of REST calls necessary
public Checks(DiscordApiClient rest, IDiscordCache cache, BotConfig botConfig, ProxyService proxy, ProxyMatcher matcher)
public Checks(DiscordApiClient rest, BotConfig botConfig, ProxyService proxy, ProxyMatcher matcher)
{
_rest = rest;
_cache = cache;
_botConfig = botConfig;
_proxy = proxy;
_matcher = matcher;
@@ -69,14 +66,14 @@ public class Checks
throw Errors.GuildNotFound(guildId);
}
var guildMember = await _rest.GetGuildMember(guild.Id, await _cache.GetOwnUser());
var guildMember = await _rest.GetGuildMember(guild.Id, _botConfig.ClientId);
// Loop through every channel and group them by sets of permissions missing
var permissionsMissing = new Dictionary<ulong, List<Channel>>();
var hiddenChannels = false;
foreach (var channel in await _rest.GetGuildChannels(guild.Id))
{
var botPermissions = PermissionExtensions.PermissionsFor(guild, channel, await _cache.GetOwnUser(), guildMember);
var botPermissions = PermissionExtensions.PermissionsFor(guild, channel, _botConfig.ClientId, guildMember);
var userPermissions = PermissionExtensions.PermissionsFor(guild, channel, ctx.Author.Id, senderGuildUser);
if ((userPermissions & PermissionSet.ViewChannel) == 0)
@@ -152,12 +149,12 @@ public class Checks
if (guild == null)
throw new PKError(error);
var guildMember = await _rest.GetGuildMember(channel.GuildId.Value, await _cache.GetOwnUser());
var guildMember = await _rest.GetGuildMember(channel.GuildId.Value, _botConfig.ClientId);
if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
throw new PKError(error);
var botPermissions = PermissionExtensions.PermissionsFor(guild, channel, await _cache.GetOwnUser(), guildMember);
var botPermissions = PermissionExtensions.PermissionsFor(guild, channel, _botConfig.ClientId, guildMember);
// We use a bitfield so we can set individual permission bits
ulong missingPermissions = 0;

View File

@@ -18,26 +18,22 @@ namespace PluralKit.Bot;
public class Misc
{
private readonly BotConfig _botConfig;
private readonly IDiscordCache _cache;
private readonly CpuStatService _cpu;
private readonly IMetrics _metrics;
private readonly ShardInfoService _shards;
private readonly ModelRepository _repo;
public Misc(BotConfig botConfig, IMetrics metrics, CpuStatService cpu, ModelRepository repo, ShardInfoService shards, IDiscordCache cache)
public Misc(BotConfig botConfig, IMetrics metrics, CpuStatService cpu, ModelRepository repo, ShardInfoService shards)
{
_botConfig = botConfig;
_metrics = metrics;
_cpu = cpu;
_repo = repo;
_shards = shards;
_cache = cache;
}
public async Task Invite(Context ctx)
{
var clientId = _botConfig.ClientId ?? await _cache.GetOwnUser();
var permissions =
PermissionSet.AddReactions |
PermissionSet.AttachFiles |
@@ -48,7 +44,7 @@ public class Misc
PermissionSet.SendMessages;
var invite =
$"https://discord.com/oauth2/authorize?client_id={clientId}&scope=bot%20applications.commands&permissions={(ulong)permissions}";
$"https://discord.com/oauth2/authorize?client_id={_botConfig.ClientId}&scope=bot%20applications.commands&permissions={(ulong)permissions}";
var botName = _botConfig.IsBetaBot ? "PluralKit Beta" : "PluralKit";
await ctx.Reply($"{Emojis.Success} Use this link to add {botName} to your server:\n<{invite}>");

View File

@@ -59,7 +59,7 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
public async Task Handle(int shardId, MessageCreateEvent evt)
{
if (evt.Author.Id == await _cache.GetOwnUser()) return;
if (evt.Author.Id == _config.ClientId) return;
if (evt.Type != Message.MessageType.Default && evt.Type != Message.MessageType.Reply) return;
if (IsDuplicateMessage(evt)) return;
@@ -109,10 +109,8 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
var content = evt.Content;
if (content == null) return false;
var ourUserId = await _cache.GetOwnUser();
// Check for command prefix
if (!HasCommandPrefix(content, ourUserId, out var cmdStart) || cmdStart == content.Length)
if (!HasCommandPrefix(content, _config.ClientId, out var cmdStart) || cmdStart == content.Length)
return false;
// Trim leading whitespace from command without actually modifying the string

View File

@@ -15,6 +15,7 @@ namespace PluralKit.Bot;
public class MessageEdited: IEventHandler<MessageUpdateEvent>
{
private readonly Bot _bot;
private readonly BotConfig _config;
private readonly IDiscordCache _cache;
private readonly Cluster _client;
private readonly IDatabase _db;
@@ -27,7 +28,7 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
public MessageEdited(LastMessageCacheService lastMessageCache, ProxyService proxy, IDatabase db,
IMetrics metrics, ModelRepository repo, Cluster client, IDiscordCache cache, Bot bot,
DiscordApiClient rest, ILogger logger)
BotConfig config, DiscordApiClient rest, ILogger logger)
{
_lastMessageCache = lastMessageCache;
_proxy = proxy;
@@ -37,13 +38,14 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
_client = client;
_cache = cache;
_bot = bot;
_config = config;
_rest = rest;
_logger = logger.ForContext<MessageEdited>();
}
public async Task Handle(int shardId, MessageUpdateEvent evt)
{
if (evt.Author.Value?.Id == await _cache.GetOwnUser()) return;
if (evt.Author.Value?.Id == _config.ClientId) return;
// Edit message events sometimes arrive with missing data; double-check it's all there
if (!evt.Content.HasValue || !evt.Author.HasValue || !evt.Member.HasValue)

View File

@@ -18,6 +18,7 @@ namespace PluralKit.Bot;
public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
{
private readonly Bot _bot;
private readonly BotConfig _config;
private readonly IDiscordCache _cache;
private readonly Cluster _cluster;
private readonly CommandMessageService _commandMessageService;
@@ -30,13 +31,14 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
public ReactionAdded(ILogger logger, IDatabase db, ModelRepository repo,
CommandMessageService commandMessageService, IDiscordCache cache, Bot bot, Cluster cluster,
DiscordApiClient rest, EmbedService embeds, PrivateChannelService dmCache)
BotConfig config, DiscordApiClient rest, EmbedService embeds, PrivateChannelService dmCache)
{
_db = db;
_repo = repo;
_commandMessageService = commandMessageService;
_cache = cache;
_bot = bot;
_config = config;
_cluster = cluster;
_rest = rest;
_embeds = embeds;
@@ -52,7 +54,7 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
private async ValueTask TryHandleProxyMessageReactions(MessageReactionAddEvent evt)
{
// ignore any reactions added by *us*
if (evt.UserId == await _cache.GetOwnUser())
if (evt.UserId == _config.ClientId)
return;
// Ignore reactions from bots (we can't DM them anyway)

View File

@@ -58,7 +58,7 @@ public class Init
var cache = services.Resolve<IDiscordCache>();
if (cache is RedisDiscordCache)
await (cache as RedisDiscordCache).InitAsync(coreConfig.RedisAddr, config.ClientId!.Value);
await (cache as RedisDiscordCache).InitAsync(coreConfig.RedisAddr);
if (config.Cluster == null)
{

View File

@@ -49,8 +49,8 @@ public class BotModule: Module
var botConfig = c.Resolve<BotConfig>();
if (botConfig.UseRedisCache)
return new RedisDiscordCache(c.Resolve<ILogger>());
return new MemoryDiscordCache();
return new RedisDiscordCache(c.Resolve<ILogger>(), botConfig.ClientId);
return new MemoryDiscordCache(botConfig.ClientId);
}).AsSelf().SingleInstance();
builder.RegisterType<PrivateChannelService>().AsSelf().SingleInstance();

View File

@@ -15,6 +15,7 @@ namespace PluralKit.Bot;
public class LogChannelService
{
private readonly Bot _bot;
private readonly BotConfig _config;
private readonly IDiscordCache _cache;
private readonly IDatabase _db;
private readonly EmbedService _embed;
@@ -23,7 +24,7 @@ public class LogChannelService
private readonly DiscordApiClient _rest;
public LogChannelService(EmbedService embed, ILogger logger, IDatabase db, ModelRepository repo,
IDiscordCache cache, DiscordApiClient rest, Bot bot)
IDiscordCache cache, DiscordApiClient rest, Bot bot, BotConfig config)
{
_embed = embed;
_db = db;
@@ -31,6 +32,7 @@ public class LogChannelService
_cache = cache;
_rest = rest;
_bot = bot;
_config = config;
_logger = logger.ForContext<LogChannelService>();
}
@@ -97,9 +99,9 @@ public class LogChannelService
var guildMember = await _cache.TryGetSelfMember(channel.GuildId.Value);
if (guildMember == null)
guildMember = await _rest.GetGuildMember(channel.GuildId.Value, await _cache.GetOwnUser());
guildMember = await _rest.GetGuildMember(channel.GuildId.Value, _config.ClientId);
var perms = PermissionExtensions.PermissionsFor(guild, channel, await _cache.GetOwnUser(), guildMember);
var perms = PermissionExtensions.PermissionsFor(guild, channel, _config.ClientId, guildMember);
return perms;
}

View File

@@ -17,16 +17,18 @@ public class WebhookCacheService
private readonly IDiscordCache _cache;
private readonly ILogger _logger;
private readonly IMetrics _metrics;
private readonly BotConfig _config;
private readonly DiscordApiClient _rest;
private readonly ConcurrentDictionary<ulong, Lazy<Task<Webhook>>> _webhooks;
public WebhookCacheService(ILogger logger, IMetrics metrics, DiscordApiClient rest, IDiscordCache cache)
public WebhookCacheService(ILogger logger, IMetrics metrics, DiscordApiClient rest, IDiscordCache cache, BotConfig config)
{
_metrics = metrics;
_rest = rest;
_cache = cache;
_config = config;
_logger = logger.ForContext<WebhookCacheService>();
_webhooks = new ConcurrentDictionary<ulong, Lazy<Task<Webhook>>>();
}
@@ -86,8 +88,7 @@ public class WebhookCacheService
var webhooks = await FetchChannelWebhooks(channelId);
// If the channel has a webhook created by PK, just return that one
var ourUserId = await _cache.GetOwnUser();
var ourWebhook = webhooks.FirstOrDefault(hook => IsWebhookMine(ourUserId, hook));
var ourWebhook = webhooks.FirstOrDefault(hook => IsWebhookMine(hook));
if (ourWebhook != null)
return ourWebhook;
@@ -122,5 +123,5 @@ public class WebhookCacheService
return await _rest.CreateWebhook(channelId, new CreateWebhookRequest(WebhookName));
}
private bool IsWebhookMine(ulong userId, Webhook arg) => arg.User?.Id == userId && arg.Name == WebhookName;
private bool IsWebhookMine(Webhook arg) => arg.User?.Id == _config.ClientId && arg.Name == WebhookName;
}