import sys import time import logging import collections from os.path import exists import json import dateutil.rrule as rrule import caldav import pytz from icalendar import Calendar, Event import datetime import caldav class CaldavHandler: def get_config(self, path): with open(path) as f: return json.load(f) def __init__(self): self._config_path = "./config.json" self._event_reminder_path = "./event_reminders.json" if not exists(self._config_path): print("No config file found. Aborting.") self._config = self.get_config(self._config_path) self._event_reminder_config = self.get_config(self._event_reminder_path) self._caldavclient = caldav.DAVClient(self._config["caldav"]["url"], username=self._config["caldav"]["username"], password=self._config["caldav"]["password"]) def get_event_map(self, events, time_span): result = {} for event in events: event.load() e = event.instance.vevent list_of_occurences = [] if e.getChildValue('rrule') == None: list_of_occurences.append(e.getChildValue('dtstart')) else: #recurring events only return with the date of the first recurring event ever created #we have to use rrule manually to expand the dates to display them correctly rule = rrule.rrulestr(e.getChildValue('rrule'), dtstart=e.getChildValue('dtstart')) list_of_occurences = rule.between(datetime.datetime.now(datetime.timezone.utc), datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=time_span), inc=True) for datetime_of_event in list_of_occurences: datestr = datetime_of_event.strftime("%x") eventstr = str( "(" + e.dtstart.value.strftime("%H:%M") + " - " + e.dtend.value.strftime("%H:%M") + ") " + e.summary.value) if datestr in result: result[datestr].append(eventstr) else: result[datestr] = [ eventstr ] #sort start times for key in result: result[key].sort() od = collections.OrderedDict(sorted(result.items())) return od def event_map_to_string(self, event_map): result = "" for k, v in event_map.items(): dt_string = k format = "%x" dt_object = datetime.datetime.strptime(dt_string, format) result += "##### " + dt_object.strftime("%A, %d. of %B") + ":\n" for event in v: result += "* " + event + "\n" return result def event_to_string(self, event): event.load() e = event.instance.vevent datestr = e.dtstart.value.strftime("%X") return str( "(" + e.dtstart.value.strftime("%a, %-d. %b - %H:%M") + " - " + e.dtend.value.strftime("%H:%M") + ") " + e.summary.value) def get_events(self, start_time, end_time): cal = self._caldavclient.principal().calendars() for ca in cal: events = ca.date_search(start=start_time, end=end_time, expand=True) return events def send_events(self, events, time_span): return self.event_map_to_string(self.get_event_map(events, time_span)) def print_month(self): events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=30)) return self.send_events(events, 30) def print_week(self): events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=7)) return self.send_events(events, 7) def time_to_remind(self, event_name, days_to_remind): events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=days_to_remind + 1)) datetime_to_remind = datetime.date.today() + datetime.timedelta(days=days_to_remind) datetime_to_remind = datetime_to_remind.strftime("%x") print(datetime_to_remind) #create a map where each day is a key and list of events are the values event_map = self.get_event_map(events, days_to_remind + 1) print(datetime_to_remind) print(event_map) if datetime_to_remind not in event_map: return False for real_event_name in event_map[datetime_to_remind]: print("real_ev_name:") print(real_event_name) print("ev_name") print(event_name) if event_name in real_event_name: print("found event!") return True return False def send_reminders(self): print(self._event_reminder_config) result = [] for event_name in self._event_reminder_config: print("iterating event configs") print(event_name) days = self._event_reminder_config[event_name]["days"] print(days) if not self.time_to_remind(event_name, days): continue reminder_message = self._event_reminder_config[event_name]["message"] result.append(reminder_message) print(reminder_message) return result def print_today(self): events = self.get_events(datetime.date.today(), datetime.date.today() + datetime.timedelta(days=1)) #self.send_reminders() return self.send_events(events, 1)