def generate_calendar(request): """http://codespeak.net/icalendar/""" cal = Calendar() cal.add("prodid", "-//Club Connect//ericleong.me//") cal.add("version", "2.0") posts = Post.objects.order_by("-created") cal["X-WR-CALNAME"] = "Club Connect Events" cal["X-PUBLISH-TTL"] = "PT12H" cal["CALSCALE"] = "GREGORIAN" cal["METHOD"] = "PUBLISH" # TODO: separate out private events using a private URL? # TODO: switch to using EDT for post in posts: if post.start_time: # Make sure we have a time event = Event() event.add("summary", vText(post.title)) event.add("dtstart", post.start_time) event.add("dtend", post.end_time if post.end_time else post.start_time) # event.add('dtstamp', datetime(2005,4,4,0,10,0,tzinfo=UTC)) event["uid"] = vText(post.id) event["organizer"] = vText(post.author.username) event["description"] = vText(post.description) event["url"] = vUri(post.get_absolute_url()) if post.location: if post.location.room: event["location"] = vText("%s (%s)" % (post.location.name, post.location.room)) else: event["location"] = vText(post.location.name) for commit in post.committed.all(): attendee = vCalAddress("MAILTO:" + commit.email) name = ( ([commit.first_name, commit.last_name]) if (commit.first_name and commit.last_name) else commit.username ) attendee.params["cn"] = vText(name) event.add("attendee", attendee, encode=0) cal.add_component(event) return HttpResponse(cal.to_ical().replace("\n", "\r\n"), content_type="text/calendar")
component['UID'] = uid = md5.hexdigest() if component.name in ('VEVENT', 'VTODO'): items[uid] = component else: other.append(component) changed = 0 added = 0 seen = 0 for (uid, ev) in items.iteritems(): seen += 1 fname = "%s-%s.ics" % (opts.prefix, uid.replace("/", "")) path = os.path.join(opts.outdir, fname) out = Calendar() out['X-IMPORTED-FROM-URL'] = vUri(url) out.update(orig.items()) for c in other: out.add_component(c) if opts.category: if isinstance(ev.get('categories', ''), vText): ev['categories'] = [ev['categories']] ev.setdefault('categories', []).append(vText(opts.category)) if opts.status and not 'status' in ev: ev['status'] = opts.status.upper() out.add_component(ev) try: old = Calendar.from_ical(open(path, 'rb').read()) except IOError: old = None write = True
items[component['UID']] = component except KeyError: raise KeyError('missing UID for %s in %s' % (component.name, url)) else: other.append(component) seen = 0 changed = 0 added = 0 for (uid, ev) in items.items(): seen += 1 (old, todo, new, href, etag, ev) = utils.create_or_update_calendar_item( target_collection_url, "VEVENT", uid) out = Calendar() if import_url is not None: out['X-IMPORTED-FROM-URL'] = vUri(import_url) # If this is not an iTIP request, then make it one. if "METHOD" not in out and opts.invite: out["METHOD"] = "REQUEST" out.update(list(orig.items())) for c in other: out.add_component(c) if opts.category: if isinstance(ev.get('CATEGORIES', ''), vText): ev['CATEGORIES'] = [ev['CATEGORIES']] ev.setdefault('categories', []).append(vText(opts.category)) if opts.status and 'STATUS' not in ev: ev['STATUS'] = opts.status.upper() out.add_component(ev) write = hasChanged(old, out) if write:
dtend = None duration = datetime.timedelta(1) props = { 'categories': opts.categories.split(','), 'dtstart': vDate(dtstart.date()), 'created': vDatetime(datetime.datetime.now()), 'class': 'PUBLIC', } if status is not None: props['status'] = status if location is not None: props['location'] = vText(location) if opts.event_url: props['url'] = vUri(opts.event_url) if description is not None: props['summary'] = vText(description) if dtend is not None: props['dtend'] = vDate(dtend.date()) if duration is not None: props['duration'] = vDuration(duration) uid = str(uuid.uuid1()) props['UID'] = uid ev = Event(**props) c = Calendar() c.add_component(ev) utils.add_member(opts.url, 'text/calendar', c.to_ical())
dtend = None duration = datetime.timedelta(1) props = { 'categories': opts.categories.split(','), 'dtstart': vDate(dtstart.date()), 'created': vDatetime(datetime.datetime.now()), 'class': 'PUBLIC', } if status is not None: props['status'] = status if location is not None: props['location'] = vText(location) if opts.url: props['url'] = vUri(opts.url) if description is not None: props['summary'] = vText(description) if dtend is not None: props['dtend'] = vDate(dtend.date()) if duration is not None: props['duration'] = vDuration(duration) ev = Event(**props) c = Calendar() c.add_component(ev) md5 = hashlib.md5() md5.update(c.to_ical())