mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 13:06:50 +00:00
feat: gateway service
This commit is contained in:
parent
1118d8bdf8
commit
e4ed354536
50 changed files with 1737 additions and 545 deletions
|
|
@ -63,14 +63,14 @@ public class ApplicationCommandProxiedMessage
|
|||
var messageId = ctx.Event.Data!.TargetId!.Value;
|
||||
|
||||
// check for command messages
|
||||
var (authorId, channelId) = await ctx.Services.Resolve<CommandMessageService>().GetCommandMessage(messageId);
|
||||
if (authorId != null)
|
||||
var cmessage = await ctx.Services.Resolve<CommandMessageService>().GetCommandMessage(messageId);
|
||||
if (cmessage != null)
|
||||
{
|
||||
if (authorId != ctx.User.Id)
|
||||
if (cmessage.AuthorId != ctx.User.Id)
|
||||
throw new PKError("You can only delete command messages queried by this account.");
|
||||
|
||||
var isDM = (await _repo.GetDmChannel(ctx.User!.Id)) == channelId;
|
||||
await DeleteMessageInner(ctx, channelId!.Value, messageId, isDM);
|
||||
var isDM = (await _repo.GetDmChannel(ctx.User!.Id)) == cmessage.ChannelId;
|
||||
await DeleteMessageInner(ctx, cmessage.GuildId, cmessage.ChannelId, messageId, isDM);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ public class ApplicationCommandProxiedMessage
|
|||
if (message.System?.Id != ctx.System.Id && message.Message.Sender != ctx.User.Id)
|
||||
throw new PKError("You can only delete your own messages.");
|
||||
|
||||
await DeleteMessageInner(ctx, message.Message.Channel, message.Message.Mid, false);
|
||||
await DeleteMessageInner(ctx, message.Message.Guild ?? 0, message.Message.Channel, message.Message.Mid, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -89,9 +89,9 @@ public class ApplicationCommandProxiedMessage
|
|||
throw Errors.MessageNotFound(messageId);
|
||||
}
|
||||
|
||||
internal async Task DeleteMessageInner(InteractionContext ctx, ulong channelId, ulong messageId, bool isDM = false)
|
||||
internal async Task DeleteMessageInner(InteractionContext ctx, ulong guildId, ulong channelId, ulong messageId, bool isDM = false)
|
||||
{
|
||||
if (!((await _cache.BotPermissionsIn(channelId)).HasFlag(PermissionSet.ManageMessages) || isDM))
|
||||
if (!((await _cache.BotPermissionsIn(guildId, channelId)).HasFlag(PermissionSet.ManageMessages) || isDM))
|
||||
throw new PKError("PluralKit does not have the *Manage Messages* permission in this channel, and thus cannot delete the message."
|
||||
+ " Please contact a server administrator to remedy this.");
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ public class ApplicationCommandProxiedMessage
|
|||
// (if not, PK shouldn't send messages on their behalf)
|
||||
var member = await _rest.GetGuildMember(ctx.GuildId, ctx.User.Id);
|
||||
var requiredPerms = PermissionSet.ViewChannel | PermissionSet.SendMessages;
|
||||
if (member == null || !(await _cache.PermissionsForMemberInChannel(ctx.ChannelId, member)).HasFlag(requiredPerms))
|
||||
if (member == null || !(await _cache.PermissionsForMemberInChannel(ctx.GuildId, ctx.ChannelId, member)).HasFlag(requiredPerms))
|
||||
{
|
||||
throw new PKError("You do not have permission to send messages in this channel.");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -99,11 +99,13 @@ public class Bot
|
|||
|
||||
private async Task OnEventReceived(int shardId, IGatewayEvent evt)
|
||||
{
|
||||
// we HandleGatewayEvent **before** getting the own user, because the own user is set in HandleGatewayEvent for ReadyEvent
|
||||
await _cache.HandleGatewayEvent(evt);
|
||||
|
||||
await _cache.TryUpdateSelfMember(_config.ClientId, evt);
|
||||
if (_cache is MemoryDiscordCache)
|
||||
{
|
||||
// we HandleGatewayEvent **before** getting the own user, because the own user is set in HandleGatewayEvent for ReadyEvent
|
||||
await _cache.HandleGatewayEvent(evt);
|
||||
|
||||
await _cache.TryUpdateSelfMember(_config.ClientId, evt);
|
||||
}
|
||||
await OnEventReceivedInner(shardId, evt);
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +177,16 @@ public class Bot
|
|||
}
|
||||
|
||||
using var _ = LogContext.PushProperty("EventId", Guid.NewGuid());
|
||||
using var __ = LogContext.Push(await serviceScope.Resolve<SerilogGatewayEnricherFactory>().GetEnricher(shardId, evt));
|
||||
// this fails when cache lookup fails, so put it in a try-catch
|
||||
try
|
||||
{
|
||||
using var __ = LogContext.Push(await serviceScope.Resolve<SerilogGatewayEnricherFactory>().GetEnricher(shardId, evt));
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
|
||||
await HandleError(handler, evt, serviceScope, exc);
|
||||
}
|
||||
_logger.Verbose("Received gateway event: {@Event}", evt);
|
||||
|
||||
try
|
||||
|
|
@ -243,7 +254,7 @@ public class Bot
|
|||
if (!exc.ShowToUser()) return;
|
||||
|
||||
// Once we've sent it to Sentry, report it to the user (if we have permission to)
|
||||
var reportChannel = handler.ErrorChannelFor(evt, _config.ClientId);
|
||||
var (guildId, reportChannel) = handler.ErrorChannelFor(evt, _config.ClientId);
|
||||
if (reportChannel == null)
|
||||
{
|
||||
if (evt is InteractionCreateEvent ice && ice.Type == Interaction.InteractionType.ApplicationCommand)
|
||||
|
|
@ -251,7 +262,7 @@ public class Bot
|
|||
return;
|
||||
}
|
||||
|
||||
var botPerms = await _cache.BotPermissionsIn(reportChannel.Value);
|
||||
var botPerms = await _cache.BotPermissionsIn(guildId ?? 0, reportChannel.Value);
|
||||
if (botPerms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks))
|
||||
await _errorMessageService.SendErrorMessage(reportChannel.Value, sentryEvent.EventId.ToString());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ public class BotConfig
|
|||
|
||||
public string? GatewayQueueUrl { get; set; }
|
||||
public bool UseRedisRatelimiter { get; set; } = false;
|
||||
public bool UseRedisCache { get; set; } = false;
|
||||
|
||||
public string? HttpCacheUrl { get; set; }
|
||||
|
||||
public string? RedisGatewayUrl { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class Context
|
|||
public readonly int ShardId;
|
||||
public readonly Cluster Cluster;
|
||||
|
||||
public Task<PermissionSet> BotPermissions => Cache.BotPermissionsIn(Channel.Id);
|
||||
public Task<PermissionSet> BotPermissions => Cache.BotPermissionsIn(Guild?.Id ?? 0, Channel.Id);
|
||||
public Task<PermissionSet> UserPermissions => Cache.PermissionsForMCE((MessageCreateEvent)Message);
|
||||
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ public class Context
|
|||
// {
|
||||
// Sensitive information that might want to be deleted by :x: reaction is typically in an embed format (member cards, for example)
|
||||
// but since we can, we just store all sent messages for possible deletion
|
||||
await _commandMessageService.RegisterMessage(msg.Id, msg.ChannelId, Author.Id);
|
||||
await _commandMessageService.RegisterMessage(msg.Id, Guild?.Id ?? 0, msg.ChannelId, Author.Id);
|
||||
// }
|
||||
|
||||
return msg;
|
||||
|
|
|
|||
|
|
@ -188,7 +188,8 @@ public static class ContextEntityArgumentsExt
|
|||
if (!MentionUtils.TryParseChannel(ctx.PeekArgument(), out var id))
|
||||
return null;
|
||||
|
||||
var channel = await ctx.Cache.TryGetChannel(id);
|
||||
// todo: match channels in other guilds
|
||||
var channel = await ctx.Cache.TryGetChannel(ctx.Guild!.Id, id);
|
||||
if (channel == null)
|
||||
channel = await ctx.Rest.GetChannelOrNull(id);
|
||||
if (channel == null)
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ public class Checks
|
|||
var error = "Channel not found or you do not have permissions to access it.";
|
||||
|
||||
// todo: this breaks if channel is not in cache and bot does not have View Channel permissions
|
||||
// with new cache it breaks if channel is not in current guild
|
||||
var channel = await ctx.MatchChannel();
|
||||
if (channel == null || channel.GuildId == null)
|
||||
throw new PKError(error);
|
||||
|
|
@ -156,7 +157,8 @@ public class Checks
|
|||
if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel))
|
||||
throw new PKError(error);
|
||||
|
||||
var botPermissions = await _cache.BotPermissionsIn(channel.Id);
|
||||
// todo: permcheck channel outside of guild?
|
||||
var botPermissions = await _cache.BotPermissionsIn(ctx.Guild.Id, channel.Id);
|
||||
|
||||
// We use a bitfield so we can set individual permission bits
|
||||
ulong missingPermissions = 0;
|
||||
|
|
@ -231,11 +233,11 @@ public class Checks
|
|||
var channel = await _rest.GetChannelOrNull(channelId.Value);
|
||||
if (channel == null)
|
||||
throw new PKError("Unable to get the channel associated with this message.");
|
||||
|
||||
var rootChannel = await _cache.GetRootChannel(channel.Id);
|
||||
if (channel.GuildId == null)
|
||||
throw new PKError("PluralKit is not able to proxy messages in DMs.");
|
||||
|
||||
var rootChannel = await _cache.GetRootChannel(channel.GuildId!.Value, channel.Id);
|
||||
|
||||
// using channel.GuildId here since _rest.GetMessage() doesn't return the GuildId
|
||||
var context = await ctx.Repository.GetMessageContext(msg.Author.Id, channel.GuildId.Value, rootChannel.Id, msg.ChannelId);
|
||||
var members = (await ctx.Repository.GetProxyMembers(msg.Author.Id, channel.GuildId.Value)).ToList();
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ public class ProxiedMessage
|
|||
try
|
||||
{
|
||||
var editedMsg =
|
||||
await _webhookExecutor.EditWebhookMessage(msg.Channel, msg.Mid, newContent, clearEmbeds);
|
||||
await _webhookExecutor.EditWebhookMessage(msg.Guild ?? 0, msg.Channel, msg.Mid, newContent, clearEmbeds);
|
||||
|
||||
if (ctx.Guild == null)
|
||||
await _rest.CreateReaction(ctx.Channel.Id, ctx.Message.Id, new Emoji { Name = Emojis.Success });
|
||||
|
|
@ -436,14 +436,14 @@ public class ProxiedMessage
|
|||
|
||||
private async Task DeleteCommandMessage(Context ctx, ulong messageId)
|
||||
{
|
||||
var (authorId, channelId) = await ctx.Services.Resolve<CommandMessageService>().GetCommandMessage(messageId);
|
||||
if (authorId == null)
|
||||
var cmessage = await ctx.Services.Resolve<CommandMessageService>().GetCommandMessage(messageId);
|
||||
if (cmessage == null)
|
||||
throw Errors.MessageNotFound(messageId);
|
||||
|
||||
if (authorId != ctx.Author.Id)
|
||||
if (cmessage!.AuthorId != ctx.Author.Id)
|
||||
throw new PKError("You can only delete command messages queried by this account.");
|
||||
|
||||
await ctx.Rest.DeleteMessage(channelId!.Value, messageId);
|
||||
await ctx.Rest.DeleteMessage(cmessage.ChannelId, messageId);
|
||||
|
||||
if (ctx.Guild != null)
|
||||
await ctx.Rest.DeleteMessage(ctx.Message);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public class ServerConfig
|
|||
if (channel.Type != Channel.ChannelType.GuildText && channel.Type != Channel.ChannelType.GuildPublicThread && channel.Type != Channel.ChannelType.GuildPrivateThread)
|
||||
throw new PKError("PluralKit cannot log messages to this type of channel.");
|
||||
|
||||
var perms = await _cache.BotPermissionsIn(channel.Id);
|
||||
var perms = await _cache.BotPermissionsIn(ctx.Guild.Id, 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))
|
||||
|
|
@ -104,7 +104,7 @@ public class ServerConfig
|
|||
|
||||
// Resolve all channels from the cache and order by position
|
||||
var channels = (await Task.WhenAll(blacklist.Blacklist
|
||||
.Select(id => _cache.TryGetChannel(id))))
|
||||
.Select(id => _cache.TryGetChannel(ctx.Guild.Id, id))))
|
||||
.Where(c => c != null)
|
||||
.OrderBy(c => c.Position)
|
||||
.ToList();
|
||||
|
|
@ -121,7 +121,7 @@ public class ServerConfig
|
|||
async (eb, l) =>
|
||||
{
|
||||
async Task<string> CategoryName(ulong? id) =>
|
||||
id != null ? (await _cache.GetChannel(id.Value)).Name : "(no category)";
|
||||
id != null ? (await _cache.GetChannel(ctx.Guild.Id, id.Value)).Name : "(no category)";
|
||||
|
||||
ulong? lastCategory = null;
|
||||
|
||||
|
|
@ -153,8 +153,9 @@ public class ServerConfig
|
|||
var config = await ctx.Repository.GetGuild(ctx.Guild.Id);
|
||||
|
||||
// Resolve all channels from the cache and order by position
|
||||
// todo: GetAllChannels?
|
||||
var channels = (await Task.WhenAll(config.LogBlacklist
|
||||
.Select(id => _cache.TryGetChannel(id))))
|
||||
.Select(id => _cache.TryGetChannel(ctx.Guild.Id, id))))
|
||||
.Where(c => c != null)
|
||||
.OrderBy(c => c.Position)
|
||||
.ToList();
|
||||
|
|
@ -171,7 +172,7 @@ public class ServerConfig
|
|||
async (eb, l) =>
|
||||
{
|
||||
async Task<string> CategoryName(ulong? id) =>
|
||||
id != null ? (await _cache.GetChannel(id.Value)).Name : "(no category)";
|
||||
id != null ? (await _cache.GetChannel(ctx.Guild.Id, id.Value)).Name : "(no category)";
|
||||
|
||||
ulong? lastCategory = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ public interface IEventHandler<in T> where T : IGatewayEvent
|
|||
{
|
||||
Task Handle(int shardId, T evt);
|
||||
|
||||
ulong? ErrorChannelFor(T evt, ulong userId) => null;
|
||||
(ulong?, ulong?) ErrorChannelFor(T evt, ulong userId) => (null, null);
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
|
|||
_dmCache = dmCache;
|
||||
}
|
||||
|
||||
public ulong? ErrorChannelFor(MessageCreateEvent evt, ulong userId) => evt.ChannelId;
|
||||
public (ulong?, ulong?) ErrorChannelFor(MessageCreateEvent evt, ulong userId) => (evt.GuildId, evt.ChannelId);
|
||||
private bool IsDuplicateMessage(Message msg) =>
|
||||
// We consider a message duplicate if it has the same ID as the previous message that hit the gateway
|
||||
_lastMessageCache.GetLastMessage(msg.ChannelId)?.Current.Id == msg.Id;
|
||||
|
|
@ -63,7 +63,7 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
|
|||
if (evt.Type != Message.MessageType.Default && evt.Type != Message.MessageType.Reply) return;
|
||||
if (IsDuplicateMessage(evt)) return;
|
||||
|
||||
var botPermissions = await _cache.BotPermissionsIn(evt.ChannelId);
|
||||
var botPermissions = await _cache.BotPermissionsIn(evt.GuildId ?? 0, evt.ChannelId);
|
||||
if (!botPermissions.HasFlag(PermissionSet.SendMessages)) return;
|
||||
|
||||
// spawn off saving the private channel into another thread
|
||||
|
|
@ -71,8 +71,8 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
|
|||
_ = _dmCache.TrySavePrivateChannel(evt);
|
||||
|
||||
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);
|
||||
var channel = await _cache.GetChannel(evt.GuildId ?? 0, evt.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(evt.GuildId ?? 0, evt.ChannelId);
|
||||
|
||||
// Log metrics and message info
|
||||
_metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
|
||||
|
|
@ -90,7 +90,8 @@ public class MessageCreated: IEventHandler<MessageCreateEvent>
|
|||
if (await TryHandleCommand(shardId, evt, guild, channel))
|
||||
return;
|
||||
|
||||
await TryHandleProxy(evt, guild, channel, rootChannel.Id, botPermissions);
|
||||
if (evt.GuildId != null)
|
||||
await TryHandleProxy(evt, guild, channel, rootChannel.Id, botPermissions);
|
||||
}
|
||||
|
||||
private async Task TryHandleLogClean(Channel channel, MessageCreateEvent evt)
|
||||
|
|
|
|||
|
|
@ -52,10 +52,12 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
|
|||
if (!evt.Content.HasValue || !evt.Author.HasValue || !evt.Member.HasValue)
|
||||
return;
|
||||
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
var guildIdMaybe = evt.GuildId.HasValue ? evt.GuildId.Value ?? 0 : 0;
|
||||
|
||||
var channel = await _cache.GetChannel(guildIdMaybe, evt.ChannelId); // todo: is this correct for message update?
|
||||
if (!DiscordUtils.IsValidGuildChannel(channel))
|
||||
return;
|
||||
var rootChannel = await _cache.GetRootChannel(channel.Id);
|
||||
var rootChannel = await _cache.GetRootChannel(guildIdMaybe, channel.Id);
|
||||
var guild = await _cache.GetGuild(channel.GuildId!.Value);
|
||||
var lastMessage = _lastMessageCache.GetLastMessage(evt.ChannelId)?.Current;
|
||||
|
||||
|
|
@ -69,7 +71,7 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
|
|||
ctx = await _repo.GetMessageContext(evt.Author.Value!.Id, channel.GuildId!.Value, rootChannel.Id, evt.ChannelId);
|
||||
|
||||
var equivalentEvt = await GetMessageCreateEvent(evt, lastMessage, channel);
|
||||
var botPermissions = await _cache.BotPermissionsIn(channel.Id);
|
||||
var botPermissions = await _cache.BotPermissionsIn(guildIdMaybe, channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -91,7 +93,7 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
|
|||
private async Task<MessageCreateEvent> GetMessageCreateEvent(MessageUpdateEvent evt, CachedMessage lastMessage,
|
||||
Channel channel)
|
||||
{
|
||||
var referencedMessage = await GetReferencedMessage(evt.ChannelId, lastMessage.ReferencedMessage);
|
||||
var referencedMessage = await GetReferencedMessage(evt.GuildId.HasValue ? evt.GuildId.Value ?? 0 : 0, evt.ChannelId, lastMessage.ReferencedMessage);
|
||||
|
||||
var messageReference = lastMessage.ReferencedMessage != null
|
||||
? new Message.Reference(channel.GuildId, evt.ChannelId, lastMessage.ReferencedMessage.Value)
|
||||
|
|
@ -118,12 +120,12 @@ public class MessageEdited: IEventHandler<MessageUpdateEvent>
|
|||
return equivalentEvt;
|
||||
}
|
||||
|
||||
private async Task<Message?> GetReferencedMessage(ulong channelId, ulong? referencedMessageId)
|
||||
private async Task<Message?> GetReferencedMessage(ulong guildId, ulong channelId, ulong? referencedMessageId)
|
||||
{
|
||||
if (referencedMessageId == null)
|
||||
return null;
|
||||
|
||||
var botPermissions = await _cache.BotPermissionsIn(channelId);
|
||||
var botPermissions = await _cache.BotPermissionsIn(guildId, channelId);
|
||||
if (!botPermissions.HasFlag(PermissionSet.ReadMessageHistory))
|
||||
{
|
||||
_logger.Warning(
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
// but we aren't able to get DMs from bots anyway, so it's not really needed
|
||||
if (evt.GuildId != null && (evt.Member?.User?.Bot ?? false)) return;
|
||||
|
||||
var channel = await _cache.GetChannel(evt.ChannelId);
|
||||
var channel = await _cache.GetChannel(evt.GuildId ?? 0, evt.ChannelId);
|
||||
|
||||
// check if it's a command message first
|
||||
// since this can happen in DMs as well
|
||||
|
|
@ -75,10 +75,10 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
return;
|
||||
}
|
||||
|
||||
var (authorId, _) = await _commandMessageService.GetCommandMessage(evt.MessageId);
|
||||
if (authorId != null)
|
||||
var cmessage = await _commandMessageService.GetCommandMessage(evt.MessageId);
|
||||
if (cmessage != null)
|
||||
{
|
||||
await HandleCommandDeleteReaction(evt, authorId.Value, false);
|
||||
await HandleCommandDeleteReaction(evt, cmessage.AuthorId, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
|
||||
private async ValueTask HandleProxyDeleteReaction(MessageReactionAddEvent evt, PKMessage msg)
|
||||
{
|
||||
if (!(await _cache.BotPermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
if (!(await _cache.BotPermissionsIn(evt.GuildId ?? 0, evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
return;
|
||||
|
||||
var isSameSystem = msg.Member != null && await _repo.IsMemberOwnedByAccount(msg.Member.Value, evt.UserId);
|
||||
|
|
@ -150,7 +150,7 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
if (authorId != null && authorId != evt.UserId)
|
||||
return;
|
||||
|
||||
if (!((await _cache.BotPermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages) || isDM))
|
||||
if (!((await _cache.BotPermissionsIn(evt.GuildId ?? 0, evt.ChannelId)).HasFlag(PermissionSet.ManageMessages) || isDM))
|
||||
return;
|
||||
|
||||
// todo: don't try to delete the user's own messages in DMs
|
||||
|
|
@ -206,14 +206,14 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
|
||||
private async ValueTask HandlePingReaction(MessageReactionAddEvent evt, FullMessage msg)
|
||||
{
|
||||
if (!(await _cache.BotPermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
if (!(await _cache.BotPermissionsIn(evt.GuildId ?? 0, 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 || !(await _cache.PermissionsForMemberInChannel(evt.ChannelId, member)).HasFlag(requiredPerms)) return;
|
||||
if (member == null || !(await _cache.PermissionsForMemberInChannel(evt.GuildId ?? 0, evt.ChannelId, member)).HasFlag(requiredPerms)) return;
|
||||
|
||||
if (msg.Member == null) return;
|
||||
|
||||
|
|
@ -266,7 +266,7 @@ public class ReactionAdded: IEventHandler<MessageReactionAddEvent>
|
|||
|
||||
private async Task TryRemoveOriginalReaction(MessageReactionAddEvent evt)
|
||||
{
|
||||
if ((await _cache.BotPermissionsIn(evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
if ((await _cache.BotPermissionsIn(evt.GuildId ?? 0, evt.ChannelId)).HasFlag(PermissionSet.ManageMessages))
|
||||
await _rest.DeleteUserReaction(evt.ChannelId, evt.MessageId, evt.Emoji, evt.UserId);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,8 +56,6 @@ public class Init
|
|||
await redis.InitAsync(coreConfig);
|
||||
|
||||
var cache = services.Resolve<IDiscordCache>();
|
||||
if (cache is RedisDiscordCache)
|
||||
await (cache as RedisDiscordCache).InitAsync(coreConfig.RedisAddr);
|
||||
|
||||
if (config.Cluster == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ public class BotModule: Module
|
|||
{
|
||||
var botConfig = c.Resolve<BotConfig>();
|
||||
|
||||
if (botConfig.UseRedisCache)
|
||||
return new RedisDiscordCache(c.Resolve<ILogger>(), botConfig.ClientId);
|
||||
if (botConfig.HttpCacheUrl != null)
|
||||
return new HttpDiscordCache(c.Resolve<ILogger>(),
|
||||
c.Resolve<HttpClient>(), botConfig.HttpCacheUrl, botConfig.ClientId);
|
||||
|
||||
return new MemoryDiscordCache(botConfig.ClientId);
|
||||
}).AsSelf().SingleInstance();
|
||||
builder.RegisterType<PrivateChannelService>().AsSelf().SingleInstance();
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public class ProxyService
|
|||
public async Task<bool> HandleIncomingMessage(MessageCreateEvent message, MessageContext ctx,
|
||||
Guild guild, Channel channel, bool allowAutoproxy, PermissionSet botPermissions)
|
||||
{
|
||||
var rootChannel = await _cache.GetRootChannel(message.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(message.GuildId!.Value, message.ChannelId);
|
||||
|
||||
if (!ShouldProxy(channel, rootChannel, message, ctx))
|
||||
return false;
|
||||
|
|
@ -207,8 +207,8 @@ public class ProxyService
|
|||
var content = match.ProxyContent;
|
||||
if (!allowEmbeds) content = content.BreakLinkEmbeds();
|
||||
|
||||
var messageChannel = await _cache.GetChannel(trigger.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(trigger.ChannelId);
|
||||
var messageChannel = await _cache.GetChannel(trigger.GuildId!.Value, trigger.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(trigger.GuildId!.Value, trigger.ChannelId);
|
||||
var threadId = messageChannel.IsThread() ? messageChannel.Id : (ulong?)null;
|
||||
var guild = await _cache.GetGuild(trigger.GuildId.Value);
|
||||
var guildMember = await _rest.GetGuildMember(trigger.GuildId!.Value, trigger.Author.Id);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class CommandMessageService
|
|||
_logger = logger.ForContext<CommandMessageService>();
|
||||
}
|
||||
|
||||
public async Task RegisterMessage(ulong messageId, ulong channelId, ulong authorId)
|
||||
public async Task RegisterMessage(ulong messageId, ulong guildId, ulong channelId, ulong authorId)
|
||||
{
|
||||
if (_redis.Connection == null) return;
|
||||
|
||||
|
|
@ -27,17 +27,19 @@ public class CommandMessageService
|
|||
messageId, authorId, channelId
|
||||
);
|
||||
|
||||
await _redis.Connection.GetDatabase().StringSetAsync(messageId.ToString(), $"{authorId}-{channelId}", expiry: CommandMessageRetention);
|
||||
await _redis.Connection.GetDatabase().StringSetAsync(messageId.ToString(), $"{authorId}-{channelId}-{guildId}", expiry: CommandMessageRetention);
|
||||
}
|
||||
|
||||
public async Task<(ulong?, ulong?)> GetCommandMessage(ulong messageId)
|
||||
public async Task<CommandMessage?> GetCommandMessage(ulong messageId)
|
||||
{
|
||||
var str = await _redis.Connection.GetDatabase().StringGetAsync(messageId.ToString());
|
||||
if (str.HasValue)
|
||||
{
|
||||
var split = ((string)str).Split("-");
|
||||
return (ulong.Parse(split[0]), ulong.Parse(split[1]));
|
||||
return new CommandMessage(ulong.Parse(split[0]), ulong.Parse(split[1]), ulong.Parse(split[2]));
|
||||
}
|
||||
return (null, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record CommandMessage(ulong AuthorId, ulong ChannelId, ulong GuildId);
|
||||
|
|
@ -336,7 +336,7 @@ public class EmbedService
|
|||
|
||||
public async Task<Embed> CreateMessageInfoEmbed(FullMessage msg, bool showContent, SystemConfig? ccfg = null)
|
||||
{
|
||||
var channel = await _cache.GetOrFetchChannel(_rest, msg.Message.Channel);
|
||||
var channel = await _cache.GetOrFetchChannel(_rest, msg.Message.Guild ?? 0, msg.Message.Channel);
|
||||
var ctx = LookupContext.ByNonOwner;
|
||||
|
||||
var serverMsg = await _rest.GetMessageOrNull(msg.Message.Channel, msg.Message.Mid);
|
||||
|
|
@ -403,14 +403,15 @@ public class EmbedService
|
|||
var roles = memberInfo?.Roles?.ToList();
|
||||
if (roles != null && roles.Count > 0 && showContent)
|
||||
{
|
||||
var rolesString = string.Join(", ", (await Task.WhenAll(roles
|
||||
.Select(async id =>
|
||||
var guild = await _cache.GetGuild(channel.GuildId!.Value);
|
||||
var rolesString = string.Join(", ", (roles
|
||||
.Select(id =>
|
||||
{
|
||||
var role = await _cache.TryGetRole(id);
|
||||
var role = Array.Find(guild.Roles, r => r.Id == id);
|
||||
if (role != null)
|
||||
return role;
|
||||
return new Role { Name = "*(unknown role)*", Position = 0 };
|
||||
})))
|
||||
}))
|
||||
.OrderByDescending(role => role.Position)
|
||||
.Select(role => role.Name));
|
||||
eb.Field(new Embed.Field($"Account roles ({roles.Count})", rolesString.Truncate(1024)));
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class LogChannelService
|
|||
if (logChannelId == null)
|
||||
return;
|
||||
|
||||
var triggerChannel = await _cache.GetChannel(proxiedMessage.Channel);
|
||||
var triggerChannel = await _cache.GetChannel(proxiedMessage.Guild!.Value, proxiedMessage.Channel);
|
||||
|
||||
var member = await _repo.GetMember(proxiedMessage.Member!.Value);
|
||||
var system = await _repo.GetSystem(member.System);
|
||||
|
|
@ -63,7 +63,7 @@ public class LogChannelService
|
|||
return null;
|
||||
|
||||
var guildId = proxiedMessage.Guild ?? trigger.GuildId.Value;
|
||||
var rootChannel = await _cache.GetRootChannel(trigger.ChannelId);
|
||||
var rootChannel = await _cache.GetRootChannel(guildId, trigger.ChannelId);
|
||||
|
||||
// get log channel info from the database
|
||||
var guild = await _repo.GetGuild(guildId);
|
||||
|
|
@ -109,7 +109,7 @@ public class LogChannelService
|
|||
private async Task<Channel?> FindLogChannel(ulong guildId, ulong channelId)
|
||||
{
|
||||
// TODO: fetch it directly on cache miss?
|
||||
if (await _cache.TryGetChannel(channelId) is Channel channel)
|
||||
if (await _cache.TryGetChannel(guildId, channelId) is Channel channel)
|
||||
return channel;
|
||||
|
||||
if (await _rest.GetChannelOrNull(channelId) is Channel restChannel)
|
||||
|
|
|
|||
|
|
@ -100,10 +100,10 @@ public class LoggerCleanService
|
|||
|
||||
public async ValueTask HandleLoggerBotCleanup(Message msg)
|
||||
{
|
||||
var channel = await _cache.GetChannel(msg.ChannelId);
|
||||
var channel = await _cache.GetChannel(msg.GuildId!.Value, msg.ChannelId!);
|
||||
|
||||
if (channel.Type != Channel.ChannelType.GuildText) return;
|
||||
if (!(await _cache.BotPermissionsIn(channel.Id)).HasFlag(PermissionSet.ManageMessages)) return;
|
||||
if (!(await _cache.BotPermissionsIn(msg.GuildId!.Value, channel.Id)).HasFlag(PermissionSet.ManageMessages)) return;
|
||||
|
||||
// If this message is from a *webhook*, check if the application ID matches one of the bots we know
|
||||
// If it's from a *bot*, check the bot ID to see if we know it.
|
||||
|
|
|
|||
|
|
@ -54,33 +54,6 @@ public class PeriodicStatCollector
|
|||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
// Aggregate guild/channel stats
|
||||
var guildCount = 0;
|
||||
var channelCount = 0;
|
||||
|
||||
// No LINQ today, sorry
|
||||
await foreach (var guild in _cache.GetAllGuilds())
|
||||
{
|
||||
guildCount++;
|
||||
foreach (var channel in await _cache.GetGuildChannels(guild.Id))
|
||||
if (DiscordUtils.IsValidGuildChannel(channel))
|
||||
channelCount++;
|
||||
}
|
||||
|
||||
if (_config.UseRedisMetrics)
|
||||
{
|
||||
var db = _redis.Connection.GetDatabase();
|
||||
await db.HashSetAsync("pluralkit:cluster_stats", new StackExchange.Redis.HashEntry[] {
|
||||
new(_botConfig.Cluster.NodeIndex, JsonConvert.SerializeObject(new ClusterMetricInfo
|
||||
{
|
||||
GuildCount = guildCount,
|
||||
ChannelCount = channelCount,
|
||||
DatabaseConnectionCount = _countHolder.ConnectionCount,
|
||||
WebhookCacheSize = _webhookCache.CacheSize,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// Process info
|
||||
var process = Process.GetCurrentProcess();
|
||||
_metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessPhysicalMemory, process.WorkingSet64);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public class WebhookExecutorService
|
|||
return webhookMessage;
|
||||
}
|
||||
|
||||
public async Task<Message> EditWebhookMessage(ulong channelId, ulong messageId, string newContent, bool clearEmbeds = false)
|
||||
public async Task<Message> EditWebhookMessage(ulong guildId, ulong channelId, ulong messageId, string newContent, bool clearEmbeds = false)
|
||||
{
|
||||
var allowedMentions = newContent.ParseMentions() with
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ public class WebhookExecutorService
|
|||
};
|
||||
|
||||
ulong? threadId = null;
|
||||
var channel = await _cache.GetOrFetchChannel(_rest, channelId);
|
||||
var channel = await _cache.GetOrFetchChannel(_rest, guildId, channelId);
|
||||
if (channel.IsThread())
|
||||
{
|
||||
threadId = channelId;
|
||||
|
|
|
|||
|
|
@ -38,9 +38,11 @@ public class SerilogGatewayEnricherFactory
|
|||
{
|
||||
props.Add(new LogEventProperty("ChannelId", new ScalarValue(channel.Value)));
|
||||
|
||||
if (await _cache.TryGetChannel(channel.Value) != null)
|
||||
var guildIdForCache = guild != null ? guild.Value : 0;
|
||||
|
||||
if (await _cache.TryGetChannel(guildIdForCache, channel.Value) != null)
|
||||
{
|
||||
var botPermissions = await _cache.BotPermissionsIn(channel.Value);
|
||||
var botPermissions = await _cache.BotPermissionsIn(guildIdForCache, channel.Value);
|
||||
props.Add(new LogEventProperty("BotPermissions", new ScalarValue(botPermissions)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue