import datetime
from abc import abstractmethod
from dataclasses import dataclass
from pathlib import Path
from models import FavoriteItem, FavoriteItemPage, Upper
from utils import aopen
@dataclass
class Base:
"""基类,有个工具方法"""
@abstractmethod
def to_xml(self) -> str:
...
@staticmethod
def escape(s: str) -> str:
"""转义 xml 特殊字符"""
return s.translate(str.maketrans({"<": "<", ">": ">", "&": "&", "'": "'", '"': """}))
async def to_file(self, path: Path) -> None:
"""把 xml 写入文件"""
async with aopen(path, "w", encoding="utf-8") as f:
await f.write(self.to_xml())
@dataclass
class EpisodeInfo(Base):
"""分p的单集信息"""
title: str
season: int
episode: int
@staticmethod
def from_favorite_item_page(page: FavoriteItemPage) -> "EpisodeInfo":
return EpisodeInfo(title=page.name, season=1, episode=page.page)
def to_xml(self) -> str:
return f"""
{self.escape(self.title)}
{self.season}
{self.episode}
""".strip()
@dataclass
class Actor(Base):
name: str
role: str
@staticmethod
def from_upper(upper: Upper) -> "Actor":
return Actor(name=upper.mid, role=upper.name)
def to_xml(self) -> str:
return f"""
{self.name}
{self.escape(self.role)}
""".strip()
@dataclass
class MovieInfo(Base):
"""单p的视频信息"""
title: str
plot: str
tags: list[str]
actor: list[Actor]
bvid: str
aired: datetime.datetime
@staticmethod
def from_favorite_item(fav_item: FavoriteItem) -> "MovieInfo":
return MovieInfo(
title=fav_item.name,
plot=fav_item.desc,
actor=[Actor.from_upper(fav_item.upper)],
tags=fav_item.tags,
bvid=fav_item.bvid,
aired=fav_item.ctime,
)
def to_xml(self) -> str:
actor = "\n".join(_.to_xml() for _ in self.actor)
tags = (
"\n".join(f" {self.escape(_)}" for _ in self.tags) if isinstance(self.tags, list) else ""
)
return f"""
{self.escape(self.title)}
{actor}
{self.aired.year}
{tags}
{self.bvid}
{self.aired.strftime("%Y-%m-%d")}
""".strip()
@dataclass
class TVShowInfo(Base):
title: str
plot: str
tags: list[str]
actor: list[Actor]
bvid: str
aired: datetime.datetime
@staticmethod
def from_favorite_item(fav_item: FavoriteItem) -> "TVShowInfo":
return TVShowInfo(
title=fav_item.name,
plot=fav_item.desc,
actor=[Actor.from_upper(fav_item.upper)],
tags=fav_item.tags,
bvid=fav_item.bvid,
aired=fav_item.ctime,
)
def to_xml(self) -> str:
actor = "\n".join(_.to_xml() for _ in self.actor)
tags = (
"\n".join(f" {self.escape(_)}" for _ in self.tags) if isinstance(self.tags, list) else ""
)
return f"""
{self.escape(self.title)}
{actor}
{self.aired.year}
{tags}
{self.bvid}
{self.aired.strftime("%Y-%m-%d")}
""".strip()
@dataclass
class UpperInfo(Base):
mid: int
created_at: datetime.datetime
def from_upper(upper: Upper) -> "UpperInfo":
return UpperInfo(mid=upper.mid, created_at=upper.created_at)
def to_xml(self) -> str:
return f"""
false
{self.created_at.strftime("%Y-%m-%d %H:%M:%S")}
{self.mid}
{self.mid}
""".strip()