199 lines
7.2 KiB
Python
199 lines
7.2 KiB
Python
"""
|
|
API Client for Telegram Bot
|
|
Connects bot to FastAPI game server instead of using direct database access
|
|
"""
|
|
|
|
import os
|
|
import httpx
|
|
from typing import Optional, Dict, Any
|
|
|
|
API_BASE_URL = os.getenv("API_BASE_URL", "http://echoes_of_the_ashes_api:8000")
|
|
API_INTERNAL_KEY = os.getenv("API_INTERNAL_KEY", "internal-bot-access-key-change-me")
|
|
|
|
|
|
class GameAPIClient:
|
|
"""Client for interacting with the FastAPI game server"""
|
|
|
|
def __init__(self):
|
|
self.base_url = API_BASE_URL
|
|
self.headers = {
|
|
"X-Internal-Key": API_INTERNAL_KEY,
|
|
"Content-Type": "application/json"
|
|
}
|
|
self.client = httpx.AsyncClient(timeout=30.0)
|
|
|
|
async def close(self):
|
|
"""Close the HTTP client"""
|
|
await self.client.aclose()
|
|
|
|
# ==================== Player Management ====================
|
|
|
|
async def get_player(self, telegram_id: int) -> Optional[Dict[str, Any]]:
|
|
"""Get player by telegram ID"""
|
|
try:
|
|
response = await self.client.get(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}",
|
|
headers=self.headers
|
|
)
|
|
if response.status_code == 404:
|
|
return None
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error getting player: {e}")
|
|
return None
|
|
|
|
async def create_player(self, telegram_id: int, name: str) -> Optional[Dict[str, Any]]:
|
|
"""Create a new player"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/player",
|
|
headers=self.headers,
|
|
json={"telegram_id": telegram_id, "name": name}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error creating player: {e}")
|
|
return None
|
|
|
|
async def update_player(self, telegram_id: int, updates: Dict[str, Any]) -> bool:
|
|
"""Update player data"""
|
|
try:
|
|
response = await self.client.patch(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}",
|
|
headers=self.headers,
|
|
json=updates
|
|
)
|
|
response.raise_for_status()
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error updating player: {e}")
|
|
return False
|
|
|
|
# ==================== Location & Movement ====================
|
|
|
|
async def get_location(self, location_id: str) -> Optional[Dict[str, Any]]:
|
|
"""Get location details"""
|
|
try:
|
|
response = await self.client.get(
|
|
f"{self.base_url}/api/internal/location/{location_id}",
|
|
headers=self.headers
|
|
)
|
|
if response.status_code == 404:
|
|
return None
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error getting location: {e}")
|
|
return None
|
|
|
|
async def move_player(self, telegram_id: int, direction: str) -> Optional[Dict[str, Any]]:
|
|
"""Move player in a direction"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}/move",
|
|
headers=self.headers,
|
|
json={"direction": direction}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except httpx.HTTPStatusError as e:
|
|
# Return error details
|
|
return {"success": False, "error": e.response.json().get("detail", str(e))}
|
|
except Exception as e:
|
|
print(f"Error moving player: {e}")
|
|
return {"success": False, "error": str(e)}
|
|
|
|
# ==================== Combat ====================
|
|
|
|
async def start_combat(self, telegram_id: int, npc_id: str) -> Optional[Dict[str, Any]]:
|
|
"""Start combat with an NPC"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/combat/start",
|
|
headers=self.headers,
|
|
json={"telegram_id": telegram_id, "npc_id": npc_id}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error starting combat: {e}")
|
|
return None
|
|
|
|
async def get_combat(self, telegram_id: int) -> Optional[Dict[str, Any]]:
|
|
"""Get active combat state"""
|
|
try:
|
|
response = await self.client.get(
|
|
f"{self.base_url}/api/internal/combat/telegram/{telegram_id}",
|
|
headers=self.headers
|
|
)
|
|
if response.status_code == 404:
|
|
return None
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error getting combat: {e}")
|
|
return None
|
|
|
|
async def combat_action(self, telegram_id: int, action: str) -> Optional[Dict[str, Any]]:
|
|
"""Perform a combat action (attack, defend, flee)"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/combat/telegram/{telegram_id}/action",
|
|
headers=self.headers,
|
|
json={"action": action}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error performing combat action: {e}")
|
|
return None
|
|
|
|
# ==================== Inventory ====================
|
|
|
|
async def get_inventory(self, telegram_id: int) -> Optional[Dict[str, Any]]:
|
|
"""Get player's inventory"""
|
|
try:
|
|
response = await self.client.get(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}/inventory",
|
|
headers=self.headers
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error getting inventory: {e}")
|
|
return None
|
|
|
|
async def use_item(self, telegram_id: int, item_db_id: int) -> Optional[Dict[str, Any]]:
|
|
"""Use an item from inventory"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}/use_item",
|
|
headers=self.headers,
|
|
json={"item_db_id": item_db_id}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error using item: {e}")
|
|
return None
|
|
|
|
async def equip_item(self, telegram_id: int, item_db_id: int) -> Optional[Dict[str, Any]]:
|
|
"""Equip/unequip an item"""
|
|
try:
|
|
response = await self.client.post(
|
|
f"{self.base_url}/api/internal/player/telegram/{telegram_id}/equip",
|
|
headers=self.headers,
|
|
json={"item_db_id": item_db_id}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
print(f"Error equipping item: {e}")
|
|
return None
|
|
|
|
|
|
# Global API client instance
|
|
api_client = GameAPIClient()
|