Add Steam free games feed to FreeLoot
This commit is contained in:
@@ -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 asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -56,6 +56,7 @@ def _store_label_for_title(source_key: str) -> str:
|
|||||||
"gog": "GOG",
|
"gog": "GOG",
|
||||||
"google_play": "Google Play",
|
"google_play": "Google Play",
|
||||||
"apple_app_store": "l'App Store",
|
"apple_app_store": "l'App Store",
|
||||||
|
"steam": "Steam",
|
||||||
}
|
}
|
||||||
return labels.get(source_key, "la boutique")
|
return labels.get(source_key, "la boutique")
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ SOURCE_LOGO_URLS = {
|
|||||||
"gog": "https://www.gog.com/favicon.ico",
|
"gog": "https://www.gog.com/favicon.ico",
|
||||||
"google_play": "https://play.google.com/favicon.ico",
|
"google_play": "https://play.google.com/favicon.ico",
|
||||||
"apple_app_store": "https://www.apple.com/favicon.ico",
|
"apple_app_store": "https://www.apple.com/favicon.ico",
|
||||||
|
"steam": "https://store.steampowered.com/favicon.ico",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+18
-4
@@ -6,6 +6,8 @@ from html import unescape
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
FEED_URL = "https://feed.eikowagenknecht.com/lootscraper.xml"
|
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"}
|
ATOM_NS = {"atom": "http://www.w3.org/2005/Atom"}
|
||||||
|
|
||||||
SOURCES = [
|
SOURCES = [
|
||||||
@@ -16,6 +18,7 @@ SOURCES = [
|
|||||||
("gog", "GOG", "🎮"),
|
("gog", "GOG", "🎮"),
|
||||||
("google_play", "Google Play", "🤖"),
|
("google_play", "Google Play", "🤖"),
|
||||||
("apple_app_store", "Apple App Store", "🍎"),
|
("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"
|
return "google_play"
|
||||||
if "APPLE APP STORE" in title_upper:
|
if "APPLE APP STORE" in title_upper:
|
||||||
return "apple_app_store"
|
return "apple_app_store"
|
||||||
|
if "STEAM" in title_upper or "store.steampowered.com" in link_lower:
|
||||||
|
return "steam"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -51,6 +56,7 @@ def game_name_from_title(title: str) -> str:
|
|||||||
"GOG (Game, Always Free) - ",
|
"GOG (Game, Always Free) - ",
|
||||||
"Google Play (Game) - ",
|
"Google Play (Game) - ",
|
||||||
"Apple App Store (Game) - ",
|
"Apple App Store (Game) - ",
|
||||||
|
"Steam (Game, PC) - ",
|
||||||
):
|
):
|
||||||
if title.startswith(prefix):
|
if title.startswith(prefix):
|
||||||
return unescape(title[len(prefix) :].strip())
|
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
|
return raw if len(raw) > 0 and len(raw) < 200 else None
|
||||||
|
|
||||||
|
|
||||||
def fetch_feed() -> list[dict] | None:
|
def _fetch_single_feed(feed_url: str) -> list[dict]:
|
||||||
"""Récupère et parse le flux Atom, retourne une liste d'entrées brutes."""
|
"""Récupère et parse un flux Atom LootScraper."""
|
||||||
try:
|
try:
|
||||||
r = requests.get(FEED_URL, timeout=15)
|
r = requests.get(feed_url, timeout=15)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
root = ET.fromstring(r.content)
|
root = ET.fromstring(r.content)
|
||||||
entries = []
|
entries = []
|
||||||
@@ -168,7 +174,15 @@ def fetch_feed() -> list[dict] | None:
|
|||||||
})
|
})
|
||||||
return entries
|
return entries
|
||||||
except Exception:
|
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]:
|
def get_display_entries() -> list[dict]:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4">
|
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4">
|
||||||
<p class="text-gray-700 dark:text-gray-300">
|
<p class="text-gray-700 dark:text-gray-300">
|
||||||
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
|
||||||
<a href="https://feed.eikowagenknecht.com/lootscraper.xml" target="_blank" rel="noopener" class="text-amber-700 dark:text-amber-300 hover:underline">LootScraper</a>.
|
<a href="https://feed.eikowagenknecht.com/lootscraper.xml" target="_blank" rel="noopener" class="text-amber-700 dark:text-amber-300 hover:underline">LootScraper</a>.
|
||||||
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.
|
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.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user