Crash course on backend programming for Product Managers//Building a Slack app from scratch — Part 4

Maxim Bassin
13 min readNov 13, 2021

--

This is the 4th part of the series, where we build an awesome app, all by ourselves.

In this part you will:

  1. Open a new account in Mongo DB
  2. Create a new database and a collection to store the messages in it
  3. Install Mongo DB’s npm package
  4. Store credentials in the config vars on the server (avoiding hardcoded credentials)
  5. Retrieve the “next up” message from Mongo DB and send it using our app
  6. Once successfully sent, mark the message as sent in Mongo DB and set the “next up” message

Setting up a MongoDB account and adding the messages to it

(4 steps)

  1. Set up the MongoDB account with Javascript as a preferred language, starting here

2. Now let’s create a “collection” for our messages data. A collection is like a folder that contains “documents”, which are similar to files under a folder. Each “document” will hold info about a single message

3. Now we’ll add our first message data. The message data should contain the following info:

  • setup — this will hold the text for the joke setup (including the special characters we used to stylize our message — the asterisks at the beginning and the end of the text)
  • punch — this will hold the text for the punchline
  • image — this will hold the link address to the joke image on the S3 bucket
  • nextup — this is the boolean (true/false) indicator for whether the message is the next up to be sent

(Use the return key to create a new line)

4. Now let’s use the document clone option to copy the structure, and for every new copy we’ll update it with the relevant content. The reason for creating a clone is to maintain the exact same document structure for our code to operate correctly. Repeat the process until you’ll add all your jokes to MongoDB

Getting our code to pull the next up message from the MongoDB account

(15 steps)

  1. Install the MongoDB npm package to our project so we will be able to easily use the MongoDB related functions in our code. Write the following text in the Terminal of the VSCode, and hit the return key:
npm install mongodb
This is how the success screen should look like

2. Now let’s include this functionality in our code by adding the following line to the top of our code, and saving the file:

//Requere the mongodb package
const { MongoClient } = require('mongodb');

3. Let’s create a user on MongoDB to get credentials to connect to our database from our app (avoid using special characters for username and password setup, for simplicity)

4. Now let’s copy those credentials

5. Add the following lines to the code and paste the copied credentials right after it. We will use mongouri as credentials in our code for MongoDB connection (instead of pasting the actual credentials each time). Also, we’ve set up a joke parameter

const mongouri = //PASTE HERE THE CREDENTIALS CODE YOU"VE COPIED//
let joke;// the joke parameter will hold our message data

6. Replace the <password> part with the password of the user you’ve recently created to access the database

7. Copy the database name from MongoDB and paste it instead of the “myFirstDatabase” part

8. Add double quotes around the credentials. content in quotes is treated as text, instead of variable

9. Create the actual connection to the database using the credentials, by adding the following code

// Create a new MongoClient
let mongoClient = new MongoClient(mongouri, {
useUnifiedTopology: true
})
try {
// Connect the client to the server
await mongoClient.connect();
let db = mongoClient.db('slackapp')//set the reference to the connected slackapp database as db

//get the joke data
let messagesCollection = db.collection('messages')// set the reference to the messages collection as messagesCollection
joke=await messagesCollection.findOne({ nextup: true }) // this line will find one document in the messages collection that has the nextup value set to true, and store this document and its content as parameter named joke


} catch (errormongo) {
console.error(errormongo);
}

This code basically connects to the database using the credentials we’ve set up, and retrieves the document that has the nextup parameter set to true, from the messages collection. The document is stored in the joke parameter, and we can use its content to fill the message content we are sending. Instead of sending a hardcoded message.

10. Using the joke’s parameter content, we’ll fill in the message data we’d like to send. Remember that in our document, there are keys named setup, punch, and image. To retrieve their content from the joke’s parameter, we can use the following syntax: joke.setup will give the setup content of the retrieved document, joke.punch will retrieve the punch content, and joke.image will retrieve the link to the link to the image.

Replace the message content with the following:

11. Let’s test it by setting up the time for 5 minutes from now, on the UTC timezone, saving the file, committing it, and pushing it to production. Then check our slack to see if we got the message when the time comes.

12. Check your Slack. Did you get a new message from the app? You did? Great! You’ve successfully hooked up MongoDB to your app and retrieved the message content from the database, instead of having it hardcoded in the app.

13. One last thing for this part. Our MongoDB credentials are hardcoded in the app code. We’ll store them on the server (Heroku) for security reasons. Go to Heroku, and add the MongoDB credentials (without the quotes) as a value of mongouri parameter.

