Improve IGDB search capabilities.
This commit is contained in:
parent
d742ab86fa
commit
cb630533e4
@ -182,6 +182,155 @@ class IGDBQuery(object):
|
||||
|
||||
return None
|
||||
|
||||
def get_games_by_release_date(
|
||||
self, year: int, month: Optional[int] = None, platform: Optional[str] = None, limit: int = 10
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""
|
||||
Search for games by release date, optionally filtered by platform.
|
||||
"""
|
||||
try:
|
||||
# Calculate date range for the query
|
||||
import datetime
|
||||
|
||||
if month:
|
||||
# Specific month
|
||||
start_date = datetime.datetime(year, month, 1)
|
||||
if month == 12:
|
||||
end_date = datetime.datetime(year + 1, 1, 1) - datetime.timedelta(seconds=1)
|
||||
else:
|
||||
end_date = datetime.datetime(year, month + 1, 1) - datetime.timedelta(seconds=1)
|
||||
else:
|
||||
# Entire year
|
||||
start_date = datetime.datetime(year, 1, 1)
|
||||
end_date = datetime.datetime(year + 1, 1, 1) - datetime.timedelta(seconds=1)
|
||||
|
||||
start_timestamp = int(start_date.timestamp())
|
||||
end_timestamp = int(end_date.timestamp())
|
||||
|
||||
# Build query filters
|
||||
additional_filters = {"first_release_date": f">= {start_timestamp} & first_release_date <= {end_timestamp}"}
|
||||
|
||||
# Add platform filter if specified
|
||||
if platform:
|
||||
# Try to map common platform names
|
||||
platform_mapping = {
|
||||
"ps5": "PlayStation 5",
|
||||
"playstation 5": "PlayStation 5",
|
||||
"xbox series x": "Xbox Series X|S",
|
||||
"xbox series s": "Xbox Series X|S",
|
||||
"xbox series x|s": "Xbox Series X|S",
|
||||
"switch": "Nintendo Switch",
|
||||
"nintendo switch": "Nintendo Switch",
|
||||
"pc": "PC (Microsoft Windows)",
|
||||
"windows": "PC (Microsoft Windows)",
|
||||
}
|
||||
platform_key = platform.lower()
|
||||
if platform_key in platform_mapping:
|
||||
platform = platform_mapping[platform_key]
|
||||
|
||||
additional_filters["platforms.name"] = f'~ "{platform}"*'
|
||||
|
||||
# Search games
|
||||
games = self.generalized_igdb_query(
|
||||
{}, # No name search
|
||||
"games",
|
||||
[
|
||||
"id",
|
||||
"name",
|
||||
"summary",
|
||||
"first_release_date",
|
||||
"genres.name",
|
||||
"platforms.name",
|
||||
"involved_companies.company.name",
|
||||
"cover.url",
|
||||
"rating",
|
||||
"aggregated_rating",
|
||||
],
|
||||
additional_filters=additional_filters,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
if not games:
|
||||
return None
|
||||
|
||||
# Format games for AI consumption
|
||||
formatted_games = []
|
||||
for game in games:
|
||||
formatted_game = self._format_game_for_ai(game)
|
||||
if formatted_game:
|
||||
formatted_games.append(formatted_game)
|
||||
|
||||
return formatted_games if formatted_games else None
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error searching games by release date {year}/{month}: {e}")
|
||||
return None
|
||||
|
||||
def get_games_by_platform(self, platform: str, genre: Optional[str] = None, limit: int = 10) -> Optional[List[Dict[str, Any]]]:
|
||||
"""
|
||||
Search for games by platform, optionally filtered by genre.
|
||||
"""
|
||||
try:
|
||||
# Platform name mapping
|
||||
platform_mapping = {
|
||||
"ps5": "PlayStation 5",
|
||||
"playstation 5": "PlayStation 5",
|
||||
"xbox series x": "Xbox Series X|S",
|
||||
"xbox series s": "Xbox Series X|S",
|
||||
"xbox series x|s": "Xbox Series X|S",
|
||||
"switch": "Nintendo Switch",
|
||||
"nintendo switch": "Nintendo Switch",
|
||||
"pc": "PC (Microsoft Windows)",
|
||||
"windows": "PC (Microsoft Windows)",
|
||||
}
|
||||
|
||||
platform_key = platform.lower()
|
||||
if platform_key in platform_mapping:
|
||||
platform = platform_mapping[platform_key]
|
||||
|
||||
# Build query filters
|
||||
additional_filters = {"platforms.name": f'~ "{platform}"*'}
|
||||
|
||||
# Add genre filter if specified
|
||||
if genre:
|
||||
additional_filters["genres.name"] = f'~ "{genre}"*'
|
||||
|
||||
# Search games
|
||||
games = self.generalized_igdb_query(
|
||||
{}, # No name search
|
||||
"games",
|
||||
[
|
||||
"id",
|
||||
"name",
|
||||
"summary",
|
||||
"first_release_date",
|
||||
"genres.name",
|
||||
"platforms.name",
|
||||
"involved_companies.company.name",
|
||||
"cover.url",
|
||||
"rating",
|
||||
"aggregated_rating",
|
||||
],
|
||||
additional_filters=additional_filters,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
if not games:
|
||||
return None
|
||||
|
||||
# Format games for AI consumption
|
||||
formatted_games = []
|
||||
for game in games:
|
||||
formatted_game = self._format_game_for_ai(game)
|
||||
if formatted_game:
|
||||
formatted_games.append(formatted_game)
|
||||
|
||||
return formatted_games if formatted_games else None
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error searching games by platform {platform}: {e}")
|
||||
return None
|
||||
|
||||
def _format_game_for_ai(self, game_data: Dict[str, Any], detailed: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
Format game data in a way that's easy for AI to understand and present to users.
|
||||
@ -249,7 +398,7 @@ class IGDBQuery(object):
|
||||
return [
|
||||
{
|
||||
"name": "search_games",
|
||||
"description": "Search for video games by name or title. Use when users ask about specific games, game recommendations, or want to know about games.",
|
||||
"description": "Search for video games by name or title. Use when users ask about specific games by name (e.g., 'Elden Ring', 'Call of Duty', 'Mario'). Do NOT use for release date or platform queries.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -267,6 +416,62 @@ class IGDBQuery(object):
|
||||
"required": ["query"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "get_games_by_release_date",
|
||||
"description": "Find games releasing in a specific time period. Use when users ask about upcoming releases, games coming out in a specific month/year, or new releases.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"year": {
|
||||
"type": "integer",
|
||||
"description": "Release year (e.g., 2025)",
|
||||
"minimum": 2020,
|
||||
"maximum": 2030,
|
||||
},
|
||||
"month": {
|
||||
"type": "integer",
|
||||
"description": "Release month (1-12). Optional, if not specified will search entire year",
|
||||
"minimum": 1,
|
||||
"maximum": 12,
|
||||
},
|
||||
"platform": {
|
||||
"type": "string",
|
||||
"description": "Platform name (e.g., 'PlayStation 5', 'Xbox Series X|S', 'Nintendo Switch', 'PC'). Optional, if not specified will search all platforms",
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of games to return (default: 10, max: 20)",
|
||||
"minimum": 1,
|
||||
"maximum": 20,
|
||||
},
|
||||
},
|
||||
"required": ["year"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "get_games_by_platform",
|
||||
"description": "Find games available on a specific platform. Use when users ask about games for a particular console or system.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"platform": {
|
||||
"type": "string",
|
||||
"description": "Platform name (e.g., 'PlayStation 5', 'Xbox Series X|S', 'Nintendo Switch', 'PC (Microsoft Windows)')",
|
||||
},
|
||||
"genre": {
|
||||
"type": "string",
|
||||
"description": "Game genre (optional) - e.g., 'Action', 'RPG', 'Sports', 'Strategy'",
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of games to return (default: 10, max: 20)",
|
||||
"minimum": 1,
|
||||
"maximum": 20,
|
||||
},
|
||||
},
|
||||
"required": ["platform"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "get_game_details",
|
||||
"description": "Get detailed information about a specific game when you have its ID from a previous search.",
|
||||
|
||||
@ -320,6 +320,50 @@ class OpenAIResponder(AIResponder, LeonardoAIDrawMixIn):
|
||||
else:
|
||||
return {"games": [], "message": f"No games found matching '{query}'"}
|
||||
|
||||
elif function_name == "get_games_by_release_date":
|
||||
year = function_args.get("year")
|
||||
month = function_args.get("month")
|
||||
platform = function_args.get("platform")
|
||||
limit = function_args.get("limit", 10)
|
||||
|
||||
logging.info(
|
||||
f"🎮 Searching IGDB for games releasing in {year}/{month or 'all'} on {platform or 'all platforms'} (limit: {limit})"
|
||||
)
|
||||
|
||||
if not year:
|
||||
logging.warning("🎮 No year provided to get_games_by_release_date")
|
||||
return {"error": "No year provided"}
|
||||
|
||||
results = self.igdb.get_games_by_release_date(year, month, platform, limit)
|
||||
logging.info(f"🎮 IGDB release date search returned: {len(results) if results and isinstance(results, list) else 0} results")
|
||||
|
||||
if results and isinstance(results, list) and len(results) > 0:
|
||||
return {"games": results}
|
||||
else:
|
||||
period = f"{year}/{month}" if month else str(year)
|
||||
platform_text = f" on {platform}" if platform else ""
|
||||
return {"games": [], "message": f"No games found releasing in {period}{platform_text}"}
|
||||
|
||||
elif function_name == "get_games_by_platform":
|
||||
platform = function_args.get("platform", "")
|
||||
genre = function_args.get("genre")
|
||||
limit = function_args.get("limit", 10)
|
||||
|
||||
logging.info(f"🎮 Searching IGDB for games on {platform} {f'in {genre} genre' if genre else ''} (limit: {limit})")
|
||||
|
||||
if not platform:
|
||||
logging.warning("🎮 No platform provided to get_games_by_platform")
|
||||
return {"error": "No platform provided"}
|
||||
|
||||
results = self.igdb.get_games_by_platform(platform, genre, limit)
|
||||
logging.info(f"🎮 IGDB platform search returned: {len(results) if results and isinstance(results, list) else 0} results")
|
||||
|
||||
if results and isinstance(results, list) and len(results) > 0:
|
||||
return {"games": results}
|
||||
else:
|
||||
genre_text = f" in {genre} genre" if genre else ""
|
||||
return {"games": [], "message": f"No games found for {platform}{genre_text}"}
|
||||
|
||||
elif function_name == "get_game_details":
|
||||
game_id = function_args.get("game_id")
|
||||
|
||||
|
||||
@ -67,7 +67,7 @@ class TestIGDBIntegration(unittest.IsolatedAsyncioTestCase):
|
||||
igdb = IGDBQuery("test_client", "test_token")
|
||||
functions = igdb.get_openai_functions()
|
||||
|
||||
self.assertEqual(len(functions), 2)
|
||||
self.assertEqual(len(functions), 4)
|
||||
|
||||
# Check search_games function
|
||||
search_func = functions[0]
|
||||
@ -76,8 +76,20 @@ class TestIGDBIntegration(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertIn("parameters", search_func)
|
||||
self.assertIn("query", search_func["parameters"]["properties"])
|
||||
|
||||
# Check get_games_by_release_date function
|
||||
release_func = functions[1]
|
||||
self.assertEqual(release_func["name"], "get_games_by_release_date")
|
||||
self.assertIn("description", release_func)
|
||||
self.assertIn("parameters", release_func)
|
||||
|
||||
# Check get_games_by_platform function
|
||||
platform_func = functions[2]
|
||||
self.assertEqual(platform_func["name"], "get_games_by_platform")
|
||||
self.assertIn("description", platform_func)
|
||||
self.assertIn("parameters", platform_func)
|
||||
|
||||
# Check get_game_details function
|
||||
details_func = functions[1]
|
||||
details_func = functions[3]
|
||||
self.assertEqual(details_func["name"], "get_game_details")
|
||||
self.assertIn("game_id", details_func["parameters"]["properties"])
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user