2015년 1월 26일 월요일

Bash script to update a Beeminder Pomodoro goal

I sometimes use the Pomodoro technique to help me focus in 25-minute bursts with forced breaks of 5 minutes in between work blocks and longer extended breaks after 3~4 pomodoros. I thought it would be cool to write a script that would keep track of pomodoros as well as integrate with the Beeminder API, but then I realized that I could more easily use existing applications in the Linux ecosystem and glue them together with a bash script.

Ingredients

The Script





Usage

Both pystopwatch and xfce4-timer-plugin allow the user to launch an application when a timer completes its countdown. See screenshots below:



For pystopwatch, you access the alarm command dialog by right-clicking on the face of the timer after changing to Countdown Mode. To launch a cli script, I invoke my terminal program, terminator, with the -e option flag to make it run a specified command contained in double quotes (btw, pystopwatch asks that you add & to the end of any alarm commands so that they run in the background without locking the main program). You could simply specify sh ~/path/to/pomo2beeminder.sh to make pystopwatch run the script above.

For xfce4-timer-plugin, you must right-click on the timer icon, select Properties, and click edit on your timer to specify a command to run. Unlike pystopwatch, it is not necessary to append & at the end of your command invocation.

Careful readers will note that the script I am invoking through both timer apps is NOT pomo2beeminder.sh (although this will work fine). I created a separate timer-launched script that first calls mplayer to play a wav file and then executes pomo2beeminder.sh:


#!/bin/bash
# Script to be executed by pystopwatch or xfce4-timer-plugin
# when the timer for 1 pomodoro completely counts down

MUSIC=~/Music/zen_temple_bell-soundbible-com.wav

mplayer $MUSIC
sh ~/Documents/MyProjects/pomodoro/pomo2beeminder.sh

This way I can hear a sound effect when the timer completes after which the pomodoro script is executed.

Format for emails to the Beeminder bot

When sending emails to bot@beeminder.com how does it know which goal to update and how much to increment the graph? It parses this info from the subject line of the email, which must be in the format

username/goalName

The body of the email to the Beeminder bot must contain a line starting with a caret followed by a space and then a positive integer. The graph will be incremented by the integer value. Comments can also be added by placing them in between double quotes. Example:

^ 1 "sent by pomo2beeminder.sh"


smtp-cli parameters

The pomo2beeminder script uses smtp-cli to send emails through your webmail provider's smtp server. I use the Gmail smtp server, but other webmail services probably work, too.

Obviously you will have to change the values for the variables HOST (if you don't use Gmail), USER, FROM, TO and SUBJ. You should also create a separate smtp server password file named pass.txt that resides in the same path as the pomo2beeminder.sh script. It is good practice not to hardcode passwords in your scripts which might end up in VCS - git users out there could blacklist the password file from being tracked by adding it to .gitignore, for example. Within the script itself, the value of variable PW will be read from the separate file, pass.txt.

*Note: For those of you planning to use smtp-cli with gmail, you cannot use your regular webmail password to send mails through the Google smtp server -- please refer to a previous blog post of mine in which I explain how to generate an application-specific password for gmail which you can use with third-party apps.

Here's sample output from pomo2beeminder.sh

[archjun@arch pomodoro]$ ./pomo2beeminder.sh
Did you successfully complete your pomodoro?(y/n)
y
Connection from 192.168.0.9:42780 to 74.125.203.108:25
[220] 'mx.google.com ESMTP i3sm10596671pdf.39 - gsmtp'
> EHLO localhost
[250] 'mx.google.com at your service, [220.76.214.86]'
[250] 'SIZE 35882577'
[250] '8BITMIME'
[250] 'STARTTLS'
[250] 'ENHANCEDSTATUSCODES'
[250] 'PIPELINING'
[250] 'CHUNKING'
[250] 'SMTPUTF8'
Starting TLS...
> STARTTLS
[220] '2.0.0 Ready to start TLS'
Using cipher: ECDHE-RSA-AES128-SHA
Subject Name: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
Issuer  Name: /C=US/O=Google Inc/CN=Google Internet Authority G2
> EHLO localhost
[250] 'mx.google.com at your service, [220.76.214.86]'
[250] 'SIZE 35882577'
[250] '8BITMIME'
[250] 'AUTH LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN'
[250] 'ENHANCEDSTATUSCODES'
[250] 'PIPELINING'
[250] 'CHUNKING'
[250] 'SMTPUTF8'
AUTH method (LOGIN PLAIN XOAUTH XOAUTH2 PLAIN-CLIENTTOKEN): using LOGIN
> AUTH LOGIN
[334] '....' (redacted)
> .......... (redacted)
[334] '....' (redacted)
> .....
[235] '2.7.0 Accepted'
Authentication of gojun077@gmail.com@smtp.gmail.com succeeded
> MAIL FROM:
[250] '2.1.0 OK i3sm10596671pdf.39 - gsmtp'
> RCPT TO:
[250] '2.1.5 OK i3sm10596671pdf.39 - gsmtp'
> DATA
[354] ' Go ahead i3sm10596671pdf.39 - gsmtp'
[250] '2.0.0 OK 1422308096 i3sm10596671pdf.39 - gsmtp'
> QUIT
[221] '2.0.0 closing connection i3sm10596671pdf.39 - gsmtp'

[archjun@arch pomodoro]$ ./pomo2beeminder.sh
Did you successfully complete your pomodoro?(y/n)
a
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
a
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
;Please answer y or n
Did you successfully complete your pomodoro?(y/n)
q
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
e
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
r
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
ty
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
1111
Please answer y or n
Did you successfully complete your pomodoro?(y/n)
n
Concentrate harder next time!



If you have any comments or suggestions about the script, please let me know!