Beispiele

Ausprobiert mit Python 3.5, benötigt Bibliothek iCalendar und Bibliothek caldav

Funktioniert aber leider nur in sehr einfachen Fällen - Sonderzeichen im JSON-String im Description-Feld machen Probleme. Über Korrekturvorschläge würde ich mich freuen.

Demo für sn_caldav.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import getpass
user = input("User: ")
pw = getpass.getpass()
group_id = input("Group-ID: ")

print()
print("Searching calendar...")
c = get_cal(user=user, pw=pw, group_id=group_id)
print("found", c)
print()
print("New Event:")
e = LocalEvent(BERLIN.localize(datetime.datetime(2100, 1, 1)),
               BERLIN.localize(datetime.datetime(2100, 1, 2)),
               "Testevent")
print(e)
print()
print("Adding Event...")
print("saved as", e.add_to_cal(c))
print()
input("Press enter to delete the event")
e.delete_caldav()
print("deleted")

Beispielclient

sn_caldav.py
  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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
import icalendar
import caldav
import json
import datetime
import pytz

__version__ = "0.1"


DESCRIPTION_MAP = {"info": "Info", "kategorien": "Kategorie", "veranstalter": "Veranstalter",
                   "zielgruppe": "Zielgruppe", "link_text": "Link_Text"}


BERLIN = pytz.timezone("Europe/Berlin")


def decode_description(s):
    return {k.lower(): v for k, v in json.loads(s.replace('\\"', '"')).items()}


def encode_description(obj):
    return json.dumps({v: obj[k] for k, v in DESCRIPTION_MAP.items()}).replace('"', '\\"')


def get_cal(user, pw, group_id):
    url = "https://{user}:{pw}@webcal.scoutnet.de/webcal/{group_id}/".format(
        user=user, pw=pw, group_id=group_id)
    client = caldav.DAVClient(url)
    principal = client.principal()
    calendars = principal.calendars()
    return calendars[0]


class LocalEvent:
    EVENT_MAP = {"summary": "summary", "dtstart": "start", "dtend": "end",
                 "url": "url", "uid": "uid", "created": "created", "last-modified": "modified"}

    def __init__(self, start, end, summary, url="", info="", kategorien=None, veranstalter="", zielgruppe="", link_text="", uid=None, created=None, modified=None, caldav_event=None):
        self.start = start
        self.end = end
        self.summary = summary
        self.url = url
        self.info = info
        self.kategorien = [] if kategorien is None else kategorien
        self.veranstalter = veranstalter
        self.zielgruppe = zielgruppe
        self.link_text = link_text
        self.uid = uid
        self.created = created
        self.modified = modified
        self.caldav_event = caldav_event

    def to_ical(self):
        now = datetime.datetime.now(pytz.UTC)
        cal = icalendar.Calendar()
        cal.add('prodid', '-//Brohlsoft//ScoutNet.de Python-CalDAV//')
        cal.add('version', __version__)
        event = icalendar.Event()
        event.add("url", self.url)
        event.add('summary', self.summary)
        event.add('dtstart', self.start)
        event.add('dtend', self.end)
        event.add('created', self.created or now)
        event.add('dtstamp', self.modified or now)
        event.add('last-modified', self.modified or now)
        event.add('description', encode_description(dict(info=self.info, kategorien=self.kategorien,
                                                         veranstalter=self.veranstalter,
                                                         zielgruppe=self.zielgruppe,
                                                         link_text=self.link_text)))
        event.add('uid', self.uid or caldav.uuid.uuid4())
        cal.add_component(event)
        return cal.to_ical()

    @classmethod
    def from_ical(cls, s):
        cal = icalendar.Calendar.from_ical(s)
        event = cal.subcomponents[0]
        d = decode_description(event["description"])
        for k, v in cls.EVENT_MAP.items():
            d[v] = event[k]
        return cls(**d)

    @classmethod
    def load_caldav(cls, caldav_event):
        obj = cls.from_ical(caldav_event.data)
        obj.caldav_event = caldav_event
        return obj

    def save_caldav(self):
        s = self.to_ical()
        self.caldav_event.data = s
        self.caldav_event.save()

    def delete_caldav(self):
        self.caldav_event.delete()

    def add_to_cal(self, cal):
        self.caldav_event = cal.add_event(self.to_ical())
        return self.caldav_event

    def __repr__(self):
        return ("LocalEvent(start={start!r}, end={end!r}, summary={summary!r}, url={url!r}, info={info!r}, "
                "kategorien={kategorien!r}, veranstalter={veranstalter!r}, zielgruppe={zielgruppe!r}, "
                "link_text={link_text!r}, uid={uid!r}, created={created!r}, modified={modified!r}, "
                "caldav_event={caldav_event!r})").format(start=self.start, end=self.end, summary=self.summary,
                                                         url=self.url, info=self.info, kategorien=self.kategorien,
                                                         veranstalter=self.veranstalter, zielgruppe=self.zielgruppe,
                                                         link_text=self.link_text, uid=self.uid,
                                                         created=self.created, modified=self.modified,
                                                         caldav_event=self.caldav_event)