1
0
card/api/app/routes/sync.py
2025-06-01 21:39:53 +09:00

151 lines
4.2 KiB
Python

"""Synchronization routes for atproto"""
from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from pydantic import BaseModel
from app.auth.dependencies import require_user, AuthUser
from app.db.base import get_db
from app.services.card_sync import CardSyncService
from app.repositories.user import UserRepository
router = APIRouter(prefix="/sync", tags=["sync"])
class SyncRequest(BaseModel):
"""Sync request model"""
atproto_session: str # Session string from atproto login
class SyncResponse(BaseModel):
"""Sync response model"""
synced_to_pds: int = 0
imported_from_pds: int = 0
message: str
@router.post("/cards", response_model=SyncResponse)
async def sync_cards(
request: SyncRequest,
current_user: AuthUser = Depends(require_user),
db: AsyncSession = Depends(get_db)
):
"""
Sync cards between database and atproto PDS
- **atproto_session**: Session string from atproto login
"""
try:
# Get user from database
user_repo = UserRepository(db)
user = await user_repo.get_by_did(current_user.did)
if not user:
raise HTTPException(status_code=404, detail="User not found")
# Create sync service
sync_service = CardSyncService(db, request.atproto_session)
# Import from PDS first
imported = await sync_service.import_cards_from_pds(current_user.did)
# Then sync all cards to PDS
synced = await sync_service.sync_all_user_cards(user.id, current_user.did)
await db.commit()
return SyncResponse(
synced_to_pds=synced,
imported_from_pds=imported,
message=f"Successfully synced {synced} cards to PDS and imported {imported} cards from PDS"
)
except Exception as e:
await db.rollback()
raise HTTPException(status_code=500, detail=str(e))
@router.post("/export")
async def export_to_pds(
request: SyncRequest,
current_user: AuthUser = Depends(require_user),
db: AsyncSession = Depends(get_db)
):
"""
Export all cards to atproto PDS
- **atproto_session**: Session string from atproto login
"""
try:
user_repo = UserRepository(db)
user = await user_repo.get_by_did(current_user.did)
if not user:
raise HTTPException(status_code=404, detail="User not found")
sync_service = CardSyncService(db, request.atproto_session)
synced = await sync_service.sync_all_user_cards(user.id, current_user.did)
return {
"exported": synced,
"message": f"Successfully exported {synced} cards to PDS"
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/import")
async def import_from_pds(
request: SyncRequest,
current_user: AuthUser = Depends(require_user),
db: AsyncSession = Depends(get_db)
):
"""
Import cards from atproto PDS
- **atproto_session**: Session string from atproto login
"""
try:
sync_service = CardSyncService(db, request.atproto_session)
imported = await sync_service.import_cards_from_pds(current_user.did)
await db.commit()
return {
"imported": imported,
"message": f"Successfully imported {imported} cards from PDS"
}
except Exception as e:
await db.rollback()
raise HTTPException(status_code=500, detail=str(e))
@router.get("/verify/{card_id}")
async def verify_card_ownership(
card_id: int,
unique_id: Optional[str] = None,
current_user: AuthUser = Depends(require_user),
db: AsyncSession = Depends(get_db)
):
"""
Verify user owns a specific card
- **card_id**: Card type ID (0-15)
- **unique_id**: Unique ID for unique cards
"""
sync_service = CardSyncService(db)
owns_card = await sync_service.verify_card_ownership(
current_user.did,
card_id,
unique_id
)
return {
"card_id": card_id,
"unique_id": unique_id,
"owned": owns_card
}
# Import Optional
from typing import Optional