--- title: "Rocket Chat App Increment Number" slug: "increment-number-example" description: "Learn how to implement an increment number in Rocket Chat Apps-Engine. Build secure app features and enhance collaboration." updated: 2024-12-26T12:52:24Z published: 2024-12-26T12:52:24Z canonical: "developer.rocket.chat/increment-number-example" --- > ## Documentation Index > Fetch the complete documentation index at: https://developer.rocket.chat/llms.txt > Use this file to discover all available pages before exploring further. # Increment Number Example In this example, we will create an app that increments the value of a number. Users will send a slash command with a number as an argument. Initially, the number’s value is incremented from 0 and stored. After that, each time the slash command is used, the new stored value is incremented with the specified number. ## Create the slash command class 1. Create a TypeScript slash command file in your app folder. You can use the following command to generate a template file: ```bash rc-apps generate ``` Select the **Slash command extension** option and provide a name for the file, for example `numberPersis`. The file is automatically created in a `slashCommands` folder located at the root of your app folder. 1. First, we will give a name to the slash command and create an association using the `MISC` [enumeration model](https://rocketchat.github.io/Rocket.Chat.Apps-engine/enums/metadata_RocketChatAssociations.RocketChatAssociationModel.html). The class looks like this initially: ```typescript import { IHttp, IModify, IPersistence, IPersistenceRead, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { RocketChatAssociationModel, RocketChatAssociationRecord } from '@rocket.chat/apps-engine/definition/metadata'; import { ISlashCommand, SlashCommandContext } from '@rocket.chat/apps-engine/definition/slashcommands/index'; import { IUser } from '@rocket.chat/apps-engine/definition/users'; import { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; export class numberPersis implements ISlashCommand {    app: IApp;    constructor(app) {        this.app = app;    }    public command = 'numberpersis';    public i18nDescription = 'Increment a number';    public providesPreview = false;    public i18nParamsExample = '';    public associations: Array = [   // this is the association that will be used to store the value        new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'increment_command'),    ]; } ``` 1. In this class, we will add a function called `getValue` to read the value of the number: ```typescript public async getValue(read: IRead): Promise {   // this function will read the value from the database        let result: number;        const persistenceRead = read.getPersistenceReader();        try {            const records: any = (await persistenceRead.readByAssociations(this.associations));            if (records.length) {                result = records[0].value;            } else {                result = 0;            }        } catch (err) {            console.error(err);            return ({                success: false,                error: err,            });        }        return ({            success: true,            result,        });    } ``` From the [**IRead**](https://rocketchat.github.io/Rocket.Chat.Apps-engine/interfaces/accessors_IRead.IRead.html#getPersistenceReader) interface, the `getPersistenceReader` method is used to read the number. If a valid number exists in the record, it is stored in the variable `result`. Otherwise, the `result` is zero. 1. Now we will add an executor function. In this, we will add subcommands to the slash command so that we can get the number from the user or reset its value to zero. We will also add a help subcommand to display the slash command options. The number calculation will be carried out within this function. ```typescript public async executor(        context: SlashCommandContext,        read: IRead,        modify: IModify,        http: IHttp,        persistence: IPersistence,    ): Promise {        const sender = context.getSender();   // the user who sent the command        const room = context.getRoom();      // the room where the command was sent        const [subcommand] = context.getArguments();    // the subcommand        const appBot = await read.getUserReader().getAppUser() as IUser; // the user(bot) who sends relevant message        const helpText = `use \`/numberpersis [number]\` to increment the value by a given integer. \n` +            `use \`/numberpersis [reset|r]\` to reset the value to 0\n` +            `use \`/numberpersis [help|h]\` to display this message`;        if (!subcommand) {  // if no argument is provided            var message = `No Subcommand :thinking: \n ${helpText}`;            await sendNotification(modify, room, sender, message);        } else {            switch (subcommand) {                case 'reset':  // if the user enters the reset argument                case 'r':                    await persistence.updateByAssociations(this.associations, { value: 0 }, true); // update the value to 0                    message = `@${sender.username} reset the value to 0.`;                    await sendMessage(modify, room, appBot, message); // calling the sendMessage function                    return;                case 'help':  // if the user enters the help argument                case 'h':                    await sendNotification(modify, room, sender, helpText); // calling the sendNotification function to display the helptext                    return;                default:                    if (isNaN(parseInt(subcommand, 10))) {  // if the subcommand is not a number                        message = `@${sender.username} you need to provide a number to increment the value by.`;                        await sendNotification(modify, room, sender, message); // calling the sendNotification function to display the helptext                        return;                    } else {                        const initialValue = parseInt(await this.getValue(read).then((value) => value.result), 10);     // get the current value                        const finalValue = await initialValue + parseInt(subcommand, 10);                               // calculate the new value                        await persistence.updateByAssociations(this.associations, { value: finalValue }, true);         // update the value                        message = `@${sender.username} incremented the value of ${initialValue} by ${subcommand}.\n` +                            `The new value is ${finalValue} `;                        await sendMessage(modify, room, appBot, message);                    }            }        }    } } ``` The `updateByAssociations` method is used to update the record. For details, see the [IPersistence interface](https://rocketchat.github.io/Rocket.Chat.Apps-engine/interfaces/accessors_IPersistence.IPersistence.html#updateByAssociations). 1. Finally, we will define the `sendMessage` and `sendNotification` functions to send messages to the channel. These functions are added after the `numberPersis` class. ```typescript export async function sendMessage(    modify: IModify,    room: IRoom,    sender: IUser,    message: string, ): Promise {    const msg = modify.getCreator().startMessage()        .setSender(sender)        .setRoom(room)        .setText(message);    return await modify.getCreator().finish(msg); } export async function sendNotification(    modify: IModify,    room: IRoom,    sender: IUser,    message: string ): Promise {    let msg = modify.getCreator().startMessage().setRoom(room).setText(message);    // uncomment below if you want the notification to be sent by the sender instead of the app bot user    // msg = msg.setSender(sender);    // lets build a really simple block    const block = modify.getCreator().startMessage();    // we want this block to have a Text supporting MarkDown    block.setBlocks([        {            type: 'section',            text: {                type: 'mrkdwn',                text: message            }        }    ])    // now let's set the blocks in our message    block.setRoom(room).setText(message);    // and finally, notify the user with the IMessage    return await modify.getNotifier().notifyUser(sender, msg.getMessage()); } ``` ## Update the main app class Next, we will update the app’s main class to call the slash command class. ```typescript // ...import commands... import { numberPersis } from './numberPersis'; // remember to import the class here export class PersistenceSampleApp extends App {    constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {        super(info, logger, accessors);    }    public async extendConfiguration(configuration: IConfigurationExtend, environmentRead: IEnvironmentRead): Promise {        await configuration.slashCommands.provideSlashCommand(            new numberPersis(this)        )    } } ``` ## Test the app Deploy the app to your workspace or package the app and upload it to the workspace. - In any channel, send the slash command `/numberPersis`. Try sending it without arguments. The app bot should send a message like this: ![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(131).png) - Now send the slash command with numbers. For example, `/numberPersis 5`, and then again with `/numberPersis 6`. The app bot will return the updated values: ![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(132).png) - If you send `/numberPersis r` or `/numberPersis reset`, the value will be reset to 0: ![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(133).png) - If you send `/numberPersis h` or `/numberPersis help`, the help menu will be displayed: ![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(134).png) With this example, we can see how the value is stored and updated using associations.