Tag Archives: gcalcli

gcalcli_agenda.py – Google Calendar agenda in conky

Conky is a wonderful application for Linux users. All sorts of valuable information is printed right onto your wallpaper in almost any manner you want! I usually like to see my calendar agenda for the month in conky. However making conky interface with google calendar is way above my skill set… And this is why I love linux. 9 times out of 10 you will be able to find a program that does exactly what you want.

Enter gcalcli! Its a nifty application that allows you to access google calendar from the command line. It can create/delete tasks, produce reminders and a do a host of other stuff. All we are going to use it for is to get our agenda for the month. The version in Ubuntu repos is out of date so I’ll be using the latest version right from the source which supports OAuth. You’ll need to install some dependencies before you can run the program which can be obtained by reading the help file.

The first time you run the command in the terminal ([path to gcalcli]/gcalcli list), follow the instructions. You’ll authenticate with google and then you’re good to go. Now the program has a command line switch that allows you to display the output in colors in a syntax used in conky. But playing with it, I found it to have limited choices of color and the most outrageous default settings. The output also wasn’t properly aligned in conky.

So I decided to write a little program that took plain output from the program, colored the output according to my tastes and aligned it properly.

#!/usr/bin/python

# gcalcli_agenda.py

version = "3.0.1"

from datetime import date, timedelta, datetime
import subprocess
import textwrap
import re
import heapq

pattern_string = '(1[012]|[1-9]):[0-5][0-9](\\s)?(?i)(am|pm)'
pattern = re.compile(pattern_string)

def join_time(lst):
	mod_lst = []
	for number, item in enumerate(lst):
		if re.search(pattern, item):
			mod_lst.append(item + ' ' + lst[number+1])
			del lst[number+1]
		else:
			mod_lst.append(item)
	return mod_lst

def get_first_day(dt, d_years=0, d_months=0):
	# d_years, d_months are "deltas" to apply to dt
	y, m = dt.year + d_years, dt.month + d_months
	a, m = divmod(m-1, 12)
	return date(y+a, m+1, 1)

def get_last_day(dt):
	return get_first_day(dt, 0, 1) + timedelta(-1)

d = date.today()
e = datetime.today()
start_first = get_first_day(d).strftime('%Y-%m-%d') + 'T00:00'
start = d.strftime('%m/%d/%Y')
end = get_last_day(d).strftime('%Y-%m-%d') + 'T23:59'
today = d.strftime('%a %b %d')

try:
	proc = subprocess.check_output('/home/saad/Downloads/gcalcli-master/gcalcli --nocolor agenda %s %s' %(start_first, end), shell=True)

except subprocess.CalledProcessError:
	print 'There seems to be a problem...'

lst = proc.split('\n')
lst = filter(None, lst)
lst = [item.split('  ') for item in lst]
lst = [item for sublist in lst for item in sublist]
lst = filter(None, lst)

date_word = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')

dct = {}    

for item in lst:
    if any(item.startswith(d) for d in date_word):
        dct[item] = []
        saveItem = item
    else:
        dct[saveItem].append(item.strip())

def parse_date(datestring):
    return datetime.strptime(datestring, "%a %b %d")

deltas = []
val_len = []

for key in dct:
	val_len.append(len(''.join(item for item in dct[key])))
	
counter = 0
for eachLen in val_len:
	if eachLen > 37:
		counter = counter + 2
	else:
		counter = counter + 1

if counter > 5:
	n = counter - 5
	
	for key in dct:
		deltas.append(e - datetime.strptime(key, '%a %b %d'))
		
	for key in sorted(dct, key=parse_date):
		tdelta = e - datetime.strptime(key, '%a %b %d')
		if tdelta in heapq.nlargest(n, deltas):
			pass
		else:
			if key == today:
				value = dct[key]
				val1 = '${color green}' + key + '$color: ' 
				mod_val = join_time(value) 
				val2 = textwrap.wrap(', '.join(item for item in mod_val), 37)
				print val1 + '${color 40E0D0}' + '$color\n            ${color 40E0D0}'.join(item for item in val2) + '$color'
			else:
				value = dct[key]
				mod_val = join_time(value)
				output = key + ': ' + ', '.join(item for item in mod_val)
				print '\n            '.join(textwrap.wrap(output, 49))

else:	
	for key in sorted(dct, key=parse_date):
		if key == today:
			value = dct[key]
			val1 = '${color green}' + key + '$color: ' 
			mod_val = join_time(value) 
			val2 = textwrap.wrap(', '.join(item for item in mod_val), 37)
			print val1 + '${color 40E0D0}' + '$color\n            ${color 40E0D0}'.join(item for item in val2) + '$color'
		else:
			value = dct[key]
			mod_val = join_time(value)
			output = key + ': ' + ', '.join(item for item in mod_val)
			print '\n            '.join(textwrap.wrap(output, 49))

The program takes your agenda list for the current month and checks for any item on the current date, colorizes that item and outputs to conky with agenda list properly aligned.

conky Calendar Events

All you have to do is replace the path to gcalcli with location of the script in your computer, change the colors to your liking and make the program executable. Then put this line in your .conkyrc file: ${execpi 3600 [path to script]/gcalcli_agenda.py} and you’re good to go.