]> ToastFreeware Gitweb - philipp/winterrodeln/wrpylib.git/blob - bots/update_sledrun_json_from_wikitext_gastronomy.py
6f3619d63e66b136f7cd9197a79278b1ba1916e0
[philipp/winterrodeln/wrpylib.git] / bots / update_sledrun_json_from_wikitext_gastronomy.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, wikilink_to_json, \
42     external_link_to_json
43
44 docuReplacements = {'&params;': pagegenerators.parameterHelp}
45
46
47 class UpdateSledrunJsonFromWikiText(
48     SingleSiteBot,
49     ConfigParserBot,
50     ExistingPageBot,
51     NoRedirectPageBot,
52     AutomaticTWSummaryBot,
53 ):
54     def setup(self) -> None:
55         schema = Page(self.site, 'Winterrodeln:Datenschema/Rodelbahn/V1.json')
56         assert schema.content_model == 'json'
57         self.sledrun_schema = json.loads(schema.text)
58
59     def treat_page(self) -> None:
60         """Load the given page, do some changes, and save it."""
61         wikitext_content_model = 'wikitext'
62         if self.current_page.content_model != wikitext_content_model:
63             warning(f"The content model of {self.current_page.title()} is {self.current_page.content_model} "
64                     f"instead of {wikitext_content_model}.")
65             return
66
67         wikicode = mwparserfromhell.parse(self.current_page.text)
68
69         sledrun_json_page = Page(self.site, self.current_page.title() + '/Rodelbahn.json')
70         if not sledrun_json_page.exists():
71             return
72         sledrun_json = json.loads(sledrun_json_page.text)
73         sledrun_json_orig = json.loads(sledrun_json_page.text)
74         sledrun_json_orig_text = json.dumps(sledrun_json_orig, ensure_ascii=False, indent=4)
75
76         for v in wikicode.get_sections(levels=[2], matches='Allgemeines'):
77             def _gastronomy(value: str):
78                 gastronomy = []
79                 line_iter = io.StringIO(value)
80                 line = next(line_iter, None)
81                 while line is not None and line.rstrip() != "* '''Hütten''':":
82                     line = next(line_iter, None)
83                 if line is None:
84                     return gastronomy
85                 while line is not None:
86                     line = next(line_iter, None)
87                     if line is not None:
88                         if line.startswith('** '):
89                             g = {}
90                             wiki = mwparserfromhell.parse(line)
91                             wiki_link = next(wiki.ifilter_wikilinks(), None)
92                             if isinstance(wiki_link, Wikilink):
93                                 g['wr_page'] = wikilink_to_json(wiki_link)
94                             ext_link = next(wiki.ifilter_external_links(), None)
95                             if isinstance(ext_link, ExternalLink):
96                                 g['weblink'] = external_link_to_json(ext_link)
97                             remaining = str(Wikicode(n for n in wiki.nodes
98                                                      if isinstance(n, (Text, Tag)) and str(n).strip() != '*')).strip()
99                             match = re.match(r'(.*)\((.+)\)', remaining)
100                             if match:
101                                 name, note = match.groups()
102                                 name = name.strip()
103                                 note = note.strip()
104                                 if len(name) > 0:
105                                     g['name'] = name
106                                 if len(note) > 0:
107                                     g['note'] = note
108                             elif len(remaining) > 0 and remaining != '...':
109                                 g['name'] = remaining
110                             if len(g) != 0:
111                                 gastronomy.append(g)
112                         else:
113                             break
114                 return gastronomy
115
116             w = _gastronomy(str(v))
117             if len(w) > 0:
118                 sledrun_json['gastronomy'] = w
119
120         jsonschema.validate(instance=sledrun_json, schema=self.sledrun_schema)
121         sledrun_json_ordered = order_json_keys(sledrun_json, self.sledrun_schema)
122         assert sledrun_json_ordered == sledrun_json
123         if sledrun_json == sledrun_json_orig:
124             return
125         sledrun_json_text = json.dumps(sledrun_json_ordered, ensure_ascii=False, indent=4)
126         summary = 'Gastronomie Information im Rodelbahn JSON aktualisiert vom Wikitext.'
127         self.userPut(sledrun_json_page, sledrun_json_orig_text, sledrun_json_text, summary=summary, contentmodel='json')
128
129
130 def main(*args: str) -> None:
131     local_args = pywikibot.handle_args(args)
132     gen_factory = pagegenerators.GeneratorFactory()
133     gen_factory.handle_args(local_args)
134     gen = gen_factory.getCombinedGenerator(preload=True)
135     if gen:
136         bot = UpdateSledrunJsonFromWikiText(generator=gen)
137         bot.run()
138     else:
139         pywikibot.bot.suggest_help(missing_generator=True)
140
141
142 if __name__ == '__main__':
143     main()