diff --git a/LibMatrix.Federation/AuthenticatedFederationClient.cs b/LibMatrix.Federation/AuthenticatedFederationClient.cs
index 15dc88f..ee4bb25 100644
--- a/LibMatrix.Federation/AuthenticatedFederationClient.cs
+++ b/LibMatrix.Federation/AuthenticatedFederationClient.cs
@@ -11,14 +11,14 @@ public class AuthenticatedFederationClient(string federationEndpoint, Authentica
public required string OriginServerName { get; set; }
}
- public async Task<UserDeviceListResponse> GetUserDevicesAsync(string userId) {
- var response = await HttpClient.SendAsync(new XMatrixAuthorizationScheme.XMatrixRequestSignature() {
- OriginServerName = config.OriginServerName,
- DestinationServerName = userId.Split(':', 2)[1],
- Method = "GET",
- Uri = $"/_matrix/federation/v1/user/devices/{userId}",
- }.ToSignedHttpRequestMessage(config.PrivateKey));
- return response;
- }
+ // public async Task<UserDeviceListResponse> GetUserDevicesAsync(string userId) {
+ // var response = await HttpClient.SendAsync(new XMatrixAuthorizationScheme.XMatrixRequestSignature() {
+ // OriginServerName = config.OriginServerName,
+ // DestinationServerName = userId.Split(':', 2)[1],
+ // Method = "GET",
+ // Uri = $"/_matrix/federation/v1/user/devices/{userId}",
+ // }.ToSignedHttpRequestMessage(config.PrivateKey));
+ // return response;
+ // }
}
\ No newline at end of file
diff --git a/LibMatrix/Helpers/RoomBuilder.cs b/LibMatrix/Helpers/RoomBuilder.cs
index 71eed69..0db4e6f 100644
--- a/LibMatrix/Helpers/RoomBuilder.cs
+++ b/LibMatrix/Helpers/RoomBuilder.cs
@@ -7,6 +7,7 @@ using LibMatrix.RoomTypes;
namespace LibMatrix.Helpers;
public class RoomBuilder {
+ private static readonly string[] V12PlusRoomVersions = ["org.matrix.hydra.11", "12"];
public string? Type { get; set; }
public string Version { get; set; } = "11";
public RoomNameEventContent Name { get; set; } = new();
@@ -25,6 +26,14 @@ public class RoomBuilder {
HistoryVisibility = RoomHistoryVisibilityEventContent.HistoryVisibilityTypes.Shared
};
+ public RoomGuestAccessEventContent GuestAccess { get; set; } = new() {
+ GuestAccess = "forbidden"
+ };
+
+ public RoomServerAclEventContent ServerAcls { get; set; } = new() {
+ AllowIpLiterals = false
+ };
+
/// <summary>
/// State events to be sent *before* room access is configured. Keep this small!
/// </summary>
@@ -57,14 +66,18 @@ public class RoomBuilder {
{ RoomCanonicalAliasEventContent.EventId, 50 },
{ RoomEncryptionEventContent.EventId, 100 },
{ RoomHistoryVisibilityEventContent.EventId, 100 },
+ { RoomGuestAccessEventContent.EventId, 100 },
{ RoomNameEventContent.EventId, 50 },
{ RoomPowerLevelEventContent.EventId, 100 },
{ RoomServerAclEventContent.EventId, 100 },
- { RoomTombstoneEventContent.EventId, 100 },
+ { RoomTombstoneEventContent.EventId, 150 },
{ RoomPolicyServerEventContent.EventId, 100 }
}
};
+ public Dictionary<string, object> AdditionalCreationContent { get; set; } = new();
+ public List<string> AdditionalCreators { get; set; } = new();
+
public async Task<GenericRoom> Create(AuthenticatedHomeserverGeneric homeserver) {
var crq = new CreateRoomRequest() {
PowerLevelContentOverride = new() {
@@ -78,20 +91,23 @@ public class RoomBuilder {
NotificationsPl = new() {
Room = 1000000
},
- Users = new Dictionary<string, long>() {
- { homeserver.WhoAmI.UserId, MatrixConstants.MaxSafeJsonInteger }
- },
+ Users = V12PlusRoomVersions.Contains(Version)
+ ? []
+ : new() {
+ { homeserver.WhoAmI.UserId, MatrixConstants.MaxSafeJsonInteger }
+ },
Events = new Dictionary<string, long> {
{ RoomAvatarEventContent.EventId, 1000000 },
{ RoomCanonicalAliasEventContent.EventId, 1000000 },
{ RoomEncryptionEventContent.EventId, 1000000 },
{ RoomHistoryVisibilityEventContent.EventId, 1000000 },
+ { RoomGuestAccessEventContent.EventId, 1000000 },
{ RoomNameEventContent.EventId, 1000000 },
{ RoomPowerLevelEventContent.EventId, 1000000 },
{ RoomServerAclEventContent.EventId, 1000000 },
{ RoomTombstoneEventContent.EventId, 1000000 },
{ RoomPolicyServerEventContent.EventId, 1000000 }
- }
+ },
},
Visibility = "private",
RoomVersion = Version
@@ -103,6 +119,14 @@ public class RoomBuilder {
if (!IsFederatable)
crq.CreationContent.Add("m.federate", false);
+ if (V12PlusRoomVersions.Contains(Version) && AdditionalCreators is { Count: > 0 }) {
+ crq.CreationContent.Add("additional_creators", AdditionalCreators);
+ }
+
+ foreach (var kvp in AdditionalCreationContent) {
+ crq.CreationContent.Add(kvp.Key, kvp.Value);
+ }
+
var room = await homeserver.CreateRoom(crq);
await SetBasicRoomInfoAsync(room);
diff --git a/LibMatrix/Responses/CreateRoomRequest.cs b/LibMatrix/Responses/CreateRoomRequest.cs
index 6933622..8f8af31 100644
--- a/LibMatrix/Responses/CreateRoomRequest.cs
+++ b/LibMatrix/Responses/CreateRoomRequest.cs
@@ -42,7 +42,7 @@ public class CreateRoomRequest {
public RoomPowerLevelEventContent? PowerLevelContentOverride { get; set; }
[JsonPropertyName("creation_content")]
- public JsonObject CreationContent { get; set; } = new();
+ public Dictionary<string, object> CreationContent { get; set; } = new();
[JsonPropertyName("invite")]
public List<string>? Invite { get; set; }
@@ -91,7 +91,7 @@ public class CreateRoomRequest {
var request = new CreateRoomRequest {
Name = name ?? "New public Room",
Visibility = "public",
- CreationContent = new JsonObject(),
+ CreationContent = new(),
PowerLevelContentOverride = new RoomPowerLevelEventContent {
EventsDefault = 0,
UsersDefault = 0,
@@ -131,7 +131,7 @@ public class CreateRoomRequest {
var request = new CreateRoomRequest {
Name = name ?? "New private Room",
Visibility = "private",
- CreationContent = new JsonObject(),
+ CreationContent = new(),
PowerLevelContentOverride = new RoomPowerLevelEventContent {
EventsDefault = 0,
UsersDefault = 0,
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 2e50e69..565776c 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -393,7 +393,7 @@ public class GenericRoom {
new UserIdAndReason { UserId = userId, Reason = reason });
public async Task InviteUserAsync(string userId, string? reason = null, bool skipExisting = true) {
- if (skipExisting && await GetStateOrNullAsync<RoomMemberEventContent>("m.room.member", userId) is not null)
+ if (skipExisting && await GetStateOrNullAsync<RoomMemberEventContent>("m.room.member", userId) is not { Membership: "leave" or "ban" or "join" })
return;
await Homeserver.ClientHttpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/invite", new UserIdAndReason(userId, reason));
}
@@ -403,7 +403,7 @@ public class GenericRoom {
#region Events
public async Task<EventIdResponse?> SendStateEventAsync(string eventType, object content) =>
- await (await Homeserver.ClientHttpClient.PutAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content))
+ await (await Homeserver.ClientHttpClient.PutAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType.UrlEncode()}", content))
.Content.ReadFromJsonAsync<EventIdResponse>();
public async Task<EventIdResponse> SendStateEventAsync(string eventType, string stateKey, object content) =>
|