3 User script for pywikibot (https://gerrit.wikimedia.org/r/pywikibot/core.git), tested with version 6.6.1.
4 Put it in directory scripts/userscripts.
6 Create a sledrun JSON page from a sledrun wikitext page (including map).
8 The following generators and filters are supported:
13 from typing import Any, Optional
15 import mwparserfromhell
17 from mwparserfromhell.nodes import Tag, Text, ExternalLink, Template
18 from mwparserfromhell.wikicode import Wikicode
19 from pywikibot import pagegenerators, Page
20 from pywikibot.bot import (
21 AutomaticTWSummaryBot,
27 from pywikibot.logging import warning
28 from pywikibot.site._namespace import BuiltinNamespace
30 from wrpylib.wrmwmarkup import create_sledrun_wiki, lonlat_to_json, lonlat_ele_to_json, parse_wrmap
31 from wrpylib.wrvalidators import rodelbahnbox_from_template, tristate_german_to_str, difficulty_german_to_str, \
32 avalanches_german_to_str, public_transport_german_to_str, opt_str_opt_comment_enum_to_str, opt_lonlat_from_str, \
35 from pywikibot.site import Namespace
37 docuReplacements = {'¶ms;': pagegenerators.parameterHelp}
40 def str_or_none(value: Any) -> Optional[str]:
46 def template_to_json(value: Template) -> dict:
48 for p in value.params:
49 parameter.append({'value': str(p)})
51 'name': str(value.name),
52 'parameter': parameter
56 class SledrunWikiTextToJsonBot(
61 AutomaticTWSummaryBot,
63 def treat_page(self) -> None:
64 """Load the given page, do some changes, and save it."""
65 wikitext_content_model = 'wikitext'
66 if self.current_page.content_model != wikitext_content_model:
67 warning(f"The content model of {self.current_page.title()} is {self.current_page.content_model} "
68 f"instead of {wikitext_content_model}.")
71 wikicode = mwparserfromhell.parse(self.current_page.text)
72 wikilink_list = wikicode.filter_wikilinks()
73 category_sledrun = 'Kategorie:Rodelbahn'
74 if sum(1 for c in wikilink_list if c.title == category_sledrun) == 0:
75 warning(f'The page {self.current_page.title()} does not have category {category_sledrun}.')
78 sledrun_json_page = Page(self.site, self.current_page.title() + '/Rodelbahn.json')
79 if sledrun_json_page.exists():
80 warning(f"{sledrun_json_page.title()} already exists, skipping {self.current_page.title()}.")
83 map_json_page = Page(self.site, self.current_page.title() + '/Landkarte.json')
84 if map_json_page.exists():
85 warning(f"{map_json_page.title()} already exists, skipping {self.current_page.title()}.")
89 v = wikicode.filter_tags(matches='wrmap')
91 map_json = parse_wrmap(str(v[0]))
94 "name": self.current_page.title(),
96 "entry_under_construction": sum(1 for c in wikilink_list if c.text == 'Kategorie:In Arbeit') > 0,
99 for v in wikicode.get_sections(levels=[2], matches='Allgemeines'):
100 for w in v.ifilter_text(recursive=False):
103 sledrun_json["description"] = str(x)
107 rbb_list = wikicode.filter_templates(recursive=False, matches=lambda t: t.name.strip() == 'Rodelbahnbox')
108 if len(rbb_list) == 1:
109 rbb = rodelbahnbox_from_template(rbb_list[0])
112 image_page = Page(self.site, v, ns=BuiltinNamespace.FILE)
113 if not image_page.exists():
114 warning(f"{image_page.title()} does not exist.")
115 sledrun_json['image'] = v
119 sledrun_json['length'] = v
121 v = rbb['Schwierigkeit']
123 sledrun_json['difficulty'] = difficulty_german_to_str(v)
127 sledrun_json['avalanches'] = avalanches_german_to_str(v)
129 v, w = rbb['Betreiber']
131 sledrun_json['has_operator'] = v
133 sledrun_json['operator'] = w
135 v = rbb['Aufstieg möglich']
137 sledrun_json['walkup_possible'] = v
139 v, w = rbb['Aufstieg getrennt']
141 sledrun_json['walkup_separate'] = tristate_german_to_str(v)
143 sledrun_json['walkup_comment'] = w # TODO
147 sledrun_json['walkup_time'] = v
149 v, w = rbb['Beleuchtungsanlage']
151 sledrun_json['nightlight_possible'] = tristate_german_to_str(v)
153 sledrun_json['nightlight_description'] = w
155 v = rbb['Rodelverleih']
157 sledrun_json['sled_rental_direct'] = v != []
158 sledrun_json['sled_rental_description'] = opt_str_opt_comment_enum_to_str(v)
160 v = rbb['In Übersichtskarte']
162 sledrun_json['show_in_overview'] = v
166 sledrun_json['forum_id'] = v
170 sledrun_json['position'] = lonlat_to_json(v)
172 v = lonlat_ele_to_json(rbb['Position oben'], rbb['Höhe oben'])
174 sledrun_json['top'] = v
176 v = lonlat_ele_to_json(rbb['Position unten'], rbb['Höhe unten'])
178 sledrun_json['bottom'] = v
180 v = rbb['Telefonauskunft']
182 sledrun_json['info_phone'] = [{'phone': p, 'name': n} for p, n in v]
184 v = rbb['Öffentliche Anreise']
186 sledrun_json['public_transport'] = public_transport_german_to_str(v)
188 for v in wikicode.get_sections(levels=[2], matches='Anreise mit öffentlichen Verkehrsmitteln',
189 include_headings=False):
190 w = next((w for w in v.nodes if isinstance(w, Tag) and w.wiki_markup == '*'), None)
192 x = str(Wikicode(v.nodes[:v.nodes.index(w)])).strip()
194 sledrun_json["public_transport_description"] = str(x)
196 public_transport_stops = []
197 public_transport_lines = []
200 if isinstance(w, Template):
201 if w.name == 'Haltestelle':
203 public_transport_stops.append(ya)
207 ya['municipality'] = str(z)
210 ya['name_local'] = str(z)
211 za = str_or_none(w.get(3, None))
212 zb = str_or_none(w.get(4, None))
213 z = lonlat_ele_to_json(opt_lonlat_from_str(za), opt_uint_from_str(zb))
216 elif w.name in ["Fahrplan Abfahrtsmonitor VVT"]:
217 ya['monitor_template'] = template_to_json(w)
218 elif w.name in ["Fahrplan Hinfahrt VVT"]:
219 ya['route_arrival_template'] = template_to_json(w)
220 elif w.name in ["Fahrplan Rückfahrt VVT"]:
221 ya['route_departure_template'] = template_to_json(w)
222 elif w.name in ["Fahrplan Linie VVT"]:
224 public_transport_stops.append(ya)
227 'timetable_template': template_to_json(w),
229 public_transport_lines.append(y)
231 public_transport_stops.append(ya)
232 if len(public_transport_stops) > 0:
233 sledrun_json['public_transport_stops'] = public_transport_stops
234 if len(public_transport_lines) > 0:
235 sledrun_json['public_transport_lines'] = public_transport_lines
238 for v in wikicode.get_sections(levels=[2], matches='Anreise mit dem Auto'):
239 for w in v.ifilter_text(recursive=False):
242 sledrun_json["car_description"] = str(x)
247 for v in wikicode.get_sections(levels=[2], matches='Allgemeines'):
251 if isinstance(w, Tag) and str(w) == "'''Siehe auch'''":
256 if isinstance(w, ExternalLink):
257 link = {'url': w.url}
258 if w.title is not None:
259 link['text'] = w.title
261 elif isinstance(w, (Text, Tag)) and str(w).strip() in ['', '*', ':']:
267 sledrun_json['see_also'] = x
269 sledrun_json['allow_reports'] = True
271 text = create_sledrun_wiki(sledrun_json, map_json)
272 summary = 'Rodelbahnbeschreibung nach Konvertierung nach und von JSON.'
273 self.put_current(text, summary=summary)
276 def main(*args: str) -> None:
277 local_args = pywikibot.handle_args(args)
278 gen_factory = pagegenerators.GeneratorFactory()
279 gen_factory.handle_args(local_args)
280 gen = gen_factory.getCombinedGenerator(preload=True)
282 bot = SledrunWikiTextToJsonBot(generator=gen)
285 pywikibot.bot.suggest_help(missing_generator=True)
288 if __name__ == '__main__':