1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
"""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 calendarium.models import Event
class CalendariumImport(PeriodicTask):
"""Periodic task for importing calendar events.
"""
run_every = timedelta(hours=1)
ignore_result = True
def flush(self, logger):
"""Flushes all previously imported events.
"""
Event.objects.filter(source=Event.SOURCE_IMPORT).delete()
logger.debug('Flushed all previously imported events.')
def fetch_calendar(self, logger):
"""Fetches the calendar events and returns a icalendar.Calendar instance.
"""
response = urllib2.urlopen(settings.CALENDARIUM_IMPORT_URL)
logger.debug('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]] = event[fieldinfo[1]].format().encode("utf-8")
event_info[fieldinfo[0]] = event_info[fieldinfo[0]].decode("string-escape")
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.
"""
logger = self.get_logger(**kwargs)
event_count = 0
now = datetime.now()
after = now - relativedelta(days=1)
before = now + relativedelta(months=+2)
logger.info('Importing events from %s to %s' % (after, before))
try:
calendar = self.fetch_calendar(logger)
self.flush(logger)
for event_info in self.get_events(calendar, after, before):
event = Event.objects.create(**event_info)
event_count += 1
logger.debug('Added event "%s".' % event)
except urllib2.URLError, error:
logger.error(error)
return 'Imported %d events.' % event_count
|