about summary refs log tree commit diff
path: root/BugMine.Sdk
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-04-20 23:48:43 +0200
committerRory& <root@rory.gay>2024-04-20 23:48:43 +0200
commit68fe1a2284045908d92ef06c1c26cd937ded784e (patch)
tree71144f404f060888dcc5e4036e038abe857adc4e /BugMine.Sdk
parentStart adding pages (diff)
downloadBugMine-68fe1a2284045908d92ef06c1c26cd937ded784e.tar.xz
Add basic project management
Diffstat (limited to 'BugMine.Sdk')
-rw-r--r--BugMine.Sdk/BugMine.Sdk.csproj19
-rw-r--r--BugMine.Sdk/BugMineClient.cs55
-rw-r--r--BugMine.Sdk/BugMineIssue.cs12
-rw-r--r--BugMine.Sdk/BugMineProject.cs43
-rw-r--r--BugMine.Sdk/Events/State/ProjectInfo.cs11
-rw-r--r--BugMine.Sdk/Events/Timeline/BugMineIssueComment.cs11
-rw-r--r--BugMine.Sdk/Events/Timeline/BugMineIssueData.cs12
-rw-r--r--BugMine.Sdk/ServiceInstaller.cs25
8 files changed, 188 insertions, 0 deletions
diff --git a/BugMine.Sdk/BugMine.Sdk.csproj b/BugMine.Sdk/BugMine.Sdk.csproj
new file mode 100644

