Files
MoviePilot/app/db/oper/downloadhistory.py
T

304 lines
9.7 KiB
Python

from typing import Dict, List, Optional, cast
from sqlalchemy import delete as sqlalchemy_delete, update as sqlalchemy_update
from sqlalchemy.orm import Session
from app.db.base import DbOper
from app.db.models.downloadhistory import DownloadHistory, DownloadFiles
from app.schemas.types import MediaSource
class DownloadHistoryOper(DbOper):
"""
下载历史管理
"""
def get_by_path(self, path: str) -> Optional[DownloadHistory]:
"""
按路径查询下载记录
:param path: 数据key
"""
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_path(session, path)
)
def get_by_hash(self, download_hash: str) -> Optional[DownloadHistory]:
"""
按Hash查询下载记录
:param download_hash: 数据key
"""
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_hash(session, download_hash)
)
def get_by_hashes(self, download_hashes: List[str]) -> Dict[str, DownloadHistory]:
"""
批量按 Hash 查询下载记录,并返回以 Hash 为键的映射。
"""
histories = self._execute_sync_query(
lambda session: DownloadHistory.get_by_hashes(
session, download_hashes
)
)
return {
history.download_hash: history
for history in histories
if history and history.download_hash
}
def get_by_media_identity(
self, media_source: MediaSource, media_id: str,
music_type: Optional[str] = None,
) -> List[DownloadHistory]:
"""
按规范媒体身份查询下载记录。
:param media_source: 媒体数据源
:param media_id: 数据源原生 ID
:param music_type: 音乐实体类型
"""
return self._execute_sync_query(
lambda session: DownloadHistory.get_by_media_identity(
session,
media_source=media_source,
media_id=media_id,
music_type=music_type,
)
)
def add(self, **kwargs):
"""
新增下载历史
"""
self._stage_create(DownloadHistory(**kwargs))
def stage_add(self, payload: dict) -> DownloadHistory:
"""在调用方同步 Session 中暂存下载历史并返回已分配 ID 的记录。"""
if not isinstance(self._db, Session):
raise RuntimeError("下载历史事务写入需要调用方提供同步 Session")
history = DownloadHistory(**payload)
self._db.add(history)
self._db.flush()
return history
def add_files(self, file_items: List[dict]):
"""
新增下载历史文件
"""
for file_item in file_items:
downloadfile = DownloadFiles(**file_item)
self._stage_create(downloadfile)
def stage_add_files(self, file_items: List[dict]) -> None:
"""在调用方事务内批量暂存下载文件,不逐条提交。"""
if not isinstance(self._db, Session):
raise RuntimeError("下载文件事务写入需要调用方提供同步 Session")
self._db.add_all(DownloadFiles(**item) for item in file_items)
self._db.flush()
def truncate_files(self):
"""
清空下载历史文件记录
"""
self._stage_truncate(DownloadFiles)
def get_files_by_hash(self, download_hash: str, state: Optional[int] = None) -> List[DownloadFiles]:
"""
按Hash查询下载文件记录
:param download_hash: 数据key
:param state: 删除状态
"""
return self._execute_sync_query(
lambda session: DownloadFiles.get_by_hash(
session, download_hash, state
)
)
def get_file_by_fullpath(self, fullpath: str) -> Optional[DownloadFiles]:
"""
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return self._execute_sync_query(
lambda session: cast(
Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=False
),
)
)
def get_files_by_fullpath(self, fullpath: str) -> List[DownloadFiles]:
"""
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return self._execute_sync_query(
lambda session: cast(
List[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=True
),
)
)
def get_files_by_savepath(self, fullpath: str) -> List[DownloadFiles]:
"""
按savepath查询下载文件记录
:param fullpath: 数据key
"""
return self._execute_sync_query(
lambda session: DownloadFiles.get_by_savepath(session, fullpath)
)
def delete_file_by_fullpath(self, fullpath: str):
"""
按fullpath删除下载文件记录
:param fullpath: 数据key
"""
self._execute_sync_write(
lambda session: DownloadFiles.delete_by_fullpath(session, fullpath)
)
def stage_delete_file_by_fullpath(self, fullpath: str) -> None:
"""暂存指定完整路径的下载文件记录删除。"""
self._db.execute(
sqlalchemy_update(DownloadFiles)
.where(
DownloadFiles.fullpath == fullpath,
DownloadFiles.state == 1,
)
.values(state=0)
)
def get_hash_by_fullpath(self, fullpath: str) -> Optional[str]:
"""
按fullpath查询下载文件记录hash
:param fullpath: 数据key
"""
fileinfo = self._execute_sync_query(
lambda session: cast(
Optional[DownloadFiles],
DownloadFiles.get_by_fullpath(
session, fullpath=fullpath, all_files=False
),
)
)
if fileinfo:
return fileinfo.download_hash
return ""
def list_by_page(self, page: int = 1, count: int = 30) -> List[DownloadHistory]:
"""
分页查询下载历史
"""
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_page(session, page, count)
)
async def async_list_by_page(
self,
page: int = 1,
count: int = 30,
) -> List[DownloadHistory]:
"""异步分页查询下载历史。"""
return await self._execute_async_query(
lambda session: DownloadHistory.async_list_by_page(
session, page, count
)
)
async def async_delete_history(self, historyid: int):
"""
异步删除下载记录。
"""
await self._stage_async_delete(DownloadHistory, historyid)
def truncate(self):
"""
清空下载记录
"""
self._stage_truncate(DownloadHistory)
def get_last_by(self, mtype=None, title: Optional[str] = None, year: Optional[str] = None,
season: Optional[str] = None, episode: Optional[str] = None,
media_source: Optional[MediaSource] = None,
media_id: Optional[str] = None) -> List[DownloadHistory]:
"""
按类型、标题、年份、季集查询下载记录
媒体身份 + mtype 或 title + year
"""
return self._execute_sync_query(
lambda session: DownloadHistory.get_last_by(
db=session,
mtype=mtype,
title=title,
year=year,
season=season,
episode=episode,
media_source=media_source,
media_id=media_id,
)
)
def list_by_user_date(self, date: str, username: Optional[str] = None) -> List[DownloadHistory]:
"""
查询某用户某时间之前的下载历史
"""
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_user_date(
db=session,
date=date,
username=username,
)
)
def list_by_date(
self, date: str, type: str, media_source: MediaSource, media_id: str,
seasons: Optional[str] = None,
) -> List[DownloadHistory]:
"""
查询某时间之后的下载历史
"""
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_date(
db=session,
date=date,
type=type,
media_source=media_source,
media_id=media_id,
seasons=seasons,
)
)
def list_by_type(self, mtype: str, days: int = 7) -> List[DownloadHistory]:
"""
获取指定类型的下载历史
"""
return self._execute_sync_query(
lambda session: DownloadHistory.list_by_type(
db=session,
mtype=mtype,
days=days,
)
)
def delete_history(self, historyid):
"""
删除下载记录
"""
self._stage_delete(DownloadHistory, historyid)
def stage_delete_history(self, historyid: int) -> None:
"""暂存下载记录删除,事务由调用方统一提交。"""
self._db.execute(
sqlalchemy_delete(DownloadHistory).where(
DownloadHistory.id == historyid
)
)
def delete_downloadfile(self, downloadfileid):
"""
删除下载文件记录
"""
self._stage_delete(DownloadFiles, downloadfileid)