You've already forked matrix-react-sdk
							
							
				mirror of
				https://github.com/matrix-org/matrix-react-sdk.git
				synced 2025-11-04 11:51:45 +03:00 
			
		
		
		
	rework SlashCommands to better expose aliases
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
				
			|||||||
Copyright 2015, 2016 OpenMarket Ltd
 | 
					Copyright 2015, 2016 OpenMarket Ltd
 | 
				
			||||||
Copyright 2018 New Vector Ltd
 | 
					Copyright 2018 New Vector Ltd
 | 
				
			||||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
 | 
					Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
 | 
				
			||||||
 | 
					Copyright 2020 The Matrix.org Foundation C.I.C.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
you may not use this file except in compliance with the License.
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
@@ -17,7 +18,8 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import * as React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {MatrixClientPeg} from './MatrixClientPeg';
 | 
					import {MatrixClientPeg} from './MatrixClientPeg';
 | 
				
			||||||
import dis from './dispatcher';
 | 
					import dis from './dispatcher';
 | 
				
			||||||
import * as sdk from './index';
 | 
					import * as sdk from './index';
 | 
				
			||||||
@@ -34,11 +36,16 @@ import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/I
 | 
				
			|||||||
import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks";
 | 
					import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks";
 | 
				
			||||||
import {inviteUsersToRoom} from "./RoomInvite";
 | 
					import {inviteUsersToRoom} from "./RoomInvite";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const singleMxcUpload = async () => {
 | 
					// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
 | 
				
			||||||
 | 
					interface HTMLInputEvent extends Event {
 | 
				
			||||||
 | 
					    target: HTMLInputElement & EventTarget;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const singleMxcUpload = async (): Promise<any> => {
 | 
				
			||||||
    return new Promise((resolve) => {
 | 
					    return new Promise((resolve) => {
 | 
				
			||||||
        const fileSelector = document.createElement('input');
 | 
					        const fileSelector = document.createElement('input');
 | 
				
			||||||
        fileSelector.setAttribute('type', 'file');
 | 
					        fileSelector.setAttribute('type', 'file');
 | 
				
			||||||
        fileSelector.onchange = (ev) => {
 | 
					        fileSelector.onchange = (ev: HTMLInputEvent) => {
 | 
				
			||||||
            const file = ev.target.files[0];
 | 
					            const file = ev.target.files[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
 | 
					            const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
 | 
				
			||||||
@@ -62,9 +69,36 @@ export const CommandCategories = {
 | 
				
			|||||||
    "other": _td("Other"),
 | 
					    "other": _td("Other"),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RunFn = ((roomId: string, args: string, cmd: string) => {error: any} | {promise: Promise<any>});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Command {
 | 
					class Command {
 | 
				
			||||||
    constructor({name, args='', description, runFn, category=CommandCategories.other, hideCompletionAfterSpace=false}) {
 | 
					    command: string;
 | 
				
			||||||
        this.command = '/' + name;
 | 
					    aliases: string[];
 | 
				
			||||||
 | 
					    args: undefined | string;
 | 
				
			||||||
 | 
					    description: string;
 | 
				
			||||||
 | 
					    runFn: undefined | RunFn;
 | 
				
			||||||
 | 
					    category: string;
 | 
				
			||||||
 | 
					    hideCompletionAfterSpace: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor({
 | 
				
			||||||
 | 
					        command,
 | 
				
			||||||
 | 
					        aliases=[],
 | 
				
			||||||
 | 
					        args='',
 | 
				
			||||||
 | 
					        description,
 | 
				
			||||||
 | 
					        runFn=undefined,
 | 
				
			||||||
 | 
					        category=CommandCategories.other,
 | 
				
			||||||
 | 
					        hideCompletionAfterSpace=false,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        command: string;
 | 
				
			||||||
 | 
					        aliases?: string[];
 | 
				
			||||||
 | 
					        args?: string;
 | 
				
			||||||
 | 
					        description: string;
 | 
				
			||||||
 | 
					        runFn?: RunFn;
 | 
				
			||||||
 | 
					        category: string;
 | 
				
			||||||
 | 
					        hideCompletionAfterSpace?: boolean;
 | 
				
			||||||
 | 
					    }) {
 | 
				
			||||||
 | 
					        this.command = command;
 | 
				
			||||||
 | 
					        this.aliases = aliases;
 | 
				
			||||||
        this.args = args;
 | 
					        this.args = args;
 | 
				
			||||||
        this.description = description;
 | 
					        this.description = description;
 | 
				
			||||||
        this.runFn = runFn;
 | 
					        this.runFn = runFn;
 | 
				
			||||||
@@ -73,17 +107,17 @@ class Command {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getCommand() {
 | 
					    getCommand() {
 | 
				
			||||||
        return this.command;
 | 
					        return `/${this.command}`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getCommandWithArgs() {
 | 
					    getCommandWithArgs() {
 | 
				
			||||||
        return this.getCommand() + " " + this.args;
 | 
					        return this.getCommand() + " " + this.args;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    run(roomId, args) {
 | 
					    run(roomId: string, args: string, cmd: string) {
 | 
				
			||||||
        // if it has no runFn then its an ignored/nop command (autocomplete only) e.g `/me`
 | 
					        // if it has no runFn then its an ignored/nop command (autocomplete only) e.g `/me`
 | 
				
			||||||
        if (!this.runFn) return;
 | 
					        if (!this.runFn) return;
 | 
				
			||||||
        return this.runFn.bind(this)(roomId, args);
 | 
					        return this.runFn.bind(this)(roomId, args, cmd);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getUsage() {
 | 
					    getUsage() {
 | 
				
			||||||
@@ -95,7 +129,7 @@ function reject(error) {
 | 
				
			|||||||
    return {error};
 | 
					    return {error};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function success(promise) {
 | 
					function success(promise?: Promise<any>) {
 | 
				
			||||||
    return {promise};
 | 
					    return {promise};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -103,11 +137,9 @@ function success(promise) {
 | 
				
			|||||||
 * functions are called with `this` bound to the Command instance.
 | 
					 * functions are called with `this` bound to the Command instance.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-disable babel/no-invalid-this */
 | 
					export const Commands = [
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
export const CommandMap = {
 | 
					        command: 'shrug',
 | 
				
			||||||
    shrug: new Command({
 | 
					 | 
				
			||||||
        name: 'shrug',
 | 
					 | 
				
			||||||
        args: '<message>',
 | 
					        args: '<message>',
 | 
				
			||||||
        description: _td('Prepends ¯\\_(ツ)_/¯ to a plain-text message'),
 | 
					        description: _td('Prepends ¯\\_(ツ)_/¯ to a plain-text message'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -119,8 +151,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.messages,
 | 
					        category: CommandCategories.messages,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
    plain: new Command({
 | 
					    new Command({
 | 
				
			||||||
        name: 'plain',
 | 
					        command: 'plain',
 | 
				
			||||||
        args: '<message>',
 | 
					        args: '<message>',
 | 
				
			||||||
        description: _td('Sends a message as plain text, without interpreting it as markdown'),
 | 
					        description: _td('Sends a message as plain text, without interpreting it as markdown'),
 | 
				
			||||||
        runFn: function(roomId, messages) {
 | 
					        runFn: function(roomId, messages) {
 | 
				
			||||||
@@ -128,11 +160,11 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.messages,
 | 
					        category: CommandCategories.messages,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
    ddg: new Command({
 | 
					    new Command({
 | 
				
			||||||
        name: 'ddg',
 | 
					        command: 'ddg',
 | 
				
			||||||
        args: '<query>',
 | 
					        args: '<query>',
 | 
				
			||||||
        description: _td('Searches DuckDuckGo for results'),
 | 
					        description: _td('Searches DuckDuckGo for results'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function() {
 | 
				
			||||||
            const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
 | 
					            const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
 | 
				
			||||||
            // TODO Don't explain this away, actually show a search UI here.
 | 
					            // TODO Don't explain this away, actually show a search UI here.
 | 
				
			||||||
            Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
 | 
					            Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
 | 
				
			||||||
@@ -144,9 +176,8 @@ export const CommandMap = {
 | 
				
			|||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
        hideCompletionAfterSpace: true,
 | 
					        hideCompletionAfterSpace: true,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    upgraderoom: new Command({
 | 
					        command: 'upgraderoom',
 | 
				
			||||||
        name: 'upgraderoom',
 | 
					 | 
				
			||||||
        args: '<new_version>',
 | 
					        args: '<new_version>',
 | 
				
			||||||
        description: _td('Upgrades a room to a new version'),
 | 
					        description: _td('Upgrades a room to a new version'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -215,9 +246,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    nick: new Command({
 | 
					        command: 'nick',
 | 
				
			||||||
        name: 'nick',
 | 
					 | 
				
			||||||
        args: '<display_name>',
 | 
					        args: '<display_name>',
 | 
				
			||||||
        description: _td('Changes your display nickname'),
 | 
					        description: _td('Changes your display nickname'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -228,9 +258,9 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    myroomnick: new Command({
 | 
					        command: 'myroomnick',
 | 
				
			||||||
        name: 'myroomnick',
 | 
					        aliases: ['roomnick'],
 | 
				
			||||||
        args: '<display_name>',
 | 
					        args: '<display_name>',
 | 
				
			||||||
        description: _td('Changes your display nickname in the current room only'),
 | 
					        description: _td('Changes your display nickname in the current room only'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -239,7 +269,7 @@ export const CommandMap = {
 | 
				
			|||||||
                const ev = cli.getRoom(roomId).currentState.getStateEvents('m.room.member', cli.getUserId());
 | 
					                const ev = cli.getRoom(roomId).currentState.getStateEvents('m.room.member', cli.getUserId());
 | 
				
			||||||
                const content = {
 | 
					                const content = {
 | 
				
			||||||
                    ...ev ? ev.getContent() : { membership: 'join' },
 | 
					                    ...ev ? ev.getContent() : { membership: 'join' },
 | 
				
			||||||
                    displayname: args,
 | 
					                    displaycommand: args,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                return success(cli.sendStateEvent(roomId, 'm.room.member', content, cli.getUserId()));
 | 
					                return success(cli.sendStateEvent(roomId, 'm.room.member', content, cli.getUserId()));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -247,9 +277,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    roomavatar: new Command({
 | 
					        command: 'roomavatar',
 | 
				
			||||||
        name: 'roomavatar',
 | 
					 | 
				
			||||||
        args: '[<mxc_url>]',
 | 
					        args: '[<mxc_url>]',
 | 
				
			||||||
        description: _td('Changes the avatar of the current room'),
 | 
					        description: _td('Changes the avatar of the current room'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -265,9 +294,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    myroomavatar: new Command({
 | 
					        command: 'myroomavatar',
 | 
				
			||||||
        name: 'myroomavatar',
 | 
					 | 
				
			||||||
        args: '[<mxc_url>]',
 | 
					        args: '[<mxc_url>]',
 | 
				
			||||||
        description: _td('Changes your avatar in this current room only'),
 | 
					        description: _td('Changes your avatar in this current room only'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -292,9 +320,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    myavatar: new Command({
 | 
					        command: 'myavatar',
 | 
				
			||||||
        name: 'myavatar',
 | 
					 | 
				
			||||||
        args: '[<mxc_url>]',
 | 
					        args: '[<mxc_url>]',
 | 
				
			||||||
        description: _td('Changes your avatar in all rooms'),
 | 
					        description: _td('Changes your avatar in all rooms'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -310,9 +337,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    topic: new Command({
 | 
					        command: 'topic',
 | 
				
			||||||
        name: 'topic',
 | 
					 | 
				
			||||||
        args: '[<topic>]',
 | 
					        args: '[<topic>]',
 | 
				
			||||||
        description: _td('Gets or sets the room topic'),
 | 
					        description: _td('Gets or sets the room topic'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -336,9 +362,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    roomname: new Command({
 | 
					        command: 'roomname',
 | 
				
			||||||
        name: 'roomname',
 | 
					 | 
				
			||||||
        args: '<name>',
 | 
					        args: '<name>',
 | 
				
			||||||
        description: _td('Sets the room name'),
 | 
					        description: _td('Sets the room name'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -349,9 +374,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    invite: new Command({
 | 
					        command: 'invite',
 | 
				
			||||||
        name: 'invite',
 | 
					 | 
				
			||||||
        args: '<user-id>',
 | 
					        args: '<user-id>',
 | 
				
			||||||
        description: _td('Invites user with given id to current room'),
 | 
					        description: _td('Invites user with given id to current room'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -390,7 +414,7 @@ export const CommandMap = {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    const inviter = new MultiInviter(roomId);
 | 
					                    const inviter = new MultiInviter(roomId);
 | 
				
			||||||
                    return success(finished.then(([useDefault] = []) => {
 | 
					                    return success(finished.then(([useDefault]: any) => {
 | 
				
			||||||
                        if (useDefault) {
 | 
					                        if (useDefault) {
 | 
				
			||||||
                            useDefaultIdentityServer();
 | 
					                            useDefaultIdentityServer();
 | 
				
			||||||
                        } else if (useDefault === false) {
 | 
					                        } else if (useDefault === false) {
 | 
				
			||||||
@@ -408,9 +432,9 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    join: new Command({
 | 
					        command: 'join',
 | 
				
			||||||
        name: 'join',
 | 
					        aliases: ['j', 'goto'],
 | 
				
			||||||
        args: '<room-alias>',
 | 
					        args: '<room-alias>',
 | 
				
			||||||
        description: _td('Joins room with given alias'),
 | 
					        description: _td('Joins room with given alias'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -521,9 +545,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    part: new Command({
 | 
					        command: 'part',
 | 
				
			||||||
        name: 'part',
 | 
					 | 
				
			||||||
        args: '[<room-alias>]',
 | 
					        args: '[<room-alias>]',
 | 
				
			||||||
        description: _td('Leave room'),
 | 
					        description: _td('Leave room'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -569,9 +592,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    kick: new Command({
 | 
					        command: 'kick',
 | 
				
			||||||
        name: 'kick',
 | 
					 | 
				
			||||||
        args: '<user-id> [reason]',
 | 
					        args: '<user-id> [reason]',
 | 
				
			||||||
        description: _td('Kicks user with given id'),
 | 
					        description: _td('Kicks user with given id'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -585,10 +607,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Ban a user from the room with an optional reason
 | 
					        command: 'ban',
 | 
				
			||||||
    ban: new Command({
 | 
					 | 
				
			||||||
        name: 'ban',
 | 
					 | 
				
			||||||
        args: '<user-id> [reason]',
 | 
					        args: '<user-id> [reason]',
 | 
				
			||||||
        description: _td('Bans user with given id'),
 | 
					        description: _td('Bans user with given id'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -602,10 +622,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Unban a user from ythe room
 | 
					        command: 'unban',
 | 
				
			||||||
    unban: new Command({
 | 
					 | 
				
			||||||
        name: 'unban',
 | 
					 | 
				
			||||||
        args: '<user-id>',
 | 
					        args: '<user-id>',
 | 
				
			||||||
        description: _td('Unbans user with given ID'),
 | 
					        description: _td('Unbans user with given ID'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -620,9 +638,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    ignore: new Command({
 | 
					        command: 'ignore',
 | 
				
			||||||
        name: 'ignore',
 | 
					 | 
				
			||||||
        args: '<user-id>',
 | 
					        args: '<user-id>',
 | 
				
			||||||
        description: _td('Ignores a user, hiding their messages from you'),
 | 
					        description: _td('Ignores a user, hiding their messages from you'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -651,9 +668,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    unignore: new Command({
 | 
					        command: 'unignore',
 | 
				
			||||||
        name: 'unignore',
 | 
					 | 
				
			||||||
        args: '<user-id>',
 | 
					        args: '<user-id>',
 | 
				
			||||||
        description: _td('Stops ignoring a user, showing their messages going forward'),
 | 
					        description: _td('Stops ignoring a user, showing their messages going forward'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -683,10 +699,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.actions,
 | 
					        category: CommandCategories.actions,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Define the power level of a user
 | 
					        command: 'op',
 | 
				
			||||||
    op: new Command({
 | 
					 | 
				
			||||||
        name: 'op',
 | 
					 | 
				
			||||||
        args: '<user-id> [<power-level>]',
 | 
					        args: '<user-id> [<power-level>]',
 | 
				
			||||||
        description: _td('Define the power level of a user'),
 | 
					        description: _td('Define the power level of a user'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -712,10 +726,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Reset the power level of a user
 | 
					        command: 'deop',
 | 
				
			||||||
    deop: new Command({
 | 
					 | 
				
			||||||
        name: 'deop',
 | 
					 | 
				
			||||||
        args: '<user-id>',
 | 
					        args: '<user-id>',
 | 
				
			||||||
        description: _td('Deops user with given id'),
 | 
					        description: _td('Deops user with given id'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -734,9 +746,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    devtools: new Command({
 | 
					        command: 'devtools',
 | 
				
			||||||
        name: 'devtools',
 | 
					 | 
				
			||||||
        description: _td('Opens the Developer Tools dialog'),
 | 
					        description: _td('Opens the Developer Tools dialog'),
 | 
				
			||||||
        runFn: function(roomId) {
 | 
					        runFn: function(roomId) {
 | 
				
			||||||
            const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
 | 
					            const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
 | 
				
			||||||
@@ -745,9 +756,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.advanced,
 | 
					        category: CommandCategories.advanced,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    addwidget: new Command({
 | 
					        command: 'addwidget',
 | 
				
			||||||
        name: 'addwidget',
 | 
					 | 
				
			||||||
        args: '<url>',
 | 
					        args: '<url>',
 | 
				
			||||||
        description: _td('Adds a custom widget by URL to the room'),
 | 
					        description: _td('Adds a custom widget by URL to the room'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -766,10 +776,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.admin,
 | 
					        category: CommandCategories.admin,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Verify a user, device, and pubkey tuple
 | 
					        command: 'verify',
 | 
				
			||||||
    verify: new Command({
 | 
					 | 
				
			||||||
        name: 'verify',
 | 
					 | 
				
			||||||
        args: '<user-id> <device-id> <device-signing-key>',
 | 
					        args: '<user-id> <device-id> <device-signing-key>',
 | 
				
			||||||
        description: _td('Verifies a user, session, and pubkey tuple'),
 | 
					        description: _td('Verifies a user, session, and pubkey tuple'),
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -834,20 +842,9 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.advanced,
 | 
					        category: CommandCategories.advanced,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    // Command definitions for autocompletion ONLY:
 | 
					        command: 'discardsession',
 | 
				
			||||||
 | 
					        aliases: ['newballsplease'],
 | 
				
			||||||
    // /me is special because its not handled by SlashCommands.js and is instead done inside the Composer classes
 | 
					 | 
				
			||||||
    me: new Command({
 | 
					 | 
				
			||||||
        name: 'me',
 | 
					 | 
				
			||||||
        args: '<message>',
 | 
					 | 
				
			||||||
        description: _td('Displays action'),
 | 
					 | 
				
			||||||
        category: CommandCategories.messages,
 | 
					 | 
				
			||||||
        hideCompletionAfterSpace: true,
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    discardsession: new Command({
 | 
					 | 
				
			||||||
        name: 'discardsession',
 | 
					 | 
				
			||||||
        description: _td('Forces the current outbound group session in an encrypted room to be discarded'),
 | 
					        description: _td('Forces the current outbound group session in an encrypted room to be discarded'),
 | 
				
			||||||
        runFn: function(roomId) {
 | 
					        runFn: function(roomId) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
@@ -859,9 +856,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.advanced,
 | 
					        category: CommandCategories.advanced,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    rainbow: new Command({
 | 
					        command: "rainbow",
 | 
				
			||||||
        name: "rainbow",
 | 
					 | 
				
			||||||
        description: _td("Sends the given message coloured as a rainbow"),
 | 
					        description: _td("Sends the given message coloured as a rainbow"),
 | 
				
			||||||
        args: '<message>',
 | 
					        args: '<message>',
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -870,9 +866,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.messages,
 | 
					        category: CommandCategories.messages,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    rainbowme: new Command({
 | 
					        command: "rainbowme",
 | 
				
			||||||
        name: "rainbowme",
 | 
					 | 
				
			||||||
        description: _td("Sends the given emote coloured as a rainbow"),
 | 
					        description: _td("Sends the given emote coloured as a rainbow"),
 | 
				
			||||||
        args: '<message>',
 | 
					        args: '<message>',
 | 
				
			||||||
        runFn: function(roomId, args) {
 | 
					        runFn: function(roomId, args) {
 | 
				
			||||||
@@ -881,9 +876,8 @@ export const CommandMap = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        category: CommandCategories.messages,
 | 
					        category: CommandCategories.messages,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					    new Command({
 | 
				
			||||||
    help: new Command({
 | 
					        command: "help",
 | 
				
			||||||
        name: "help",
 | 
					 | 
				
			||||||
        description: _td("Displays list of commands with usages and descriptions"),
 | 
					        description: _td("Displays list of commands with usages and descriptions"),
 | 
				
			||||||
        runFn: function() {
 | 
					        runFn: function() {
 | 
				
			||||||
            const SlashCommandHelpDialog = sdk.getComponent('dialogs.SlashCommandHelpDialog');
 | 
					            const SlashCommandHelpDialog = sdk.getComponent('dialogs.SlashCommandHelpDialog');
 | 
				
			||||||
@@ -894,36 +888,25 @@ export const CommandMap = {
 | 
				
			|||||||
        category: CommandCategories.advanced,
 | 
					        category: CommandCategories.advanced,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    whois: new Command({
 | 
					    // Command definitions for autocompletion ONLY:
 | 
				
			||||||
        name: "whois",
 | 
					    // /me is special because its not handled by SlashCommands.js and is instead done inside the Composer classes
 | 
				
			||||||
        description: _td("Displays information about a user"),
 | 
					    new Command({
 | 
				
			||||||
        args: '<user-id>',
 | 
					        command: 'me',
 | 
				
			||||||
        runFn: function(roomId, userId) {
 | 
					        args: '<message>',
 | 
				
			||||||
            if (!userId || !userId.startsWith("@") || !userId.includes(":")) {
 | 
					        description: _td('Displays action'),
 | 
				
			||||||
                return reject(this.getUsage());
 | 
					        category: CommandCategories.messages,
 | 
				
			||||||
            }
 | 
					        hideCompletionAfterSpace: true,
 | 
				
			||||||
 | 
					 | 
				
			||||||
            const member = MatrixClientPeg.get().getRoom(roomId).getMember(userId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            dis.dispatch({
 | 
					 | 
				
			||||||
                action: 'view_user',
 | 
					 | 
				
			||||||
                member: member || {userId},
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            return success();
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        category: CommandCategories.advanced,
 | 
					 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
};
 | 
					];
 | 
				
			||||||
/* eslint-enable babel/no-invalid-this */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// build a map from names and aliases to the Command objects.
 | 
				
			||||||
// helpful aliases
 | 
					export const CommandMap = new Map();
 | 
				
			||||||
const aliases = {
 | 
					Commands.forEach(cmd => {
 | 
				
			||||||
    j: "join",
 | 
					    CommandMap.set(cmd.command, cmd);
 | 
				
			||||||
    newballsplease: "discardsession",
 | 
					    cmd.aliases.forEach(alias => {
 | 
				
			||||||
    goto: "join", // because it handles event permalinks magically
 | 
					        CommandMap.set(alias, cmd);
 | 
				
			||||||
    roomnick: "myroomnick",
 | 
					    });
 | 
				
			||||||
};
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -950,10 +933,7 @@ export function getCommand(roomId, input) {
 | 
				
			|||||||
        cmd = input;
 | 
					        cmd = input;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (aliases[cmd]) {
 | 
					    if (CommandMap.has(cmd)) {
 | 
				
			||||||
        cmd = aliases[cmd];
 | 
					        return () => CommandMap.get(cmd).run(roomId, args, cmd);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (CommandMap[cmd]) {
 | 
					 | 
				
			||||||
        return () => CommandMap[cmd].run(roomId, args);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -23,17 +23,16 @@ import AutocompleteProvider from './AutocompleteProvider';
 | 
				
			|||||||
import QueryMatcher from './QueryMatcher';
 | 
					import QueryMatcher from './QueryMatcher';
 | 
				
			||||||
import {TextualCompletion} from './Components';
 | 
					import {TextualCompletion} from './Components';
 | 
				
			||||||
import type {Completion, SelectionRange} from "./Autocompleter";
 | 
					import type {Completion, SelectionRange} from "./Autocompleter";
 | 
				
			||||||
import {CommandMap} from '../SlashCommands';
 | 
					import {Commands, CommandMap} from '../SlashCommands';
 | 
				
			||||||
 | 
					 | 
				
			||||||
const COMMANDS = Object.values(CommandMap);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
 | 
					const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class CommandProvider extends AutocompleteProvider {
 | 
					export default class CommandProvider extends AutocompleteProvider {
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super(COMMAND_RE);
 | 
					        super(COMMAND_RE);
 | 
				
			||||||
        this.matcher = new QueryMatcher(COMMANDS, {
 | 
					        this.matcher = new QueryMatcher(Commands, {
 | 
				
			||||||
           keys: ['command', 'args', 'description'],
 | 
					            keys: ['command', 'args', 'description'],
 | 
				
			||||||
 | 
					            funcs: [({aliases}) => aliases.join(" ")], // aliases
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,31 +45,40 @@ export default class CommandProvider extends AutocompleteProvider {
 | 
				
			|||||||
        if (command[0] !== command[1]) {
 | 
					        if (command[0] !== command[1]) {
 | 
				
			||||||
            // The input looks like a command with arguments, perform exact match
 | 
					            // The input looks like a command with arguments, perform exact match
 | 
				
			||||||
            const name = command[1].substr(1); // strip leading `/`
 | 
					            const name = command[1].substr(1); // strip leading `/`
 | 
				
			||||||
            if (CommandMap[name]) {
 | 
					            if (CommandMap.has(name)) {
 | 
				
			||||||
                // some commands, namely `me` and `ddg` don't suit having the usage shown whilst typing their arguments
 | 
					                // some commands, namely `me` and `ddg` don't suit having the usage shown whilst typing their arguments
 | 
				
			||||||
                if (CommandMap[name].hideCompletionAfterSpace) return [];
 | 
					                if (CommandMap.get(name).hideCompletionAfterSpace) return [];
 | 
				
			||||||
                matches = [CommandMap[name]];
 | 
					                matches = [CommandMap.get(name)];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (query === '/') {
 | 
					            if (query === '/') {
 | 
				
			||||||
                // If they have just entered `/` show everything
 | 
					                // If they have just entered `/` show everything
 | 
				
			||||||
                matches = COMMANDS;
 | 
					                matches = Commands;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // otherwise fuzzy match against all of the fields
 | 
					                // otherwise fuzzy match against all of the fields
 | 
				
			||||||
                matches = this.matcher.match(command[1]);
 | 
					                matches = this.matcher.match(command[1]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return matches.map((result) => ({
 | 
					
 | 
				
			||||||
            // If the command is the same as the one they entered, we don't want to discard their arguments
 | 
					        return matches.map((result) => {
 | 
				
			||||||
            completion: result.command === command[1] ? command[0] : (result.command + ' '),
 | 
					            let completion = result.getCommand() + ' ';
 | 
				
			||||||
            type: "command",
 | 
					            const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);
 | 
				
			||||||
            component: <TextualCompletion
 | 
					            // If the command (or an alias) is the same as the one they entered, we don't want to discard their arguments
 | 
				
			||||||
                title={result.command}
 | 
					            if (usedAlias || result.getCommand() === command[1]) {
 | 
				
			||||||
                subtitle={result.args}
 | 
					                completion = command[0];
 | 
				
			||||||
                description={_t(result.description)} />,
 | 
					            }
 | 
				
			||||||
            range,
 | 
					
 | 
				
			||||||
        }));
 | 
					            return {
 | 
				
			||||||
 | 
					                completion,
 | 
				
			||||||
 | 
					                type: "command",
 | 
				
			||||||
 | 
					                component: <TextualCompletion
 | 
				
			||||||
 | 
					                    title={`/${usedAlias || result.command}`}
 | 
				
			||||||
 | 
					                    subtitle={result.args}
 | 
				
			||||||
 | 
					                    description={_t(result.description)} />,
 | 
				
			||||||
 | 
					                range,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getName() {
 | 
					    getName() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,14 +16,14 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import {_t} from "../../../languageHandler";
 | 
					import {_t} from "../../../languageHandler";
 | 
				
			||||||
import {CommandCategories, CommandMap} from "../../../SlashCommands";
 | 
					import {CommandCategories, Commands} from "../../../SlashCommands";
 | 
				
			||||||
import * as sdk from "../../../index";
 | 
					import * as sdk from "../../../index";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ({onFinished}) => {
 | 
					export default ({onFinished}) => {
 | 
				
			||||||
    const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
 | 
					    const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const categories = {};
 | 
					    const categories = {};
 | 
				
			||||||
    Object.values(CommandMap).forEach(cmd => {
 | 
					    Commands.forEach(cmd => {
 | 
				
			||||||
        if (!categories[cmd.category]) {
 | 
					        if (!categories[cmd.category]) {
 | 
				
			||||||
            categories[cmd.category] = [];
 | 
					            categories[cmd.category] = [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -41,7 +41,7 @@ export default ({onFinished}) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        categories[category].forEach(cmd => {
 | 
					        categories[category].forEach(cmd => {
 | 
				
			||||||
            rows.push(<tr key={cmd.command}>
 | 
					            rows.push(<tr key={cmd.command}>
 | 
				
			||||||
                <td><strong>{cmd.command}</strong></td>
 | 
					                <td><strong>{cmd.getCommand()}</strong></td>
 | 
				
			||||||
                <td>{cmd.args}</td>
 | 
					                <td>{cmd.args}</td>
 | 
				
			||||||
                <td>{cmd.description}</td>
 | 
					                <td>{cmd.description}</td>
 | 
				
			||||||
            </tr>);
 | 
					            </tr>);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user