index 0000000..092683c --- /dev/null +++ b/BugMine.Sdk/BugMine.Sdk.csproj
@@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions"> + <HintPath>..\..\..\..\.nuget\packages\microsoft.extensions.dependencyinjection.abstractions\8.0.0\lib\net8.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath> + </Reference> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\LibMatrix\LibMatrix\LibMatrix.csproj" /> + </ItemGroup> + +</Project> diff --git a/BugMine.Sdk/BugMineClient.cs b/BugMine.Sdk/BugMineClient.cs new file mode 100644
index 0000000..be80c3a --- /dev/null +++ b/BugMine.Sdk/BugMineClient.cs
@@ -0,0 +1,55 @@ +using System.Text.RegularExpressions; +using ArcaneLibs.Extensions; +using LibMatrix.Homeservers; +using LibMatrix.Responses; + +namespace BugMine.Web.Classes; + +public class BugMineClient(AuthenticatedHomeserverGeneric homeserver) { + public AuthenticatedHomeserverGeneric Homeserver { get; } = homeserver; + + public async IAsyncEnumerable<BugMineProject> GetProjects() { + List<Task<BugMineProject>> tasks = []; + await foreach (var room in homeserver.GetJoinedRoomsByType(BugMineProject.RoomType)) { + tasks.Add(room.AsBugMineProject()); + } + + var results = tasks.ToAsyncEnumerable(); + await foreach (var result in results) { + yield return result; + } + } + + public async Task<BugMineProject> CreateProject(ProjectInfo request) { + var alias = string.Join('_', Regex.Matches(request.Name, @"[a-zA-Z0-9]+").Select(x => x.Value))+"-bugmine"; + + var crr = new CreateRoomRequest() { + CreationContent = new() { + ["type"] = "gay.rory.bugmine.project" + }, + Name = $"{request.Name} (BugMine project)", + RoomAliasName = alias + }; + + var response = await Homeserver.CreateRoom(crr); + await response.SendStateEventAsync(ProjectInfo.EventId, request); + + return await response.AsBugMineProject(); + } + + public async Task<BugMineProject?> GetProject(string projectSlug) { + if (projectSlug.StartsWith('!')) { + var room = homeserver.GetRoom(projectSlug); + if (room == null) return null; + + return await (await room.AsBugMineProject()).InitializeAsync(); + } + else { + var alias = $"#{projectSlug}"; + var resolveResult = await Homeserver.ResolveRoomAliasAsync(alias); + if (string.IsNullOrEmpty(resolveResult?.RoomId)) return null; //TODO: fallback to finding via joined rooms' canonical alias event? + + return await (await homeserver.GetRoom(resolveResult.RoomId).AsBugMineProject()).InitializeAsync(); + } + } +} \ No newline at end of file diff --git a/BugMine.Sdk/BugMineIssue.cs b/BugMine.Sdk/BugMineIssue.cs new file mode 100644
index 0000000..6cf3409 --- /dev/null +++ b/BugMine.Sdk/BugMineIssue.cs
@@ -0,0 +1,12 @@ +using LibMatrix; +using LibMatrix.RoomTypes; + +namespace BugMine.Web.Classes; + +public class BugMineIssue(GenericRoom room, StateEventResponse data) { + public GenericRoom Room { get; } = room; + public StateEventResponse Data { get; } = data; + // public async IAsyncEnumerable<StateEventResponse> GetRelatedEventsAsync() { + // + // } +} \ No newline at end of file diff --git a/BugMine.Sdk/BugMineProject.cs b/BugMine.Sdk/BugMineProject.cs new file mode 100644
index 0000000..c90ba6e --- /dev/null +++ b/BugMine.Sdk/BugMineProject.cs
@@ -0,0 +1,43 @@ +using System.Text.Json.Nodes; +using LibMatrix.Homeservers; +using LibMatrix.RoomTypes; + +namespace BugMine.Web.Classes; + +public class BugMineProject(GenericRoom room) { + public const string RoomType = "gay.rory.bugmine.project"; + public GenericRoom Room { get; } = room; + public ProjectInfo Info { get; set; } + public string ProjectSlug { get; set; } + + public async Task<BugMineProject> InitializeAsync() { + Info = (await Room.GetStateAsync<ProjectInfo>(ProjectInfo.EventId))!; + var alias = await room.GetCanonicalAliasAsync(); + + if (alias != null) + ProjectSlug = alias.Alias?[1..] ?? room.RoomId; + else ProjectSlug = room.RoomId; + + return this; + } + + public async Task<BugMineIssue> CreateIssue(BugMineIssueData issue) { + // add relation to room creation event + issue.RelatesTo = new() { + EventId = (await Room.GetStateEventAsync("m.room.create")).EventId, + RelationType = "gay.rory.bugmine.issue" + }; + var eventId = await Room.SendTimelineEventAsync(BugMineIssueData.EventId, issue); + + // return new BugMineIssueAccessor(Room, await Room.GetEventAsync<>(eventId)); + var evt = await room.GetEventAsync(eventId.EventId); + Console.WriteLine(evt); + return new BugMineIssue(Room, evt); + } +} + +public static class ProjectRoomExtensions { + public static async Task<BugMineProject> AsBugMineProject(this GenericRoom room) { + return await new BugMineProject(room).InitializeAsync(); + } +} \ No newline at end of file diff --git a/BugMine.Sdk/Events/State/ProjectInfo.cs b/BugMine.Sdk/Events/State/ProjectInfo.cs new file mode 100644
index 0000000..2d15bff --- /dev/null +++ b/BugMine.Sdk/Events/State/ProjectInfo.cs
@@ -0,0 +1,11 @@ +using LibMatrix.EventTypes; + +namespace BugMine.Web.Classes; + +[MatrixEvent(EventName = EventId)] +public class ProjectInfo : EventContent { + public const string EventId = "gay.rory.bugmine.project_info"; + public string? Name { get; set; } + public string? ProjectIcon { get; set; } + public string? Repository { get; set; } +} \ No newline at end of file diff --git a/BugMine.Sdk/Events/Timeline/BugMineIssueComment.cs b/BugMine.Sdk/Events/Timeline/BugMineIssueComment.cs new file mode 100644
index 0000000..50c73a1 --- /dev/null +++ b/BugMine.Sdk/Events/Timeline/BugMineIssueComment.cs
@@ -0,0 +1,11 @@ +using LibMatrix.EventTypes; + +namespace BugMine.Web.Classes; + +[MatrixEvent(EventName = EventId)] +public class BugMineIssueComment : TimelineEventContent { + public const string EventId = "gay.rory.bugmine.comment"; + public string Comment { get; set; } + public string Author { get; set; } + public DateTime Timestamp { get; set; } +} \ No newline at end of file diff --git a/BugMine.Sdk/Events/Timeline/BugMineIssueData.cs b/BugMine.Sdk/Events/Timeline/BugMineIssueData.cs new file mode 100644
index 0000000..480102a --- /dev/null +++ b/BugMine.Sdk/Events/Timeline/BugMineIssueData.cs
@@ -0,0 +1,12 @@ +using LibMatrix.EventTypes; + +namespace BugMine.Web.Classes; + +[MatrixEvent(EventName = ProjectInfo.EventId)] +public class BugMineIssueData : TimelineEventContent { + public const string EventId = "gay.rory.bugmine.issue"; + public string Name { get; set; } + public string? AssignedTo { get; set; } + public string? Status { get; set; } + public string? Priority { get; set; } +} \ No newline at end of file diff --git a/BugMine.Sdk/ServiceInstaller.cs b/BugMine.Sdk/ServiceInstaller.cs new file mode 100644
index 0000000..06309ac --- /dev/null +++ b/BugMine.Sdk/ServiceInstaller.cs
@@ -0,0 +1,25 @@ +using LibMatrix.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +public static class ServiceInstaller { + /// <summary> + /// Adds BugMine SDK services to the service collection. + /// </summary> + /// <param name="services">Service collection</param> + /// <param name="config">Optional BugMine SDK configuration</param> + /// <returns>Input service collection</returns> + public static IServiceCollection AddBugMine(this IServiceCollection services, BugMineSdkConfiguration? config = null) { + services.AddRoryLibMatrixServices(new() { + AppName = config?.AppName ?? "BugMine SDK app" + }); + return services; + } +} + +/// <summary> +/// Configuration for the BugMine SDK. +/// </summary> +public class BugMineSdkConfiguration { + public string AppName { get; set; } = "BugMine SDK app"; +} \ No newline at end of file