feat: rewrite database schema for localized autoproxy

This commit is contained in:
spiral
2022-03-21 23:43:33 -04:00
parent ca108813b7
commit 982812333b
16 changed files with 245 additions and 188 deletions

View File

@@ -18,12 +18,12 @@ public class ProxyMatcher
_clock = clock;
}
public bool TryMatch(MessageContext ctx, IReadOnlyCollection<ProxyMember> members, out ProxyMatch match,
public bool TryMatch(MessageContext ctx, AutoproxySettings settings, IReadOnlyCollection<ProxyMember> members, out ProxyMatch match,
string messageContent,
bool hasAttachments, bool allowAutoproxy)
{
if (TryMatchTags(members, messageContent, hasAttachments, out match)) return true;
if (allowAutoproxy && TryMatchAutoproxy(ctx, members, messageContent, out match)) return true;
if (allowAutoproxy && TryMatchAutoproxy(ctx, settings, members, messageContent, out match)) return true;
return false;
}
@@ -37,7 +37,7 @@ public class ProxyMatcher
return hasAttachments || match.Content.Trim().Length > 0;
}
private bool TryMatchAutoproxy(MessageContext ctx, IReadOnlyCollection<ProxyMember> members,
private bool TryMatchAutoproxy(MessageContext ctx, AutoproxySettings settings, IReadOnlyCollection<ProxyMember> members,
string messageContent,
out ProxyMatch match)
{
@@ -49,41 +49,41 @@ public class ProxyMatcher
"This message matches none of your proxy tags, and it was not autoproxied because it starts with a backslash (`\\`).");
// Find the member we should autoproxy (null if none)
var member = ctx.AutoproxyMode switch
var member = settings.AutoproxyMode switch
{
AutoproxyMode.Member when ctx.AutoproxyMember != null =>
members.FirstOrDefault(m => m.Id == ctx.AutoproxyMember),
AutoproxyMode.Member when settings.AutoproxyMember != null =>
members.FirstOrDefault(m => m.Id == settings.AutoproxyMember),
AutoproxyMode.Front when ctx.LastSwitchMembers.Length > 0 =>
members.FirstOrDefault(m => m.Id == ctx.LastSwitchMembers[0]),
AutoproxyMode.Latch when ctx.LastMessageMember != null =>
members.FirstOrDefault(m => m.Id == ctx.LastMessageMember.Value),
AutoproxyMode.Latch when settings.AutoproxyMember != null =>
members.FirstOrDefault(m => m.Id == settings.AutoproxyMember.Value),
_ => null
};
// Throw an error if the member is null, message varies depending on autoproxy mode
if (member == null)
{
if (ctx.AutoproxyMode == AutoproxyMode.Front)
if (settings.AutoproxyMode == AutoproxyMode.Front)
throw new ProxyService.ProxyChecksFailedException(
"You are using autoproxy front, but no members are currently registered as fronting. Please use `pk;switch <member>` to log a new switch.");
if (ctx.AutoproxyMode == AutoproxyMode.Member)
if (settings.AutoproxyMode == AutoproxyMode.Member)
throw new ProxyService.ProxyChecksFailedException(
"You are using member-specific autoproxy with an invalid member. Was this member deleted?");
if (ctx.AutoproxyMode == AutoproxyMode.Latch)
if (settings.AutoproxyMode == AutoproxyMode.Latch)
throw new ProxyService.ProxyChecksFailedException(
"You are using autoproxy latch, but have not sent any messages yet in this server. Please send a message using proxy tags first.");
throw new ProxyService.ProxyChecksFailedException(
"This message matches none of your proxy tags and autoproxy is not enabled.");
}
if (ctx.AutoproxyMode != AutoproxyMode.Member && !member.AllowAutoproxy)
if (settings.AutoproxyMode != AutoproxyMode.Member && !member.AllowAutoproxy)
throw new ProxyService.ProxyChecksFailedException(
"This member has autoproxy disabled. To enable it, use `pk;m <member> autoproxy on`.");
// Moved the IsLatchExpired() check to here, so that an expired latch and a latch without any previous messages throw different errors
if (ctx.AutoproxyMode == AutoproxyMode.Latch && IsLatchExpired(ctx))
if (settings.AutoproxyMode == AutoproxyMode.Latch && IsLatchExpired(ctx, settings))
throw new ProxyService.ProxyChecksFailedException(
"Latch-mode autoproxy has timed out. Please send a new message using proxy tags.");
@@ -99,16 +99,14 @@ public class ProxyMatcher
return true;
}
private bool IsLatchExpired(MessageContext ctx)
private bool IsLatchExpired(MessageContext ctx, AutoproxySettings settings)
{
if (ctx.LastMessage == null) return true;
if (ctx.LatchTimeout == 0) return false;
var timeout = ctx.LatchTimeout.HasValue
? Duration.FromSeconds(ctx.LatchTimeout.Value)
: DefaultLatchExpiryTime;
var timestamp = DiscordUtils.SnowflakeToInstant(ctx.LastMessage.Value);
return _clock.GetCurrentInstant() - timestamp > timeout;
return _clock.GetCurrentInstant() - settings.LastLatchTimestamp > timeout;
}
}

