diff --git a/BugMine.Sdk/BugMineClient.cs b/BugMine.Sdk/BugMineClient.cs
index be80c3a..db47b85 100644
--- a/BugMine.Sdk/BugMineClient.cs
+++ b/BugMine.Sdk/BugMineClient.cs
@@ -1,15 +1,18 @@
using System.Text.RegularExpressions;
using ArcaneLibs.Extensions;
+using BugMine.Web.Classes.Exceptions;
+using LibMatrix;
using LibMatrix.Homeservers;
using LibMatrix.Responses;
+using LibMatrix.RoomTypes;
namespace BugMine.Web.Classes;
public class BugMineClient(AuthenticatedHomeserverGeneric homeserver) {
public AuthenticatedHomeserverGeneric Homeserver { get; } = homeserver;
-
+
public async IAsyncEnumerable<BugMineProject> GetProjects() {
- List<Task<BugMineProject>> tasks = [];
+ List<Task<BugMineProject>> tasks = [];
await foreach (var room in homeserver.GetJoinedRoomsByType(BugMineProject.RoomType)) {
tasks.Add(room.AsBugMineProject());
}
@@ -21,35 +24,58 @@ public class BugMineClient(AuthenticatedHomeserverGeneric homeserver) {
}
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 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
+ RoomAliasName = alias,
+ InitialState = [
+ new StateEvent() {
+ Type = "m.room.join_rules",
+ RawContent = new() {
+ ["join_rule"] = "public"
+ }
+ },
+ new StateEvent() {
+ Type = ProjectInfo.EventId,
+ TypedContent = request
+ }
+ ]
};
-
+
var response = await Homeserver.CreateRoom(crr);
- await response.SendStateEventAsync(ProjectInfo.EventId, request);
-
+ // 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;
+ var room = await ResolveProjectSlug(projectSlug);
+
+ if (room == null) return null;
- return await (await room.AsBugMineProject()).InitializeAsync();
+ var rooms = await Homeserver.GetJoinedRooms();
+ if (!rooms.Any(r => r.RoomId == room.RoomId)) throw new BugMineException(BugMineException.ErrorCodes.UserNotInRoom);
+
+ return await (await room.AsBugMineProject()).InitializeAsync();
+ }
+
+ public async Task<GenericRoom?> ResolveProjectSlug(string projectSlug) {
+ GenericRoom? room;
+ if (projectSlug.StartsWith('!')) {
+ room = homeserver.GetRoom(projectSlug);
}
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();
+
+ room = homeserver.GetRoom(resolveResult.RoomId);
}
+
+ return room;
}
}
\ No newline at end of file
diff --git a/BugMine.Sdk/BugMineProject.cs b/BugMine.Sdk/BugMineProject.cs
index c90ba6e..babb680 100644
--- a/BugMine.Sdk/BugMineProject.cs
+++ b/BugMine.Sdk/BugMineProject.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Nodes;
+using LibMatrix.EventTypes.Spec.State;
using LibMatrix.Homeservers;
using LibMatrix.RoomTypes;
@@ -13,27 +14,34 @@ public class BugMineProject(GenericRoom room) {
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,
+ EventId = await room.GetStateEventIdAsync(RoomCreateEventContent.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 async IAsyncEnumerable<BugMineIssue> GetIssues() {
+ var creationEventId = await room.GetStateEventIdAsync(RoomCreateEventContent.EventId);
+ await foreach (var evt in room.GetRelatedEventsAsync(creationEventId, "gay.rory.bugmine.issue", BugMineIssueData.EventId)) {
+ yield return new BugMineIssue(Room, evt);
+ }
+ }
}
public static class ProjectRoomExtensions {
diff --git a/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs b/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs
new file mode 100644
index 0000000..a6686d3
--- /dev/null
+++ b/BugMine.Sdk/Events/State/BugMineRoomMetadata.cs
@@ -0,0 +1,11 @@
+using LibMatrix.EventTypes;
+
+namespace BugMine.Web.Classes;
+
+[MatrixEvent(EventName = EventId)]
+public class BugMineRoomMetadata : EventContent {
+ public const string EventId = "gay.rory.bugmine.room_metadata";
+
+ public string RoomCreationEventId { get; set; }
+
+}
\ No newline at end of file
diff --git a/BugMine.Sdk/Exceptions/BugMineException.cs b/BugMine.Sdk/Exceptions/BugMineException.cs
new file mode 100644
index 0000000..7e843b3
--- /dev/null
+++ b/BugMine.Sdk/Exceptions/BugMineException.cs
@@ -0,0 +1,23 @@
+using System.Diagnostics.CodeAnalysis;
+using LibMatrix;
+
+namespace BugMine.Web.Classes.Exceptions;
+
+public class BugMineException : MatrixException {
+ [SetsRequiredMembers]
+ public BugMineException(string errorCode, string? message = null) {
+ ErrorCode = errorCode;
+ Error = message ?? Message;
+ }
+
+ public sealed override string Message =>
+ $"{ErrorCode}: {ErrorCode switch {
+ // common
+ ErrorCodes.UserNotInRoom => "User is not in the room",
+ _ => base.Message
+ }}";
+
+ public new static class ErrorCodes {
+ public const string UserNotInRoom = "BUGMINE_USER_NOT_IN_ROOM";
+ }
+}
\ No newline at end of file
|