covid19-helper-bot
covid19-helper-bot copied to clipboard
A helper Whatsapp Bot for COVID-19 related information
COVID19 Helper Bot
A Whatsapp Bot to help get information about COVID19, aiming to participate on the Twilio & Dev 2020 Hackathon.
Using Twilio Autopilot and Python 3.8
Stack
- Python3.8.2
- Poetry
- Fastapi
- Pydantic
- Fauna DB
- Hosted on Heroku
- Pytest
- Loguru
- Requests
- Sentry
- Click
Kickstarted with: https://github.com/Dectinc/cookiecutter-fastapi
Project structure
Files related to application are in the app
or tests
directories.
Application parts are:
.
├── app
│ ├── api - Api routes
│ │ └── routes
│ │ └── autopilot - Twilio Autopilot Dynamic actions
│ ├── core - Critical configuration (sessions, logging, etc)
│ ├── custom_routers - FastAPI custom routes
│ ├── error_handlers - Custom error handlers
│ ├── middlewares - FastAPI/Starlette middleware configuration
│ ├── models - Pydatic models
│ ├── scripts - Helper scripts (mainly cli stuff)
│ ├── services - Utilites for interaction with external apis and logic too heavy for the routes
│ └── utils - Helper functions
├── assistant - Autopilot schema
├── design_docs - Some diagrams (not to comprehensive)
└── tests - Pytest
How to run
First, install dependencies with Poetry: poetry install
.
Integrated cli
This app comes with an integrated CLI, activate the env (with poetry shell
) and run
python main.py
. The options are:
Usage: main.py [OPTIONS] COMMAND [ARGS]...
COVID19 Whatsapp Bot CLI Helper
Options:
--help Show this message and exit.
Commands:
create-collections Creates all collections defined in the models folder
generate-env Generates a file .env with the default configuration with the default values
prepare-schema Replaces the variables in the assistant schema for the ones on the env
run Runs the development server
FaunaDB
Then, we need to set FaunaDB; two options:
Use provide Docker file
- Spin up the Docker image:
docker-compose up
. - Run the FaunaDB shell:
docker-compose exec --user root shell /bin/bash
- Run:
fauna create-database myapp
- Then,
fauna create-key myapp
- Copy the key that gets generated
Use FaunaDB from the cloud
Easier but not so recommended for development.
- Check out FaunaDB's getting started
- Follow the steps to generate a key for the database you created
- The URL now will be: https://db.fauna.com (hold this)
Environment variables.
The default environment variables are defined ins app/models/config
and are as follow:
API_PREFIX = "/api"
AUTOPILOT_ENDPOINT_PREFIX = "/autopilot" # API Prefix for autopilot endpoints
VERSION = "0.1.0"
DEBUG = False
TESTING = False
PROJECT_NAME = "COVID19 Helper Bot"
LOGGING_LEVEL = LoggingLevels.INFO
ENVIRONMENT = Environments.DEV # Possible also STAGING and PRODUCTION
FAUNA_DB_URL = "http://localhost:8443"
FAUNA_SERVER_KEY = "your_server_key_here"
TWILIO_ENDPOINT = "http://localhost:5000" # Your API's endpoint that will be called by Twilio
NOVELCOVID_JHUCSSE_API_URL = "https://corona.lmao.ninja/v2"
ENDLESS_MEDICAL_API_URL = "https://api.endlessmedical.com/v1/dx"
OUTCOME_THRESHOLD = 0.45 # Confidence level for recommending seeking medical help
FAKE_NUMBER = '+15555555' # Fake number to be user in dev
TWILIO_AUTH_TOKEN # Not needed in dev, can be leaved as this
SENTRY_DSN # Not needed in dev, can be leaved as this
The order on which the variables take precedence are:
- The ones defined in the SO environment
- The ones defined in the
.env
file (can only be used in dev mode) - The defaults on the config schema
For development purposes, just generate the .env
file with python main.py generate-env
You need to replace FAUNA_SERVER_KEY
with the key obtained when you set up FaunaDB. Also, if you are using
the cloud version, you need to replace the FAUNA_DB_URL
with the url stated on that step.
Create schema
Once the envs are set up, run python main.py create-collection
to generate the FaunaDB Collections an indexes.
Running
Finally, you can run the server with python main.py run
.
Docs available under /docs
.
Generate the Autopilot Assistant
The Autopilot Assistant Schema for this bot lives in assistant/schema.json
.
Refer to Twilio docs for how to create an assistant with the CLI.
Once that's done, replace the TWILIO_ENDPOINT
with your url; run python main.py prepare-schema
. This option
looks for occurrences of %TWILIO_ENDPOINT%%API_PREFIX%%AUTOPILOT_ENDPOINT_PREFIX%
on the schema and replaces with
the values defined in the environment (or .env
file if in dev mode).
Then, open the after_deploy.sh
script and replace the --unique-name
flag for your assistant's unique name.
Run the script with bash
to update your assistant with the schema (needs yarn
installed).
This script is a bit rough around the edges, since it was written ad-hoc for CI/CD. In summary, what this script does
is prepare the schema with the prepare-schema
command defined above (so you don't need to run that if you use after_deploy
)
and uploads the schema to twilio using its cli.
For running in local
In dev mode, the API injects the FAKE_NUMBER
env into all incoming Autopilot Requests, this way you can test
your API locally from the Twilio Simulator using a SSH tunnel such as ngrok.
Deployment
This API comes with a Procfile ready to be deployed on Heroku, the only extra configuration you need is to add this buildpack in order for Heroku to support Poetry. But, for running, it will require the following envs to be present:
-
FAUNA_SERVER_KEY
-
TWILIO_AUTH_TOKEN
-
SENTRY_DSN
Tests
The tests are by no means complete, but you can run them anyways with pytest
. The caveat is that, being FaunaDB so new,
there is not much info on how to mock it; so the FAUNA_SERVER_KEY
would need to be present (use Docker for this).
Information
All information regarding statistics are from the Novelcovid API; which in turn takes its data from the John Hopkins University repository.
The Endless Medical API was used for the analysis of the user symptoms. This analysis only serves as guidance and does not replace the diagnosis of a doctor.
Acknowledgments
Huge thanks to the team of Endless Medical for answering my inquiries and being so helpful overall. And thanks to all the friends and family who copped with my annoying "could you please text the bot?"