]> ToastFreeware Gitweb - philipp/winterrodeln/wrpylib.git/blob - bots/update_sledrun_json_from_wikitext_gütesiegel.py
Fine-tune parsing of 'Tiroler Naturrodelbahn Gütesiegel'.
[philipp/winterrodeln/wrpylib.git] / bots / update_sledrun_json_from_wikitext_gütesiegel.py
1 #!/usr/bin/python
2 """
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.
5
6 Update a sledrun JSON page from a detail in a sledrun wikitext page.
7
8 The following generators and filters are supported:
9
10 &params;
11 """
12 import io
13 import json
14 import re
15 from itertools import takewhile, dropwhile
16 from typing import Optional
17
18 import jsonschema
19 import mwparserfromhell
20 from mwparserfromhell.nodes.extras import Parameter
21
22 import pywikibot
23 from mwparserfromhell.nodes import Tag, Text, ExternalLink, Template, Wikilink, Heading
24 from mwparserfromhell.wikicode import Wikicode
25 from pywikibot import pagegenerators, Page
26 from pywikibot.bot import (
27     AutomaticTWSummaryBot,
28     ConfigParserBot,
29     ExistingPageBot,
30     NoRedirectPageBot,
31     SingleSiteBot,
32 )
33 from pywikibot.logging import warning
34 from pywikibot.site._namespace import BuiltinNamespace
35 from wrpylib.json_tools import order_json_keys
36
37 from wrpylib.wrmwmarkup import create_sledrun_wiki, lonlat_to_json, lonlat_ele_to_json, parse_wrmap
38 from wrpylib.wrvalidators import rodelbahnbox_from_template, tristate_german_to_str, difficulty_german_to_str, \
39     avalanches_german_to_str, public_transport_german_to_str, opt_lonlat_from_str, \
40     opt_uint_from_str
41 from wrpylib.lib_sledrun_wikitext_to_json import optional_set, get_sledrun_description
42
43 docuReplacements = {'&params;': pagegenerators.parameterHelp}
44
45
46 class UpdateSledrunJsonFromWikiText(
47     SingleSiteBot,
48     ConfigParserBot,
49     ExistingPageBot,
50     NoRedirectPageBot,
51     AutomaticTWSummaryBot,
52 ):
53     def setup(self) -> None:
54         schema = Page(self.site, 'Winterrodeln:Datenschema/Rodelbahn/V1.json')
55         assert schema.content_model == 'json'
56         self.sledrun_schema = json.loads(schema.text)
57
58     def treat_page(self) -> None:
59         """Load the given page, do some changes, and save it."""
60         wikitext_content_model = 'wikitext'
61         if self.current_page.content_model != wikitext_content_model:
62             warning(f"The content model of {self.current_page.title()} is {self.current_page.content_model} "
63                     f"instead of {wikitext_content_model}.")
64             return
65
66         wikicode = mwparserfromhell.parse(self.current_page.text)
67
68         sledrun_json_page = Page(self.site, self.current_page.title() + '/Rodelbahn.json')
69         if not sledrun_json_page.exists():
70             return
71         sledrun_json = json.loads(sledrun_json_page.text)
72         sledrun_json_orig = json.loads(sledrun_json_page.text)
73         sledrun_json_orig_text = json.dumps(sledrun_json, ensure_ascii=False, indent=4)
74
75         def _tiroler_naturrodelbahn_guetesiegel(wikicode) -> Optional[dict]:
76             for gst in wikicode.filter_templates():
77                 if gst.name.strip() != 'Tiroler Naturrodelbahn Gütesiegel':
78                     continue
79                 gsj = {}
80                 keys = {
81                     'Anlagename': 'name',
82                     'Organisation': 'organization',
83                     'Erstverleihung': 'first_issued',
84                     'Verlängerung': 'valid_from',
85                     'Forum': 'forum_id',
86                     'Thread': 'thread_id',
87                 }
88                 numeric = ['first_issued', 'valid_from', 'forum_id', 'thread_id']
89                 for key, value in keys.items():
90                     if gst.has(key):
91                         v = gst.get(key).value.strip()
92                         if v != '':
93                             if value in numeric:
94                                 v = int(v)
95                             gsj[value] = v
96                 if len(gsj) > 0:
97                     return gsj
98
99         gsj = _tiroler_naturrodelbahn_guetesiegel(wikicode)
100
101         if gsj is None:
102             return
103
104         sledrun_json['tiroler_naturrodelbahn_gütesiegel'] = gsj
105
106         description_code = mwparserfromhell.parse(sledrun_json.get('description', ''))
107         for t in description_code.filter_templates():
108             # remove template from text
109             description_code.remove(t)
110             d = str(description_code)
111             d = re.sub(r'\n{2,}', r'\n\n', d)
112             sledrun_json['description'] = d
113
114         jsonschema.validate(instance=sledrun_json, schema=self.sledrun_schema)
115         sledrun_json_ordered = order_json_keys(sledrun_json, self.sledrun_schema)
116         assert sledrun_json_ordered == sledrun_json
117         sledrun_json_text = json.dumps(sledrun_json_ordered, ensure_ascii=False, indent=4)
118         if sledrun_json == sledrun_json_orig:
119             return
120         summary = 'Gütesiegel im Rodelbahn JSON aktualisiert vom Wikitext.'
121         self.userPut(sledrun_json_page, sledrun_json_orig_text, sledrun_json_text, summary=summary, contentmodel='json')
122
123
124 def main(*args: str) -> None:
125     local_args = pywikibot.handle_args(args)
126     gen_factory = pagegenerators.GeneratorFactory()
127     gen_factory.handle_args(local_args)
128     gen = gen_factory.getCombinedGenerator(preload=True)
129     if gen:
130         bot = UpdateSledrunJsonFromWikiText(generator=gen)
131         bot.run()
132     else:
133         pywikibot.bot.suggest_help(missing_generator=True)
134
135
136 if __name__ == '__main__':
137     main()