From 9587d6fcbae0cfcc524abde08640848753577c2d Mon Sep 17 00:00:00 2001 From: Gnuxie <50846879+Gnuxie@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:51:44 +0000 Subject: [PATCH] Update for simulated capabilities from MPS v2.10.0 and add their renderers, commands. (#727) * Set renderers and glue for new simulated capabilities. https://github.com/the-draupnir-project/planning/issues/2. * Distinguish simulated capability messages when rendering. * Update for MPS 2.10.0 * Add `!protections capability reset ` command. This will allow you to use the default capabilities for a protection. * Update CHANGELOG for simulated capabilities. --- CHANGELOG.md | 8 +++++ package.json | 4 +-- .../DraupnirRendererMessageCollector.tsx | 31 ++++++++++++++----- src/capabilities/RendererMessageCollector.ts | 29 ++++++++++++++--- .../ServerACLConsequencesRenderer.tsx | 25 ++++++++++++++- .../StandardEventConsequencesRenderer.tsx | 4 ++- .../StandardUserConsequencesRenderer.tsx | 23 +++++++++++++- src/commands/DraupnirCommands.ts | 6 ++++ src/commands/ProtectionsCommands.tsx | 30 ++++++++++++++++++ src/commands/ProtectionsShowCommand.tsx | 5 +++ yarn.lock | 16 +++++----- 11 files changed, 155 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3302fe8d..a4c241ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ and this project adheres to ## [Unreleased] - None +### Added + +- Simulated capabilities for all available protection capabilities. These allow + protections to run without effects. + +- A command `!draupnir protections capability reset ` to + restore the default capability set. + ## [v2.1.0] - 2025-02-02 ### Fixed diff --git a/package.json b/package.json index ec9d3d86..81b6e3da 100644 --- a/package.json +++ b/package.json @@ -63,8 +63,8 @@ "jsdom": "^24.0.0", "matrix-appservice-bridge": "^10.3.1", "matrix-bot-sdk": "npm:@vector-im/matrix-bot-sdk@^0.7.1-element.6", - "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@2.9.0", - "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@2.9.0", + "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@2.10.0", + "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@2.10.0", "pg": "^8.8.0", "yaml": "^2.3.2" }, diff --git a/src/capabilities/DraupnirRendererMessageCollector.tsx b/src/capabilities/DraupnirRendererMessageCollector.tsx index 09b94b62..ee9f4b43 100644 --- a/src/capabilities/DraupnirRendererMessageCollector.tsx +++ b/src/capabilities/DraupnirRendererMessageCollector.tsx @@ -7,6 +7,7 @@ import { RendererMessageCollector, } from "./RendererMessageCollector"; import { + Capability, DescriptionMeta, RoomMessageSender, Task, @@ -17,8 +18,6 @@ import { DocumentNode, } from "@the-draupnir-project/interface-manager"; import { sendMatrixEventsFromDeadDocument } from "../commands/interface-manager/MPSMatrixInterfaceAdaptor"; -import { Result } from "@gnuxie/typescript-result"; - export class DraupnirRendererMessageCollector implements RendererMessageCollector { @@ -28,21 +27,37 @@ export class DraupnirRendererMessageCollector ) { // nothing to do. } - private sendMessage(document: DocumentNode): void { + private sendMessage(capability: Capability, document: DocumentNode): void { void Task( sendMatrixEventsFromDeadDocument( this.roomMessageSender, this.managementRoomID, - {document}, + + {capability.isSimulated ? ( + ⚠️ (preview) + ) : ( + + )} + {document} + , {} - ) as Promise> + ) ); } - addMessage(protection: DescriptionMeta, message: DocumentNode): void { - this.sendMessage(message); + addMessage( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void { + this.sendMessage(capability, message); } - addOneliner(protection: DescriptionMeta, message: DocumentNode): void { + addOneliner( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void { this.sendMessage( + capability, {protection.name}: {message} diff --git a/src/capabilities/RendererMessageCollector.ts b/src/capabilities/RendererMessageCollector.ts index 9ca7a214..c577fc9a 100644 --- a/src/capabilities/RendererMessageCollector.ts +++ b/src/capabilities/RendererMessageCollector.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AFL-3.0 import { DocumentNode } from "@the-draupnir-project/interface-manager"; -import { DescriptionMeta } from "matrix-protection-suite"; +import { Capability, DescriptionMeta } from "matrix-protection-suite"; export enum MessageType { Document = "Document", @@ -12,13 +12,22 @@ export enum MessageType { } export interface RendererMessageCollector { - addMessage(protection: DescriptionMeta, message: DocumentNode): void; - addOneliner(protection: DescriptionMeta, message: DocumentNode): void; + addMessage( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void; + addOneliner( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void; getMessages(): RendererMessage[]; } export interface RendererMessage { protection: DescriptionMeta; + capability: Capability; message: DocumentNode; type: MessageType; } @@ -33,17 +42,27 @@ export class AbstractRendererMessageCollector public getMessages(): RendererMessage[] { return this.messages; } - addMessage(protection: DescriptionMeta, message: DocumentNode): void { + addMessage( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void { this.messages.push({ protection, + capability, message, type: MessageType.Document, }); } - addOneliner(protection: DescriptionMeta, message: DocumentNode): void { + addOneliner( + protection: DescriptionMeta, + capability: Capability, + message: DocumentNode + ): void { this.messages.push({ protection, + capability, message, type: MessageType.OneLine, }); diff --git a/src/capabilities/ServerACLConsequencesRenderer.tsx b/src/capabilities/ServerACLConsequencesRenderer.tsx index 4c5cc5c3..b4108f38 100644 --- a/src/capabilities/ServerACLConsequencesRenderer.tsx +++ b/src/capabilities/ServerACLConsequencesRenderer.tsx @@ -62,6 +62,7 @@ class StandardServerConsequencesRenderer implements ServerConsequences { if (isError(capabilityResult)) { this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -72,7 +73,11 @@ class StandardServerConsequencesRenderer implements ServerConsequences { } // only add the message if we changed anything in the room. if (capabilityResult.ok) { - this.messageCollector.addOneliner(this.description, title); + this.messageCollector.addOneliner( + this.description, + this.capability, + title + ); } return capabilityResult; } @@ -85,6 +90,7 @@ class StandardServerConsequencesRenderer implements ServerConsequences { if (isError(capabilityResult)) { this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -95,6 +101,7 @@ class StandardServerConsequencesRenderer implements ServerConsequences { } this.messageCollector.addMessage( this.description, + this.capability, renderRoomSetResult(capabilityResult.ok, { summary: ( @@ -121,6 +128,7 @@ class StandardServerConsequencesRenderer implements ServerConsequences { if (isError(capabilityResult)) { this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -131,6 +139,7 @@ class StandardServerConsequencesRenderer implements ServerConsequences { } this.messageCollector.addMessage( this.description, + this.capability, renderRoomSetResult(capabilityResult.ok, { summary: ( @@ -154,6 +163,7 @@ describeCapabilityRenderer({ capability ); }, + isDefaultForInterface: true, }); describeCapabilityContextGlue({ @@ -169,3 +179,16 @@ describeCapabilityContextGlue({ }); }, }); + +describeCapabilityContextGlue({ + name: "SimulatedServerConsequences", + glueMethod: function ( + protectionDescription, + draupnir, + capabilityProvider + ): Capability { + return capabilityProvider.factory(protectionDescription, { + protectedRoomsSet: draupnir.protectedRoomsSet, + } as ServerACLConsequencesContext); + }, +}); diff --git a/src/capabilities/StandardEventConsequencesRenderer.tsx b/src/capabilities/StandardEventConsequencesRenderer.tsx index f158e8fa..29c18cc0 100644 --- a/src/capabilities/StandardEventConsequencesRenderer.tsx +++ b/src/capabilities/StandardEventConsequencesRenderer.tsx @@ -57,6 +57,7 @@ class StandardEventConsequencesRenderer implements EventConsequences { if (isError(capabilityResult)) { this.messageCollector.addOneliner( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -65,7 +66,7 @@ class StandardEventConsequencesRenderer implements EventConsequences { ); return capabilityResult; } - this.messageCollector.addOneliner(this.description, title); + this.messageCollector.addOneliner(this.description, this.capability, title); return capabilityResult; } } @@ -81,6 +82,7 @@ describeCapabilityRenderer({ capability ); }, + isDefaultForInterface: true, }); describeCapabilityContextGlue({ diff --git a/src/capabilities/StandardUserConsequencesRenderer.tsx b/src/capabilities/StandardUserConsequencesRenderer.tsx index 8a2fa366..ea3ee266 100644 --- a/src/capabilities/StandardUserConsequencesRenderer.tsx +++ b/src/capabilities/StandardUserConsequencesRenderer.tsx @@ -127,6 +127,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { if (isError(capabilityResult)) { this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -135,7 +136,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { ); return capabilityResult; } - this.messageCollector.addOneliner(this.description, title); + this.messageCollector.addOneliner(this.description, this.capability, title); return Ok(undefined); } public async consequenceForUsersInRoomSet( @@ -149,6 +150,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { ); this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -163,6 +165,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { } this.messageCollector.addMessage( this.description, + this.capability, renderResultForUserInSetMap(usersInSetMap, { ingword: "Banning", nnedword: "banned", @@ -188,6 +191,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { ); this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -202,6 +206,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { } this.messageCollector.addMessage( this.description, + this.capability, renderResultForUsersInRoom(resultMap, { summary: ( @@ -233,6 +238,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { ); this.messageCollector.addMessage( this.description, + this.capability, renderFailedSingularConsequence( this.description, title, @@ -247,6 +253,7 @@ class StandardUserConsequencesRenderer implements UserConsequences { } this.messageCollector.addMessage( this.description, + this.capability, renderRoomSetResultForUser(usersInSetMap, userID, "unbanned", { description: this.description, }) @@ -266,6 +273,7 @@ describeCapabilityRenderer({ capability ); }, + isDefaultForInterface: true, }); describeCapabilityContextGlue({ @@ -282,3 +290,16 @@ describeCapabilityContextGlue({ }); }, }); + +describeCapabilityContextGlue({ + name: "SimulatedUserConsequences", + glueMethod: function ( + protectionDescription, + draupnir, + capabilityProvider + ): Capability { + return capabilityProvider.factory(protectionDescription, { + setMembership: draupnir.protectedRoomsSet.setRoomMembership, + } as StandardUserConsequencesContext); + }, +}); diff --git a/src/commands/DraupnirCommands.ts b/src/commands/DraupnirCommands.ts index 0e3dd5d7..8a173b61 100644 --- a/src/commands/DraupnirCommands.ts +++ b/src/commands/DraupnirCommands.ts @@ -22,6 +22,7 @@ import { DraupnirImportCommand } from "./ImportCommand"; import { DraupnirKickCommand } from "./KickCommand"; import { DraupnirListProtectionsCommand, + DraupnirProtectionsCapabilityResetCommand, DraupnirProtectionsConfigAddCommand, DraupnirProtectionsConfigRemoveCommand, DraupnirProtectionsConfigResetCommand, @@ -75,6 +76,11 @@ const DraupnirCommands = new StandardCommandTable("draupnir") "protections", "capability", ]) + .internCommand(DraupnirProtectionsCapabilityResetCommand, [ + "protections", + "capability", + "reset", + ]) .internCommand(DraupnirProtectionsEnableCommand, ["protections", "enable"]) .internCommand(DraupnirProtectionsDisableCommand, ["protections", "disable"]) .internCommand(DraupnirProtectionsConfigAddCommand, [ diff --git a/src/commands/ProtectionsCommands.tsx b/src/commands/ProtectionsCommands.tsx index dca8d83b..665cf9fe 100644 --- a/src/commands/ProtectionsCommands.tsx +++ b/src/commands/ProtectionsCommands.tsx @@ -501,6 +501,36 @@ DraupnirInterfaceAdaptor.describeRenderer( } ); +export const DraupnirProtectionsCapabilityResetCommand = describeCommand({ + summary: "Use the default set of capabilies for the named protection", + parameters: tuple({ + name: "protection name", + acceptor: StringPresentationType, + description: "The name of the protection to be modified.", + }), + async executor(draupnir: Draupnir, _info, _keywords, _rest, protectionName) { + const protectionDescription = findProtection(protectionName); + if (protectionDescription === undefined) { + return ActionError.Result( + `Couldn't find a protection named ${protectionName}` + ); + } + return await draupnir.protectedRoomsSet.protections.changeCapabilityProviderSet( + protectionDescription as unknown as ProtectionDescription, + draupnir.protectedRoomsSet, + draupnir, + protectionDescription.defaultCapabilities + ); + }, +}); + +DraupnirInterfaceAdaptor.describeRenderer( + DraupnirProtectionsCapabilityResetCommand, + { + isAlwaysSupposedToUseDefaultRenderer: true, + } +); + export const DraupnirListProtectionsCommand = describeCommand({ summary: "List all available protections.", parameters: [], diff --git a/src/commands/ProtectionsShowCommand.tsx b/src/commands/ProtectionsShowCommand.tsx index 4c4065b2..3d2d1af1 100644 --- a/src/commands/ProtectionsShowCommand.tsx +++ b/src/commands/ProtectionsShowCommand.tsx @@ -177,6 +177,11 @@ function renderCapabilityProviderSet(set: CapabilityProviderSet): DocumentNode { !draupnir protections capability {"<"}protection name{">"} {"<"} capability name{">"} {"<"}capability provider name{">"} {" "} + command. To reset the capability provider set to its default capabilities, + use the{" "} + + !draupnir protections capability reset {"<"}protection name{">"} + {" "} command. ); diff --git a/yarn.lock b/yarn.lock index c7b43dde..1746adb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2593,18 +2593,18 @@ matrix-appservice@^2.0.0: request-promise "^4.2.6" sanitize-html "^2.11.0" -"matrix-protection-suite-for-matrix-bot-sdk@npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@2.9.0": - version "2.9.0" - resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite-for-matrix-bot-sdk/-/matrix-protection-suite-for-matrix-bot-sdk-2.9.0.tgz#bef8ab7efe85cc560eadc3ce9ab4764bc6261223" - integrity sha512-UCVprdP8f0dexKGgK7Xdc+dYDwCQ086dP1oRQ1mG22F6OJ0sn0NL3Me+JWT8SMUE6RNkolA6krw8/hcHYyVh+Q== +"matrix-protection-suite-for-matrix-bot-sdk@npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite-for-matrix-bot-sdk/-/matrix-protection-suite-for-matrix-bot-sdk-2.10.0.tgz#4ddaea4e6c566e6e31457f197c853b17e19497fc" + integrity sha512-nLlJKi2KHulS6gjeWJqoV9X6KXewI8OYeqlxOdY8EWKFU9HD23xzFoZjpo/2ey6S5l/U+2z5qaQ7AsO0DGoxpQ== dependencies: "@gnuxie/typescript-result" "^1.0.0" await-lock "^2.2.2" -"matrix-protection-suite@npm:@gnuxie/matrix-protection-suite@2.9.0": - version "2.9.0" - resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite/-/matrix-protection-suite-2.9.0.tgz#b5eb5d2d4db6374904ba51034ec0dae363c96e43" - integrity sha512-XnMtYp35yLThPjL+1Nk91gCurtPkvRYWhwWdFVL63JMo2O94vdY9CaJ4Y/VytUPpPuQ5B0MOLQMUJacgNjm87A== +"matrix-protection-suite@npm:@gnuxie/matrix-protection-suite@2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite/-/matrix-protection-suite-2.10.0.tgz#23016419cbed28b8a645fe9c82b5df2fe5cf4751" + integrity sha512-Zwrm9RryTgJEqZ6Y9uPa39YZZwsRLUqfS5I5X0fXrre3M68VX7BNIYKQ9xKvjTBKsTI/jSSCJImARYt5fBT0Zg== dependencies: "@gnuxie/typescript-result" "^1.0.0" await-lock "^2.2.2"