summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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
commit680f2b2256bfd715f6428ebb5b9f71b04380aaa4 (patch)
tree529c806915e59f5972c41b91021f2cd2da46312e
parentcdaf3001850fb637700576077a7ec307eb16f861 (diff)
downloadChimère-680f2b2256bfd715f6428ebb5b9f71b04380aaa4.tar.bz2
Chimère-680f2b2256bfd715f6428ebb5b9f71b04380aaa4.zip
Imports: add ical management
-rw-r--r--chimere/models.py7
-rw-r--r--chimere/tests.py11
-rw-r--r--chimere/tests/test.ics20
-rw-r--r--chimere/utils.py67
-rw-r--r--requirements.txt1
-rw-r--r--requirements_searchengine.txt1
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