From b6953cf52f1186770b7b03eacf07eb9d780edd81 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Fri, 29 Sep 2023 14:17:56 +0100 Subject: [PATCH] WIP --- dab_mechanic/mediawiki_api.py | 39 ++++++++++++-- dab_mechanic/wikipedia.py | 4 +- templates/article.html | 2 +- templates/index.html | 14 +++++ templates/navbar.html | 8 +-- templates/preview.html | 3 ++ web_view.py | 99 ++++++++++++++++++++++++++++------- 7 files changed, 135 insertions(+), 34 deletions(-) diff --git a/dab_mechanic/mediawiki_api.py b/dab_mechanic/mediawiki_api.py index f681af3..265cb73 100644 --- a/dab_mechanic/mediawiki_api.py +++ b/dab_mechanic/mediawiki_api.py @@ -30,19 +30,32 @@ def call(params: dict[str, str | int]) -> dict[str, Any]: return data.json() -def get_content(title: str) -> str: +def article_exists(title: str) -> bool: + """Get article text.""" + params: dict[str, str | int] = { + "action": "query", + "format": "json", + "formatversion": 2, + "titles": title, + } + return not call(params)["query"]["pages"][0].get("missing") + + +def get_content(title: str) -> tuple[str, int]: """Get article text.""" params: dict[str, str | int] = { "action": "query", "format": "json", "formatversion": 2, "prop": "revisions|info", - "rvprop": "content|timestamp", + "rvprop": "content|timestamp|ids", "titles": title, } data = call(params) - rev: str = data["query"]["pages"][0]["revisions"][0]["content"] - return rev + rev = data["query"]["pages"][0]["revisions"][0] + content: str = rev["content"] + revid: int = int(rev["revid"]) + return content, revid def compare(title: str, new_text: str) -> str: @@ -58,3 +71,21 @@ def compare(title: str, new_text: str) -> str: } diff: str = call(params)["compare"]["body"] return diff + + +def edit_page( + title: str, text: str, summary: str, baserevid: str, token: str +) -> dict[str, str | int]: + """Edit a page on Wikipedia.""" + params: dict[str, str | int] = { + "format": "json", + "formatversion": 2, + "action": "edit", + "title": title, + "text": text, + "baserevid": baserevid, + "token": token, + "summary": summary, + } + edit: str = call(params)["edit"] + return edit diff --git a/dab_mechanic/wikipedia.py b/dab_mechanic/wikipedia.py index 96eb110..fecf7f2 100644 --- a/dab_mechanic/wikipedia.py +++ b/dab_mechanic/wikipedia.py @@ -163,9 +163,9 @@ class Article: self.parse: Optional[dict[str, Any]] = None self.dab_html: dict[str, str] = {} - def save_endpoint(self) -> str: + def preview_endpoint(self) -> str: """Endpoint for saving changes.""" - href: str = flask.url_for("save", enwiki=self.enwiki.replace(" ", "_")) + href: str = flask.url_for("preview", enwiki=self.enwiki.replace(" ", "_")) return href def load(self) -> None: diff --git a/templates/article.html b/templates/article.html index 87680b0..eb1e62d 100644 --- a/templates/article.html +++ b/templates/article.html @@ -53,7 +53,7 @@ a.new { color: red; }

{{ article.enwiki }}

-
+ diff --git a/templates/index.html b/templates/index.html index 1758d8e..d6d6ca3 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,7 +1,21 @@ {% extends "base.html" %} +{% block title %}DAB Mechanic{% endblock %} + {% block content %}
+ + + article title: + + + + + {% if title and not exists %} +

No article titled "{{ title }}" found in Wikipedia.

