diff --git a/ArcaneLibs b/ArcaneLibs
-Subproject 174c07bba99f268bafcb15153e26ad63980d729
+Subproject 21040e61a1a2876092830af82ec67b8d4a8ac73
diff --git a/LibMatrix.EventTypes/LibMatrix.EventTypes.csproj b/LibMatrix.EventTypes/LibMatrix.EventTypes.csproj
index b8c4132..ae2f4de 100644
--- a/LibMatrix.EventTypes/LibMatrix.EventTypes.csproj
+++ b/LibMatrix.EventTypes/LibMatrix.EventTypes.csproj
@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20250123-182609" Condition="'$(Configuration)' == 'Release'"/>
+ <PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20250208-191806" Condition="'$(Configuration)' == 'Release'" />
<ProjectReference Include="..\ArcaneLibs\ArcaneLibs\ArcaneLibs.csproj" Condition="'$(Configuration)' == 'Debug'"/>
</ItemGroup>
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
index a008c37..03d994d 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
@@ -12,7 +12,7 @@ public class RoomJoinRulesEventContent : EventContent {
/// unknown values are treated as "private"
/// </summary>
[JsonPropertyName("join_rule")]
- public string JoinRuleValue { get; set; } = null!;
+ public string JoinRuleValue { get; set; }
[JsonIgnore]
public JoinRules JoinRule {
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
index c9aa603..22fa3b7 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
@@ -20,7 +20,7 @@ public class RoomPowerLevelEventContent : EventContent {
public long? Kick { get; set; } = 50;
[JsonPropertyName("notifications")]
- public NotificationsPowerLevels? NotificationsPl { get; set; } // = null!;
+ public NotificationsPowerLevels? NotificationsPl { get; set; }
[JsonPropertyName("redact")]
public long? Redact { get; set; } = 50;
@@ -29,10 +29,10 @@ public class RoomPowerLevelEventContent : EventContent {
public long? StateDefault { get; set; } = 50;
[JsonPropertyName("events")]
- public Dictionary<string, long>? Events { get; set; } // = null!;
+ public Dictionary<string, long>? Events { get; set; }
[JsonPropertyName("users")]
- public Dictionary<string, long>? Users { get; set; } // = null!;
+ public Dictionary<string, long>? Users { get; set; }
[JsonPropertyName("users_default")]
public long? UsersDefault { get; set; } = 0;
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomServerACLEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomServerACLEventContent.cs
index e3fc892..c492250 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomServerACLEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomServerACLEventContent.cs
@@ -7,10 +7,10 @@ public class RoomServerAclEventContent : EventContent {
public const string EventId = "m.room.server_acl";
[JsonPropertyName("allow")]
- public List<string>? Allow { get; set; } // = null!;
+ public List<string>? Allow { get; set; }
[JsonPropertyName("deny")]
- public List<string>? Deny { get; set; } // = null!;
+ public List<string>? Deny { get; set; }
[JsonPropertyName("allow_ip_literals")]
public bool AllowIpLiterals { get; set; } // = false;
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index f47ab64..8c95bc3 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -39,11 +39,12 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
public string UserId => WhoAmI.UserId;
public string UserLocalpart => UserId.Split(":")[0][1..];
public string ServerName => UserId.Split(":", 2)[1];
+ public string BaseUrl => ClientHttpClient.BaseAddress!.ToString().TrimEnd('/');
[JsonIgnore]
public string AccessToken { get; set; }
- public HsNamedCaches NamedCaches { get; set; } = null!;
+ public HsNamedCaches NamedCaches { get; set; }
public GenericRoom GetRoom(string roomId) {
if (roomId is null || !roomId.StartsWith("!")) throw new ArgumentException("Room ID must start with !", nameof(roomId));
@@ -408,22 +409,22 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
#region Authenticated Media
// TODO: implement /_matrix/client/v1/media/config when it's actually useful - https://spec.matrix.org/v1.11/client-server-api/#get_matrixclientv1mediaconfig
+ private bool? _serverSupportsAuthMedia;
- private (string ServerName, string MediaId) ParseMxcUri(string mxcUri) {
- if (!mxcUri.StartsWith("mxc://")) throw new ArgumentException("Matrix Content URIs must start with 'mxc://'", nameof(mxcUri));
- var parts = mxcUri[6..].Split('/');
- if (parts.Length != 2) throw new ArgumentException($"Invalid Matrix Content URI '{mxcUri}' passed! Matrix Content URIs must exist of only 2 parts!", nameof(mxcUri));
- return (parts[0], parts[1]);
- }
+ public async Task<string> GetMediaUrlAsync(MxcUri mxcUri, string? filename = null, int? timeout = null) {
+ if (_serverSupportsAuthMedia == true) return mxcUri.ToDownloadUri(BaseUrl, filename, timeout);
+ if (_serverSupportsAuthMedia == false) return mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout);
- public async Task<Stream> GetMediaStreamAsync(string mxcUri, string? filename = null, int? timeout = null) {
- var (serverName, mediaId) = ParseMxcUri(mxcUri);
try {
- var uri = $"/_matrix/client/v1/media/download/{serverName}/{mediaId}";
- if (!string.IsNullOrWhiteSpace(filename)) uri += $"/{HttpUtility.UrlEncode(filename)}";
- if (timeout is not null) uri += $"?timeout_ms={timeout}";
- var res = await ClientHttpClient.GetAsync(uri);
- return await res.Content.ReadAsStreamAsync();
+ // Console.WriteLine($"Trying authenticated media URL: {uri}");
+ var res = await ClientHttpClient.SendAsync(new() {
+ Method = HttpMethod.Head,
+ RequestUri = (new Uri(mxcUri.ToDownloadUri(BaseUrl, filename, timeout), string.IsNullOrWhiteSpace(BaseUrl) ? UriKind.Relative : UriKind.Absolute))
+ });
+ if (res.IsSuccessStatusCode) {
+ _serverSupportsAuthMedia = true;
+ return mxcUri.ToDownloadUri(BaseUrl, filename, timeout);
+ }
}
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNKNOWN" }) throw;
@@ -431,11 +432,15 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
//fallback to legacy media
try {
- var uri = $"/_matrix/media/v3/download/{serverName}/{mediaId}";
- if (!string.IsNullOrWhiteSpace(filename)) uri += $"/{HttpUtility.UrlEncode(filename)}";
- if (timeout is not null) uri += $"?timeout_ms={timeout}";
- var res = await ClientHttpClient.GetAsync(uri);
- return await res.Content.ReadAsStreamAsync();
+ // Console.WriteLine($"Trying legacy media URL: {uri}");
+ var res = await ClientHttpClient.SendAsync(new() {
+ Method = HttpMethod.Head,
+ RequestUri = new(mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout), string.IsNullOrWhiteSpace(BaseUrl) ? UriKind.Relative : UriKind.Absolute)
+ });
+ if (res.IsSuccessStatusCode) {
+ _serverSupportsAuthMedia = false;
+ return mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout);
+ }
}
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNKNOWN" }) throw;
@@ -443,13 +448,19 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
throw new LibMatrixException() {
ErrorCode = LibMatrixException.ErrorCodes.M_UNSUPPORTED,
- Error = "Failed to download media"
+ Error = "Failed to get media URL"
};
- // return default;
}
- public async Task<Stream> GetThumbnailStreamAsync(string mxcUri, int width, int height, string? method = null, int? timeout = null) {
- var (serverName, mediaId) = ParseMxcUri(mxcUri);
+ public async Task<Stream> GetMediaStreamAsync(string mxcUri, string? filename = null, int? timeout = null) {
+ var uri = await GetMediaUrlAsync(mxcUri, filename, timeout);
+ var res = await ClientHttpClient.GetAsync(uri);
+ return await res.Content.ReadAsStreamAsync();
+ }
+
+ public async Task<Stream> GetThumbnailStreamAsync(MxcUri mxcUri, int width, int height, string? method = null, int? timeout = null) {
+ var (serverName, mediaId) = mxcUri;
+
try {
var uri = new Uri($"/_matrix/client/v1/thumbnail/{serverName}/{mediaId}");
uri = uri.AddQuery("width", width.ToString());
@@ -494,7 +505,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw;
}
-
+
//fallback to legacy media
try {
var res = await ClientHttpClient.GetAsync($"/_matrix/media/v3/preview_url?url={HttpUtility.UrlEncode(url)}");
@@ -503,7 +514,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw;
}
-
+
throw new LibMatrixException() {
ErrorCode = LibMatrixException.ErrorCodes.M_UNSUPPORTED,
Error = "Failed to download URL preview"
diff --git a/LibMatrix/Homeservers/FederationClient.cs b/LibMatrix/Homeservers/FederationClient.cs
index c7f0240..617b737 100644
--- a/LibMatrix/Homeservers/FederationClient.cs
+++ b/LibMatrix/Homeservers/FederationClient.cs
@@ -13,8 +13,8 @@ public class FederationClient {
if (proxy is not null) HttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", federationEndpoint);
}
- public MatrixHttpClient HttpClient { get; set; } = null!;
- public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } = null!;
+ public MatrixHttpClient HttpClient { get; set; }
+ public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; }
public async Task<ServerVersionResponse> GetServerVersionAsync() => await HttpClient.GetFromJsonAsync<ServerVersionResponse>("/_matrix/federation/v1/version");
}
diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs
index 7995f03..7ac54a7 100644
--- a/LibMatrix/Homeservers/RemoteHomeServer.cs
+++ b/LibMatrix/Homeservers/RemoteHomeServer.cs
@@ -10,24 +10,24 @@ using LibMatrix.Services;
namespace LibMatrix.Homeservers;
public class RemoteHomeserver {
- public RemoteHomeserver(string baseUrl, HomeserverResolverService.WellKnownUris wellKnownUris, string? proxy) {
+ public RemoteHomeserver(string serverName, HomeserverResolverService.WellKnownUris wellKnownUris, string? proxy) {
if (string.IsNullOrWhiteSpace(proxy))
proxy = null;
- BaseUrl = baseUrl;
+ ServerNameOrUrl = serverName;
WellKnownUris = wellKnownUris;
ClientHttpClient = new MatrixHttpClient {
- BaseAddress = new Uri(proxy?.TrimEnd('/') ?? wellKnownUris.Client?.TrimEnd('/') ?? throw new InvalidOperationException($"No client URI for {baseUrl}!")),
+ BaseAddress = new Uri(proxy?.TrimEnd('/') ?? wellKnownUris.Client?.TrimEnd('/') ?? throw new InvalidOperationException($"No client URI for {serverName}!")),
// Timeout = TimeSpan.FromSeconds(300) // TODO: Re-implement this
};
- if (proxy is not null) ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl);
+ if (proxy is not null) ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName);
if (!string.IsNullOrWhiteSpace(wellKnownUris.Server))
FederationClient = new FederationClient(WellKnownUris.Server!, proxy);
Auth = new(this);
}
private Dictionary<string, object> _profileCache { get; set; } = new();
- public string BaseUrl { get; }
+ public string ServerNameOrUrl { get; }
[JsonIgnore]
public MatrixHttpClient ClientHttpClient { get; set; }
@@ -111,8 +111,8 @@ public class RemoteHomeserver {
public class AliasResult {
[JsonPropertyName("room_id")]
- public string RoomId { get; set; } = null!;
+ public string RoomId { get; set; }
[JsonPropertyName("servers")]
- public List<string> Servers { get; set; } = null!;
+ public List<string> Servers { get; set; }
}
\ No newline at end of file
diff --git a/LibMatrix/Homeservers/UserInteractiveAuthClient.cs b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
index bb3889f..8de01d2 100644
--- a/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
+++ b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
@@ -49,27 +49,27 @@ public class UserInteractiveAuthClient {
internal class RegisterFlowsResponse {
[JsonPropertyName("session")]
- public string Session { get; set; } = null!;
+ public string Session { get; set; }
[JsonPropertyName("flows")]
- public List<RegisterFlow> Flows { get; set; } = null!;
+ public List<RegisterFlow> Flows { get; set; }
[JsonPropertyName("params")]
- public JsonObject Params { get; set; } = null!;
+ public JsonObject Params { get; set; }
public class RegisterFlow {
[JsonPropertyName("stages")]
- public List<string> Stages { get; set; } = null!;
+ public List<string> Stages { get; set; }
}
}
internal class LoginFlowsResponse {
[JsonPropertyName("flows")]
- public List<LoginFlow> Flows { get; set; } = null!;
+ public List<LoginFlow> Flows { get; set; }
public class LoginFlow {
[JsonPropertyName("type")]
- public string Type { get; set; } = null!;
+ public string Type { get; set; }
}
}
diff --git a/LibMatrix/LibMatrix.csproj b/LibMatrix/LibMatrix.csproj
index c074e81..4814a18 100644
--- a/LibMatrix/LibMatrix.csproj
+++ b/LibMatrix/LibMatrix.csproj
@@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20250123-182609" Condition="'$(Configuration)' == 'Release'"/>
+ <PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20250208-191806" Condition="'$(Configuration)' == 'Release'" />
<ProjectReference Include="..\ArcaneLibs\ArcaneLibs\ArcaneLibs.csproj" Condition="'$(Configuration)' == 'Debug'"/>
</ItemGroup>
diff --git a/LibMatrix/MxcUri.cs b/LibMatrix/MxcUri.cs
new file mode 100644
index 0000000..02a8fa6
--- /dev/null
+++ b/LibMatrix/MxcUri.cs
@@ -0,0 +1,43 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace LibMatrix;
+
+public class MxcUri {
+ public required string ServerName;
+ public required string MediaId;
+
+ public static MxcUri Parse([StringSyntax("Uri")] string mxcUri) {
+ if (!mxcUri.StartsWith("mxc://")) throw new ArgumentException("Matrix Content URIs must start with 'mxc://'", nameof(mxcUri));
+ var parts = mxcUri[6..].Split('/');
+ if (parts.Length != 2) throw new ArgumentException($"Invalid Matrix Content URI '{mxcUri}' passed! Matrix Content URIs must exist of only 2 parts!", nameof(mxcUri));
+ return new MxcUri {
+ ServerName = parts[0],
+ MediaId = parts[1]
+ };
+ }
+
+ public static implicit operator MxcUri(string mxcUri) => Parse(mxcUri);
+ public static implicit operator string(MxcUri mxcUri) => $"mxc://{mxcUri.ServerName}/{mxcUri.MediaId}";
+ public static implicit operator (string, string)(MxcUri mxcUri) => (mxcUri.ServerName, mxcUri.MediaId);
+ public static implicit operator MxcUri((string serverName, string mediaId) mxcUri) => (mxcUri.serverName, mxcUri.mediaId);
+ // public override string ToString() => $"mxc://{ServerName}/{MediaId}";
+
+ public string ToDownloadUri(string? baseUrl = null, string? filename = null, int? timeout = null) {
+ var uri = $"{baseUrl}/_matrix/client/v1/media/download/{ServerName}/{MediaId}";
+ if (filename is not null) uri += $"/{filename}";
+ if (timeout is not null) uri += $"?timeout={timeout}";
+ return uri;
+ }
+
+ public string ToLegacyDownloadUri(string? baseUrl = null, string? filename = null, int? timeout = null) {
+ var uri = $"{baseUrl}/_matrix/media/v3/download/{ServerName}/{MediaId}";
+ if (filename is not null) uri += $"/{filename}";
+ if (timeout is not null) uri += $"?timeout_ms={timeout}";
+ return uri;
+ }
+
+ public void Deconstruct(out string serverName, out string mediaId) {
+ serverName = ServerName;
+ mediaId = MediaId;
+ }
+}
\ No newline at end of file
diff --git a/LibMatrix/Responses/CreateRoomRequest.cs b/LibMatrix/Responses/CreateRoomRequest.cs
index 1da6ff3..d9a6acd 100644
--- a/LibMatrix/Responses/CreateRoomRequest.cs
+++ b/LibMatrix/Responses/CreateRoomRequest.cs
@@ -26,7 +26,7 @@ public class CreateRoomRequest {
//we dont want to use this, we want more control
// [JsonPropertyName("preset")]
- // public string Preset { get; set; } = null!;
+ // public string Preset { get; set; }
[JsonPropertyName("initial_state")]
public List<StateEvent>? InitialState { get; set; }
diff --git a/LibMatrix/Responses/LoginResponse.cs b/LibMatrix/Responses/LoginResponse.cs
index b15eb20..ac2269c 100644
--- a/LibMatrix/Responses/LoginResponse.cs
+++ b/LibMatrix/Responses/LoginResponse.cs
@@ -4,10 +4,10 @@ namespace LibMatrix.Responses;
public class LoginResponse {
[JsonPropertyName("access_token")]
- public string AccessToken { get; set; } = null!;
+ public string AccessToken { get; set; }
[JsonPropertyName("device_id")]
- public string DeviceId { get; set; } = null!;
+ public string DeviceId { get; set; }
private string? _homeserver;
@@ -18,7 +18,7 @@ public class LoginResponse {
}
[JsonPropertyName("user_id")]
- public string UserId { get; set; } = null!;
+ public string UserId { get; set; }
// public async Task<AuthenticatedHomeserverGeneric> GetAuthenticatedHomeserver(string? proxy = null) {
// var urls = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(Homeserver);
diff --git a/LibMatrix/Responses/SyncResponse.cs b/LibMatrix/Responses/SyncResponse.cs
index b2308c5..529bd5c 100644
--- a/LibMatrix/Responses/SyncResponse.cs
+++ b/LibMatrix/Responses/SyncResponse.cs
@@ -8,7 +8,7 @@ internal partial class SyncResponseSerializerContext : JsonSerializerContext { }
public class SyncResponse {
[JsonPropertyName("next_batch")]
- public string NextBatch { get; set; } = null!;
+ public string NextBatch { get; set; }
[JsonPropertyName("account_data")]
public EventList? AccountData { get; set; }
@@ -17,7 +17,7 @@ public class SyncResponse {
public PresenceDataStructure? Presence { get; set; }
[JsonPropertyName("device_one_time_keys_count")]
- public Dictionary<string, int>? DeviceOneTimeKeysCount { get; set; } = null!;
+ public Dictionary<string, int>? DeviceOneTimeKeysCount { get; set; }
[JsonPropertyName("rooms")]
public RoomsDataStructure? Rooms { get; set; }
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 202bfc1..8f1b56d 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -553,5 +553,5 @@ public class GenericRoom {
public class RoomIdResponse {
[JsonPropertyName("room_id")]
- public string RoomId { get; set; } = null!;
+ public string RoomId { get; set; }
}
\ No newline at end of file
diff --git a/Tests/LibMatrix.Tests/Abstractions/RoomAbstraction.cs b/Tests/LibMatrix.Tests/Abstractions/RoomAbstraction.cs
index 88c0353..13c5f58 100644
--- a/Tests/LibMatrix.Tests/Abstractions/RoomAbstraction.cs
+++ b/Tests/LibMatrix.Tests/Abstractions/RoomAbstraction.cs
@@ -52,7 +52,7 @@ public static class RoomAbstraction {
return testRoom;
}
- private static SemaphoreSlim _spaceSemaphore = null!;
+ private static SemaphoreSlim _spaceSemaphore = new(1, 1);
public static async Task<SpaceRoom> GetTestSpace(AuthenticatedHomeserverGeneric hs, int roomCount = 100, bool addSpaces = false, int spaceSizeReduction = 10) {
_spaceSemaphore ??= new SemaphoreSlim(roomCount / spaceSizeReduction, roomCount / spaceSizeReduction);
diff --git a/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs b/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs
index 85c86a3..745c75d 100644
--- a/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs
+++ b/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs
@@ -7,5 +7,16 @@ public class PingCommand : ICommand {
public string Name { get; } = "ping";
public string Description { get; } = "Pong!";
- public async Task Invoke(CommandContext ctx) => await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!"));
+ // public async Task Invoke(CommandContext ctx) => await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!"));
+ public async Task Invoke(CommandContext ctx) {
+ // await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!"));
+ var count = ctx.Args.Length > 0 ? int.Parse(ctx.Args[0]) : 1;
+ var tasks = Enumerable.Range(0, count).Select(async i => {
+ await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: $"!ping {i}", messageType: "m.text"));
+ await Task.Delay(1000);
+ }).ToList();
+ await Task.WhenAll(tasks);
+
+ await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "Pong!"));
+ }
}
\ No newline at end of file
diff --git a/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs b/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs
new file mode 100644
index 0000000..9c8ad67
--- /dev/null
+++ b/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs
@@ -0,0 +1,125 @@
+using System.Diagnostics.CodeAnalysis;
+using ArcaneLibs.Extensions;
+using LibMatrix.EventTypes.Spec;
+using LibMatrix.EventTypes.Spec.State.RoomInfo;
+using LibMatrix.ExampleBot.Bot.Interfaces;
+using LibMatrix.Filters;
+using LibMatrix.Helpers;
+using LibMatrix.Homeservers;
+using LibMatrix.Services;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace LibMatrix.ExampleBot.Bot;
+
+public class PingTestBot : IHostedService {
+ private readonly HomeserverProviderService _homeserverProviderService;
+ private readonly ILogger<DevTestBot> _logger;
+ private readonly DevTestBotConfiguration _configuration;
+ private readonly IEnumerable<ICommand> _commands;
+
+ public PingTestBot(HomeserverProviderService homeserverProviderService, ILogger<DevTestBot> logger,
+ DevTestBotConfiguration configuration, IServiceProvider services) {
+ logger.LogInformation("{} instantiated!", GetType().Name);
+ _homeserverProviderService = homeserverProviderService;
+ _logger = logger;
+ _configuration = configuration;
+ _logger.LogInformation("Getting commands...");
+ _commands = services.GetServices<ICommand>();
+ _logger.LogInformation("Got {} commands!", _commands.Count());
+ }
+
+ /// <summary>Triggered when the application host is ready to start the service.</summary>
+ /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
+ [SuppressMessage("ReSharper", "FunctionNeverReturns")]
+ public async Task StartAsync(CancellationToken cancellationToken) {
+ // Directory.GetFiles("bot_data/cache").ToList().ForEach(File.Delete);
+ AuthenticatedHomeserverGeneric hs;
+ try {
+ hs = await _homeserverProviderService.GetAuthenticatedWithToken(_configuration.Homeserver,
+ _configuration.AccessToken);
+ }
+ catch (Exception e) {
+ _logger.LogError("{}", e.Message);
+ throw;
+ }
+
+ var msg = new MessageBuilder().WithRainbowString("Meanwhile, I'm sitting here, still struggling with trying to rainbow. ^^'").Build();
+
+ var syncHelper = new SyncHelper(hs);
+ syncHelper.Filter = new SyncFilter {
+ Room = new SyncFilter.RoomFilter {
+ Timeline = new SyncFilter.RoomFilter.StateFilter() {
+ Limit = 1,
+ Senders = ["@me"]
+ },
+ Rooms = ["!ping-v11:maunium.net"],
+ AccountData = new(types: []),
+ IncludeLeave = false
+ }
+ };
+
+ // await hs.GetRoom("!VJwxdebqoQlhGSEncc:codestorm.net").JoinAsync();
+
+ // foreach (var room in await hs.GetJoinedRooms()) {
+ // if(room.RoomId is "!OGEhHVWSdvArJzumhm:matrix.org") continue;
+ // foreach (var stateEvent in await room.GetStateAsync<List<StateEvent>>("")) {
+ // var _ = stateEvent.GetType;
+ // }
+ // _logger.LogInformation($"Got room state for {room.RoomId}!");
+ // }
+
+ // syncHelper.InviteReceivedHandlers.Add(async Task (args) => {
+ // var inviteEvent =
+ // args.Value.InviteState.Events.FirstOrDefault(x =>
+ // x.Type == "m.room.member" && x.StateKey == hs.UserId);
+ // _logger.LogInformation(
+ // $"Got invite to {args.Key} by {inviteEvent.Sender} with reason: {(inviteEvent.TypedContent as RoomMemberEventContent).Reason}");
+ // if (inviteEvent.Sender.EndsWith(":rory.gay") || inviteEvent.Sender == "@mxidupwitch:the-apothecary.club")
+ // try {
+ // var senderProfile = await hs.GetProfileAsync(inviteEvent.Sender);
+ // await hs.GetRoom(args.Key).JoinAsync(reason: $"I was invited by {senderProfile.DisplayName ?? inviteEvent.Sender}!");
+ // }
+ // catch (Exception e) {
+ // _logger.LogError("{}", e.ToString());
+ // await hs.GetRoom(args.Key).LeaveAsync("I was unable to join the room: " + e);
+ // }
+ // });
+ syncHelper.TimelineEventHandlers.Add(async @event => {
+ _logger.LogInformation(
+ "Got timeline event in {}: {}", @event.RoomId, @event.ToJson(false, true));
+
+ var room = hs.GetRoom(@event.RoomId);
+ // _logger.LogInformation(eventResponse.ToJson(indent: false));
+ if (@event is not { Sender: "@emma:rory.gay" }) return;
+ if (@event is { Type: "m.room.message", TypedContent: RoomMessageEventContent message })
+ if (message is { MessageType: "m.text" } && message.Body.StartsWith(_configuration.Prefix)) {
+ var command = _commands.FirstOrDefault(x => x.Name == message.Body.Split(' ')[0][_configuration.Prefix.Length..]);
+ if (command == null) {
+ await room.SendMessageEventAsync(
+ new RoomMessageEventContent("m.text", "Command not found!"));
+ return;
+ }
+
+ var ctx = new CommandContext {
+ Room = room,
+ MessageEvent = @event
+ };
+ if (await command.CanInvoke(ctx))
+ await command.Invoke(ctx);
+ else
+ await room.SendMessageEventAsync(
+ new RoomMessageEventContent("m.text", "You do not have permission to run this command!"));
+ }
+ });
+ await syncHelper.RunSyncLoopAsync(cancellationToken: cancellationToken);
+ }
+
+ /// <summary>Triggered when the application host is performing a graceful shutdown.</summary>
+ /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
+ public Task StopAsync(CancellationToken cancellationToken) {
+ _logger.LogInformation("Shutting down bot!");
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj b/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj
index 3f4c9d8..8817e9c 100644
--- a/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj
+++ b/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj
@@ -18,7 +18,7 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-preview.20250123-182609" Condition="'$(Configuration)' == 'Release'"/>
+ <PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-preview.20250208-191806" Condition="'$(Configuration)' == 'Release'" />
<ProjectReference Include="..\..\ArcaneLibs\ArcaneLibs.StringNormalisation\ArcaneLibs.StringNormalisation.csproj" Condition="'$(Configuration)' == 'Debug'"/>
<ProjectReference Include="..\..\LibMatrix\LibMatrix.csproj"/>
</ItemGroup>
diff --git a/Utilities/LibMatrix.DevTestBot/Program.cs b/Utilities/LibMatrix.DevTestBot/Program.cs
index daaa65e..8eaaea8 100644
--- a/Utilities/LibMatrix.DevTestBot/Program.cs
+++ b/Utilities/LibMatrix.DevTestBot/Program.cs
@@ -24,7 +24,7 @@ var host = Host.CreateDefaultBuilder(args).ConfigureServices((_, services) => {
}
// services.AddHostedService<ServerRoomSizeCalulator>();
- services.AddHostedService<DevTestBot>();
+ services.AddHostedService<PingTestBot>();
}).UseConsoleLifetime().Build();
await host.RunAsync();
\ No newline at end of file
diff --git a/Utilities/LibMatrix.DevTestBot/appsettings.json b/Utilities/LibMatrix.DevTestBot/appsettings.json
index db64c22..0d18b81 100644
--- a/Utilities/LibMatrix.DevTestBot/appsettings.json
+++ b/Utilities/LibMatrix.DevTestBot/appsettings.json
@@ -8,7 +8,7 @@
},
"Bot": {
"Homeserver": "rory.gay",
- "AccessToken": "syt_xxxxxxxxxxxxxxxxx",
- "Prefix": "!"
+ "AccessToken": "syt_ZW1tYQ_ATWykhpCWzjxkgTJHnAx_2AaoI7",
+ "Prefix": "$"
}
}
\ No newline at end of file
diff --git a/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs b/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs
index 2cfcf32..6dc76f6 100644
--- a/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs
+++ b/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs
@@ -4,28 +4,28 @@ namespace LibMatrix.Utilities.Bot.AppServices;
public class AppServiceConfiguration {
[JsonPropertyName("id")]
- public string Id { get; set; } = null!;
+ public string Id { get; set; }
[JsonPropertyName("url")]
- public string? Url { get; set; } = null!;
+ public string? Url { get; set; }
[JsonPropertyName("sender_localpart")]
- public string SenderLocalpart { get; set; } = null!;
+ public string SenderLocalpart { get; set; }
[JsonPropertyName("as_token")]
- public string AppserviceToken { get; set; } = null!;
+ public string AppserviceToken { get; set; }
[JsonPropertyName("hs_token")]
- public string HomeserverToken { get; set; } = null!;
+ public string HomeserverToken { get; set; }
[JsonPropertyName("protocols")]
- public List<string>? Protocols { get; set; } = null!;
+ public List<string>? Protocols { get; set; }
[JsonPropertyName("rate_limited")]
- public bool? RateLimited { get; set; } = null!;
+ public bool? RateLimited { get; set; }
[JsonPropertyName("namespaces")]
- public AppserviceNamespaces Namespaces { get; set; } = null!;
+ public AppserviceNamespaces Namespaces { get; set; }
public class AppserviceNamespaces {
[JsonPropertyName("users")]
@@ -42,7 +42,7 @@ public class AppServiceConfiguration {
public bool Exclusive { get; set; }
[JsonPropertyName("regex")]
- public string Regex { get; set; } = null!;
+ public string Regex { get; set; }
}
}
|