"""Main routes for the application.""" from datetime import datetime, timedelta from zoneinfo import ZoneInfo from flask import Blueprint, request from sqlalchemy import desc, func from app.database import db from app.models.playlist import Playlist from app.models.sound import Sound from app.models.sound_played import SoundPlayed from app.models.user import User from app.services.decorators import require_auth bp = Blueprint("main", __name__) @bp.route("/health") def health() -> dict[str, str]: """Health check endpoint.""" return {"status": "ok"} def get_period_filter(period: str) -> datetime | None: """Get the start date for the specified period.""" now = datetime.now(tz=ZoneInfo("UTC")) if period == "today": return now.replace(hour=0, minute=0, second=0, microsecond=0) if period == "week": return now - timedelta(days=7) if period == "month": return now - timedelta(days=30) if period == "year": return now - timedelta(days=365) if period == "all": return None # Default to all time return None @bp.route("/dashboard/stats") @require_auth def dashboard_stats() -> dict: """Get dashboard statistics.""" # Count soundboard sounds (type = SDB) soundboard_count = Sound.query.filter_by(type="SDB").count() # Count tracks (type = STR) track_count = Sound.query.filter_by(type="STR").count() # Count playlists playlist_count = Playlist.query.count() # Calculate total size of all sounds (original + normalized) total_size_result = db.session.query( func.sum(Sound.size).label("original_size"), func.sum(Sound.normalized_size).label("normalized_size"), ).first() original_size = getattr(total_size_result, "original_size", 0) or 0 normalized_size = getattr(total_size_result, "normalized_size", 0) or 0 total_size = original_size + normalized_size return { "soundboard_sounds": soundboard_count, "tracks": track_count, "playlists": playlist_count, "total_size": total_size, "original_size": original_size, "normalized_size": normalized_size, } @bp.route("/dashboard/top-sounds") @require_auth def top_sounds() -> dict: """Get top played sounds for a specific period.""" period = request.args.get("period", "all") limit = int(request.args.get("limit", 5)) period_start = get_period_filter(period) # Base query for soundboard sounds with play counts query = ( db.session.query( Sound.id, Sound.name, Sound.filename, Sound.thumbnail, Sound.type, func.count(SoundPlayed.id).label("play_count"), ) .outerjoin(SoundPlayed, Sound.id == SoundPlayed.sound_id) .filter(Sound.type == "SDB") # Only soundboard sounds .group_by( Sound.id, Sound.name, Sound.filename, Sound.thumbnail, Sound.type, ) ) # Apply period filter if specified if period_start: query = query.filter(SoundPlayed.played_at >= period_start) # Order by play count and limit results results = query.order_by(desc("play_count")).limit(limit).all() # Convert to list of dictionaries top_sounds_list = [ { "id": result.id, "name": result.name, "filename": result.filename, "thumbnail": result.thumbnail, "type": result.type, "play_count": result.play_count, } for result in results ] return { "period": period, "sounds": top_sounds_list, } @bp.route("/dashboard/top-tracks") @require_auth def top_tracks() -> dict: """Get top played tracks for a specific period.""" period = request.args.get("period", "all") limit = int(request.args.get("limit", 10)) period_start = get_period_filter(period) # Base query for tracks with play counts query = ( db.session.query( Sound.id, Sound.name, Sound.filename, Sound.thumbnail, Sound.type, func.count(SoundPlayed.id).label("play_count"), ) .outerjoin(SoundPlayed, Sound.id == SoundPlayed.sound_id) .filter(Sound.type == "STR") # Only tracks .group_by( Sound.id, Sound.name, Sound.filename, Sound.thumbnail, Sound.type, ) ) # Apply period filter if specified if period_start: query = query.filter(SoundPlayed.played_at >= period_start) # Order by play count and limit results results = query.order_by(desc("play_count")).limit(limit).all() # Convert to list of dictionaries top_tracks_list = [ { "id": result.id, "name": result.name, "filename": result.filename, "thumbnail": result.thumbnail, "type": result.type, "play_count": result.play_count, } for result in results ] return { "period": period, "tracks": top_tracks_list, } @bp.route("/dashboard/top-users") @require_auth def top_users() -> dict: """Get top users by play count for a specific period.""" period = request.args.get("period", "all") limit = int(request.args.get("limit", 10)) period_start = get_period_filter(period) # Base query for users with play counts query = ( db.session.query( User.id, User.name, User.email, User.picture, func.count(SoundPlayed.id).label("play_count"), ) .outerjoin(SoundPlayed, User.id == SoundPlayed.user_id) .group_by(User.id, User.name, User.email, User.picture) ) # Apply period filter if specified if period_start: query = query.filter(SoundPlayed.played_at >= period_start) # Order by play count and limit results results = query.order_by(desc("play_count")).limit(limit).all() # Convert to list of dictionaries top_users_list = [ { "id": result.id, "name": result.name, "email": result.email, "picture": result.picture, "play_count": result.play_count, } for result in results ] return { "period": period, "users": top_users_list, }