feat: Add dashboard API endpoints and service for sound statistics
Some checks failed
Backend CI / lint (push) Failing after 4m52s
Backend CI / test (push) Failing after 3m42s

This commit is contained in:
JSC
2025-08-11 11:16:45 +02:00
parent bb1f036caa
commit 49ad6c8581
5 changed files with 133 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ from fastapi import APIRouter
from app.api.v1 import (
admin,
auth,
dashboard,
extractions,
files,
main,
@@ -19,6 +20,7 @@ api_router = APIRouter(prefix="/v1")
# Include all route modules
api_router.include_router(auth.router, tags=["authentication"])
api_router.include_router(dashboard.router, tags=["dashboard"])
api_router.include_router(extractions.router, tags=["extractions"])
api_router.include_router(files.router, tags=["files"])
api_router.include_router(main.router, tags=["main"])

29
app/api/v1/dashboard.py Normal file
View File

@@ -0,0 +1,29 @@
"""Dashboard API endpoints."""
from typing import Annotated, Any
from fastapi import APIRouter, Depends
from app.core.dependencies import get_current_user, get_dashboard_service
from app.models.user import User
from app.services.dashboard import DashboardService
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
@router.get("/soundboard-statistics")
async def get_soundboard_statistics(
_current_user: Annotated[User, Depends(get_current_user)],
dashboard_service: Annotated[DashboardService, Depends(get_dashboard_service)],
) -> dict[str, Any]:
"""Get soundboard statistics."""
return await dashboard_service.get_soundboard_statistics()
@router.get("/track-statistics")
async def get_track_statistics(
_current_user: Annotated[User, Depends(get_current_user)],
dashboard_service: Annotated[DashboardService, Depends(get_dashboard_service)],
) -> dict[str, Any]:
"""Get track statistics."""
return await dashboard_service.get_track_statistics()

View File

@@ -9,7 +9,9 @@ from app.core.database import get_db
from app.core.logging import get_logger
from app.models.user import User
from app.services.auth import AuthService
from app.services.dashboard import DashboardService
from app.services.oauth import OAuthService
from app.repositories.sound import SoundRepository
from app.utils.auth import JWTUtils, TokenUtils
logger = get_logger(__name__)
@@ -184,3 +186,11 @@ async def get_admin_user(
detail="Not enough permissions",
)
return current_user
async def get_dashboard_service(
session: Annotated[AsyncSession, Depends(get_db)],
) -> DashboardService:
"""Get the dashboard service."""
sound_repository = SoundRepository(session)
return DashboardService(sound_repository)

View File

@@ -178,3 +178,49 @@ class SoundRepository(BaseRepository[Sound]):
search_query, sound_types, sort_by, sort_order
)
raise
async def get_soundboard_statistics(self) -> dict[str, int | float]:
"""Get statistics for SDB type sounds."""
try:
statement = select(
func.count(Sound.id).label("count"),
func.sum(Sound.play_count).label("total_plays"),
func.sum(Sound.duration).label("total_duration"),
func.sum(Sound.size + func.coalesce(Sound.normalized_size, 0)).label("total_size")
).where(Sound.type == "SDB")
result = await self.session.exec(statement)
row = result.first()
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": row.total_duration if row.total_duration is not None else 0,
"total_size": row.total_size if row.total_size is not None else 0
}
except Exception:
logger.exception("Failed to get soundboard statistics")
raise
async def get_track_statistics(self) -> dict[str, int | float]:
"""Get statistics for EXT type sounds."""
try:
statement = select(
func.count(Sound.id).label("count"),
func.sum(Sound.play_count).label("total_plays"),
func.sum(Sound.duration).label("total_duration"),
func.sum(Sound.size + func.coalesce(Sound.normalized_size, 0)).label("total_size")
).where(Sound.type == "EXT")
result = await self.session.exec(statement)
row = result.first()
return {
"count": row.count if row.count is not None else 0,
"total_plays": row.total_plays if row.total_plays is not None else 0,
"total_duration": row.total_duration if row.total_duration is not None else 0,
"total_size": row.total_size if row.total_size is not None else 0
}
except Exception:
logger.exception("Failed to get track statistics")
raise

46
app/services/dashboard.py Normal file
View File

@@ -0,0 +1,46 @@
"""Dashboard service for statistics and analytics."""
from typing import Any
from app.core.logging import get_logger
from app.repositories.sound import SoundRepository
logger = get_logger(__name__)
class DashboardService:
"""Service for dashboard statistics and analytics."""
def __init__(self, sound_repository: SoundRepository) -> None:
"""Initialize the dashboard service."""
self.sound_repository = sound_repository
async def get_soundboard_statistics(self) -> dict[str, Any]:
"""Get comprehensive soundboard statistics."""
try:
stats = await self.sound_repository.get_soundboard_statistics()
return {
"sound_count": stats["count"],
"total_play_count": stats["total_plays"],
"total_duration": stats["total_duration"],
"total_size": stats["total_size"],
}
except Exception:
logger.exception("Failed to get soundboard statistics")
raise
async def get_track_statistics(self) -> dict[str, Any]:
"""Get comprehensive track statistics."""
try:
stats = await self.sound_repository.get_track_statistics()
return {
"track_count": stats["count"],
"total_play_count": stats["total_plays"],
"total_duration": stats["total_duration"],
"total_size": stats["total_size"],
}
except Exception:
logger.exception("Failed to get track statistics")
raise