about summary refs log tree commit diff
path: root/MiniUtils/Commands/MakeRoomCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MiniUtils/Commands/MakeRoomCommand.cs')
-rw-r--r--MiniUtils/Commands/MakeRoomCommand.cs235
1 files changed, 235 insertions, 0 deletions
diff --git a/MiniUtils/Commands/MakeRoomCommand.cs b/MiniUtils/Commands/MakeRoomCommand.cs
new file mode 100644

index 0000000..068bca5 --- /dev/null +++ b/MiniUtils/Commands/MakeRoomCommand.cs
@@ -0,0 +1,235 @@ +using ArcaneLibs.Extensions; +using LibMatrix.EventTypes.Common; +using LibMatrix.EventTypes.Spec.State.RoomInfo; +using LibMatrix.Helpers; +using LibMatrix.Responses; +using LibMatrix.RoomTypes; +using LibMatrix.Utilities.Bot.Interfaces; + +namespace MiniUtils.Commands; + +public class MakeRoomCommand() : ICommand { + public string Name => "make room"; + + public string[]? Aliases => ["makeroom", "create room", "createroom"]; + + public string Description => "Make a new room"; + + public bool Unlisted => false; + + public async Task Invoke(CommandContext ctx) { + if (ctx.Args.Length == 0) { + await ctx.Room.SendMessageEventAsync( + new MessageBuilder() + .WithTable(tb => { + tb.WithTitle("~create room", 3); + tb.WithRow(rb => { + rb.WithCell("Argument") + .WithCell("Alternatives") + .WithCell("Description"); + }); + tb.WithRow(rb => { + rb.WithCell("--alias <localpart>") + .WithCell("") + .WithCell("Set the room alias"); + }); + tb.WithRow(rb => { + rb.WithCell("--avatar-url <url>") + .WithCell("") + .WithCell("Set the room avatar URL"); + }); + tb.WithRow(rb => { + rb.WithCell("--copy-avatar [room]") + .WithCell("") + .WithCell("Copy the avatar from another room (or current room if unspecified)"); + }); + tb.WithRow(rb => { + rb.WithCell("--copy-powerlevels [room]") + .WithCell("") + .WithCell("Copy the power levels from another room (or current room if unspecified)"); + }); + tb.WithRow(rb => { + rb.WithCell("--invite-admin <user>") + .WithCell("") + .WithCell("Invite a user as an admin"); + }); + tb.WithRow(rb => { + rb.WithCell("--invite <user>") + .WithCell("") + .WithCell("Invite a user"); + }); + tb.WithRow(rb => { + rb.WithCell("--name <name>") + .WithCell("") + .WithCell("Set the room name"); + }); + tb.WithRow(rb => { + rb.WithCell("--topic <topic>") + .WithCell("") + .WithCell("Set the room topic"); + }); + tb.WithRow(rb => { + rb.WithCell("--federate <true|false>") + .WithCell("") + .WithCell("Set whether the room is federatable"); + }); + tb.WithRow(rb => { + rb.WithCell("--join-rule <rule>") + .WithCell(""" + --public + --invite-only + --knock + --restricted + --knock_restricted + --private + """) + .WithCell("Set the room join rule to public, invite-only, knock, restricted, knock-restricted or private"); + }); + tb.WithRow(rb => { + rb.WithCell("--history-visibility <visibility>") + .WithCell(""" + --shared + --invited + --joined + --world_readable + """) + .WithCell("Set the room history visibility to shared, invited, joined or world_readable"); + }); + }) + .Build() + ); + return; + } + + var rb = new RoomBuilder() { }; + + for (int i = 0; i < ctx.Args.Length; i++) { + switch (ctx.Args[i]) { + case "--alias": + rb.AliasLocalPart = ctx.Args[++i]; + break; + case "--avatar-url": + rb.Avatar!.Url = ctx.Args[++i]; + break; + case "--copy-avatar": { + var room = await GetRoomByArgument(ctx, ctx.Args[i + 1]); + if (room != ctx.Room) i++; + rb.Avatar = await room.GetAvatarUrlAsync() ?? throw new ArgumentException($"Room {room.RoomId} does not have an avatar"); + break; + } + case "--copy-powerlevels": { + var room = await GetRoomByArgument(ctx, ctx.Args[i + 1]); + if (room != ctx.Room) i++; + rb.PowerLevels = await room.GetPowerLevelsAsync() ?? throw new ArgumentException($"Room {room.RoomId} does not have power levels???"); + break; + } + case "--invite-admin": + var inviteAdmin = ctx.Args[++i]; + if (!inviteAdmin.StartsWith('@')) { + throw new ArgumentException("Invalid user reference: " + inviteAdmin); + } + + rb.Invites.Add(inviteAdmin, "Marked explicitly as admin to be invited"); + break; + case "--invite": + var inviteUser = ctx.Args[++i]; + if (!inviteUser.StartsWith('@')) { + throw new ArgumentException("Invalid user reference: " + inviteUser); + } + + rb.Invites.Add(inviteUser, "Marked explicitly to be invited"); + break; + case "--name": + var nameEvt = rb.Name = new() { Name = "" }; + while (i + 1 < ctx.Args.Length && !ctx.Args[i + 1].StartsWith("--")) { + nameEvt.Name += (nameEvt.Name.Length > 0 ? " " : "") + ctx.Args[++i]; + } + + break; + case "--topic": + var topicEvt = rb.Topic = new() { Topic = "" }; + while (i + 1 < ctx.Args.Length && !ctx.Args[i + 1].StartsWith("--")) { + topicEvt.Topic += (topicEvt.Topic.Length > 0 ? " " : "") + ctx.Args[++i]; + } + + break; + case "--federate": + rb.IsFederatable = bool.Parse(ctx.Args[++i]); + break; + case "--public": + case "--invite-only": + case "--knock": + case "--restricted": + case "--knock_restricted": + case "--private": + rb.JoinRules.JoinRule = ctx.Args[i].Replace("--", "").ToLowerInvariant() switch { + "public" => RoomJoinRulesEventContent.JoinRules.Public, + "invite-only" => RoomJoinRulesEventContent.JoinRules.Invite, + "knock" => RoomJoinRulesEventContent.JoinRules.Knock, + "restricted" => RoomJoinRulesEventContent.JoinRules.Restricted, + "knock_restricted" => RoomJoinRulesEventContent.JoinRules.KnockRestricted, + "private" => RoomJoinRulesEventContent.JoinRules.Private, + _ => throw new ArgumentException("Unknown join rule: " + ctx.Args[i]) + }; + break; + case "--join-rule": + if (i + 1 >= ctx.Args.Length || !ctx.Args[i + 1].StartsWith("--")) { + throw new ArgumentException("Expected join rule after --join-rule"); + } + + rb.JoinRules.JoinRule = ctx.Args[++i].ToLowerInvariant() switch { + "public" => RoomJoinRulesEventContent.JoinRules.Public, + "invite" => RoomJoinRulesEventContent.JoinRules.Invite, + "knock" => RoomJoinRulesEventContent.JoinRules.Knock, + "restricted" => RoomJoinRulesEventContent.JoinRules.Restricted, + "knock_restricted" => RoomJoinRulesEventContent.JoinRules.KnockRestricted, + "private" => RoomJoinRulesEventContent.JoinRules.Private, + _ => throw new ArgumentException("Unknown join rule: " + ctx.Args[i]) + }; + break; + case "--history-visibility": + rb.HistoryVisibility = new RoomHistoryVisibilityEventContent { + HistoryVisibility = ctx.Args[++i].ToLowerInvariant() switch { + "shared" => RoomHistoryVisibilityEventContent.HistoryVisibilityTypes.Shared, + "invited" => RoomHistoryVisibilityEventContent.HistoryVisibilityTypes.Invited, + "joined" => RoomHistoryVisibilityEventContent.HistoryVisibilityTypes.Joined, + "world_readable" => RoomHistoryVisibilityEventContent.HistoryVisibilityTypes.WorldReadable, + _ => throw new ArgumentException("Unknown history visibility: " + ctx.Args[i]) + } + }; + break; + + default: + throw new ArgumentException("Unknown argument: " + ctx.Args[i]); + } + } + + // await ctx.Room.SendMessageEventAsync( + // new MessageBuilder() + // .WithCodeBlock(rb.ToJson(), "json") + // .Build() + // ); + // var result = await ctx.Homeserver.CreateRoom(creationContent); + var result = await rb.Create(ctx.Homeserver); + await ctx.Room.SendMessageEventAsync(new MessageBuilder() + .WithMention($"{result.RoomId}?via={ctx.Homeserver.ServerName}", rb.CanonicalAlias.Alias) + .Build()); + } + + private async Task<GenericRoom> GetRoomByArgument(CommandContext ctx, string roomReference, bool defaultToCurrent = true) { + if (roomReference.StartsWith("--")) { + return defaultToCurrent ? ctx.Room : throw new ArgumentException("Invalid room reference: " + roomReference); + } + + if (roomReference.StartsWith('!')) { + return ctx.Homeserver.GetRoom(roomReference); + } + + if (roomReference.StartsWith('#')) { + var resolvedAlias = await ctx.Homeserver.ResolveRoomAliasAsync(roomReference); + return ctx.Homeserver.GetRoom(resolvedAlias.RoomId); + } + + throw new ArgumentException("Invalid room reference: " + roomReference); + } +} \ No newline at end of file