fediversion/backend/routers/reviews.py
fullsizemalt b4cddf41ea feat: Initialize Fediversion multi-band platform
- Fork elmeg-demo codebase for multi-band support
- Add data importer infrastructure with base class
- Create band-specific importers:
  - phish.py: Phish.net API v5
  - grateful_dead.py: Grateful Stats API
  - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm)
- Add spec-kit configuration for Gemini
- Update README with supported bands and architecture
2025-12-28 12:39:28 -08:00

93 lines
3.3 KiB
Python

from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlmodel import Session, select, func
from database import get_session
from models import Review, User, Profile
from schemas import ReviewCreate, ReviewRead
from auth import get_current_user
from services.gamification import award_xp, check_and_award_badges, update_streak, XP_REWARDS
router = APIRouter(prefix="/reviews", tags=["reviews"])
@router.post("/", response_model=ReviewRead)
def create_review(
review: ReviewCreate,
session: Session = Depends(get_session),
current_user: User = Depends(get_current_user)
):
# Create model from schema data + user_id
db_review = Review(**review.model_dump(), user_id=current_user.id)
session.add(db_review)
session.flush() # Ensure ID is generated for badge checks if needed
# Check if this is user's first review for bonus XP
# We check relative to THIS review just being added (id > 0)
review_count = session.exec(
select(func.count(Review.id)).where(Review.user_id == current_user.id)
).one() or 0
# Award XP
xp_amount = XP_REWARDS["review_write"]
if review_count <= 1: # This is the first one
xp_amount += XP_REWARDS["first_review"] # Bonus for first review
try:
award_xp(session, current_user, xp_amount, "review")
update_streak(session, current_user)
check_and_award_badges(session, current_user)
except Exception as e:
# Don't fail the review if gamification fails, but log it
print(f"Error in gamification service during review: {e}")
session.commit()
session.refresh(db_review)
return db_review
@router.get("/")
def read_reviews(
show_id: Optional[int] = None,
venue_id: Optional[int] = None,
song_id: Optional[int] = None,
performance_id: Optional[int] = None,
tour_id: Optional[int] = None,
year: Optional[int] = None,
offset: int = 0,
limit: int = Query(default=100, le=100),
session: Session = Depends(get_session)
):
query = select(Review)
if show_id:
query = query.where(Review.show_id == show_id)
if venue_id:
query = query.where(Review.venue_id == venue_id)
if song_id:
query = query.where(Review.song_id == song_id)
if performance_id:
query = query.where(Review.performance_id == performance_id)
if tour_id:
query = query.where(Review.tour_id == tour_id)
if year:
query = query.where(Review.year == year)
reviews = session.exec(query.offset(offset).limit(limit)).all()
# Enrich with user profile data
result = []
for review in reviews:
user = session.get(User, review.user_id)
profile = session.exec(
select(Profile).where(Profile.user_id == review.user_id)
).first()
result.append({
**review.model_dump(),
"user": {
"id": user.id if user else review.user_id,
"username": profile.username if profile else f"User {review.user_id}",
"display_name": profile.display_name if profile else None,
"avatar_bg_color": user.avatar_bg_color if user else "#0F4C81",
"avatar_text": user.avatar_text if user else None,
} if user else None
})
return result