parent
c691adf8c9
commit
25f96dd920
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Myriad.Gateway;
|
using Myriad.Gateway;
|
||||||
@ -17,11 +18,13 @@ namespace PluralKit.Bot
|
|||||||
private readonly IDatabase _db;
|
private readonly IDatabase _db;
|
||||||
private readonly ModelRepository _repo;
|
private readonly ModelRepository _repo;
|
||||||
private readonly ILogger _logger;
|
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;
|
_db = db;
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
|
_lastMessage = lastMessage;
|
||||||
_logger = logger.ForContext<MessageDeleted>();
|
_logger = logger.ForContext<MessageDeleted>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +39,8 @@ namespace PluralKit.Bot
|
|||||||
await _db.Execute(c => _repo.DeleteMessage(c, evt.Id));
|
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
|
// Fork a task to delete the message after a short delay
|
||||||
// to allow for lookups to happen for a little while after deletion
|
// to allow for lookups to happen for a little while after deletion
|
||||||
_ = Inner();
|
_ = Inner();
|
||||||
@ -54,6 +59,7 @@ namespace PluralKit.Bot
|
|||||||
await _db.Execute(c => _repo.DeleteMessagesBulk(c, evt.Ids));
|
await _db.Execute(c => _repo.DeleteMessagesBulk(c, evt.Ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastMessage.HandleMessageDeletion(evt.ChannelId, evt.Ids.ToList());
|
||||||
_ = Inner();
|
_ = Inner();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,11 @@ namespace PluralKit.Bot
|
|||||||
private readonly ProxyMatcher _matcher;
|
private readonly ProxyMatcher _matcher;
|
||||||
private readonly IMetrics _metrics;
|
private readonly IMetrics _metrics;
|
||||||
private readonly IDiscordCache _cache;
|
private readonly IDiscordCache _cache;
|
||||||
|
private readonly LastMessageCacheService _lastMessage;
|
||||||
private readonly DiscordApiClient _rest;
|
private readonly DiscordApiClient _rest;
|
||||||
|
|
||||||
public ProxyService(LogChannelService logChannel, ILogger logger,
|
public ProxyService(LogChannelService logChannel, ILogger logger, WebhookExecutorService webhookExecutor, IDatabase db,
|
||||||
WebhookExecutorService webhookExecutor, IDatabase db, ProxyMatcher matcher, IMetrics metrics, ModelRepository repo, IDiscordCache cache, DiscordApiClient rest)
|
ProxyMatcher matcher, IMetrics metrics, ModelRepository repo, IDiscordCache cache, DiscordApiClient rest, LastMessageCacheService lastMessage)
|
||||||
{
|
{
|
||||||
_logChannel = logChannel;
|
_logChannel = logChannel;
|
||||||
_webhookExecutor = webhookExecutor;
|
_webhookExecutor = webhookExecutor;
|
||||||
@ -45,6 +46,7 @@ namespace PluralKit.Bot
|
|||||||
_metrics = metrics;
|
_metrics = metrics;
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
_lastMessage = lastMessage;
|
||||||
_rest = rest;
|
_rest = rest;
|
||||||
_logger = logger.ForContext<ProxyService>();
|
_logger = logger.ForContext<ProxyService>();
|
||||||
}
|
}
|
||||||
@ -142,7 +144,7 @@ namespace PluralKit.Bot
|
|||||||
GuildId = trigger.GuildId!.Value,
|
GuildId = trigger.GuildId!.Value,
|
||||||
ChannelId = rootChannel.Id,
|
ChannelId = rootChannel.Id,
|
||||||
ThreadId = threadId,
|
ThreadId = threadId,
|
||||||
Name = match.Member.ProxyName(ctx),
|
Name = await FixSameName(messageChannel.Id, ctx, match.Member),
|
||||||
AvatarUrl = AvatarUtils.TryRewriteCdnUrl(match.Member.ProxyAvatar(ctx)),
|
AvatarUrl = AvatarUtils.TryRewriteCdnUrl(match.Member.ProxyAvatar(ctx)),
|
||||||
Content = content,
|
Content = content,
|
||||||
Attachments = trigger.Attachments,
|
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,
|
private async Task HandleProxyExecutedActions(Shard shard, IPKConnection conn, MessageContext ctx,
|
||||||
Message triggerMessage, Message proxyMessage,
|
Message triggerMessage, Message proxyMessage,
|
||||||
ProxyMatch match)
|
ProxyMatch match)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Myriad.Types;
|
using Myriad.Types;
|
||||||
|
|
||||||
@ -13,14 +14,58 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
public void AddMessage(Message msg)
|
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)
|
public CachedMessage? GetLastMessage(ulong channel)
|
||||||
{
|
{
|
||||||
return _cache.TryGetValue(channel, out var message) ? message : null;
|
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 record CachedMessage(ulong Id, ulong? ReferencedMessage);
|
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, ulong? Previous);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user