Files
bili-sync/commands.py

86 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
import functools
from pathlib import Path
from typing import Callable
from loguru import logger
from constants import MediaStatus, MediaType
from models import FavoriteItem
from processor import process_favorite_item
from utils import aexists, aremove
async def recheck():
"""刷新数据库中视频的状态,如果发现文件不存在则标记未下载,以便在下次任务重新下载,在自己手动删除文件后调用"""
async def is_ok(item: FavoriteItem) -> bool:
if len(item.pages):
# 多 p 视频全部存在才算存在
return all(await asyncio.gather(*[aexists(page.video_path) for page in item.pages]))
return await aexists(item.video_path)
items = await FavoriteItem.filter(
type=MediaType.VIDEO, status=MediaStatus.NORMAL, downloaded=True
).prefetch_related("pages")
items_to_update = []
for item in items:
for page in item.pages:
# 疑似 tortoise 的 bugprefetch_related 不会更新反向引用的字段,这里手动更新一下
page.favorite_item = item
items_ok = await asyncio.gather(*[is_ok(item) for item in items], return_exceptions=True)
for item, ok in zip(items, items_ok):
if isinstance(ok, Exception):
logger.error("Error when checking file {} {}: {}.", item.bvid, item.name, ok)
continue
if not ok:
logger.info("Lack of file detected for {} {}, mark as not downloaded.", item.bvid, item.name)
item.downloaded = False
items_to_update.append(item)
logger.info("Updating database...")
await FavoriteItem.bulk_update(items_to_update, fields=["downloaded"], batch_size=300)
logger.info("Database updated.")
async def _refresh_favorite_item_info(
path_getter: Callable[[FavoriteItem], list[Path]],
process_poster: bool = False,
process_video: bool = False,
process_nfo: bool = False,
process_upper: bool = False,
process_subtitle: bool = False,
force: bool = False,
):
items = await FavoriteItem.filter(downloaded=True).prefetch_related("upper")
if force:
# 如果强制刷新,那么就先把现存的所有内容删除
await asyncio.gather(*[aremove(path) for item in items for path in path_getter(item)], return_exceptions=True)
await asyncio.gather(
*[
process_favorite_item(
item,
process_poster=process_poster,
process_video=process_video,
process_nfo=process_nfo,
process_upper=process_upper,
process_subtitle=process_subtitle,
refresh_mode=True,
)
for item in items
],
return_exceptions=True,
)
refresh_nfo = functools.partial(_refresh_favorite_item_info, lambda item: [item.nfo_path], process_nfo=True)
refresh_poster = functools.partial(_refresh_favorite_item_info, lambda item: [item.poster_path], process_poster=True)
refresh_video = functools.partial(_refresh_favorite_item_info, lambda item: [item.video_path], process_video=True)
refresh_upper = functools.partial(_refresh_favorite_item_info, lambda item: item.upper_path, process_upper=True)
refresh_subtitle = functools.partial(
_refresh_favorite_item_info, lambda item: [item.subtitle_path], process_subtitle=True
)