- New TUI using Textual framework with responsive interface - Search, results, download, and queue screens for YouTube video management - Download queue system with sequential background downloads - Status bar with queue count and download progress indicators - Comprehensive test suite (97 tests) with 100% pass rate - Modern Python packaging with pyproject.toml and uv support - Added requirements-tui.txt for TUI-specific dependencies - Updated setup.py and install.sh for TUI integration - Enhanced README.md with TUI usage documentation
78 lines
2.1 KiB
Python
78 lines
2.1 KiB
Python
"""
|
|
Video data model for YouTube TUI
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass
|
|
class Video:
|
|
"""Represents a YouTube video"""
|
|
|
|
video_id: str
|
|
title: str
|
|
channel: str
|
|
channel_id: str
|
|
duration: str
|
|
view_count: str
|
|
upload_date: str
|
|
description: str
|
|
thumbnail_url: Optional[str] = None
|
|
is_short: bool = False
|
|
url: str = ""
|
|
|
|
def __post_init__(self) -> None:
|
|
"""Post-initialization to set URL and detect shorts"""
|
|
if not self.url:
|
|
self.url = f"https://www.youtube.com/watch?v={self.video_id}"
|
|
|
|
if "/shorts/" in self.url or self.duration == "0:00":
|
|
self.is_short = True
|
|
|
|
@property
|
|
def display_title(self) -> str:
|
|
"""Get title with short indicator"""
|
|
if self.is_short:
|
|
return f"(short) {self.title}"
|
|
return self.title
|
|
|
|
@property
|
|
def display_duration(self) -> str:
|
|
"""Get formatted duration"""
|
|
if self.is_short:
|
|
return "Short"
|
|
return self.duration
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to dictionary for JSON serialization"""
|
|
return {
|
|
"video_id": self.video_id,
|
|
"title": self.title,
|
|
"channel": self.channel,
|
|
"channel_id": self.channel_id,
|
|
"duration": self.duration,
|
|
"view_count": self.view_count,
|
|
"upload_date": self.upload_date,
|
|
"description": self.description,
|
|
"thumbnail_url": self.thumbnail_url,
|
|
"is_short": self.is_short,
|
|
"url": self.url,
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: dict) -> "Video":
|
|
"""Create Video instance from dictionary"""
|
|
return cls(
|
|
video_id=data["video_id"],
|
|
title=data["title"],
|
|
channel=data["channel"],
|
|
channel_id=data["channel_id"],
|
|
duration=data["duration"],
|
|
view_count=data["view_count"],
|
|
upload_date=data["upload_date"],
|
|
description=data.get("description", ""),
|
|
thumbnail_url=data.get("thumbnail_url"),
|
|
url=data.get("url", ""),
|
|
)
|