Initial commit: AudiOhm - Alternative Spotify avec streaming YouTube

Backend:
- FastAPI avec PostgreSQL et Redis
- Authentification JWT complète
- API REST pour musique, playlists, recherche
- Streaming audio via yt-dlp
- SQLAlchemy 2.0 async

Frontend:
- Flutter avec thème néon cyberpunk
- State management Riverpod
- Layout adaptatif desktop/mobile
- Lecteur audio avec mini-player

Infrastructure:
- Docker Compose (PostgreSQL + Redis)
- Scripts d'installation automatisés
- Scripts de build pour exécutables

Fichiers ajoutés:
- BUILD_CLIENT_*.bat/sh: Scripts de compilation
- BUILD_CLIENT_README.md: Documentation compilation
- CHECK_FLUTTER.sh: Vérificateur d'environnement
- requirements.txt mis à jour pour Python 3.13
- Modèles SQLAlchemy corrigés (metadata -> extra_metadata)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
root
2026-01-18 20:08:36 +00:00
commit a89c7894cf
132 changed files with 23178 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
"""Main FastAPI application entry point."""
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from app.core.config import settings
from app.core.database import close_db, init_db
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Lifespan context manager for FastAPI application.
Handles startup and shutdown events.
"""
# Startup
print("Starting up...")
if settings.DEBUG:
print("Debug mode is ON")
print(f"Database URL: {settings.DATABASE_URL}")
print(f"Redis URL: {settings.FULL_REDIS_URL}")
# Initialize database
await init_db()
print("Database initialized")
yield
# Shutdown
print("Shutting down...")
await close_db()
print("Database connections closed")
# Create FastAPI application
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
description="Alternative to Spotify with YouTube streaming",
docs_url="/api/docs",
redoc_url="/api/redoc",
openapi_url="/api/openapi.json",
lifespan=lifespan,
)
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.BACKEND_CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def root() -> dict[str, str]:
"""Root endpoint with API information."""
return {
"name": settings.APP_NAME,
"version": settings.APP_VERSION,
"status": "running",
"docs": "/api/docs",
}
@app.get("/health")
async def health_check() -> dict[str, str]:
"""Health check endpoint."""
return {"status": "healthy"}
@app.get("/api/v1")
async def api_v1_info() -> dict[str, str]:
"""API v1 information endpoint."""
return {
"version": "v1",
"prefix": settings.API_V1_PREFIX,
"docs": "/api/docs",
}
# Exception handlers
@app.exception_handler(Exception)
async def global_exception_handler(request, exc) -> JSONResponse:
"""Global exception handler for unhandled exceptions."""
if settings.DEBUG:
# In debug mode, return full error details
return JSONResponse(
status_code=500,
content={
"detail": str(exc),
"type": type(exc).__name__,
},
)
# In production, return generic error message
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)
# API routes
from app.api.v1 import auth, music, playlists
app.include_router(auth.router, prefix=settings.API_V1_PREFIX, tags=["authentication"])
app.include_router(music.router, prefix=settings.API_V1_PREFIX, tags=["music"])
app.include_router(playlists.router, prefix=settings.API_V1_PREFIX, tags=["playlists"])
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.HOST,
port=settings.PORT,
reload=settings.DEBUG,
log_level=settings.LOG_LEVEL.lower(),
)