Good Morning Slack Bot 🤖
Published: 2022-07-11 16:23:39

**TL;DR**
I made a slack app that says **Good Morning** with a random **emoji** and **gif** at a random time after 8 AM.

For the code and detailed step by step on how to install the bot, click on the repo below 👨‍💻👩‍💻👇

{% embed https://github.com/danielbellmas/good-morning-bot %}

After coming up with the idea, I started with a simple app: An app that squares up a number it gets from the user. 
I started small to give myself time to get acquainted with slack's framework: [`@slack/bolt`](https://slack.dev/bolt-js/tutorial/getting-started)

Seeing everything worked gave me the OK to start thinking about how to achieve the goal: Send a good morning message every workday (as myself).

**Here are the objectives:**

1. [Get a random emoji from the emoji list.](#1-the-random-emoji)
1. [Fetch a random gif from the Giphy API.](#2-the-random-gif)
1. [Send every workday - not including holidays.](#3-send-the-message-on-every-workday)
1. [Send the massage in the morning.](#4-send-the-message-in-the-morning)
1. [Send the message as myself.](#5-send-the-message-as-myself)
1. [Deploy the bot](#6-deploy-the-bot)

## Let’s start 🦾
### 1. The random emoji
![Emoji list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3oujq8nmxpnpifmk3grd.png)

 
You might be wondering why there are several instances of the sun emoji ☀️.
Well… that’s for giving this emoji a higher chance to be picked.
After all, it’s the most appropriate emoji IMO.

For picking a random item from a list I use the `pick` function:

![pick function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qk6e47kadp1v9uc3rfh6.png)
 
 

### 2. The random gif
For that, I used Giphy’s API.
I also considered a set list of gifs, stored in a JSON file, but fetching on the fly is more fun. 👾

```js
https://api.giphy.com/v1/gifs/search?api_key=${process.env.GIPHY_API_KEY}&q=good morning
```
> In order to get the `GIPHY_API_KEY` you need to sign into [Giphy](https://developers.giphy.com/).


### 3. Send the message on every workday
Sometimes I think there’s a package for every need… so naturally, I looked for one…and found a package called  [`hebcal`](https://github.com/hebcal/hebcal)! 🤯
With a little research, I saw that they expose an API for dates of holidays, among other things.
With this API I could expose a function that tells me if it’s a day off (**don't** send the message) or a workday (**do** send the message).

That was the hard part, the easy part is to check if it’s a weekend or not:

```js
function isWeekend(date = new Date()): boolean {
  return date.getDay() === 5 || date.getDay() === 6;
}
```


### 4. Send the message in the morning
Ok. A quick recap: We've managed to pick a random emoji and gif, and avoid sending the message on the weekend and on days off.

Now we can get to the juicy part: actually sending the message and timing it so that it will happen at a **random** time each workday.
> Why random you ask? because we can't have them know it's a bot.👻

![Schedule the massage - code snippet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqonkyqkrkxq4aa3ycpq.png)

**Code Breakdown**

- In order to send every day we need to check if we need to send or not, every period of time (I chose every half an or so), and we can achieve that with the `setTimeout` function.
- If the current hour is 8 am, we check that:
- We didn't already send a message today.
- It's not the weekend.
- It's not a day off.

Only then do we send the massage and set `isSentToday` to `true`, That way, we'll only send once a day. ⚡️

### 5. Send the message as myself
So this one was a tricky one for me.
At first, I didn't really find out what was missing to make it work. 
I saw the `as_user` option but setting it to `true` was not enough. We also need to pass in the user's token (in our case it's our own token).

![Send massage function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbwoix5jfmyiric4bct.png)

With the help of slacks API we can call `postMessage` and see our bot come to life 🤖 🦾 🦿
 

### 6. Deploy the bot
Deploying will allow us to run the bot independently from our machine.
I deployed mine on `heroku`.
If you already looked at [the code](https://github.com/danielbellmas/good-morning-bot), you may have seen the `Procfile` - the file that says to `heroku` what command to execute in order to run the app.

```js
worker: npm start
```
If you're familiar with `heroku` than you probably saw `web: npm start`.
Here we are using the `worker` option because we want it to always run in the background:
> `worker` dynos (non-web) do not sleep (as they don't receive web requests), so they will run 24/7. 

`Heroku` has a limitation for the number of **dyno hours** per month. But the good news is that a free user has 1000 free dyno hours per month, which means more than 730 hours (_The number of hours in a month_).

> **Disclaimer**: This is just the way I implemented the idea.
If you have a different idea, write a comment 🙂


![Good Morning message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8jnpm0uezozlokw5acv.png)
 
### 🔥 Bonus 🔥
Minimizing API calls by fetching for the holiday JSON **only once at the beginning of each month.**

To fetch only once **every** month we need to introduce `cron`, or more specifically `node-schedule`

![Cron syntax gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ltegxwf2180uyq71hugk.gif)
> If you want to play with the cron syntax, use [cron.guru](https://crontab.guru/#0_0_1_*_*).
 
`Cron` is a scheduler or timer that automatically starts a job.

![Schedule job - code snippet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lru2khjvzihydwopiw2.png)
_You can find this code in the [`utils` folder under `dayOff.ts`](https://github.com/danielbellmas/good-morning-bot/blob/main/utils/dayOff.ts)_
 
Every 1st of the month we'll fetch - `getHolidays()` and save the result in a JSON file.
And every time we'll want to check if today is a holiday, we'll just read the file instead of making an API call 🦅