How to Create a Slack News Bot Using AWS Lambda and Terraform

Aurimas Mickevicius
7 min readMay 31, 2021
Photo by Markus Winkler on Unsplash

It’s so easy to get distracted by the modern media which is full of click baits, fake sensationalism, ads, and generally poor content. If I check the latest news (or worse, Social Media updates) first thing in the morning, I find myself in the media rabbit hole, following article links, and researching various irrelevant topics waisting the most productive part of the day.

This article is a step by step guide showing how to create a Slack bot which posts the highest ranked Hacker News(HN) and/or Product Hunt(PH) articles to Slack at a specific time each day. If you set yourself a rule “No news until I get this Slack message at 2pm” and stick to it, you could boost your productivity by keeping clear mind for deep work and build a habit for it.

The Slack bot you’ll build ranks HN articles by the amount of comments, with links to discussions as well as article source URL. PH posts are ranked by votes count and link to PH product page as well as the product website. Below is an example of Slack post:

It’s worth mentioning that you can disable specific news sources. For example, you could disable Product Hunt news if you are not interested in product development. This bot can also be easily extended by adding other media sources, for example the highest ranking posts in the subreddits you subscribe to.

A few technologies used:

  • terraform-aws-lambda Terraform module to build Lambda package and provision AWS resources.
  • Pythonasyncio to query large number of URLs (Hacker News).
  • Python requests to query GraphQL API (Product Hunt).
  • pytest and Github Actions to run AWS Lambda unit tests.
  • Slack blocks to format messages.

Prerequisites

  • AWS account. The aim is to run the news Bot free of charge, so all resources created in AWS use free tier.
  • Slack workspace.
  • Product Hunt account API token(Optional).
  • Terraform installed on local machine.

Architecture

The architecture of this bot is very straightforward. AWS EventBridge runs on cron like schedule and triggers the Lambda function at a set time. The Lambda queries the Hacker News and/or Product Hunt API, filters top posts, formats text, and sends to the Slack channel. All AWS resources are deployed with Terraform.

Setting up the bot

Slack

Sign it to your Slack workspace and create a new public Slack channel #news. This is where you’ll receive Lambda posts.

Navigate to https://api.slack.com/apps. Click on “Create New App” and select “From scratch”. Give your App a Name, pick a workspace, and click on “Create App”.

Click on “Permissions” section and under “Scopes” part click on “Add an OAuth Scope”. You need to add incoming-webhook and chat:write scopes to allow Lambda posting to channel.

At the top of the page find “OAuth Tokens for Your Workspace” section and click on “Install to Workspace”. This will create a request to access your workspace. Enter #news channel for NewsBot posts and click on “Allow”. You will be issued a “Bot User OAuth Token” which is used when deploying AWS Lambda with Terraform.

Invite the bot to your Slack channel by entering the below command in #news:

/invite @NewsBot

You should see:

In this example the bot icon is customised, you can modify it by adding an image in Basic Information -> Display Information.

Deploying AWS Lambda

First of all, we need to create a private S3 bucket to store Terraform state. If it’s your first time using AWS, make sure you’ve created a non-root AWS IAM admin user and have the AWS cli installed on your local machine. The S3 bucket name has to be globally unique, you can create a random string, but it’s a good practice to append the bucket name with your AWS account ID:

## Get AWS Acount ID
$ aws sts get-caller-identity --query Account --output text
123456789012
## Create S3 bucket
$ aws s3 mb s3://slack-news-bot-123456789012 --region eu-west-1
make_bucket: slack-news-bot-123456789012

Clone the NewsBot github repo. If you don’t have git installed, you can set it up using this guide:

git clone https://github.com/aurimasmick/slack-news-bot.git

Main repository files and folders:

  • ./github — Github Actions workflows and templates.
  • /src — Lambda Python source code and unit tests.
  • .coveragercpytest-cov plugin settings.
  • .flake8flake8 settings for Python linting.
  • .pre-commit-config.yaml — pre-commit hooks for Terraform linting.
  • Makefile — helper functions.
  • main.tf — Terraform code for AWS resources.
  • secrets.tfvars.example — template to store secrets locally. It should not be pushed to public repo. It’s added to .gitignore by default.
  • state.tf — Terraform state file location. You need to modify this file to use the newly created bucket.
terraform {backend "s3" {
bucket = "slack-news-bot-123456789012"
key = "slack-news-bot/main.tfstate"
region = "eu-west-1"
encrypt = true
}
}
  • terraform.tfvars — variable values.
  • variables.tf — variable definitions.

It is worth mentioning that there are multiple ways to handle Lambda secrets. The most secure method is to use a secrets store like AWS Secrets Manager and fetch secrets dynamically during Lambda execution. However, this service is not free and we don’t want NewsBot to cost anything. You could also use a tool like sops which encrypts the secrets file using PGP or AWS KMS allowing to store it on Git. After we decrypt the file and run Terraform to deploy Lambda, we still store that secret as a Lambda environment variable in plain text on AWS, so it defeats the purpose in our use case.
Since this is not a Production or mission critical project, and the secrets involved aren’t hard to rotate/regenerate if compromised, you will export the secrets as environment variables. After you run Terraform in the next step, the secrets will be stored in AWS as Lambda environment variables.

export TF_VAR_slack_bot_token=(TOKEN CREATED IN SLACK STEP)
export TF_VAR_ph_api_token=(PRODUCT HUNT API TOKEN)

You would still need some place to store those secrets, like a 1Password or LastPass vault. If you don’t use either of those tools, you can create a secrets.tfvars file. Make sure this file is not pushed to a public repo, by default it’s added to .gitignore:

slack_bot_token = (TOKEN CREATED IN SLACK STEP)
ph_api_token = (PRODUCT HUNT API TOKEN)

PRODUCT HUNT API TOKEN can be obtained by creating a Product Hunt account. If you don’t want Product Hunt posts, you don’t need to export or specify a value for this variable. In such case, modify terraform.tfvars and change post_ph to “false”:

name                = "slack-news-bot"
slack_channel_name = "news"
post_hn = "true"
post_ph = "false"
stories_number = 5
schedule_expression = "cron(0 14 * * ? *)"

Deploy AWS resources with Terraform:

terraform initterraform plan
terraform apply
## If using secrets.tfvars
terraform plan -var-file=secrets.tfvars
terraform apply -var-file=secrets.tfvars

Terraform will create the following resources:

  • Lambda .zip package in /build directory
  • AWS Lambda function
  • AWS IAM Role and Policy for Lambda
  • AWS CloudWatch Logs Group
  • AWS EvenBridge rule and event target
  • Lambda permission to allow event trigger

Once all resources are provisioned, you can trigger the Lambda function manually from the AWS Lambda console by using the default “Hello World” template. Make sure to select Ireland as the region for the AWS console if you are following this example verbatim or change it to the region you specified when configuring your Terraform variables.

Making changes to Lambda

If you want to modify or add functionality to the Lambda function, you need to create a Python virtual environment and install dependencies:

python3 -m venv venv
source venv/bin/activate
pip install -r src/slacknewsbot/requirements.txt

There are a few Makefile helper functions to lint, unit test and deploy lambda:

make tests
make deploy
## if using secrets.tfvars
make deploy-with-secrets-file

Conclusion

I hope the NewsBot you’ve created will increase your productivity and reduce distractions which are so common when working from home. If you’ve followed this step by step guide, you have been using a few modern technologies along the way. Now it’s your turn to fine-tune the bot to your liking and preferences and dive deeper into the code to further improve your skills. Enjoy!

--

--