using System.Collections.Frozen;
using ArcaneLibs.Extensions;
using Elastic.Apm;
using Elastic.Apm.Api;
using LibMatrix.Homeservers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ModAS.Server.Attributes;
using ModAS.Server.Services;
using MxApiExtensions.Services;
namespace ModAS.Server.Controllers.Debug;
///
/// Provides debugging endpoints.
///
///
///
///
[ApiController]
[UserAuth(AnyRoles = AuthRoles.Developer | AuthRoles.Administrator)]
public class DebugController(ModASConfiguration config, UserProviderService authHsProvider, RoomContextService roomContextService) : ControllerBase {
///
/// Returns a JSON object containing the request and response headers.
///
/// JSON object with request and partial response headers.
[HttpGet("/_matrix/_modas/debug")]
public IActionResult Index() {
return Ok(new {
Request = Request.Headers,
Response = Response.Headers
});
}
///
/// Returns a JSON object containing the configuration.
///
///
[HttpGet("/_matrix/_modas/debug/config")]
public IActionResult Config() {
return Ok(config);
}
[HttpGet("/_matrix/_modas/debug/known_users")]
public IActionResult KnownUsers() {
return Ok(authHsProvider.KnownUsers.Keys);
}
[HttpGet("/_matrix/_modas/debug/test_locate_users")]
public async IAsyncEnumerable TestLocateUsers([FromQuery] string startUser) {
List foundUsers = (await authHsProvider.GetValidUsers()).Select(x => x.Value).ToList();
if (!foundUsers.Any(x => x.WhoAmI.UserId == startUser)) {
foundUsers.Add(await authHsProvider.GetImpersonatedHomeserver(startUser));
}
List processedRooms = [], processedUsers = [];
var foundNew = true;
while (foundNew) {
var span1 = currentTransaction.StartSpan("iterateUsers", ApiConstants.TypeApp);
foundNew = false;
var usersToProcess = foundUsers.Where(x => !processedUsers.Any(y => x.WhoAmI.UserId == y)).ToFrozenSet();
Console.WriteLine($"Got {usersToProcess.Count} users: {string.Join(", ", usersToProcess)}");
var rooms = usersToProcess.Select(async x => await x.GetJoinedRooms());
var roomLists = rooms.ToAsyncEnumerable();
await foreach (var roomList in roomLists) {
if (roomList is null) continue;
foreach (var room in roomList) {
if (processedRooms.Contains(room.RoomId)) continue;
processedRooms.Add(room.RoomId);
var roomMembers = await room.GetMembersListAsync(false);
foreach (var roomMember in roomMembers) {
if (roomMember.StateKey.EndsWith(':' + config.ServerName) && !foundUsers.Any(x => x.WhoAmI.UserId == roomMember.StateKey)) {
foundUsers.Add(await authHsProvider.GetImpersonatedHomeserver(roomMember.StateKey));
foundNew = true;
yield return roomMember.StateKey;
}
}
}
}
// await foreach (var task in tasks) {
// if (task is null) continue;
// foreach (var user in task) {
// if (foundUsers.Contains(user)) continue;
// foundUsers.Add(user);
// foundNew = true;
// yield return user;
// }
// }
span1.End();
}
}
[HttpGet("/_matrix/_modas/debug/room_contexts")]
public IActionResult RoomContexts() {
return Ok(roomContextService.RoomContexts.Values);
}
[HttpGet("/_matrix/_modas/debug/room_contexts/{roomId}")]
public async Task RoomContext(string roomId) {
var roomContext = await roomContextService.GetRoomContext(roomId);
if (roomContext is null) return NotFound("Room not found");
return Ok(roomContext);
}
[HttpGet("/_matrix/_modas/debug/room_contexts/by_user/{userId}")]
public async IAsyncEnumerable RoomContextByUser(string userId) {
var user = await authHsProvider.GetImpersonatedHomeserver(userId);
var rooms = await user.GetJoinedRooms();
var contexts = rooms.Select(x => roomContextService.GetRoomContext(x.RoomId)).ToAsyncEnumerable();
await foreach (var context in contexts) {
if (context is null) continue;
yield return context;
}
}
private static ITransaction currentTransaction => Agent.Tracer.CurrentTransaction;
}