A kind of initial commit
This commit is contained in:
115
app/db/models.py
Normal file
115
app/db/models.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
|
||||
from sqlalchemy import Boolean, Date, DateTime, Float, ForeignKey, Integer, String, Text, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class User(Base, TimestampMixin):
|
||||
__tablename__ = "users"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
telegram_chat_id: Mapped[str] = mapped_column(String(64), unique=True, index=True)
|
||||
telegram_username: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
|
||||
spotify_user_id: Mapped[str | None] = mapped_column(String(128), unique=True, nullable=True, index=True)
|
||||
spotify_access_token: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
spotify_refresh_token: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
spotify_token_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
spotify_scopes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
timezone: Mapped[str] = mapped_column(String(64), default="UTC")
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
playlist_size: Mapped[int] = mapped_column(Integer, default=30)
|
||||
min_new_ratio: Mapped[float] = mapped_column(Float, default=0.8)
|
||||
last_generated_date: Mapped[date | None] = mapped_column(Date, nullable=True)
|
||||
latest_playlist_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
latest_playlist_url: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
saved_tracks: Mapped[list["SavedTrack"]] = relationship(back_populates="user", cascade="all, delete-orphan")
|
||||
playlist_runs: Mapped[list["PlaylistRun"]] = relationship(back_populates="user", cascade="all, delete-orphan")
|
||||
rec_history: Mapped[list["RecommendationHistory"]] = relationship(
|
||||
back_populates="user", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
|
||||
class AuthState(Base):
|
||||
__tablename__ = "auth_states"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
state: Mapped[str] = mapped_column(String(128), unique=True, index=True)
|
||||
telegram_chat_id: Mapped[str] = mapped_column(String(64), index=True)
|
||||
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
||||
|
||||
|
||||
class SavedTrack(Base):
|
||||
__tablename__ = "saved_tracks"
|
||||
__table_args__ = (UniqueConstraint("user_id", "spotify_track_id", name="uq_saved_track_user_track"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True)
|
||||
spotify_track_id: Mapped[str] = mapped_column(String(128), index=True)
|
||||
name: Mapped[str] = mapped_column(Text)
|
||||
artist_names: Mapped[str] = mapped_column(Text)
|
||||
artist_ids_csv: Mapped[str] = mapped_column(Text)
|
||||
album_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
added_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
popularity: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
|
||||
user: Mapped[User] = relationship(back_populates="saved_tracks")
|
||||
|
||||
|
||||
class RecommendationHistory(Base):
|
||||
__tablename__ = "recommendation_history"
|
||||
__table_args__ = (UniqueConstraint("user_id", "spotify_track_id", name="uq_rec_history_user_track"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True)
|
||||
spotify_track_id: Mapped[str] = mapped_column(String(128), index=True)
|
||||
first_recommended_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
||||
last_recommended_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
||||
times_recommended: Mapped[int] = mapped_column(Integer, default=1)
|
||||
|
||||
user: Mapped[User] = relationship(back_populates="rec_history")
|
||||
|
||||
|
||||
class PlaylistRun(Base, TimestampMixin):
|
||||
__tablename__ = "playlist_runs"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True)
|
||||
run_date: Mapped[date] = mapped_column(Date)
|
||||
status: Mapped[str] = mapped_column(String(32), default="pending")
|
||||
playlist_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
playlist_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
playlist_url: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
total_tracks: Mapped[int] = mapped_column(Integer, default=0)
|
||||
new_tracks: Mapped[int] = mapped_column(Integer, default=0)
|
||||
reused_tracks: Mapped[int] = mapped_column(Integer, default=0)
|
||||
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
user: Mapped[User] = relationship(back_populates="playlist_runs")
|
||||
tracks: Mapped[list["PlaylistRunTrack"]] = relationship(back_populates="run", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class PlaylistRunTrack(Base):
|
||||
__tablename__ = "playlist_run_tracks"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("run_id", "spotify_track_id", name="uq_run_track"),
|
||||
UniqueConstraint("run_id", "position", name="uq_run_position"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
run_id: Mapped[int] = mapped_column(ForeignKey("playlist_runs.id", ondelete="CASCADE"), index=True)
|
||||
spotify_track_id: Mapped[str] = mapped_column(String(128), index=True)
|
||||
name: Mapped[str] = mapped_column(Text)
|
||||
artist_names: Mapped[str] = mapped_column(Text)
|
||||
source: Mapped[str] = mapped_column(String(64))
|
||||
position: Mapped[int] = mapped_column(Integer)
|
||||
is_new_to_bot: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
|
||||
run: Mapped[PlaylistRun] = relationship(back_populates="tracks")
|
||||
Reference in New Issue
Block a user