diff --git a/cfp/models.py b/cfp/models.py index db8cf42..3f720e7 100644 --- a/cfp/models.py +++ b/cfp/models.py @@ -320,18 +320,6 @@ class Talk(PonyConfModel): else: return None - @property - def dtstart(self): - return self.start_date.strftime('%Y%m%dT%H%M%SZ') - - @property - def dtend(self): - return self.end_date.strftime('%Y%m%dT%H%M%SZ') - - @property - def dtstamp(self): - return self.updated.strftime('%Y%m%dT%H%M%SZ') - #@property #def materials_name(self): # return basename(self.materials.name) diff --git a/cfp/planning.py b/cfp/planning.py index 029602d..424712e 100644 --- a/cfp/planning.py +++ b/cfp/planning.py @@ -5,6 +5,7 @@ from django.utils.timezone import localtime from django.core.cache import cache from django.core.urlresolvers import reverse from django.template.loader import get_template +from django.conf import settings from datetime import datetime, timedelta from copy import deepcopy @@ -12,6 +13,7 @@ from collections import OrderedDict, namedtuple from itertools import islice from zlib import adler32 import xml.etree.ElementTree as ET +from icalendar import Calendar as iCalendar, Event as iEvent from .models import Conference, Talk, Room @@ -252,7 +254,27 @@ class Program: def _as_ics(self): if not self.initialized: self._lazy_init() - return get_template('cfp/planning.ics').render({'site': self.site, 'talks': self.talks}) + cal = iCalendar() + cal.add('prodid', '-//PonyConf.io//PonyConf//FR') + cal.add('version', '2.0') + cal.add('x-wr-calname', self.conference.name) + cal.add('x-wr-timezone', settings.TIME_ZONE) + cal.add('calscale', 'GREGORIAN') + for talk in self.talks.all(): + event = iEvent() + event.add('dtstart', talk.start_date) + if not talk.end_date: + continue + event.add('dtend', talk.end_date) + event.add('dtstamp', talk.updated) + event.add('summary', talk.title) + if talk.room: + event.add('location', talk.room) + event.add('status', 'CONFIRMED' if talk.accepted else 'TENTATIVE') + event.add('description', talk.description) + event.add('uid', '%s/%s' % (self.site.domain, talk.id)) + cal.add_component(event) + return cal.to_ical() def render(self, output='html'): if self.cache: diff --git a/cfp/templates/cfp/ics/talk.ics b/cfp/templates/cfp/ics/talk.ics deleted file mode 100644 index e69de29..0000000 diff --git a/cfp/templates/cfp/planning.ics b/cfp/templates/cfp/planning.ics deleted file mode 100644 index 651e74b..0000000 --- a/cfp/templates/cfp/planning.ics +++ /dev/null @@ -1,18 +0,0 @@ -BEGIN:VCALENDAR -PRODID:-//{{ site.domain }}//{{ site.name }}//FR -X-WR-CALNAME:{{ site.name }} -X-WR-TIMEZONE:Europe/Paris -VERSION:2.0 -CALSCALE:GREGORIAN -{% for talk in talks %} -BEGIN:VEVENT -DTSTAMP:{{ talk.dtstamp }} -DTSTART:{{ talk.dtstart }} -DTEND:{{ talk.dtend }} -SUMMARY:{{ talk.title }} -LOCATION:{{ talk.room }} -STATUS:{% if talk.accepted %}CONFIRMED{% else %}TENTATIVE{% endif %} -DESCRIPTION:{{ talk.description|linebreaksbr }} -UID:{{ site.domain }}/{{ talk.id }} -END:VEVENT{% endfor %} -END:VCALENDAR diff --git a/cfp/views.py b/cfp/views.py index 8fa9ecd..186c9d1 100644 --- a/cfp/views.py +++ b/cfp/views.py @@ -481,17 +481,8 @@ def schedule(request, program_format, pending, cache, template): elif program_format == 'xml': return HttpResponse(program.render('xml'), content_type="application/xml") elif program_format == 'ics': - response = HttpResponse('', content_type='text/plain') + response = HttpResponse(program.render('ics'), content_type='text/calendar') response['Content-Disposition'] = 'attachment; filename="planning.ics"' - ics = [] - for line in program.render('ics').split('\n'): - line = line.strip().replace('
', '') - if len(line) < 50: - ics.append(line) - else: # https://icalendar.org/iCalendar-RFC-5545/3-1-content-lines.html - for i in range(ceil(len(line) / 50)): - ics.append((' ' if i > 0 else '') + line[i * 50:(i + 1) * 50]) - response.write('\r\n'.join([line for line in ics if line]).strip() + '\r\n') return response else: raise Http404(_("Format '%s' not available" % program_format)) diff --git a/requirements.in b/requirements.in index c26ab7c..6a7a0df 100644 --- a/requirements.in +++ b/requirements.in @@ -10,3 +10,4 @@ django-colorful markdown bleach chardet +icalendar diff --git a/requirements.txt b/requirements.txt index d3998db..8e2b32f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,9 @@ django-crispy-forms==1.6.1 django-select2==5.11.1 django==1.11.5 html5lib==0.999999999 # via bleach +icalendar==3.11.7 markdown==2.6.9 -pytz==2017.2 # via django -six==1.10.0 # via bleach, django-bower, html5lib +python-dateutil==2.6.1 # via icalendar +pytz==2017.2 # via django, icalendar +six==1.10.0 # via bleach, django-bower, html5lib, python-dateutil webencodings==0.5.1 # via html5lib