In this section, we'll look at two slash command examples:
Update user status value and text.
Extend messages to include an image attachment and a custom field.
Example 1: Update user status
To update the user status, we will create a new slash command that takes two parameters:
The first parameter is the status value - online, away, busy, etc.
The second contains the status text.
We will refer to the status slash command as st to execute code such as:
/st busy doing code :)Step 1: Create the slash command
To implement this, follow these steps:
Create a new class named
StatusUpdateCmd.tsand place it in the same subdirectorycommandsthat we created in the previous section.Now, add the following code for the status update:
import {
IHttp,
IModify,
IPersistence,
IRead,
} from '@rocket.chat/apps-engine/definition/accessors';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms';
import {
ISlashCommand,
SlashCommandContext,
} from '@rocket.chat/apps-engine/definition/slashcommands';
import { IUser } from '@rocket.chat/apps-engine/definition/users';
export class StatusUpdateCmd implements ISlashCommand {
public command = 'st';
public i18nParamsExample: string = 'status_update_command_params_example';
public i18nDescription: string = 'status_update_command_description';
public providesPreview: boolean = false;
public async executor(context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<void> {
const user = context.getSender();
const params = context.getArguments();
const room: IRoom = context.getRoom();
if (!params || params.length == 0) {
return this.notifyMessage(room, read, user, "At least one status argument is mandatory. A second argument can be passed as status text.");
}
let status = params[0];
let statusText = params.length > 1 ? params.slice(1).join(' ') : '';
await modify.getUpdater().getUserUpdater().updateStatus(user, statusText, status);
await this.notifyMessage(room, read, user, "Status updated to " + status + " (" + statusText + ").");
}
private async notifyMessage(room: IRoom, read: IRead, sender: IUser, message: string): Promise<void> {
const notifier = read.getNotifier();
const messageBuilder = notifier.getMessageBuilder();
messageBuilder.setText(message);
messageBuilder.setRoom(room);
return notifier.notifyUser(sender, messageBuilder.getMessage());
}
}Here, we are implementing the following:
Fetch the status value from the first argument. This argument is mandatory otherwise, the
notifyMessagemethod informs the user that the argument is missing.Fetch the status message from the second argument, joining the terms with a white space. If the second argument is not passed, the status message remains an empty string.
Update the status according to the value passed using
modify.Notify the user about the status update.
Step 2: Register the slash command
In the app's main class, register the new slash command as follows:
public async extendConfiguration(configuration: IConfigurationExtend) {
configuration.slashCommands.provideSlashCommand(new StatusUpdateCmd());
}You can only have one
extendConfigurationmethod in your app's main class. Therefore, make sure to add all your slash commands to this method.
Make sure to import the slash command class in the main class:
import { StatusUpdateCmd } from './commands/StatusUpdateCmd';All that remains is deployment and testing!
Step 3: Deploy the app
In the command line, go to the app folder and run:
rc-apps deploy --url <server_url> -u <user> -p <pwd>The
<server_url>parameter is the URL of your Rocket.Chat server.Replace the placeholders with the URL, username, and password for your server, respectively.
After executing this command, your application will be deployed to the server.
Packaging your app
Alternatively, you can execute the
rc-apps packagecommand. This gives you a compressed zip file of your app that you can upload as a private app to your Rocket.Chat server.
Step 4: Test the app
Send /st <status> <message> to any channel. You can see the change in the user status accordingly. The following screenshot shows the result when you enter /st busy doing code :).
.png?sv=2022-11-02&spr=https&st=2026-02-22T06%3A20%3A14Z&se=2026-02-22T06%3A37%3A14Z&sr=c&sp=r&sig=q18gqv8%2F4W6BqcjMTWfhm67a%2B%2FCRoQbTbdvp2VoK%2BEw%3D)
If we execute /st with no input, we receive the notification:
.png?sv=2022-11-02&spr=https&st=2026-02-22T06%3A20%3A14Z&se=2026-02-22T06%3A37%3A14Z&sr=c&sp=r&sig=q18gqv8%2F4W6BqcjMTWfhm67a%2B%2FCRoQbTbdvp2VoK%2BEw%3D)
Example 2: Extend messages
This example explains how to construct an app that is invoked via a slash command, sends a message, and is extended to include an image and a custom field. Rocket.Chat supports numerous attachments (with applicable customizations). For instance, you can attach images, documents, videos, and audio files to messages.
Step 1: Create the slash command
To implement this, follow these steps:
Create a new class named
ExtendMessageCommand.tsand place it in the same subdirectorycommandsthat we created in the previous section.Now, add the following code:
import { IHttp, IModify, IPersistence, IRead, IMessageExtender } from '@rocket.chat/apps-engine/definition/accessors';
import { ISlashCommand, SlashCommandContext } from '@rocket.chat/apps-engine/definition/slashcommands';
import { IMessageAttachment } from '@rocket.chat/apps-engine/definition/messages';
class ImageAttachment implements IMessageAttachment {
imageUrl?: string;
constructor(imgUrl: string) {
this.imageUrl = imgUrl;
}
}
export class ExtendMessageCommand implements ISlashCommand {
public command = 'extend-message';
public i18nParamsExample = '';
public i18nDescription = '';
public providesPreview = false;
public async executor(context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<void> {
try {
// Send message [1]
const messageId = await this.sendMessage(context, modify, 'Sending a message!');
// Get message extender [2]
const messageExtender = await this.getMessageExtender(context, modify, messageId);
// Create and add image attachment [3]
const img = new ImageAttachment('https://test.rocket.chat/images/logo/logo.svg');
messageExtender.addAttachment(img); // [4]
// Finish extending [5]
await modify.getExtender().finish(messageExtender);
await this.notifyUser(context, read, 'Message extended successfully with image!');
} catch (error) {
await this.notifyUser(context, read, `ERROR: ${error.message || error}`);
}
}
private async sendMessage(context: SlashCommandContext, modify: IModify, message: string): Promise<string> {
const messageStructure = modify.getCreator().startMessage();
const sender = context.getSender();
const room = context.getRoom();
messageStructure
.setSender(sender)
.setRoom(room)
.setText(message);
return modify.getCreator().finish(messageStructure);
}
private async getMessageExtender(context: SlashCommandContext, modify: IModify, messageId: string): Promise<IMessageExtender> {
const sender = context.getSender();
return modify.getExtender().extendMessage(messageId, sender);
}
private async notifyUser(context: SlashCommandContext, read: IRead, message: string): Promise<void> {
const notifier = read.getNotifier();
const messageBuilder = notifier.getMessageBuilder();
messageBuilder.setText(message);
messageBuilder.setRoom(context.getRoom());
await notifier.notifyUser(context.getSender(), messageBuilder.getMessage());
}
}The main actions performed by the code above are:
[1] Sends a message and stores the sent message's ID in the
messageIdvariable.[2] Uses the sent message's ID. The
messageExtenderobject is returned by thegetMessageExtendermethod and stored in themessageExtendervariable.[3] Creates the attachment object as an instance of the
ImageAttachmentclass. Here, the attachment is an image.[4] Adds the image attachment to the message using the
addAttachmentmethod from themessageExtenderobject. Many attachments can be added all at once using theaddAttachmentsmethod.[5] Finishes the
modifyExtenderobject, which is crucial to apply the extensions made to the message and make them visible to the user.
Method: sendMessage
The sendMessage method needs to return the message's ID after it has been sent. The method must return a Promise<string>.
Method: getMessageExtender
After obtaining the message's ID, we can get the messageExtender object, which enables the addition of custom fields and attachments.
Step 2: Add image attachment class
We will implement the ImageAttachment class in the same class:
import { IMessageAttachment } from '@rocket.chat/apps-engine/definition/messages';
export class ImageAttachment implements IMessageAttachment{
imageUrl?: string;
constructor(imgUrl: string){
this.imageUrl = imgUrl;
}
}Here, we use a class attribute with the same identifier and type as in the IMessageAttachment interface, which is required for your linked media to be visible to the user. This is because only the variables in your attachment class defined in the IMessageAttachment interface will be used to retrieve the attachment's media.
You can also construct your own classes for video or audio attachments, or you can group them all into a single class that can accommodate all of these possibilities. Make sure to use the same attributes described in the IMessageAttachment.d.ts file.
The audio and video formats that are supported in the Rocket.Chat message attachments are identical to HTML audio and video elements.
Step 3: Register the slash command
We must register the slash command in the app's main class, the project's root.
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { ExtendMessageCommand } from './slashcommands/ExtendSlashcommand'; // [1]
export class RocketChatTester extends App {
constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
super(info, logger, accessors);
}
public async extendConfiguration(configuration: IConfigurationExtend) {
configuration.slashCommands.provideSlashCommand(new ExtendMessageCommand()); // [2]
}
}Here, we import our new slash command class and register it in the app's configuration.
Step 5: Deploy the app
To deploy the app, follow the deployment steps highlighted in the previous example.
Step 6: Test the slash command
After the app has been deployed, execute the slash command /extend-message in any channel.
When you execute the registered slash command, a message is sent to the current channel and altered to include the image attachment. The attached image is visible in the message after editing.
The following screenshot shows an example:
.png?sv=2022-11-02&spr=https&st=2026-02-22T06%3A20%3A14Z&se=2026-02-22T06%3A37%3A14Z&sr=c&sp=r&sig=q18gqv8%2F4W6BqcjMTWfhm67a%2B%2FCRoQbTbdvp2VoK%2BEw%3D)