private async Task <Channel?> FindLogChannel(ulong guildId, ulong channelId) { // TODO: fetch it directly on cache miss? if (await _cache.TryGetChannel(channelId) is Channel channel) { return(channel); } if (await _rest.GetChannelOrNull(channelId) is Channel restChannel) { return(restChannel); } // Channel doesn't exist or we don't have permission to access it, let's remove it from the database too _logger.Warning( "Attempted to fetch missing log channel {LogChannel} for guild {Guild}, removing from database", channelId, guildId ); await using var conn = await _db.Obtain(); await conn.ExecuteAsync("update servers set log_channel = null where id = @Guild", new { Guild = guildId }); return(null); }
public async Task MessageProxyCheck(Context ctx) { if (!ctx.HasNext() && ctx.Message.MessageReference == null) { throw new PKSyntaxError("You need to specify a message."); } var failedToGetMessage = "Could not find a valid message to check, was not able to fetch the message, or the message was not sent by you."; var(messageId, channelId) = ctx.MatchMessage(false); if (messageId == null || channelId == null) { throw new PKError(failedToGetMessage); } var proxiedMsg = await ctx.Database.Execute(conn => ctx.Repository.GetMessage(conn, messageId.Value)); if (proxiedMsg != null) { await ctx.Reply($"{Emojis.Success} This message was proxied successfully."); return; } // get the message info var msg = await _rest.GetMessageOrNull(channelId.Value, messageId.Value); if (msg == null) { throw new PKError(failedToGetMessage); } // if user is fetching a message in a different channel sent by someone else, throw a generic error message if (msg == null || msg.Author.Id != ctx.Author.Id && msg.ChannelId != ctx.Channel.Id) { throw new PKError(failedToGetMessage); } if ((_botConfig.Prefixes ?? BotConfig.DefaultPrefixes).Any(p => msg.Content.StartsWith(p))) { await ctx.Reply("This message starts with the bot's prefix, and was parsed as a command."); return; } if (msg.Author.Bot) { throw new PKError("You cannot check messages sent by a bot."); } if (msg.WebhookId != null) { throw new PKError("You cannot check messages sent by a webhook."); } if (msg.Author.Id != ctx.Author.Id && !ctx.CheckBotAdmin()) { throw new PKError("You can only check your own messages."); } // get the channel info var channel = await _rest.GetChannelOrNull(channelId.Value); if (channel == null) { throw new PKError("Unable to get the channel associated with this message."); } // using channel.GuildId here since _rest.GetMessage() doesn't return the GuildId var context = await ctx.Repository.GetMessageContext(msg.Author.Id, channel.GuildId.Value, msg.ChannelId); var members = (await ctx.Repository.GetProxyMembers(msg.Author.Id, channel.GuildId.Value)).ToList(); // for now this is just server var autoproxySettings = await ctx.Repository.GetAutoproxySettings(ctx.System.Id, channel.GuildId.Value, null); // todo: match unlatch // Run everything through the checks, catch the ProxyCheckFailedException, and reply with the error message. try { _proxy.ShouldProxy(channel, msg, context); _matcher.TryMatch(context, autoproxySettings, members, out var match, msg.Content, msg.Attachments.Length > 0, context.AllowAutoproxy); await ctx.Reply("I'm not sure why this message was not proxied, sorry."); } catch (ProxyService.ProxyChecksFailedException e) { await ctx.Reply($"{e.Message}"); } }
private async Task <FullMessage> GetMessageToEdit(Context ctx, Duration timeout, bool isReproxy) { var editType = isReproxy ? "reproxy" : "edit"; var editTypeAction = isReproxy ? "reproxied" : "edited"; // todo: is it correct to get a connection here? await using var conn = await ctx.Database.Obtain(); FullMessage?msg = null; var(referencedMessage, _) = ctx.MatchMessage(false); if (referencedMessage != null) { msg = await ctx.Repository.GetMessage(conn, referencedMessage.Value); if (msg == null) { throw new PKError("This is not a message proxied by PluralKit."); } } if (msg == null) { if (ctx.Guild == null) { throw new PKSyntaxError($"You must use a message link to {editType} messages in DMs."); } var recent = await FindRecentMessage(ctx, timeout); if (recent == null) { throw new PKSyntaxError($"Could not find a recent message to {editType}."); } msg = await ctx.Repository.GetMessage(conn, recent.Mid); if (msg == null) { throw new PKSyntaxError($"Could not find a recent message to {editType}."); } } 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 = await _rest.GetChannelOrNull(msg.Message.Channel); if (channel == null) { throw new PKError(error); } if (!await ctx.CheckPermissionsInGuildChannel(channel, PermissionSet.ViewChannel | PermissionSet.SendMessages )) { throw new PKError(error); } } var msgTimestamp = DiscordUtils.SnowflakeToInstant(msg.Message.Mid); if (isReproxy && SystemClock.Instance.GetCurrentInstant() - msgTimestamp > timeout) { throw new PKError($"The message is too old to be {editTypeAction}."); } return(msg); }
private async Task <FullMessage> GetMessageToEdit(Context ctx) { // todo: is it correct to get a connection here? await using var conn = await ctx.Database.Obtain(); FullMessage?msg = null; var(referencedMessage, _) = ctx.MatchMessage(false); if (referencedMessage != null) { msg = await ctx.Repository.GetMessage(conn, referencedMessage.Value); if (msg == null) { throw new PKError("This is not a message proxied by PluralKit."); } } if (msg == null) { if (ctx.Guild == null) { throw new PKSyntaxError("You must use a message link to edit messages in DMs."); } var recent = await FindRecentMessage(ctx); if (recent == null) { throw new PKSyntaxError("Could not find a recent message to edit."); } msg = await ctx.Repository.GetMessage(conn, recent.Mid); if (msg == null) { throw new PKSyntaxError("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 = await _rest.GetChannelOrNull(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); }