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 👨💻👩💻👇
Good Morning Bot
A slack app that sends a 'Good Morning' with a random emoji and gif, every workday in the morning.
Installation
Clone the repo:
git clone https://github.com/danielbellmas/good-morning-bot.git
Install dependencies with npm:
cd good-morning-bot
npm install
💡 Before you can run the project you'll need some environment variables 👇
Environment Variables
In order to run this project, you will need to add the following environment variables to your .env file.
Follow these instructions to get Slack's environment variables.
By signing in to Giphy, you can obtain the GIPHY API KEY
.
Here are the env variables you'll be needing: (you can also view them here)
#Slack
SLACK_BOT_TOKEN=xoxb-...
SLACK_USER_TOKEN=xoxp-...
SLACK_SIGNING_SECRET=00...
SLACK_APP_TOKEN=xapp-...
#Giphy API
GIPHY_API_KEY=X...
Run project:
npm start
Resources
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
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:
- Get a random emoji from the emoji list.
- Fetch a random gif from the Giphy API.
- Send every workday - not including holidays.
- Send the massage in the morning.
- Send the message as myself.
- Deploy the bot
Let’s start 🦾
1. The random emoji
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:
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. 👾
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.
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
! 🤯
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:
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.👻
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).
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, you may have seen the Procfile
- the file that says to heroku
what command to execute in order to run the app.
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 🙂
🔥 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
If you want to play with the cron syntax, use cron.guru.
Cron
is a scheduler or timer that automatically starts a job.
You can find this code in the utils
folder under 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 🦅
Top comments (0)