diff --git a/discord_rss_bot/extensions/hoyolab.py b/discord_rss_bot/extensions/hoyolab.py index f2044dc..0f1abb3 100644 --- a/discord_rss_bot/extensions/hoyolab.py +++ b/discord_rss_bot/extensions/hoyolab.py @@ -16,7 +16,6 @@ import contextlib import json import logging import re -import time from typing import TYPE_CHECKING from typing import ClassVar from typing import cast @@ -103,36 +102,6 @@ def fetch_post(post_id: str) -> JsonObject | None: http_ok: int = 200 -# --------------------------------------------------------------------------- -# In-memory cache for Hoyolab post data. -# Key: post_id (str) -# Value: tuple of (JsonObject | None, expiry_timestamp) -# -# Prevents redundant API calls when the same post is processed by both -# ``process_entry()`` and ``modify_webhook()`` within a short timeframe. -# --------------------------------------------------------------------------- -_POST_CACHE: dict[str, tuple[JsonObject | None, float]] = {} - -#: Cache TTL in seconds. Entries older than this are re-fetched. -_CACHE_TTL_SECONDS: int = 300 # 5 minutes - - -def _cached_fetch_post(post_id: str) -> JsonObject | None: - """Return cached post data if fresh, otherwise fetch and cache.""" - now: float = time.time() - if post_id in _POST_CACHE: - cached_data, expiry = _POST_CACHE[post_id] - if now < expiry: - logger.debug("Cache hit for Hoyolab post %s", post_id) - return cached_data - logger.debug("Cache expired for Hoyolab post %s", post_id) - - # Cache miss or expired — fetch fresh data. - post_data: JsonObject | None = fetch_post(post_id) - _POST_CACHE[post_id] = (post_data, now + _CACHE_TTL_SECONDS) - return post_data - - def _as_json_object(value: JsonValue) -> JsonObject: return cast("JsonObject", value) if isinstance(value, dict) else {} @@ -179,7 +148,7 @@ class HoyolabExtension(FeedExtension): if not post_id: return {} - post_data: JsonObject | None = _cached_fetch_post(post_id) + post_data: JsonObject | None = fetch_post(post_id) if not post_data: return {} @@ -233,7 +202,7 @@ class HoyolabExtension(FeedExtension): if not post_id: return webhook - post_data: JsonObject | None = _cached_fetch_post(post_id) + post_data: JsonObject | None = fetch_post(post_id) if not post_data: return webhook diff --git a/discord_rss_bot/feeds.py b/discord_rss_bot/feeds.py index 6de7b0a..e91d097 100644 --- a/discord_rss_bot/feeds.py +++ b/discord_rss_bot/feeds.py @@ -56,6 +56,9 @@ from discord_rss_bot.custom_message import replace_tags_in_embed from discord_rss_bot.custom_message import replace_tags_in_text_message from discord_rss_bot.extensions import auto_enable_extensions_for_feed from discord_rss_bot.extensions import run_modify_webhook +from discord_rss_bot.extensions.steam import extract_app_id as steam_extract_app_id +from discord_rss_bot.extensions.steam import get_icon_file_for_app as steam_get_icon_file +from discord_rss_bot.extensions.steam import is_steam_url from discord_rss_bot.filter.evaluator import get_entry_filter_decision_from_reader from discord_rss_bot.is_url_valid import is_url_valid from discord_rss_bot.settings import default_custom_embed @@ -1762,7 +1765,7 @@ def create_components_v2_webhook( ) -def create_embed_webhook( # ruff:ignore[complex-structure, too-many-branches] +def create_embed_webhook( # ruff:ignore[complex-structure, too-many-branches, too-many-statements] webhook_url: str, entry: Entry, reader: Reader, @@ -1839,6 +1842,20 @@ def create_embed_webhook( # ruff:ignore[complex-structure, too-many-branches] if custom_embed.thumbnail_url: discord_embed.set_thumbnail(url=custom_embed.thumbnail_url) + # Steam feed: override thumbnail with the game's capsule image when enabled. + steam_thumbnail_file: WebhookFile | None = None + if custom_embed.show_steam_game_icon_in_thumbnail and is_steam_url(feed.url or ""): + app_id: str | None = steam_extract_app_id(feed.url) or steam_extract_app_id(str(entry.link or "")) + if app_id: + icon_file: WebhookFile | None = steam_get_icon_file(app_id) + if icon_file: + steam_thumbnail_file = icon_file + discord_embed.set_thumbnail(url=f"attachment://{icon_file.filename}") + else: + discord_embed.set_thumbnail( + url=f"https://cdn.cloudflare.steamstatic.com/steam/apps/{app_id}/capsule_sm_120.jpg", + ) + if custom_embed.image_url: discord_embed.set_image(url=custom_embed.image_url) @@ -1851,6 +1868,9 @@ def create_embed_webhook( # ruff:ignore[complex-structure, too-many-branches] if custom_embed.footer_icon_url and not custom_embed.footer_text: discord_embed.set_footer(text="-", icon_url=custom_embed.footer_icon_url) + if steam_thumbnail_file: + webhook.add_file(file=steam_thumbnail_file.content, filename=steam_thumbnail_file.filename) + webhook.add_embed(discord_embed) return webhook