game-advisor / source /APIs /metacritic_api.py
merligus's picture
Upload folder using huggingface_hub
f906754 verified
Raw
History Blame Contribute Delete
3.5 kB
from dotenv import load_dotenv
import os
import requests
from APIs.api_types import MetacriticType
from difflib import SequenceMatcher
from urllib.parse import quote
class Metacritic:
def __init__(self):
load_dotenv()
self.api_key = os.getenv("METACRITIC_API_KEY")
def _score_ratio(self, score_obj: dict):
score = score_obj.get("score", 0)
num = 0 if score is None else score
max = score_obj.get("max", 1)
den = 1 if max is None else max
return float(num) / float(den)
def search(self, game_name: str, max_n: int = 1) -> list[MetacriticType]:
"""
Searches for games by name and retrieves details.
Returns a list of MetacriticType objects.
"""
# Find name of the game in the Metacritic API
find_url = f"https://backend.metacritic.com/finder/metacritic/search/{quote(game_name)}/web?apiKey={self.api_key}&limit={max_n+5}&offset=0"
find_response = requests.get(find_url)
find_response.raise_for_status()
find_data = find_response.json()
# No result found
if not "data" in find_data:
return []
# Start the return array
metacritic_results = []
for item in find_data["data"]["items"]:
if item["type"] == "game-title":
# Match between names
name_ratio = SequenceMatcher(None, item["title"], game_name).ratio()
# Get game metadata
game_slug = item["slug"]
game_url = f"https://backend.metacritic.com/composer/metacritic/pages/games/{game_slug}/web?contentOnly=true"
game_response = requests.get(game_url)
game_response.raise_for_status()
game_data = game_response.json()
if not "components" in game_data or len(game_data["components"]) < 8:
continue
if not "data" in game_data["components"][0]:
continue
if not "data" in game_data["components"][6]:
continue
if not "data" in game_data["components"][8]:
continue
metadata = game_data["components"][0]["data"]["item"]
critics_score = self._score_ratio(game_data["components"][6]["data"]["item"])
user_score = self._score_ratio(game_data["components"][8]["data"]["item"])
metacritic_obj = MetacriticType(
name=metadata.get("title"),
release=metadata.get("releaseDate", ""),
developers=[company["name"] for company in metadata.get("production", {}).get("companies", []) if company["typeName"] == "Developer"],
publishers=[company["name"] for company in metadata.get("production", {}).get("companies", []) if company["typeName"] == "Publisher"],
genres=[genre["name"] for genre in metadata.get("genres", [])],
platforms=[platform["name"] for platform in metadata.get("platforms", [])],
metacritic_rating=critics_score,
user_rating=user_score,
)
metacritic_results.append((metacritic_obj, name_ratio))
# Sort by ratio of the name
sorted_data = sorted(metacritic_results, key=lambda x: x[1], reverse=True)
# Only return the max_n results
return [obj for obj, ratio in sorted_data][:max_n]