Refactor SlashCommands to not use MatrixClientPeg (#10905)
This commit is contained in:
parent
192e6f6c3d
commit
796ed35e75
7 changed files with 244 additions and 170 deletions
|
@ -26,8 +26,8 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||
import { IContent } from "matrix-js-sdk/src/models/event";
|
||||
import { MRoomTopicEventContent } from "matrix-js-sdk/src/@types/topic";
|
||||
import { SlashCommand as SlashCommandEvent } from "@matrix-org/analytics-events/types/typescript/SlashCommand";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import dis from "./dispatcher/dispatcher";
|
||||
import { _t, _td, UserFriendlyError } from "./languageHandler";
|
||||
import Modal from "./Modal";
|
||||
|
@ -75,7 +75,7 @@ interface HTMLInputEvent extends Event {
|
|||
target: HTMLInputElement & EventTarget;
|
||||
}
|
||||
|
||||
const singleMxcUpload = async (): Promise<string | null> => {
|
||||
const singleMxcUpload = async (cli: MatrixClient): Promise<string | null> => {
|
||||
return new Promise((resolve) => {
|
||||
const fileSelector = document.createElement("input");
|
||||
fileSelector.setAttribute("type", "file");
|
||||
|
@ -87,7 +87,7 @@ const singleMxcUpload = async (): Promise<string | null> => {
|
|||
file,
|
||||
onFinished: async (shouldContinue): Promise<void> => {
|
||||
if (shouldContinue) {
|
||||
const { content_uri: uri } = await MatrixClientPeg.get().uploadContent(file);
|
||||
const { content_uri: uri } = await cli.uploadContent(file);
|
||||
resolve(uri);
|
||||
} else {
|
||||
resolve(null);
|
||||
|
@ -111,7 +111,7 @@ export const CommandCategories = {
|
|||
|
||||
export type RunResult = XOR<{ error: Error }, { promise: Promise<IContent | undefined> }>;
|
||||
|
||||
type RunFn = (this: Command, roomId: string, args?: string) => RunResult;
|
||||
type RunFn = (this: Command, matrixClient: MatrixClient, roomId: string, args?: string) => RunResult;
|
||||
|
||||
interface ICommandOpts {
|
||||
command: string;
|
||||
|
@ -122,7 +122,7 @@ interface ICommandOpts {
|
|||
runFn?: RunFn;
|
||||
category: string;
|
||||
hideCompletionAfterSpace?: boolean;
|
||||
isEnabled?(): boolean;
|
||||
isEnabled?(matrixClient?: MatrixClient): boolean;
|
||||
renderingTypes?: TimelineRenderingType[];
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ export class Command {
|
|||
public readonly hideCompletionAfterSpace: boolean;
|
||||
public readonly renderingTypes?: TimelineRenderingType[];
|
||||
public readonly analyticsName?: SlashCommandEvent["command"];
|
||||
private readonly _isEnabled?: () => boolean;
|
||||
private readonly _isEnabled?: (matrixClient?: MatrixClient) => boolean;
|
||||
|
||||
public constructor(opts: ICommandOpts) {
|
||||
this.command = opts.command;
|
||||
|
@ -159,7 +159,7 @@ export class Command {
|
|||
return this.getCommand() + " " + this.args;
|
||||
}
|
||||
|
||||
public run(roomId: string, threadId: string | null, args?: string): RunResult {
|
||||
public run(matrixClient: MatrixClient, roomId: string, threadId: string | null, args?: string): RunResult {
|
||||
// if it has no runFn then its an ignored/nop command (autocomplete only) e.g `/me`
|
||||
if (!this.runFn) {
|
||||
return reject(new UserFriendlyError("Command error: Unable to handle slash command."));
|
||||
|
@ -182,15 +182,15 @@ export class Command {
|
|||
});
|
||||
}
|
||||
|
||||
return this.runFn(roomId, args);
|
||||
return this.runFn(matrixClient, roomId, args);
|
||||
}
|
||||
|
||||
public getUsage(): string {
|
||||
return _t("Usage") + ": " + this.getCommandWithArgs();
|
||||
}
|
||||
|
||||
public isEnabled(): boolean {
|
||||
return this._isEnabled ? this._isEnabled() : true;
|
||||
public isEnabled(cli?: MatrixClient): boolean {
|
||||
return this._isEnabled?.(cli) ?? true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,15 +206,21 @@ function successSync(value: any): RunResult {
|
|||
return success(Promise.resolve(value));
|
||||
}
|
||||
|
||||
const isCurrentLocalRoom = (): boolean => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const isCurrentLocalRoom = (cli?: MatrixClient): boolean => {
|
||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!roomId) return false;
|
||||
const room = cli.getRoom(roomId);
|
||||
const room = cli?.getRoom(roomId);
|
||||
if (!room) return false;
|
||||
return isLocalRoom(room);
|
||||
};
|
||||
|
||||
const canAffectPowerlevels = (cli?: MatrixClient): boolean => {
|
||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!cli || !roomId) return false;
|
||||
const room = cli?.getRoom(roomId);
|
||||
return !!room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getSafeUserId()) && !isLocalRoom(room);
|
||||
};
|
||||
|
||||
/* Disable the "unexpected this" error for these commands - all of the run
|
||||
* functions are called with `this` bound to the Command instance.
|
||||
*/
|
||||
|
@ -224,7 +230,7 @@ export const Commands = [
|
|||
command: "spoiler",
|
||||
args: "<message>",
|
||||
description: _td("Sends the given message as a spoiler"),
|
||||
runFn: function (roomId, message = "") {
|
||||
runFn: function (cli, roomId, message = "") {
|
||||
return successSync(ContentHelpers.makeHtmlMessage(message, `<span data-mx-spoiler>${message}</span>`));
|
||||
},
|
||||
category: CommandCategories.messages,
|
||||
|
@ -233,7 +239,7 @@ export const Commands = [
|
|||
command: "shrug",
|
||||
args: "<message>",
|
||||
description: _td("Prepends ¯\\_(ツ)_/¯ to a plain-text message"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let message = "¯\\_(ツ)_/¯";
|
||||
if (args) {
|
||||
message = message + " " + args;
|
||||
|
@ -246,7 +252,7 @@ export const Commands = [
|
|||
command: "tableflip",
|
||||
args: "<message>",
|
||||
description: _td("Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let message = "(╯°□°)╯︵ ┻━┻";
|
||||
if (args) {
|
||||
message = message + " " + args;
|
||||
|
@ -259,7 +265,7 @@ export const Commands = [
|
|||
command: "unflip",
|
||||
args: "<message>",
|
||||
description: _td("Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let message = "┬──┬ ノ( ゜-゜ノ)";
|
||||
if (args) {
|
||||
message = message + " " + args;
|
||||
|
@ -272,7 +278,7 @@ export const Commands = [
|
|||
command: "lenny",
|
||||
args: "<message>",
|
||||
description: _td("Prepends ( ͡° ͜ʖ ͡°) to a plain-text message"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let message = "( ͡° ͜ʖ ͡°)";
|
||||
if (args) {
|
||||
message = message + " " + args;
|
||||
|
@ -285,7 +291,7 @@ export const Commands = [
|
|||
command: "plain",
|
||||
args: "<message>",
|
||||
description: _td("Sends a message as plain text, without interpreting it as markdown"),
|
||||
runFn: function (roomId, messages = "") {
|
||||
runFn: function (cli, roomId, messages = "") {
|
||||
return successSync(ContentHelpers.makeTextMessage(messages));
|
||||
},
|
||||
category: CommandCategories.messages,
|
||||
|
@ -294,7 +300,7 @@ export const Commands = [
|
|||
command: "html",
|
||||
args: "<message>",
|
||||
description: _td("Sends a message as html, without interpreting it as markdown"),
|
||||
runFn: function (roomId, messages = "") {
|
||||
runFn: function (cli, roomId, messages = "") {
|
||||
return successSync(ContentHelpers.makeHtmlMessage(messages, messages));
|
||||
},
|
||||
category: CommandCategories.messages,
|
||||
|
@ -303,10 +309,9 @@ export const Commands = [
|
|||
command: "upgraderoom",
|
||||
args: "<new_version>",
|
||||
description: _td("Upgrades a room to a new version"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(roomId);
|
||||
if (!room?.currentState.mayClientSendStateEvent("m.room.tombstone", cli)) {
|
||||
return reject(
|
||||
|
@ -339,7 +344,7 @@ export const Commands = [
|
|||
args: "<YYYY-MM-DD>",
|
||||
description: _td("Jump to the given date in the timeline"),
|
||||
isEnabled: () => SettingsStore.getValue("feature_jump_to_date"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
return success(
|
||||
(async (): Promise<void> => {
|
||||
|
@ -352,7 +357,6 @@ export const Commands = [
|
|||
);
|
||||
}
|
||||
|
||||
const cli = MatrixClientPeg.get();
|
||||
const { event_id: eventId, origin_server_ts: originServerTs } = await cli.timestampToEvent(
|
||||
roomId,
|
||||
unixTimestamp,
|
||||
|
@ -381,9 +385,9 @@ export const Commands = [
|
|||
command: "nick",
|
||||
args: "<display_name>",
|
||||
description: _td("Changes your display nickname"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
return success(MatrixClientPeg.get().setDisplayName(args));
|
||||
return success(cli.setDisplayName(args));
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
},
|
||||
|
@ -395,16 +399,15 @@ export const Commands = [
|
|||
aliases: ["roomnick"],
|
||||
args: "<display_name>",
|
||||
description: _td("Changes your display nickname in the current room only"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const ev = cli.getRoom(roomId)?.currentState.getStateEvents("m.room.member", cli.getUserId()!);
|
||||
const ev = cli.getRoom(roomId)?.currentState.getStateEvents("m.room.member", cli.getSafeUserId());
|
||||
const content = {
|
||||
...(ev ? ev.getContent() : { membership: "join" }),
|
||||
displayname: args,
|
||||
};
|
||||
return success(cli.sendStateEvent(roomId, "m.room.member", content, cli.getUserId()!));
|
||||
return success(cli.sendStateEvent(roomId, "m.room.member", content, cli.getSafeUserId()));
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
},
|
||||
|
@ -415,17 +418,17 @@ export const Commands = [
|
|||
command: "roomavatar",
|
||||
args: "[<mxc_url>]",
|
||||
description: _td("Changes the avatar of the current room"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
let promise = Promise.resolve(args ?? null);
|
||||
if (!args) {
|
||||
promise = singleMxcUpload();
|
||||
promise = singleMxcUpload(cli);
|
||||
}
|
||||
|
||||
return success(
|
||||
promise.then((url) => {
|
||||
if (!url) return;
|
||||
return MatrixClientPeg.get().sendStateEvent(roomId, "m.room.avatar", { url }, "");
|
||||
return cli.sendStateEvent(roomId, "m.room.avatar", { url }, "");
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
@ -436,15 +439,14 @@ export const Commands = [
|
|||
command: "myroomavatar",
|
||||
args: "[<mxc_url>]",
|
||||
description: _td("Changes your avatar in this current room only"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
const room = cli.getRoom(roomId);
|
||||
const userId = cli.getUserId()!;
|
||||
const userId = cli.getSafeUserId();
|
||||
|
||||
let promise = Promise.resolve(args ?? null);
|
||||
if (!args) {
|
||||
promise = singleMxcUpload();
|
||||
promise = singleMxcUpload(cli);
|
||||
}
|
||||
|
||||
return success(
|
||||
|
@ -466,16 +468,16 @@ export const Commands = [
|
|||
command: "myavatar",
|
||||
args: "[<mxc_url>]",
|
||||
description: _td("Changes your avatar in all rooms"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let promise = Promise.resolve(args ?? null);
|
||||
if (!args) {
|
||||
promise = singleMxcUpload();
|
||||
promise = singleMxcUpload(cli);
|
||||
}
|
||||
|
||||
return success(
|
||||
promise.then((url) => {
|
||||
if (!url) return;
|
||||
return MatrixClientPeg.get().setAvatarUrl(url);
|
||||
return cli.setAvatarUrl(url);
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
@ -486,9 +488,8 @@ export const Commands = [
|
|||
command: "topic",
|
||||
args: "[<topic>]",
|
||||
description: _td("Gets or sets the room topic"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const html = htmlSerializeFromMdIfNeeded(args, { forceHTML: false });
|
||||
return success(cli.setRoomTopic(roomId, args, html));
|
||||
|
@ -525,10 +526,10 @@ export const Commands = [
|
|||
command: "roomname",
|
||||
args: "<name>",
|
||||
description: _td("Sets the room name"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
return success(MatrixClientPeg.get().setRoomName(roomId, args));
|
||||
return success(cli.setRoomName(roomId, args));
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
},
|
||||
|
@ -540,8 +541,8 @@ export const Commands = [
|
|||
args: "<user-id> [<reason>]",
|
||||
description: _td("Invites user with given id to current room"),
|
||||
analyticsName: "Invite",
|
||||
isEnabled: () => !isCurrentLocalRoom() && shouldShowComponent(UIComponent.InviteUsers),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli) && shouldShowComponent(UIComponent.InviteUsers),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const [address, reason] = args.split(/\s+(.+)/);
|
||||
if (address) {
|
||||
|
@ -551,10 +552,7 @@ export const Commands = [
|
|||
// get a bit more complex here, but we try to show something
|
||||
// meaningful.
|
||||
let prom = Promise.resolve();
|
||||
if (
|
||||
getAddressType(address) === AddressType.Email &&
|
||||
!MatrixClientPeg.get().getIdentityServerUrl()
|
||||
) {
|
||||
if (getAddressType(address) === AddressType.Email && !cli.getIdentityServerUrl()) {
|
||||
const defaultIdentityServerUrl = getDefaultIdentityServerUrl();
|
||||
if (defaultIdentityServerUrl) {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
|
@ -576,7 +574,7 @@ export const Commands = [
|
|||
|
||||
prom = finished.then(([useDefault]) => {
|
||||
if (useDefault) {
|
||||
setToDefaultIdentityServer(MatrixClientPeg.get());
|
||||
setToDefaultIdentityServer(cli);
|
||||
return;
|
||||
}
|
||||
throw new UserFriendlyError(
|
||||
|
@ -589,7 +587,7 @@ export const Commands = [
|
|||
);
|
||||
}
|
||||
}
|
||||
const inviter = new MultiInviter(MatrixClientPeg.get(), roomId);
|
||||
const inviter = new MultiInviter(cli, roomId);
|
||||
return success(
|
||||
prom
|
||||
.then(() => {
|
||||
|
@ -621,7 +619,7 @@ export const Commands = [
|
|||
aliases: ["j", "goto"],
|
||||
args: "<room-address>",
|
||||
description: _td("Joins room with given address"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
// Note: we support 2 versions of this command. The first is
|
||||
// the public-facing one for most users and the other is a
|
||||
|
@ -654,7 +652,7 @@ export const Commands = [
|
|||
if (params[0][0] === "#") {
|
||||
let roomAlias = params[0];
|
||||
if (!roomAlias.includes(":")) {
|
||||
roomAlias += ":" + MatrixClientPeg.get().getDomain();
|
||||
roomAlias += ":" + cli.getDomain();
|
||||
}
|
||||
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
|
@ -733,10 +731,8 @@ export const Commands = [
|
|||
args: "[<room-address>]",
|
||||
description: _td("Leave room"),
|
||||
analyticsName: "Part",
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
let targetRoomId: string | undefined;
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+)$/);
|
||||
|
@ -775,12 +771,12 @@ export const Commands = [
|
|||
aliases: ["kick"],
|
||||
args: "<user-id> [reason]",
|
||||
description: _td("Removes user with given id from this room"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+?)( +(.*))?$/);
|
||||
if (matches) {
|
||||
return success(MatrixClientPeg.get().kick(roomId, matches[1], matches[3]));
|
||||
return success(cli.kick(roomId, matches[1], matches[3]));
|
||||
}
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
|
@ -792,12 +788,12 @@ export const Commands = [
|
|||
command: "ban",
|
||||
args: "<user-id> [reason]",
|
||||
description: _td("Bans user with given id"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+?)( +(.*))?$/);
|
||||
if (matches) {
|
||||
return success(MatrixClientPeg.get().ban(roomId, matches[1], matches[3]));
|
||||
return success(cli.ban(roomId, matches[1], matches[3]));
|
||||
}
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
|
@ -809,13 +805,13 @@ export const Commands = [
|
|||
command: "unban",
|
||||
args: "<user-id>",
|
||||
description: _td("Unbans user with given ID"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+)$/);
|
||||
if (matches) {
|
||||
// Reset the user membership to "leave" to unban him
|
||||
return success(MatrixClientPeg.get().unban(roomId, matches[1]));
|
||||
return success(cli.unban(roomId, matches[1]));
|
||||
}
|
||||
}
|
||||
return reject(this.getUsage());
|
||||
|
@ -827,10 +823,8 @@ export const Commands = [
|
|||
command: "ignore",
|
||||
args: "<user-id>",
|
||||
description: _td("Ignores a user, hiding their messages from you"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
const matches = args.match(/^(@[^:]+:\S+)$/);
|
||||
if (matches) {
|
||||
const userId = matches[1];
|
||||
|
@ -858,10 +852,8 @@ export const Commands = [
|
|||
command: "unignore",
|
||||
args: "<user-id>",
|
||||
description: _td("Stops ignoring a user, showing their messages going forward"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
const matches = args.match(/(^@[^:]+:\S+$)/);
|
||||
if (matches) {
|
||||
const userId = matches[1];
|
||||
|
@ -890,17 +882,8 @@ export const Commands = [
|
|||
command: "op",
|
||||
args: "<user-id> [<power-level>]",
|
||||
description: _td("Define the power level of a user"),
|
||||
isEnabled(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!roomId) return false;
|
||||
const room = cli.getRoom(roomId);
|
||||
return (
|
||||
!!room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId()!) &&
|
||||
!isLocalRoom(room)
|
||||
);
|
||||
},
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: canAffectPowerlevels,
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+?)( +(-?\d+))?$/);
|
||||
let powerLevel = 50; // default power level for op
|
||||
|
@ -910,7 +893,6 @@ export const Commands = [
|
|||
powerLevel = parseInt(matches[3], 10);
|
||||
}
|
||||
if (!isNaN(powerLevel)) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(roomId);
|
||||
if (!room) {
|
||||
return reject(
|
||||
|
@ -941,21 +923,11 @@ export const Commands = [
|
|||
command: "deop",
|
||||
args: "<user-id>",
|
||||
description: _td("Deops user with given id"),
|
||||
isEnabled(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!roomId) return false;
|
||||
const room = cli.getRoom(roomId);
|
||||
return (
|
||||
!!room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId()!) &&
|
||||
!isLocalRoom(room)
|
||||
);
|
||||
},
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: canAffectPowerlevels,
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+)$/);
|
||||
if (matches) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(roomId);
|
||||
if (!room) {
|
||||
return reject(
|
||||
|
@ -981,7 +953,7 @@ export const Commands = [
|
|||
new Command({
|
||||
command: "devtools",
|
||||
description: _td("Opens the Developer Tools dialog"),
|
||||
runFn: function (roomId) {
|
||||
runFn: function (cli, roomId) {
|
||||
Modal.createDialog(DevtoolsDialog, { roomId }, "mx_DevtoolsDialog_wrapper");
|
||||
return success();
|
||||
},
|
||||
|
@ -991,11 +963,11 @@ export const Commands = [
|
|||
command: "addwidget",
|
||||
args: "<url | embed code | Jitsi url>",
|
||||
description: _td("Adds a custom widget by URL to the room"),
|
||||
isEnabled: () =>
|
||||
isEnabled: (cli) =>
|
||||
SettingsStore.getValue(UIFeature.Widgets) &&
|
||||
shouldShowComponent(UIComponent.AddIntegrations) &&
|
||||
!isCurrentLocalRoom(),
|
||||
runFn: function (roomId, widgetUrl) {
|
||||
!isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, widgetUrl) {
|
||||
if (!widgetUrl) {
|
||||
return reject(new UserFriendlyError("Please supply a widget URL or embed code"));
|
||||
}
|
||||
|
@ -1005,12 +977,12 @@ export const Commands = [
|
|||
const embed = new DOMParser().parseFromString(widgetUrl, "text/html").body;
|
||||
if (embed?.childNodes?.length === 1) {
|
||||
const iframe = embed.firstElementChild;
|
||||
if (iframe.tagName.toLowerCase() === "iframe") {
|
||||
if (iframe?.tagName.toLowerCase() === "iframe") {
|
||||
logger.log("Pulling URL out of iframe (embed code)");
|
||||
if (!iframe.hasAttribute("src")) {
|
||||
return reject(new UserFriendlyError("iframe has no src attribute"));
|
||||
}
|
||||
widgetUrl = iframe.getAttribute("src");
|
||||
widgetUrl = iframe.getAttribute("src")!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1018,8 +990,8 @@ export const Commands = [
|
|||
if (!widgetUrl.startsWith("https://") && !widgetUrl.startsWith("http://")) {
|
||||
return reject(new UserFriendlyError("Please supply a https:// or http:// widget URL"));
|
||||
}
|
||||
if (WidgetUtils.canUserModifyWidgets(MatrixClientPeg.get(), roomId)) {
|
||||
const userId = MatrixClientPeg.get().getUserId();
|
||||
if (WidgetUtils.canUserModifyWidgets(cli, roomId)) {
|
||||
const userId = cli.getUserId();
|
||||
const nowMs = new Date().getTime();
|
||||
const widgetId = encodeURIComponent(`${roomId}_${userId}_${nowMs}`);
|
||||
let type = WidgetType.CUSTOM;
|
||||
|
@ -1036,9 +1008,7 @@ export const Commands = [
|
|||
widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl();
|
||||
}
|
||||
|
||||
return success(
|
||||
WidgetUtils.setRoomWidget(MatrixClientPeg.get(), roomId, widgetId, type, widgetUrl, name, data),
|
||||
);
|
||||
return success(WidgetUtils.setRoomWidget(cli, roomId, widgetId, type, widgetUrl, name, data));
|
||||
} else {
|
||||
return reject(new UserFriendlyError("You cannot modify widgets in this room."));
|
||||
}
|
||||
|
@ -1050,12 +1020,10 @@ export const Commands = [
|
|||
command: "verify",
|
||||
args: "<user-id> <device-id> <device-signing-key>",
|
||||
description: _td("Verifies a user, session, and pubkey tuple"),
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
const matches = args.match(/^(\S+) +(\S+) +(\S+)$/);
|
||||
if (matches) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
const userId = matches[1];
|
||||
const deviceId = matches[2];
|
||||
const fingerprint = matches[3];
|
||||
|
@ -1130,10 +1098,10 @@ export const Commands = [
|
|||
new Command({
|
||||
command: "discardsession",
|
||||
description: _td("Forces the current outbound group session in an encrypted room to be discarded"),
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId) {
|
||||
try {
|
||||
MatrixClientPeg.get().forceDiscardSession(roomId);
|
||||
cli.forceDiscardSession(roomId);
|
||||
} catch (e) {
|
||||
return reject(e.message);
|
||||
}
|
||||
|
@ -1145,19 +1113,19 @@ export const Commands = [
|
|||
new Command({
|
||||
command: "remakeolm",
|
||||
description: _td("Developer command: Discards the current outbound group session and sets up new Olm sessions"),
|
||||
isEnabled: () => {
|
||||
return SettingsStore.getValue("developerMode") && !isCurrentLocalRoom();
|
||||
isEnabled: (cli) => {
|
||||
return SettingsStore.getValue("developerMode") && !isCurrentLocalRoom(cli);
|
||||
},
|
||||
runFn: (roomId) => {
|
||||
runFn: (cli, roomId) => {
|
||||
try {
|
||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||
const room = cli.getRoom(roomId);
|
||||
|
||||
MatrixClientPeg.get().forceDiscardSession(roomId);
|
||||
cli.forceDiscardSession(roomId);
|
||||
|
||||
return success(
|
||||
room?.getEncryptionTargetMembers().then((members) => {
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
MatrixClientPeg.get().crypto?.ensureOlmSessionsForUsers(
|
||||
cli.crypto?.ensureOlmSessionsForUsers(
|
||||
members.map((m) => m.userId),
|
||||
true,
|
||||
);
|
||||
|
@ -1174,7 +1142,7 @@ export const Commands = [
|
|||
command: "rainbow",
|
||||
description: _td("Sends the given message coloured as a rainbow"),
|
||||
args: "<message>",
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (!args) return reject(this.getUsage());
|
||||
return successSync(ContentHelpers.makeHtmlMessage(args, textToHtmlRainbow(args)));
|
||||
},
|
||||
|
@ -1184,7 +1152,7 @@ export const Commands = [
|
|||
command: "rainbowme",
|
||||
description: _td("Sends the given emote coloured as a rainbow"),
|
||||
args: "<message>",
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (!args) return reject(this.getUsage());
|
||||
return successSync(ContentHelpers.makeHtmlEmote(args, textToHtmlRainbow(args)));
|
||||
},
|
||||
|
@ -1203,13 +1171,13 @@ export const Commands = [
|
|||
command: "whois",
|
||||
description: _td("Displays information about a user"),
|
||||
args: "<user-id>",
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, userId) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, userId) {
|
||||
if (!userId || !userId.startsWith("@") || !userId.includes(":")) {
|
||||
return reject(this.getUsage());
|
||||
}
|
||||
|
||||
const member = MatrixClientPeg.get().getRoom(roomId)?.getMember(userId);
|
||||
const member = cli.getRoom(roomId)?.getMember(userId);
|
||||
dis.dispatch<ViewUserPayload>({
|
||||
action: Action.ViewUser,
|
||||
// XXX: We should be using a real member object and not assuming what the receiver wants.
|
||||
|
@ -1225,7 +1193,7 @@ export const Commands = [
|
|||
description: _td("Send a bug report with logs"),
|
||||
isEnabled: () => !!SdkConfig.get().bug_report_endpoint_url,
|
||||
args: "<description>",
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
return success(
|
||||
Modal.createDialog(BugReportDialog, {
|
||||
initialText: args,
|
||||
|
@ -1238,10 +1206,10 @@ export const Commands = [
|
|||
command: "tovirtual",
|
||||
description: _td("Switches to this room's virtual room, if it has one"),
|
||||
category: CommandCategories.advanced,
|
||||
isEnabled(): boolean {
|
||||
return !!LegacyCallHandler.instance.getSupportsVirtualRooms() && !isCurrentLocalRoom();
|
||||
isEnabled(cli): boolean {
|
||||
return !!LegacyCallHandler.instance.getSupportsVirtualRooms() && !isCurrentLocalRoom(cli);
|
||||
},
|
||||
runFn: (roomId) => {
|
||||
runFn: (cli, roomId) => {
|
||||
return success(
|
||||
(async (): Promise<void> => {
|
||||
const room = await VoipUserMapper.sharedInstance().getVirtualRoomForRoom(roomId);
|
||||
|
@ -1260,7 +1228,7 @@ export const Commands = [
|
|||
command: "query",
|
||||
description: _td("Opens chat with the given user"),
|
||||
args: "<user-id>",
|
||||
runFn: function (roomId, userId) {
|
||||
runFn: function (cli, roomId, userId) {
|
||||
// easter-egg for now: look up phone numbers through the thirdparty API
|
||||
// (very dumb phone number detection...)
|
||||
const isPhoneNumber = userId && /^\+?[0123456789]+$/.test(userId);
|
||||
|
@ -1278,7 +1246,7 @@ export const Commands = [
|
|||
userId = results[0].userid;
|
||||
}
|
||||
|
||||
const roomId = await ensureDMExists(MatrixClientPeg.get(), userId);
|
||||
const roomId = await ensureDMExists(cli, userId);
|
||||
if (!roomId) throw new Error("Failed to ensure DM exists");
|
||||
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
|
@ -1296,7 +1264,7 @@ export const Commands = [
|
|||
command: "msg",
|
||||
description: _td("Sends a message to the given user"),
|
||||
args: "<user-id> [<message>]",
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
if (args) {
|
||||
// matches the first whitespace delimited group and then the rest of the string
|
||||
const matches = args.match(/^(\S+?)(?: +(.*))?$/s);
|
||||
|
@ -1305,7 +1273,6 @@ export const Commands = [
|
|||
if (userId && userId.startsWith("@") && userId.includes(":")) {
|
||||
return success(
|
||||
(async (): Promise<void> => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomId = await ensureDMExists(cli, userId);
|
||||
if (!roomId) throw new Error("Failed to ensure DM exists");
|
||||
|
||||
|
@ -1332,8 +1299,8 @@ export const Commands = [
|
|||
command: "holdcall",
|
||||
description: _td("Places the call in the current room on hold"),
|
||||
category: CommandCategories.other,
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
const call = LegacyCallHandler.instance.getCallForRoom(roomId);
|
||||
if (!call) {
|
||||
return reject(new UserFriendlyError("No active call in this room"));
|
||||
|
@ -1347,8 +1314,8 @@ export const Commands = [
|
|||
command: "unholdcall",
|
||||
description: _td("Takes the call in the current room off hold"),
|
||||
category: CommandCategories.other,
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
const call = LegacyCallHandler.instance.getCallForRoom(roomId);
|
||||
if (!call) {
|
||||
return reject(new UserFriendlyError("No active call in this room"));
|
||||
|
@ -1362,9 +1329,9 @@ export const Commands = [
|
|||
command: "converttodm",
|
||||
description: _td("Converts the room to a DM"),
|
||||
category: CommandCategories.other,
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
const room = cli.getRoom(roomId);
|
||||
if (!room) return reject(new UserFriendlyError("Could not find room"));
|
||||
return success(guessAndSetDMRoom(room, true));
|
||||
},
|
||||
|
@ -1374,9 +1341,9 @@ export const Commands = [
|
|||
command: "converttoroom",
|
||||
description: _td("Converts the DM to a room"),
|
||||
category: CommandCategories.other,
|
||||
isEnabled: () => !isCurrentLocalRoom(),
|
||||
runFn: function (roomId, args) {
|
||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||
isEnabled: (cli) => !isCurrentLocalRoom(cli),
|
||||
runFn: function (cli, roomId, args) {
|
||||
const room = cli.getRoom(roomId);
|
||||
if (!room) return reject(new UserFriendlyError("Could not find room"));
|
||||
return success(guessAndSetDMRoom(room, false));
|
||||
},
|
||||
|
@ -1398,7 +1365,7 @@ export const Commands = [
|
|||
command: effect.command,
|
||||
description: effect.description(),
|
||||
args: "<message>",
|
||||
runFn: function (roomId, args) {
|
||||
runFn: function (cli, roomId, args) {
|
||||
let content: IContent;
|
||||
if (!args) {
|
||||
content = ContentHelpers.makeEmoteMessage(effect.fallbackMessage());
|
||||
|
|
|
@ -341,7 +341,13 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
|||
const [cmd, args, commandText] = getSlashCommand(this.model);
|
||||
if (cmd) {
|
||||
const threadId = editedEvent?.getThread()?.id || null;
|
||||
const [content, commandSuccessful] = await runSlashCommand(cmd, args, roomId, threadId);
|
||||
const [content, commandSuccessful] = await runSlashCommand(
|
||||
MatrixClientPeg.get(),
|
||||
cmd,
|
||||
args,
|
||||
roomId,
|
||||
threadId,
|
||||
);
|
||||
if (!commandSuccessful) {
|
||||
return; // errored
|
||||
}
|
||||
|
|
|
@ -474,6 +474,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
|
|||
|
||||
let commandSuccessful: boolean;
|
||||
[content, commandSuccessful] = await runSlashCommand(
|
||||
MatrixClientPeg.get(),
|
||||
cmd,
|
||||
args,
|
||||
this.props.room.roomId,
|
||||
|
|
|
@ -85,7 +85,7 @@ export async function sendMessage(
|
|||
if (cmd) {
|
||||
const threadId = relation?.rel_type === THREAD_RELATION_TYPE.name ? relation?.event_id : null;
|
||||
let commandSuccessful: boolean;
|
||||
[content, commandSuccessful] = await runSlashCommand(cmd, args, roomId, threadId ?? null);
|
||||
[content, commandSuccessful] = await runSlashCommand(mxClient, cmd, args, roomId, threadId ?? null);
|
||||
|
||||
if (!commandSuccessful) {
|
||||
return; // errored
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { IContent } from "matrix-js-sdk/src/models/event";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import EditorModel from "./model";
|
||||
import { Type } from "./parts";
|
||||
|
@ -58,12 +59,13 @@ export function getSlashCommand(model: EditorModel): [Command | undefined, strin
|
|||
}
|
||||
|
||||
export async function runSlashCommand(
|
||||
matrixClient: MatrixClient,
|
||||
cmd: Command,
|
||||
args: string | undefined,
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
): Promise<[content: IContent | null, success: boolean]> {
|
||||
const result = cmd.run(roomId, threadId, args);
|
||||
const result = cmd.run(matrixClient, roomId, threadId, args);
|
||||
let messageContent: IContent | null = null;
|
||||
let error: any = result.error;
|
||||
if (result.promise) {
|
||||
|
|
|
@ -19,11 +19,13 @@ import { mocked } from "jest-mock";
|
|||
|
||||
import { Command, Commands, getCommand } from "../src/SlashCommands";
|
||||
import { createTestClient } from "./test-utils";
|
||||
import { MatrixClientPeg } from "../src/MatrixClientPeg";
|
||||
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../src/models/LocalRoom";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import LegacyCallHandler from "../src/LegacyCallHandler";
|
||||
import { SdkContextClass } from "../src/contexts/SDKContext";
|
||||
import Modal from "../src/Modal";
|
||||
import WidgetUtils from "../src/utils/WidgetUtils";
|
||||
import { WidgetType } from "../src/widgets/WidgetType";
|
||||
|
||||
describe("SlashCommands", () => {
|
||||
let client: MatrixClient;
|
||||
|
@ -57,7 +59,6 @@ describe("SlashCommands", () => {
|
|||
jest.clearAllMocks();
|
||||
|
||||
client = createTestClient();
|
||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(client);
|
||||
|
||||
room = new Room(roomId, client, client.getUserId()!);
|
||||
localRoom = new LocalRoom(localRoomId, client, client.getUserId()!);
|
||||
|
@ -70,9 +71,16 @@ describe("SlashCommands", () => {
|
|||
const command = getCommand("/topic pizza");
|
||||
expect(command.cmd).toBeDefined();
|
||||
expect(command.args).toBeDefined();
|
||||
await command.cmd!.run("room-id", null, command.args);
|
||||
await command.cmd!.run(client, "room-id", null, command.args);
|
||||
expect(client.setRoomTopic).toHaveBeenCalledWith("room-id", "pizza", undefined);
|
||||
});
|
||||
|
||||
it("should show topic modal if no args passed", async () => {
|
||||
const spy = jest.spyOn(Modal, "createDialog");
|
||||
const command = getCommand("/topic")!;
|
||||
await command.cmd!.run(client, roomId, null);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe.each([
|
||||
|
@ -104,12 +112,12 @@ describe("SlashCommands", () => {
|
|||
describe("isEnabled", () => {
|
||||
it("should return true for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled()).toBe(true);
|
||||
expect(command.isEnabled(client)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoon();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -127,12 +135,12 @@ describe("SlashCommands", () => {
|
|||
|
||||
it("should return true for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled()).toBe(true);
|
||||
expect(command.isEnabled(client)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoon();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -143,12 +151,12 @@ describe("SlashCommands", () => {
|
|||
|
||||
it("should return false for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoon();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -169,12 +177,12 @@ describe("SlashCommands", () => {
|
|||
|
||||
it("should return true for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled()).toBe(true);
|
||||
expect(command.isEnabled(client)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoon();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -187,12 +195,12 @@ describe("SlashCommands", () => {
|
|||
|
||||
it("should return false for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoon();
|
||||
expect(command.isEnabled()).toBe(false);
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -209,7 +217,7 @@ describe("SlashCommands", () => {
|
|||
const command = getCommand("/part #foo:bar");
|
||||
expect(command.cmd).toBeDefined();
|
||||
expect(command.args).toBeDefined();
|
||||
await command.cmd!.run("room-id", null, command.args);
|
||||
await command.cmd!.run(client, "room-id", null, command.args);
|
||||
expect(client.leaveRoomChain).toHaveBeenCalledWith("room-id", expect.anything());
|
||||
});
|
||||
|
||||
|
@ -223,7 +231,7 @@ describe("SlashCommands", () => {
|
|||
const command = getCommand("/part #foo:bar");
|
||||
expect(command.cmd).toBeDefined();
|
||||
expect(command.args).toBeDefined();
|
||||
await command.cmd!.run("room-id", null, command.args!);
|
||||
await command.cmd!.run(client, "room-id", null, command.args!);
|
||||
expect(client.leaveRoomChain).toHaveBeenCalledWith("room-id", expect.anything());
|
||||
});
|
||||
});
|
||||
|
@ -232,11 +240,45 @@ describe("SlashCommands", () => {
|
|||
const command = findCommand(commandName)!;
|
||||
|
||||
it("should return usage if no args", () => {
|
||||
expect(command.run(roomId, null, undefined).error).toBe(command.getUsage());
|
||||
expect(command.run(client, roomId, null, undefined).error).toBe(command.getUsage());
|
||||
});
|
||||
|
||||
it("should make things rainbowy", () => {
|
||||
return expect(command.run(roomId, null, "this is a test message").promise).resolves.toMatchSnapshot();
|
||||
return expect(
|
||||
command.run(client, roomId, null, "this is a test message").promise,
|
||||
).resolves.toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(["shrug", "tableflip", "unflip", "lenny"])("/%s", (commandName: string) => {
|
||||
const command = findCommand(commandName)!;
|
||||
|
||||
it("should match snapshot with no args", () => {
|
||||
return expect(command.run(client, roomId, null).promise).resolves.toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should match snapshot with args", () => {
|
||||
return expect(
|
||||
command.run(client, roomId, null, "this is a test message").promise,
|
||||
).resolves.toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("/addwidget", () => {
|
||||
it("should parse html iframe snippets", async () => {
|
||||
jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(true);
|
||||
const spy = jest.spyOn(WidgetUtils, "setRoomWidget");
|
||||
const command = findCommand("addwidget")!;
|
||||
await command.run(client, roomId, null, '<iframe src="https://element.io"></iframe>');
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
client,
|
||||
roomId,
|
||||
expect.any(String),
|
||||
WidgetType.CUSTOM,
|
||||
"https://element.io",
|
||||
"Custom",
|
||||
{},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SlashCommands /lenny should match snapshot with args 1`] = `
|
||||
{
|
||||
"body": "( ͡° ͜ʖ ͡°) this is a test message",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /lenny should match snapshot with no args 1`] = `
|
||||
{
|
||||
"body": "( ͡° ͜ʖ ͡°)",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /rainbow should make things rainbowy 1`] = `
|
||||
{
|
||||
"body": "this is a test message",
|
||||
|
@ -17,3 +31,45 @@ exports[`SlashCommands /rainbowme should make things rainbowy 1`] = `
|
|||
"msgtype": "m.emote",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /shrug should match snapshot with args 1`] = `
|
||||
{
|
||||
"body": "¯\\_(ツ)_/¯ this is a test message",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /shrug should match snapshot with no args 1`] = `
|
||||
{
|
||||
"body": "¯\\_(ツ)_/¯",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /tableflip should match snapshot with args 1`] = `
|
||||
{
|
||||
"body": "(╯°□°)╯︵ ┻━┻ this is a test message",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /tableflip should match snapshot with no args 1`] = `
|
||||
{
|
||||
"body": "(╯°□°)╯︵ ┻━┻",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /unflip should match snapshot with args 1`] = `
|
||||
{
|
||||
"body": "┬──┬ ノ( ゜-゜ノ) this is a test message",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`SlashCommands /unflip should match snapshot with no args 1`] = `
|
||||
{
|
||||
"body": "┬──┬ ノ( ゜-゜ノ)",
|
||||
"msgtype": "m.text",
|
||||
}
|
||||
`;
|
||||
|
|
Loading…
Reference in a new issue