mirror of
https://github.com/spacebarchat/server.git
synced 2026-03-30 20:25:40 +00:00
Clean up admin api a bit
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Db\Spacebar.Models.Db.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<PackageReference Include="Spacebar.Models.Db" Version="*-preview*" Condition="'$(ContinuousIntegrationBuild)'=='true'"/>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.AdminApi\Spacebar.Models.AdminApi.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<PackageReference Include="Spacebar.Models.AdminApi" Version="*-preview*" Condition="'$(ContinuousIntegrationBuild)'=='true'"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,26 @@
|
||||
using Spacebar.Models.AdminApi;
|
||||
|
||||
namespace Spacebar.DataMappings.AdminApi;
|
||||
|
||||
public static class User
|
||||
{
|
||||
// public static UserModel ToPartialUser(this Models.Db.Models.User user)
|
||||
// {
|
||||
// return new PartialUser() {
|
||||
// Id = user.Id,
|
||||
// Discriminator = user.Discriminator,
|
||||
// Username = user.Username,
|
||||
// AccentColor = user.AccentColor,
|
||||
// Avatar = user.Avatar,
|
||||
// AvatarDecorationData = user.AvatarDecorationData,
|
||||
// Banner = user.Banner,
|
||||
// Bot = user.Bot,
|
||||
// Collectibles = user.Collectibles,
|
||||
// DisplayNameStyles = user.DisplayNameStyles,
|
||||
// // GlobalName = x.GlobalName,
|
||||
// PrimaryGuild = user.PrimaryGuild,
|
||||
// PublicFlags = user.PublicFlags,
|
||||
// System = user.System,
|
||||
// };
|
||||
// }
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Db\Spacebar.Models.Db.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Db\Spacebar.Models.Db.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<PackageReference Include="Spacebar.Models.Db" Version="*-preview*" Condition="'$(ContinuousIntegrationBuild)'=='true'"/>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Generic\Spacebar.Models.Generic.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Generic\Spacebar.Models.Generic.csproj" Condition="'$(ContinuousIntegrationBuild)'!='true'"/>
|
||||
<PackageReference Include="Spacebar.Models.Generic" Version="*-preview*" Condition="'$(ContinuousIntegrationBuild)'=='true'"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Diagnostics;
|
||||
using ArcaneLibs;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Spacebar.AdminApi.Extensions;
|
||||
using Spacebar.Interop.Authentication;
|
||||
using Spacebar.Interop.Authentication.AspNetCore;
|
||||
using Spacebar.Interop.Replication.Abstractions;
|
||||
using Spacebar.Models.AdminApi;
|
||||
using Spacebar.Models.Db.Contexts;
|
||||
|
||||
namespace Spacebar.AdminApi.Controllers.TestControllers;
|
||||
|
||||
[ApiController]
|
||||
public class IpcTestController(
|
||||
ILogger<UserController> logger,
|
||||
SpacebarAuthenticationConfiguration config,
|
||||
SpacebarDbContext db,
|
||||
IServiceProvider sp,
|
||||
SpacebarAspNetAuthenticationService auth,
|
||||
ISpacebarReplication replication
|
||||
) : ControllerBase {
|
||||
[HttpGet("test")]
|
||||
public async IAsyncEnumerable<string> Test() {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
var guildId = "1006649183970562092";
|
||||
// var roleId = "1006706520514028812"; //Administrator
|
||||
var roleId = "1391303296148639051"; //Spacebar Maintainer
|
||||
// int color = 16711680; //Administrator
|
||||
int color = 99839; //Spacebar Maintainer
|
||||
|
||||
int framerate = 30;
|
||||
float delay = 1000f / framerate;
|
||||
var secondsPerRotation = 6.243f;
|
||||
// use delay, 255f = one rotation, lengthFactor = iterations to make a full rotation
|
||||
var lengthFactor = (secondsPerRotation * 1000f / delay);
|
||||
Console.WriteLine("Length factor: {0}, RPS: {1}", lengthFactor, 0);
|
||||
var re = new RainbowEnumerator(lengthFactor: lengthFactor, offset: color, skip: 1);
|
||||
var sw = Stopwatch.StartNew();
|
||||
while (true) {
|
||||
var clr = re.Next();
|
||||
color = clr.r << 16 | clr.g << 8 | clr.b;
|
||||
await replication.SendAsync(new() {
|
||||
Event = "GUILD_ROLE_UPDATE",
|
||||
GuildId = guildId,
|
||||
Origin = "Admin API (GET /users/test)",
|
||||
Payload = new {
|
||||
guild_id = guildId,
|
||||
role = new {
|
||||
id = roleId,
|
||||
guild_id = guildId,
|
||||
color,
|
||||
hoist = false,
|
||||
managed = false,
|
||||
mentionable = true,
|
||||
name = "Spacebar Maintainer",
|
||||
permissions = "8",
|
||||
position = 5,
|
||||
unicode_emoji = "",
|
||||
flags = 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
yield return $"{clr.r:X2} {clr.g:X2} {clr.b:X2} | {color:X8} | {sw.Elapsed} (waiting {Math.Max(0, (int)delay - (int)sw.ElapsedMilliseconds)} out of {delay} ms)";
|
||||
await Task.Delay(Math.Max(0, (int)delay - (int)sw.ElapsedMilliseconds));
|
||||
sw.Restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@ public class UserController(
|
||||
SpacebarAspNetAuthenticationService auth,
|
||||
ISpacebarReplication replication
|
||||
) : ControllerBase {
|
||||
/// <summary>
|
||||
/// Get all users
|
||||
/// </summary>
|
||||
/// <returns>List of user objects</returns>
|
||||
[HttpGet]
|
||||
public async IAsyncEnumerable<UserModel> Get() {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
@@ -77,6 +81,63 @@ public class UserController(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get user by ID
|
||||
/// </summary>
|
||||
/// <param name="id">User ID</param>
|
||||
/// <returns>User object</returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<UserModel> GetById(string id) {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
return await db.Users
|
||||
.Include(user => user.ApplicationBotUser)
|
||||
.Include(user => user.MessageAuthors)
|
||||
.Include(user => user.Sessions)
|
||||
.Include(user => user.Templates)
|
||||
.Include(user => user.VoiceStates)
|
||||
.Include(user => user.Guilds)
|
||||
.Select(x => new UserModel {
|
||||
Id = x.Id,
|
||||
Username = x.Username,
|
||||
Discriminator = x.Discriminator,
|
||||
Avatar = x.Avatar,
|
||||
AccentColor = x.AccentColor,
|
||||
Banner = x.Banner,
|
||||
ThemeColors = x.ThemeColors,
|
||||
Pronouns = x.Pronouns,
|
||||
Phone = x.Phone,
|
||||
Desktop = x.Desktop,
|
||||
Mobile = x.Mobile,
|
||||
Premium = x.Premium,
|
||||
PremiumType = x.PremiumType,
|
||||
Bot = x.Bot,
|
||||
Bio = x.Bio,
|
||||
System = x.System,
|
||||
NsfwAllowed = x.NsfwAllowed,
|
||||
MfaEnabled = x.MfaEnabled,
|
||||
WebauthnEnabled = x.WebauthnEnabled,
|
||||
CreatedAt = x.CreatedAt,
|
||||
PremiumSince = x.PremiumSince,
|
||||
Verified = x.Verified,
|
||||
Disabled = x.Disabled,
|
||||
Deleted = x.Deleted,
|
||||
Email = x.Email,
|
||||
Flags = x.Flags,
|
||||
PublicFlags = x.PublicFlags,
|
||||
Rights = x.Rights,
|
||||
ApplicationBotUser = x.ApplicationBotUser == null ? null : new(),
|
||||
ConnectedAccounts = new List<UserModel.ConnectedAccountModel>(),
|
||||
MessageCount = x.MessageAuthors.Count, // This property is weirdly named due to scaffolding, might patch later
|
||||
SessionCount = x.Sessions.Count,
|
||||
TemplateCount = x.Templates.Count,
|
||||
VoiceStateCount = x.VoiceStates.Count,
|
||||
GuildCount = x.Guilds.Count,
|
||||
OwnedGuildCount = x.Guilds.Count(g => g.OwnerId == x.Id)
|
||||
})
|
||||
.SingleAsync(x => x.Id == id);
|
||||
}
|
||||
|
||||
[HttpGet("{id}/delete")]
|
||||
public async IAsyncEnumerable<AsyncActionResult> DeleteUser(string id, [FromQuery] int messageDeleteChunkSize = 100) {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
@@ -171,129 +232,6 @@ public class UserController(
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("duplicate")]
|
||||
public async Task<IActionResult> Duplicate() {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
var msg = db.Messages.First();
|
||||
var channels = db.Channels.Select(x => new { x.Id, x.GuildId }).ToList();
|
||||
int count = 1;
|
||||
while (true) {
|
||||
foreach (var channel in channels) {
|
||||
var newMsg = new Message {
|
||||
Id = $"{Random.Shared.NextInt64()}",
|
||||
ChannelId = channel.Id,
|
||||
GuildId = channel.GuildId,
|
||||
AuthorId = msg.AuthorId,
|
||||
Content = msg.Content,
|
||||
MemberId = msg.MemberId,
|
||||
Timestamp = msg.Timestamp,
|
||||
EditedTimestamp = msg.EditedTimestamp,
|
||||
Tts = msg.Tts,
|
||||
MentionEveryone = msg.MentionEveryone,
|
||||
Attachments = msg.Attachments,
|
||||
Embeds = msg.Embeds,
|
||||
Reactions = msg.Reactions,
|
||||
Nonce = msg.Nonce,
|
||||
PinnedAt = msg.PinnedAt,
|
||||
Type = msg.Type,
|
||||
};
|
||||
db.Messages.Add(newMsg);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count % 100 == 0) {
|
||||
await db.SaveChangesAsync();
|
||||
await db.Database.ExecuteSqlRawAsync("VACUUM FULL messages");
|
||||
}
|
||||
|
||||
if (count >= 100_000) {
|
||||
await db.SaveChangesAsync();
|
||||
await db.Database.ExecuteSqlRawAsync("VACUUM FULL messages");
|
||||
await db.Database.ExecuteSqlRawAsync("REINDEX TABLE messages");
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("duplicate/{id}")]
|
||||
public async Task<IActionResult> DuplicateMessage(ulong id, [FromQuery] int count = 100) {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
var msg = await db.Messages.FindAsync(id.ToString());
|
||||
int createdCount = 1;
|
||||
while (true) {
|
||||
var newMsg = new Message {
|
||||
Id = $"{Random.Shared.NextInt64()}",
|
||||
ChannelId = msg.ChannelId,
|
||||
GuildId = msg.GuildId,
|
||||
AuthorId = msg.AuthorId,
|
||||
Content = msg.Content,
|
||||
MemberId = msg.MemberId,
|
||||
Timestamp = msg.Timestamp,
|
||||
EditedTimestamp = msg.EditedTimestamp,
|
||||
Tts = msg.Tts,
|
||||
MentionEveryone = msg.MentionEveryone,
|
||||
Attachments = msg.Attachments,
|
||||
Embeds = msg.Embeds,
|
||||
Reactions = msg.Reactions,
|
||||
Nonce = msg.Nonce,
|
||||
PinnedAt = msg.PinnedAt,
|
||||
Type = msg.Type,
|
||||
};
|
||||
db.Messages.Add(newMsg);
|
||||
createdCount++;
|
||||
|
||||
if (createdCount % 100 == 0) {
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (createdCount >= count) {
|
||||
await db.SaveChangesAsync();
|
||||
await db.Database.ExecuteSqlRawAsync("VACUUM FULL messages");
|
||||
await db.Database.ExecuteSqlRawAsync("REINDEX TABLE messages");
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
await db.Database.ExecuteSqlRawAsync("VACUUM FULL messages");
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("truncate_messages")]
|
||||
public async Task TruncateMessages() {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
var channels = db.Channels.Select(x => new { x.Id, x.GuildId }).ToList();
|
||||
|
||||
var ss = new SemaphoreSlim(12, 12);
|
||||
|
||||
async Task TruncateChannelMessages(string channelId, string guildId) {
|
||||
await ss.WaitAsync();
|
||||
var tasks = Enumerable.Range(0, 99).Select(i => Task.Run(async () => {
|
||||
await using var scope = sp.CreateAsyncScope();
|
||||
await using var _db = scope.ServiceProvider.GetRequiredService<SpacebarDbContext>();
|
||||
// set timeout
|
||||
_db.Database.SetCommandTimeout(6000);
|
||||
await _db.Database.ExecuteSqlAsync($"""
|
||||
DELETE FROM messages
|
||||
WHERE channel_id = '{channelId}'
|
||||
AND guild_id = '{guildId}'
|
||||
AND id LIKE '%{i:00}';
|
||||
""");
|
||||
|
||||
Console.WriteLine($"Truncated messages for {channelId} in {guildId} ending with {i}");
|
||||
})).ToList();
|
||||
await Task.WhenAll(tasks);
|
||||
ss.Release();
|
||||
}
|
||||
|
||||
var tasks = channels.Select(c => TruncateChannelMessages(c.Id, c.GuildId)).ToList();
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<T> AggregateAsyncEnumerablesWithoutOrder<T>(params IEnumerable<IAsyncEnumerable<T>> enumerables) {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
@@ -347,75 +285,4 @@ public class UserController(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// "op": 0,
|
||||
// "t": "GUILD_ROLE_UPDATE",
|
||||
// "d": {
|
||||
// "guild_id": "1006649183970562092",
|
||||
// "role": {
|
||||
// "id": "1006706520514028812",
|
||||
// "guild_id": "1006649183970562092",
|
||||
// "color": 16711680,
|
||||
// "hoist": true,
|
||||
// "managed": false,
|
||||
// "mentionable": true,
|
||||
// "name": "Adminstrator",
|
||||
// "permissions": "9",
|
||||
// "position": 5,
|
||||
// "unicode_emoji": "💖",
|
||||
// "flags": 0
|
||||
// }
|
||||
// },
|
||||
// "s": 38
|
||||
// }
|
||||
|
||||
[HttpGet("test")]
|
||||
public async IAsyncEnumerable<string> Test() {
|
||||
(await auth.GetCurrentUserAsync(Request)).GetRights().AssertHasAllRights(SpacebarRights.Rights.OPERATOR);
|
||||
|
||||
var guildId = "1006649183970562092";
|
||||
// var roleId = "1006706520514028812"; //Administrator
|
||||
var roleId = "1391303296148639051"; //Spacebar Maintainer
|
||||
// int color = 16711680; //Administrator
|
||||
int color = 99839; //Spacebar Maintainer
|
||||
|
||||
int framerate = 30;
|
||||
float delay = 1000f / framerate;
|
||||
var secondsPerRotation = 6.243f;
|
||||
// use delay, 255f = one rotation, lengthFactor = iterations to make a full rotation
|
||||
var lengthFactor = (secondsPerRotation * 1000f / delay);
|
||||
Console.WriteLine("Length factor: {0}, RPS: {1}", lengthFactor, 0);
|
||||
var re = new RainbowEnumerator(lengthFactor: lengthFactor, offset: color, skip: 1);
|
||||
var sw = Stopwatch.StartNew();
|
||||
while (true) {
|
||||
var clr = re.Next();
|
||||
color = clr.r << 16 | clr.g << 8 | clr.b;
|
||||
await replication.SendAsync(new() {
|
||||
Event = "GUILD_ROLE_UPDATE",
|
||||
GuildId = guildId,
|
||||
Origin = "Admin API (GET /users/test)",
|
||||
Payload = new {
|
||||
guild_id = guildId,
|
||||
role = new {
|
||||
id = roleId,
|
||||
guild_id = guildId,
|
||||
color,
|
||||
hoist = false,
|
||||
managed = false,
|
||||
mentionable = true,
|
||||
name = "Spacebar Maintainer",
|
||||
permissions = "8",
|
||||
position = 5,
|
||||
unicode_emoji = "",
|
||||
flags = 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
yield return $"{clr.r:X2} {clr.g:X2} {clr.b:X2} | {color:X8} | {sw.Elapsed} (waiting {Math.Max(0, (int)delay - (int)sw.ElapsedMilliseconds)} out of {delay} ms)";
|
||||
await Task.Delay(Math.Max(0, (int)delay - (int)sw.ElapsedMilliseconds));
|
||||
sw.Restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<Platform Name="x86" />
|
||||
</Configurations>
|
||||
<Folder Name="/DataMappings/">
|
||||
<Project Path="DataMappings/Spacebar.DataMappings.AdminApi/Spacebar.DataMappings.AdminApi.csproj" />
|
||||
<Project Path="DataMappings/Spacebar.DataMappings.Generic/Spacebar.DataMappings.Generic.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Interop/">
|
||||
|
||||
Reference in New Issue
Block a user