mirror of
https://github.com/the-draupnir-project/Draupnir.git
synced 2026-05-25 00:35:17 +00:00
Migrate status command to use interface-manager.
This commit is contained in:
@@ -26,7 +26,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { Mjolnir } from "../Mjolnir";
|
||||
import { execStatusCommand } from "./StatusCommand";
|
||||
import { showJoinsStatus } from "./JoinsCommand";
|
||||
import { execDumpRulesCommand, execRulesMatchingCommand } from "./DumpRulesCommand";
|
||||
import { LogService, RichReply } from "matrix-bot-sdk";
|
||||
import { htmlEscape } from "../utils";
|
||||
@@ -70,6 +70,7 @@ import "./interface-manager/MatrixPresentations";
|
||||
import "./HijackRoomCommand";
|
||||
import "./Ban";
|
||||
import "./Unban";
|
||||
import "./StatusCommand";
|
||||
|
||||
export const COMMAND_PREFIX = "!mjolnir";
|
||||
|
||||
@@ -82,8 +83,8 @@ export async function handleCommand(roomId: string, event: { content: { body: st
|
||||
const tokens = tokenize(cmd.replace("#", "\\#")).slice(/* get rid of ["!mjolnir", command] */ 2);
|
||||
|
||||
try {
|
||||
if (parts.length === 1 || parts[1] === 'status') {
|
||||
return await execStatusCommand(roomId, event, mjolnir, parts.slice(2));
|
||||
if (parts.length === 1 || parts[1] === 'joins') {
|
||||
return await showJoinsStatus(roomId, event, mjolnir, parts.slice(/* ["joins"] */ 2));
|
||||
} else if (parts[1] === 'rules' && parts.length === 4 && parts[2] === 'matching') {
|
||||
return await execRulesMatchingCommand(roomId, event, mjolnir, parts[3])
|
||||
} else if (parts[1] === 'rules') {
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (C) 2022 Gnuxie <Gnuxie@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is modified and is NOT licensed under the Apache License.
|
||||
* This modified file incorperates work from mjolnir
|
||||
* https://github.com/matrix-org/mjolnir
|
||||
* which included the following license notice:
|
||||
|
||||
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*
|
||||
* However, this file is modified and the modifications in this file
|
||||
* are NOT distributed, contributed, committed, or licensed under the Apache License.
|
||||
*/
|
||||
|
||||
import { Mjolnir } from "../Mjolnir";
|
||||
import { RichReply } from "matrix-bot-sdk";
|
||||
import { htmlEscape, parseDuration } from "../utils";
|
||||
import { HumanizeDurationLanguage, HumanizeDuration } from "humanize-duration-ts";
|
||||
|
||||
const HUMANIZE_LAG_SERVICE: HumanizeDurationLanguage = new HumanizeDurationLanguage();
|
||||
const HUMANIZER: HumanizeDuration = new HumanizeDuration(HUMANIZE_LAG_SERVICE);
|
||||
|
||||
|
||||
/**
|
||||
* Show the most recent joins to a room.
|
||||
*
|
||||
* Seems like this command never worked how it was expected to
|
||||
* "100 day" without quotes is 2 parts, so if you wrote them like the examples
|
||||
* then you would have 4 parts?
|
||||
*
|
||||
* For now I will copy this as it were, but this needs fixing
|
||||
* https://github.com/Gnuxie/Draupnir/issues/19
|
||||
*/
|
||||
export async function showJoinsStatus(destinationRoomId: string, event: any, mjolnir: Mjolnir, args: string[]) {
|
||||
const targetRoomAliasOrId = args[0];
|
||||
const maxAgeArg = args[1] || "1 day";
|
||||
const maxEntriesArg = args[2] = "200";
|
||||
const { html, text } = await (async () => {
|
||||
if (!targetRoomAliasOrId) {
|
||||
return {
|
||||
html: "Missing arg: <code>room id</code>",
|
||||
text: "Missing arg: `room id`"
|
||||
};
|
||||
}
|
||||
const maxAgeMS = parseDuration(maxAgeArg);
|
||||
if (!maxAgeMS) {
|
||||
return {
|
||||
html: "Invalid duration. Example: <code>1.5 days</code> or <code>10 minutes</code>",
|
||||
text: "Invalid duration. Example: `1.5 days` or `10 minutes`",
|
||||
}
|
||||
}
|
||||
const maxEntries = Number.parseInt(maxEntriesArg, 10);
|
||||
if (!maxEntries) {
|
||||
return {
|
||||
html: "Invalid number of entries. Example: <code>200</code>",
|
||||
text: "Invalid number of entries. Example: `200`",
|
||||
}
|
||||
}
|
||||
const minDate = new Date(Date.now() - maxAgeMS);
|
||||
const HUMANIZER_OPTIONS = {
|
||||
// Reduce "1 day" => "1day" to simplify working with CSV.
|
||||
spacer: "",
|
||||
// Reduce "1 day, 2 hours" => "1.XXX day" to simplify working with CSV.
|
||||
largest: 1,
|
||||
};
|
||||
const maxAgeHumanReadable = HUMANIZER.humanize(maxAgeMS, HUMANIZER_OPTIONS);
|
||||
let targetRoomId;
|
||||
try {
|
||||
targetRoomId = await mjolnir.client.resolveRoom(targetRoomAliasOrId);
|
||||
} catch (ex) {
|
||||
return {
|
||||
html: `Cannot resolve room ${htmlEscape(targetRoomAliasOrId)}.`,
|
||||
text: `Cannot resolve room \`${targetRoomAliasOrId}\`.`
|
||||
}
|
||||
}
|
||||
const joins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
const htmlFragments = [];
|
||||
const textFragments = [];
|
||||
for (let join of joins) {
|
||||
const durationHumanReadable = HUMANIZER.humanize(Date.now() - join.timestamp, HUMANIZER_OPTIONS);
|
||||
htmlFragments.push(`<li>${htmlEscape(join.userId)}: ${durationHumanReadable}</li>`);
|
||||
textFragments.push(`- ${join.userId}: ${durationHumanReadable}`);
|
||||
}
|
||||
return {
|
||||
html: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries): <ul> ${htmlFragments.join()} </ul>`,
|
||||
text: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries):\n${textFragments.join("\n")}`
|
||||
}
|
||||
})();
|
||||
const reply = RichReply.createFor(destinationRoomId, event, text, html);
|
||||
reply["msgtype"] = "m.notice";
|
||||
return mjolnir.client.sendMessage(destinationRoomId, reply);
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2022 Gnuxie <Gnuxie@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is modified and is NOT licensed under the Apache License.
|
||||
* This modified file incorperates work from mjolnir
|
||||
* https://github.com/matrix-org/mjolnir
|
||||
* which included the following license notice:
|
||||
|
||||
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*
|
||||
* However, this file is modified and the modifications in this file
|
||||
* are NOT distributed, contributed, committed, or licensed under the Apache License.
|
||||
*/
|
||||
|
||||
import { Mjolnir, STATE_CHECKING_PERMISSIONS, STATE_NOT_STARTED, STATE_RUNNING, STATE_SYNCING } from "../Mjolnir";
|
||||
import { RichReply } from "matrix-bot-sdk";
|
||||
import { htmlEscape, parseDuration } from "../utils";
|
||||
import { HumanizeDurationLanguage, HumanizeDuration } from "humanize-duration-ts";
|
||||
import PolicyList from "../models/PolicyList";
|
||||
import { PACKAGE_JSON, SOFTWARE_VERSION } from "../config";
|
||||
|
||||
const HUMANIZE_LAG_SERVICE: HumanizeDurationLanguage = new HumanizeDurationLanguage();
|
||||
const HUMANIZER: HumanizeDuration = new HumanizeDuration(HUMANIZE_LAG_SERVICE);
|
||||
|
||||
// !mjolnir
|
||||
export async function execStatusCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||
switch (parts[0]) {
|
||||
case undefined:
|
||||
case 'mjolnir':
|
||||
return showMjolnirStatus(roomId, event, mjolnir);
|
||||
case 'joins':
|
||||
return showJoinsStatus(roomId, event, mjolnir, parts.slice(/* ["joins"] */ 1));
|
||||
case 'protection':
|
||||
return showProtectionStatus(roomId, event, mjolnir, parts.slice(/* ["protection"] */ 1));
|
||||
default:
|
||||
throw new Error(`Invalid status command: ${htmlEscape(parts[0])}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function showMjolnirStatus(roomId: string, event: any, mjolnir: Mjolnir) {
|
||||
// Display the status of Mjölnir.
|
||||
let html = "";
|
||||
let text = "";
|
||||
|
||||
const state = mjolnir.state;
|
||||
|
||||
switch (state) {
|
||||
case STATE_NOT_STARTED:
|
||||
html += "<b>Running: </b>❌ (not started)<br/>";
|
||||
text += "Running: ❌ (not started)\n";
|
||||
break;
|
||||
case STATE_CHECKING_PERMISSIONS:
|
||||
html += "<b>Running: </b>❌ (checking own permissions)<br/>";
|
||||
text += "Running: ❌ (checking own permissions)\n";
|
||||
break;
|
||||
case STATE_SYNCING:
|
||||
html += "<b>Running: </b>❌ (syncing lists)<br/>";
|
||||
text += "Running: ❌ (syncing lists)\n";
|
||||
break;
|
||||
case STATE_RUNNING:
|
||||
html += "<b>Running: </b>✅<br/>";
|
||||
text += "Running: ✅\n";
|
||||
break;
|
||||
default:
|
||||
html += "<b>Running: </b>❌ (unknown state)<br/>";
|
||||
text += "Running: ❌ (unknown state)\n";
|
||||
break;
|
||||
}
|
||||
|
||||
html += `<b>Protected rooms: </b> ${mjolnir.protectedRoomsTracker.getProtectedRooms().length}<br/>`;
|
||||
text += `Protected rooms: ${mjolnir.protectedRoomsTracker.getProtectedRooms().length}\n`;
|
||||
|
||||
// Append list information
|
||||
const renderPolicyLists = (header: string, lists: PolicyList[]) => {
|
||||
html += `<b>${header}:</b><br><ul>`;
|
||||
text += `${header}:\n`;
|
||||
for (const list of lists) {
|
||||
const ruleInfo = `rules: ${list.serverRules.length} servers, ${list.userRules.length} users, ${list.roomRules.length} rooms`;
|
||||
html += `<li>${htmlEscape(list.listShortcode)} @ <a href="${list.roomRef}">${list.roomId}</a> (${ruleInfo})</li>`;
|
||||
text += `* ${list.listShortcode} @ ${list.roomRef} (${ruleInfo})\n`;
|
||||
}
|
||||
if (lists.length === 0) {
|
||||
html += "<li><i>None</i></li>";
|
||||
text += "* None\n";
|
||||
}
|
||||
html += "</ul>";
|
||||
}
|
||||
const subscribedLists = mjolnir.policyListManager.lists.filter(list => !mjolnir.explicitlyProtectedRooms.includes(list.roomId));
|
||||
renderPolicyLists("Subscribed policy lists", subscribedLists);
|
||||
const subscribedAndProtectedLists = mjolnir.policyListManager.lists.filter(list => mjolnir.explicitlyProtectedRooms.includes(list.roomId));
|
||||
renderPolicyLists("Subscribed and protected policy lists", subscribedAndProtectedLists);
|
||||
|
||||
html += `<b>Version:</b> ${SOFTWARE_VERSION}<br/>`;
|
||||
text += `Version: ${SOFTWARE_VERSION}\n`;
|
||||
|
||||
html += `<b>Repository:</b> <code>${PACKAGE_JSON['repository'] ?? 'Unknown'}</code>`;
|
||||
text += `Repository: ${PACKAGE_JSON['repository'] ?? 'Unknown'}`;
|
||||
|
||||
const reply = RichReply.createFor(roomId, event, text, html);
|
||||
reply["msgtype"] = "m.notice";
|
||||
return mjolnir.client.sendMessage(roomId, reply);
|
||||
}
|
||||
|
||||
async function showProtectionStatus(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||
const protectionName = parts[0];
|
||||
const protection = mjolnir.protectionManager.getProtection(protectionName);
|
||||
let text;
|
||||
let html;
|
||||
if (!protection) {
|
||||
text = html = "Unknown protection";
|
||||
} else {
|
||||
const status = await protection.statusCommand(mjolnir, parts.slice(1));
|
||||
if (status) {
|
||||
text = status.text;
|
||||
html = status.html;
|
||||
} else {
|
||||
text = "<no status>";
|
||||
html = "<no status>";
|
||||
}
|
||||
}
|
||||
const reply = RichReply.createFor(roomId, event, text, html);
|
||||
reply["msgtype"] = "m.notice";
|
||||
await mjolnir.client.sendMessage(roomId, reply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the most recent joins to a room.
|
||||
*/
|
||||
async function showJoinsStatus(destinationRoomId: string, event: any, mjolnir: Mjolnir, args: string[]) {
|
||||
const targetRoomAliasOrId = args[0];
|
||||
const maxAgeArg = args[1] || "1 day";
|
||||
const maxEntriesArg = args[2] = "200";
|
||||
const { html, text } = await (async () => {
|
||||
if (!targetRoomAliasOrId) {
|
||||
return {
|
||||
html: "Missing arg: <code>room id</code>",
|
||||
text: "Missing arg: `room id`"
|
||||
};
|
||||
}
|
||||
const maxAgeMS = parseDuration(maxAgeArg);
|
||||
if (!maxAgeMS) {
|
||||
return {
|
||||
html: "Invalid duration. Example: <code>1.5 days</code> or <code>10 minutes</code>",
|
||||
text: "Invalid duration. Example: `1.5 days` or `10 minutes`",
|
||||
}
|
||||
}
|
||||
const maxEntries = Number.parseInt(maxEntriesArg, 10);
|
||||
if (!maxEntries) {
|
||||
return {
|
||||
html: "Invalid number of entries. Example: <code>200</code>",
|
||||
text: "Invalid number of entries. Example: `200`",
|
||||
}
|
||||
}
|
||||
const minDate = new Date(Date.now() - maxAgeMS);
|
||||
const HUMANIZER_OPTIONS = {
|
||||
// Reduce "1 day" => "1day" to simplify working with CSV.
|
||||
spacer: "",
|
||||
// Reduce "1 day, 2 hours" => "1.XXX day" to simplify working with CSV.
|
||||
largest: 1,
|
||||
};
|
||||
const maxAgeHumanReadable = HUMANIZER.humanize(maxAgeMS, HUMANIZER_OPTIONS);
|
||||
let targetRoomId;
|
||||
try {
|
||||
targetRoomId = await mjolnir.client.resolveRoom(targetRoomAliasOrId);
|
||||
} catch (ex) {
|
||||
return {
|
||||
html: `Cannot resolve room ${htmlEscape(targetRoomAliasOrId)}.`,
|
||||
text: `Cannot resolve room \`${targetRoomAliasOrId}\`.`
|
||||
}
|
||||
}
|
||||
const joins = mjolnir.roomJoins.getUsersInRoom(targetRoomId, minDate, maxEntries);
|
||||
const htmlFragments = [];
|
||||
const textFragments = [];
|
||||
for (let join of joins) {
|
||||
const durationHumanReadable = HUMANIZER.humanize(Date.now() - join.timestamp, HUMANIZER_OPTIONS);
|
||||
htmlFragments.push(`<li>${htmlEscape(join.userId)}: ${durationHumanReadable}</li>`);
|
||||
textFragments.push(`- ${join.userId}: ${durationHumanReadable}`);
|
||||
}
|
||||
return {
|
||||
html: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries): <ul> ${htmlFragments.join()} </ul>`,
|
||||
text: `${joins.length} recent joins (cut at ${maxAgeHumanReadable} ago / ${maxEntries} entries):\n${textFragments.join("\n")}`
|
||||
}
|
||||
})();
|
||||
const reply = RichReply.createFor(destinationRoomId, event, text, html);
|
||||
reply["msgtype"] = "m.notice";
|
||||
return mjolnir.client.sendMessage(destinationRoomId, reply);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Copyright (C) 2022 Gnuxie <Gnuxie@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is modified and is NOT licensed under the Apache License.
|
||||
* This modified file incorperates work from mjolnir
|
||||
* https://github.com/matrix-org/mjolnir
|
||||
* which included the following license notice:
|
||||
|
||||
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*
|
||||
* However, this file is modified and the modifications in this file
|
||||
* are NOT distributed, contributed, committed, or licensed under the Apache License.
|
||||
*/
|
||||
|
||||
import { STATE_CHECKING_PERMISSIONS, STATE_NOT_STARTED, STATE_RUNNING, STATE_SYNCING } from "../Mjolnir";
|
||||
import { RichReply } from "matrix-bot-sdk";
|
||||
import PolicyList from "../models/PolicyList";
|
||||
import { PACKAGE_JSON, SOFTWARE_VERSION } from "../config";
|
||||
import { defineInterfaceCommand, findTableCommand } from "./interface-manager/InterfaceCommand";
|
||||
import { findPresentationType, parameters, RestDescription } from "./interface-manager/ParameterParsing";
|
||||
import { MjolnirContext } from "./CommandHandler";
|
||||
import { CommandError, CommandResult } from "./interface-manager/Validation";
|
||||
import { defineMatrixInterfaceAdaptor, MatrixContext, MatrixInterfaceAdaptor } from "./interface-manager/MatrixInterfaceAdaptor";
|
||||
import { MatrixSendClient } from "../MatrixEmitter";
|
||||
import { JSXFactory } from "./interface-manager/JSXFactory";
|
||||
import { Protection } from "../protections/IProtection";
|
||||
import { tickCrossRenderer } from "./interface-manager/MatrixHelpRenderer";
|
||||
import { renderMatrixAndSend } from "./interface-manager/DeadDocumentMatrix";
|
||||
|
||||
defineInterfaceCommand({
|
||||
designator: ["status"],
|
||||
table: "mjolnir",
|
||||
parameters: parameters([]),
|
||||
command: async function () { return CommandResult.Ok(mjolnirStatusInfo.call(this)) },
|
||||
summary: "Show the status of the bot."
|
||||
})
|
||||
|
||||
export interface ListInfo {
|
||||
shortcode: string,
|
||||
roomRef: string,
|
||||
roomId: string,
|
||||
serverRules: number,
|
||||
userRules: number,
|
||||
roomRules: number,
|
||||
}
|
||||
|
||||
export interface StatusInfo {
|
||||
state: string, // a small description of the state of Mjolnir
|
||||
numberOfProtectedRooms: number,
|
||||
subscribedLists: ListInfo[],
|
||||
subscribedAndProtectedLists: ListInfo[],
|
||||
version: string,
|
||||
repository: string
|
||||
}
|
||||
|
||||
|
||||
function mjolnirStatusInfo(this: MjolnirContext): StatusInfo {
|
||||
const listInfo = (list: PolicyList): ListInfo => {
|
||||
return {
|
||||
shortcode: list.listShortcode,
|
||||
roomRef: list.roomRef,
|
||||
roomId: list.roomId,
|
||||
serverRules: list.serverRules.length,
|
||||
userRules: list.userRules.length,
|
||||
roomRules: list.roomRules.length,
|
||||
}
|
||||
}
|
||||
return {
|
||||
state: this.mjolnir.state,
|
||||
numberOfProtectedRooms: this.mjolnir.protectedRoomsTracker.getProtectedRooms().length,
|
||||
subscribedLists: this.mjolnir.policyListManager.lists
|
||||
.filter(list => !this.mjolnir.explicitlyProtectedRooms.includes(list.roomId))
|
||||
.map(listInfo),
|
||||
subscribedAndProtectedLists: this.mjolnir.policyListManager.lists
|
||||
.filter(list => this.mjolnir.explicitlyProtectedRooms.includes(list.roomId))
|
||||
.map(listInfo),
|
||||
version: SOFTWARE_VERSION,
|
||||
repository: PACKAGE_JSON['repository'] ?? 'Unknown'
|
||||
}
|
||||
}
|
||||
|
||||
defineMatrixInterfaceAdaptor({
|
||||
interfaceCommand: findTableCommand("mjolnir", "status"),
|
||||
renderer: async function (this: MatrixInterfaceAdaptor<MatrixContext>, client: MatrixSendClient, commandRoomId: string, event: any, result: CommandResult<StatusInfo>): Promise<void> {
|
||||
const renderState = (state: StatusInfo['state']) => {
|
||||
const notRunning = (text: string) => {
|
||||
return <fragment><b>Running: </b>❌ (${text})<br/></fragment>
|
||||
};
|
||||
switch (state) {
|
||||
case STATE_NOT_STARTED:
|
||||
return notRunning('not started');
|
||||
case STATE_CHECKING_PERMISSIONS:
|
||||
return notRunning('checking own permission');
|
||||
case STATE_SYNCING:
|
||||
return notRunning('syncing lists');
|
||||
case STATE_RUNNING:
|
||||
return <fragment><b>Running: </b>✅<br/></fragment>
|
||||
default:
|
||||
return notRunning('unknown state');
|
||||
}
|
||||
};
|
||||
const renderPolicyLists = (header: string, lists: ListInfo[]) => {
|
||||
const listInfo = lists.map(list => {
|
||||
return <li>
|
||||
{list.shortcode} @ <a href={list.roomRef}>{list.roomId}</a>
|
||||
(rules: {list.serverRules} servers, {list.userRules} users, {list.roomRules} rooms)
|
||||
</li>
|
||||
});
|
||||
return <fragment>
|
||||
<b>{header}</b><br/>
|
||||
<ul>
|
||||
{listInfo.length === 0 ? <li><i>None</i></li> : listInfo}
|
||||
</ul>
|
||||
</fragment>
|
||||
};
|
||||
const info = result.ok;
|
||||
|
||||
await renderMatrixAndSend(<root>
|
||||
{renderState(info.state)}
|
||||
<b>Protected Rooms: </b>{info.numberOfProtectedRooms}<br/>
|
||||
{renderPolicyLists('Subscribed policy lists', info.subscribedLists)}
|
||||
{renderPolicyLists('Subscribed and protected policy lists', info.subscribedAndProtectedLists)}
|
||||
<b>Version: </b><code>{info.version}</code><br/>
|
||||
<b>Repository: </b><code>{info.repository}</code><br/>
|
||||
</root>,
|
||||
commandRoomId,
|
||||
event,
|
||||
client);
|
||||
}
|
||||
});
|
||||
|
||||
defineInterfaceCommand({
|
||||
designator: ["status", "protection"],
|
||||
table: "mjolnir",
|
||||
parameters: parameters([
|
||||
{
|
||||
name: "protection name",
|
||||
acceptor: findPresentationType("string")
|
||||
},
|
||||
],
|
||||
new RestDescription<MjolnirContext>(
|
||||
"subcommand",
|
||||
findPresentationType("string")
|
||||
)),
|
||||
command: async function (
|
||||
this: MjolnirContext, _keywords, protectionName: string, ...subcommands: string[]
|
||||
): Promise<CommandResult<Awaited<ReturnType<Protection['statusCommand']>>>> {
|
||||
const protection = this.mjolnir.protectionManager.getProtection(protectionName);
|
||||
if (!protection) {
|
||||
return CommandError.Result(`Unknown protection ${protectionName}`);
|
||||
}
|
||||
return CommandResult.Ok(await protection.statusCommand(this.mjolnir, subcommands))
|
||||
},
|
||||
summary: "Show the status of a protection."
|
||||
})
|
||||
|
||||
defineMatrixInterfaceAdaptor({
|
||||
interfaceCommand: findTableCommand("mjolnir", "status", "protection"),
|
||||
renderer: async function(client, commandRoomId, event, result) {
|
||||
tickCrossRenderer.call(this, ...arguments);
|
||||
if (result.isErr()) {
|
||||
return; // tickCrossRenderer will handle it.
|
||||
}
|
||||
const status = result.ok;
|
||||
const reply = RichReply.createFor(
|
||||
commandRoomId,
|
||||
event,
|
||||
status?.text ?? "<no status>",
|
||||
status?.html ?? "<no status>"
|
||||
);
|
||||
reply["msgtype"] = "m.notice";
|
||||
await client.sendMessage(commandRoomId, reply);
|
||||
}
|
||||
})
|
||||
@@ -53,7 +53,7 @@ type RendererSignature<C extends MatrixContext, ExecutorType extends BaseFunctio
|
||||
event: any,
|
||||
result: Awaited<ReturnType<ExecutorType>>) => Promise<void>;
|
||||
|
||||
export class MatrixInterfaceAdaptor<C extends MatrixContext, ExecutorType extends BaseFunction> implements InterfaceAcceptor {
|
||||
export class MatrixInterfaceAdaptor<C extends MatrixContext, ExecutorType extends BaseFunction = BaseFunction> implements InterfaceAcceptor {
|
||||
public readonly isPromptable = true;
|
||||
constructor(
|
||||
public readonly interfaceCommand: InterfaceCommand<ExecutorType>,
|
||||
|
||||
@@ -311,7 +311,7 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
// Initially, the command should show that same result.
|
||||
for (let roomId of roomIds) {
|
||||
const reply = await getFirstReply(mjolnir.matrixEmitter, mjolnir.managementRoomId, () => {
|
||||
const command = `!mjolnir status joins ${roomId}`;
|
||||
const command = `!mjolnir joins ${roomId}`;
|
||||
return this.moderator.sendMessage(mjolnir.managementRoomId, { msgtype: 'm.text', body: command });
|
||||
});
|
||||
const body = reply["content"]?.["body"] as string;
|
||||
@@ -329,7 +329,7 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
const joined = manager.getUsersInRoom(roomId, start, 100);
|
||||
assert.equal(joined.length, SAMPLE_SIZE / 2 /* half of the users */ + 1 /* mjolnir */, "We should now see all joined users in the room");
|
||||
const reply = await getFirstReply(mjolnir.matrixEmitter, mjolnir.managementRoomId, () => {
|
||||
const command = `!mjolnir status joins ${roomId}`;
|
||||
const command = `!mjolnir joins ${roomId}`;
|
||||
return this.moderator.sendMessage(mjolnir.managementRoomId, { msgtype: 'm.text', body: command });
|
||||
});
|
||||
const body = reply["content"]?.["body"] as string;
|
||||
@@ -362,7 +362,7 @@ describe("Test: Testing RoomMemberManager", function() {
|
||||
for (let i = 0; i < roomIds.length; ++i) {
|
||||
const roomId = roomIds[i];
|
||||
const reply = await getFirstReply(mjolnir.matrixEmitter, mjolnir.managementRoomId, () => {
|
||||
const command = `!mjolnir status joins ${roomId}`;
|
||||
const command = `!mjolnir joins ${roomId}`;
|
||||
return this.moderator.sendMessage(mjolnir.managementRoomId, { msgtype: 'm.text', body: command });
|
||||
});
|
||||
const body = reply["content"]?.["body"] as string;
|
||||
|
||||
Reference in New Issue
Block a user