User:Uo4tie/bot/wikitext_parser.py

From OpenStreetMap Wiki
Jump to navigation Jump to search

Python code to copy the informations in the sidebar of the Key:* and Tag:* description pages to the data item via MediaWiki Action API. See the Not copied ... categories in Category:Data item issues.

Copyright (C) 2026 uo4tie

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.



#! /usr/bin/python3
"""
    adapted from MediaWiki API Demos at https://www.mediawiki.org/wiki/API:Categorymembers under MIT License; assisted by AI
    
    # SPDX-License-Identifier:  AGPL-3.0-or-later

"""

def extract_param(data, template_name, param_name):
    text = data.get("parse", {}).get("wikitext", {}).get("*", "")

    # --- 1. Die gesuchte Vorlage inkl. Verschachtelung isolieren ---
    start = text.find("{{" + template_name)
    if start == -1:
        return None

    depth, i = 1, start + 2
    while i < len(text) and depth:
        if text.startswith("{{", i):
            depth += 1; i += 2
        elif text.startswith("}}", i):
            depth -= 1; i += 2
        else:
            i += 1
    body = text[start + 2 : i - 2]   # Inhalt zwischen {{ ... }}

    # --- 2. Body an Top-Level-Pipes '|' trennen (ignoriert | in {{...}}) ---
    parts, cur, depth, eq = [], "", 0, -1
    j = 0
    while j < len(body):
        if body.startswith("{{", j):
            depth += 1; cur += "{{"; j += 2
        elif body.startswith("}}", j):
            depth -= 1; cur += "}}"; j += 2
        else:
            ch = body[j]; j += 1
            if depth == 0 and ch == "|":
                parts.append((cur, eq)); cur, eq = "", -1
            else:
                if depth == 0 and ch == "=" and eq == -1:
                    eq = len(cur)      # erstes '=' auf oberster Ebene merken
                cur += ch
    parts.append((cur, eq))

    # --- 3. Gesuchten Parameter heraussuchen ---
    for value, eq in parts:
        if eq > -1 and value[:eq].strip().lower() == param_name.strip().lower():
            return value[eq + 1:].strip()
    return None
    
    
def get_param_for_page(page_title,template,param):
    
    import requests

    S = requests.Session()

    URL = "https://test.wiki.openstreetmap.org/w/api.php"
    
    PARAMS = {
        "action": "parse",
        "page": page_title,
        "prop": "wikitext",
        "format": "json"
    }

    R = S.get(url=URL, params=PARAMS)
    DATA = R.json()

    return extract_param(DATA, template, param)