+ {% endif %} + +
    {% for enwiki, count in articles %}
  1. diff --git a/templates/navbar.html b/templates/navbar.html index 9ce6f07..0b52925 100644 --- a/templates/navbar.html +++ b/templates/navbar.html @@ -15,13 +15,7 @@ Dab Mechanic diff --git a/templates/preview.html b/templates/preview.html index 68fa693..cd4bb3a 100644 --- a/templates/preview.html +++ b/templates/preview.html @@ -30,7 +30,10 @@ +
    + +
    diff --git a/web_view.py b/web_view.py index cfdff71..aa962bc 100755 --- a/web_view.py +++ b/web_view.py @@ -5,6 +5,7 @@ import json import re from typing import Optional, TypedDict import mwparserfromhell +from pprint import pprint import flask import lxml.html @@ -65,13 +66,25 @@ def parse_articles_with_dab_links(root: lxml.html.Element) -> list[tuple[str, in @app.route("/") def index(): + title = flask.request.args.get("title") + exists = None + if title: + title = title.strip() + exists = mediawiki_api.article_exists(title) + if exists: + return flask.redirect( + flask.url_for("article_page", enwiki=title.replace(" ", "_")) + ) + r = requests.get(awdl_url, params={"limit": 100}) root = lxml.html.fromstring(r.content) articles = parse_articles_with_dab_links(root) # articles = [line[:-1] for line in open("article_list")] - return flask.render_template("index.html", articles=articles) + return flask.render_template( + "index.html", title=title, exists=exists, articles=articles, + ) class Edit(TypedDict): @@ -82,7 +95,7 @@ class Edit(TypedDict): title: str -def apply_edits(article_text: str, edits: list[Edit]) -> str: +def old_apply_edits(article_text: str, edits: list[Edit]) -> str: """Apply edits to article text.""" def escape(s: str) -> str: @@ -114,49 +127,92 @@ def build_edit_summary(edits: list[Edit]) -> str: return f"Disambiguate {titles} using [[User:Edward/Dab mechanic]]" -def get_links(wikicode, edits): + +def get_links(wikicode, dab_links): + edits = [edit for edit in dab_links if edit.get("title")] + dab_titles = {dab["link_to"] for dab in edits} return [ link for link in wikicode.filter_wikilinks() if str(link.title) in dab_titles ] -@app.route("/preview/", methods=["POST"]) -def preview(enwiki: str) -> Response | str: - """Save edits to article.""" - enwiki = enwiki.replace("_", " ") - - dab_links = json.loads(flask.request.form["edits"]) - edits = [edit for edit in dab_links if edit.get("title")] - - edit_summary = build_edit_summary(edits) - # return flask.jsonify(edits=dab_links, edit_summary=edit_summary) - - text = mediawiki_api.get_content(enwiki) +def apply_edits(text, dab_links): wikicode = mwparserfromhell.parse(text) links = get_links(wikicode, dab_links) + if len(links) != len(dab_links): + print("links:", len(links)) + print("dab_links:", len(dab_links)) + print("dab_links:", dab_links) assert len(links) == len(dab_links) for wikilink, edit in zip(links, dab_links): - print(edit, wikilink) if not edit.get("title"): continue if not wikilink.text: wikilink.text = wikilink.title wikilink.title = edit["title"] - diff = mediawiki_api.compare(enwiki, str(wikicode)) + return str(wikicode) + + +@app.route("/preview/", methods=["POST"]) +def preview(enwiki: str) -> Response | str: + """Preview article edits.""" + enwiki = enwiki.replace("_", " ") + + dab_links = json.loads(flask.request.form["edits"]) + dab_links = [link for link in dab_links if "title" in link] + cur_text, baserevid = mediawiki_api.get_content(enwiki) + + text = apply_edits(cur_text, dab_links) + diff = mediawiki_api.compare(enwiki, text) return flask.render_template( - "peview.html", - edit_summary=edit_summary, + "preview.html", + edit_summary=build_edit_summary(dab_links), title=enwiki, edits=dab_links, - # text=str(wikicode), diff=diff, ) +def do_save(enwiki: str): + """Update page on Wikipedia.""" + dab_links = json.loads(flask.request.form["edits"]) + dab_links = [link for link in dab_links if "title" in link] + + cur_text, baserevid = mediawiki_api.get_content(enwiki) + + new_text = apply_edits(cur_text, dab_links) + token = wikidata_oauth.get_token() + + summary = build_edit_summary(dab_links) + print(summary) + + edit = mediawiki_api.edit_page( + title=enwiki, + text=new_text, + summary=summary, + baserevid=baserevid, + token=token, + ) + + return edit + + +@app.route("/save/", methods=["GET", "POST"]) +def save(enwiki: str) -> Response | str: + """Save edits to article.""" + enwiki_norm = enwiki.replace("_", " ") + + if flask.request.method == "GET": + return flask.render_template("edit_saved.html", title=enwiki_norm) + + do_save(enwiki_norm) + return flask.redirect(flask.url_for(flask.request.endpoint, enwiki=enwiki)) + + def redirect_if_needed(enwiki: str) -> Optional[Response]: """Check if there are spaces in the article name and redirect.""" return ( @@ -175,6 +231,9 @@ def article_page(enwiki: str) -> Response: if redirect: return redirect + if "owner_key" not in flask.session: + return flask.render_template("login_needed.html") + article = wikipedia.Article(enwiki) article.load() article.process_links()