import json import pathlib from pathlib import Path from typing import Optional, Dict, List, Union from sqlalchemy import Column, Integer, String, Boolean, JSON, Date, ForeignKey, BigInteger from sqlalchemy.orm import relationship, Session, deferred from sqlalchemy.orm.collections import InstrumentedList from modules.videos.errors import UnknownVideo, UnknownChannel from wrolpi.captions import read_captions from wrolpi.common import Base, ModelHelper, logger, get_media_directory, background_task, replace_file from wrolpi.db import get_db_curs, get_db_session, optional_session from wrolpi.downloader import Download, download_manager, DownloadFrequency from wrolpi.files.lib import refresh_files, split_path_stem_and_suffix from wrolpi.files.models import FileGroup from wrolpi.media_path import MediaPathType from wrolpi.tags import Tag, TagFile from wrolpi.vars import PYTEST logger = logger.getChild(__name__) __all__ = ['Video', 'Channel', 'ChannelDownload'] class Video(ModelHelper, Base): __tablename__ = 'video' id = Column(Integer, primary_key=True) source_id = Column(String) # The id from yt-dlp view_count = Column(Integer) # The view count from the ChannelDownloader (or from initial download) ffprobe_json = deferred(Column(JSON)) # Data that is fetched once from ffprobe (ffmpeg) have_comments = Column(Boolean, default=False) # see `get_missing_videos_comments` comments_failed = Column(Boolean, default=False) # see `get_missing_videos_comments` channel_id = Column(Integer, ForeignKey('channel.id')) channel = relationship('Channel', primaryjoin='Video.channel_id==Channel.id', back_populates='videos') file_group_id = Column(BigInteger, ForeignKey('file_group.id', ondelete='CASCADE'), unique=True, nullable=False) file_group: FileGroup = relationship('FileGroup') def __repr__(self): v = None if self.video_path: v = repr(str(self.video_path.relative_to(get_media_directory()))) return f'