parent
c691adf8c9
commit
25f96dd920
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Gateway;
|
||||
@ -17,11 +18,13 @@ namespace PluralKit.Bot
|
||||
private readonly IDatabase _db;
|
||||
private readonly ModelRepository _repo;
|
||||
private readonly ILogger _logger;
|
||||
private readonly LastMessageCacheService _lastMessage;
|
||||
|
||||
public MessageDeleted(ILogger logger, IDatabase db, ModelRepository repo)
|
||||
public MessageDeleted(ILogger logger, IDatabase db, ModelRepository repo, LastMessageCacheService lastMessage)
|
||||
{
|
||||
_db = db;
|
||||
_repo = repo;
|
||||
_lastMessage = lastMessage;
|
||||
_logger = logger.ForContext<MessageDeleted>();
|
||||
}
|
||||
|
||||
@ -36,6 +39,8 @@ namespace PluralKit.Bot
|
||||
await _db.Execute(c => _repo.DeleteMessage(c, evt.Id));
|
||||
}
|
||||
|
||||
_lastMessage.HandleMessageDeletion(evt.ChannelId, evt.Id);
|
||||
|
||||
// Fork a task to delete the message after a short delay
|
||||
// to allow for lookups to happen for a little while after deletion
|
||||
_ = Inner();
|
||||
@ -54,6 +59,7 @@ namespace PluralKit.Bot
|
||||
await _db.Execute(c => _repo.DeleteMessagesBulk(c, evt.Ids));
|
||||
}
|
||||
|
||||
_lastMessage.HandleMessageDeletion(evt.ChannelId, evt.Ids.ToList());
|
||||
_ = Inner();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@ -33,10 +33,11 @@ namespace PluralKit.Bot
|
||||
private readonly ProxyMatcher _matcher;
|
||||
private readonly IMetrics _metrics;
|
||||
private readonly IDiscordCache _cache;
|
||||
private readonly LastMessageCacheService _lastMessage;
|
||||
private readonly DiscordApiClient _rest;
|
||||
|
||||
public ProxyService(LogChannelService logChannel, ILogger logger,
|
||||
WebhookExecutorService webhookExecutor, IDatabase db, ProxyMatcher matcher, IMetrics metrics, ModelRepository repo, IDiscordCache cache, DiscordApiClient rest)
|
||||
public ProxyService(LogChannelService logChannel, ILogger logger, WebhookExecutorService webhookExecutor, IDatabase db,
|
||||
ProxyMatcher matcher, IMetrics metrics, ModelRepository repo, IDiscordCache cache, DiscordApiClient rest, LastMessageCacheService lastMessage)
|
||||
{
|
||||
_logChannel = logChannel;
|
||||
_webhookExecutor = webhookExecutor;
|
||||
@ -45,6 +46,7 @@ namespace PluralKit.Bot
|
||||
_metrics = metrics;
|
||||
_repo = repo;
|
||||
_cache = cache;
|
||||
_lastMessage = lastMessage;
|
||||
_rest = rest;
|
||||
_logger = logger.ForContext<ProxyService>();
|
||||
}
|
||||
@ -142,7 +144,7 @@ namespace PluralKit.Bot
|
||||
GuildId = trigger.GuildId!.Value,
|
||||
ChannelId = rootChannel.Id,
|
||||
ThreadId = threadId,
|
||||
Name = match.Member.ProxyName(ctx),
|
||||
Name = await FixSameName(messageChannel.Id, ctx, match.Member),
|
||||
AvatarUrl = AvatarUtils.TryRewriteCdnUrl(match.Member.ProxyAvatar(ctx)),
|
||||
Content = content,
|
||||
Attachments = trigger.Attachments,
|
||||
@ -230,6 +232,49 @@ namespace PluralKit.Bot
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<string> FixSameName(ulong channel_id, MessageContext ctx, ProxyMember member)
|
||||
{
|
||||
var proxyName = member.ProxyName(ctx);
|
||||
|
||||
Message? lastMessage = null;
|
||||
|
||||
var lastMessageId = _lastMessage.GetLastMessage(channel_id)?.Previous;
|
||||
if (lastMessageId == null)
|
||||
// cache is out of date or channel is empty.
|
||||
return proxyName;
|
||||
|
||||
lastMessage = await _rest.GetMessage(channel_id, lastMessageId.Value);
|
||||
|
||||
if (lastMessage == null)
|
||||
// we don't have enough information to figure out if we need to fix the name, so bail here.
|
||||
return proxyName;
|
||||
|
||||
await using var conn = await _db.Obtain();
|
||||
var message = await _repo.GetMessage(conn, lastMessage.Id);
|
||||
|
||||
if (lastMessage.Author.Username == proxyName)
|
||||
{
|
||||
// last message wasn't proxied by us, but somehow has the same name
|
||||
// it's probably from a different webhook (Tupperbox?) but let's fix it anyway!
|
||||
if (message == null)
|
||||
return FixSameNameInner(proxyName);
|
||||
|
||||
// last message was proxied by a different member
|
||||
if (message.Member.Id != member.Id)
|
||||
return FixSameNameInner(proxyName);
|
||||
}
|
||||
|
||||
// if we fixed the name last message and it's the same member proxying, we want to fix it again
|
||||
if (lastMessage.Author.Username == FixSameNameInner(proxyName) && message?.Member.Id == member.Id)
|
||||
return FixSameNameInner(proxyName);
|
||||
|
||||
// No issues found, current proxy name is fine.
|
||||
return proxyName;
|
||||
}
|
||||
|
||||
private string FixSameNameInner(string name)
|
||||
=> $"{name}\u17b5";
|
||||
|
||||
private async Task HandleProxyExecutedActions(Shard shard, IPKConnection conn, MessageContext ctx,
|
||||
Message triggerMessage, Message proxyMessage,
|
||||
ProxyMatch match)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Myriad.Types;
|
||||
|
||||
@ -13,14 +14,58 @@ namespace PluralKit.Bot
|
||||
|
||||
public void AddMessage(Message msg)
|
||||
{
|
||||
_cache[msg.ChannelId] = new CachedMessage(msg.Id, msg.ReferencedMessage.Value?.Id);
|
||||
var previous = GetLastMessage(msg.ChannelId);
|
||||
_cache[msg.ChannelId] = new CachedMessage(msg.Id, msg.ReferencedMessage.Value?.Id, previous?.Id);
|
||||
}
|
||||
|
||||
public CachedMessage? GetLastMessage(ulong channel)
|
||||
{
|
||||
return _cache.TryGetValue(channel, out var message) ? message : null;
|
||||
}
|
||||
|
||||
public void HandleMessageDeletion(ulong channel, ulong message)
|
||||
{
|
||||
var storedMessage = GetLastMessage(channel);
|
||||
if (storedMessage == null)
|
||||
return;
|
||||
|
||||
if (message == storedMessage.Id)
|
||||
if (storedMessage.Previous != null)
|
||||
_cache[channel] = new CachedMessage(storedMessage.Previous.Value, null, null);
|
||||
else
|
||||
_cache.Remove(channel);
|
||||
else if (message == storedMessage.Previous)
|
||||
_cache[channel] = new CachedMessage(storedMessage.Id, storedMessage.ReferencedMessage, null);
|
||||
}
|
||||
|
||||
public void HandleMessageDeletion(ulong channel, List<ulong> messages)
|
||||
{
|
||||
var storedMessage = GetLastMessage(channel);
|
||||
if (storedMessage == null)
|
||||
return;
|
||||
|
||||
if (!(messages.Contains(storedMessage.Id) || (storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Value))))
|
||||
// none of the deleted messages are relevant to the cache
|
||||
return;
|
||||
|
||||
ulong? newLastMessage = null;
|
||||
|
||||
if (messages.Contains(storedMessage.Id))
|
||||
newLastMessage = storedMessage.Previous;
|
||||
|
||||
if (storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Value))
|
||||
if (newLastMessage == storedMessage.Previous)
|
||||
newLastMessage = null;
|
||||
else
|
||||
{
|
||||
_cache[channel] = new CachedMessage(storedMessage.Id, storedMessage.ReferencedMessage, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newLastMessage == null)
|
||||
_cache.Remove(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public record CachedMessage(ulong Id, ulong? ReferencedMessage);
|
||||
public record CachedMessage(ulong Id, ulong? ReferencedMessage, ulong? Previous);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user