http -> https.
[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]).where(region_id == wrregioncache.c.region_id)))
67     else:
68         # user wants to have all reports
69         pass
70     result = db.session.connection().execute(sql)
71
72     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'})
73     feed_title = SubElement(feed, "title")
74     feed_title.text = "Winterrodeln Rodelbahnberichte"
75     feed_id = SubElement(feed, "id")
76     if not page_title is None:
77         feed_id.text = url_for('bahn', bahn=page_title, _external=True)
78     elif not page_ids is None:
79         feed_id.text = url_for('bahnen', bahnen="+".join(map(str, page_ids)), _external=True)
80     elif not region_name is None:
81         feed_id.text = url_for('region', region=region_name, _external=True)
82     else:
83         feed_id.text = url_for('alle', _external=True)
84     feed_updated = SubElement(feed, "updated")
85     feed.append(Element("link", rel="self", href=feed_id.text))
86
87     last_updated = None
88     for row in result:
89         page_title_url = row.page_title.replace(' ', '_')
90         entry = SubElement(feed, "entry")
91         entry_title = SubElement(entry, "title")
92         entry_title.text = row.page_title
93         entry.append(Element("link", rel="alternate", href="https://www.winterrodeln.org/wiki/{0}".format(page_title_url), type="text/html", hreflang="de"))
94         entry_id = SubElement(entry, "id")
95         entry_id.text = "https://www.winterrodeln.org/wiki/{0}#{1}".format(page_title_url, row.id)
96         entry_updated = SubElement(entry, "updated")
97         entry_updated.text = row.date_entry.isoformat() + "+01:00"
98         if last_updated is None: last_updated = row.date_entry
99         # entry_summary = SubElement(entry, "summary")
100         # entry_summary.text = str(condition)
101         entry_content = SubElement(entry, "content")
102         entry_content.attrib["type"] = "xhtml"
103         entry_content_div = SubElement(entry_content, "div")
104         entry_content_div.attrib["xmlns"] = "http://www.w3.org/1999/xhtml"
105         entry_content_ul = SubElement(entry_content_div, "ul")
106         if not row.date_report is None:
107             entry_content_date = SubElement(entry_content_ul, "li")
108             entry_content_date.text = "Bericht für " + row.date_report.isoformat()
109         if not row.condition is None:
110             entry_content_condition = SubElement(entry_content_ul, "li")
111             entry_content_condition.text = "Schneelage: " + {1: 'Sehr gut', 2: 'Gut', 3: 'Mittelmäßig', 4: 'Schlecht', 5: 'Geht nicht'}[row.condition]
112         entry_content_description = SubElement(entry_content_ul, "li")
113         entry_content_description.text = row.description
114         entry_author = SubElement(entry, "author")
115         entry_author_name = SubElement(entry_author, "name")
116         if row.author_name is None or len(row.author_name.strip()) == 0:
117             entry_author_name.text = "Anonymous user"
118         else:
119             entry_author_name.text = row.author_name
120         if not row.lon is None and not row.lat is None:
121             entry_geo = SubElement(entry, "georss:point")
122             entry_geo.text = "{lat} {lon}".format(lat=row.lat, lon=row.lon)
123         entry_wrreport = SubElement(entry, "wr:report")
124         entry_wrreport.attrib['report_id'] = str(row.id)
125         entry_wrreport.attrib['page_id'] = str(row.page_id)
126         entry_wrreport.attrib['page_title'] = row.page_title
127         entry_wrreport.attrib['date_report'] = str(row.date_report)
128         entry_wrreport.attrib['date_entry'] = str(row.date_entry)
129         entry_wrreport.attrib['condition'] = "0" if row.condition is None else str(row.condition)
130         entry_wrreport.attrib['author_name'] = row.author_name
131         entry_wrreport.attrib['author_username'] = "" if row.author_userid is None else row.author_username
132         entry_wrreport.text = row.description
133
134     if last_updated is None:
135         last_updated = datetime.datetime.now()
136     feed_updated.text = last_updated.isoformat() + "+01:00"
137
138     return b'<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)