"""Track model.""" from typing import Any from sqlalchemy import BigInteger, Column, Enum, Integer, SmallInteger, String, select from sqlalchemy.orm import Mapped, Session, mapped_column from video.connectors import mysql from video.constants import track_field as tf class Track(mysql.ArModel): """Track.""" __tablename__ = "track" track_id = Column( Integer, name="id", nullable=False, primary_key=True, autoincrement=True, ) product_id = Column(Integer, name="release_id", nullable=False) # Basic Metadata track_name = Column(String(255)) meta_language_code = Column("meta_language", String(8)) isrc = Column(String(16)) p_info = Column(String(255), name="p_line") explicit: Mapped[str] = mapped_column( Enum("Y", "N", "C", ""), name="explicit_lyrics", default="N" ) upc = Column(BigInteger, name="upc", nullable=False) preview_start_time = Column( Integer, name="preview_start_time", default=None, nullable=True ) offer_type: Mapped[str | None] = mapped_column( Enum( tf.OFFER_TYPE_ALL, tf.OFFER_TYPE_ALBUM_DOWNLOAD_ONLY, tf.OFFER_TYPE_TRACK_DOWNLOAD_ONLY, tf.OFFER_TYPE_TRACK_DOWNLOAD_STREAM, tf.OFFER_TYPE_ALBUM_TRACK_DOWNLOAD, tf.OFFER_TYPE_ALBUM_DOWNLOAD_STREAM, tf.OFFER_TYPE_STREAM_ONLY, tf.OFFER_TYPE_NONE, ), name="offer_type", default=tf.OFFER_TYPE_ALL, ) stereo_or_mono: Mapped[str | None] = mapped_column( Enum( tf.STEREO_TYPE, tf.STEREO_MONO_TYPE, tf.STEREO_5_1_SURROUND_TYPE, ), name="stereo_or_mono", ) # Track Ordering volume_number = Column(SmallInteger, name="cd", nullable=False) track_number = Column(SmallInteger, name="track_id", nullable=False) track_type: Mapped[str | None] = mapped_column( Enum(tf.TRACK_TYPE_MUSIC, tf.TRACK_TYPE_VIDEO), name="track_type", default=tf.TRACK_TYPE_MUSIC, ) duration_minutes = Column( SmallInteger, name="length_minute", nullable=True, default=None, ) duration_seconds = Column( SmallInteger, name="length_seconds", nullable=True, default=None, ) closed_caption_exists = Column( SmallInteger, name="closed_caption_exists", nullable=True, default=None, ) closed_caption_reason_id = Column( SmallInteger, name="closed_caption_reason_id", nullable=True, default=None, ) def to_dict(self) -> dict[str, Any]: """Get a dict representation.""" return { "track_id": self.track_id, "track_name": self.track_name, "track_number": self.track_number, "isrc": self.isrc, "explicit": self.explicit, "upc": self.upc, "p_info": self.p_info, "offer_type": self.offer_type, "meta_language_code": self.meta_language_code, "stereo_or_mono": self.stereo_or_mono, "preview_start_time": self.preview_start_time, "track_type": self.track_type, "volume_number": self.volume_number, "product_id": self.product_id, "duration_minutes": self.duration_minutes, "duration_seconds": self.duration_seconds, "closed_caption_exists": self.closed_caption_exists, "closed_caption_reason_id": self.closed_caption_reason_id, } def _get(track_id: int | None, session: Session) -> Track | None: return session.execute( select(Track).where(Track.track_id == track_id) ).scalar_one_or_none() def upsert(track: dict[str, Any], session: Session | None = None) -> dict[str, Any]: """Create or update.""" if session is None: with mysql.ar_db_session() as s: return upsert(track, s) track_entry = _get(track.get("track_id"), session) if track_entry: return update(track_entry, track, session) return create(track, session) def create(track: dict[str, Any], session: Session) -> dict[str, Any]: """Create a track entry.""" track_model = Track(**track) session.add(track_model) session.flush() return track_model.to_dict() def update( track: Track, track_update: dict[str, Any], session: Session, ) -> dict[str, Any]: """Update track.""" for field_name, value in track_update.items(): setattr(track, field_name, value) session.add(track) session.flush() return track.to_dict() def get_tracks_by_product_id( product_id: int, volume_number: int | None = None, *, session: Session | None = None, ) -> list[dict[str, Any]]: """Get tracks product_id.""" if session is None: with mysql.ar_db_session() as s: return get_tracks_by_product_id(product_id, volume_number, session=s) filters = [Track.product_id == product_id] if volume_number is not None: filters.append(Track.volume_number == volume_number) tracks = session.execute(select(Track).where(*filters)).scalars().all() return [track.to_dict() for track in tracks]