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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
"""
iCalendar feed generation library -- used for generating
iCalendar feeds.
Sample usage:
>>> from django_ical import feedgenerator
>>> from datetime import datetime
>>> feed = feedgenerator.ICal20Feed(
... title="My Events",
... link="http://www.example.com/events.ical",
... description="A iCalendar feed of my events.",
... language="en",
... )
>>> feed.add_item(
... title="Hello",
... link="http://www.example.com/test/",
... description="Testing.",
... start_datetime=datetime(2012, 5, 6, 10, 00),
... end_datetime=datetime(2012, 5, 6, 12, 00),
... )
>>> fp = open('test.ical', 'wb')
>>> feed.write(fp, 'utf-8')
>>> fp.close()
For definitions of the iCalendar format see:
http://www.ietf.org/rfc/rfc2445.txt
"""
from icalendar import Calendar, Event, Todo
from django.utils.feedgenerator import SyndicationFeed
__all__ = ("ICal20Feed", "DefaultFeed")
FEED_FIELD_MAP = (
("product_id", "prodid"),
("method", "method"),
("title", "x-wr-calname"),
("description", "x-wr-caldesc"),
("timezone", "x-wr-timezone"),
(
"ttl",
"x-published-ttl",
), # See format here: http://www.rfc-editor.org/rfc/rfc2445.txt (sec 4.3.6)
)
ITEM_ELEMENT_FIELD_MAP = (
# 'item_guid' becomes 'unique_id' when passed to the SyndicationFeed
("unique_id", "uid"),
("title", "summary"),
("description", "description"),
("start_datetime", "dtstart"),
("end_datetime", "dtend"),
("updateddate", "last-modified"),
("created", "created"),
("timestamp", "dtstamp"),
("transparency", "transp"),
("location", "location"),
("geolocation", "geo"),
("link", "url"),
("organizer", "organizer"),
("categories", "categories"),
("rrule", "rrule"),
("exrule", "exrule"),
("rdate", "rdate"),
("exdate", "exdate"),
("status", "status"),
("attendee", "attendee"),
("valarm", None),
# additional properties supported by the Todo class (VTODO calendar component).
# see https://icalendar.readthedocs.io/en/latest/_modules/icalendar/cal.html#Todo
("completed", "completed"),
("percent_complete", "percent-complete"),
("priority", "priority"),
("due", "due"),
("calscale", "calscale"),
("method", "method"),
("prodid", "prodid"),
("version", "version"),
("attach", "attach"),
("class", "class"),
("comment", "comment"),
("resources", "resources"),
("duration", "duration"),
("freebusy", "freebusy"),
("tzid", "tzid"),
("tzname", "tzname"),
("tzoffsetfrom", "tzoffsetfrom"),
("tzoffsetto", "tzoffsetto"),
("tzurl", "tzurl"),
("contact", "contact"),
("recurrence_id", "recurrence-id"),
("related_to", "related-to"),
("action", "action"),
("repeat", "repeat"),
("trigger", "trigger"),
("sequence", "sequence"),
("request_status", "request-status"),
)
class ICal20Feed(SyndicationFeed):
"""
iCalendar 2.0 Feed implementation.
"""
mime_type = "text/calendar; charset=utf-8"
def write(self, outfile, encoding):
"""
Writes the feed to the specified file in the
specified encoding.
"""
cal = Calendar()
cal.add("version", "2.0")
cal.add("calscale", "GREGORIAN")
for ifield, efield in FEED_FIELD_MAP:
val = self.feed.get(ifield)
if val is not None:
cal.add(efield, val)
self.write_items(cal)
to_ical = getattr(cal, "as_string", None)
if not to_ical:
to_ical = cal.to_ical
outfile.write(to_ical())
def write_items(self, calendar):
"""
Write all elements to the calendar
"""
for item in self.items:
component_type = item.get("component_type")
if component_type == "todo":
element = Todo()
else:
element = Event()
for ifield, efield in ITEM_ELEMENT_FIELD_MAP:
val = item.get(ifield)
if val is not None:
if ifield == "attendee":
for list_item in val:
element.add(efield, list_item)
elif ifield == "valarm":
for list_item in val:
element.add_component(list_item)
else:
element.add(efield, val)
calendar.add_component(element)
DefaultFeed = ICal20Feed
|