Browse Source

ICS: url and description; refactoring

boyska 5 years ago
parent
commit
632db0c37f
3 changed files with 43 additions and 30 deletions
  1. 39 30
      plugins/talks.py
  2. 3 0
      publishconf.py
  3. 1 0
      requirements.txt

+ 39 - 30
plugins/talks.py

@@ -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):

+ 3 - 0
publishconf.py

@@ -14,6 +14,9 @@ SITEURL = '/hackit18'
 RELATIVE_URLS = True
 TALKS_GRID_STEP = 30
 
+# plugin/talks.py
+SCHEDULEURL = 'https://hackmeeting.org' + SITEURL + '/schedule.html'
+
 # DELETE_OUTPUT_DIRECTORY = True
 
 # Following items are often useful when publishing

+ 1 - 0
requirements.txt

@@ -3,6 +3,7 @@ beautifulsoup4==4.6.0
 blinker==1.3
 docutils==0.12
 feedgenerator==1.7
+ics==0.4
 Jinja2==2.7.3
 Markdown==2.6.1
 MarkupSafe==0.23