From 2167528f1905343e1b903a4419d65d468d6c1963 Mon Sep 17 00:00:00 2001 From: Kumi Date: Thu, 5 Dec 2024 17:45:47 +0100 Subject: [PATCH] feat: Add badge support to wiki articles Fetches and displays badges for articles using the MediaWiki API. Updates templates to show badges as icons linking to detailed info. Adds CSS styling for badge presentation in the article view. Enhances user experience by providing additional context through quick-access badge information. Fixes #21. --- src/wikimore/app.py | 61 ++++++++++++++++++++++++++++- src/wikimore/static/css/style.css | 4 ++ src/wikimore/templates/article.html | 13 +++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/wikimore/app.py b/src/wikimore/app.py index b11eca5..321ecd2 100644 --- a/src/wikimore/app.py +++ b/src/wikimore/app.py @@ -169,6 +169,7 @@ else: "ar", ] + def langsort(input: list[dict], key: str = "lang") -> list[dict]: """Sorting of language data. @@ -199,12 +200,17 @@ def langsort(input: list[dict], key: str = "lang") -> list[dict]: return output + logger.debug("Initialized language sort order") -app_languages = [{"lang": lang, "name": data["name"]} for lang, data in app.languages.items()] +app_languages = [ + {"lang": lang, "name": data["name"]} for lang, data in app.languages.items() +] app_languages = langsort(app_languages) -app.languages = {lang: app.languages[lang] for lang in [lang["lang"] for lang in app_languages]} +app.languages = { + lang: app.languages[lang] for lang in [lang["lang"] for lang in app_languages] +} def render_template(*args, **kwargs) -> Text: @@ -393,6 +399,56 @@ def wiki_article( logger.debug(f"Request URL: {api_request.full_url}") + # Use the MediaWiki API to fetch any badges for the article + api_request_badges = urllib.request.Request( + f"{base_url}/w/api.php?action=query&format=json&titles={escape(quote(title.replace(' ', '_')), True)}&prop=pageprops", + headers=HEADERS, + ) + + badges = [] + + with urllib.request.urlopen(api_request_badges) as response: + logger.debug(f"Tried to fetch badges from {api_request_badges.full_url}") + data = json.loads(response.read().decode()) + page = data["query"]["pages"].popitem()[1] + props = page.get("pageprops", {}) + + for prop in props: + if prop.startswith("wikibase-badge-"): + try: + badge_id = prop.replace("wikibase-badge-", "") + + badge_request = urllib.request.Request( + f"https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&ids={badge_id}&languages={lang}", + headers=HEADERS, + ) + + with urllib.request.urlopen(badge_request) as badge_response: + logger.debug( + f"Tried to fetch badge {badge_id} from {badge_request.full_url}" + ) + + badge_data = json.loads(badge_response.read().decode()) + + badge = badge_data["entities"][badge_id]["labels"][lang][ + "value" + ] + badge_image = badge_data["entities"][badge_id]["claims"]["P18"][ + 0 + ]["mainsnak"]["datavalue"]["value"] + badges.append( + { + "title": badge, + "url": f"https://www.wikidata.org/wiki/{badge_id}", + "image": get_proxy_url( + f"https://commons.wikimedia.org/wiki/Special:Redirect/file/{badge_image}" + ), + } + ) + + except Exception as e: + logger.error(f"Error fetching badge {prop}: {e}") + # Use the MediaWiki API to fetch interwiki links api_request_interwiki = urllib.request.Request( f"{base_url}/w/api.php?action=query&format=json&titles={escape(quote(title.replace(' ', '_')), True)}&prop=langlinks&lllimit=500", @@ -622,6 +678,7 @@ def wiki_article( rtl=rtl, license=license, interwiki=interwiki, + badges=badges, ) diff --git a/src/wikimore/static/css/style.css b/src/wikimore/static/css/style.css index 1ab7b5b..387f06d 100644 --- a/src/wikimore/static/css/style.css +++ b/src/wikimore/static/css/style.css @@ -1315,4 +1315,8 @@ Currently blocked by implementation of comments retrieval in the backend .language-selector-link:active, .language-selector-link:focus { outline: none; +} + +.badge { + max-height: 1em; } \ No newline at end of file diff --git a/src/wikimore/templates/article.html b/src/wikimore/templates/article.html index 48c43c3..c41f413 100644 --- a/src/wikimore/templates/article.html +++ b/src/wikimore/templates/article.html @@ -1,7 +1,18 @@ {% extends "base.html" %} {% block content %} -

{{ title }}

+

+ {{ title }} + {% if badges %} + + {% for badge in badges %} + + {{ badge.title }} + + {% endfor %} + + {% endif %} +

{% if interwiki %}