import datetime import dateutil.parser as dateparser import ics import pytz import requests from rcal.db import Session from rcal.model import Calendar, Entry def update_event_data(db_event, ical_event): db_event.name = ical_event.name db_event.location = ical_event.location db_event.begin_date = ical_event.begin.datetime db_event.end_date = ical_event.end.datetime db_event.all_day = ( (db_event.end_date - db_event.begin_date).seconds % 86400 == 0 ) and ( db_event.begin_date.time() == datetime.time.min) if db_event.all_day: db_event.end_date = db_event.end_date - datetime.timedelta(days=1) return db_event def update_event(db_event, ical_event): update_event_data(db_event, ical_event) def add_event(event, calendar, session): entry = Entry() entry.uid = event.uid entry.calendar = calendar entry = update_event_data(entry, event) session.add(entry) def remove_event(event, session): session.delete(event) def get_last_modification_time(event): for unused in event.__dict__['_unused']: if unused.name == 'LAST-MODIFIED': return dateparser.parse(unused.value) return None def fetch_calendar(calendar, session): cal_data = requests.get(calendar.url) cal_object = ics.Calendar(cal_data.content.decode(cal_data.encoding)) cal_events = {e.uid: e for e in cal_object.events} db_events = {e.uid: e for e in calendar.entries} new_events = [e for u, e in cal_events.iteritems() if u not in db_events.keys()] old_events = [e for u, e in db_events.iteritems() if u not in cal_events.keys()] mod_events = [{'ics': cal_events[u], 'db': e} for u, e in db_events.iteritems() if u in cal_events.keys()] for event in mod_events: modified_date = get_last_modification_time(event['ics']) if not modified_date or \ not calendar.last_updated or \ modified_date > calendar.last_updated.replace(tzinfo=pytz.UTC): print 'Updating event %s' % event['db'].uid update_event(event['db'], event['ics']) for event in new_events: print 'Adding event %s' % event.uid add_event(event, calendar, session) for event in old_events: print 'Removing event %s' % event.uid remove_event(event, session) calendar.last_updated = datetime.datetime.now() def main(): session = Session.create() calendars = session.query(Calendar).all() for calendar in calendars: # print 'Fetching %s' % calendar.url fetch_calendar(calendar, session) session.commit() if __name__ == '__main__': main()