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.
This commit is contained in:
Kumi 2024-12-05 17:45:47 +01:00
parent 5bd90742b0
commit 2167528f19
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 75 additions and 3 deletions

View file

@ -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,
)

View file

@ -1316,3 +1316,7 @@ Currently blocked by implementation of comments retrieval in the backend
.language-selector-link:focus {
outline: none;
}
.badge {
max-height: 1em;
}

View file

@ -1,7 +1,18 @@
{% extends "base.html" %}
{% block content %}
<h1 class="title{% if rtl %} title-rtl{% endif %}">{{ title }}</h1>
<h1 class="title{% if rtl %} title-rtl{% endif %}">
{{ title }}
{% if badges %}
<span class="badges">
{% for badge in badges %}
<a href="{{ badge.url }}" class="badge" title="{{ badge.title }}">
<img src="{{ badge.image }}" alt="{{ badge.title }}">
</a>
{% endfor %}
</span>
{% endif %}
</h1>
{% if interwiki %}
<div class="language-selector">
<input type="checkbox" id="language-selector-toggle" class="language-selector-toggle">