144 lines
4.7 KiB
C#
144 lines
4.7 KiB
C#
|
using System;
|
||
|
using System.Collections.Concurrent;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Collections.Immutable;
|
||
|
using System.Linq;
|
||
|
using BITKit;
|
||
|
using Cysharp.Threading.Tasks;
|
||
|
|
||
|
namespace Net.BITKit.Chat
|
||
|
{
|
||
|
public interface IChatService
|
||
|
{
|
||
|
UniTask SendMessage(ChatMessage message);
|
||
|
UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId);
|
||
|
UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId1, string userId2);
|
||
|
UniTask<IReadOnlyList<ChatMessage>> GetChatList(string userId);
|
||
|
public event Action<ChatMessage> OnMessageReceived;
|
||
|
}
|
||
|
|
||
|
public interface IChatVoiceService
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public class ChatService : IChatService
|
||
|
{
|
||
|
private readonly IDictionary<int,ChatMessage> _messages;
|
||
|
|
||
|
public ChatService(IDictionary<int, ChatMessage> messages)
|
||
|
{
|
||
|
_messages = messages;
|
||
|
|
||
|
if (_messages.Count is 0)
|
||
|
{
|
||
|
foreach (var chatMessage in ChatMockDataGenerator.GenerateMockMessages())
|
||
|
{
|
||
|
_messages.Add(chatMessage.Id,chatMessage);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public UniTask SendMessage(ChatMessage message)
|
||
|
{
|
||
|
if (_messages.ContainsKey(message.Id))
|
||
|
{
|
||
|
message.Id = Guid.NewGuid().GetHashCode();
|
||
|
}
|
||
|
_messages.Add(message.Id,message);
|
||
|
|
||
|
OnMessageReceived?.Invoke(message);
|
||
|
|
||
|
return UniTask.CompletedTask;
|
||
|
}
|
||
|
|
||
|
public UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId)
|
||
|
{
|
||
|
var list = new List<ChatMessage>();
|
||
|
|
||
|
list.AddRange(_messages.Values.Where(x=>x.FromUserId==userId));
|
||
|
|
||
|
list.Sort((a, b) => a.Timestamp.CompareTo(b.Timestamp));
|
||
|
|
||
|
return UniTask.FromResult<IReadOnlyList<ChatMessage>>(list);
|
||
|
}
|
||
|
|
||
|
public UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId1, string userId2)
|
||
|
{
|
||
|
var list = new List<ChatMessage>();
|
||
|
|
||
|
list.AddRange(_messages.Values.Where(x=>(x.FromUserId==userId1&&x.ToUserId==userId2) || (x.FromUserId==userId2&&x.ToUserId==userId1)));
|
||
|
|
||
|
list.Sort((a, b) => a.Timestamp.CompareTo(b.Timestamp));
|
||
|
|
||
|
return UniTask.FromResult<IReadOnlyList<ChatMessage>>(list);
|
||
|
}
|
||
|
|
||
|
public UniTask<IReadOnlyList<ChatMessage>> GetChatList(string userId)
|
||
|
{
|
||
|
var result = new List<ChatMessage>();
|
||
|
|
||
|
foreach (var chatMessage in _messages.Values)
|
||
|
{
|
||
|
if (chatMessage.FromUserId == userId || chatMessage.ToUserId == userId)
|
||
|
{
|
||
|
result.Add(chatMessage);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if NET5_0_OR_GREATER
|
||
|
result = result.OrderByDescending(m => m.Timestamp).DistinctBy(x=>new
|
||
|
{
|
||
|
x.FromUserId,
|
||
|
x.ToUserId
|
||
|
}).ToList();
|
||
|
#else
|
||
|
result = result
|
||
|
.OrderByDescending(m => m.Timestamp)
|
||
|
.GroupBy(x => new { x.FromUserId, x.ToUserId }) // 按这两个字段分组
|
||
|
.Select(g => g.First()) // 每组取最新的一条
|
||
|
.ToList();
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return UniTask.FromResult<IReadOnlyList<ChatMessage>>(result);
|
||
|
}
|
||
|
|
||
|
public event Action<ChatMessage> OnMessageReceived;
|
||
|
}
|
||
|
|
||
|
public static class ChatMockDataGenerator
|
||
|
{
|
||
|
private static int _count;
|
||
|
public static List<ChatMessage> GenerateMockMessages(int countPerUser = 10)
|
||
|
{
|
||
|
var systemUserId = Environment.UserName;
|
||
|
var otherUsers = new[] { "bob", "alice", "lucy", "john", "eva" };
|
||
|
var messages = new List<ChatMessage>();
|
||
|
var rnd = new Random();
|
||
|
|
||
|
foreach (var otherUser in otherUsers)
|
||
|
{
|
||
|
for (int i = 0; i < countPerUser; i++)
|
||
|
{
|
||
|
// 随机决定谁说话
|
||
|
bool fromSystem = rnd.NextDouble() < 0.5;
|
||
|
|
||
|
messages.Add(new ChatMessage
|
||
|
{
|
||
|
Id = _count++,
|
||
|
FromUserId = fromSystem ? systemUserId : otherUser,
|
||
|
ToUserId = fromSystem ? otherUser : systemUserId,
|
||
|
Content = fromSystem
|
||
|
? $"Hi {otherUser}, message {i}"
|
||
|
: $"Hey {systemUserId}, reply {i}",
|
||
|
Timestamp = DateTime.Now.AddMinutes(-rnd.Next(0, 60 * 24 * 3)) // 过去3天内
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return messages.OrderBy(m => m.Timestamp).ToList();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|