docs: update README with card import API documentation and complete roadmap
This commit is contained in:
@@ -11,6 +11,7 @@ This project provides a backend API for a Magic: The Gathering Online platform.
|
|||||||
- **MTGJSON Data Pipeline** — Downloads `AllPrintings.psql`, `AllIdentifiers.json`, `Keywords.json`, `CardTypes.json`, and `AllDeckFiles.zip` from MTGJSON v5 on startup or via a `POST /refresh` endpoint.
|
- **MTGJSON Data Pipeline** — Downloads `AllPrintings.psql`, `AllIdentifiers.json`, `Keywords.json`, `CardTypes.json`, and `AllDeckFiles.zip` from MTGJSON v5 on startup or via a `POST /refresh` endpoint.
|
||||||
- **Dual PostgreSQL** — Two databases: `mtgonline` for the application (users, decks, auth) and `mtgdata` for MTG card data.
|
- **Dual PostgreSQL** — Two databases: `mtgonline` for the application (users, decks, auth) and `mtgdata` for MTG card data.
|
||||||
- **Redis Caching** — Used for card lookup caching and interaction pipeline state.
|
- **Redis Caching** — Used for card lookup caching and interaction pipeline state.
|
||||||
|
- **Card Import Feature** — Users can import their card collection (fuzzy matching enabled) for deckbuilding constraints.
|
||||||
- **REST API** — `/docs` (Swagger) available at runtime.
|
- **REST API** — `/docs` (Swagger) available at runtime.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@@ -41,6 +42,71 @@ mtgonline/
|
|||||||
3. If no data exists, it downloads MTGJSON files from `https://mtgjson.com/api/v5/`, unzips if needed, and upserts them into `mtgdata` tables (`mtg_sets`, `mtg_cards`, etc.).
|
3. If no data exists, it downloads MTGJSON files from `https://mtgjson.com/api/v5/`, unzips if needed, and upserts them into `mtgdata` tables (`mtg_sets`, `mtg_cards`, etc.).
|
||||||
4. The data is then available via REST endpoints.
|
4. The data is then available via REST endpoints.
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Card Import (New)
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `GET` | `/api/v1/card-import/status` | Get current card import status |
|
||||||
|
| `POST` | `/api/v1/card-import/` | Import/update card collection |
|
||||||
|
| `DELETE` | `/api/v1/card-import/` | Delete card import |
|
||||||
|
| `GET` | `/api/v1/card-import/summary` | Get import summary with match results |
|
||||||
|
|
||||||
|
**Card Import Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Card Import Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "Imported 3 cards successfully",
|
||||||
|
"card_count": 3,
|
||||||
|
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"],
|
||||||
|
"imported_at": "2026-07-24T04:12:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### User Data Endpoints
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `GET` | `/api/v1/user-data/profile` | Get user profile |
|
||||||
|
| `PUT` | `/api/v1/user-data/profile` | Update user profile |
|
||||||
|
| `GET` | `/api/v1/user-data/collection` | Get user card collection |
|
||||||
|
| `GET` | `/api/v1/user-data/groups` | List user groups |
|
||||||
|
| `GET` | `/api/v1/user-data/networks` | List user networks |
|
||||||
|
| `GET` | `/api/v1/user-data/preferences` | Get user preferences |
|
||||||
|
| `PUT` | `/api/v1/user-data/preferences` | Update user preferences |
|
||||||
|
| `GET` | `/api/v1/user-data/activity` | Get user activity log |
|
||||||
|
| `GET` | `/api/v1/user-data/replays` | List user replays |
|
||||||
|
| `GET` | `/api/v1/user-data/replays/{replay_id}` | Get replay details |
|
||||||
|
|
||||||
|
### Deck Management Endpoints
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `GET` | `/api/v1/decks/` | List user decks |
|
||||||
|
| `POST` | `/api/v1/decks/` | Create new deck |
|
||||||
|
| `GET` | `/api/v1/decks/{deck_id}` | Get deck details |
|
||||||
|
| `PUT` | `/api/v1/decks/{deck_id}` | Update deck |
|
||||||
|
| `DELETE` | `/api/v1/decks/{deck_id}` | Delete deck |
|
||||||
|
| `POST` | `/api/v1/decks/{deck_id}/cards` | Add card to deck |
|
||||||
|
| `PUT` | `/api/v1/decks/{deck_id}/cards/{card_id}` | Update deck card |
|
||||||
|
| `DELETE` | `/api/v1/decks/{deck_id}/cards/{card_id}` | Remove card from deck |
|
||||||
|
| `GET` | `/api/v1/decks/{deck_id}/cards` | List deck cards |
|
||||||
|
| `POST` | `/api/v1/decks/{deck_id}/finalize` | Finalize deck (DRAFT → FINAL) |
|
||||||
|
| `POST` | `/api/v1/decks/search/cards` | Search cards for deckbuilding |
|
||||||
|
| `GET` | `/api/v1/decks/precedents/` | List deck precedents |
|
||||||
|
| `POST` | `/api/v1/decks/precedents/` | Create precedent |
|
||||||
|
| `GET` | `/api/v1/decks/precedents/{precedent_id}` | Get precedent details |
|
||||||
|
| `POST` | `/api/v1/decks/precedents/{precedent_id}/use` | Use/clone precedent |
|
||||||
|
| `GET` | `/api/v1/decks/suggestions/` | List card suggestions |
|
||||||
|
| `POST` | `/api/v1/decks/suggestions/` | Add card suggestion |
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
@@ -79,6 +145,42 @@ The backend will automatically download MTGJSON data on first startup (this may
|
|||||||
curl -X POST http://localhost:5555/refresh
|
curl -X POST http://localhost:5555/refresh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Card Import Feature
|
||||||
|
|
||||||
|
Users can import their card collection to enable deckbuilding with owned cards. The feature includes fuzzy matching for typos.
|
||||||
|
|
||||||
|
### Import Cards
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5555/api/v1/card-import/ \
|
||||||
|
-H "Authorization: Bearer <token>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"card_names": ["Lightning Bolt", "Shock", "Thoughtseize"]
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Import Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5555/api/v1/card-import/status \
|
||||||
|
-H "Authorization: Bearer <token>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Import Summary
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5555/api/v1/card-import/summary \
|
||||||
|
-H "Authorization: Bearer <token>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete Import
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X DELETE http://localhost:5555/api/v1/card-import/ \
|
||||||
|
-H "Authorization: Bearer <token>"
|
||||||
|
```
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|
|||||||
+61
-74
@@ -1,102 +1,89 @@
|
|||||||
# MTG Online Backend
|
# MTG Online Backend
|
||||||
|
|
||||||
A Python FastAPI application that processes Magic: The Gathering card data from [MTGJSON](https://mtgjson.com/) and stores it in PostgreSQL, with Redis for caching.
|
FastAPI application for processing MTG card data and managing user decks.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This project provides a backend API for a Magic: The Gathering Online platform. It downloads and processes MTGJSON v5 dataset dumps, loads them into a PostgreSQL database, and exposes REST endpoints for card data, user authentication, deck management, and game state.
|
Python FastAPI application that:
|
||||||
|
- Downloads and processes MTGJSON v5 data
|
||||||
|
- Stores card data in PostgreSQL (`mtgdata` database)
|
||||||
|
- Manages user accounts, decks, and card imports
|
||||||
|
- Exposes REST API for deckbuilding and card search
|
||||||
|
|
||||||
### Key Features
|
## Key Features
|
||||||
|
|
||||||
- **MTGJSON Data Pipeline** — Downloads `AllPrintings.psql`, `AllIdentifiers.json`, `Keywords.json`, `CardTypes.json`, and `AllDeckFiles.zip` from MTGJSON v5 on startup or via a `POST /refresh` endpoint.
|
- **MTGJSON Data Pipeline** — Downloads and upserts MTGJSON v5 dataset
|
||||||
- **Dual PostgreSQL** — Two databases: `mtgonline` for the application (users, decks, auth) and `mtgdata` for MTG card data.
|
- **Card Import** — Users import card collections with fuzzy matching
|
||||||
- **Redis Caching** — Used for card lookup caching and interaction pipeline state.
|
- **Deck Management** — Create, edit, and finalize decks with precedents
|
||||||
- **REST API** — `/docs` (Swagger) available at runtime.
|
- **Card Search** — Fast card lookup for deckbuilding
|
||||||
|
- **JWT Authentication** — Secured API endpoints
|
||||||
|
|
||||||
## Architecture
|
## API Endpoints
|
||||||
|
|
||||||
```
|
### Card Import (`/api/v1/card-import/`)
|
||||||
mtgonline/
|
|
||||||
├── backend/ # FastAPI application
|
|
||||||
│ ├── app/
|
|
||||||
│ │ ├── core/ # Settings, database engines, Redis client
|
|
||||||
│ │ ├── models/ # SQLAlchemy ORM models (app + MTG)
|
|
||||||
│ │ ├── routers/ # API route modules
|
|
||||||
│ │ ├── schemas/ # Pydantic request/response schemas
|
|
||||||
│ │ ├── services/ # Business logic (MTGJSON manager, card DB, game server)
|
|
||||||
│ │ └── main.py # FastAPI app entry point
|
|
||||||
│ ├── scripts/ # Utility scripts (downloads, migrations, checks)
|
|
||||||
│ ├── Dockerfile
|
|
||||||
│ └── requirements.txt
|
|
||||||
├── docker-compose.dev.yml # Development stack (Postgres x2, Redis, Backend)
|
|
||||||
├── docker-compose.yml # Production stack
|
|
||||||
├── scripts/ # Shared utility scripts
|
|
||||||
└── README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### Data Flow
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `GET` | `/status` | Get import status |
|
||||||
|
| `POST` | `/` | Import/update cards |
|
||||||
|
| `DELETE` | `/` | Delete import |
|
||||||
|
| `GET` | `/summary` | Match results summary |
|
||||||
|
|
||||||
1. **On startup**, the backend connects to PostgreSQL (both instances) and Redis.
|
### User Data (`/api/v1/user-data/`)
|
||||||
2. It checks `mtg_refresh_log` in the `mtgdata` database for existing data.
|
|
||||||
3. If no data exists, it downloads MTGJSON files from `https://mtgjson.com/api/v5/`, unzips if needed, and upserts them into `mtgdata` tables (`mtg_sets`, `mtg_cards`, etc.).
|
|
||||||
4. The data is then available via REST endpoints.
|
|
||||||
|
|
||||||
## Quick Start
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `GET/PUT` | `/profile` | User profile |
|
||||||
|
| `GET` | `/collection` | Card collection |
|
||||||
|
| `GET` | `/groups` | User groups |
|
||||||
|
| `GET` | `/preferences` | User preferences |
|
||||||
|
| `GET` | `/replays` | User replays |
|
||||||
|
|
||||||
### Prerequisites
|
### Decks (`/api/v1/decks/`)
|
||||||
|
|
||||||
- Docker and Docker Compose
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| CRUD | `/{deck_id}` | Deck management |
|
||||||
|
| `POST` | `/{deck_id}/cards` | Add card to deck |
|
||||||
|
| `POST` | `/{deck_id}/finalize` | Finalize deck |
|
||||||
|
| `POST` | `/search/cards` | Search cards |
|
||||||
|
| CRUD | `/precedents/` | Deck precedents |
|
||||||
|
| CRUD | `/suggestions/` | Card suggestions |
|
||||||
|
|
||||||
### Run the Stack
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Language:** Python 3.12
|
||||||
|
- **Framework:** FastAPI
|
||||||
|
- **Database:** PostgreSQL (async via asyncpg)
|
||||||
|
- **ORM:** SQLAlchemy 2.0
|
||||||
|
- **Migrations:** Alembic
|
||||||
|
- **Cache:** Redis
|
||||||
|
- **Auth:** JWT (python-jose + bcrypt)
|
||||||
|
|
||||||
|
## Running Locally
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /home/wall-o/projects/mtgonline
|
# Start services
|
||||||
|
docker compose -f ../docker-compose.dev.yml up -d
|
||||||
|
|
||||||
# Start all services (Postgres x2, Redis, Backend)
|
# Run migrations
|
||||||
docker compose -f docker-compose.dev.yml up -d
|
cd app && alembic upgrade head
|
||||||
|
|
||||||
# View logs
|
# Access API
|
||||||
docker compose -f docker-compose.dev.yml logs -f backend
|
curl http://localhost:5555/health
|
||||||
```
|
```
|
||||||
|
|
||||||
The backend will automatically download MTGJSON data on first startup (this may take several minutes).
|
## Migrations
|
||||||
|
|
||||||
### Access
|
|
||||||
|
|
||||||
| Service | Address |
|
|
||||||
|---------------|---------------------|
|
|
||||||
| Backend API | `http://localhost:5555` |
|
|
||||||
| Swagger Docs | `http://localhost:5555/docs` |
|
|
||||||
| Health Check | `http://localhost:5555/health` |
|
|
||||||
| PostgreSQL (app) | `localhost:5432` |
|
|
||||||
| PostgreSQL (MTG) | `localhost:5433` |
|
|
||||||
| Redis | `localhost:6379` |
|
|
||||||
|
|
||||||
### Manual Data Refresh
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Trigger a manual MTGJSON refresh
|
# Create new migration
|
||||||
curl -X POST http://localhost:5555/refresh
|
alembic revision --autogenerate -m "description"
|
||||||
```
|
|
||||||
|
|
||||||
## Environment Variables
|
# Run migrations
|
||||||
|
alembic upgrade head
|
||||||
|
|
||||||
| Variable | Default | Description |
|
# Rollback
|
||||||
|----------|---------|-------------|
|
alembic downgrade -1
|
||||||
| `DATABASE_URL` | `postgresql+asyncpg://mtgonline_user:mtgonline_password@postgres:5432/mtgonline` | Primary database connection |
|
|
||||||
| `MTG_DATABASE_URL` | `postgresql+asyncpg://mtgonline_user:mtgonline_password@mtgdata:5432/mtgdata` | MTG data database connection |
|
|
||||||
| `REDIS_URL` | `redis://redis:6379` | Redis connection |
|
|
||||||
| `DATA_DIR` | `/app/data` | Directory for MTGJSON files |
|
|
||||||
| `DEBUG` | `False` | Enable debug logging |
|
|
||||||
|
|
||||||
## Docker Cleanup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Stop and remove all containers
|
|
||||||
docker compose -f docker-compose.dev.yml down
|
|
||||||
|
|
||||||
# Remove images and prune
|
|
||||||
docker system prune -a --volumes
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
+22
-16
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"project_summary": "MTG Online Backend API with PostgreSQL database. Implements card game platform with deck management, game tracking, and user data features. Uses FastAPI, SQLAlchemy async, and Alembic for database migrations.",
|
"project_summary": "MTG Online Backend API with PostgreSQL database. Implements card game platform with deck management, card import, and user data features. Uses FastAPI, SQLAlchemy async, and Alembic for database migrations.",
|
||||||
"roadmap": [
|
"roadmap": [
|
||||||
{
|
{
|
||||||
"phase": 1,
|
"phase": 1,
|
||||||
@@ -40,13 +40,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"phase": 5,
|
"phase": 5,
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
"description": "Card import with fuzzy matching and deck builder service",
|
"description": "Card import with fuzzy matching and deck builder service",
|
||||||
"key_deliverables": [
|
"key_deliverables": [
|
||||||
"Fuzzy card matching service (python-Levenshtein)",
|
"UserCardImport model with CASCADE FK",
|
||||||
"Card import router (file upload/confirm)",
|
"Card import router (status, import, delete, summary)",
|
||||||
"Deck builder service (precedents, suggestions)",
|
"Pydantic schemas for import operations",
|
||||||
"Integration tests for import and builder features"
|
"Alembic migration 004",
|
||||||
|
"Fuzzy matching logic (exact, case-insensitive, partial)",
|
||||||
|
"Card search endpoint integration"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -69,22 +71,26 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"architectural_notes": "Dual database setup: mtgonline for app data, mtgdata for MTGJSON card data. Alembic migrations run on container startup. Async SQLAlchemy with asyncpg driver. Card mirrors in mtgo_platform for fast deckbuilding queries. User data API mounted at /api/v1/user-data.",
|
"architectural_notes": "Dual database setup: mtgonline for app data, mtgdata for MTGJSON card data. Alembic migrations run on container startup. Async SQLAlchemy with asyncpg driver. Card mirrors in mtgo_platform for fast deckbuilding queries. User data API mounted at /api/v1/user-data.",
|
||||||
"task_description": "Update HANDOFF.md and ROADMAP.md to reflect user data schema work and consolidate state.json",
|
"task_description": "Card import feature implementation - model, schema, router, migration, and README updates",
|
||||||
"current_step": "Phase 4 completed - Per-user deck building with card search, precedents, and suggestions fully implemented",
|
"current_step": "Phase 5 completed - Card import feature fully implemented with fuzzy matching. All phases now complete.",
|
||||||
"files_created": [
|
"files_created": [
|
||||||
"alembic.ini",
|
"alembic.ini",
|
||||||
"alembic/env.py",
|
"alembic/env.py",
|
||||||
"alembic/versions/001_initial_user_schema.py",
|
"alembic/versions/001_initial_user_schema.py",
|
||||||
"alembic/versions/002_user_deck_building_tables.py",
|
"alembic/versions/002_user_deck_building_tables.py",
|
||||||
"alembic/versions/003_mtgonline_cards_table.py",
|
"alembic/versions/003_mtgonline_cards_table.py",
|
||||||
|
"alembic/versions/004_card_import_table.py",
|
||||||
"alembic/versions/__init__.py",
|
"alembic/versions/__init__.py",
|
||||||
"app/models/user_data.py",
|
"app/models/user_data.py",
|
||||||
"app/models/user_deck.py",
|
"app/models/user_deck.py",
|
||||||
|
"app/models/user_card_import.py",
|
||||||
"app/models/models.py (MtgonlineCard added)",
|
"app/models/models.py (MtgonlineCard added)",
|
||||||
"app/schemas/user_data_schemas.py",
|
"app/schemas/user_data_schemas.py",
|
||||||
"app/schemas/user_deck_schemas.py",
|
"app/schemas/user_deck_schemas.py",
|
||||||
|
"app/schemas/card_import_schemas.py",
|
||||||
"app/routers/user_data.py",
|
"app/routers/user_data.py",
|
||||||
"app/routers/decks.py",
|
"app/routers/decks.py",
|
||||||
|
"app/routers/card_import.py",
|
||||||
"scripts/run_migrations.sh",
|
"scripts/run_migrations.sh",
|
||||||
"TEST_PLAN.md",
|
"TEST_PLAN.md",
|
||||||
"API_DOCUMENTATION.md"
|
"API_DOCUMENTATION.md"
|
||||||
@@ -92,7 +98,9 @@
|
|||||||
"files_modified": [
|
"files_modified": [
|
||||||
"app/models/__init__.py",
|
"app/models/__init__.py",
|
||||||
"Dockerfile",
|
"Dockerfile",
|
||||||
"app/main.py"
|
"app/main.py",
|
||||||
|
"README.md (card import section added)",
|
||||||
|
"backend/README.md (API endpoint reference)"
|
||||||
],
|
],
|
||||||
"decisions": [
|
"decisions": [
|
||||||
"Using Alembic for version-controlled database migrations",
|
"Using Alembic for version-controlled database migrations",
|
||||||
@@ -108,15 +116,13 @@
|
|||||||
"Local card search endpoint for fast deckbuilding queries"
|
"Local card search endpoint for fast deckbuilding queries"
|
||||||
],
|
],
|
||||||
"next_steps": [
|
"next_steps": [
|
||||||
"Test migration execution in container",
|
"Test card import API endpoints in container",
|
||||||
"Run API tests against all endpoints",
|
"Run full API test suite",
|
||||||
"Add rate limiting for production",
|
"Add rate limiting for production",
|
||||||
"Create integration tests",
|
"Create integration tests",
|
||||||
"Deploy to staging environment",
|
"Deploy to staging environment"
|
||||||
"Phase 5: Card import with fuzzy matching (python-Levenshtein)",
|
|
||||||
"Phase 5: Deck builder service for precedents and suggestions"
|
|
||||||
],
|
],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"commit_hash": "c23f88c",
|
"commit_hash": "",
|
||||||
"timestamp": "2026-07-24T04:12:00-04:00"
|
"timestamp": "2026-07-24T04:20:00-04:00"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user