@page "/HSAdmin/Synapse/RoomQuery"
@using Microsoft.AspNetCore.WebUtilities
@using ArcaneLibs.Extensions
@using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Filters
@using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Requests
@using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Responses
@using MatrixUtils.Web.Pages.HSAdmin.Synapse.Components
Homeserver Administration - Room Query
Search name:
Order by:
@foreach (var item in validOrderBy) {
@item.Value
}
Ascending:
Local filtering (slow)
String contains
Room ID:
Room name:
Canonical alias:
Creator:
Room version:
Encryption algorithm:
Join rules:
Guest access:
History visibility:
Optional checks
Is federated:
@if (Filter.CheckFederation) {
}
Is public:
@if (Filter.CheckPublic) {
}
Ranges
state events
members
local members
Search
@if (Results.Count > 0) {
Found @Results.Count rooms
TSV data (copy/paste)
@foreach (var res in Results) {
@res.RoomId@("\t")
@res.CanonicalAlias@("\t")
@res.Creator@("\t")
@res.Name
}
}
@foreach (var res in Results) {
@*
*@
@if (!string.IsNullOrWhiteSpace(res.CanonicalAlias)) {
@res.CanonicalAlias - @res.RoomId (@res.Name)
}
else {
@res.RoomId (@res.Name)
}
@if (!string.IsNullOrWhiteSpace(res.Creator)) {
@* Created by *@
Created by @res.Creator
}
Delete room
@res.StateEvents state events
@if (res.LocalMembers is null) {
@res.JoinedMembers members, of which @res.JoinedLocalMembers are on this server
}
else {
@res.JoinedMembers members, of which @res.JoinedLocalMembers are on this server: @(string.Join(", ", res.LocalMembers))
}
Full result data
@res.ToJson(ignoreNull: true)
}
@* *@
@* @if (DeleteRequest.HasValue) { *@
@* *@
@* *@
@* *@
@* } *@
@* @foreach (var (roomId, status) in DeleteStatuses) { *@
@* *@
@* @status.ToJson() *@
@* *@
@* } *@
@foreach(var (roomId, deleteRequest) in DeleteRequests) {
}
@code {
[Parameter]
[SupplyParameterFromQuery(Name = "order_by")]
public string? OrderBy { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "name_search")]
public string SearchTerm { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "ascending")]
public bool Ascending { get; set; }
private List Results { get; set; } = new();
private AuthenticatedHomeserverSynapse Homeserver { get; set; } = null!;
private string Status { get; set; }
public SynapseAdminLocalRoomQueryFilter Filter { get; set; } = new();
private Dictionary DeleteRequests { get; set; } = [];
// private Dictionary DeleteStatuses { get; set; } = new();
protected override Task OnParametersSetAsync() {
if (Ascending == null)
Ascending = true;
OrderBy ??= "name";
var execute = false;
foreach (var (key, value) in QueryHelpers.ParseQuery(new Uri(NavigationManager.Uri).Query)) {
switch (key) {
case "RoomIdContains":
Filter.RoomIdContains = value[0]!;
break;
case "NameContains":
Filter.NameContains = value[0]!;
break;
case "CanonicalAliasContains":
Filter.CanonicalAliasContains = value[0]!;
break;
case "VersionContains":
Filter.VersionContains = value[0]!;
break;
case "CreatorContains":
Filter.CreatorContains = value[0]!;
break;
case "EncryptionContains":
Filter.EncryptionContains = value[0]!;
break;
case "JoinRulesContains":
Filter.JoinRulesContains = value[0]!;
break;
case "GuestAccessContains":
Filter.GuestAccessContains = value[0]!;
break;
case "HistoryVisibilityContains":
Filter.HistoryVisibilityContains = value[0]!;
break;
case "Federatable":
Filter.Federatable = bool.Parse(value[0]!);
Filter.CheckFederation = true;
break;
case "Public":
Filter.Public = value[0] == "true";
Filter.CheckPublic = true;
break;
case "JoinedMembersGreaterThan":
Filter.JoinedMembersGreaterThan = int.Parse(value[0]!);
break;
case "JoinedMembersLessThan":
Filter.JoinedMembersLessThan = int.Parse(value[0]!);
break;
case "JoinedLocalMembersGreaterThan":
Filter.JoinedLocalMembersGreaterThan = int.Parse(value[0]!);
break;
case "JoinedLocalMembersLessThan":
Filter.JoinedLocalMembersLessThan = int.Parse(value[0]!);
break;
case "StateEventsGreaterThan":
Filter.StateEventsGreaterThan = int.Parse(value[0]!);
break;
case "StateEventsLessThan":
Filter.StateEventsLessThan = int.Parse(value[0]!);
break;
case "Execute":
execute = true;
break;
default:
Console.WriteLine($"Unknown query parameter: {key}");
break;
}
}
if (execute)
_ = Search();
return Task.CompletedTask;
}
private async Task Search() {
Results.Clear();
var hs = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true);
if (hs is AuthenticatedHomeserverSynapse synapse) {
Homeserver = synapse;
var searchRooms = synapse.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, localFilter: Filter).GetAsyncEnumerator();
while (await searchRooms.MoveNextAsync()) {
var room = searchRooms.Current;
if (Results.Count < 100)
Console.WriteLine("Hit: " + room.ToJson(false));
var roomInfo = new RoomInfo {
RoomId = room.RoomId,
Name = room.Name,
CanonicalAlias = room.CanonicalAlias,
Creator = room.Creator,
Version = room.Version,
Encryption = room.Encryption,
Federatable = room.Federatable,
Public = room.Public,
JoinRules = room.JoinRules,
GuestAccess = room.GuestAccess,
HistoryVisibility = room.HistoryVisibility,
StateEvents = room.StateEvents,
JoinedMembers = room.JoinedMembers,
JoinedLocalMembers = room.JoinedLocalMembers
};
Results.Add(roomInfo);
if (room.JoinedLocalMembers is > 0 and < 100)
roomInfo.LocalMembers = (await synapse.Admin.GetRoomMembersAsync(room.RoomId)).Members.Where(x => x.EndsWith(":" + synapse.ServerName)).ToList();
if (Results.Count < 200 || Results.Count % 1000 == 0) {
StateHasChanged();
await Task.Yield();
}
}
}
StateHasChanged();
}
//
// private async Task DeleteRoom() {
// if (DeleteRequest is { } deleteRequest) {
// var media = await Homeserver.Admin.GetRoomMediaAsync(deleteRequest.RoomId);
// if (deleteRequest.DeleteRequest.QuarantineRemoteMedia) {
// foreach (var remoteMedia in media.Remote) {
// await Homeserver.Admin.QuarantineMediaById(remoteMedia);
// }
// }
//
// if (deleteRequest.DeleteRequest.DeleteRemoteMedia) {
// foreach (var remoteMedia in media.Remote) {
// await Homeserver.Admin.DeleteMediaById(remoteMedia);
// }
// }
// else if (deleteRequest.DeleteRequest.QuarantineLocalMedia) {
// foreach (var localMedia in media.Local) {
// await Homeserver.Admin.QuarantineMediaById(localMedia);
// }
// }
//
// var deleteId = await Homeserver.Admin.DeleteRoom(deleteRequest.RoomId, deleteRequest.DeleteRequest, waitForCompletion: false);
// DeleteRequest = null;
// List alreadyCleanedUsers = [];
// while (true) {
// var status = await Homeserver.Admin.GetRoomDeleteStatus(deleteId.DeleteId);
// DeleteStatuses[deleteRequest.RoomId] = status;
// StateHasChanged();
// await Task.Delay(5000);
// if (status.Status == "complete") {
// DeleteStatuses.Remove(deleteRequest.RoomId);
// StateHasChanged();
// break;
// }
//
// if (status.Status == "failed") {
// deleteId = await Homeserver.Admin.DeleteRoom(deleteRequest.RoomId, deleteRequest.DeleteRequest, waitForCompletion: false);
// }
//
// var newCleanedUsers = status.ShutdownRoom?.KickedUsers?.Except(alreadyCleanedUsers).ToList();
// if (newCleanedUsers is not null) {
// alreadyCleanedUsers.AddRange(newCleanedUsers);
// foreach (var user in newCleanedUsers) {
// if (deleteRequest.DeleteRequest.SuspendLocalUsers) {
// // await Homeserver.Admin.(user);
// }
//
// if (deleteRequest.DeleteRequest.QuarantineLocalUserMedia) {
// await Homeserver.Admin.QuarantineMediaByUserId(user);
// }
//
// if (deleteRequest.DeleteRequest.DeleteLocalUserMedia) {
// var userMedia = Homeserver.Admin.GetUserMediaEnumerableAsync(user);
// await foreach (var mediaEntry in userMedia) {
// await Homeserver.Admin.DeleteMediaById(mediaEntry.MediaId);
// }
// }
// }
// }
// }
// }
// }
private readonly Dictionary validOrderBy = new() {
{ "name", "Room name" },
{ "canonical_alias", "Main alias address" },
{ "joined_members", "Number of members (reversed)" },
{ "joined_local_members", "Number of local members (reversed)" },
{ "version", "Room version" },
{ "creator", "Creator of the room" },
{ "encryption", "End-to-end encryption algorithm" },
{ "federatable", "Is room federated" },
{ "public", "Visibility in room list" },
{ "join_rules", "Join rules" },
{ "guest_access", "Guest access" },
{ "history_visibility", "Visibility of history" },
{ "state_events", "Number of state events" }
};
private class RoomInfo : SynapseAdminRoomListResult.SynapseAdminRoomListResultRoom {
public List? LocalMembers { get; set; }
}
}