Fix proxying in channels without message history + reduce proxy latency
This commit is contained in:
parent
1720a28af2
commit
4c17ee3d89
@ -95,6 +95,8 @@ namespace PluralKit.Bot
|
|||||||
throw new PKError("Could not find a recent message to edit.");
|
throw new PKError("Could not find a recent message to edit.");
|
||||||
|
|
||||||
msg = await _repo.GetMessage(conn, recent.Mid);
|
msg = await _repo.GetMessage(conn, recent.Mid);
|
||||||
|
if (msg == null)
|
||||||
|
throw new PKError("Could not find a recent message to edit.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
|
@ -53,7 +53,7 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
private bool IsDuplicateMessage(Message msg) =>
|
private bool IsDuplicateMessage(Message msg) =>
|
||||||
// We consider a message duplicate if it has the same ID as the previous message that hit the gateway
|
// We consider a message duplicate if it has the same ID as the previous message that hit the gateway
|
||||||
_lastMessageCache.GetLastMessage(msg.ChannelId)?.Id == msg.Id;
|
_lastMessageCache.GetLastMessage(msg.ChannelId)?.Current.Id == msg.Id;
|
||||||
|
|
||||||
public async Task Handle(Shard shard, MessageCreateEvent evt)
|
public async Task Handle(Shard shard, MessageCreateEvent evt)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ namespace PluralKit.Bot
|
|||||||
if (!DiscordUtils.IsValidGuildChannel(channel))
|
if (!DiscordUtils.IsValidGuildChannel(channel))
|
||||||
return;
|
return;
|
||||||
var guild = _cache.GetGuild(channel.GuildId!.Value);
|
var guild = _cache.GetGuild(channel.GuildId!.Value);
|
||||||
var lastMessage = _lastMessageCache.GetLastMessage(evt.ChannelId);
|
var lastMessage = _lastMessageCache.GetLastMessage(evt.ChannelId)?.Current;
|
||||||
|
|
||||||
// Only react to the last message in the channel
|
// Only react to the last message in the channel
|
||||||
if (lastMessage?.Id != evt.Id)
|
if (lastMessage?.Id != evt.Id)
|
||||||
|
@ -242,40 +242,32 @@ namespace PluralKit.Bot
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> FixSameName(ulong channel_id, MessageContext ctx, ProxyMember member)
|
private async Task<string> FixSameName(ulong channelId, MessageContext ctx, ProxyMember member)
|
||||||
{
|
{
|
||||||
var proxyName = member.ProxyName(ctx);
|
var proxyName = member.ProxyName(ctx);
|
||||||
|
|
||||||
Message? lastMessage = null;
|
var lastMessage = _lastMessage.GetLastMessage(channelId)?.Previous;
|
||||||
|
if (lastMessage == null)
|
||||||
var lastMessageId = _lastMessage.GetLastMessage(channel_id)?.Previous;
|
|
||||||
if (lastMessageId == null)
|
|
||||||
// cache is out of date or channel is empty.
|
// cache is out of date or channel is empty.
|
||||||
return proxyName;
|
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();
|
await using var conn = await _db.Obtain();
|
||||||
var message = await _repo.GetMessage(conn, lastMessage.Id);
|
var pkMessage = await _repo.GetMessage(conn, lastMessage.Id);
|
||||||
|
|
||||||
if (lastMessage.Author.Username == proxyName)
|
if (lastMessage.AuthorUsername == proxyName)
|
||||||
{
|
{
|
||||||
// last message wasn't proxied by us, but somehow has the same name
|
// 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!
|
// it's probably from a different webhook (Tupperbox?) but let's fix it anyway!
|
||||||
if (message == null)
|
if (pkMessage == null)
|
||||||
return FixSameNameInner(proxyName);
|
return FixSameNameInner(proxyName);
|
||||||
|
|
||||||
// last message was proxied by a different member
|
// last message was proxied by a different member
|
||||||
if (message.Member.Id != member.Id)
|
if (pkMessage.Member.Id != member.Id)
|
||||||
return FixSameNameInner(proxyName);
|
return FixSameNameInner(proxyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we fixed the name last message and it's the same member proxying, we want to fix it again
|
// 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)
|
if (lastMessage.AuthorUsername == FixSameNameInner(proxyName) && pkMessage?.Member.Id == member.Id)
|
||||||
return FixSameNameInner(proxyName);
|
return FixSameNameInner(proxyName);
|
||||||
|
|
||||||
// No issues found, current proxy name is fine.
|
// No issues found, current proxy name is fine.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#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;
|
||||||
|
|
||||||
@ -10,15 +9,19 @@ namespace PluralKit.Bot
|
|||||||
// TODO: Should this be moved to Myriad.Cache?
|
// TODO: Should this be moved to Myriad.Cache?
|
||||||
public class LastMessageCacheService
|
public class LastMessageCacheService
|
||||||
{
|
{
|
||||||
private readonly IDictionary<ulong, CachedMessage> _cache = new ConcurrentDictionary<ulong, CachedMessage>();
|
private readonly IDictionary<ulong, CacheEntry> _cache = new ConcurrentDictionary<ulong, CacheEntry>();
|
||||||
|
|
||||||
public void AddMessage(Message msg)
|
public void AddMessage(Message msg)
|
||||||
{
|
{
|
||||||
var previous = GetLastMessage(msg.ChannelId);
|
var previous = GetLastMessage(msg.ChannelId);
|
||||||
_cache[msg.ChannelId] = new CachedMessage(msg.Id, msg.ReferencedMessage.Value?.Id, previous?.Id);
|
var current = ToCachedMessage(msg);
|
||||||
|
_cache[msg.ChannelId] = new(current, previous?.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedMessage? GetLastMessage(ulong channel)
|
private CachedMessage ToCachedMessage(Message msg) =>
|
||||||
|
new(msg.Id, msg.ReferencedMessage.Value?.Id, msg.Author.Username);
|
||||||
|
|
||||||
|
public CacheEntry? GetLastMessage(ulong channel)
|
||||||
{
|
{
|
||||||
return _cache.TryGetValue(channel, out var message) ? message : null;
|
return _cache.TryGetValue(channel, out var message) ? message : null;
|
||||||
}
|
}
|
||||||
@ -29,13 +32,13 @@ namespace PluralKit.Bot
|
|||||||
if (storedMessage == null)
|
if (storedMessage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (message == storedMessage.Id)
|
if (message == storedMessage.Current.Id)
|
||||||
if (storedMessage.Previous != null)
|
if (storedMessage.Previous != null)
|
||||||
_cache[channel] = new CachedMessage(storedMessage.Previous.Value, null, null);
|
_cache[channel] = new(storedMessage.Previous, null);
|
||||||
else
|
else
|
||||||
_cache.Remove(channel);
|
_cache.Remove(channel);
|
||||||
else if (message == storedMessage.Previous)
|
else if (message == storedMessage.Previous?.Id)
|
||||||
_cache[channel] = new CachedMessage(storedMessage.Id, storedMessage.ReferencedMessage, null);
|
_cache[channel] = new(storedMessage.Current, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandleMessageDeletion(ulong channel, List<ulong> messages)
|
public void HandleMessageDeletion(ulong channel, List<ulong> messages)
|
||||||
@ -44,21 +47,21 @@ namespace PluralKit.Bot
|
|||||||
if (storedMessage == null)
|
if (storedMessage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(messages.Contains(storedMessage.Id) || (storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Value))))
|
if (!(messages.Contains(storedMessage.Current.Id) || storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Id)))
|
||||||
// none of the deleted messages are relevant to the cache
|
// none of the deleted messages are relevant to the cache
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ulong? newLastMessage = null;
|
ulong? newLastMessage = null;
|
||||||
|
|
||||||
if (messages.Contains(storedMessage.Id))
|
if (messages.Contains(storedMessage.Current.Id))
|
||||||
newLastMessage = storedMessage.Previous;
|
newLastMessage = storedMessage.Previous?.Id;
|
||||||
|
|
||||||
if (storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Value))
|
if (storedMessage.Previous != null && messages.Contains(storedMessage.Previous.Id))
|
||||||
if (newLastMessage == storedMessage.Previous)
|
if (newLastMessage == storedMessage.Previous?.Id)
|
||||||
newLastMessage = null;
|
newLastMessage = null;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_cache[channel] = new CachedMessage(storedMessage.Id, storedMessage.ReferencedMessage, null);
|
_cache[channel] = new(storedMessage.Current, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,5 +70,7 @@ namespace PluralKit.Bot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CachedMessage(ulong Id, ulong? ReferencedMessage, ulong? Previous);
|
public record CacheEntry(CachedMessage Current, CachedMessage? Previous);
|
||||||
|
|
||||||
|
public record CachedMessage(ulong Id, ulong? ReferencedMessage, string AuthorUsername);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace PluralKit.Core
|
|||||||
_logger.Debug("Stored message {@StoredMessage} in channel {Channel}", msg, msg.Channel);
|
_logger.Debug("Stored message {@StoredMessage} in channel {Channel}", msg, msg.Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<FullMessage> GetMessage(IPKConnection conn, ulong id)
|
public async Task<FullMessage?> GetMessage(IPKConnection conn, ulong id)
|
||||||
{
|
{
|
||||||
FullMessage Mapper(PKMessage msg, PKMember member, PKSystem system) =>
|
FullMessage Mapper(PKMessage msg, PKMember member, PKSystem system) =>
|
||||||
new FullMessage {Message = msg, System = system, Member = member};
|
new FullMessage {Message = msg, System = system, Member = member};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user