"""Synchronization routes for atproto""" from typing import Optional 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_session 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_session) ): """ 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_session) ): """ 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_session) ): """ 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_session) ): """ 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