---
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
---

> ## 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<RocketChatAssociationRecord> = [   // 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<any> {   // 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<void> {

        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<string> {

    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<void> {
    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<void> {
        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.
