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]:
47 class SledrunWikiTextToJsonBot(
52 AutomaticTWSummaryBot,
54 def treat_page(self) -> None:
55 """Load the given page, do some changes, and save it."""
56 wikitext_content_model = 'wikitext'
57 if self.current_page.content_model != wikitext_content_model:
58 warning(f"The content model of {self.current_page.title()} is {self.current_page.content_model} "
59 f"instead of {wikitext_content_model}.")
62 wikicode = mwparserfromhell.parse(self.current_page.text)
63 wikilink_list = wikicode.filter_wikilinks()
64 category_sledrun = 'Kategorie:Rodelbahn'
65 if sum(1 for c in wikilink_list if c.title == category_sledrun) == 0:
66 warning(f'The page {self.current_page.title()} does not have category {category_sledrun}.')
69 sledrun_json_page = Page(self.site, self.current_page.title() + '/Rodelbahn.json')
70 if sledrun_json_page.exists():
71 warning(f"{sledrun_json_page.title()} already exists, skipping {self.current_page.title()}.")
74 map_json_page = Page(self.site, self.current_page.title() + '/Landkarte.json')
75 if map_json_page.exists():
76 warning(f"{map_json_page.title()} already exists, skipping {self.current_page.title()}.")
80 v = wikicode.filter_tags(matches='wrmap')
82 map_json = parse_wrmap(str(v[0]))
85 "name": self.current_page.title(),
87 "entry_under_construction": sum(1 for c in wikilink_list if c.text == 'Kategorie:In Arbeit') > 0,
90 for v in wikicode.get_sections(levels=[2], matches='Allgemeines'):
91 for w in v.ifilter_text(recursive=False):
94 sledrun_json["description"] = str(x)
98 rbb_list = wikicode.filter_templates(recursive=False, matches=lambda t: t.name.strip() == 'Rodelbahnbox')
99 if len(rbb_list) == 1:
100 rbb = rodelbahnbox_from_template(rbb_list[0])
103 image_page = Page(self.site, v, ns=BuiltinNamespace.FILE)
104 if not image_page.exists():
105 warning(f"{image_page.title()} does not exist.")
106 sledrun_json['image'] = v
110 sledrun_json['length'] = v
112 v = rbb['Schwierigkeit']
114 sledrun_json['difficulty'] = difficulty_german_to_str(v)
118 sledrun_json['avalanches'] = avalanches_german_to_str(v)
120 v, w = rbb['Betreiber']
122 sledrun_json['has_operator'] = v
124 sledrun_json['operator'] = w
126 v = rbb['Aufstieg möglich']
128 sledrun_json['walkup_possible'] = v
130 v, w = rbb['Aufstieg getrennt']
132 sledrun_json['walkup_separate'] = tristate_german_to_str(v)
134 sledrun_json['walkup_comment'] = w # TODO
138 sledrun_json['walkup_time'] = v
140 v, w = rbb['Beleuchtungsanlage']
142 sledrun_json['nightlight_possible'] = tristate_german_to_str(v)
144 sledrun_json['nightlight_description'] = w
146 v = rbb['Rodelverleih']
148 sledrun_json['sled_rental_direct'] = v != []
149 sledrun_json['sled_rental_description'] = opt_str_opt_comment_enum_to_str(v)
151 v = rbb['In Übersichtskarte']
153 sledrun_json['show_in_overview'] = v
157 sledrun_json['forum_id'] = v
161 sledrun_json['position'] = lonlat_to_json(v)
163 v = lonlat_ele_to_json(rbb['Position oben'], rbb['Höhe oben'])
165 sledrun_json['top'] = v
167 v = lonlat_ele_to_json(rbb['Position unten'], rbb['Höhe unten'])
169 sledrun_json['bottom'] = v
171 v = rbb['Telefonauskunft']
173 sledrun_json['info_phone'] = [{'phone': p, 'name': n} for p, n in v]
175 v = rbb['Öffentliche Anreise']
177 sledrun_json['public_transport'] = public_transport_german_to_str(v)
179 for v in wikicode.get_sections(levels=[2], matches='Anreise mit öffentlichen Verkehrsmitteln',
180 include_headings=False):
181 w = next((w for w in v.nodes if isinstance(w, Tag) and w.wiki_markup == '*'), None)
183 x = str(Wikicode(v.nodes[:v.nodes.index(w)])).strip()
185 sledrun_json["public_transport_description"] = str(x)
189 if isinstance(w, Template):
190 if w.name == 'Haltestelle':
196 y['municipality'] = str(z)
199 y['name_local'] = str(z)
200 za = str_or_none(w.get(3, None))
201 zb = str_or_none(w.get(4, None))
202 z = lonlat_ele_to_json(opt_lonlat_from_str(za), opt_uint_from_str(zb))
208 sledrun_json['public_transport_stops'] = x
211 for v in wikicode.get_sections(levels=[2], matches='Anreise mit dem Auto'):
212 for w in v.ifilter_text(recursive=False):
215 sledrun_json["car_description"] = str(x)
220 for v in wikicode.get_sections(levels=[2], matches='Allgemeines'):
224 if isinstance(w, Tag) and str(w) == "'''Siehe auch'''":
229 if isinstance(w, ExternalLink):
230 link = {'url': w.url}
231 if w.title is not None:
232 link['text'] = w.title
234 elif isinstance(w, (Text, Tag)) and str(w).strip() in ['', '*', ':']:
240 sledrun_json['see_also'] = x
242 sledrun_json['allow_reports'] = True
244 text = create_sledrun_wiki(sledrun_json, map_json)
245 summary = 'Rodelbahnbeschreibung nach Konvertierung nach und von JSON.'
246 self.put_current(text, summary=summary)
249 def main(*args: str) -> None:
250 local_args = pywikibot.handle_args(args)
251 gen_factory = pagegenerators.GeneratorFactory()
252 gen_factory.handle_args(local_args)
253 gen = gen_factory.getCombinedGenerator(preload=True)
255 bot = SledrunWikiTextToJsonBot(generator=gen)
258 pywikibot.bot.suggest_help(missing_generator=True)
261 if __name__ == '__main__':