169 lines
5.8 KiB
Python
169 lines
5.8 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Card Game CLI Client - Interactive testing tool for the backend API.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import requests
|
||
|
|
import json
|
||
|
|
import uuid
|
||
|
|
|
||
|
|
BASE_URL = "http://localhost:8000"
|
||
|
|
|
||
|
|
class CardGameClient:
|
||
|
|
def __init__(self):
|
||
|
|
self.token = None
|
||
|
|
self.session = requests.Session()
|
||
|
|
|
||
|
|
def _headers(self):
|
||
|
|
if self.token:
|
||
|
|
return {"Authorization": f"Bearer {self.token}"}
|
||
|
|
return {}
|
||
|
|
|
||
|
|
def _print_response(self, resp, label="Response"):
|
||
|
|
print(f"\n{label} ({resp.status_code}):")
|
||
|
|
try:
|
||
|
|
print(json.dumps(resp.json(), indent=2))
|
||
|
|
except:
|
||
|
|
print(resp.text)
|
||
|
|
|
||
|
|
def register(self, email, password, nickname):
|
||
|
|
resp = self.session.post(f"{BASE_URL}/auth/register", json={
|
||
|
|
"email": email,
|
||
|
|
"password": password,
|
||
|
|
"nickname": nickname
|
||
|
|
})
|
||
|
|
self._print_response(resp, "Register")
|
||
|
|
if resp.status_code == 200:
|
||
|
|
data = resp.json()
|
||
|
|
self.token = data.get("access_token")
|
||
|
|
print("✓ Logged in automatically after registration.")
|
||
|
|
|
||
|
|
def login(self, email, password):
|
||
|
|
resp = self.session.post(f"{BASE_URL}/auth/login", json={
|
||
|
|
"email": email,
|
||
|
|
"password": password
|
||
|
|
})
|
||
|
|
self._print_response(resp, "Login")
|
||
|
|
if resp.status_code == 200:
|
||
|
|
self.token = resp.json()["access_token"]
|
||
|
|
print("✓ Token saved.")
|
||
|
|
|
||
|
|
def me(self):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/me/profile", headers=self._headers())
|
||
|
|
self._print_response(resp, "My Profile")
|
||
|
|
|
||
|
|
resp = self.session.get(f"{BASE_URL}/me/wallet", headers=self._headers())
|
||
|
|
self._print_response(resp, "My Wallet")
|
||
|
|
|
||
|
|
def collection(self):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/me/collection", headers=self._headers())
|
||
|
|
self._print_response(resp, "My Collection")
|
||
|
|
|
||
|
|
def chests(self):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/catalog/chests")
|
||
|
|
self._print_response(resp, "Available Chests")
|
||
|
|
|
||
|
|
def cards(self):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/catalog/cards")
|
||
|
|
self._print_response(resp, "All Cards")
|
||
|
|
|
||
|
|
def open_chest(self, chest_id, idempotency_key=None):
|
||
|
|
headers = self._headers()
|
||
|
|
if idempotency_key:
|
||
|
|
headers["Idempotency-Key"] = idempotency_key
|
||
|
|
else:
|
||
|
|
headers["Idempotency-Key"] = str(uuid.uuid4())
|
||
|
|
|
||
|
|
resp = self.session.post(f"{BASE_URL}/chests/{chest_id}/open", headers=headers)
|
||
|
|
self._print_response(resp, "Chest Open Result")
|
||
|
|
|
||
|
|
def profile(self, nickname):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/profiles/{nickname}")
|
||
|
|
self._print_response(resp, f"Profile: {nickname}")
|
||
|
|
|
||
|
|
def profile_collection(self, nickname):
|
||
|
|
resp = self.session.get(f"{BASE_URL}/profiles/{nickname}/collection")
|
||
|
|
self._print_response(resp, f"Collection: {nickname}")
|
||
|
|
|
||
|
|
def print_help():
|
||
|
|
print("""
|
||
|
|
=== Card Game CLI ===
|
||
|
|
Commands:
|
||
|
|
register <email> <password> <nickname> - Create new account
|
||
|
|
login <email> <password> - Login to existing account
|
||
|
|
me - Show my profile and wallet
|
||
|
|
collection - Show my cards
|
||
|
|
chests - List available chests
|
||
|
|
cards - List all cards in catalog
|
||
|
|
open <chest_id> - Open a chest
|
||
|
|
profile <nickname> - View public profile
|
||
|
|
profile_collection <nickname> - View public collection
|
||
|
|
help - Show this help
|
||
|
|
quit / exit - Exit
|
||
|
|
""")
|
||
|
|
|
||
|
|
def main():
|
||
|
|
client = CardGameClient()
|
||
|
|
print_help()
|
||
|
|
|
||
|
|
while True:
|
||
|
|
try:
|
||
|
|
cmd = input("\n> ").strip()
|
||
|
|
if not cmd:
|
||
|
|
continue
|
||
|
|
|
||
|
|
parts = cmd.split()
|
||
|
|
command = parts[0].lower()
|
||
|
|
args = parts[1:]
|
||
|
|
|
||
|
|
if command in ["quit", "exit", "q"]:
|
||
|
|
print("Goodbye!")
|
||
|
|
break
|
||
|
|
elif command == "help":
|
||
|
|
print_help()
|
||
|
|
elif command == "register":
|
||
|
|
if len(args) < 3:
|
||
|
|
print("Usage: register <email> <password> <nickname>")
|
||
|
|
else:
|
||
|
|
client.register(args[0], args[1], args[2])
|
||
|
|
elif command == "login":
|
||
|
|
if len(args) < 2:
|
||
|
|
print("Usage: login <email> <password>")
|
||
|
|
else:
|
||
|
|
client.login(args[0], args[1])
|
||
|
|
elif command == "me":
|
||
|
|
client.me()
|
||
|
|
elif command == "collection":
|
||
|
|
client.collection()
|
||
|
|
elif command == "chests":
|
||
|
|
client.chests()
|
||
|
|
elif command == "cards":
|
||
|
|
client.cards()
|
||
|
|
elif command == "open":
|
||
|
|
if len(args) < 1:
|
||
|
|
print("Usage: open <chest_id>")
|
||
|
|
else:
|
||
|
|
key = args[1] if len(args) > 1 else None
|
||
|
|
client.open_chest(args[0], key)
|
||
|
|
elif command == "profile":
|
||
|
|
if len(args) < 1:
|
||
|
|
print("Usage: profile <nickname>")
|
||
|
|
else:
|
||
|
|
client.profile(args[0])
|
||
|
|
elif command == "profile_collection":
|
||
|
|
if len(args) < 1:
|
||
|
|
print("Usage: profile_collection <nickname>")
|
||
|
|
else:
|
||
|
|
client.profile_collection(args[0])
|
||
|
|
else:
|
||
|
|
print(f"Unknown command: {command}. Type 'help' for commands.")
|
||
|
|
|
||
|
|
except KeyboardInterrupt:
|
||
|
|
print("\nGoodbye!")
|
||
|
|
break
|
||
|
|
except Exception as e:
|
||
|
|
print(f"Error: {e}")
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|