summaryrefslogtreecommitdiff
path: root/sublab_project/calendarium/tasks.py
diff options
context:
space:
mode:
Diffstat (limited to 'sublab_project/calendarium/tasks.py')
-rw-r--r--sublab_project/calendarium/tasks.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/sublab_project/calendarium/tasks.py b/sublab_project/calendarium/tasks.py
new file mode 100644
index 0000000..9174105
--- /dev/null
+++ b/sublab_project/calendarium/tasks.py
@@ -0,0 +1,82 @@
+"""Celery tasks.
+"""
+from datetime import datetime, timedelta
+from dateutil.relativedelta import relativedelta
+import urllib2
+
+from celery.task import PeriodicTask
+from django.conf import settings
+from dateutil.rrule import rrulestr
+import icalendar
+
+from models import Event
+
+
+class CalendariumImport(PeriodicTask):
+ """Periodic task for importing calendar events.
+ """
+ run_every = timedelta(hours=1)
+ ignore_result = True
+
+ def flush(self):
+ """Flushes all previously imported events.
+ """
+ Event.objects.filter(source=Event.SOURCE_IMPORT).delete()
+ self.logger.info('Flushed all previously imported events.')
+
+ def fetch_calendar(self):
+ """Fetches the calendar events and returns a icalendar.Calendar instance.
+ """
+ response = urllib2.urlopen(settings.CALENDARIUM_IMPORT_URL)
+ self.logger.info('Fetched calendar from %s' % settings.CALENDARIUM_IMPORT_URL)
+ return icalendar.Calendar.from_string(response.read())
+
+ def get_events(self, calendar, after, before):
+ """Yields all events in calendar as dictionary.
+
+ Only events after (including) after will be shown. Recurring events
+ til before (inclusively) will be shown.
+ """
+ for event in calendar.walk('vevent'):
+ event_fields = [
+ # dest, src, default
+ ('name', 'summary', 'unknown Event'),
+ ('description', 'description', ''),
+ ]
+ event_info = {}
+ for fieldinfo in event_fields:
+ try:
+ event_info[fieldinfo[0]] = str(event[fieldinfo[1]])
+ except KeyError:
+ event_info[fieldinfo[0]] = fieldinfo[2]
+ start = icalendar.vDatetime.from_ical(event['dtstart'].ical())
+ end = icalendar.vDatetime.from_ical(event['dtend'].ical())
+ if 'rrule' in event:
+ rrule = rrulestr(event['rrule'].ical(), dtstart=start)
+ duration = end - start
+ for occurence in rrule.between(after, before, True):
+ event_info['start'] = occurence
+ event_info['end'] = occurence + duration
+ yield event_info
+ else:
+ if start >= after:
+ event_info['start'] = start
+ event_info['end'] = end
+ yield event_info
+
+ def run(self, **kwargs):
+ """Imports all events.
+ """
+ self.logger = self.get_logger(**kwargs)
+ now = datetime.now()
+ after = now - relativedelta(days=1)
+ before = now + relativedelta(months=+2)
+ self.logger.info('Importing events from %s to %s' % (after, before))
+ try:
+ calendar = self.fetch_calendar()
+ self.flush()
+ for event_info in self.get_events(calendar, after, before):
+ event = Event.objects.create(**event_info)
+ self.logger.info('Added event "%s".' % event)
+ except urllib2.URLError, error:
+ self.logger.error(error)