fish-station/Content.Server/_Sunrise/CartridgeLoader/Cartridges/MessengerCartridgeSystem.PacketHandlers.cs
Vigers Ray 95d7d4d348
ыыыыы, месенжер макс, ихихяхя (#3789)
Co-authored-by: Daniel <77834935+Orvex07@users.noreply.github.com>
2026-01-26 22:44:54 +03:00

478 lines
18 KiB
C#

using System.Linq;
using Content.Server._Sunrise.Messenger;
using Content.Server.CartridgeLoader;
using Content.Server.PDA.Ringer;
using Content.Shared._Sunrise.CartridgeLoader.Cartridges;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared._Sunrise.Messenger;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.PDA.Ringer;
namespace Content.Server._Sunrise.CartridgeLoader.Cartridges;
/// <summary>
/// Часть системы картриджа мессенджера, отвечающая за обработку входящих пакетов
/// </summary>
public sealed partial class MessengerCartridgeSystem
{
private void OnPacketReceived(EntityUid uid, MessengerCartridgeComponent component, CartridgeDeviceNetPacketEvent args)
{
var packet = args.PacketEvent;
if (!packet.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command))
{
return;
}
var loaderUid = args.Loader;
if (loaderUid == EntityUid.Invalid)
{
Sawmill.Warning($"Packet received but LoaderUid is invalid");
return;
}
switch (command)
{
case MessengerCommands.CmdUserRegistered:
HandleUserRegistered(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdUsersList:
HandleUsersList(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdGroupsList:
HandleGroupsList(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdMessagesList:
HandleMessagesList(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdMessageReceived:
HandleMessageReceived(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdGroupCreated:
HandleGroupCreated(uid, component, packet, loaderUid);
break;
case MessengerCommands.CmdUserAddedToGroup:
HandleUserAddedToGroup(uid, component, packet, loaderUid);
break;
default:
Sawmill.Warning($"Unknown command received: {command}");
break;
}
}
private void HandleUserRegistered(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (!packet.Data.TryGetValue("user_id", out string? userId))
{
Sawmill.Warning($"UserRegistered packet missing user_id");
return;
}
Sawmill.Info($"User registered successfully: {userId}");
component.UserId = userId;
component.IsRegistered = true;
component.LastRegistrationAttempt = null;
if (TryComp<DeviceNetworkComponent>(loaderUid, out var deviceNetwork))
{
RequestUsers(uid, component, loaderUid, deviceNetwork);
RequestGroups(uid, component, loaderUid, deviceNetwork);
}
UpdateUiState(uid, loaderUid, component);
}
private void HandleUsersList(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent args, EntityUid loaderUid)
{
if (!args.Data.TryGetValue("users", out List<Dictionary<string, object>>? usersData))
return;
var users = new List<MessengerUser>();
foreach (var userData in usersData)
{
if (!userData.TryGetValue("user_id", out object? userIdObj) ||
!userData.TryGetValue("user_name", out object? userNameObj))
continue;
var userId = userIdObj?.ToString();
var userName = userNameObj?.ToString();
if (userId == null || userName == null)
continue;
userData.TryGetValue("job_title", out object? jobTitleObj);
userData.TryGetValue("department_id", out object? departmentIdObj);
var jobTitle = jobTitleObj?.ToString();
var departmentId = departmentIdObj?.ToString();
users.Add(new MessengerUser(userId, userName, jobTitle, departmentId));
}
component.Users = users;
UpdateUiState(uid, loaderUid, component);
}
private void HandleGroupsList(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (!packet.Data.TryGetValue("groups", out List<Dictionary<string, object>>? groupsData))
return;
Dictionary<string, int>? serverUnreadCounts = null;
if (packet.Data.TryGetValue("unread_counts", out object? unreadCountsObj))
{
if (unreadCountsObj is Dictionary<string, object> unreadCountsDict)
{
serverUnreadCounts = new Dictionary<string, int>();
foreach (var (chatId, countObj) in unreadCountsDict)
{
if (int.TryParse(countObj?.ToString(), out var count))
{
serverUnreadCounts[chatId] = count;
}
}
}
}
var groups = new List<MessengerGroup>();
foreach (var groupData in groupsData)
{
if (!groupData.TryGetValue("group_id", out object? groupIdObj) ||
!groupData.TryGetValue("group_name", out object? groupNameObj))
continue;
var groupId = groupIdObj?.ToString();
var groupName = groupNameObj?.ToString();
if (groupId == null || groupName == null)
continue;
List<string>? membersList = null;
if (groupData.TryGetValue("members", out object? membersObj))
{
if (membersObj is List<object> membersObjList)
{
membersList = membersObjList.Select(m => m?.ToString() ?? string.Empty).Where(m => !string.IsNullOrEmpty(m)).ToList();
}
else if (membersObj is List<string> membersStringList)
{
membersList = membersStringList;
}
else if (membersObj is IEnumerable<object> membersEnumerable)
{
membersList = membersEnumerable.Select(m => m?.ToString() ?? string.Empty).Where(m => !string.IsNullOrEmpty(m)).ToList();
}
}
groupData.TryGetValue("group_type", out object? groupTypeObj);
groupData.TryGetValue("auto_group_prototype_id", out object? autoGroupPrototypeIdObj);
groupData.TryGetValue("owner_id", out object? ownerIdObj);
var groupType = MessengerGroupType.UserCreated;
if (groupTypeObj != null && int.TryParse(groupTypeObj.ToString(), out var typeInt))
{
groupType = (MessengerGroupType)typeInt;
}
var autoGroupPrototypeId = autoGroupPrototypeIdObj?.ToString();
var ownerId = ownerIdObj?.ToString();
groups.Add(new MessengerGroup(groupId, groupName, new HashSet<string>(membersList ?? new List<string>()), groupType, autoGroupPrototypeId, ownerId));
}
component.Groups = groups;
if (serverUnreadCounts != null)
{
foreach (var (chatId, count) in serverUnreadCounts)
{
component.ServerUnreadCounts[chatId] = count;
}
}
UpdateUiState(uid, loaderUid, component);
}
private void HandleMessagesList(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (!packet.Data.TryGetValue("messages", out List<Dictionary<string, object>>? messagesData))
return;
var isStatusUpdate = packet.Data.TryGetValue("chat_id", out object? updateChatIdObj);
var updateChatId = updateChatIdObj?.ToString();
var chatId = isStatusUpdate ? updateChatId : component.LastRequestedChatId;
if (string.IsNullOrEmpty(chatId))
{
if (messagesData.Count > 0)
{
var firstMessage = messagesData[0];
firstMessage.TryGetValue("group_id", out object? groupIdObj);
firstMessage.TryGetValue("recipient_id", out object? recipientIdObj);
var groupId = groupIdObj?.ToString();
var recipientId = recipientIdObj?.ToString();
if (!string.IsNullOrEmpty(groupId))
{
chatId = groupId;
}
else if (!string.IsNullOrEmpty(recipientId) && !string.IsNullOrEmpty(component.UserId))
{
var ids = new[] { recipientId, component.UserId }.OrderBy(x => x).ToArray();
chatId = $"personal_{ids[0]}_{ids[1]}";
}
}
}
var messages = new List<MessengerMessage>();
foreach (var messageData in messagesData)
{
if (!messageData.TryGetValue("sender_id", out object? senderIdObj) ||
!messageData.TryGetValue("sender_name", out object? senderNameObj) ||
!messageData.TryGetValue("content", out object? contentObj) ||
!messageData.TryGetValue("timestamp", out object? timestampObj))
continue;
var senderId = senderIdObj?.ToString();
var senderName = senderNameObj?.ToString();
var content = contentObj?.ToString();
if (senderId == null || senderName == null || content == null)
continue;
if (!double.TryParse(timestampObj?.ToString(), out var timestampSeconds))
continue;
messageData.TryGetValue("group_id", out object? groupIdObj);
messageData.TryGetValue("recipient_id", out object? recipientIdObj);
messageData.TryGetValue("is_read", out object? isReadObj);
var groupId = groupIdObj?.ToString();
var recipientId = recipientIdObj?.ToString();
var isRead = false;
if (isReadObj != null && bool.TryParse(isReadObj.ToString(), out var isReadValue))
{
isRead = isReadValue;
}
var timestamp = TimeSpan.FromSeconds(timestampSeconds);
messages.Add(new MessengerMessage(senderId, senderName, content, timestamp, groupId, recipientId, isRead));
}
if (!string.IsNullOrEmpty(chatId) && messages.Count >= 0)
{
if (component.MessageHistory.TryGetValue(chatId, out var existingMessages))
{
var existingDict = new Dictionary<string, MessengerMessage>();
for (int i = 0; i < existingMessages.Count; i++)
{
var msg = existingMessages[i];
var key = $"{msg.SenderId}_{msg.Timestamp.TotalSeconds}_{msg.Content}_{i}";
if (existingDict.ContainsKey(key))
{
key = $"{msg.SenderId}_{msg.Timestamp.TotalSeconds}_{msg.Content.GetHashCode()}_{i}";
}
existingDict[key] = msg;
}
var hasStatusUpdate = false;
foreach (var newMessage in messages)
{
var matchingMessage = existingMessages.FirstOrDefault(m =>
m.SenderId == newMessage.SenderId &&
Math.Abs(m.Timestamp.TotalSeconds - newMessage.Timestamp.TotalSeconds) < 0.001 &&
m.Content == newMessage.Content);
if (matchingMessage != null)
{
if (matchingMessage.IsRead != newMessage.IsRead)
{
matchingMessage.IsRead = newMessage.IsRead;
hasStatusUpdate = true;
}
}
}
var newMessages = messages.Where(newMsg =>
{
return !existingMessages.Any(existingMsg =>
existingMsg.SenderId == newMsg.SenderId &&
Math.Abs(existingMsg.Timestamp.TotalSeconds - newMsg.Timestamp.TotalSeconds) < 0.001 &&
existingMsg.Content == newMsg.Content);
}).ToList();
if (newMessages.Count > 0)
{
existingMessages.AddRange(newMessages);
existingMessages = existingMessages.OrderBy(m => m.Timestamp)
.ThenBy(m => m.SenderId)
.ThenBy(m => m.Content)
.ToList();
}
component.MessageHistory[chatId] = existingMessages;
}
else
component.MessageHistory[chatId] = messages.OrderBy(m => m.Timestamp).ToList();
}
UpdateUiState(uid, loaderUid, component);
}
private void HandleMessageReceived(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (!packet.Data.TryGetValue("sender_id", out object? senderIdObj) ||
!packet.Data.TryGetValue("sender_name", out object? senderNameObj) ||
!packet.Data.TryGetValue("content", out object? contentObj) ||
!packet.Data.TryGetValue("timestamp", out object? timestampObj))
return;
var senderId = senderIdObj?.ToString();
var senderName = senderNameObj?.ToString();
var content = contentObj?.ToString();
if (senderId == null || senderName == null || content == null)
return;
if (!double.TryParse(timestampObj?.ToString(), out var timestampSeconds))
return;
packet.Data.TryGetValue("group_id", out object? groupIdObj);
packet.Data.TryGetValue("recipient_id", out object? recipientIdObj);
packet.Data.TryGetValue("is_read", out object? isReadObj);
var groupId = groupIdObj?.ToString();
var recipientId = recipientIdObj?.ToString();
var isRead = false;
if (isReadObj != null && bool.TryParse(isReadObj.ToString(), out var isReadValue))
{
isRead = isReadValue;
}
var timestamp = TimeSpan.FromSeconds(timestampSeconds);
var message = new MessengerMessage(senderId, senderName, content, timestamp, groupId, recipientId, isRead);
string chatId;
if (!string.IsNullOrEmpty(groupId))
{
chatId = groupId;
}
else if (!string.IsNullOrEmpty(senderId) && !string.IsNullOrEmpty(component.UserId))
{
string otherUserId;
if (component.UserId == senderId)
{
if (string.IsNullOrEmpty(recipientId))
{
otherUserId = senderId;
}
else
{
otherUserId = recipientId;
}
}
else
{
otherUserId = senderId;
}
var ids = new[] { component.UserId, otherUserId }.OrderBy(x => x).ToArray();
chatId = $"personal_{ids[0]}_{ids[1]}";
}
else
{
chatId = senderId;
}
if (!component.MessageHistory.TryGetValue(chatId, out var history))
{
history = new List<MessengerMessage>();
component.MessageHistory[chatId] = history;
}
var messageExists = history.Any(m =>
m.SenderId == message.SenderId &&
Math.Abs(m.Timestamp.TotalSeconds - message.Timestamp.TotalSeconds) < 0.001 &&
m.Content == message.Content);
if (!messageExists)
{
history.Add(message);
history = history.OrderBy(m => m.Timestamp)
.ThenBy(m => m.SenderId)
.ThenBy(m => m.Content)
.ToList();
component.MessageHistory[chatId] = history;
}
else
{
var existingMessage = history.FirstOrDefault(m =>
m.SenderId == message.SenderId &&
Math.Abs(m.Timestamp.TotalSeconds - message.Timestamp.TotalSeconds) < 0.001 &&
m.Content == message.Content);
if (existingMessage != null)
{
existingMessage.IsRead = message.IsRead;
}
}
var isGroupChat = chatId == "common" || chatId.StartsWith("dept_") || chatId.StartsWith("group_");
var isMuted = isGroupChat
? component.MutedGroupChats.Contains(chatId)
: component.MutedPersonalChats.Contains(chatId);
var isSender = component.UserId == senderId;
var isChatOpen = component.LastRequestedChatId == chatId;
if (!isSender && !isChatOpen && isGroupChat)
{
component.ServerUnreadCounts.TryGetValue(chatId, out var currentCount);
component.ServerUnreadCounts[chatId] = currentCount + 1;
}
if (!isMuted && !isSender && TryComp<RingerComponent>(loaderUid, out var ringer))
{
_ringer.RingerPlayRingtone(loaderUid);
}
UpdateUiState(uid, loaderUid, component);
if (TryComp<DeviceNetworkComponent>(loaderUid, out var deviceNetwork))
{
RequestUsers(uid, component, loaderUid, deviceNetwork);
RequestGroups(uid, component, loaderUid, deviceNetwork);
}
}
private void HandleGroupCreated(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (TryComp<DeviceNetworkComponent>(loaderUid, out var deviceNetwork))
RequestGroups(uid, component, loaderUid, deviceNetwork);
}
private void HandleUserAddedToGroup(EntityUid uid, MessengerCartridgeComponent component, DeviceNetworkPacketEvent packet, EntityUid loaderUid)
{
if (!packet.Data.TryGetValue("user_id", out object? addedUserIdObj) ||
!packet.Data.TryGetValue("group_id", out object? groupIdObj))
return;
var addedUserId = addedUserIdObj?.ToString();
var groupId = groupIdObj?.ToString();
if (addedUserId == component.UserId && !string.IsNullOrEmpty(groupId))
{
if (TryComp<RingerComponent>(loaderUid, out var ringer))
{
_ringer.RingerPlayRingtone(loaderUid);
}
}
if (TryComp<DeviceNetworkComponent>(loaderUid, out var deviceNetwork))
RequestGroups(uid, component, loaderUid, deviceNetwork);
}
}