summaryrefslogtreecommitdiff
path: root/scripts/get_calendar.py
blob: 3e0f8e3c7461e73a2c223f246591fdb009024575 (plain)
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
87
from datetime import datetime, timedelta, time
from dateutil.relativedelta import relativedelta
import urllib2

import json
import logging
import sys
import copy
import os

from dateutil.rrule import rrulestr
import icalendar

def fetch_calendar(logger):
    """Fetches the calendar events and returns a icalendar.Calendar instance.
    """
    response = urllib2.urlopen(CALENDARIUM_IMPORT_URL)
    logger.debug('Fetched calendar from %s' % CALENDARIUM_IMPORT_URL)
    return icalendar.Calendar.from_ical(response.read())

def get_events(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.vDDDTypes.from_ical(event['dtstart'].to_ical())
        if 'dtend' in event:
            end = icalendar.vDDDTypes.from_ical(event['dtend'].to_ical())
        else:
            end = start + icalendar.vDDDTypes.from_ical(event['duration'].to_ical())
        if not isinstance(start, datetime):
            start = datetime.combine(start, time())
        if not isinstance(end, datetime):
            end = datetime.combine(end, time())

        if 'rrule' in event:
            rrule = rrulestr(event['rrule'].to_ical(), dtstart=start)
            duration = end - start
            for occurence in rrule.between(after, before, True):
                event_info['start'] = occurence
                event_info['end'] = occurence + duration
                yield copy.deepcopy(event_info)
        else:
            if start >= after:
                event_info['start'] = start
                event_info['end'] = end
                yield event_info

class DatetimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return json.JSONEncoder.default(self,obj)

#CALENDARIUM_IMPORT_URL = 'https://sublab.org:5232/calendars/events'
CALENDARIUM_IMPORT_URL = 'https://posteo.de/calendars/ics/ruku1tibpa2b2evfwsxrbvwcy2n60j9g'
if __name__ == '__main__':
    logging.basicConfig(stream=sys.stderr, level=logging.ERROR)
    logger = logging.getLogger('calendar_feed')
    calendar = fetch_calendar(logger)
    now = datetime.now()
    after = now - relativedelta(days=1)
    before = now + relativedelta(months=+1)

    events = []
    for event in get_events(calendar, after, before):
        event['start'] = event['start'].isoformat()
        event['end'] = event['end'].isoformat()
        events.append(event)
    destination = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../template/calendar.json')
    with open(destination + '.new', 'w') as dfile:
        dfile.write(json.dumps(events, indent=4))
    os.rename(destination + '.new', destination)