1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 02:32:59 +08:00

Fix handling of local echo deduplication

This commit is contained in:
Dan Balasescu 2022-11-04 16:42:59 +09:00
parent 4f8e912f06
commit 58396d49dc
6 changed files with 51 additions and 23 deletions

View File

@ -28,6 +28,7 @@ namespace osu.Game.Online.API.Requests
req.AddParameter(@"target_id", user.Id.ToString());
req.AddParameter(@"message", message.Content);
req.AddParameter(@"is_action", message.IsAction.ToString().ToLowerInvariant());
req.AddParameter(@"uuid", message.Uuid);
return req;
}

View File

@ -25,6 +25,7 @@ namespace osu.Game.Online.API.Requests
req.Method = HttpMethod.Post;
req.AddParameter(@"is_action", Message.IsAction.ToString().ToLowerInvariant());
req.AddParameter(@"message", Message.Content);
req.AddParameter(@"uuid", Message.Uuid);
return req;
}

View File

@ -134,6 +134,14 @@ namespace osu.Game.Online.Chat
/// <param name="messages"></param>
public void AddNewMessages(params Message[] messages)
{
foreach (var m in messages)
{
LocalEchoMessage localEcho = pendingMessages.FirstOrDefault(local => local.Uuid == m.Uuid);
if (localEcho != null)
ReplaceMessage(localEcho, m);
}
messages = messages.Except(Messages).ToArray();
if (messages.Length == 0) return;

View File

@ -85,8 +85,21 @@ namespace osu.Game.Online.Chat
[BackgroundDependencyLoader]
private void load()
{
connector.ChannelJoined += ch => Schedule(() => joinChannel(ch));
connector.ChannelJoined += ch => Schedule(() =>
{
var localChannel = getChannel(ch);
if (localChannel != ch)
{
localChannel.Joined.Value = true;
localChannel.Id = ch.Id;
}
joinChannel(localChannel);
});
connector.NewMessages += msgs => Schedule(() => addMessages(msgs));
connector.PresenceReceived += () => Schedule(() =>
{
if (!channelsInitialised)
@ -189,7 +202,8 @@ namespace osu.Game.Online.Chat
Timestamp = DateTimeOffset.Now,
ChannelId = target.Id,
IsAction = isAction,
Content = text
Content = text,
Uuid = Guid.NewGuid().ToString()
};
target.AddLocalEcho(message);
@ -199,13 +213,7 @@ namespace osu.Game.Online.Chat
{
var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message);
createNewPrivateMessageRequest.Success += createRes =>
{
target.Id = createRes.ChannelID;
target.ReplaceMessage(message, createRes.Message);
dequeueAndRun();
};
createNewPrivateMessageRequest.Success += _ => dequeueAndRun();
createNewPrivateMessageRequest.Failure += exception =>
{
handlePostException(exception);
@ -219,12 +227,7 @@ namespace osu.Game.Online.Chat
var req = new PostMessageRequest(message);
req.Success += m =>
{
target.ReplaceMessage(message, m);
dequeueAndRun();
};
req.Success += m => dequeueAndRun();
req.Failure += exception =>
{
handlePostException(exception);
@ -403,7 +406,20 @@ namespace osu.Game.Online.Chat
{
Channel found = null;
bool lookupCondition(Channel ch) => lookup.Id > 0 ? ch.Id == lookup.Id : lookup.Name == ch.Name;
bool lookupCondition(Channel ch)
{
// If both channels have an id, use that.
if (lookup.Id > 0 && ch.Id > 0)
return ch.Id == lookup.Id;
// In the case that the local echo is received in a new channel (i.e. one that does not yet have an ID),
// then we need to check for any existing channel with the message containing the same message matched by UUID.
if (lookup.Messages.Count > 0 && ch.Messages.Any(m => m.Uuid == lookup.Messages.Last().Uuid))
return true;
// As a last resort, fallback to matching by name.
return lookup.Name == ch.Name;
}
var available = AvailableChannels.FirstOrDefault(lookupCondition);
if (available != null)

View File

@ -37,6 +37,12 @@ namespace osu.Game.Online.Chat
set => Sender = new APIUser { Id = value };
}
/// <summary>
/// A unique identifier for this message. Sent to and from osu!web to use for deduplication.
/// </summary>
[JsonProperty(@"uuid")]
public string Uuid { get; set; } = string.Empty;
[JsonConstructor]
public Message()
{

View File

@ -2,9 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
@ -126,12 +124,10 @@ namespace osu.Game.Online.Notifications.WebSocket
NewChatMessageData? messageData = JsonConvert.DeserializeObject<NewChatMessageData>(message.Data.ToString());
Debug.Assert(messageData != null);
List<Message> messages = messageData.Messages.Where(m => m.Sender.OnlineID != api.LocalUser.Value.OnlineID).ToList();
foreach (var msg in messageData.Messages)
HandleJoinedChannel(new Channel(msg.Sender) { Id = msg.ChannelId, Messages = { msg } });
foreach (var msg in messages)
HandleJoinedChannel(new Channel(msg.Sender) { Id = msg.ChannelId });
HandleMessages(messages);
HandleMessages(messageData.Messages);
break;
}