Add "user/dm/invite/revoke" and "user/dm/invite/decline"
All checks were successful
Server Build / publish (push) Successful in 30s
Voice Build / publish (push) Successful in 26s

This commit is contained in:
olcxja 2026-05-27 08:52:40 +02:00
commit 69ccfd3421
5 changed files with 158 additions and 32 deletions

View file

@ -316,6 +316,29 @@ public class Requests
} }
public static async Task NameToId(HttpContext context, Func<Task> 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<Task> next, IQueryCollection query) public static async Task IdToName(HttpContext context, Func<Task> next, IQueryCollection query)
{ {
if (!query.TryGetValue("id", out var id)) if (!query.TryGetValue("id", out var id))
@ -467,18 +490,16 @@ public class Requests
public static async Task GetUserPublicKey(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader) public static async Task GetUserPublicKey(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader)
{ {
if (!query.TryGetValue("u", out var username)) if (!query.TryGetValue("id", out var idQuery))
{ {
return; return;
} }
if (!Utils.IsUserLocal(username, out string domain)) //federation :( if (!Utils.IsUserLocal(idQuery, out string domain)) //federation :(
{ {
return; return;
} }
username = username.ToString().Split(":")[0]; string id = idQuery.ToString().Split(":")[0];
string id = await Utils.IdFromName(username);
Universal2String keys = JsonSerializer.Deserialize( Universal2String keys = JsonSerializer.Deserialize(
await Utils.GetUserKeys(id), await Utils.GetUserKeys(id),
@ -490,21 +511,20 @@ public class Requests
public static async Task GetUserPublicStorageEntry(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader) public static async Task GetUserPublicStorageEntry(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader)
{ {
if (!query.TryGetValue("u", out var username)) if (!query.TryGetValue("id", out var idQuery))
{ {
return; return;
} }
if (!query.TryGetValue("entry", out var entry)) if (!query.TryGetValue("e", out var entry))
{ {
return; return;
} }
if (!Utils.IsUserLocal(username, out string domain)) //federation :(
if (!Utils.IsUserLocal(idQuery, out string domain)) //federation :(
{ {
return; return;
} }
username = username.ToString().Split(":")[0]; string id = idQuery.ToString().Split(":")[0];
string id = await Utils.IdFromName(username);
byte[] entryByte = await Utils.GetUserPublicStorageEntry(id, entry); byte[] entryByte = await Utils.GetUserPublicStorageEntry(id, entry);
@ -589,6 +609,18 @@ public class Requests
await Room.Requests.DmInvite(id, serializedBody.string2) await Room.Requests.DmInvite(id, serializedBody.string2)
, password)); , password));
break; 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": case "user/dm/create":
await context.Response.WriteAsync( await context.Response.WriteAsync(
Encryption.Encryption.EncryptString( Encryption.Encryption.EncryptString(

View file

@ -56,6 +56,37 @@ public class Receiver
await context.Response.WriteAsync("success:user.invited"); 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; return;
case "dm/invite/hassent": case "dm/invite/hassent":
ids = serializedBody.string2.Split(','); //0=sender, 1=receiver ids = serializedBody.string2.Split(','); //0=sender, 1=receiver

View file

@ -49,4 +49,14 @@ public class Sender
{ {
return await FederationRequest("dm/invite/send", $"{receiverId},{senderId}", domain); return await FederationRequest("dm/invite/send", $"{receiverId},{senderId}", domain);
} }
public static async Task<string> DmInviteRevoke(string senderId, string domain, string receiverId)
{
return await FederationRequest("dm/invite/revoke", $"{receiverId},{senderId}", domain);
}
public static async Task<string> DmInviteDecline(string receiverId, string domain, string senderId)
{
return await FederationRequest("dm/invite/decline", $"{senderId},{receiverId}", domain);
}
} }

View file

@ -165,6 +165,9 @@ public class Program
case "/_larpix/correctedname": case "/_larpix/correctedname":
await Account.Requests.CorrectedName(context, next, query); await Account.Requests.CorrectedName(context, next, query);
return; return;
case "/_larpix/nametoid":
await Account.Requests.NameToId(context, next, query);
return;
case "/_larpix/idtoname": case "/_larpix/idtoname":
await Account.Requests.IdToName(context, next, query); await Account.Requests.IdToName(context, next, query);
return; return;

View file

@ -10,20 +10,18 @@ namespace LarpixServer.Room;
public class Requests public class Requests
{ {
public static SemaphoreSlim createLock = new SemaphoreSlim(1, 1); public static SemaphoreSlim createLock = new SemaphoreSlim(1, 1);
public static async Task<string> DmInvite(string id, string username2) public static async Task<string> DmInvite(string id, string targetId)
{ {
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation if (!Account.Utils.IsUserLocal(targetId, out string domain)) //federation
{ {
targetId = targetId.Split(":")[0];
username2 = username2.Split(":")[0]; await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{targetId};{domain}", Encoding.UTF8.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString()));
string remoteId2 = await Federation.Sender.GetUserId(username2, domain); return await Federation.Sender.DmInvite(id, domain, targetId);
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);
} }
username2 = username2.Split(":")[0]; targetId = targetId.Split(":")[0];
string id2 = await Account.Utils.IdFromName(username2); string id2 = targetId;
if (id2 == "0") if (id2 == "0" || string.IsNullOrEmpty(id2))
{ {
return "error:user.not.found"; return "error:user.not.found";
} }
@ -54,28 +52,80 @@ public class Requests
return "success:user.invited"; return "success:user.invited";
} }
public static async Task<string> 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<string> 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<string> DmCreate(string id, string body) public static async Task<string> DmCreate(string id, string body)
{ {
await createLock.WaitAsync(); await createLock.WaitAsync();
try 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, body,
AppJsonSerializerContext.Default.Universal3String AppJsonSerializerContext.Default.Universal3String
); );
string username2 = serializedBody.string1; string targetId = serializedBody.string1;
bool isUserLocal = Account.Utils.IsUserLocal(username2, out string domain); bool isUserLocal = Account.Utils.IsUserLocal(targetId, out string domain);
string id2; 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); return "error:user.not.found";
}
else //get id from federation
{
id2 = await Federation.Sender.GetUserId(username2, domain);
} }
if (isUserLocal) if (isUserLocal)