🎉 Initial commit: AudiOhm - Alternative à Spotify avec streaming YouTube
Features: - Frontend Flutter avec thème néon cyberpunk - Backend FastAPI avec streaming YouTube - Base de données PostgreSQL + Redis - Authentification JWT complète - Recherche multi-source (DB + YouTube) - Playlists CRUD avec drag & drop - Queue management - Settings avec audio quality - Interface adaptative (Desktop + Mobile) Tech Stack: - Frontend: Flutter 3.2+, Riverpod - Backend: Python 3.11+, FastAPI - Database: PostgreSQL 15+ - Cache: Redis 7+ - Streaming: yt-dlp + FFmpeg 🚀 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""Artist model."""
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import String, ARRAY, Integer
|
||||
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.models.album import Album
|
||||
from app.models.track import Track
|
||||
|
||||
|
||||
class Artist(Base):
|
||||
"""Artist model representing music artists."""
|
||||
|
||||
__tablename__ = "artists"
|
||||
|
||||
# Primary key
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
primary_key=True,
|
||||
default=uuid.uuid4,
|
||||
index=True,
|
||||
)
|
||||
|
||||
# Basic info
|
||||
name: Mapped[str] = mapped_column(
|
||||
String(255),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
image_url: Mapped[str | None] = mapped_column(
|
||||
String(500),
|
||||
)
|
||||
bio: Mapped[str | None] = mapped_column(
|
||||
String(2000),
|
||||
)
|
||||
|
||||
# Genres as array
|
||||
genres: Mapped[list[str]] = mapped_column(
|
||||
ARRAY(String(100)),
|
||||
default=list,
|
||||
)
|
||||
|
||||
# Popularity score (0-100)
|
||||
popularity: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
default=0,
|
||||
)
|
||||
|
||||
# External IDs
|
||||
spotify_id: Mapped[str | None] = mapped_column(
|
||||
String(100),
|
||||
unique=True,
|
||||
index=True,
|
||||
)
|
||||
youtube_id: Mapped[str | None] = mapped_column(
|
||||
String(100),
|
||||
unique=True,
|
||||
index=True,
|
||||
)
|
||||
|
||||
# Additional metadata stored as JSON
|
||||
metadata: Mapped[dict] = mapped_column(
|
||||
JSONB,
|
||||
default=dict,
|
||||
)
|
||||
|
||||
# Timestamps
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
default=datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Relationships
|
||||
albums: Mapped[list["Album"]] = relationship(
|
||||
"Album",
|
||||
back_populates="artist",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="selectin",
|
||||
)
|
||||
tracks: Mapped[list["Track"]] = relationship(
|
||||
"Track",
|
||||
back_populates="artist",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Artist {self.name}>"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert artist model to dictionary."""
|
||||
return {
|
||||
"id": str(self.id),
|
||||
"name": self.name,
|
||||
"image_url": self.image_url,
|
||||
"bio": self.bio,
|
||||
"genres": self.genres,
|
||||
"popularity": self.popularity,
|
||||
"spotify_id": self.spotify_id,
|
||||
"youtube_id": self.youtube_id,
|
||||
"metadata": self.metadata,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"updated_at": self.updated_at.isoformat(),
|
||||
}
|
||||
Reference in New Issue
Block a user