add more group setting messages & fix leaving empty groups and pfp upload deadlock
All checks were successful
Server Build / publish (push) Successful in 29s
Voice Build / publish (push) Successful in 24s

This commit is contained in:
olcxja 2026-08-22 09:17:44 +02:00
commit bf8659b8cd
2 changed files with 85 additions and 70 deletions

View file

@ -1166,19 +1166,10 @@ public static async Task Auth(HttpContext context, Func<Task> 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<Task> next, IQueryCollection query)
{

View file

@ -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");
});
}
}
}
}
}