summary refs log tree commit diff
path: root/MatrixInviteLogger
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixInviteLogger')
-rw-r--r--MatrixInviteLogger/InviteLogger.cs117
-rw-r--r--MatrixInviteLogger/InviteLoggerConfiguration.cs9
-rw-r--r--MatrixInviteLogger/MatrixInviteLogger.csproj17
-rw-r--r--MatrixInviteLogger/Program.cs16
-rw-r--r--MatrixInviteLogger/Properties/launchSettings.json12
-rw-r--r--MatrixInviteLogger/appsettings.Development.json16
-rw-r--r--MatrixInviteLogger/appsettings.json8
7 files changed, 195 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 diff --git a/MatrixInviteLogger/InviteLoggerConfiguration.cs b/MatrixInviteLogger/InviteLoggerConfiguration.cs new file mode 100644
index 0000000..8fe1a29 --- /dev/null +++ b/MatrixInviteLogger/InviteLoggerConfiguration.cs
@@ -0,0 +1,9 @@ +using Microsoft.Extensions.Configuration; + +namespace MatrixInviteLogger; + +public class InviteLoggerConfiguration { + public InviteLoggerConfiguration(IConfiguration config) => config.GetRequiredSection("InviteLogger").Bind(this); + public string LogRoom { get; set; } + public bool SendInviteDataAsFile { get; set; } +} \ No newline at end of file diff --git a/MatrixInviteLogger/MatrixInviteLogger.csproj b/MatrixInviteLogger/MatrixInviteLogger.csproj new file mode 100644
index 0000000..5a322ce --- /dev/null +++ b/MatrixInviteLogger/MatrixInviteLogger.csproj
@@ -0,0 +1,17 @@ +<Project Sdk="Microsoft.NET.Sdk.Worker"> + + <PropertyGroup> + <TargetFramework>net9.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + <UserSecretsId>dotnet-MatrixInviteLogger-87d8c346-8c07-42f9-8bfb-f2a714bbd663</UserSecretsId> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2"/> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\LibMatrix\Utilities\LibMatrix.Utilities.Bot\LibMatrix.Utilities.Bot.csproj" /> + </ItemGroup> +</Project> diff --git a/MatrixInviteLogger/Program.cs b/MatrixInviteLogger/Program.cs new file mode 100644
index 0000000..403f066 --- /dev/null +++ b/MatrixInviteLogger/Program.cs
@@ -0,0 +1,16 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using LibMatrix.Services; +using LibMatrix.Utilities.Bot; +using MatrixInviteLogger; + +var builder = Host.CreateApplicationBuilder(args); +// builder.Services.AddHostedService<Worker>(); + +builder.Services.AddSingleton<InviteLoggerConfiguration>(); +builder.Services.AddRoryLibMatrixServices() + .AddMatrixBot() + .WithInviteHandler<InviteLogger>(); + +var host = builder.Build(); +host.Run(); \ No newline at end of file diff --git a/MatrixInviteLogger/Properties/launchSettings.json b/MatrixInviteLogger/Properties/launchSettings.json new file mode 100644
index 0000000..383a8e2 --- /dev/null +++ b/MatrixInviteLogger/Properties/launchSettings.json
@@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "MatrixInviteLogger": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/MatrixInviteLogger/appsettings.Development.json b/MatrixInviteLogger/appsettings.Development.json new file mode 100644
index 0000000..ffdfb9c --- /dev/null +++ b/MatrixInviteLogger/appsettings.Development.json
@@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "LibMatrixBot": { + "Homeserver": "rory.gay", + "AccessTokenPath": "/home/Rory/matrix_access_token" + }, + "InviteLogger": { + "LogRoom": "!GrLSwdAkdrvfMrRYKR:rory.gay", + "SendInviteDataAsFile": true // default: false + } +} diff --git a/MatrixInviteLogger/appsettings.json b/MatrixInviteLogger/appsettings.json new file mode 100644
index 0000000..b2dcdb6 --- /dev/null +++ b/MatrixInviteLogger/appsettings.json
@@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +}