## Major Features Added - **Enhanced igdblib.py**: * Added search_games() method with fuzzy game search * Added get_game_details() for comprehensive game information * Added AI-friendly data formatting with _format_game_for_ai() * Added OpenAI function definitions via get_openai_functions() - **OpenAI Function Calling Integration**: * Modified OpenAIResponder to support function calling * Added IGDB function execution with _execute_igdb_function() * Backward compatible - gracefully falls back if IGDB unavailable * Auto-detects gaming queries and fetches real-time data - **Configuration & Setup**: * Added IGDB configuration options to config.toml * Updated system prompt to inform AI of gaming capabilities * Added comprehensive IGDB_SETUP.md documentation * Graceful initialization with proper error handling ## Technical Implementation - **Function Calling**: Uses OpenAI's tools/function calling API - **Smart Game Search**: Includes ratings, platforms, developers, genres - **Error Handling**: Robust fallbacks and logging - **Data Formatting**: Optimized for AI comprehension and user presentation - **Rate Limiting**: Respects IGDB API limits ## Usage Users can now ask natural gaming questions: - "Tell me about Elden Ring" - "What are good RPG games from 2023?" - "Is Cyberpunk 2077 on PlayStation?" The AI automatically detects gaming queries, calls IGDB API, and presents accurate, real-time game information seamlessly. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
149 lines
5.7 KiB
Python
149 lines
5.7 KiB
Python
import unittest
|
|
from unittest.mock import Mock, patch
|
|
|
|
from fjerkroa_bot.igdblib import IGDBQuery
|
|
from fjerkroa_bot.openai_responder import OpenAIResponder
|
|
|
|
|
|
class TestIGDBIntegration(unittest.IsolatedAsyncioTestCase):
|
|
"""Test IGDB integration with OpenAI responder."""
|
|
|
|
def setUp(self):
|
|
self.config_with_igdb = {
|
|
"openai-key": "test_key",
|
|
"model": "gpt-4",
|
|
"enable-game-info": True,
|
|
"igdb-client-id": "test_client",
|
|
"igdb-access-token": "test_token"
|
|
}
|
|
|
|
self.config_without_igdb = {
|
|
"openai-key": "test_key",
|
|
"model": "gpt-4",
|
|
"enable-game-info": False
|
|
}
|
|
|
|
def test_igdb_initialization_enabled(self):
|
|
"""Test IGDB is initialized when enabled in config."""
|
|
with patch('fjerkroa_bot.openai_responder.IGDBQuery') as mock_igdb:
|
|
mock_igdb_instance = Mock()
|
|
mock_igdb.return_value = mock_igdb_instance
|
|
|
|
responder = OpenAIResponder(self.config_with_igdb)
|
|
|
|
mock_igdb.assert_called_once_with("test_client", "test_token")
|
|
self.assertEqual(responder.igdb, mock_igdb_instance)
|
|
|
|
def test_igdb_initialization_disabled(self):
|
|
"""Test IGDB is not initialized when disabled."""
|
|
responder = OpenAIResponder(self.config_without_igdb)
|
|
self.assertIsNone(responder.igdb)
|
|
|
|
def test_igdb_search_games_functionality(self):
|
|
"""Test the search_games functionality."""
|
|
igdb = IGDBQuery("test_client", "test_token")
|
|
|
|
# Mock the actual API call
|
|
mock_games = [{
|
|
"id": 1,
|
|
"name": "Test Game",
|
|
"summary": "A test game",
|
|
"first_release_date": 1577836800, # 2020-01-01
|
|
"genres": [{"name": "Action"}],
|
|
"platforms": [{"name": "PC"}],
|
|
"rating": 85.5
|
|
}]
|
|
|
|
with patch.object(igdb, 'generalized_igdb_query', return_value=mock_games):
|
|
results = igdb.search_games("Test Game")
|
|
|
|
self.assertIsNotNone(results)
|
|
self.assertEqual(len(results), 1)
|
|
self.assertEqual(results[0]["name"], "Test Game")
|
|
self.assertIn("genres", results[0])
|
|
self.assertIn("platforms", results[0])
|
|
|
|
def test_igdb_openai_functions(self):
|
|
"""Test OpenAI function definitions."""
|
|
igdb = IGDBQuery("test_client", "test_token")
|
|
functions = igdb.get_openai_functions()
|
|
|
|
self.assertEqual(len(functions), 2)
|
|
|
|
# Check search_games function
|
|
search_func = functions[0]
|
|
self.assertEqual(search_func["name"], "search_games")
|
|
self.assertIn("description", search_func)
|
|
self.assertIn("parameters", search_func)
|
|
self.assertIn("query", search_func["parameters"]["properties"])
|
|
|
|
# Check get_game_details function
|
|
details_func = functions[1]
|
|
self.assertEqual(details_func["name"], "get_game_details")
|
|
self.assertIn("game_id", details_func["parameters"]["properties"])
|
|
|
|
async def test_execute_igdb_function_search(self):
|
|
"""Test executing IGDB search function."""
|
|
with patch('fjerkroa_bot.openai_responder.IGDBQuery') as mock_igdb_class:
|
|
mock_igdb = Mock()
|
|
mock_igdb.search_games.return_value = [{"name": "Test Game", "id": 1}]
|
|
mock_igdb_class.return_value = mock_igdb
|
|
|
|
responder = OpenAIResponder(self.config_with_igdb)
|
|
|
|
result = await responder._execute_igdb_function(
|
|
"search_games",
|
|
{"query": "Test Game", "limit": 5}
|
|
)
|
|
|
|
self.assertIsNotNone(result)
|
|
self.assertIn("games", result)
|
|
mock_igdb.search_games.assert_called_once_with("Test Game", 5)
|
|
|
|
async def test_execute_igdb_function_details(self):
|
|
"""Test executing IGDB game details function."""
|
|
with patch('fjerkroa_bot.openai_responder.IGDBQuery') as mock_igdb_class:
|
|
mock_igdb = Mock()
|
|
mock_igdb.get_game_details.return_value = {"name": "Test Game", "id": 1}
|
|
mock_igdb_class.return_value = mock_igdb
|
|
|
|
responder = OpenAIResponder(self.config_with_igdb)
|
|
|
|
result = await responder._execute_igdb_function(
|
|
"get_game_details",
|
|
{"game_id": 1}
|
|
)
|
|
|
|
self.assertIsNotNone(result)
|
|
self.assertIn("game", result)
|
|
mock_igdb.get_game_details.assert_called_once_with(1)
|
|
|
|
def test_format_game_for_ai(self):
|
|
"""Test game data formatting for AI consumption."""
|
|
igdb = IGDBQuery("test_client", "test_token")
|
|
|
|
mock_game = {
|
|
"id": 1,
|
|
"name": "Elden Ring",
|
|
"summary": "A fantasy action RPG",
|
|
"first_release_date": 1645747200, # 2022-02-25
|
|
"rating": 96.0,
|
|
"aggregated_rating": 90.5,
|
|
"genres": [{"name": "Role-playing (RPG)"}, {"name": "Adventure"}],
|
|
"platforms": [{"name": "PC (Microsoft Windows)"}, {"name": "PlayStation 5"}],
|
|
"developers": [{"name": "FromSoftware"}]
|
|
}
|
|
|
|
formatted = igdb._format_game_for_ai(mock_game)
|
|
|
|
self.assertEqual(formatted["name"], "Elden Ring")
|
|
self.assertEqual(formatted["rating"], "96.0/100")
|
|
self.assertEqual(formatted["user_rating"], "90.5/100")
|
|
self.assertEqual(formatted["release_year"], 2022)
|
|
self.assertIn("Role-playing (RPG)", formatted["genres"])
|
|
self.assertIn("PC (Microsoft Windows)", formatted["platforms"])
|
|
self.assertIn("FromSoftware", formatted["developers"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main() |