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