diff --git a/LarpixServer/Account/Requests.cs b/LarpixServer/Account/Requests.cs index 9062cf2..52df624 100644 --- a/LarpixServer/Account/Requests.cs +++ b/LarpixServer/Account/Requests.cs @@ -653,6 +653,18 @@ public static async Task Auth(HttpContext context, Func next, IQueryCollec await Room.Requests.DmMessageSend(id, serializedBody.string2) , password)); break; + case "dm/message/delete": + await context.Response.WriteAsync( + Encryption.Encryption.EncryptString( + await Room.Requests.DmMessageDelete(id, serializedBody.string2) + , password)); + break; + case "dm/message/react": + await context.Response.WriteAsync( + Encryption.Encryption.EncryptString( + await Room.Requests.DmMessageReact(id, serializedBody.string2) + , password)); + break; case "dm/messages/get": { Universal3String msgGet = JsonSerializer.Deserialize( diff --git a/LarpixServer/Room/Requests.cs b/LarpixServer/Room/Requests.cs index a3b9e80..221698d 100644 --- a/LarpixServer/Room/Requests.cs +++ b/LarpixServer/Room/Requests.cs @@ -23,6 +23,16 @@ public class Requests return true; } + private static bool IsSafeMsgId(string msgId) + { + if (string.IsNullOrEmpty(msgId)) return false; + if (msgId.Contains("..") || msgId.Contains("/") || msgId.Contains("\\")) + { + return false; + } + return true; + } + private static async Task IsMemberOfDm(string id, string dmId) { if (!IsSafeDmId(dmId)) return false; @@ -361,13 +371,14 @@ public class Requests public static async Task DmMessageSend(string id, string body) { - Universal3String serializedBody = JsonSerializer.Deserialize( + Universal4String serializedBody = JsonSerializer.Deserialize( body, - AppJsonSerializerContext.Default.Universal3String + AppJsonSerializerContext.Default.Universal4String ); string dmId = serializedBody.string1; string content = serializedBody.string2; string attachment = serializedBody.string3; + string responded = serializedBody.string4; if (!await IsMemberOfDm(id, dmId)) return "error:forbidden"; @@ -387,6 +398,8 @@ public class Requests msg.attachment = attachment; msg.key = "0"; // Flag for encrypted content msg.pervious = ""; + msg.responded = responded ?? ""; + msg.reactions = ""; await Fs.WriteFile($"{msgDir}/{nextId}", Encoding.UTF8.GetBytes(JsonSerializer.Serialize(msg, AppJsonSerializerContext.Default.Message))); await Fs.WriteFile($"{msgDir}/last", Encoding.UTF8.GetBytes(nextId.ToString())); @@ -424,4 +437,84 @@ public class Requests } return "success:message.sent"; } + + public static async Task DmMessageDelete(string id, string body) + { + Universal2String serializedBody = JsonSerializer.Deserialize( + body, + AppJsonSerializerContext.Default.Universal2String + ); + string dmId = serializedBody.string1; + string msgId = serializedBody.string2; + + if (!IsSafeMsgId(msgId)) return "error:invalid.msg.id"; + if (!await IsMemberOfDm(id, dmId)) return "error:forbidden"; + + string msgPath = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/{msgId}"; + if (!Fs.Exists(msgPath)) return "error:message.not.found"; + + Message msg = JsonSerializer.Deserialize( + Encoding.UTF8.GetString(await Fs.ReadFile(msgPath)), + AppJsonSerializerContext.Default.Message + ); + + if (msg.author != id) return "error:forbidden"; + + msg.type = "larp.redacted"; + msg.content = "{blah(larp.redacted)}"; + msg.attachment = ""; + msg.key = ""; + + await Fs.WriteFile(msgPath, Encoding.UTF8.GetBytes(JsonSerializer.Serialize(msg, AppJsonSerializerContext.Default.Message))); + + string[] members = Fs.ReadDirectory($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/members"); + foreach(string memberWD in members) + { + bool isLocal = Account.Utils.IsUserLocal(memberWD, out string domain); + string memberId = Account.Utils.GetValidIdOrZero(memberWD); + if (isLocal) + { + await Utils.Utils.SendWsMessage(memberId, $"dm_message:{dmId}"); + } + } + return "success:message.deleted"; + } + + public static async Task DmMessageReact(string id, string body) + { + Universal3String serializedBody = JsonSerializer.Deserialize( + body, + AppJsonSerializerContext.Default.Universal3String + ); + string dmId = serializedBody.string1; + string msgId = serializedBody.string2; + string reactions = serializedBody.string3; + + if (!IsSafeMsgId(msgId)) return "error:invalid.msg.id"; + if (!await IsMemberOfDm(id, dmId)) return "error:forbidden"; + + string msgPath = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/{msgId}"; + if (!Fs.Exists(msgPath)) return "error:message.not.found"; + + Message msg = JsonSerializer.Deserialize( + Encoding.UTF8.GetString(await Fs.ReadFile(msgPath)), + AppJsonSerializerContext.Default.Message + ); + + msg.reactions = reactions ?? ""; + + await Fs.WriteFile(msgPath, Encoding.UTF8.GetBytes(JsonSerializer.Serialize(msg, AppJsonSerializerContext.Default.Message))); + + string[] members = Fs.ReadDirectory($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/members"); + foreach(string memberWD in members) + { + bool isLocal = Account.Utils.IsUserLocal(memberWD, out string domain); + string memberId = Account.Utils.GetValidIdOrZero(memberWD); + if (isLocal) + { + await Utils.Utils.SendWsMessage(memberId, $"dm_message:{dmId}"); + } + } + return "success:message.reacted"; + } } \ No newline at end of file diff --git a/LarpixServer/Utils/AppJsonSerializerContext.cs b/LarpixServer/Utils/AppJsonSerializerContext.cs index ffdc077..d95ba6d 100644 --- a/LarpixServer/Utils/AppJsonSerializerContext.cs +++ b/LarpixServer/Utils/AppJsonSerializerContext.cs @@ -7,6 +7,7 @@ namespace LarpixServer.Utils.Jsons; [JsonSerializable(typeof(CaptchaPayloadClient))] [JsonSerializable(typeof(Universal2String))] [JsonSerializable(typeof(Universal3String))] +[JsonSerializable(typeof(Universal4String))] [JsonSerializable(typeof(ServerInfo))] [JsonSerializable(typeof(Message))] public partial class AppJsonSerializerContext : JsonSerializerContext diff --git a/LarpixServer/Utils/Jsons.cs b/LarpixServer/Utils/Jsons.cs index 54c94fc..7ee2e57 100644 --- a/LarpixServer/Utils/Jsons.cs +++ b/LarpixServer/Utils/Jsons.cs @@ -17,6 +17,13 @@ public class Universal3String public string string2 { get; set; } public string string3 { get; set; } } +public class Universal4String +{ + public string string1 { get; set; } + public string string2 { get; set; } + public string string3 { get; set; } + public string string4 { get; set; } +} public class KeyExchangePayload @@ -51,4 +58,6 @@ public class Message public string attachment { get; set; } public string timestamp { get; set; } public string key { get; set; } + public string responded { get; set; } + public string reactions { get; set; } } \ No newline at end of file