Command-Line Cloud: gcalcli
If you follow my columns in Linux Journal, you probably are aware that I'm a big fan of the command line. When it comes to getting things done efficiently, most of the time the command line can't be beat. This has led me to integrating services like instant messaging and Twitter into BitlBee so I can use them with my command-line IRC client Irssi (both written up in previous LJ issues).
You probably also are aware that unlike some other Linux Journal writers out there (I'm looking at you Bill Childers), I'm a bit more skeptical of cloud services. That said, in this day and age, it seems you can't escape cloud services, so what's a guy like me to do? Well, I've just figured out how to use cloud services from the comfort of my green-on-black terminal. So, I figured it might be interesting to write a few articles describing how you can access various cloud services from the command line.
The first cloud service I thought I'd cover also is one of the most prevalent: Google Calendar. Although a lot of calendaring options exist, in a corporate environment, you often are talking about either Exchange (usually larger, older-school companies) or Google Apps (usually smaller startups). Google Calendar can be pretty convenient as a shared calendar, particularly if you are issued an Android device at work. Plus, like with all major cloud services, you can collaborate and share your data with other people (like the NSA). My main problem with Google Calendar always has been having to open up a browser every time I want to view my calendar. Although I'm sure some people are logged in to the Gmail Web interface all day and get meeting notifications that way, I'm not. Because I'm usually glued to my terminal window, I often don't see those reminders. After missing a few meetings, I decided I needed to find some way to put meeting notifications inside my terminal.
The CLI to Google Calendar that worked for me was gcalcli. It provides a command-line interface to view your calendar in various formats and also lets you add events—all from the command line.
Install gcalcligcalcli itself was not packaged for my distribution, so installation took me a few extra steps. First, I cloned the project's git repository into a local directory named src that I use to keep track of source code (feel free to replace this with the directory you use for the same purpose). Then, I created a symlink to the included script so I could start identifying what Python libraries I'd need:
$ cd ~/src/
$ git clone https://github.com/insanum/gcalcli.git
$ sudo ln -s ~/src/gcalcli/gcalcli /usr/local/bin/gcalcli
At this point, I tried to launch the application but noticed I was missing a few required Python libraries, such as gflags, dateutil, httplib2 and google-api-python-client. The first three had Debian packages, so I was able to install them with:
$ sudo apt-get install python-gflags python-dateutil
↪python-httplib2
The final Python library wasn't packaged in Debian. For better or worse, it seems just about every modern scripting language has its own implementation of Perl's CPAN, so I fell back to using Python's pip (which I first had to install):
$ sudo apt-get install python-pip
$ sudo pip install --upgrade google-api-python-client
Initial Setup
With all of the libraries in place, you are ready to set up gcalcli to use your Google account. The first time gcalcli is run, it will set up your account, but if you are not running it from your local machine, you will want to add an extra argument the first time you launch it so it can provide you with a URL to load locally to authorize gcalcli:
$ gcalcli agenda --noauth_local_webserver
Once it's set up, you can see your current calendar agenda with the
agenda
command (the events have been changed to protect the innocent):
$ gcalcli agenda
Mon Jul 15 9:15am Space out and stare at screen
10:00am Meeting with the Bobs
11:00am Remodel Cubical Wall
11:45am Lunch at Flinger's
1:00pm Meeting with Michael
I've found the agenda
output to be the most useful for
seeing what's on my plate
for the day; however, you also can use calw
and
calm
to output ASCII-art-style weekly and monthly calendars, respectively (Figure 1).
Figure 1. gcalcli Screenshot from the Official Project Page
Meeting Notifications in ScreenHaving access to my calendar from the command line is handy, but it still doesn't quite solve my problem of getting notifications so I don't miss an important meeting. I'm sure many people simply rely on the pop-up notification in their browsers, but I usually am not looking at my browser, and when I am, I'm not logged in to Gmail. I am, however, almost always looking at a screen session, so I found the best approach for me was to put notifications there.
I wrote about how to set up screen notifications in my February 2011 Hack and / column, so I recommend reading that column if you haven't set up your hardstatus line yet. Because notifications in screen are simply scripts that output short lines of text, what I want to do is tell gcalcli to display the next meeting in my agenda today that hasn't yet started, or if there are no more meetings today, to display nothing. That way, I can see at a glance what meeting is next.
The first step is to create a basic shell script in my local ~/bin/ directory called gagenda that calls gcalcli with extra arguments and then parses the results:
$ gcalcli --nocolor --nostarted agenda "`date`" 11:59pm |
↪grep -v 'No Events' | head -2 | tail -1 | grep -v '^$'
With this long one-liner, I tell gcalcli to show me all of the events
on my agenda that haven't started (--nostarted
)
between now ("`date`"
)
and 11:59pm. Then if there are no events, I grep that out so I get empty
output. If there are results, I use head and tail to pull out the line I
want. Finally, if the line is empty I also grep that out. The end result
is a single line of output suitable for screen.
Of course, I didn't want to stop there. What I wanted was for regular events to show up in white on my output, but then as the meeting got closer, I thought it would be nice if it turned to yellow and then finally to red. Also, when commands in your screen hardstatus line take a long time to run, the whole screen session can stall, so my solution was to have my gagenda script redirect the output to a few temporary files. The key to having a status appear to change colors is to have different backtick commands show up in the same location, each assigned its own color. Then as long as you make sure that only one of the commands will display output at any time, you get the illusion that you have only one status that changes color. Here is the resulting gagenda shell script to accomplish that:
#!/bin/bash
# first look for urgent events occurring
# in the next five minutes
gcalcli --nocolor --nostarted agenda "`date`" "`date -d
↪'now + 5 minutes'`" | grep -v 'No Events' | head -2 |
↪tail -1 | grep -v '^$' > /tmp/gagenda-urgent
# if there are no urgent events, look for warning
# events in the next 10 minutes
if [ ! -s /tmp/gagenda-urgent ]; then
gcalcli --nocolor --nostarted agenda "`date`" "`date -d
↪'now + 10 minutes'`" | grep -v 'No Events' | head -2 |
↪tail -1 | grep -v '^$' > /tmp/gagenda-warning
# if there are no warning events, just grab the next
# event for the day
if [ ! -s /tmp/gagenda-warning ]; then
gcalcli --nocolor --nostarted agenda "`date`" 11:59pm |
↪grep -v 'No Events' | head -2 | tail -1 |
↪grep -v '^$' > /tmp/gagenda
else
cat /dev/null > /tmp/gagenda
fi
else
cat /dev/null > /tmp/gagenda-warning
cat /dev/null > /tmp/gagenda
fi
Now I edited my local user's crontab with crontab -e
to add gagenda:
* * * * * /home/greenfly/bin/gagenda
To configure screen, I updated my .screenrc with three new backtick commands that just cat the output of the temporary files:
backtick 111 37 37 cat /tmp/gagenda
backtick 112 37 37 cat /tmp/gagenda-warning
backtick 113 37 37 cat /tmp/gagenda-urgent
And finally, I referenced those backtick commands with the appropriate colors in my hardstatus line:
hardstatus string '%{= w}%Y-%m-%d %c%{= w}|%{= w}%111`%{+b
↪y}%112`%{+b r}%113`%{-}%{= w}|%= |%{+b g}%108`%{-}|%{+b
↪b}%105`%{-}|%{= y}%107`%{= w}'
The relevant section of the hardstatus line for these commands is:
|%{= w}%111`%{+b y}%112`%{+b r}%113`%{-}%{= w}|
Once I reload my .screenrc file, Figure 2 shows that I have an urgent meeting in a few minutes.
Figure 2. Urgent Meeting
In this article, I just touched on using gcalcli to access your agenda from the command line, but in my next column, I'll expand on the topic to talk about how to add new events and do even more with your Google Calendar without having to leave your terminal.