186 lines
No EOL
7.4 KiB
C#
186 lines
No EOL
7.4 KiB
C#
using System.Numerics;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using LarpixServer.Filesystem;
|
|
using LarpixServer.Utils.Jsons;
|
|
using static LarpixServer.Utils.Utils;
|
|
|
|
namespace LarpixServer.Room;
|
|
|
|
public class Requests
|
|
{
|
|
public static SemaphoreSlim createLock = new SemaphoreSlim(1, 1);
|
|
public static async Task<string> DmInvite(string id, string username2)
|
|
{
|
|
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
|
|
{
|
|
SemaphoreSlim userLock = Account.Utils.GetUserLock(id);
|
|
await userLock.WaitAsync();
|
|
try
|
|
{
|
|
username2 = username2.Split(":")[0];
|
|
string remoteId2 = await Federation.Sender.GetUserId(username2, domain);
|
|
await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{remoteId2};{domain}", []); //only save sent while federating
|
|
return await Federation.Sender.DmInvite(id, domain, remoteId2);
|
|
}
|
|
finally
|
|
{
|
|
userLock.Release();
|
|
}
|
|
}
|
|
username2 = username2.Split(":")[0];
|
|
string id2 = await Account.Utils.IdFromName(username2);
|
|
|
|
SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2);
|
|
await userLock2.WaitAsync();
|
|
|
|
try
|
|
{
|
|
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/recv/{id};{DOMAIN}";
|
|
if (Fs.Exists(inviteFile))
|
|
{
|
|
return "User already invited";
|
|
}
|
|
|
|
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
|
|
|
//im not saving this like ts is litterally local scenario
|
|
//await Fs.WriteFile(inviteSentFile, []); //we should also save that this user invited someone, because this will act as dm accept verification while federating
|
|
}
|
|
finally
|
|
{
|
|
userLock2.Release();
|
|
}
|
|
|
|
return "User invited";
|
|
}
|
|
|
|
public static async Task<string> 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
|
|
body,
|
|
AppJsonSerializerContext.Default.Universal3String
|
|
);
|
|
|
|
string username2 = serializedBody.string1;
|
|
bool isUserLocal = Account.Utils.IsUserLocal(username2, out string domain);
|
|
string id2;
|
|
username2 = username2.Split(":")[0];
|
|
if (isUserLocal)
|
|
{
|
|
id2 = await Account.Utils.IdFromName(username2);
|
|
}
|
|
else //get id from federation
|
|
{
|
|
id2 = await Federation.Sender.GetUserId(username2, domain);
|
|
}
|
|
|
|
if (isUserLocal)
|
|
{
|
|
/*
|
|
string inviteSentFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/sent/{id};{DOMAIN}";
|
|
if (!Fs.Exists(inviteSentFile))
|
|
{
|
|
return "You can't create a DM without an invitation";
|
|
}
|
|
Fs.DeleteFile(inviteSentFile);
|
|
*/ // local scenario, there is no need to check sent
|
|
}
|
|
else //check sent on federated server
|
|
{
|
|
if (!await Federation.Sender.HasSentDmInvite(id2, domain, id))
|
|
{
|
|
return "You can't create a DM without an invitation";
|
|
}
|
|
}
|
|
|
|
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id}/dminvites/recv/{id2};{domain}";
|
|
if (Fs.Exists(inviteFile))
|
|
{
|
|
|
|
try
|
|
{
|
|
Fs.DeleteFile(inviteFile); //remove invite bc now its accepted (error = no invite & no dm)
|
|
|
|
|
|
//best dmId creation ever
|
|
List<string> users = new List<string>(){$"{id};{DOMAIN}", $"{id2};{domain}"};
|
|
users.Sort();
|
|
string dmId = $"{users[0]}_{users[1]}";
|
|
|
|
|
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/members",
|
|
Encoding.UTF8.GetBytes($"{id}:{DOMAIN};{id2}:{domain}"));
|
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/last", Encoding.UTF8.GetBytes($"0"));
|
|
|
|
|
|
Message startingMessage = new();
|
|
startingMessage.attachment = "";
|
|
startingMessage.author = "0";
|
|
startingMessage.timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
|
|
startingMessage.type = "larp.info";
|
|
startingMessage.content =
|
|
"At the beginning of a DM, you should always verify that the person you're talking to is the intended recipient";
|
|
startingMessage.key = ""; //no key == NOT encrypted
|
|
startingMessage.pervious = "";
|
|
|
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/keys/0/{id};{DOMAIN}", //klucz dla uzytkownika tworzÄ…cego jest juz gotowy i ma zwykly zapis
|
|
Encoding.UTF8.GetBytes(serializedBody.string2));
|
|
|
|
|
|
Universal2String keys = JsonSerializer.Deserialize(
|
|
await Account.Utils.GetUserKeys(id),
|
|
AppJsonSerializerContext.Default.Universal2String
|
|
);
|
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/keys/0/{id2};{domain}",
|
|
Encoding.UTF8.GetBytes($"SETUP:{keys.string2};{serializedBody.string3}")); //jezeli mamy setup to [1] to jest publiczny klucz drugiej osoby,
|
|
//a string 3 to zaszyfrowany klucz pokoju ktory musi odszyfrowac za pomoca swoich kluczy i tego publicznego
|
|
|
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/0", Encoding.UTF8.GetBytes(
|
|
JsonSerializer.Serialize(startingMessage, AppJsonSerializerContext.Default.Message)
|
|
));
|
|
|
|
await Account.Utils.UpdateUserDm(id, dmId, "false",
|
|
startingMessage.timestamp);
|
|
|
|
if (isUserLocal)
|
|
{
|
|
SemaphoreSlim userLock = Account.Utils.GetUserLock(id2);
|
|
await userLock.WaitAsync();
|
|
try
|
|
{
|
|
await Account.Utils.UpdateUserDm(id2, dmId, "false",
|
|
startingMessage.timestamp);
|
|
}
|
|
finally
|
|
{
|
|
userLock.Release();
|
|
}
|
|
}
|
|
else //federacja
|
|
{
|
|
await Federation.Sender.AddToDm(id, domain, id2);
|
|
}
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
|
|
return "Failed to accept DM. Ask for another invite";
|
|
}
|
|
|
|
return "DM accepted";
|
|
|
|
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
createLock.Release();
|
|
}
|
|
return "You can't create a DM without an invitation";
|
|
}
|
|
} |