Jarian Cottingham 06877fb2fc feat: add TUI (Textual User Interface) with download queue system
- 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
2026-02-25 15:59:15 -06:00

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", ""),
)