From 69ccfd34212e1642460089f09ce5ecb344255c32 Mon Sep 17 00:00:00 2001 From: olcxja Date: Wed, 27 May 2026 08:52:40 +0200 Subject: [PATCH] Add "user/dm/invite/revoke" and "user/dm/invite/decline" --- LarpixServer/Account/Requests.cs | 54 +++++++++++++---- LarpixServer/Federation/Receiver.cs | 31 ++++++++++ LarpixServer/Federation/Sender.cs | 10 ++++ LarpixServer/Program.cs | 3 + LarpixServer/Room/Requests.cs | 92 ++++++++++++++++++++++------- 5 files changed, 158 insertions(+), 32 deletions(-) diff --git a/LarpixServer/Account/Requests.cs b/LarpixServer/Account/Requests.cs index 3aeda86..23750e8 100644 --- a/LarpixServer/Account/Requests.cs +++ b/LarpixServer/Account/Requests.cs @@ -316,6 +316,29 @@ public class Requests } + public static async Task NameToId(HttpContext context, Func next, IQueryCollection query) + { + if (!query.TryGetValue("u", out var username)) + { + return; + } + + if (!Utils.IsUserLocal(username, out string domain)) //federation + { + username = username.ToString().Split(":")[0]; + string remoteId = await Federation.Sender.GetUserId(username, domain); + if (remoteId != "0" && !string.IsNullOrEmpty(remoteId)) + { + await context.Response.WriteAsync(remoteId + $":{domain}"); + } + return; + } + username = username.ToString().Split(":")[0]; + + await context.Response.WriteAsync(await Utils.IdFromName(username) + $":{DOMAIN}"); + return; + } + public static async Task IdToName(HttpContext context, Func next, IQueryCollection query) { if (!query.TryGetValue("id", out var id)) @@ -467,18 +490,16 @@ public class Requests public static async Task GetUserPublicKey(HttpContext context, Func next, IQueryCollection query, StreamReader bodyReader) { - if (!query.TryGetValue("u", out var username)) + if (!query.TryGetValue("id", out var idQuery)) { return; } - if (!Utils.IsUserLocal(username, out string domain)) //federation :( + if (!Utils.IsUserLocal(idQuery, out string domain)) //federation :( { return; } - username = username.ToString().Split(":")[0]; - - string id = await Utils.IdFromName(username); + string id = idQuery.ToString().Split(":")[0]; Universal2String keys = JsonSerializer.Deserialize( await Utils.GetUserKeys(id), @@ -490,21 +511,20 @@ public class Requests public static async Task GetUserPublicStorageEntry(HttpContext context, Func next, IQueryCollection query, StreamReader bodyReader) { - if (!query.TryGetValue("u", out var username)) + if (!query.TryGetValue("id", out var idQuery)) { return; } - if (!query.TryGetValue("entry", out var entry)) + if (!query.TryGetValue("e", out var entry)) { return; } - if (!Utils.IsUserLocal(username, out string domain)) //federation :( + + if (!Utils.IsUserLocal(idQuery, out string domain)) //federation :( { return; } - username = username.ToString().Split(":")[0]; - - string id = await Utils.IdFromName(username); + string id = idQuery.ToString().Split(":")[0]; byte[] entryByte = await Utils.GetUserPublicStorageEntry(id, entry); @@ -589,6 +609,18 @@ public class Requests await Room.Requests.DmInvite(id, serializedBody.string2) , password)); break; + case "user/dm/invite/revoke": + await context.Response.WriteAsync( + Encryption.Encryption.EncryptString( + await Room.Requests.DmInviteRevoke(id, serializedBody.string2) + , password)); + break; + case "user/dm/invite/decline": + await context.Response.WriteAsync( + Encryption.Encryption.EncryptString( + await Room.Requests.DmInviteDecline(id, serializedBody.string2) + , password)); + break; case "user/dm/create": await context.Response.WriteAsync( Encryption.Encryption.EncryptString( diff --git a/LarpixServer/Federation/Receiver.cs b/LarpixServer/Federation/Receiver.cs index b860ed2..eb1ad16 100644 --- a/LarpixServer/Federation/Receiver.cs +++ b/LarpixServer/Federation/Receiver.cs @@ -56,6 +56,37 @@ public class Receiver await context.Response.WriteAsync("success:user.invited"); + return; + case "dm/invite/revoke": + ids = serializedBody.string2.Split(','); //0=receiver, 1=sender + + userLock = Account.Utils.GetUserLock(ids[0]); + await userLock.WaitAsync(); + try + { + string inviteFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/recv/{ids[1]};{domain}"; + if (Fs.Exists(inviteFile)) + { + Fs.DeleteFile(inviteFile); + } + } + finally + { + userLock.Release(); + } + + await context.Response.WriteAsync("success:invite.revoked"); + return; + case "dm/invite/decline": + ids = serializedBody.string2.Split(','); //0=sender, 1=receiver + + string inviteSentFileDecline = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/sent/{ids[1]};{domain}"; + if (Fs.Exists(inviteSentFileDecline)) + { + Fs.DeleteFile(inviteSentFileDecline); + } + + await context.Response.WriteAsync("success:invite.declined"); return; case "dm/invite/hassent": ids = serializedBody.string2.Split(','); //0=sender, 1=receiver diff --git a/LarpixServer/Federation/Sender.cs b/LarpixServer/Federation/Sender.cs index ff432ad..bcdbdeb 100644 --- a/LarpixServer/Federation/Sender.cs +++ b/LarpixServer/Federation/Sender.cs @@ -49,4 +49,14 @@ public class Sender { return await FederationRequest("dm/invite/send", $"{receiverId},{senderId}", domain); } + + public static async Task DmInviteRevoke(string senderId, string domain, string receiverId) + { + return await FederationRequest("dm/invite/revoke", $"{receiverId},{senderId}", domain); + } + + public static async Task DmInviteDecline(string receiverId, string domain, string senderId) + { + return await FederationRequest("dm/invite/decline", $"{senderId},{receiverId}", domain); + } } \ No newline at end of file diff --git a/LarpixServer/Program.cs b/LarpixServer/Program.cs index d89b850..39586e0 100644 --- a/LarpixServer/Program.cs +++ b/LarpixServer/Program.cs @@ -165,6 +165,9 @@ public class Program case "/_larpix/correctedname": await Account.Requests.CorrectedName(context, next, query); return; + case "/_larpix/nametoid": + await Account.Requests.NameToId(context, next, query); + return; case "/_larpix/idtoname": await Account.Requests.IdToName(context, next, query); return; diff --git a/LarpixServer/Room/Requests.cs b/LarpixServer/Room/Requests.cs index a308a65..40eec66 100644 --- a/LarpixServer/Room/Requests.cs +++ b/LarpixServer/Room/Requests.cs @@ -10,20 +10,18 @@ namespace LarpixServer.Room; public class Requests { public static SemaphoreSlim createLock = new SemaphoreSlim(1, 1); - public static async Task DmInvite(string id, string username2) + public static async Task DmInvite(string id, string targetId) { - if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation + if (!Account.Utils.IsUserLocal(targetId, out string domain)) //federation { - - username2 = username2.Split(":")[0]; - string remoteId2 = await Federation.Sender.GetUserId(username2, domain); - await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{remoteId2};{domain}", Encoding.UTF8.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString())); - return await Federation.Sender.DmInvite(id, domain, remoteId2); + targetId = targetId.Split(":")[0]; + await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{targetId};{domain}", Encoding.UTF8.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString())); + return await Federation.Sender.DmInvite(id, domain, targetId); } - username2 = username2.Split(":")[0]; - string id2 = await Account.Utils.IdFromName(username2); - if (id2 == "0") + targetId = targetId.Split(":")[0]; + string id2 = targetId; + if (id2 == "0" || string.IsNullOrEmpty(id2)) { return "error:user.not.found"; } @@ -54,28 +52,80 @@ public class Requests return "success:user.invited"; } + + public static async Task DmInviteRevoke(string id, string targetId) + { + if (!Account.Utils.IsUserLocal(targetId, out string domain)) //federation + { + targetId = targetId.Split(":")[0]; + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{targetId};{domain}"); + return await Federation.Sender.DmInviteRevoke(id, domain, targetId); + } + targetId = targetId.Split(":")[0]; + string id2 = targetId; + if (id2 == "0" || string.IsNullOrEmpty(id2)) return "error:user.not.found"; + + SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2); + await userLock2.WaitAsync(); + try + { + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/recv/{id}"); + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{id2}"); + } + finally + { + userLock2.Release(); + } + + return "success:invite.revoked"; + } + + public static async Task DmInviteDecline(string id, string targetId) + { + if (!Account.Utils.IsUserLocal(targetId, out string domain)) //federation + { + targetId = targetId.Split(":")[0]; + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/recv/{targetId};{domain}"); + return await Federation.Sender.DmInviteDecline(id, domain, targetId); + } + targetId = targetId.Split(":")[0]; + string id2 = targetId; + if (id2 == "0" || string.IsNullOrEmpty(id2)) return "error:user.not.found"; + + SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2); + await userLock2.WaitAsync(); + try + { + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/recv/{id2}"); + Fs.DeleteFile(ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/sent/{id}"); + } + finally + { + userLock2.Release(); + } + + return "success:invite.declined"; + } public static async Task DmCreate(string id, string body) { await createLock.WaitAsync(); try { - Universal3String serializedBody = JsonSerializer.Deserialize( //1 is ID2 nameWD, 2 is creators dm key, 3 is key for ID2 + Universal3String serializedBody = JsonSerializer.Deserialize( //1 is targetId, 2 is creators dm key, 3 is key for ID2 body, AppJsonSerializerContext.Default.Universal3String ); - - string username2 = serializedBody.string1; - bool isUserLocal = Account.Utils.IsUserLocal(username2, out string domain); + + string targetId = serializedBody.string1; + bool isUserLocal = Account.Utils.IsUserLocal(targetId, out string domain); string id2; - username2 = username2.Split(":")[0]; - if (isUserLocal) + + targetId = targetId.Split(":")[0]; + id2 = targetId; + if (id2 == "0" || string.IsNullOrEmpty(id2)) { - id2 = await Account.Utils.IdFromName(username2); - } - else //get id from federation - { - id2 = await Federation.Sender.GetUserId(username2, domain); + return "error:user.not.found"; } if (isUserLocal)