earn the White PyBites Ninja earn the Yellow PyBites Ninja earn the Orange PyBites Ninja right arrow earn more PyBites Ninja belts and certificates
The best way to learn to code in Python is to actually use the language.

Our platform offers effective Test Driven Learning which will be key to your progress.


Join thousands of Pythonistas and start coding!


Join us on our PyBites Platform
Click here to code!

Simple API Part 2 - Building a Deep Work Logger with Flask, Slack and Google Docs

Posted by Bob on Fri 10 March 2017 in Flask • 3 min read

After Simple API - part 1 a more practical app in this part 2 tutorial: a Deep Work logger integrating Google docs and Slack, including deployment of the app to Heroku.

Sometimes you come across an article you think: "I definitely need to play with this!", enter Google Spreadsheets and Python.

I decided to make a Flask app to log the amount of deep work. Why? Read the book, in short: it is a powerful success habit.

Design

So we have the API = Flask, the back-end = Google Docs. What about the interface?

I wanted something for both laptop and mobile = Slack. Enter the Slack API / Slash Commands. I defined this super basic interface:

/dw <time> (<activity>)
- /dw is the slack command
- time can be an int (hour) or more specifically hh:mm
- activity is optional, if not provided it defaults to the name of the channel

Step by step

Here is roughly what I did. I document it here so you can start building something similar to scratch your own itch. The code so far is here.

  • To be able to write to a Google Doc follow Google Spreadsheets and Python to create an app via the Google API and obtain the client_secret.json file.

  • pip install flask and pygsheets, implement GET and POST, again more details here. I used Flask's HTTP Basic Auth snippet to protect the GET. For the POST I verify the Slack token. As good practice I stored user/pw in (OS) env variables. I defined some helpers in backend.py.

  • Deploy the app to Heroku (Free plan), I was so glad I took notes some time ago (section "Deployment to Heroku"). I captured the steps as good as I could here (I will adjust next time I deploy an app to Heroku).

  • Deploying an app is a challenge in itself. For example how do you get the client_secret.json file in Heroku? I had to go with this (not ideal) workaround.

    # put client_secret.json in .gitignore on master
    # commit it to secret-branch you keep between localhost and Heroku (not Github)
    ...
    $ git push heroku secret-branch:master
    
  • Create a Slack app, then a Slash Command where I defined:

    • Command: /dw
    • URL = API endpoint on Heroku
    • Method = POST
    • Token = generated, I put that in env variable SLACK_DW_CMD_TOKEN above
    • You can set an Autocomplete help text which is useful to your team
    • This is the payload Slack sends to your API for consumption:

      token=xyz
      team_id=T0001
      team_domain=example
      channel_id=C123
      channel_name=deepwork
      user_id=U123
      user_name=bbelderbos  -> cool: the app can be used by the whole team on Slack
      command=/dw
      text=your_entered_text
      response_url=https://hooks.slack.com/commands/1234/5678
      

      See the parsing of it in the post_entry method.

The app in action

the complete flow

Lessons learned

  • Scratch your own itch. This was a nice exercise to integrate with apps I often use. It taught me a lot because I got stuck so had to debug.

  • For example Slack does not seem to use JSON so in my Flask I had to change request.json to request.form, using ngrok speeded up the debugging.

  • I lost quite some time struggling with gspread (used in the mentioned Twilio article) which was way too slow (2 min for a POST request?!), using pygsheets response times went down to 1-2 seconds or less which made Slack, Heroku and me happy. Lesson: fail fast and small, compare different libraries, and obviously read article comments first before trying!


Keep Calm and Code in Python!

-- Bob


See an error in this post? Please submit a pull request on Github.