# How to Send MongoDB Document Changes to a Slack Channel

In this tutorial, we will explore a seamless integration of your database with Slack using Atlas Triggers and the Slack API. Discover how to effortlessly send notifications to your desired Slack channels, effectively connecting the operations happening within your collections and relaying them in real-time updates. 

The overall flow will be: 

.

Once this has been completed, we are ready to start creating our first database trigger that will react every time there is an operation in a certain collection. 

## Atlas trigger

For this tutorial, we will create a trigger that monitors all changes in a `test` collection for `insert`, `update`, and `delete` operations.

To create a new database trigger, you will need to:

1. Click the **Data Services** tab in the top navigation of your screen if you haven't already navigated to Atlas.
2. Click **Triggers** in the left-hand navigation.
3. On the **Overview** tab of the **Triggers** page, click **Add Trigger** to open the trigger configuration page.
4. Enter the configuration values for the trigger and click **Save** at the bottom of the page.

Please note that this trigger will make use of the *event ordering* as we want the operations to be processed according to when they were performed. 

The trigger configuration values will look like this: 

 using the UI, we need to:   

1. Click the **Data Services** tab in the top navigation of your screen if you haven't already navigated to Atlas.

2. Click **Functions** in the left navigation menu.

3. Click **New Function** in the top right of the **Functions** page.

4. Enter a unique, identifying name for the function in the **Name** field.

5. Configure **User Authentication**. Functions in App Services always execute in the context of a specific application user or as a system user that bypasses rules. For this tutorial, we are going to use **System user**.

### "processEvent" function

The processEvent function will process the change events every time an operation we are monitoring in the given collection is processed. In this way, we are going to create an object that we will then send to the function in charge of sending this message in Slack. 

The code of the function is the following:

```javascript
exports = function(changeEvent) {

    const docId = changeEvent.documentKey._id;

    const { updateDescription, operationType } = changeEvent;

    var object = {
        operationType,
        docId,
    };

    if (updateDescription) {
        const updatedFields = updateDescription.updatedFields; // A document containing updated fields
        const removedFields = updateDescription.removedFields; // An array of removed fields
        object = {
            ...object,
            updatedFields,
            removedFields
        };
    }

    const result = context.functions.execute("sendToSlack", object);

    return true;
};
```

In this function, we will create an object that we will then send as a parameter to another function that will be in charge of sending to our Slack channel. 

Here we will use change event and its properties to capture the: 

1. `_id` of the object that has been modified/inserted.
2. Operation that has been performed.
3. Fields of the object that have been modified or deleted when the operation has been an `update`.

With all this, we create an object and make use of the internal function calls to execute our `sendToSlack` function.

### "sendToSlack" function

This function will make use of the "chat.postMessage" method of the Slack API to send a message to a specific channel.

To use the Slack library, you must add it as a dependency in your Atlas function. Therefore, in the **Functions** section, we must go to the **Dependencies** tab and install `@slack/web-api`.

You will need to have a Slack token that will be used for creating the `WebClient` object as well as a Slack application. Therefore: 

1. Create or use an existing Slack app: This is necessary as the subsequent token we will need will be linked to a Slack App. For this step, you can navigate to the Slack application and use your credentials to authenticate and create or use an existing app you are a member of. 

2. Within this app, we will need to create a bot token that will hold the authentication API key to send messages to the corresponding channel in the Slack app created. Please note that you will need to add as many authorization scopes on your token as you need, but the bare minimum is to add the `chat:write` scope to allow your app to post messages.

A full guide on how to get these two can be found in the Slack official documentation.

First, we will perform the logic with the received object to create a message adapted to the event that occurred. 

