summary refs log tree commit diff
path: root/MatrixInviteLogger/InviteLogger.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixInviteLogger/InviteLogger.cs')
-rw-r--r--MatrixInviteLogger/InviteLogger.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/MatrixInviteLogger/InviteLogger.cs b/MatrixInviteLogger/InviteLogger.cs
new file mode 100644

index 0000000..22a519b --- /dev/null +++ b/MatrixInviteLogger/InviteLogger.cs
@@ -0,0 +1,117 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using ArcaneLibs; +using ArcaneLibs.Extensions; +using LibMatrix.EventTypes.Spec.State.RoomInfo; +using LibMatrix.Helpers; +using LibMatrix.Utilities.Bot.Services; +using MatrixInviteLogger; + +public class InviteLogger(ILogger<InviteLogger> logger, InviteLoggerConfiguration config) : InviteHandlerHostedService.IInviteHandler +{ + public async Task HandleInviteAsync(InviteHandlerHostedService.InviteEventArgs invite) + { + logger.LogInformation("Received invite to room {}", invite.RoomId); + var logRoom = invite.Homeserver.GetRoom(config.LogRoom); + var inviterName = await GetInviterNameAsync(invite); + string roomName = await GetRoomNameAsync(invite); + + logger.LogInformation("Inviter: {}, Room: {}", inviterName, roomName); + + var message = new MessageBuilder() + .WithBody("Received invite to ").WithMention(invite.RoomId, roomName).WithBody(" from ").WithMention(invite.MemberEvent.Sender!, inviterName) + .Build(); + + // TODO: can we filter this somehow to stay within event size limits? + // var serialisedInviteData = JsonNode.Parse(invite.InviteData.ToJson(ignoreNull: true)); + // message.AdditionalData!["gay.rory.invite_logger.invite_data"] = serialisedInviteData!; + + var inviteData = invite.InviteData.ToJsonUtf8Bytes(); + var inviteDataFileUri = await invite.Homeserver.UploadFile(invite.RoomId + ".json", inviteData, "application/json"); + logger.LogInformation("Uploaded invite data ({}) to {}", Util.BytesToString(inviteData.Length), inviteDataFileUri); + + // Dictionary<string, JsonElement> + message.AdditionalData!["gay.rory.invite_logger.invite_data_uri"] = JsonDocument.Parse($"\"{inviteDataFileUri}\"").RootElement; + + await logRoom.SendMessageEventAsync(message); + + if (config.SendInviteDataAsFile) + { + await logRoom.SendMessageEventAsync(new() + { + MessageType = "m.file", + Body = invite.RoomId + ".json", + FileName = invite.RoomId + ".json", + Url = inviteDataFileUri, + FileInfo = new() { Size = inviteData.Length, MimeType = "application/json" } + }); + } + } + + private async Task<string> GetInviterNameAsync(InviteHandlerHostedService.InviteEventArgs invite) + { + var name = invite.InviteData.InviteState?.Events? + .FirstOrDefault(evt => evt is { Type: RoomMemberEventContent.EventId } && evt.StateKey == invite.MemberEvent.Sender)? + .ContentAs<RoomMemberEventContent>()?.DisplayName; + + if (!string.IsNullOrWhiteSpace(name)) + return name; + + try + { + await invite.Homeserver.GetProfileAsync(invite.MemberEvent.Sender!); + } + catch + { + //ignored + } + + return invite.MemberEvent.Sender!; + } + + private async Task<string> GetRoomNameAsync(InviteHandlerHostedService.InviteEventArgs invite) + { + // try get room name from invite state + var name = invite.InviteData.InviteState?.Events? + .FirstOrDefault(evt => evt is { Type: RoomNameEventContent.EventId, StateKey: "" })? + .ContentAs<RoomNameEventContent>()?.Name; + + if (!string.IsNullOrWhiteSpace(name)) + return name; + + // try get room alias + var alias = invite.InviteData.InviteState?.Events? + .FirstOrDefault(evt => evt is { Type: RoomCanonicalAliasEventContent.EventId, StateKey: "" })? + .ContentAs<RoomCanonicalAliasEventContent>()?.Alias; + + if (!string.IsNullOrWhiteSpace(alias)) + return alias; + + // try get room name via public previews + try + { + name = await invite.Homeserver.GetRoom(invite.RoomId).GetNameOrFallbackAsync(); + if (name != invite.RoomId && !string.IsNullOrWhiteSpace(name)) + return name; + } + catch + { + //ignored + } + + // fallback to room alias via public previews + try + { + alias = (await invite.Homeserver.GetRoom(invite.RoomId).GetCanonicalAliasAsync())?.Alias; + if (!string.IsNullOrWhiteSpace(alias)) + return alias; + } + catch + { + //ignored + } + + // fall back to room ID + return invite.RoomId; + } +} \ No newline at end of file