diff --git a/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj b/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj
new file mode 100644
index 0000000..f07ebda
--- /dev/null
+++ b/BugMine.DevTools.CLI/BugMine.DevTools.CLI.csproj
@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk.Worker">
+
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <UserSecretsId>dotnet-BugMine.DevTools.CLI-68C1536A-FE5E-4724-8406-B1B1430F105A</UserSecretsId>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\BugMine.Sdk\BugMine.Sdk.csproj" />
+ </ItemGroup>
+</Project>
diff --git a/BugMine.DevTools.CLI/Program.cs b/BugMine.DevTools.CLI/Program.cs
new file mode 100644
index 0000000..6e5bead
--- /dev/null
+++ b/BugMine.DevTools.CLI/Program.cs
@@ -0,0 +1,9 @@
+using BugMine.DevTools.CLI;
+using BugMine.Web.Classes;
+
+var builder = Host.CreateApplicationBuilder(args);
+builder.Services.AddBugMine(new() { AppName = "BugMine DevTools CLI" });
+builder.Services.AddHostedService<Worker>();
+
+var host = builder.Build();
+host.Run();
\ No newline at end of file
diff --git a/BugMine.DevTools.CLI/Properties/launchSettings.json b/BugMine.DevTools.CLI/Properties/launchSettings.json
new file mode 100644
index 0000000..43460c6
--- /dev/null
+++ b/BugMine.DevTools.CLI/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "BugMine.DevTools.CLI": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "DOTNET_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/BugMine.DevTools.CLI/Worker.cs b/BugMine.DevTools.CLI/Worker.cs
new file mode 100644
index 0000000..8cd931e
--- /dev/null
+++ b/BugMine.DevTools.CLI/Worker.cs
@@ -0,0 +1,123 @@
+using System.Text.Json;
+using ArcaneLibs.Extensions;
+using BugMine.Web.Classes;
+using LibMatrix.EventTypes.Spec.State;
+using LibMatrix.Responses;
+using LibMatrix.Services;
+
+namespace BugMine.DevTools.CLI;
+
+public class Worker(ILogger<Worker> logger, HomeserverProviderService hsProvider) : BackgroundService {
+ private readonly ILogger<Worker> _logger = logger;
+ private BugMineClient? Client { get; set; }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
+ if (!File.Exists("auth.json")) {
+ Console.Write("Homeserver: ");
+ var homeserver = Console.ReadLine()!;
+ Console.Write("Username: ");
+ var username = Console.ReadLine()!;
+ Console.Write("Password: ");
+ var password = Console.ReadLine()!;
+
+ var login = await hsProvider.Login(homeserver, username, password);
+ await File.WriteAllTextAsync("auth.json", login.ToJson(), stoppingToken);
+ }
+
+ var auth = await JsonSerializer.DeserializeAsync<LoginResponse>(File.OpenRead("auth.json"));
+ Client = new BugMineClient(await hsProvider.GetAuthenticatedWithToken(auth.Homeserver, auth.AccessToken, useGeneric: true));
+
+ while (!stoppingToken.IsCancellationRequested) {
+ Console.WriteLine("""
+ 1) List all projects
+ 2) Create 500 projects
+ 3) Destroy all projects
+ 4) Get room count
+ """);
+
+ var input = Console.ReadKey();
+ Console.WriteLine();
+ switch (input.Key) {
+ case ConsoleKey.D1: {
+ if (Client is null) {
+ _logger.LogError("No client available.");
+ break;
+ }
+
+ var projects = Client.GetProjects();
+ await foreach (var project in projects) {
+ Console.WriteLine(project.ToJson(indent: false));
+ }
+
+ break;
+ }
+ case ConsoleKey.D2: {
+ if (Client is null) {
+ _logger.LogError("No client available.");
+ break;
+ }
+
+ await MassCreateProjects();
+ break;
+ }
+ case ConsoleKey.D3: {
+ if (Client is null) {
+ _logger.LogError("No client available.");
+ break;
+ }
+
+ await DestroyAllProjects();
+ break;
+ }
+ case ConsoleKey.D4: {
+ if (Client is null) {
+ _logger.LogError("No client available.");
+ break;
+ }
+
+ var rooms = await Client.Homeserver.GetJoinedRooms();
+ Console.WriteLine(rooms.Count());
+ break;
+ }
+ }
+ }
+ }
+
+ private async Task DestroyAllProjects() {
+ var ss = new SemaphoreSlim(4, 4);
+ await foreach (var proj in Client.Homeserver.GetJoinedRoomsByType(null!)) {
+ if (proj.RoomId == "!UktPWOzit8gmms5FQ6:conduit.matrixunittests.rory.gay") continue;
+ Task.Run(async () => {
+ // await ss.WaitAsync();
+ await proj.SendStateEventAsync(RoomNameEventContent.EventId, new RoomNameEventContent() {
+ Name = "Disbanded BugMine project."
+ });
+ await proj.SendStateEventAsync(RoomJoinRulesEventContent.EventId, new RoomJoinRulesEventContent() {
+ JoinRule = RoomJoinRulesEventContent.JoinRules.Private
+ });
+ await proj.SendStateEventAsync(RoomCanonicalAliasEventContent.EventId, new RoomCanonicalAliasEventContent() {
+ Alias = null
+ });
+ await proj.LeaveAsync("Disbanded room.");
+ // ss.Release();
+ });
+ }
+ }
+
+ private async Task MassCreateProjects() {
+ // var rooms = await Client.Homeserver.GetJoinedRooms();
+ // List<string> roomNames = (await Task.WhenAll(rooms.Select(x => x.GetNameAsync()))).Where(x => x != null).ToList();
+ for (int i = 0; i < 500; i++) {
+ Task.Run(async () => {
+ // var randomName = roomNames[Random.Shared.Next(roomNames.Count)];
+ var proj = await Client.CreateProject(new() {
+ Name = /*randomName + */Guid.NewGuid().ToString()[..8]
+ });
+
+ // await proj.CreateIssue(new() {
+ // Name = "meow"
+ // });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/BugMine.DevTools.CLI/appsettings.Development.json b/BugMine.DevTools.CLI/appsettings.Development.json
new file mode 100644
index 0000000..b2dcdb6
--- /dev/null
+++ b/BugMine.DevTools.CLI/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/BugMine.DevTools.CLI/appsettings.json b/BugMine.DevTools.CLI/appsettings.json
new file mode 100644
index 0000000..b2dcdb6
--- /dev/null
+++ b/BugMine.DevTools.CLI/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/BugMine.DevTools.CLI/auth.json b/BugMine.DevTools.CLI/auth.json
new file mode 100644
index 0000000..e42970e
--- /dev/null
+++ b/BugMine.DevTools.CLI/auth.json
@@ -0,0 +1,6 @@
+{
+ "access_token": "wODFOcoMnoruFaUGrjWibY80sVVEqSUg",
+ "device_id": "VHX31Cw6jz",
+ "home_server": "conduit.matrixunittests.rory.gay",
+ "user_id": "@meow:conduit.matrixunittests.rory.gay"
+}
\ No newline at end of file
|