feat:增加单聊消息模块
This commit is contained in:
@@ -13,13 +13,13 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace SweetChatService.Handlers
|
||||
{
|
||||
internal class WebSocketMessageHandler(ILogger<WebSocketMessageHandler> logger,
|
||||
WebSocketSessionManager sessionManager,
|
||||
UserService userService)
|
||||
internal class WsMsgHandler(ILogger<WsMsgHandler> logger,
|
||||
WsSessionManager sessionManager,
|
||||
PrivateChatService privateChatService)
|
||||
{
|
||||
private readonly ILogger<WebSocketMessageHandler> _logger = logger;
|
||||
private readonly WebSocketSessionManager _sessionManager = sessionManager;
|
||||
private readonly UserService _userService = userService;
|
||||
private readonly ILogger<WsMsgHandler> _logger = logger;
|
||||
private readonly WsSessionManager _sessionManager = sessionManager;
|
||||
private readonly PrivateChatService _privateChatService = privateChatService;
|
||||
|
||||
public async ValueTask HandleAsync(WebSocketSession session, WebSocketPackage package)
|
||||
{
|
||||
@@ -55,20 +55,17 @@ namespace SweetChatService.Handlers
|
||||
{
|
||||
switch (msg.Type)
|
||||
{
|
||||
case ImMessageType.CHAT:
|
||||
if (_sessionManager.TryGet(msg.To, out var toSession))
|
||||
{
|
||||
await toSession.SendAsync(msg.Content);
|
||||
}
|
||||
case ImMessageType.CHAT_PRIVATE:
|
||||
await _privateChatService.HandleAsync(msg);
|
||||
break;
|
||||
|
||||
case ImMessageType.ONLINE:
|
||||
_sessionManager.Add(msg.From, session);
|
||||
await session.SendAsync("ok");
|
||||
await session.SendAsync(ImMessage.SystemMessage(msg.From, "OK").ToJson());
|
||||
break;
|
||||
|
||||
case ImMessageType.HEARTBEAT:
|
||||
await session.SendAsync("ok");
|
||||
await session.SendAsync(ImMessage.SystemMessage(msg.From, "OK").ToJson());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
||||
|
||||
namespace SweetChatService.Handlers
|
||||
{
|
||||
internal class WebSocketSessionManager
|
||||
internal class WsSessionManager
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, WebSocketSession> _sessions = new();
|
||||
|
||||
@@ -17,6 +17,19 @@ namespace SweetChatService.Handlers
|
||||
_sessions.TryRemove(userId, out _);
|
||||
}
|
||||
|
||||
public void RemoveBySession(string sessionId)
|
||||
{
|
||||
var keys = _sessions
|
||||
.Where(x => ReferenceEquals(x.Value.SessionID, sessionId))
|
||||
.Select(x => x.Key)
|
||||
.ToList();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
_sessions.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGet(string userId, out WebSocketSession? session)
|
||||
{
|
||||
return _sessions.TryGetValue(userId, out session);
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SweetChatService.Models
|
||||
{
|
||||
@@ -15,5 +16,28 @@ namespace SweetChatService.Models
|
||||
|
||||
[JsonPropertyName("content")]
|
||||
public string Content { get; set; } = default!;
|
||||
|
||||
public static ImMessage SystemMessage(string to, string content)
|
||||
{
|
||||
return new ImMessage
|
||||
{
|
||||
Type = ImMessageType.SYSTEM,
|
||||
From = "SYSTEM",
|
||||
To = to,
|
||||
Content = content
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为 JSON 字符串
|
||||
/// </summary>
|
||||
public string ToJson()
|
||||
{
|
||||
return JsonSerializer.Serialize(this, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace SweetChatService.Models
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
internal enum ImMessageType
|
||||
{
|
||||
CHAT,
|
||||
CHAT_PRIVATE,
|
||||
CHAT_GROUP,
|
||||
ONLINE,
|
||||
HEARTBEAT,
|
||||
SYSTEM,
|
||||
|
||||
@@ -12,8 +12,10 @@ var host = Host.CreateDefaultBuilder(args)
|
||||
})
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
services.AddSingleton<WebSocketMessageHandler>();
|
||||
services.AddSingleton<WebSocketSessionManager>();
|
||||
services.AddSingleton<WsMsgHandler>();
|
||||
services.AddSingleton<WsSessionManager>();
|
||||
|
||||
services.AddSingleton<PrivateChatService>();
|
||||
|
||||
services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"]));
|
||||
services.AddSingleton<UserService>();
|
||||
@@ -22,18 +24,20 @@ var host = Host.CreateDefaultBuilder(args)
|
||||
.AddWebSocketServer(builder =>
|
||||
{
|
||||
builder
|
||||
//.UseSessionHandler(async (session) =>
|
||||
//{
|
||||
// Console.WriteLine($"Client connected: {session.SessionID}");
|
||||
//},
|
||||
//async (session, error) =>
|
||||
//{
|
||||
// Console.WriteLine($"Client disconnected: {session.SessionID}");
|
||||
//})
|
||||
.UseSessionHandler(async (session) =>
|
||||
{
|
||||
|
||||
},
|
||||
async (session, error) =>
|
||||
{
|
||||
using var scope = session.Server.ServiceProvider.CreateScope();
|
||||
var manager = scope.ServiceProvider.GetRequiredService<WsSessionManager>();
|
||||
manager.RemoveBySession(session.SessionID);
|
||||
})
|
||||
.UseWebSocketMessageHandler(async (session, package) =>
|
||||
{
|
||||
using var scope = session.Server.ServiceProvider.CreateScope();
|
||||
var handler = scope.ServiceProvider.GetRequiredService<WebSocketMessageHandler>();
|
||||
var handler = scope.ServiceProvider.GetRequiredService<WsMsgHandler>();
|
||||
|
||||
await handler.HandleAsync(session, package);
|
||||
})
|
||||
|
||||
26
SweetChatService/Services/PrivateChatService.cs
Normal file
26
SweetChatService/Services/PrivateChatService.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using SweetChatService.Handlers;
|
||||
using SweetChatService.Models;
|
||||
|
||||
namespace SweetChatService.Services
|
||||
{
|
||||
internal class PrivateChatService(WsSessionManager wsSessionManager)
|
||||
{
|
||||
private readonly WsSessionManager _wsSessionManager = wsSessionManager;
|
||||
|
||||
public async Task HandleAsync(ImMessage msg)
|
||||
{
|
||||
// 推送给对方
|
||||
if (_wsSessionManager.TryGet(msg.To, out var toSession))
|
||||
{
|
||||
await toSession.SendAsync(msg.ToJson());
|
||||
}
|
||||
|
||||
|
||||
// 推送给自己
|
||||
if (_wsSessionManager.TryGet(msg.From, out var fromSession))
|
||||
{
|
||||
await fromSession.SendAsync(msg.ToJson());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=123456;Charset=utf8mb4;"
|
||||
"Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=estun@medical;Charset=utf8mb4;"
|
||||
},
|
||||
"serverOptions": {
|
||||
"WebSocketServer": {
|
||||
|
||||
Reference in New Issue
Block a user