Slack bot that takes orders of electronics.
- user writes AlzaBot one or more direct messages with link(s) of items to order
- user responds to several questions about the order by interacting with buttons:
- country (if user ordered from Alza, country is determined by the language version of the first link)
- office/home delivery
- personal/company
- if company - reason for the order
- whether it is urgent
- note
- submitted order is:
- stored in PostgreSQL DB
- stored in Google sheet
- sent to common admin Slack channel
- in the common admin Slack channel admin can:
- forward the order to admin channel dedicated for the selected office
- decline the order (sends notification to the customer)
- discard the order (removes the order)
- in the admin channel dedicated for the selected office admin can:
- change order status
- send notification to user that the order was ordered/delivered
- close the order
- move the order to archive channel
Send a message to the news channel (channels.news
config) to have Alza bot send it as a direct message to every user in the workspace.
App is configured via environment variables. In config.js
, the variables are read by transenv
package and mapped to a runtime config object.
There are:
- workspace-specific env vars
- currently, the app is hardcoded for three workspaces -
vacuumlabs
,wincent
andtest
- the
vacuumlabs
,wincent
, andtest
env vars accept a stringified object with all workspace-specific variables
- currently, the app is hardcoded for three workspaces -
- global env vars - workspace-agnostic variables
channels
- object of specific channel IDsorders
- main channel where the orders are posted after being submitted by usersarchive
- archived orders are moved heresupport
- channel for bot error reportsnews
- check Announce to allcities
- object of dedicated city channel IDs- e.g. vacuumlabs workspace has
bratislava
,kosice
,presov
,praha
,brno
,budapest
properties here
- e.g. vacuumlabs workspace has
slack
- object of OAuth tokens required for communication via Slack API, obtained from Slack bot app OAuth pageadminToken
- this is the user that installed the app. he needs to be a part of the channels and have workspace admin rights (the app is able to remove messages only by using this token)botToken
- bot tokensigningSecret
- bot signing secret used to initialize@slack/bolt
app
dbTables
- object of the table names that handle the orders for this workspace apporder
- stores the whole order, may contain multiple itemsorderItem
- stores the single items of the order
google
- object of google-sheets-related workspace-app-specific variablesspreadsheetId
- taken from spreadsheet's URL
DATABASE_URL
- PostgreSQL database connection URL; provided automatically by Herokudb_schema
- database schema name
Google API service account is needed to enable communication with Google sheets.
google_sheets_email
- email of the service accountgoogle_sheets_key
- base64 encoded private key the service account (including the -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----)google_sheets_order_id_suffix
- suffix that is added to the order ID stored in the sheet
Other configuration related to Google sheets is stored in src/sheets/constants.js.
NODE_ENV
(optional, default - "development")log_level
(optional, default - "debug" ifNODE_ENV
is "development", "error" otherwise) - winston level of logs that are writtenPORT
- port number where server starts, provided by Heroku automatically
These variables are currently not used but they still need to be present:
alza_username
- username of alza.sk accountalza_password
- password of alza.sk accountalza_cz_username
- username of alza.cz accountalza_cz_password
- password of alza.cz accountalza_hu_username
- username of alza.hu accountalza_hu_password
- password of alza.hu accountcurrency
(optional, default - "EUR") - default currency which is used to show prices
Logging in to Alza account was disabled because they use captcha, so usernames and passwords are technically not used.
App is deployed to Heroku https://dashboard.heroku.com/apps/vacuumlabs-alzabot . Every merge to master
is automatically deployed to production.
Slack app: AlzaBot
Google sheet: Electronics
- company orders: sheet Electronics
- personal orders: sheet Personal Orders
To test the currently deployed app without polluting the real orders database and without letting the office team know about every such order, you can make use of the test
app variant.
How it works: There's a separate Slack bot app configured with another endpoint for actions. When you write it a message and submit a request, it gets send to the test orders channel instead. It is also written to a separate Google sheet and separate database table.
When running a local server, you can decide whether you'll run the database locally too or you'll use the production one with the alzabot-test
table.
Either way, make a copy of .env-dev
called .env
and replace placeholders with actual values (ask for any values you can't obtain yourself).
You should have node.js and yarn installed. If you don't, try Volta - https://volta.sh/.
Install the dependencies - run:
$ yarn
Skip if you decided to use the production alzabot-test
table.
To setup PostgreSQL database:
// open postgres
$ psql
// if you receive the `database "user" does not exist` error, run:
$ createdb
$ psql
// in postgres prompt, run these (ignore `user=#`):
user=# create database alzabot;
user=# \c alzabot;
user=# create schema alzabot;
user=# \q
Run migrations:
$ yarn knex migrate:latest
Your database is now ready for local use. You can change the db configuration in .env
(DATABASE_URL
and db_schema
variables).
Example:
DATABASE_URL=postgres://user:@localhost:5432/alzabot
db_schema=alzabot
You'll need to make your server reachable from outside world - you can use ngrok or similar services.
Run ngrok (this actually runs ngrok http 8000
):
$ yarn ngrok
After that, copy your ngrok url into the Slack app's Interactive messages configuration as Request URL, e.g. https://cb47f7c1.ngrok.io/test/actions
- don't forget the /<variant>/actions
route.
Run the server:
$ yarn dev
You should be able to make an order through the AlzaBotTest app now.
If by any chance you need an own Slack bot app or setting up the app for a new workspace, you'll need to:
- create a legacy Slack app - this option can only be reached somewhere from the documentation (https://api.slack.com/apps?new_classic_app=1)
- the legacy app is needed because AlzaBot still uses legacy permission scopes
- configure the actions endpoint, events endpoint (your app needs to be running), permission scopes, ...
- install the app to the workspace
- copy the user and bot tokens into the env vars
- add the app into the
orders
,archive
,news
, andsupport
channels
You may need access rights:
- Google sheets - Electronics (vacuumlabs), Nozdormu_office _equipment (wincent), AlzaBot Test sheet (test) or your own
- Slack apps - AlzaBot, Wincent-AlzaBot, AlzaBot Test or your own
- heroku app - vacuumlabs-alzabot (production)
- workspace admin rights and being in the channels
- this is needed for the bot to perform some actions "as user" (mainly for deleting messages and comments)
- only such admin should (re)install the app, his token is then used as an env var
- there are two options:
- you are (or you become) the workspace admin
- you install the app(s)
- you get the user token from the Slack app's OAuth page and put it in the env vars
- you get invited to all the channels
- you let another workspace admin install the app
- you list them as the Slack app's collaborator
- they install the app
- they send you the user token and you put it in the env vars
- they make sure they are in all the required channels
- you are (or you become) the workspace admin
If changes in database are required, you can create a new migration:
$ yarn knex migrate:make your_new_migration_name
Find it in knex/migrations/
folder and edit the up
and down
functions.
To apply the migrations to your local db:
$ yarn knex migrate:latest
To push the changes to the production database (you need to have heroku CLI installed and be logged in to your account):
$ heroku run yarn knex migrate:latest --app vacuumlabs-alzabot
If you made a mistake and want to go one migration back (calling the down
function):
$ yarn knex migrate:down migration_name.js
You can do the same on production, but be extra careful:
$ heroku run yarn knex migrate:down migration_name.js --app vacuumlabs-alzabot