#!usr/bin/env/python """ Add Birthdays to Your Google Calendar Greg Pinero, Fall 2006 Find all contacts in Gmail contacts with birthday in note field, try to get birthdate and then create a repeating event in Google Calendar for that person (If it doesn't already exist). You'll want to run this on a scheduled basis for adding or editing contacts. Just put a line in each contact like: Birthday:mm/dd/yyyy (But I do try to be flexible in the format so don't fear if you're off a little) """ import re import datetime import time import cal #http://code.google.com/p/pygooglecalendar/ import libgmail #http://libgmail.sourceforge.net/ from dateutil.parser import parse #http://labix.org/python-dateutil, sWWEET! #----------------------------------------------------------------------------- #USER SETTINGS: gmail_userid="username@gmail.com" ##<- Replace with yours! gmail_pw="password" ##<- Replace with yours! BIRTHDAY_EUPHEMISMS=['birthday','birthdate','dob'] REMINDER_MINUTES=3*24*60 #3 days for me NUM_YEARS_AHEAD=10 #how many years ahead to add birthday events TIME_ZONE_OFFSET=-4 #EDT? Use http://www.isc.tamu.edu/~astro/jupiter/offset.html to find yours DATE_PATTERN=r'(\d{1,4}[-/\\. ]{1,4}\d{1,2})([-/\\. ]{1,3}\d{1,4}){0,1}' DEEP_SLEEP_EVERY=5 #sleep for 15 seconds every this many contacts processed DEEP_SLEEP_SECONDS=20 #how long to enter deep sleep #----------------------------------------------------------------------------- reDATE_PATTERN=re.compile(DATE_PATTERN) CAL=None def calendar_auth(): global CAL if not CAL: print "Logging into google" a = cal.googCal() a.time_zone_offset=TIME_ZONE_OFFSET a.getAuth(gmail_userid,gmail_pw) CAL=a return CAL def add_birthday_to_google_calendar(title,date_time,desc): """ """ a=calendar_auth() ty=datetime.date.today().year for year in range(ty,NUM_YEARS_AHEAD+ty,1): print start=datetime.datetime(year,date_time.month,date_time.day) start_search=datetime.datetime(year,date_time.month,date_time.day,0,0,0) end_search=datetime.datetime(year,date_time.month,date_time.day,23,59,59) #time.sleep(1) #This makes google throttle me worse?? existing_birthday_on_this_date=a.query('birthday',start_search,end_search) if existing_birthday_on_this_date: alert="""Found %s events on %s with "birthday" in title. Since I am super fraid of making mistakes, please add %s manually if you want it.""" % (len(existing_birthday_on_this_date),start,title) print alert else: print 'Adding Event',title.title(),desc,start a.login("%s's Birthday" % title.title(),desc,gmail_userid,gmail_userid,'here',start=start,end='',all_day_event=True,reminder_min_before=REMINDER_MINUTES) def parse_out_birthday(contact_text): """ We are looking for the line in the text that contains birthday. We then look for the first date anywhere in that line past the end of birthday. (Just trying to be super flexible with this)""" for line in contact_text.split('\n'): be_found=[be for be in BIRTHDAY_EUPHEMISMS if be.upper().strip() in line.upper()] if be_found: be_found=be_found[0].upper().strip() text_to_examine=line[line.upper().index(be_found)+len(be_found):] #find date part potential_dates=reDATE_PATTERN.findall(text_to_examine) if potential_dates: date_to_parse=''.join(potential_dates[0]) #comes in a groups else: break print ' date to parse is',date_to_parse try: birthdatetime=parse(date_to_parse) except ValueError,ErrMsg: print ' WARNING: Could not get date out of','"',line,'"',ErrMsg return 0 else: return birthdatetime print ' WARNING: No date signal found in','"',contact_text,'"' return 0 def get_info_for_birthdays(): """""" birthday_name_datetime_extra_info_pairs=[] print 'Retrieving Gmail Contact info...' ga=libgmail.GmailAccount(gmail_userid,gmail_pw) ga.login() contacts=ga.getContacts().getAllContacts() #so we just get list print '\tGot %s contacts' % len(contacts) for contact in contacts: bdate=parse_out_birthday(contact.notes) if bdate: birthday_name_datetime_extra_info_pairs.append([contact.name,bdate,contact.notes]) print 'found',len(birthday_name_datetime_extra_info_pairs),'Contacts with valid birthdays.' return birthday_name_datetime_extra_info_pairs def main(): birthday_name_datetime_extra_info_pairs=get_info_for_birthdays() count_for_deep_sleep=1 for birthday_name_datetime_extra_info in birthday_name_datetime_extra_info_pairs: if count_for_deep_sleep%DEEP_SLEEP_EVERY==0: print 'Deep sleeping (%s seconds) for benefit of Google' % DEEP_SLEEP_SECONDS time.sleep(DEEP_SLEEP_SECONDS) add_birthday_to_google_calendar(*birthday_name_datetime_extra_info) count_for_deep_sleep+=1 if __name__=='__main__': main()