diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-03-01 23:17:13 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-03-01 23:17:13 +0100 |
commit | 680f2b2256bfd715f6428ebb5b9f71b04380aaa4 (patch) | |
tree | 529c806915e59f5972c41b91021f2cd2da46312e | |
parent | cdaf3001850fb637700576077a7ec307eb16f861 (diff) | |
download | Chimère-680f2b2256bfd715f6428ebb5b9f71b04380aaa4.tar.bz2 Chimère-680f2b2256bfd715f6428ebb5b9f71b04380aaa4.zip |
Imports: add ical management
-rw-r--r-- | chimere/models.py | 7 | ||||
-rw-r--r-- | chimere/tests.py | 11 | ||||
-rw-r--r-- | chimere/tests/test.ics | 20 | ||||
-rw-r--r-- | chimere/utils.py | 67 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | requirements_searchengine.txt | 1 |
6 files changed, 105 insertions, 2 deletions
diff --git a/chimere/models.py b/chimere/models.py index 755d43c..a9bac2c 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2008-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2008-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as @@ -46,7 +46,8 @@ from chimere.widgets import HiddenPointChooserWidget, PointField, RouteField, \ DatePickerWidget from chimere.managers import BaseGeoManager from chimere.utils import KMLManager, OSMManager, ShapefileManager, \ - GeoRSSManager, CSVManager, HtmlXsltManager, XMLXsltManager, JsonManager + GeoRSSManager, CSVManager, HtmlXsltManager, XMLXsltManager, JsonManager, \ + IcalManager class Page(models.Model): @@ -340,6 +341,7 @@ IMPORTERS = {'KML': KMLManager, 'RSS': GeoRSSManager, 'CSV': CSVManager, 'JSON': JsonManager, + 'ICAL': IcalManager, 'XSLT': HtmlXsltManager, 'XXLT': XMLXsltManager } @@ -350,6 +352,7 @@ IMPORTER_CHOICES = (('KML', 'KML'), ('RSS', 'GeoRSS'), ('CSV', 'CSV'), ('JSON', 'JSON'), + ('ICAL', 'ICAL'), ('XSLT', 'HTML-XSLT'), ('XXLT', 'XML-XSLT'), ) diff --git a/chimere/tests.py b/chimere/tests.py index ca93546..e192bcc 100644 --- a/chimere/tests.py +++ b/chimere/tests.py @@ -349,6 +349,17 @@ class JsonImporterTest(TestCase, ImporterTest): self.marker_importers = [(importer1, 5), ] +class IcalImporterTest(TestCase, ImporterTest): + def setUp(self): + subcategories = subcategory_setup() + icsfile = File(open(test_dir_path + 'tests/test.ics')) + importer1 = Importer.objects.create( + importer_type='ICAL', + source_file=icsfile,) + importer1.categories.add(subcategories[0]) + self.marker_importers = [(importer1, 1), ] + + class FeedsTest(TestCase): def setUp(self): self.areas = areas_setup() diff --git a/chimere/tests/test.ics b/chimere/tests/test.ics new file mode 100644 index 0000000..7253042 --- /dev/null +++ b/chimere/tests/test.ics @@ -0,0 +1,20 @@ +BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//SOURCE ID - ECPv4.0.5//NONSGML v1.0//EN
+CALSCALE:GREGORIAN
+METHOD:PUBLISH
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20151201
+DTEND;VALUE=DATE:20160309
+DTSTAMP:20160301T212219
+CREATED:20151223
+LAST-MODIFIED:20151223
+UID:226383-1448928000-1457567999@www.example.com
+SUMMARY:Dix moi dix maux
+DESCRIPTION:Concours.....
+URL:http://www.caps.fr/evenement/dix-moi-dix-mots/
+LOCATION:Adresse fictibe
+GEO:48.7304316;2.1765011
+CATEGORIES:Animation
+END:VEVENT
+END:VCALENDAR
diff --git a/chimere/utils.py b/chimere/utils.py index 96c41b4..1240914 100644 --- a/chimere/utils.py +++ b/chimere/utils.py @@ -1222,3 +1222,70 @@ class HtmlXsltManager(ImportManager): class XMLXsltManager(HtmlXsltManager): PARSER = 'XMLParser' + +import icalendar + + +class IcalManager(ImportManager): + def get(self): + u""" + Get data from an icalendar source + """ + from models import Marker + new_item, updated_item, msg = 0, 0, '' + source, msg = self.get_source_file([]) + if msg: + return (0, 0, msg) + + data = source.read() + try: + cal = icalendar.Calendar.from_ical(data) + except ValueError as e: + return (new_item, updated_item, + _(u"Error on icalendar parsing: " + e.message)) + + default_dct = {'origin': self.importer_instance.origin, + 'license': self.importer_instance.license} + if self.importer_instance.default_localisation: + default_dct['point'] = self.importer_instance.default_localisation + + for event in cal.walk('VEVENT'): + dct = default_dct.copy() + dct['name'] = event.get('SUMMARY', '') + if dct['name']: + dct['name'] = unicode(dct['name']) + dct['description'] = event.get('DESCRIPTION', '') + if dct['description']: + dct['description'] = unicode(dct['description']) + loc = event.get('LOCATION', None) + if loc: + dct['description'] += u"<br/>{}".format(unicode(loc)) + url = event.get('URL', None) + if url: + dct['description'] += u"<br/><a href='{}'>{}</a>".format( + unicode(url), unicode(_(u'Link'))) + dct['start_date'] = event.get('DTSTART', None) + if dct['start_date']: + dct['start_date'] = event.decoded('DTSTART') + dct['end_date'] = event.get('DTEND', None) + if dct['end_date']: + dct['end_date'] = event.decoded('DTEND') + point = event.get('GEO', None) + if point: + dct['point'] = 'SRID=4326;POINT(%s %s)' % (point.longitude, + point.latitude) + + if not dct.get('point', None): + continue + + cls = Marker + pl_id = event.get('UID', None) + if not pl_id: + pl_id = dct['name'] + "-" + unicode(self.importer_instance.pk) + pl_id += "-" + unicode(self.importer_instance.pk) + it, updated, created = self.create_or_update_item(cls, dct, pl_id) + if updated: + updated_item += 1 + if created: + new_item += 1 + return (new_item, updated_item, msg) diff --git a/requirements.txt b/requirements.txt index bd9e95d..4417b69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ south>=0.7.3,<0.7.99 simplejson feedparser django-tinymce +icalendar==3.8 diff --git a/requirements_searchengine.txt b/requirements_searchengine.txt index a87b1bb..3383004 100644 --- a/requirements_searchengine.txt +++ b/requirements_searchengine.txt @@ -10,3 +10,4 @@ django-tinymce django-haystack==2.1 geopy pysolr +icalendar==3.8 |