From bf8659b8cd4017ba910d59f0d4fbc23acb6329a3 Mon Sep 17 00:00:00 2001 From: olcxja Date: Sat, 22 Aug 2026 09:17:44 +0200 Subject: [PATCH] add more group setting messages & fix leaving empty groups and pfp upload deadlock --- LarpixServer/Account/Requests.cs | 17 +--- LarpixServer/Room/Groups.cs | 138 ++++++++++++++++++------------- 2 files changed, 85 insertions(+), 70 deletions(-) diff --git a/LarpixServer/Account/Requests.cs b/LarpixServer/Account/Requests.cs index 29e2e1b..0759149 100644 --- a/LarpixServer/Account/Requests.cs +++ b/LarpixServer/Account/Requests.cs @@ -1166,19 +1166,10 @@ public static async Task Auth(HttpContext context, Func next, IQueryCollec return; } - SemaphoreSlim userLock = Utils.GetUserLock(id); - await userLock.WaitAsync(); - try - { - await context.Response.WriteAsync( - Encryption.Encryption.EncryptString( - await Utils.UpdateUserPublicStorageEntryRaw(id, target, fileBytes) - , password)); - } - finally - { - userLock.Release(); - } + await context.Response.WriteAsync( + Encryption.Encryption.EncryptString( + await Utils.UpdateUserPublicStorageEntryRaw(id, target, fileBytes) + , password)); } public static async Task UploadDmAttachmentStaging(HttpContext context, Func next, IQueryCollection query) { diff --git a/LarpixServer/Room/Groups.cs b/LarpixServer/Room/Groups.cs index d200b5d..8f21706 100644 --- a/LarpixServer/Room/Groups.cs +++ b/LarpixServer/Room/Groups.cs @@ -167,7 +167,17 @@ public class Groups if (!string.IsNullOrEmpty(name)) { if (string.IsNullOrWhiteSpace(name)) return "error:invalid.name"; - await Fs.WriteFile($"{groupPath}/name", Encoding.UTF8.GetBytes(name)); + string currentName = ""; + if (Fs.Exists($"{groupPath}/name")) + { + currentName = Encoding.UTF8.GetString(await Fs.ReadFile($"{groupPath}/name")); + } + + if (currentName != name) + { + await Fs.WriteFile($"{groupPath}/name", Encoding.UTF8.GetBytes(name)); + await AddGroupInfoMessage(groupPath, groupId, userId, "larp.info.name", name); + } } if (!string.IsNullOrEmpty(historyVisible)) @@ -195,61 +205,7 @@ public class Groups if (currentState != newState) { await Fs.WriteFile($"{groupPath}/history_visible", Encoding.UTF8.GetBytes(newState ? "true" : "false")); - - string timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(); - - Message infoMsg = new(); - infoMsg.attachment = ""; - infoMsg.author = userId; - infoMsg.timestamp = timestamp; - infoMsg.type = "larp.info.history"; - infoMsg.content = newState ? "{blah(history.visible)}" : "{blah(history.hidden)}"; - infoMsg.key = ""; - - ulong lastMessageId = 0; - if (Fs.Exists($"{groupPath}/messages/last")) - { - lastMessageId = ulong.Parse(Encoding.UTF8.GetString(await Fs.ReadFile($"{groupPath}/messages/last"))); - } - ulong newMessageId = lastMessageId + 1; - - infoMsg.pervious = lastMessageId.ToString(); - - await Fs.WriteFile($"{groupPath}/messages/{newMessageId}", Encoding.UTF8.GetBytes(JsonSerializer.Serialize(infoMsg, AppJsonSerializerContext.Default.Message))); - await Fs.WriteFile($"{groupPath}/messages/last", Encoding.UTF8.GetBytes(newMessageId.ToString())); - - string[] members = Fs.ReadDirectory($"{groupPath}/members"); - foreach (string memberWD in members) - { - string memberStr = Path.GetFileName(memberWD); - bool isLocal = Account.Utils.IsUserLocal(memberStr, out string d); - string memberId = Account.Utils.GetValidIdOrZero(memberStr); - if (isLocal) - { - if (memberId == userId) - { - await UpdateUserGroup(memberId, groupId, "true", timestamp); - await Utils.Utils.SendWsMessage(memberId, $"group_message:{groupId}:read"); - } - else - { - _ = Task.Run(async () => - { - SemaphoreSlim userLock = Account.Utils.GetUserLock(memberId); - await userLock.WaitAsync(); - try - { - await UpdateUserGroup(memberId, groupId, "false", timestamp); - } - finally - { - userLock.Release(); - } - await Utils.Utils.SendWsMessage(memberId, $"group_message:{groupId}:unread"); - }); - } - } - } + await AddGroupInfoMessage(groupPath, groupId, userId, "larp.info.history", newState ? "{blah(history.visible)}" : "{blah(history.hidden)}"); } } } @@ -737,6 +693,11 @@ public class Groups long fileExistingSize = Fs.Exists(path) ? new System.IO.FileInfo(path).Length : 0; if (currentTotalSize - fileExistingSize + contentBytes.Length > Utils.Utils.PUBLIC_STORAGE_LIMIT) return "error:storage.limit.exceeded"; await Fs.WriteFile(path, contentBytes); + if (entry == "larp.profile.pfp") + { + string msgType = contentBytes.Length > 0 ? "larp.info.pfp" : "larp.info.pfp_removed"; + await AddGroupInfoMessage(dirPath.Replace("/storage/public", ""), groupId, userId, msgType, ""); + } } finally { @@ -829,9 +790,13 @@ public class Groups string id = parts[0]; string domain = parts.Length > 1 ? parts[1] : Utils.Utils.DOMAIN; string groupPath = $"{Utils.Utils.ROOMS_DIR}/groups/{domain}/{id}"; + string userGroupPath = $"{Utils.Utils.ACCOUNTS_DATA_DIR}/{userId}/groups/{id};{domain}"; if (!Fs.Exists(groupPath)) + { + if (Fs.Exists(userGroupPath)) Fs.DeleteFile(userGroupPath); return "error:group.not.found"; + } string memberPath = $"{groupPath}/members/{userId};{Utils.Utils.DOMAIN}"; @@ -840,13 +805,15 @@ public class Groups try { if (!Fs.Exists(memberPath)) + { + if (Fs.Exists(userGroupPath)) Fs.DeleteFile(userGroupPath); return "error:not.a.member"; + } // Remove from members Fs.DeleteFile(memberPath); // Remove group from user's groups - string userGroupPath = $"{Utils.Utils.ACCOUNTS_DATA_DIR}/{userId}/groups/{id};{domain}"; if (Fs.Exists(userGroupPath)) { Fs.DeleteFile(userGroupPath); @@ -1077,4 +1044,61 @@ public class Groups return "success"; } + private static async Task AddGroupInfoMessage(string groupPath, string groupId, string userId, string type, string content) + { + string timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(); + + Message infoMsg = new(); + infoMsg.attachment = ""; + infoMsg.author = userId; + infoMsg.timestamp = timestamp; + infoMsg.type = type; + infoMsg.content = content; + infoMsg.key = ""; + + ulong lastMessageId = 0; + if (Fs.Exists($"{groupPath}/messages/last")) + { + lastMessageId = ulong.Parse(Encoding.UTF8.GetString(await Fs.ReadFile($"{groupPath}/messages/last"))); + } + ulong newMessageId = lastMessageId + 1; + + infoMsg.pervious = lastMessageId.ToString(); + + await Fs.WriteFile($"{groupPath}/messages/{newMessageId}", Encoding.UTF8.GetBytes(JsonSerializer.Serialize(infoMsg, AppJsonSerializerContext.Default.Message))); + await Fs.WriteFile($"{groupPath}/messages/last", Encoding.UTF8.GetBytes(newMessageId.ToString())); + + string[] members = Fs.ReadDirectory($"{groupPath}/members"); + foreach (string memberWD in members) + { + string memberStr = Path.GetFileName(memberWD); + bool isLocal = Account.Utils.IsUserLocal(memberStr, out string d); + string memberId = Account.Utils.GetValidIdOrZero(memberStr); + if (isLocal) + { + if (memberId == userId) + { + await UpdateUserGroup(memberId, groupId, "true", timestamp); + await Utils.Utils.SendWsMessage(memberId, $"group_message:{groupId}:read"); + } + else + { + _ = Task.Run(async () => + { + SemaphoreSlim userLock = Account.Utils.GetUserLock(memberId); + await userLock.WaitAsync(); + try + { + await UpdateUserGroup(memberId, groupId, "false", timestamp); + } + finally + { + userLock.Release(); + } + await Utils.Utils.SendWsMessage(memberId, $"group_message:{groupId}:unread"); + }); + } + } + } + } }