Refactor to a clean separation of concerns

I've made use of promises to simplify error handling and clean up the code. Overall, there are more lines now, but this is mostly because of my heavy commenting.

I brought in `dotenv` as well. I'm not sure how @x was managing environment variables, but this seemed to be a sane way to go about it.

It might be easier to understand the changes by looking at the actual code in the branch rather than the diff, since so much has changed.