---
title: "Rocket Chat Event Interface Examples"
slug: "event-interface-examples"
description: "Explore examples of Rocket Chat event interfaces. Build secure apps that respond to collaboration events effectively."
updated: 2026-02-23T04:33:34Z
published: 2026-02-23T04:33:34Z
---

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

# Event Interface Examples

Now that we have learned about the event interfaces, let's go through some examples to implement them. On this page, we will follow three examples:

1. Messaging governance
2. Notify messages
3. Content inspection

## Example 1: Messaging governance

In this example, we will use the `IPreMessageSentPrevent` interface to control whether a particular message should be sent to a channel. We are using our [Hello World app](/v1/docs/create-an-app) to test this.

1. Open your app folder in Visual Studio and select the main app file, in this case, `HelloWorldApp.ts`.
2. To the `HelloWorldApp` class, add the `IPreMessageSentPrevent` interface as follows:

```typescript
export class HelloWorldApp extends App implements IPreMessageSentPrevent {
```
3. Import the following interface in the main app file:

```typescript
import { IPreMessageSentPrevent } from '@rocket.chat/apps-engine/definition/messages/IPreMessageSentPrevent';
```
4. Now Visual Studio will display an error that a part of the interface is missing its implementation, with the option to fix it quickly. Accept the suggested fix. Visual Studio adds two methods to the interface that are not implemented. The methods will throw an error when executed. But now, we have a skeleton code to work with:

```typescript
checkPreMessageSentPrevent?(message: IMessage, read: IRead, http: IHttp): Promise<boolean> {
        throw new Error('Method not implemented.');
}

executePreMessageSentPrevent(message: IMessage, read: IRead, http: IHttp, persistence: IPersistence): Promise<boolean> {
    throw new Error('Method not implemented.');
}
```
5. With the `checkPreMessageSentPrevent` method, we will only check the messages from channels other than **general**. Visual Studio helps you navigate the APIs of object classes by suggesting available methods. For this example, you can see that the method variable `message` has a room attribute, which has a `slugifiedName` string attribute. Update the method as follows:

```typescript
checkPreMessageSentPrevent?(message: IMessage, read: IRead, http: IHttp): Promise<boolean> {
        return message.room.slugifiedName != 'general';
}
```
6. Now Visual Studio displays an error that the method signature is not compatible with returning a `Promise&lt;boolean&gt;`. To fix this issue, add `async` to the method signature.
7. Next, implement the `executePreMessageSentPrevent` method. If the message equals "test", we prevent it from being published. Update the method as follows:

```typescript
async executePreMessageSentPrevent(message: IMessage, read: IRead, http: IHttp, persistence: IPersistence): Promise<boolean> {
        return message.text == 'test';
}
```
8. Your main app file should look something like this:

```typescript
import {
    IAppAccessors,
    IHttp,
    ILogger,
    IPersistence,
    IRead,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IMessage } from '@rocket.chat/apps-engine/definition/messages';
import { IPreMessageSentPrevent } from '@rocket.chat/apps-engine/definition/messages/IPreMessageSentPrevent';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';

export class HelloWorldApp extends App implements IPreMessageSentPrevent {
    constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
        super(info, logger, accessors);
    }
    
    async checkPreMessageSentPrevent?(message: IMessage, read: IRead, http: IHttp): Promise<boolean> {
        return message.room.slugifiedName != 'general';
    }
    
    async executePreMessageSentPrevent(message: IMessage, read: IRead, http: IHttp, persistence: IPersistence): Promise<boolean> {
        return message.text == 'test';
    }
}
```
9. Save the file and deploy your app.
10. If we send the `test` message in a channel other than **general**, it is not published (it will appear grayed out). If the message is something different, it will get sent as shown in the following screenshot:

![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(55).png)
11. As for the room **general**, all messages will be sent, including `test` as shown in the following screenshot:

![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(56).png)

## Example 2: Notify messages

In this example, we will notify the **general** channel whenever a message is sent anywhere else. Here we will implement the `IPostMessageSent` interface.

1. Like the previous example, in the main app file (in this case, `HelloWorldApp.ts`), we will add the `check` and `execute` methods from the `IPostMessageSent` interface as shown in the code below.
2. The `checkPostMessageSent` method ensures that the handler only runs for messages outside of the `#general` channel.
3. In the `executePostMessageSent` method, we fetch the `#general` channel and create a new message there. This message includes information about the original message, the room where it was published, and the sender. We use `sendMessage` together with the `messageBuilder` to construct and post a richly formatted message in `#general`.

