I’m taking a small break from the SIP registration project for twilio to work on a quick app that automatically updates the time spent on my JIRA issues based on my TimeDoctor logs. I also want it to send me a weekly report and a monthly report. I originally designed everything to be extremely modular (so that you could use different “notification” plugins and time tracking services) but I got discouraged by the time it was taking me. This needs to be something that makes my life easier, not an extra project :). I’m using Python here because… I want to!
TimeDoctor has an API that lets me retrieve my worklogs… and that’s cool, but the only way to authenticate a user is through OAuth2 without the possiblity of using
password. That is great if you’re creating an app that lots of people are going to use and most importantly: if the app you’re building is a web app. I want to do this as a console app, so that I can put it in a cron and just forget about it. This approach requires me to put my TimeDoctor credentials in the application, but I’m ok with that.
My first approach was using Flask, and launching a web server if the tokens (access and refresh) failed. That seemed like a decent workaround, given that refresh tokens should get me access for as long as the application remains approved by the user… but that’s not enough, I want the cron to be completely independent from me…
This particular API implements the Authorization Code Grant flow. In plain English, this is how it’s meant to work:
- You should register your app and provide a redirection url. That’s where your users would land once they complete the registration process. They give you a
- You show a link to your user saying “Log in with TimeDoctor” that points to
- The user enters their credentials in the TimeDoctor site, and then choose to allow your application to access their data
- TimeDoctor’s site redirects the user to whatever you set as
redirect_uriwhen redirecting the user to them and appends
?code=<SOME_WEIRD_CODE>(the hostname needs to match with what you used when registering your app on the very first step)
- Once your server has the code, it should query
https://webapi.timedoctor.com/oauth/v2/token?client_id=<YOUR_CLIENT_ID>&client_secret=<YOUR_CLIENT_SECRET>&grant_type=authorization_code&redirect_uri=<REDIRECT_URI>&code=<RETURNED_CODE_FROM_POINT.4>which now will return the
access_token(that you need to access the API) and the
refresh_token(that you need to use when the
access_tokenexpires and you want a new one)
One of my goals is not to have a server. In order to accomplish that, I’m going to have PhantomJS tell me what’s the URL on step 4 and parse the code from it.
I originally set it so that my redirect url was
http://127.0.0.1:1234 but that didn’t work. For some (extremely weird) reason, if PhantomJS doesn’t find a server in the port you specify, it doesn’t change the page. So what I ended up doing was using their own server… I set up my TimeDoctor app to redirect to
https://webapi.timedoctor.com/oauth/v2/token with the code.
Requirements for this code to work:
- Have PhantomJS installed (running
npm -g install phantomjsif you have nodejs installed)
- Have the selenium package (running
pip install selenium)
- If you’re on a mac and installed nodejs with brew, you may need to do
sudo ln -s /usr/local/bin/node /usr/bin/node(thanks to this answer!)
Here is the extremely simple code
And if at any time you want to really see what PhantomJS is seeing, you can do
driver.save_screenshot('screen.png') and it creates an image for you… soooo cool!
Hope it helps someone! Oh, and I wouldn’t have been able to figure out how to use PhantomJS via selenium without this answer. If you’re interested in this particular project, you can take a look and clone the repo here.