add message pinning
All checks were successful
Server Build / publish (push) Successful in 29s
Voice Build / publish (push) Successful in 25s

This commit is contained in:
olcxja 2026-07-25 01:06:59 +02:00
commit 0a0e79180a
3 changed files with 161 additions and 0 deletions

View file

@ -753,6 +753,12 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
await Room.Requests.DmMessageDelete(id, serializedBody.string2) await Room.Requests.DmMessageDelete(id, serializedBody.string2)
, password)); , password));
break; break;
case "dm/message/pin/toggle":
await context.Response.WriteAsync(
Encryption.Encryption.EncryptString(
await Room.Requests.DmMessagePinToggle(id, serializedBody.string2)
, password));
break;
case "dm/message/react/add": case "dm/message/react/add":
await context.Response.WriteAsync( await context.Response.WriteAsync(
Encryption.Encryption.EncryptString( Encryption.Encryption.EncryptString(
@ -774,6 +780,12 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
await context.Response.WriteAsync(Encryption.Encryption.EncryptString(await Room.Requests.GetDmMessages(id, msgGet.string1, msgGet.string3, msgGet.string2), password)); await context.Response.WriteAsync(Encryption.Encryption.EncryptString(await Room.Requests.GetDmMessages(id, msgGet.string1, msgGet.string3, msgGet.string2), password));
break; break;
} }
case "dm/messages/pinned":
await context.Response.WriteAsync(
Encryption.Encryption.EncryptString(
await Room.Requests.DmMessageGetPinned(id, serializedBody.string2)
, password));
break;
case "dm/read": case "dm/read":
{ {
Universal2String readGet = JsonSerializer.Deserialize( Universal2String readGet = JsonSerializer.Deserialize(

View file

@ -107,6 +107,11 @@ public class Requests
msgObj.reactions = ""; msgObj.reactions = "";
} }
if (Fs.Exists($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/pinned/{i}"))
{
msgObj.pinned = "true";
}
sb.Append(JsonSerializer.Serialize(msgObj, AppJsonSerializerContext.Default.Message)); sb.Append(JsonSerializer.Serialize(msgObj, AppJsonSerializerContext.Default.Message));
fetched++; fetched++;
} }
@ -650,4 +655,147 @@ public class Requests
} }
return "success:message.reaction.removed"; return "success:message.reaction.removed";
} }
public static async Task<string> DmMessagePinToggle(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";
string pinnedDir = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/pinned";
if (!System.IO.Directory.Exists(pinnedDir))
{
System.IO.Directory.CreateDirectory(pinnedDir);
}
string pinnedFilePath = $"{pinnedDir}/{msgId}";
bool isNowPinned = false;
if (Fs.Exists(pinnedFilePath))
{
Fs.DeleteFile(pinnedFilePath);
isNowPinned = false;
}
else
{
await Fs.WriteFile(pinnedFilePath, new byte[0]);
isNowPinned = true;
}
// Send larp.info.pin message
long nextId = 0;
await createLock.WaitAsync();
try
{
if (Fs.Exists($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/last"))
{
string lastStr = Encoding.UTF8.GetString(await Fs.ReadFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/last"));
if (long.TryParse(lastStr, out long last))
{
nextId = last + 1;
}
}
Message infoMessage = new();
infoMessage.attachment = "";
infoMessage.author = id;
infoMessage.timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
infoMessage.type = "larp.info.pin";
infoMessage.content = isNowPinned ? "{blah(message.pinned.by)}" : "{blah(message.unpinned.by)}";
infoMessage.key = "";
infoMessage.pervious = msgId;
string mPath = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/{nextId}";
await Fs.WriteFile(mPath, Encoding.UTF8.GetBytes(JsonSerializer.Serialize(infoMessage, AppJsonSerializerContext.Default.Message)));
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/last", Encoding.UTF8.GetBytes(nextId.ToString()));
}
finally
{
createLock.Release();
}
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}:update");
}
}
return "success:message.pin.toggled";
}
public static async Task<string> DmMessageGetPinned(string id, string dmId)
{
if (!await IsMemberOfDm(id, dmId)) return "error:forbidden";
string pinnedDir = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/pinned";
if (!System.IO.Directory.Exists(pinnedDir)) return "{}";
string[] pinnedFiles = Fs.ReadDirectory(pinnedDir);
StringBuilder sb = new StringBuilder("{");
int fetched = 0;
foreach (string pFile in pinnedFiles)
{
string msgId = System.IO.Path.GetFileName(pFile);
string msgPath = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/{msgId}";
if (Fs.Exists(msgPath))
{
if (fetched > 0) sb.Append(',');
sb.Append($"\"{msgId}\":");
string msgJson = Encoding.UTF8.GetString(await Fs.ReadFile(msgPath));
Message msgObj = JsonSerializer.Deserialize(msgJson, AppJsonSerializerContext.Default.Message);
string reactDir = $"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/reactions/{msgId}";
if (Fs.Exists(reactDir))
{
StringBuilder rxSb = new StringBuilder("[");
string[] reactFiles = Fs.ReadDirectory(reactDir);
int rxCount = 0;
foreach(string rf in reactFiles)
{
string rId = System.IO.Path.GetFileName(rf);
if (rId == "last") continue;
string content = Encoding.UTF8.GetString(await Fs.ReadFile($"{reactDir}/{rId}"));
int nLineIdx = content.IndexOf('\n');
if (nLineIdx != -1)
{
string u = content.Substring(0, nLineIdx).Trim();
string r = content.Substring(nLineIdx + 1).Trim();
if (rxCount > 0) rxSb.Append(',');
rxSb.Append($"{{\"id\":\"{rId}\",\"u\":\"{u}\",\"r\":\"{r}\"}}");
rxCount++;
}
}
rxSb.Append("]");
msgObj.reactions = rxCount > 0 ? rxSb.ToString() : "";
}
else
{
msgObj.reactions = "";
}
msgObj.pinned = "true";
sb.Append(JsonSerializer.Serialize(msgObj, AppJsonSerializerContext.Default.Message));
fetched++;
}
}
sb.Append("}");
return sb.ToString();
}
} }

View file

@ -60,4 +60,5 @@ public class Message
public string key { get; set; } public string key { get; set; }
public string responded { get; set; } public string responded { get; set; }
public string reactions { get; set; } public string reactions { get; set; }
public string pinned { get; set; }
} }