```javascript
var message = "";
if (arg.operationType == 'insert') {
    message += `A new document with id \`${arg.docId}\` has been inserted`;
} else if (arg.operationType == 'update') {
    message += `The document \`${arg.docId}\` has been updated.`;
    if (arg.updatedFields && Object.keys(arg.updatedFields).length > 0) {
        message += ` The fileds ${JSON.stringify(arg.updatedFields)} has been modified.`;
    }
    if (arg.removedFields && arg.removedFields.length > 0) {
        message += ` The fileds ${JSON.stringify(arg.removedFields)} has been removed.`;
    }
} else {
    message += `An unexpected operation affecting document \`${arg.docId}\` ocurred`;
}
```

Once we have the library, we must use it to create a `WebClient` client that we will use later to make use of the methods we need. 

```javascript
  const { WebClient } = require('@slack/web-api');
  // Read a token from the environment variables
  const token = context.values.get('SLACK_TOKEN');
  // Initialize
  const app = new WebClient(token);
```

Finally, we can send our message with: 

```javascript
try {
    // Call the chat.postMessage method using the WebClient
    const result = await app.chat.postMessage({
        channel: channelId,
        text: `New Event: ${message}`
    });

    console.log(result);
}
catch (error) {
    console.error(error);
}
```

The full function code will be as:

```javascript
exports = async function(arg){

    const { WebClient } = require('@slack/web-api');
    // Read a token from the environment variables
    const token = context.values.get('SLACK_TOKEN');
    const channelId = context.values.get('CHANNEL_ID');
    // Initialize
    const app = new WebClient(token);

    var message = "";
    if (arg.operationType == 'insert') {
        message += `A new document with id \`${arg.docId}\` has been inserted`;
    } else if (arg.operationType == 'update') {
        message += `The document \`${arg.docId}\` has been updated.`;
        if (arg.updatedFields && Object.keys(arg.updatedFields).length > 0) {
            message += ` The fileds ${JSON.stringify(arg.updatedFields)} has been modified.`;
        }
        if (arg.removedFields && arg.removedFields.length > 0) {
            message += ` The fileds ${JSON.stringify(arg.removedFields)} has been removed.`;
        }
    } else {
        message += `An unexpected operation affecting document \`${arg.docId}\` ocurred`;
    }

    try {
        // Call the chat.postMessage method using the WebClient
        const result = await app.chat.postMessage({
            channel: channelId,
            text: `New Event: ${message}`
        });
        console.log(result);
    }
    catch (error) {
        console.error(error);
    }

};
```

Note: The bot token we use must have the minimum permissions to send messages to a certain channel. We must also have the application created in Slack added to the channel where we want to receive the messages.

If everything is properly configured, every change in the collection and monitored operations will be received in the Slack channel:

 to only detect certain changes and then adapt the change event to only receive certain fields with a "$project".

## Conclusion

In this tutorial, we've learned how to seamlessly integrate your database with Slack using Atlas Triggers and the Slack API. This integration allows you to send real-time notifications to your Slack channels, keeping your team informed about important operations within your database collections.

We started by creating a new application in Atlas and then set up a database trigger that reacts to specific collection operations. We explored the `processEvent` function, which processes change events and prepares the data for Slack notifications. Through a step-by-step process, we demonstrated how to create a message and use the Slack API to post it to a specific channel.

Now that you've grasped the basics, it's time to take your integration skills to the next level. Here are some steps you can follow:

- **Explore advanced use cases**: Consider how you can adapt the principles you've learned to more complex scenarios within your organization. Whether it's custom notifications or handling specific database events, there are countless possibilities.
- **Dive into the Slack API documentation**: For a deeper understanding of what's possible with Slack's API, explore their official documentation. This will help you harness the full potential of Slack's features.

By taking these steps, you'll be well on your way to creating powerful, customized integrations that can streamline your workflow and keep your team in the loop with real-time updates. Good luck with your integration journey!

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt8fcfb82094f04d75/653816cde299fbd2960a4695/image2.png
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltc7874f54dc0cd8be/653816e70d850608a2f05bb9/image3.png
  [3]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt99aaf337d37c41ae/653816fd2c35813636b3a54d/image1.png