Two appservice bot commands to test with.

One lists unstarted mjolnirs, and one allows you to try restart them.
This commit is contained in:
gnuxie committed 2023-01-14 18:33:06 +00:00
1 parent 203f42dc0e
commit de9a0a078b
2 files changed
+163

No files matched your search

@@ -0,0 +1,72 @@
/**
* Copyright (C) 2022 Gnuxie <Gnuxie@protonmail.com>
* All rights reserved.
*/
import { WeakEvent } from 'matrix-appservice-bridge';
import { readCommand } from '../../commands/interface-manager/CommandReader';
import { defineCommandTable, defineInterfaceCommand, findCommandTable } from '../../commands/interface-manager/InterfaceCommand';
import { defineMatrixInterfaceAdaptor, findMatrixInterfaceAdaptor, MatrixContext } from '../../commands/interface-manager/MatrixInterfaceAdaptor';
import { ArgumentStream, paramaters } from '../../commands/interface-manager/ParamaterParsing';
import { MjolnirAppService } from '../AppService';
import { CommandResult } from '../../commands/interface-manager/Validation';
import { renderHelp } from '../../commands/interface-manager/MatrixHelpRenderer';
defineCommandTable("appservice bot");
export interface AppserviceContext extends MatrixContext {
appservice: MjolnirAppService;
}
export type AppserviceBaseExecutor = (this: AppserviceContext, ...args: any[]) => Promise<CommandResult<any>>;
import '../../commands/interface-manager/MatrixPresentations';
import './ListCommand';
const helpCommand = defineInterfaceCommand({
paramaters: paramaters([]),
table: "appservice bot",
command: async function() { return CommandResult.Ok(findCommandTable("appservice bot").getCommands()) },
designator: ["help"],
summary: "Display this message"
})
defineMatrixInterfaceAdaptor({
interfaceCommand: helpCommand,
renderer: renderHelp
})
export class AppserviceCommandHandler {
private readonly commandTable = findCommandTable("appservice bot");
constructor (
private readonly appservice: MjolnirAppService
) {
}
public handleEvent(mxEvent: WeakEvent): void {
if (mxEvent.type !== 'm.room.message' && mxEvent.room_id !== this.appservice.config.adminRoom) {
return;
}
const body = typeof mxEvent.content['body'] === 'string' ? mxEvent.content['body'] : '';
if (body.startsWith(this.appservice.bridge.getBot().getUserId())) {
const readItems = readCommand(body).slice(1); // remove "!mjolnir"
const argumentStream = new ArgumentStream(readItems);
const command = this.commandTable.findAMatchingCommand(argumentStream);
// FIXME: what if there's no command, print help?
if (command) {
const adaptor = findMatrixInterfaceAdaptor(command);
const context: AppserviceContext = {
appservice: this.appservice,
roomId: mxEvent.room_id,
event: mxEvent,
client: this.appservice.bridge.getBot().getClient()
};
adaptor.invoke(context, context, ...argumentStream.rest());
return;
}
}
}
}
+91
View File
@@ -0,0 +1,91 @@
/**
* Copyright (C) 2022 Gnuxie <Gnuxie@protonmail.com>
* All rights reserved.
*/
import { defineMatrixInterfaceAdaptor, MatrixContext, MatrixInterfaceAdaptor } from '../../commands/interface-manager/MatrixInterfaceAdaptor';
import { MatrixSendClient } from '../../MatrixEmitter';
import { htmlEscape } from '../../utils';
import { UnstartedMjolnir } from '../MjolnirManager';
import { BaseFunction, defineInterfaceCommand } from '../../commands/interface-manager/InterfaceCommand';
import { findPresentationType, paramaters } from '../../commands/interface-manager/ParamaterParsing';
import { AppserviceBaseExecutor } from './AppserviceCommandHandler';
import { UserID } from 'matrix-bot-sdk';
import { CommandError, CommandResult } from '../../commands/interface-manager/Validation';
import { tickCrossRenderer } from '../../commands/interface-manager/MatrixHelpRenderer';
/**
* There is ovbiously something we're doing very wrong here,
* all just to satisfy type contstraints.
* Really there should only be `defineApplicationCommand`
* and `defineMatrixInterfaceCommand` but we have to do this
* long winded dance just to make type contstraints work.
* There might be a better way, but at what cost.
*/
const listUnstarted = defineInterfaceCommand<AppserviceBaseExecutor>({
designator: ["list", "unstarted"],
table: "appservice bot",
paramaters: paramaters([]),
command: async function() {
return CommandResult.Ok(this.appservice.mjolnirManager.getUnstartedMjolnirs());
},
summary: "List any Mjolnir that failed to start."
});
defineMatrixInterfaceAdaptor({
interfaceCommand: listUnstarted,
renderer: async function(this: MatrixInterfaceAdaptor<MatrixContext, BaseFunction>, client: MatrixSendClient, commandRoomId: string, event: any, result: CommandResult<UnstartedMjolnir[]>) {
tickCrossRenderer.call(this, client, commandRoomId, event, result); // don't await, it doesn't really matter.
if (result.isErr()) {
return; // just let the default handler deal with it.
}
const unstarted = result.ok;
let text = '';
let html = '';
html += `<b>Unstarted mjolnir: </b> ${unstarted.length}<br/>`;
text += `Unstarted mjolnir: ${unstarted.length}\n`;
html += "<li>";
for (const mjolnir of unstarted) {
html += `<ul>${htmlEscape(mjolnir.mjolnirRecord.owner)}, <code>${htmlEscape(mjolnir.mxid.toString())}</code>, <code>${mjolnir.failCode}</code>:\n${mjolnir.cause}</ul>`
text += ` * ${htmlEscape(mjolnir.mjolnirRecord.owner)}, ${htmlEscape(mjolnir.mxid.toString())}, ${mjolnir.failCode}: ${mjolnir.cause}`;
}
html += "</li>";
await client.sendMessage(commandRoomId, {
msgtype: 'm.notice',
body: text,
formatted_body: html,
});
}
})
// We need a "default" adaptor that needs to be explicitly defined still
// (since you need to know if you have not created an adaptor)
// but can be composed onto the end of existing adaptors easily
// e.g. read recipt and tick vs cross.
const restart = defineInterfaceCommand<AppserviceBaseExecutor>({
designator: ["restart"],
table: "appservice bot",
paramaters: paramaters([
{
name: "mjolnir",
acceptor: findPresentationType("UserID"),
}
]),
command: async(context, mjolnirId: UserID): Promise<CommandResult<true>> => {
const mjolnirManager = context.appservice.mjolnirManager;
const mjolnir = mjolnirManager.findUnstartedMjolnir(mjolnirId.localpart);
if (mjolnir?.mjolnirRecord === undefined) {
return CommandError.Result(`We can't find the unstarted mjolnir ${mjolnirId}, is it running?`);
}
await mjolnirManager.startMjolnir(mjolnir?.mjolnirRecord);
return CommandResult.Ok(true);
},
summary: "Attempt to restart a Mjolnir."
})
defineMatrixInterfaceAdaptor({
interfaceCommand: restart,
renderer: tickCrossRenderer
})