import os import requests from dotenv import load_dotenv from APIs.api_types import IGDBType import datetime class IGDB: def __init__(self): load_dotenv() self.client_id = os.getenv("IGDB_CLIENT_ID") self.client_secret = os.getenv("IGDB_CLIENT_SECRET") self.access_token = None # Format pattern to get release date 2025-04-24 00:00:00+00:00 self.format_pattern = "%Y-%m-%d %H:%M:%S+00:00" def _get_access_token(self): """ Authenticates with Twitch to get the Bearer Token required for IGDB. """ auth_url = "https://id.twitch.tv/oauth2/token" params = { "client_id": self.client_id, "client_secret": self.client_secret, "grant_type": "client_credentials", } response = requests.post(auth_url, params=params) if response.status_code != 200: raise Exception(f"Authentication failed: {response.text}") self.access_token = response.json()["access_token"] return self.access_token def search(self, game_name: str, max_n: int = 1) -> list[IGDBType]: """ Searches for games by name and retrieves details. Returns a list of IGDBType objects. """ if not self.access_token: self._get_access_token() url = "https://api.igdb.com/v4/games" headers = { "Client-ID": self.client_id, "Authorization": f"Bearer {self.access_token}", "Content-Type": "text/plain", } # IGDB's APICALYPSE query language wants the raw search string with only # backslashes and double-quotes escaped — NOT URL-encoded. Using quote() # here (the old behavior) turned 'The Witcher 3: Wild Hunt' into # 'The%20Witcher%203%3A...' which matched nothing; only punctuation-free # names happened to work. safe_name = game_name.replace("\\", "\\\\").replace('"', '\\"') body = f""" fields name, game_modes.name, game_type.type, keywords.name, language_supports.language.name, platforms.name, player_perspectives.name, themes.name, rating, summary, first_release_date, genres.name, cover.url; search "{safe_name}"; limit {max_n}; """ response = requests.post(url, headers=headers, data=body) if response.status_code != 200: raise Exception(f"IGDB Query failed: {response.text}") results = response.json() igdb_results = [] for game in results: igdb_obj = IGDBType( name=game.get("name"), game_modes=[g["name"] for g in game.get("game_modes", [])], game_type=game.get("game_type", {}).get("type"), keywords=[g["name"] for g in game.get("keywords", [])], language_supports=[g["language"]["name"] for g in game.get("language_supports", [])], platforms=[g["name"] for g in game.get("platforms", [])], player_perspectives=[g["name"] for g in game.get("player_perspectives", [])], themes=[g["name"] for g in game.get("themes", [])], igdb_rating=float(game.get("rating")) / 100.0 if game.get("rating") else 0.0, release=datetime.datetime.fromtimestamp(int(game.get("first_release_date", "0")), datetime.timezone.utc).strftime("%Y-%m-%d"), genres=[g["name"] for g in game.get("genres", [])], cover_url=[game.get("cover", {}).get("url")], description=game.get("summary"), ) igdb_results.append(igdb_obj) return igdb_results