From 4283905b341cb183ad9f22aff246299c8ea8fb52 Mon Sep 17 00:00:00 2001 From: gnuxie Date: Wed, 15 Feb 2023 15:41:07 +0000 Subject: [PATCH] I don't like this solution `details` and `summary` being put into html in markdown is unacceptable regardless of whether popular implementations support it. Plain text client will not lol. What's being asked for is detail/summary on category of commands. That can only really happen once Synapse admin commands are all grouped together into one table. --- src/commands/CommandHandler.ts | 84 ++++--------------- .../interface-manager/DeadDocument.ts | 2 + .../interface-manager/DeadDocumentHtml.ts | 6 ++ .../interface-manager/DeadDocumentMarkdown.ts | 6 ++ .../interface-manager/MatrixHelpRenderer.tsx | 10 ++- 5 files changed, 38 insertions(+), 70 deletions(-) diff --git a/src/commands/CommandHandler.ts b/src/commands/CommandHandler.ts index 5fd9f22d..25ea2555 100644 --- a/src/commands/CommandHandler.ts +++ b/src/commands/CommandHandler.ts @@ -28,7 +28,6 @@ limitations under the License. import { Mjolnir } from "../Mjolnir"; import { showJoinsStatus } from "./JoinsCommand"; import { LogService, RichReply } from "matrix-bot-sdk"; -import { htmlEscape } from "../utils"; import { execSyncCommand } from "./SyncCommand"; import { execPermissionCheckCommand } from "./PermissionCheckCommand"; import { execCreateListCommand } from "./CreateBanListCommand"; @@ -51,12 +50,12 @@ import { execKickCommand } from "./KickCommand"; import { parse as tokenize } from "shell-quote"; import { execSinceCommand } from "./SinceCommand"; import { readCommand } from "./interface-manager/CommandReader"; -import { BaseFunction, CommandTable, defineCommandTable } from "./interface-manager/InterfaceCommand"; +import { BaseFunction, CommandTable, defineCommandTable, findTableCommand } from "./interface-manager/InterfaceCommand"; import { findMatrixInterfaceAdaptor, MatrixContext } from "./interface-manager/MatrixInterfaceAdaptor"; import { ArgumentStream } from "./interface-manager/ParameterParsing"; import { CommandResult } from "./interface-manager/Validation"; import { CommandException } from "./interface-manager/CommandException"; -import { tickCrossRenderer, renderCommandHelp } from "./interface-manager/MatrixHelpRenderer"; +import { tickCrossRenderer } from "./interface-manager/MatrixHelpRenderer"; export interface MjolnirContext extends MatrixContext { mjolnir: Mjolnir, @@ -71,6 +70,7 @@ import "./Ban"; import "./Unban"; import "./StatusCommand"; import "./Rules"; +import "./Help"; export const COMMAND_PREFIX = "!mjolnir"; @@ -146,73 +146,19 @@ export async function handleCommand(roomId: string, event: { content: { body: st } else { const readItems = readCommand(cmd).slice(1); // remove "!mjolnir" const stream = new ArgumentStream(readItems); - const command = commandTable.findAMatchingCommand(stream); - if (command) { - const adaptor = findMatrixInterfaceAdaptor(command); - const mjolnirContext: MjolnirContext = { - mjolnir, roomId, event, client: mjolnir.client, emitter: mjolnir.matrixEmitter, - }; - try { - return await adaptor.invoke(mjolnirContext, mjolnirContext, ...stream.rest()); - } catch (e) { - const commandError = new CommandException(e, 'Unknown Unexpected Error'); - LogService.error("CommandHandler", commandError.uuid, commandError.message, e); - await tickCrossRenderer.call(mjolnirContext, mjolnir.client, roomId, event, CommandResult.Err(commandError)); - } + const command = commandTable.findAMatchingCommand(stream) + ?? findTableCommand("mjolnir", "help"); + const adaptor = findMatrixInterfaceAdaptor(command); + const mjolnirContext: MjolnirContext = { + mjolnir, roomId, event, client: mjolnir.client, emitter: mjolnir.matrixEmitter, + }; + try { + return await adaptor.invoke(mjolnirContext, mjolnirContext, ...stream.rest()); + } catch (e) { + const commandError = new CommandException(e, 'Unknown Unexpected Error'); + LogService.error("CommandHandler", commandError.uuid, commandError.message, e); + await tickCrossRenderer.call(mjolnirContext, mjolnir.client, roomId, event, CommandResult.Err(commandError)); } - - // new commands - let newCommandsHelp = '' - for (const tableCommand of commandTable.getCommands()) { - newCommandsHelp += `${renderCommandHelp(tableCommand)}\n`; - } - // Help menu - const menu = "" + - "!mjolnir - Print status information\n" + - "!mjolnir status - Print status information\n" + - "!mjolnir status protection [subcommand] - Print status information for a protection\n" + - "!mjolnir ban [reason] - Adds an entity to the ban list\n" + - "!mjolnir unban [apply] - Removes an entity from the ban list. If apply is 'true', the users matching the glob will actually be unbanned\n" + - "!mjolnir redact [room alias/ID] [limit] - Redacts messages by the sender in the target room (or all rooms), up to a maximum number of events in the backlog (default 1000)\n" + - "!mjolnir redact - Redacts a message by permalink\n" + - "!mjolnir kick [room alias/ID] [reason] - Kicks a user or all of those matching a glob in a particular room or all protected rooms\n" + - "!mjolnir rules - Lists the rules currently in use by Mjolnir\n" + - "!mjolnir rules matching - Lists the rules in use that will match this entity e.g. `!rules matching @foo:example.com` will show all the user and server rules, including globs, that match this user\n" + - "!mjolnir sync - Force updates of all lists and re-apply rules\n" + - "!mjolnir verify - Ensures Mjolnir can moderate all your rooms\n" + - "!mjolnir list create - Creates a new ban list with the given shortcode and alias\n" + - "!mjolnir watch - Watches a ban list\n" + - "!mjolnir unwatch - Unwatches a ban list\n" + - "!mjolnir import - Imports bans and ACLs into the given list\n" + - "!mjolnir default - Sets the default list for commands\n" + - "!mjolnir deactivate - Deactivates a user ID\n" + - "!mjolnir protections - List all available protections\n" + - "!mjolnir enable - Enables a particular protection\n" + - "!mjolnir disable - Disables a particular protection\n" + - "!mjolnir config set . [value] - Change a protection setting\n" + - "!mjolnir config add . [value] - Add a value to a list protection setting\n" + - "!mjolnir config remove . [value] - Remove a value from a list protection setting\n" + - "!mjolnir config get [protection] - List protection settings\n" + - "!mjolnir rooms - Lists all the protected rooms\n" + - "!mjolnir rooms add - Adds a protected room (may cause high server load)\n" + - "!mjolnir rooms remove - Removes a protected room\n" + - "!mjolnir move - Moves a to a new \n" + - "!mjolnir directory add - Publishes a room in the server's room directory\n" + - "!mjolnir directory remove - Removes a room from the server's room directory\n" + - "!mjolnir alias add - Adds to \n" + - "!mjolnir alias remove - Deletes the room alias from whatever room it is attached to\n" + - "!mjolnir resolve - Resolves a room alias to a room ID\n" + - "!mjolnir since / [rooms...] [reason] - Apply an action ('kick', 'ban', 'mute', 'unmute' or 'show') to all users who joined a room since / (up to users)\n" + - "!mjolnir shutdown room [message] - Uses the bot's account to shut down a room, preventing access to the room on this server\n" + - "!mjolnir powerlevel [room alias/ID] - Sets the power level of the user in the specified room (or all protected rooms)\n" + - "!mjolnir help - This menu\n"; - let html = `Old Commands:
${htmlEscape(menu)}
`; - let text = `Old Commands:\n${menu}`; - html += `
New Commands:
${htmlEscape(newCommandsHelp)}
`; - text += `\n\nNew Commands:\n${newCommandsHelp}`; - const reply = RichReply.createFor(roomId, event, text, html); - reply["msgtype"] = "m.notice"; - return await mjolnir.client.sendMessage(roomId, reply); } } catch (e) { LogService.error("CommandHandler", e); diff --git a/src/commands/interface-manager/DeadDocument.ts b/src/commands/interface-manager/DeadDocument.ts index 6b8fc652..0c4bf00e 100644 --- a/src/commands/interface-manager/DeadDocument.ts +++ b/src/commands/interface-manager/DeadDocument.ts @@ -64,6 +64,8 @@ export enum NodeTag { ItalicFace = 'i', Anchor = 'a', Fragment = 'fragment', + Details = 'details', + Summary = 'summary', } /** diff --git a/src/commands/interface-manager/DeadDocumentHtml.ts b/src/commands/interface-manager/DeadDocumentHtml.ts index 527852c9..5166b4aa 100644 --- a/src/commands/interface-manager/DeadDocumentHtml.ts +++ b/src/commands/interface-manager/DeadDocumentHtml.ts @@ -65,4 +65,10 @@ HTML_RENDERER.registerRenderer'), + staticString('') +).registerInnerNode(NodeTag.Summary, + staticString(''), + staticString('') ); diff --git a/src/commands/interface-manager/DeadDocumentMarkdown.ts b/src/commands/interface-manager/DeadDocumentMarkdown.ts index c9893231..8cd55e0c 100644 --- a/src/commands/interface-manager/DeadDocumentMarkdown.ts +++ b/src/commands/interface-manager/DeadDocumentMarkdown.ts @@ -136,4 +136,10 @@ MARKDOWN_RENDERER.registerRenderer'), + staticString('') +).registerInnerNode(NodeTag.Summary, + staticString(''), + staticString('') ); diff --git a/src/commands/interface-manager/MatrixHelpRenderer.tsx b/src/commands/interface-manager/MatrixHelpRenderer.tsx index 93743232..5fe38054 100644 --- a/src/commands/interface-manager/MatrixHelpRenderer.tsx +++ b/src/commands/interface-manager/MatrixHelpRenderer.tsx @@ -26,6 +26,15 @@ function restArgument(rest: RestDescription): string { return `[...${rest.name}]`; } +export function renderCommandSummary(command: InterfaceCommand): DocumentNode { + return
+ + {renderCommandHelp(command)} - {command.summary} + + {command.description ?? 'No description.'} +
+} + export function renderCommandHelp(command: InterfaceCommand): string { const rest = command.argumentListParser.rest; const keywords = command.argumentListParser.keywords; @@ -38,7 +47,6 @@ export function renderCommandHelp(command: InterfaceCommand): stri ].join(' '); } -// What is really needed is a rendering protocol, that works with bullshit text+html that's really just string building like we're doing here or some other media format export async function renderHelp(client: MatrixSendClient, commandRoomId: string, event: any, result: CommandResult[], CommandError>): Promise { const commands = result.ok; let text = ''