Files
calendar_bot/my_project_name/caldav_handler.py

151 lines
5.5 KiB
Python

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)