The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Rocket.Chat/apps/meteor/app/utils/lib/slashCommand.ts

135 lines
3.4 KiB

import { Meteor } from 'meteor/meteor';
import type {
IMessage,
SlashCommand,
SlashCommandOptions,
RequiredField,
SlashCommandPreviewItem,
SlashCommandPreviews,
} from '@rocket.chat/core-typings';
interface ISlashCommandAddParams<T extends string> {
command: string;
callback?: SlashCommand<T>['callback'];
options?: SlashCommandOptions;
result?: SlashCommand['result'];
providesPreview?: boolean;
previewer?: SlashCommand['previewer'];
previewCallback?: SlashCommand['previewCallback'];
appId?: string;
description?: string;
}
export const slashCommands = {
commands: {} as Record<string, SlashCommand>,
add<T extends string>({
command,
callback,
options = {},
result,
providesPreview = false,
previewer,
previewCallback,
appId,
description = '',
}: ISlashCommandAddParams<T>): void {
if (this.commands[command]) {
return;
}
this.commands[command] = {
command,
callback,
params: options.params,
description: options.description || description,
permission: options.permission,
clientOnly: options.clientOnly || false,
result,
Chore: RestApiClient as Package (#25469) <!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. --> <!-- Your Pull Request name should start with one of the following tags [NEW] For new features [IMPROVE] For an improvement (performance or little improvements) in existing features [FIX] For bug fixes that affect the end-user [BREAK] For pull requests including breaking changes Chore: For small tasks Doc: For documentation --> <!-- Checklist!!! If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code. - I have read the Contributing Guide - https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat doc - I have signed the CLA - https://cla-assistant.io/RocketChat/Rocket.Chat - Lint and unit tests pass locally with my changes - I have added tests that prove my fix is effective or that my feature works (if applicable) - I have added necessary documentation (if applicable) - Any dependent changes have been merged and published in downstream modules --> ## Proposed changes (including videos or screenshots) <!-- CHANGELOG --> <!-- Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue below. This description will appear in the release notes if we accept the contribution. --> <!-- END CHANGELOG --> ## Issue(s) <!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 --> ## Steps to test or reproduce <!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable --> ## Further comments <!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... --> Co-authored-by: Tasso Evangelista <2263066+tassoevan@users.noreply.github.com>
4 years ago
providesPreview: Boolean(providesPreview),
previewer,
previewCallback,
appId,
} as SlashCommand;
},
async run({
command,
message,
params,
triggerId,
userId,
}: {
command: string;
params: string;
message: RequiredField<Partial<IMessage>, 'rid' | '_id'>;
userId: string;
triggerId?: string | undefined;
}): Promise<unknown> {
const cmd = this.commands[command];
if (typeof cmd?.callback !== 'function') {
return;
}
if (!message?.rid) {
throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
}
return cmd.callback({ command, params, message, triggerId, userId });
},
async getPreviews(
command: string,
params: string,
message: RequiredField<Partial<IMessage>, 'rid'>,
): Promise<SlashCommandPreviews | undefined> {
const cmd = this.commands[command];
if (typeof cmd?.previewer !== 'function') {
return;
}
if (!message?.rid) {
throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
}
const previewInfo = await cmd.previewer(command, params, message);
if (!previewInfo?.items?.length) {
return;
}
// A limit of ten results, to save time and bandwidth
if (previewInfo.items.length >= 10) {
previewInfo.items = previewInfo.items.slice(0, 10);
}
return previewInfo;
},
async executePreview(
command: string,
params: string,
message: Pick<IMessage, 'rid'> & Partial<Omit<IMessage, 'rid'>>,
preview: SlashCommandPreviewItem,
triggerId?: string,
) {
const cmd = this.commands[command];
if (typeof cmd?.previewCallback !== 'function') {
return;
}
if (!message?.rid) {
throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
}
// { id, type, value }
if (!preview.id || !preview.type || !preview.value) {
throw new Meteor.Error('error-invalid-preview', 'Preview Item must have an id, type, and value.');
}
return cmd.previewCallback(command, params, message, preview, triggerId);
},
};
declare module '@rocket.chat/ui-contexts' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
slashCommand(params: { cmd: string; params: string; msg: IMessage; triggerId: string }): unknown;
}
}