|
@@ -24,6 +24,14 @@ from docutils.parsers.rst import directives, Directive
|
|
|
from pelican import signals, generators
|
|
|
import jinja2
|
|
|
|
|
|
+try:
|
|
|
+ import ics
|
|
|
+except ImportError:
|
|
|
+ ICS_ENABLED = False
|
|
|
+else:
|
|
|
+ ICS_ENABLED = True
|
|
|
+import unidecode
|
|
|
+
|
|
|
pelican = None # This will be set during register()
|
|
|
|
|
|
|
|
@@ -110,6 +118,8 @@ def get_talk_data(talkname):
|
|
|
if 'text' not in data:
|
|
|
logging.warn("Talk <{}> has no `text` field".format(talkname))
|
|
|
data['text'] = ''
|
|
|
+ else:
|
|
|
+ data['text'] = unicode(data['text'])
|
|
|
if 'duration' not in data:
|
|
|
logging.info("Talk <{}> has no `duration` field (50min used)"
|
|
|
.format(talkname))
|
|
@@ -303,37 +313,33 @@ class TalkGridDirective(Directive):
|
|
|
|
|
|
|
|
|
def talks_to_ics():
|
|
|
- content = u'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:pelican\n'
|
|
|
+ c = ics.Calendar()
|
|
|
+ c.creator = u'pelican'
|
|
|
for t in all_talks():
|
|
|
- try:
|
|
|
- content += talk_to_ics(t)
|
|
|
- except:
|
|
|
- logging.exception("Error producing calendar for talk %s", t['id'])
|
|
|
- content += 'END:VCALENDAR\n'
|
|
|
- return content
|
|
|
+ e = talk_to_ics(t)
|
|
|
+ if e is not None:
|
|
|
+ c.events.add(e)
|
|
|
+ return unicode(c)
|
|
|
|
|
|
|
|
|
def talk_to_ics(talk):
|
|
|
if 'time' not in talk or 'duration' not in talk:
|
|
|
- return ''
|
|
|
- start = talk['time']
|
|
|
- end = start + datetime.timedelta(minutes=talk['duration'])
|
|
|
- content = 'BEGIN:VEVENT\n'
|
|
|
- content += "UID:%s@%d.hackmeeting.org\n" % (talk['id'], talk['day'].year)
|
|
|
- content += "SUMMARY:%s\n" % talk['title']
|
|
|
- content += "DTSTAMP:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
|
|
- time.gmtime(float(
|
|
|
- start.strftime('%s'))))
|
|
|
- content += "DTSTART:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
|
|
- time.gmtime(float(
|
|
|
- start.strftime('%s'))))
|
|
|
- content += "DTEND:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
|
|
- time.gmtime(float(
|
|
|
- end.strftime('%s'))))
|
|
|
-
|
|
|
- content += "LOCATION:%s\n" % (talk['room'] if 'room' in talk else 'todo')
|
|
|
- content += 'END:VEVENT\n'
|
|
|
- return content
|
|
|
+ return None
|
|
|
+ e = ics.Event(
|
|
|
+ uid="%s@%d.hackmeeting.org\n" % (talk['id'], talk['day'].year),
|
|
|
+ name=talk['id'],
|
|
|
+ begin=talk['time'],
|
|
|
+ duration=datetime.timedelta(minutes=talk['duration']),
|
|
|
+ transparent=True,
|
|
|
+ )
|
|
|
+ # ics.py has some problems with unicode
|
|
|
+ # unidecode replaces letters with their most similar ASCII counterparts
|
|
|
+ # (ie: accents get stripped)
|
|
|
+ e.description = unidecode.unidecode(talk['text'])
|
|
|
+
|
|
|
+ e.url = pelican.settings['SCHEDULEURL'] + '#talk-' + talk['id']
|
|
|
+
|
|
|
+ return e
|
|
|
|
|
|
|
|
|
class TalksGenerator(generators.Generator):
|
|
@@ -354,10 +360,13 @@ class TalksGenerator(generators.Generator):
|
|
|
if os.path.isdir(outdir):
|
|
|
shutil.rmtree(outdir)
|
|
|
shutil.copytree(self.talks[talkname]['resources'], outdir)
|
|
|
- with io.open(os.path.join(self.output_path, pelican.settings.get('TALKS_ICS')),
|
|
|
- 'w',
|
|
|
- encoding='utf8') as buf:
|
|
|
- buf.write(talks_to_ics())
|
|
|
+ if ICS_ENABLED:
|
|
|
+ with io.open(os.path.join(self.output_path, pelican.settings.get('TALKS_ICS')),
|
|
|
+ 'w',
|
|
|
+ encoding='utf8') as buf:
|
|
|
+ buf.write(talks_to_ics())
|
|
|
+ else:
|
|
|
+ logging.warning('module `ics` not found. ICS calendar will not be generated')
|
|
|
|
|
|
|
|
|
def add_talks_option_defaults(pelican):
|