from oauth2client.client import AccessTokenRefreshError import constants import datetime import file_writer import gdata import globals import os import renderer import time class gcal_renderer(renderer.debuggable_abstaining_renderer): """A renderer to fetch upcoming events from www.google.com/calendar""" calendar_whitelist = frozenset([ 'Alex\'s calendar', 'Family', 'Holidays in United States', 'Lynn Gasch', 'Lynn\'s Work', 'scott.gasch@gmail.com', 'Scott Gasch External - Misc', 'Birthdays', # <-- from g+ contacts ]) class comparable_event(object): """A helper class to sort events.""" def __init__(self, start_time, end_time, summary, calendar): if start_time is None: assert(end_time is None) self.start_time = start_time self.end_time = end_time self.summary = summary self.calendar = calendar def __lt__(self, that): if self.start_time is None and that.start_time is None: return self.summary < that.summary if self.start_time is None or that.start_time is None: return self.start_time is None return (self.start_time, self.end_time, self.summary, self.calendar) < (that.start_time, that.end_time, that.summary, that.calendar) def __str__(self): return '[%s] %s' % (self.timestamp(), self.friendly_name()) def friendly_name(self): name = self.summary name = name.replace("countdown:", "") return "%s" % name def timestamp(self): if self.start_time is None: return "None" elif (self.start_time.hour == 0): return datetime.datetime.strftime(self.start_time, '%a %b %d %Y') else: return datetime.datetime.strftime(self.start_time, '%a %b %d %Y %H:%M%p') def __init__(self, name_to_timeout_dict, oauth): super(gcal_renderer, self).__init__(name_to_timeout_dict, True) self.oauth = oauth self.client = self.oauth.calendar_service() self.sortable_events = [] self.countdown_events = [] def debug_prefix(self): return "gcal" def periodic_render(self, key): self.debug_print('called for "%s"' % key) if (key == "Render Upcoming Events"): return self.render_upcoming_events() elif (key == "Look For Triggered Events"): return self.look_for_triggered_events() else: raise error('Unexpected operation') def render_upcoming_events(self): page_token = None def format_datetime(x): return datetime.datetime.strftime(x, '%Y-%m-%dT%H:%M:%SZ') time_min = datetime.datetime.now() time_max = time_min + datetime.timedelta(95) time_min, time_max = list(map(format_datetime, (time_min, time_max))) self.debug_print("time_min is %s" % time_min) self.debug_print("time_max is %s" % time_max) # Writes 2 files: # + "upcoming events", # + a countdown timer for a subser of events, f = file_writer.file_writer('gcal_3_none.html') f.write('

Upcoming Calendar Events:


\n') f.write('
\n') g = file_writer.file_writer('countdown_3_7200.html') g.write('

Countdowns:


\n""" % (event.timestamp(), event.friendly_name())) f.write('
%s %s
\n') f.close() self.countdown_events.sort() upcoming_countdown_events = self.countdown_events[:12] now = datetime.datetime.now() count = 0 timestamps = { } for event in upcoming_countdown_events: eventstamp = event.start_time delta = eventstamp - now name = event.friendly_name() x = int(delta.total_seconds()) if x > 0: identifier = "id%d" % count days = divmod(x, constants.seconds_per_day) hours = divmod(days[1], constants.seconds_per_hour) minutes = divmod(hours[1], constants.seconds_per_minute) g.write('
  • %d days, %02d:%02d until %s
  • \n' % (identifier, days[0], hours[0], minutes[0], name)) timestamps[identifier] = time.mktime(eventstamp.timetuple()) count += 1 self.debug_print("countdown to %s is %dd %dh %dm" % ( name, days[0], hours[0], minutes[0])) g.write('') g.write('"""); g.close() return True except (gdata.service.RequestError, AccessTokenRefreshError): print("********* TRYING TO REFRESH GCAL CLIENT *********") self.oauth.refresh_token() self.client = self.oauth.calendar_service() return False except: raise def look_for_triggered_events(self): f = file_writer.file_writer(constants.gcal_imminent_pagename) f.write('

    Imminent Upcoming Calendar Events:

    \n
    \n') f.write('
    \n') now = datetime.datetime.now() count = 0 for event in self.sortable_events: eventstamp = event.start_time delta = eventstamp - now x = int(delta.total_seconds()) if x > 0 and x <= constants.seconds_per_minute * 3: days = divmod(x, constants.seconds_per_day) hours = divmod(days[1], constants.seconds_per_hour) minutes = divmod(hours[1], constants.seconds_per_minute) eventstamp = event.start_time name = event.friendly_name() calendar = event.calendar f.write("
  • %s (%s) upcoming in %d minutes.\n" % (name, calendar, minutes[0])) count += 1 f.write("
  • ") f.close() if count > 0: globals.put("gcal_triggered", True) else: globals.put("gcal_triggered", False) return True