1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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(ignoreNull: true);
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;
}
}
|