Automated Action c5e673d2ea Implement complete beat marketplace API with FastAPI
- Set up FastAPI project structure with main.py and requirements.txt
- Created SQLite database models for users, beats, and transactions
- Implemented Alembic database migrations
- Added user authentication system with JWT tokens
- Created beat management endpoints (CRUD operations)
- Implemented purchase/transaction system
- Added file upload/download functionality for beat files
- Created health endpoint and API documentation
- Updated README with comprehensive documentation
- Fixed all linting issues with Ruff

Environment variables needed:
- SECRET_KEY: JWT secret key for authentication
2025-07-06 17:42:23 +00:00

66 lines
2.1 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from pathlib import Path
from app.db.session import get_db
from app.models.transaction import Transaction, TransactionStatus
from app.models.beat import Beat
from app.models.user import User
from app.services.auth import get_current_active_user
router = APIRouter()
@router.get("/download/{beat_id}")
async def download_beat(
beat_id: int,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
# Check if user has purchased this beat
transaction = db.query(Transaction).filter(
Transaction.buyer_id == current_user.id,
Transaction.beat_id == beat_id,
Transaction.status == TransactionStatus.COMPLETED
).first()
if not transaction:
# Check if user is the producer of this beat
beat = db.query(Beat).filter(
Beat.id == beat_id,
Beat.producer_id == current_user.id
).first()
if not beat:
raise HTTPException(status_code=403, detail="Access denied - beat not purchased")
else:
beat = transaction.beat
if not beat.file_path or not Path(beat.file_path).exists():
raise HTTPException(status_code=404, detail="Beat file not found")
return FileResponse(
beat.file_path,
media_type='application/octet-stream',
filename=f"{beat.title}.{beat.file_path.split('.')[-1]}"
)
@router.get("/preview/{beat_id}")
async def get_beat_preview(
beat_id: int,
db: Session = Depends(get_db)
):
beat = db.query(Beat).filter(
Beat.id == beat_id,
Beat.is_available
).first()
if not beat:
raise HTTPException(status_code=404, detail="Beat not found")
if not beat.preview_path or not Path(beat.preview_path).exists():
raise HTTPException(status_code=404, detail="Preview not available")
return FileResponse(
beat.preview_path,
media_type='audio/mpeg',
filename=f"{beat.title}_preview.{beat.preview_path.split('.')[-1]}"
)