diff --git a/discordbot/freeloot.py b/discordbot/freeloot.py index c3598d5..8e3a1f8 100644 --- a/discordbot/freeloot.py +++ b/discordbot/freeloot.py @@ -1,4 +1,4 @@ -# FreeLoot Discord : notifications depuis le feed LootScraper (jeux gratuits Epic, Amazon Prime, GOG, etc.) +# FreeLoot Discord : notifications depuis les flux LootScraper (Epic, Amazon Prime, GOG, Steam, etc.) import asyncio import logging @@ -56,6 +56,7 @@ def _store_label_for_title(source_key: str) -> str: "gog": "GOG", "google_play": "Google Play", "apple_app_store": "l'App Store", + "steam": "Steam", } return labels.get(source_key, "la boutique") @@ -69,6 +70,7 @@ SOURCE_LOGO_URLS = { "gog": "https://www.gog.com/favicon.ico", "google_play": "https://play.google.com/favicon.ico", "apple_app_store": "https://www.apple.com/favicon.ico", + "steam": "https://store.steampowered.com/favicon.ico", } diff --git a/freeloot_feed.py b/freeloot_feed.py index 721a913..6101e6f 100644 --- a/freeloot_feed.py +++ b/freeloot_feed.py @@ -6,6 +6,8 @@ from html import unescape import requests FEED_URL = "https://feed.eikowagenknecht.com/lootscraper.xml" +STEAM_FEED_URL = "https://feed.eikowagenknecht.com/lootscraper_steam_game.xml" +FEED_URLS = (FEED_URL, STEAM_FEED_URL) ATOM_NS = {"atom": "http://www.w3.org/2005/Atom"} SOURCES = [ @@ -16,6 +18,7 @@ SOURCES = [ ("gog", "GOG", "🎮"), ("google_play", "Google Play", "🤖"), ("apple_app_store", "Apple App Store", "🍎"), + ("steam", "Steam", "🎮"), ] @@ -37,6 +40,8 @@ def source_key_from_entry(title: str, link: str) -> str | None: return "google_play" if "APPLE APP STORE" in title_upper: return "apple_app_store" + if "STEAM" in title_upper or "store.steampowered.com" in link_lower: + return "steam" return None @@ -51,6 +56,7 @@ def game_name_from_title(title: str) -> str: "GOG (Game, Always Free) - ", "Google Play (Game) - ", "Apple App Store (Game) - ", + "Steam (Game, PC) - ", ): if title.startswith(prefix): return unescape(title[len(prefix) :].strip()) @@ -135,10 +141,10 @@ def extract_rating_from_content(content: str) -> str | None: return raw if len(raw) > 0 and len(raw) < 200 else None -def fetch_feed() -> list[dict] | None: - """Récupère et parse le flux Atom, retourne une liste d'entrées brutes.""" +def _fetch_single_feed(feed_url: str) -> list[dict]: + """Récupère et parse un flux Atom LootScraper.""" try: - r = requests.get(FEED_URL, timeout=15) + r = requests.get(feed_url, timeout=15) r.raise_for_status() root = ET.fromstring(r.content) entries = [] @@ -168,7 +174,15 @@ def fetch_feed() -> list[dict] | None: }) return entries except Exception: - return None + return [] + + +def fetch_feed() -> list[dict] | None: + """Récupère les flux LootScraper général et Steam.""" + entries = [] + for feed_url in FEED_URLS: + entries.extend(_fetch_single_feed(feed_url)) + return entries or None def get_display_entries() -> list[dict]: diff --git a/webapp/templates/freeloot.html b/webapp/templates/freeloot.html index 3a287b0..c7ff14b 100644 --- a/webapp/templates/freeloot.html +++ b/webapp/templates/freeloot.html @@ -11,7 +11,7 @@ {% endif %}

- Notifications des jeux gratuits (Epic Games, Amazon Prime, GOG, Google Play, Apple App Store) via le flux + Notifications des jeux gratuits (Epic Games, Amazon Prime, GOG, Steam, Google Play, Apple App Store) via les flux LootScraper. Choisissez le canal Discord et les types de loot à notifier (PC, Android, iOS selon la source). Le bot vérifie le flux environ toutes les 30 minutes.