```typescript
import {
   IAppAccessors,
   IHttp,
   ILogger,
   IModify,
   IPersistence,
   IRead,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IMessage, IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms/IRoom';
import { IUser } from '@rocket.chat/apps-engine/definition/users/IUser';

export class HelloWorldApp extends App implements IPostMessageSent {
   constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
       super(info, logger, accessors);
   }
   
   async checkPostMessageSent?(message: IMessage, read: IRead, http: IHttp): Promise<boolean> {
       return message.room.slugifiedName != 'general';
   }
   
   async executePostMessageSent(message: IMessage, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {
       const general = await read.getRoomReader().getByName('general');
       if (!general) {
           return;
       }
       const msg = `@${message.sender.username} said "${message.text}" in #${message.room.displayName}`;
       const author = await read.getUserReader().getAppUser();
       if (general.id != message.room.id) { // prevent this for running on #general channel
           await this.sendMessage(general, msg, author?author:message.sender, modify);
       }
   }
   
   private async sendMessage(room: IRoom, textMessage: string, author: IUser, modify: IModify) {
       const messageBuilder = modify.getCreator().startMessage({
           text: textMessage,
       } as IMessage);
       messageBuilder.setRoom(room);
       messageBuilder.setSender(author);
       return modify.getCreator().finish(messageBuilder);
   }
}
```
4. Now save, deploy, and test the app. You should be able to see the messages posted to the **general** channel when writing to any other channel.

![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(57).png)

## Example 3: Content inspection

A typical use case of the previous two examples is to control the content of the information being exchanged. For instance, we could use regular expressions matching inappropriate words to flag them.

Some apps that implement content inspection are:

- [Data Loss Prevention (DLP)](https://docs.rocket.chat/extend-rocket.chat-capabilities/rocket.chat-marketplace/rocket.chat-public-apps-guides/data-loss-prevention-dlp-app)
- [Antivirus (ClamAV)](https://docs.rocket.chat/extend-rocket.chat-capabilities/rocket.chat-marketplace/rocket.chat-public-apps-guides/clamav-app)
- [Word Replacer](https://www.rocket.chat/apps/word-replacer)

For our Hello World app, let's look into inspecting file attachments.

1. In our main app file, we will implement `IPreFileUpload` and print a message notifying the user that the attached file has been inspected.
2. If the file type is `text/plain`, we will also display the file's content. The main app file looks something like this:

```typescript
import {
    IAppAccessors,
    IHttp,
    ILogger,
    IModify,
    IPersistence,
    IRead,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IMessage } from '@rocket.chat/apps-engine/definition/messages';
import { AppMethod, IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms/IRoom';
import { IFileUploadContext, IPreFileUpload } from '@rocket.chat/apps-engine/definition/uploads';
import { IUser } from '@rocket.chat/apps-engine/definition/users/IUser';

export class HelloWorldApp extends App implements IPreFileUpload {
    public async executePreFileUpload(
        context: IFileUploadContext,
        read: IRead,
        http: IHttp,
        persis: IPersistence,
        modify: IModify
    ): Promise<void> {
        const user = await read.getUserReader().getById(context.file.userId);
        const room = await read.getRoomReader().getById(context.file.rid);

        if (!room || !user) {
            return;
        }

        // Build file details message
        let fileDetails = `File Uploaded - Name: ${context.file.name}\n`;
        fileDetails += `File Uploaded - Type: ${context.file.type}\n`;
        fileDetails += `File Uploaded - Size: ${context.file.size}`;

        // If text file, include content
        if (context.file.type === 'text/plain') {
            const content = String.fromCharCode.apply(null, context.content);
            fileDetails += `\nFile Uploaded - Content: ${content}`;
        }

        // Get app user to send the message
        const appUser = await read.getUserReader().getAppUser();
        const sender = appUser ? appUser : user;

        // Send message to the room where file was uploaded
        await this.sendMessage(room, fileDetails, sender, modify);
    }

    private async sendMessage(
        room: IRoom,
        textMessage: string,
        author: IUser,
        modify: IModify
    ): Promise<void> {
        const messageBuilder = modify.getCreator().startMessage({
            text: textMessage,
        } as IMessage);

        messageBuilder.setRoom(room);
        messageBuilder.setSender(author);

        await modify.getCreator().finish(messageBuilder);
    }
}
```
3. Save the file and deploy the app. Send an attachment to a room to test the app. The notification is like a temporary private message visible only to the user who sent the attachment (if you refresh the page, the notification is gone). The following screenshot shows an example: ![](https://cdn.us.document360.io/27ca1fd4-36d7-4cde-b4eb-97fc1652954c/Images/Documentation/image(189).png)

Great! With these examples, you have learned how to implement event interfaces and react to certain events. You have made significant progress in expanding your app!

In the upcoming sections, we will look at another way to extend your app's capabilities by creating interactive user experiences with the Apps-Engine UIKit.
