""" .. moduleauthor:: Fabio Manganiello """ import dateutil.parser import importlib from abc import ABCMeta, abstractmethod from platypush.plugins import Plugin, action class CalendarInterface: __metaclass__ = ABCMeta @abstractmethod def get_upcoming_events(self, max_results=10): raise NotImplementedError() class CalendarPlugin(Plugin, CalendarInterface): """ The CalendarPlugin allows you to keep track of multiple calendars (Google or iCal URLs) and get joined events from all of them. Requires: * **dateutil** (``pip install python-dateutil``) """ def __init__(self, calendars=[], *args, **kwargs): """ :param calendars: List of calendars to be queried. Supported types so far: Google Calendar and iCal URLs. :type calendars: list Example format:: calendars = [ { "type": "platypush.plugins.google.calendar.GoogleCalendarPlugin" }, { "type": "platypush.plugins.calendar.ical.IcalCalendarPlugin", "url": "https://www.facebook.com/ical/u.php?uid=USER_ID&key=FB_KEY" }, ... ] """ super().__init__(*args, **kwargs) self.calendars = [] for calendar in calendars: if 'type' not in calendar: self.logger.warning("Invalid calendar with no type specified: {}".format(calendar)) continue cal_type = calendar.pop('type') module_name = '.'.join(cal_type.split('.')[:-1]) class_name = cal_type.split('.')[-1] module = importlib.import_module(module_name) self.calendars.append(getattr(module, class_name)(**calendar)) @action def get_upcoming_events(self, max_results=10): """ Get a list of upcoming events merging all the available calendars. :param max_results: Maximum number of results to be returned (default: 10) :type max_results: int :returns: platypush.message.Response -- Response object with the list of events in the Google calendar API format. Example:: output = [ { "id": "123456abcdef", "kind": "calendar#event", "status": "confirmed", "htmlLink": "...", "created": "2018-06-01T01:23:45.000Z", "updated": "2018-06-01T01:23:45.000Z", "creator": { "email": "...", "displayName": "...", "self": true }, "organizer" { "email": "...", "displayName": "...", "self": true }, "start": { "dateTime": "2018-06-02T10:00:00.000Z", }, "end": { "dateTime": "2018-06-02T12:00:00.000Z", }, }, ... ] """ events = [] for calendar in self.calendars: cal_events = calendar.get_upcoming_events().output or [] events.extend(cal_events) events = sorted(events, key=lambda event: dateutil.parser.parse( event['start']['dateTime'] if 'dateTime' in event['start'] else event['start']['date'] + 'T00:00:00+00:00' ))[:max_results] return events # vim:sw=4:ts=4:et: