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 <protection name>`  command.

This will allow you to use the default capabilities for a protection.

* Update CHANGELOG for simulated capabilities.
This commit is contained in:
Gnuxie
2025-02-12 12:51:44 +00:00
committed by GitHub
parent d3b55a879a
commit 9587d6fcba
11 changed files with 155 additions and 26 deletions
+8
View File
@@ -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 <protection name>` to
restore the default capability set.
## [v2.1.0] - 2025-02-02
### Fixed
+2 -2
View File
@@ -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"
},
@@ -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,
<root>{document}</root>,
<root>
{capability.isSimulated ? (
<fragment> (preview) </fragment>
) : (
<fragment></fragment>
)}
{document}
</root>,
{}
) as Promise<Result<void>>
)
);
}
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,
<fragment>
<code>{protection.name}</code>: {message}
</fragment>
+24 -5
View File
@@ -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,
});
@@ -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: (
<fragment>
@@ -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: (
<fragment>
@@ -154,6 +163,7 @@ describeCapabilityRenderer<ServerConsequences, Draupnir>({
capability
);
},
isDefaultForInterface: true,
});
describeCapabilityContextGlue<Draupnir, ServerACLConsequencesContext>({
@@ -169,3 +179,16 @@ describeCapabilityContextGlue<Draupnir, ServerACLConsequencesContext>({
});
},
});
describeCapabilityContextGlue<Draupnir, ServerACLConsequencesContext>({
name: "SimulatedServerConsequences",
glueMethod: function (
protectionDescription,
draupnir,
capabilityProvider
): Capability {
return capabilityProvider.factory(protectionDescription, {
protectedRoomsSet: draupnir.protectedRoomsSet,
} as ServerACLConsequencesContext);
},
});
@@ -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<EventConsequences, Draupnir>({
capability
);
},
isDefaultForInterface: true,
});
describeCapabilityContextGlue<Draupnir, { eventRedacter: RoomEventRedacter }>({
@@ -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: (
<fragment>
@@ -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<UserConsequences, Draupnir>({
capability
);
},
isDefaultForInterface: true,
});
describeCapabilityContextGlue<Draupnir, StandardUserConsequencesContext>({
@@ -282,3 +290,16 @@ describeCapabilityContextGlue<Draupnir, StandardUserConsequencesContext>({
});
},
});
describeCapabilityContextGlue<Draupnir, StandardUserConsequencesContext>({
name: "SimulatedUserConsequences",
glueMethod: function (
protectionDescription,
draupnir,
capabilityProvider
): Capability {
return capabilityProvider.factory(protectionDescription, {
setMembership: draupnir.protectedRoomsSet.setRoomMembership,
} as StandardUserConsequencesContext);
},
});
+6
View File
@@ -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, [
+30
View File
@@ -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: [],
+5
View File
@@ -177,6 +177,11 @@ function renderCapabilityProviderSet(set: CapabilityProviderSet): DocumentNode {
!draupnir protections capability {"<"}protection name{">"} {"<"}
capability name{">"} {"<"}capability provider name{">"}
</code>{" "}
command. To reset the capability provider set to its default capabilities,
use the{" "}
<code>
!draupnir protections capability reset {"<"}protection name{">"}
</code>{" "}
command.
</fragment>
);
+8 -8
View File
@@ -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"