Autocommit of file /home/julien/scripts/gcal-notify changed on host ares
[dotfiles/scripts.git] / gcal-notify
1 #!/usr/bin/python
2 """
3 Usage: gcal-notify [OPTION]
4
5   -h, --help        displays this help
6   -n, --new         create a new account in the default GNOME keyring
7   -d, --daemonize   check new events on a regular basis (default 10 minutes)
8
9 When called without option, gcal-notify will check the events once only.
10
11 Send a notification when an event with an alert occurs on the default Google Calendar.
12 Accounts information are saved within the default GNOME keyring.
13
14 Most code and idea from: http://julien.danjou.info/blog/2012/google-calendar-pynotify
15 """
16
17 import sys
18 import gtk
19 import datetime
20 import time
21 import getpass
22 import pynotify
23 import gdata.calendar.service
24 import gnomekeyring as gkey
25 import string
26 import getopt
27
28 gkey.get_default_keyring_sync()
29 pynotify.init(sys.argv[0])
30
31 def get_credentials():
32     """ Retrieve credentials from the default GNOME Keyring """
33     attrs = {"server": "google", "protocol": "googlecal"}
34     items = gkey.find_items_sync(gkey.ITEM_NETWORK_PASSWORD, attrs)
35     return items[0].attributes["user"], items[0].secret
36
37 def set_password():
38     """ Add new account into the default GNOME Keyring """
39     username = raw_input("Username: ")
40     password = getpass.getpass(prompt="Password: ")
41     print
42
43     attrs = {
44         "user": username,
45         "server": "google",
46         "protocol": "googlecal" ,
47     }
48     gkey.item_create_sync(gkey.get_default_keyring_sync(),
49             gkey.ITEM_NETWORK_PASSWORD, "Google", attrs, password, True)
50     
51     print ("User added.")
52
53 def daemonize():
54     """ Run a loop and check events every 10 minutes """
55     while True:
56         process()
57         time.sleep(600)
58
59
60 def process():
61     """ Retrieve events and display a notification """
62     # Then, we need to import gdata Calendar API and connect to the calendar.
63     calendar_service = gdata.calendar.service.CalendarService()
64     (calendar_service.email, calendar_service.password) = get_credentials()
65     calendar_service.ProgrammaticLogin()
66
67     # Request the events from the default calendar.
68     feed = calendar_service.GetCalendarEventFeed()
69
70     # Now we can iterate over feed and do various checks.
71     for event in feed.entry:
72         # If the event status is not confirmed, go to the next event.
73         if event.event_status.value != "CONFIRMED":
74             continue
75         # Now iterate over all the event dates (usually it has one)
76         for when in event.when:
77             # Parse start and end time
78             try:
79                 start_time = datetime.datetime.strptime(when.start_time.split(".")[0], "%Y-%m-%dT%H:%M:%S")
80                 end_time = datetime.datetime.strptime(when.end_time.split(".")[0], "%Y-%m-%dT%H:%M:%S")
81             except ValueError:
82                 # ValueError happens on parsing error. Parsing errors
83                 # usually happen for "all day" events since they have
84                 # not time, but we do not care about this events.
85                 continue
86             now = datetime.datetime.now()
87             # Check that the event hasn't already ended
88             if end_time > now:
89                 # Check each alert
90                 for reminder in when.reminder:
91                     # We handle only reminders with method "alert"
92                     # and whose start time minus the reminder delay has passed
93                     if reminder.method == "alert" \
94                             and start_time - datetime.timedelta(0, 60 * int(reminder.minutes)) < now:
95                         # Build the notification
96                         notification = pynotify.Notification(summary=event.title.text,
97                                 message="\n".join(filter(None, (event.content.text, "<a href='https://www.google.com/calendar/render'>Google Calendar</a>"))))
98                         # Set an icon from the GTK+ stock icons
99                         notification.set_icon_from_pixbuf(gtk.Label().render_icon(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_LARGE_TOOLBAR))
100                         notification.set_timeout(0)
101                         # Show the notification
102                         notification.show()
103
104 def main():
105     # parse command line options
106     try:
107         opts, args = getopt.getopt(sys.argv[1:], "hnd", ["help", "new", "daemonize"])
108     except getopt.error, msg:
109         print msg
110         print "for help use --help"
111         sys.exit(2)
112     # process options
113     for o, a in opts:
114         if o in ("-h", "--help"):
115             print __doc__
116             sys.exit(0)
117         elif o in ("-n", "--new"):
118             set_password()
119             sys.exit()
120         elif o in ("-d", "--daemonize"):
121             daemonize()
122     # no option, no argument
123     process()
124
125 if __name__ == "__main__":
126     main()