diff --git a/extra/admin-api/Spacebar.Offload/Controllers/Op14Controller.cs b/extra/admin-api/Spacebar.Offload/Controllers/Op14Controller.cs
index 1102bec2..95998151 100644
--- a/extra/admin-api/Spacebar.Offload/Controllers/Op14Controller.cs
+++ b/extra/admin-api/Spacebar.Offload/Controllers/Op14Controller.cs
@@ -1,6 +1,11 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text.Json;
+using System.Text.Json.Serialization;
+using ArcaneLibs.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
+using Spacebar.DataMappings.Generic;
using Spacebar.GatewayOffload.Extensions.Db;
using Spacebar.Interop.Authentication.AspNetCore;
using Spacebar.Interop.Replication.Abstractions;
@@ -29,13 +34,87 @@ public class Op14Controller(ILogger<Op12Controller> logger, SpacebarAspNetAuthen
yield break;
}
+ var memberList = new List<IMemberListEntry>();
+
// Fetch hoisted roles for the guild to define groups
var hoistedRoles = await db.Roles
.AsNoTracking()
.Where(r => r.GuildId == payload.GuildId && r.Hoist)
.OrderByDescending(r => r.Position)
- .Select(r => new { r.Id })
+ // .Select(r => r.Id)
.ToListAsync();
+
+ logger.LogDebug("Got hoisted roles: {roleIds}", hoistedRoles.Select(x => x.Id).ToList());
+ List<long> handledRoles = [];
+ foreach (var roleObj in hoistedRoles) {
+ var role = roleObj.Id;
+ var members = await db.Members.AsNoTracking()
+ .Include(x => x.IdNavigation)
+ .Where(x =>
+ x.GuildId == payload.GuildId
+ && x.Roles.Any(r => r.Id == role)
+ && !x.Roles.Any(r => handledRoles.Contains(r.Id))
+ // and finally, filter by online
+ && x.IdNavigation.Sessions.Any(s => s.Status != "offline" && s.Status != "invisible" && s.Status != "unknown")
+ )
+ .OrderBy(x => x.Nick ?? x.IdNavigation.Username).ToListAsync();
+
+ logger.LogInformation("Got {count} potential members for group {group} ({groupName}):\n - {members}",
+ members.Count, role, roleObj.Name, string.Join("\n - ", members.Take(10).Select(x => $"{x.Id} {x.Nick ?? x.IdNavigation.Tag}"))
+ );
+
+ memberList.Add(new RoleEntry() { Id = role.ToString(), Count = members.Count });
+ memberList.AddRange(members.Select(m => (IMemberListEntry)new MemberEntry() { Member = m.ToPublicMember() }));
+
+ handledRoles.Add(role);
+ }
+
+ // online members
+ var onlineMembers = await db.Members.AsNoTracking()
+ .Include(x => x.IdNavigation)
+ // .ThenInclude(x=>x.Sessions)
+ .Where(x =>
+ x.GuildId == payload.GuildId
+ && !x.Roles.Any(r => handledRoles.Contains(r.Id))
+ // and finally, filter by online
+ && x.IdNavigation.Sessions.Any(s => s.Status != "offline" && s.Status != "invisible" && s.Status != "unknown")
+ )
+ .OrderBy(x => x.Nick ?? x.IdNavigation.Username).ToListAsync();
+
+ logger.LogInformation("Got {count} potential members for group {group} ({groupName}):\n - {members}",
+ onlineMembers.Count, "online", "online", string.Join("\n - ", onlineMembers.Take(10).Select(x => $"{x.Id} {x.Nick ?? x.IdNavigation.Tag}"))
+ );
+
+ if (onlineMembers.Count > 0) {
+ memberList.Add(new RoleEntry() { Id = "online", Count = onlineMembers.Count });
+ memberList.AddRange(onlineMembers.Select(m => (IMemberListEntry)new MemberEntry() { Member = m.ToPublicMember() }));
+ }
+
+
+ if (memberList.Count < 2000) {
+ logger.LogInformation("Less than 2000 members, including offline members...");
+ var offlineMembers = await db.Members.AsNoTracking()
+ .Include(x => x.IdNavigation)
+ // .ThenInclude(x=>x.Sessions)
+ .Where(x =>
+ x.GuildId == payload.GuildId
+ && !x.Roles.Any(r => handledRoles.Contains(r.Id))
+ // and finally, filter by online
+ && (x.IdNavigation.Sessions.Any(s => s.Status == "offline" || s.Status == "invisible" || s.Status == "unknown") || !x.IdNavigation.Sessions.Any())
+ )
+ .OrderBy(x => x.Nick ?? x.IdNavigation.Username).ToListAsync();
+
+ logger.LogInformation("Got {count} potential members for group {group} ({groupName}):\n - {members}",
+ offlineMembers.Count, "offline", "offline", string.Join("\n - ", offlineMembers.Take(10).Select(x => $"{x.Id} {x.Nick ?? x.IdNavigation.Tag}"))
+ );
+
+ if (offlineMembers.Count > 0) {
+ memberList.Add(new RoleEntry() { Id = "offline", Count = offlineMembers.Count });
+ memberList.AddRange(offlineMembers.Select(m => (IMemberListEntry)new MemberEntry() { Member = m.ToPublicMember() }));
+ }
+ }
+
+ logger.LogInformation("Got member list with {count} total nodes", memberList.Count);
}
private async Task<string?> GetMemberListIdAsync(SpacebarDbContext db, long guildId, long channelId) {
@@ -48,4 +127,19 @@ public class Op14Controller(ILogger<Op12Controller> logger, SpacebarAspNetAuthen
return null; // TODO
}
+}
+
+internal interface IMemberListEntry { }
+
+internal struct RoleEntry : IMemberListEntry {
+ [JsonPropertyName("id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
+ public string Id { get; set; }
+
+ [JsonPropertyName("count")]
+ public int Count { get; set; }
+}
+
+internal struct MemberEntry : IMemberListEntry {
+ [JsonPropertyName("member")]
+ public Member Member { get; set; }
}
\ No newline at end of file
|