1 """Creates an Atom-Feed for single or multiple winterrodeln sled reports.
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
9 https://www.winterrodeln.org/trac/wiki/UrlSchema
12 from xml.etree.ElementTree import Element, SubElement, tostring
13 from flask import url_for
14 from sqlalchemy import func, desc
17 class CreateFeedError(RuntimeError):
21 class RegionNotFoundError(CreateFeedError):
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."""
31 wrreport = db.metadata.tables['wrreport']
32 wrsledruncache = db.metadata.tables['wrsledruncache']
33 wrregion = db.metadata.tables['wrregion']
34 wrregioncache = db.metadata.tables['wrregioncache']
38 wrsledruncache.c.position_longitude.label('lon'),
39 wrsledruncache.c.position_latitude.label('lat')
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)). \
47 if page_title is not None:
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)))
69 # user wants to have all reports
71 result = db.session.connection().execute(sql)
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)
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))
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"
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
141 if last_updated is None:
142 last_updated = datetime.datetime.now()
143 feed_updated.text = last_updated.isoformat() + "+01:00"
145 return b'<?xml version="1.0" encoding="utf-8"?>\n' + tostring(feed)