14. Instead of the hardcoded credentials we should get the value from our server. These Config Vars are stored as environment variable that is available on the server. To access its value from the code we can use process.env.mongouri syntax, which basically goes to the process object, and gets the mongouri variable from the env (environment) parameters.

15. Let’s test it again (adjust the job time to 5 minutes ahead in UTC, save, commit, push). Got the message in Slack? Yay!

Update the jokes collection to indicate the new next up message, to be used for the next message

We’ll a new field to our documents to indicate messages that have already been sent, and mark the next up message to be sent.

Let’s go!

Add the “sent” field of a boolean type (true/false) to all our documents in the collection

(7 steps)

  1. Let’s set up our terminal in VSCode to access and modify our MongoDB documents programmatically. Go here to find the instructions:

2. I’ll go with the Mac version. Write the following command in the Terminal and hit the return key

brew install mongosh

This might take a few minutes to complete.

3. Once you’ll see this line, this means that the process is complete.

You might notice a few errors, that were thrown in the process — those can pop up for many reasons. Let’s try to run our command anyway, in case the errors are not related to our goal.

4. Now add the connection command copied from the instructions and hit the return key

5. Add your password for the added user in MongoDB and click enter

This is the sign of a successful connection

6. Now that we are connected to our database in MongoDB, we can add “sent” field to all of our documents in the messages collection, using the following code:

db.messages.updateMany({},{ $set: {"sent": false} })

Note: messages in the code above is the name of the collection that keeps your documents containing the jokes

You can read more about this code in the official documentation here.

Basically, this code translates to:

  • Go to “messages” collection in the database and update (db.messages.updateMany)
  • all the documents (the curly brackets {} without a value inside them specify that we don’t want to filter anything out of the messages collection)
  • with an additional parameter named “sent”, that is set to false ({ $set: {“sent”: false} })

When clicking enter, you should see a similar result in the terminal

7. Check the collection in MongoDB to see the updated documents 🎉

Upon sending the message to slack, update the “sent” field of the sent document to “true” and mark another document as “nextup”

(5 steps)

  1. Since we’re going to update several things in our collection, let’s set the variables for the database and collection references as global variables, by putting them in the top section of our code, before our functions are executed. To do so we need to add these 2 lines (variables set up outside of a function are available for all functions. Variables set up inside a function are available only for that function and are not accessible from other functions)

and then to remove the “let” from the variables here (“let” is a command to create a new variable, since we’ve set it up at the beginning of our code, we wouldn’t want to create a new one locally)

2. Mark the currently sent document as sent and remove the nextup flag from it. Paste the following lines into the code in the VSCode, to be right after the last “catch” statement:

try {
let updatesent = await messagesCollection.updateOne({ nextup: true }, { $set: { nextup: false, sent: true } }) ; //Find one document that has the nextup value set to true and change its nextup value to false, and sent value to true
}
catch (errormongo){
console.error(errormongo);//in case an of an error with the execution, printout the error in the server log
}

Which translated to:

  • Try to update one document from the messages collection, wait for the action to finish. Let updatesent be the variable holding the results of the action
  • When looking for a document to update, search the one that has the nextup field set to true
  • When found, set the nextup field to false and the sent field to true
  • In case of an error, print it out in the server log

3. Now let’s find a document that is not flagged as nextup, nor as sent (nextup: false, sent: false), and set it to be next up (nextup: true). Paste this code right after the previous one:

try {
let updatenextup = await messagesCollection.updateOne({ nextup: false, sent: false }, { $set: { nextup: true } }) ; //Find one document that has the nextup value set to false, while the sent value is set to false, and change its nextup value to true
}
catch (errormongo2){
console.error(errormongo2);//in case an of an error with the execution, printout the error in the server log
}

4. Change the corn job timing to be a few minutes from now and save.

5. Then add, commit and push to the server. when the job will finish executing, you will be able to see the updated fields in MongoDB

To summarize what we’ve achieved in this part

  • We set up a MongoDB account
  • Switched the message sending to use database info, instead of hardcoded messages
  • Used the terminal and shell commands to access the database and perform batch actions on our database data
  • Dynamically retrieved and updated database from our app

In the next part you will:

  1. Create a new server app on Heroku that will serve as a website
  2. Set the server application to respond to GET messages
  3. Create a simple HTML page with an “Add to Slack” button
  4. Built an Oauth2 authentication process: Get from Slack a temporary authorization code and exchange it for an access token

Let’s go to part 5>>

--

--