]> ToastFreeware Gitweb - philipp/winterrodeln/wrfeed.git/blob - wrfeed/controllers/berichte.py
10e83af7f7ac1f1649e11463388d86ebad2c3782
[philipp/winterrodeln/wrfeed.git] / wrfeed / controllers / berichte.py
1 """Creates an Atom-Feed for single or multiple winterrodeln sled reports.
2
3 Format:
4     http://www.winterrodeln.org/feed/berichte/alle
5     http://www.winterrodeln.org/feed/berichte/bahn/kemater_alm
6     http://www.winterrodeln.org/feed/berichte/bahnen/5+280+251
7     http://www.winterrodeln.org/feed/berichte/region/osttirol
8 See:
9     http://www.atompub.org/
10     http://effbot.org/zone/element.htm
11     http://www.winterrodeln.org/trac/wiki/UrlSchema
12 """
13 import datetime
14 from xml.etree.ElementTree import Element, SubElement, tostring
15 from osgeo import ogr
16 from flask import url_for
17
18
19 class CreateFeedError(RuntimeError):
20     pass
21
22
23 class RegionNotFoundError(CreateFeedError):
24     pass
25
26
27 def create_feed(conn, limit, page_title=None, page_ids=None, region_name=None):
28     """If a page_title is given, only the reports for the given sledrun are shown.
29     If a list of page_ids is given, only the reports for the selected pages are shown.
30     If a region name (lower case) is given, the reports just for this region are shown.
31     Otherwise, all reports are shown."""
32     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'
33     where = 'where date_invalid > now() and delete_date is null'
34     order = 'order by id desc'
35     limit = 'limit {0}'.format(limit)
36     params = []
37
38     if not page_title is None:
39         # page_title is given
40         page_title = page_title.replace('_', ' ')
41         where += ' and lcase(wrreport.page_title) = lcase(%s)'
42         params += [page_title]
43     elif not page_ids is None:
44         # a list of page_ids is given
45         assert len(page_ids) > 0
46         where += ' and ('
47         where += " or ".join(['wrreport.page_id=%s' for page_id in page_ids])
48         where += ')'
49         params += list(map(str, page_ids))
50     elif not region_name is None:
51         # a name of a region is given
52         # (1) find out whether the region exists
53         subselect = 'select aswkb(border) as border_wkb from wrregion where name=lcase(%s)'
54         subresult = conn.execute(subselect, region_name)
55         if subresult.rowcount == 0:
56             # no region with such a name
57             raise RegionNotFoundError(region_name)
58         assert subresult.rowcount == 1
59         row = subresult.fetchone()
60         # (2) now we have the border
61         border_wkb = row['border_wkb'] # border as WKB
62         where += ' and contains(geomfromwkb(%s), point(position_longitude, position_latitude))'
63         params += [border_wkb]
64         # the following variables are needed for the additional filtering below
65         border = ogr.CreateGeometryFromWkb(border_wkb)
66         point = ogr.Geometry(ogr.wkbPoint)
67     else:
68         # user wants to have all reports
69         pass
70     sql = ' '.join([select, where, order, limit])
71     result = conn.execute(sql, *params)
72
73     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'})
74     feed_title = SubElement(feed, "title")
75     feed_title.text = "Winterrodeln Rodelbahnberichte"
76     feed_id = SubElement(feed, "id")
77     if not page_title is None:
78         feed_id.text = url_for('bahn', bahn=page_title, _external=True)
79     elif not page_ids is None:
80         feed_id.text = url_for('bahnen', bahnen="+".join(map(str, page_ids)), _external=True)
81     elif not region_name is None:
82         feed_id.text = url_for('region', region=region_name, _external=True)
83     else:
84         feed_id.text = url_for('alle', _external=True)
85     feed_updated = SubElement(feed, "updated")
86     feed.append(Element("link", rel="self", href=feed_id.text))
87
88     last_updated = None
89     for row in result:
90         page_id, page_title, report_id, date_report, date_entry, condition, description, author_name, author_userid, author_username, lon, lat = row
91
92         if not region_name is None:
93             # mysql 5.5 doesn't have specification conform geospacial functions.
94             # http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html
95             # therefore we have to do further filtering here.
96             point.SetPoint(0, lon, lat)
97             if not point.Within(border):
98                 continue
99
100         page_title_url = page_title.replace(' ', '_')
101         entry = SubElement(feed, "entry")
102         entry_title = SubElement(entry, "title")
103         entry_title.text = page_title
104         entry.append(Element("link", rel="alternate", href="http://www.winterrodeln.org/wiki/{0}".format(page_title_url), type="text/html", hreflang="de"))
105         entry_id = SubElement(entry, "id")
106         entry_id.text = "http://www.winterrodeln.org/wiki/{0}#{1}".format(page_title_url, report_id)
107         entry_updated = SubElement(entry, "updated")
108         entry_updated.text = date_entry.isoformat() + "+01:00"
109         if last_updated is None: last_updated = date_entry
110         # entry_summary = SubElement(entry, "summary")
111         # entry_summary.text = str(condition)
112         entry_content = SubElement(entry, "content")
113         entry_content.attrib["type"] = "xhtml"
114         entry_content_div = SubElement(entry_content, "div")
115         entry_content_div.attrib["xmlns"] = "http://www.w3.org/1999/xhtml"
116         entry_content_ul = SubElement(entry_content_div, "ul")
117         if not date_report is None:
118             entry_content_date = SubElement(entry_content_ul, "li")
119             entry_content_date.text = "Bericht für " + date_report.isoformat()
120         if not condition is None:
121             entry_content_condition = SubElement(entry_content_ul, "li")
122             entry_content_condition.text = "Schneelage: " + {1: 'Sehr gut', 2: 'Gut', 3: 'Mittelmäßig', 4: 'Schlecht', 5: 'Geht nicht'}[condition]
123         entry_content_description = SubElement(entry_content_ul, "li")
124         entry_content_description.text = description
125         entry_author = SubElement(entry, "author")
126         entry_author_name = SubElement(entry_author, "name")
127         if author_name is None or len(author_name.strip()) == 0: entry_author_name.text = "Anonymous user"
128         else: entry_author_name.text = author_name
129         if not lon is None and not lat is None:
130             entry_geo = SubElement(entry, "georss:point")
131             entry_geo.text = "{lat} {lon}".format(lat=lat, lon=lon)
132         entry_wrreport = SubElement(entry, "wr:report")
133         entry_wrreport.attrib['report_id'] = str(report_id)
134         entry_wrreport.attrib['page_id'] = str(page_id)
135         entry_wrreport.attrib['page_title'] = page_title
136         entry_wrreport.attrib['date_report'] = str(date_report)
137         entry_wrreport.attrib['date_entry'] = str(date_entry)
138         entry_wrreport.attrib['condition'] = "0" if condition is None else str(condition)
139         entry_wrreport.attrib['author_name'] = author_name
140         entry_wrreport.attrib['author_username'] = "" if author_userid is None else author_username
141         entry_wrreport.text = description
142
143     if last_updated is None: last_updated = datetime.datetime.now()
144     feed_updated.text = last_updated.isoformat() + "+01:00"
145
146     return b'<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)