View File

@@ -32,10 +32,11 @@ public class ProxyService
private readonly ModelRepository _repo;
private readonly DiscordApiClient _rest;
private readonly WebhookExecutorService _webhookExecutor;
private readonly NodaTime.IClock _clock;
public ProxyService(LogChannelService logChannel, ILogger logger, WebhookExecutorService webhookExecutor,
DispatchService dispatch, IDatabase db, ProxyMatcher matcher, IMetrics metrics, ModelRepository repo,
IDiscordCache cache, DiscordApiClient rest, LastMessageCacheService lastMessage)
NodaTime.IClock clock, IDiscordCache cache, DiscordApiClient rest, LastMessageCacheService lastMessage)
{
_logChannel = logChannel;
_webhookExecutor = webhookExecutor;
@@ -47,6 +48,7 @@ public class ProxyService
_cache = cache;
_lastMessage = lastMessage;
_rest = rest;
_clock = clock;
_logger = logger.ForContext<ProxyService>();
}
@@ -56,6 +58,17 @@ public class ProxyService
if (!ShouldProxy(channel, message, ctx))
return false;
var autoproxySettings = await _repo.GetAutoproxySettings(ctx.SystemId.Value, guild.Id, null);
if (autoproxySettings.AutoproxyMode == AutoproxyMode.Latch && IsUnlatch(message))
{
// "unlatch"
await _repo.UpdateAutoproxy(ctx.SystemId.Value, guild.Id, null, new() {
AutoproxyMember = null
});
return false;
}
var rootChannel = await _cache.GetRootChannel(message.ChannelId);
List<ProxyMember> members;
@@ -63,7 +76,7 @@ public class ProxyService
using (_metrics.Measure.Timer.Time(BotMetrics.ProxyMembersQueryTime))
members = (await _repo.GetProxyMembers(message.Author.Id, message.GuildId!.Value)).ToList();
if (!_matcher.TryMatch(ctx, members, out var match, message.Content, message.Attachments.Length > 0,
if (!_matcher.TryMatch(ctx, autoproxySettings, members, out var match, message.Content, message.Attachments.Length > 0,
allowAutoproxy)) return false;
// this is hopefully temporary, so not putting it into a separate method
@@ -84,7 +97,7 @@ public class ProxyService
var allowEmbeds = senderPermissions.HasFlag(PermissionSet.EmbedLinks);
// Everything's in order, we can execute the proxy!
await ExecuteProxy(message, ctx, match, allowEveryone, allowEmbeds);
await ExecuteProxy(message, ctx, autoproxySettings, match, allowEveryone, allowEmbeds);
return true;
}
@@ -129,7 +142,7 @@ public class ProxyService
return true;
}
private async Task ExecuteProxy(Message trigger, MessageContext ctx,
private async Task ExecuteProxy(Message trigger, MessageContext ctx, AutoproxySettings autoproxySettings,
ProxyMatch match, bool allowEveryone, bool allowEmbeds)
{
// Create reply embed
@@ -171,7 +184,7 @@ public class ProxyService
Stickers = trigger.StickerItems,
AllowEveryone = allowEveryone
});
await HandleProxyExecutedActions(ctx, trigger, proxyMessage, match);
await HandleProxyExecutedActions(ctx, autoproxySettings, trigger, proxyMessage, match);
}
private async Task<(string?, string?)> FetchReferencedMessageAuthorInfo(Message trigger, Message referenced)
@@ -290,7 +303,11 @@ public class ProxyService
private string FixSameNameInner(string name)
=> $"{name}\u17b5";
private async Task HandleProxyExecutedActions(MessageContext ctx, Message triggerMessage, Message proxyMessage, ProxyMatch match)
public static bool IsUnlatch(Message message)
=> message.Content.StartsWith(@"\\") || message.Content.StartsWith("\\\u200b\\");
private async Task HandleProxyExecutedActions(MessageContext ctx, AutoproxySettings autoproxySettings,
Message triggerMessage, Message proxyMessage, ProxyMatch match)
{
var sentMessage = new PKMessage
{
@@ -308,6 +325,14 @@ public class ProxyService
Task LogMessageToChannel() =>
_logChannel.LogMessage(ctx, sentMessage, triggerMessage, proxyMessage).AsTask();
Task SaveLatchAutoproxy() => autoproxySettings.AutoproxyMode == AutoproxyMode.Latch
? _repo.UpdateAutoproxy(ctx.SystemId.Value, triggerMessage.GuildId, null, new()
{
AutoproxyMember = match.Member.Id,
LastLatchTimestamp = _clock.GetCurrentInstant(),
})
: Task.CompletedTask;
Task DispatchWebhook() => _dispatch.Dispatch(ctx.SystemId.Value, sentMessage);
async Task DeleteProxyTriggerMessage()
@@ -333,6 +358,7 @@ public class ProxyService
DeleteProxyTriggerMessage(),
SaveMessageInDatabase(),
LogMessageToChannel(),
SaveLatchAutoproxy(),
DispatchWebhook()
);
}