]> ToastFreeware Gitweb - philipp/winterrodeln/wrfeed.git/blob - wrfeed/controllers/berichte.py
41ffb63ea75e330ce429cf0e88517655040c2be3
[philipp/winterrodeln/wrfeed.git] / wrfeed / controllers / berichte.py
1 #!/usr/bin/python2.7
2 # -*- coding: UTF-8 -*-
3 """Creates an Atom-Feed for single or multiple winterrodeln sled reports.
4
5 Format:
6     http://www.winterrodeln.org/feed/berichte/alle
7     http://www.winterrodeln.org/feed/berichte/bahn/kemater_alm
8     http://www.winterrodeln.org/feed/berichte/bahnen/5+280+251
9     http://www.winterrodeln.org/feed/berichte/region/osttirol
10 See:
11     http://www.atompub.org/
12     http://effbot.org/zone/element.htm
13     http://www.winterrodeln.org/trac/wiki/UrlSchema
14 """
15 import sys
16 import datetime
17 from xml.etree.ElementTree import Element, SubElement, tostring
18
19 from sqlalchemy.engine import create_engine
20 from osgeo import ogr
21
22 import logging
23
24 import webob.exc
25 from pylons import request, response, session, config, tmpl_context as c, url
26 from pylons.controllers.util import abort, redirect
27
28 from wrfeed.lib.base import BaseController, render
29
30 log = logging.getLogger(__name__)
31
32
33 def create_feed(page_title=None, page_ids=None, region_name=None):
34     """If a page_title is given, only the reports for the given sledrun are shown.
35     If a list of page_ids is given, only the reports for the selected pages are shown.
36     If a region name (lower case) is given, the reports just for this region are shown.
37     Otherwise, all reports are shown."""
38
39     engine = create_engine(config['sqlalchemy.url'])
40     limit = int(config['feedentrylimit'])
41     conn = engine.connect()
42
43     select = 'select wrreport.page_id, wrreport.page_title, wrreport.id, date_report, date_entry, `condition`, description, author_name, author_userid, author_username, position_longitude, position_latitude from wrreport left outer join wrsledruncache on wrreport.page_id=wrsledruncache.page_id'
44     where = 'where date_invalid > now() and delete_date is null'
45     order = 'order by id desc'
46     limit = 'limit {0}'.format(limit)
47     params = []
48
49     if not page_title is None:
50         # page_title is given
51         page_title = page_title.replace('_', ' ')
52         where += ' and lcase(wrreport.page_title) = lcase(%s)'
53         params += [page_title]
54     elif not page_ids is None:
55         # a list of page_ids is given
56         if len(page_ids) == 0:
57             raise webob.exc.HTTPBadRequest()
58         where += ' and ('
59         where += " or ".join(['wrreport.page_id=%s' for page_id in page_ids])
60         where += ')'
61         params += map(str, page_ids)
62     elif not region_name is None:
63         # a name of a region is given
64         # (1) find out whether the region exists
65         subselect = 'select aswkb(border) as border_wkb from wrregion where name=lcase(%s)'
66         subresult = conn.execute(subselect, region_name)
67         if subresult.rowcount == 0:
68             # no region with such a name
69             raise webob.exc.HTTPNotFound()
70         assert subresult.rowcount == 1
71         row = subresult.fetchone()
72         border_wkb = row['border_wkb'] # border as WKB
73         where += ' and contains(geomfromwkb(%s), point(position_longitude, position_latitude))'
74         params += [border_wkb]
75         # the following variables are needed for the additional filtering below
76         border = ogr.CreateGeometryFromWkb(border_wkb)
77         point = ogr.Geometry(ogr.wkbPoint)
78     else:
79         # user wants to have all reports
80         pass
81     sql = ' '.join([select, where, order, limit])
82     result = conn.execute(sql, *params)
83
84     feed = Element("feed", xmlns="http://www.w3.org/2005/Atom", attrib={'xmlns:georss': 'http://www.georss.org/georss', 'xmlns:wr': 'http://www.winterrodeln.org/schema/wrreport'})
85     feed_title = SubElement(feed, "title")
86     feed_title.text = "Winterrodeln Rodelbahnberichte"
87     feed_id = SubElement(feed, "id")
88     if not page_title is None:
89         feed_id.text = url(qualified=True, controller='berichte', action='bahn', id=page_title)
90     elif not page_ids is None:
91         feed_id.text = url(qualified=True, controller='berichte', action='bahnen', id="+".join(map(str, page_ids)))
92     elif not region_name is None:
93         feed_id.text = url(qualified=True, controller='berichte', action='region', id=region_name)
94     else:
95         feed_id.text = url(qualified=True, controller='berichte', action='alle')
96     feed_updated = SubElement(feed, "updated")
97     feed.append(Element("link", rel="self", href=feed_id.text))
98
99     last_updated = None
100     for row in result:
101         page_id, page_title, report_id, date_report, date_entry, condition, description, author_name, author_userid, author_username, lon, lat = row
102
103         if not region_name is None:
104             # mysql 5.5 doesn't have specification conform geospacial functions.
105             # http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html
106             # therefore we have to do further filtering here.
107             point.SetPoint(0, lon, lat)
108             if not point.Within(border):
109                 continue
110
111         page_title_url = page_title.replace(u' ', u'_')
112         entry = SubElement(feed, "entry")
113         entry_title = SubElement(entry, "title")
114         entry_title.text = page_title
115         entry.append(Element("link", rel="alternate", href=u"http://www.winterrodeln.org/wiki/{0}".format(page_title_url), type="text/html", hreflang="de"))
116         entry_id = SubElement(entry, "id")
117         entry_id.text = u"http://www.winterrodeln.org/wiki/{0}#{1}".format(page_title_url, report_id)
118         entry_updated = SubElement(entry, "updated")
119         entry_updated.text = date_entry.isoformat() + "+01:00"
120         if last_updated is None: last_updated = date_entry
121         # entry_summary = SubElement(entry, "summary")
122         # entry_summary.text = str(condition)
123         entry_content = SubElement(entry, "content")
124         entry_content.attrib["type"] = "xhtml"
125         entry_content_div = SubElement(entry_content, "div")
126         entry_content_div.attrib["xmlns"] = "http://www.w3.org/1999/xhtml"
127         entry_content_ul = SubElement(entry_content_div, "ul")
128         if not date_report is None:
129             entry_content_date = SubElement(entry_content_ul, "li")
130             entry_content_date.text = u"Bericht für " + date_report.isoformat()
131         if not condition is None:
132             entry_content_condition = SubElement(entry_content_ul, "li")
133             entry_content_condition.text = u"Schneelage: " + {1: u'Sehr gut', 2: u'Gut', 3: u'Mittelmäßig', 4: u'Schlecht', 5: u'Geht nicht'}[condition]
134         entry_content_description = SubElement(entry_content_ul, "li")
135         entry_content_description.text = description
136         entry_author = SubElement(entry, "author")
137         entry_author_name = SubElement(entry_author, "name")
138         if author_name is None or len(author_name.strip()) == 0: entry_author_name.text = "Anonymous user"
139         else: entry_author_name.text = author_name
140         if not lon is None and not lat is None:
141             entry_geo = SubElement(entry, "georss:point")
142             entry_geo.text = "{lat} {lon}".format(lat=lat, lon=lon)
143         entry_wrreport = SubElement(entry, "wr:report")
144         entry_wrreport.attrib['report_id'] = str(report_id)
145         entry_wrreport.attrib['page_id'] = str(page_id)
146         entry_wrreport.attrib['page_title'] = page_title
147         entry_wrreport.attrib['date_report'] = str(date_report)
148         entry_wrreport.attrib['date_entry'] = str(date_entry)
149         entry_wrreport.attrib['condition'] = "0" if condition is None else str(condition)
150         entry_wrreport.attrib['author_name'] = author_name
151         entry_wrreport.attrib['author_username'] = "" if author_userid is None else author_username
152         entry_wrreport.text = description
153
154     if last_updated is None: last_updated = datetime.datetime.now()
155     feed_updated.text = last_updated.isoformat() + "+01:00"
156
157     feed_xml =  '<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)
158     conn.close()
159     return feed_xml
160
161
162
163 class BerichteController(BaseController):
164
165     def alle(self):
166         """Handles URLs like
167         http://127.0.0.1:5000/berichte/alle
168         http://www.winterrodeln.org/feed/berichte/alle
169         """
170         response.content_type = 'application/atom+xml'
171         return create_feed()
172
173
174     def bahn(self, id):
175         """Handles URLs like
176         http://127.0.0.1:5000/berichte/bahn/kemater_alm
177         http://www.winterrodeln.org/feed/berichte/bahn/kemater_alm
178         """
179         response.content_type = 'application/atom+xml'
180         return create_feed(page_title=id)
181
182
183     def bahnen(self, id):
184         """Handles URLs like
185         http://127.0.0.1:5000/berichte/bahnen/5+280+251
186         http://www.winterrodeln.org/feed/berichte/bahnen/5+280+251
187         """
188         page_ids = id.split('+')
189         try:
190             page_ids = [int(page_id) for page_id in page_ids]
191         except ValueError:
192             abort(400) # bad request
193         response.content_type = 'application/atom+xml'
194         return create_feed(page_ids=page_ids)
195
196     def region(self, id):
197         """Handles URLs like
198         http://www.winterrodeln.org/feed/berichte/region/osttirol
199         """
200         response.content_type = 'application/atom+xml'
201         return create_feed(region_name=id)
202