From 31fe552af4263330dac23df8fc0ceb6d93608912 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Fri, 9 Jun 2023 15:52:53 +0800 Subject: [PATCH] add transfer notification --- app/chain/__init__.py | 2 +- app/chain/subscribe.py | 12 ++++++ app/chain/transfer.py | 62 ++++++++++++++++++++++++---- app/modules/__init__.py | 2 +- app/modules/filetransfer/__init__.py | 16 ++++--- app/utils/system.py | 23 +++++++++++ 6 files changed, 102 insertions(+), 15 deletions(-) diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 970b09f6..b9ab2cbc 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -105,7 +105,7 @@ class ChainBase(AbstractSingleton, metaclass=Singleton): def remove_torrents(self, hashs: Union[str, list]) -> bool: return self.run_module("remove_torrents", hashs=hashs) - def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[Path]: + def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[dict]: return self.run_module("transfer", path=path, mediainfo=mediainfo) def transfer_completed(self, hashs: Union[str, list]) -> bool: diff --git a/app/chain/subscribe.py b/app/chain/subscribe.py index 20218686..f00a5ba3 100644 --- a/app/chain/subscribe.py +++ b/app/chain/subscribe.py @@ -98,6 +98,9 @@ class SubscribeChain(ChainBase): if exist_flag: logger.info(f'{mediainfo.get_title_string()} 媒体库中已存在,完成订阅') self.subscribes.delete(subscribe.id) + # 发送通知 + self.post_message(title=f'{mediainfo.get_title_string()}{meta.get_season_string()} 已完成订阅', + image=mediainfo.get_message_image()) continue # 搜索 contexts = self.searchchain.process(meta=meta, mediainfo=mediainfo, keyword=subscribe.keyword) @@ -110,6 +113,9 @@ class SubscribeChain(ChainBase): # 全部下载完成 logger.info(f'{mediainfo.get_title_string()} 下载完成,完成订阅') self.subscribes.delete(subscribe.id) + # 发送通知 + self.post_message(title=f'{mediainfo.get_title_string()}{meta.get_season_string()} 已完成订阅', + image=mediainfo.get_message_image()) else: # 未完成下载 logger.info(f'{mediainfo.get_title_string()} 未下载未完整,继续订阅 ...') @@ -176,6 +182,9 @@ class SubscribeChain(ChainBase): if exist_flag: logger.info(f'{mediainfo.get_title_string()} 媒体库中已存在,完成订阅') self.subscribes.delete(subscribe.id) + # 发送通知 + self.post_message(title=f'{mediainfo.get_title_string()}{meta.get_season_string()} 已完成订阅', + image=mediainfo.get_message_image()) continue # 遍历缓存种子 _match_context = [] @@ -200,6 +209,9 @@ class SubscribeChain(ChainBase): # 全部下载完成 logger.info(f'{mediainfo.get_title_string()} 下载完成,完成订阅') self.subscribes.delete(subscribe.id) + # 发送通知 + self.post_message(title=f'{mediainfo.get_title_string()}{meta.get_season_string()} 已完成订阅', + image=mediainfo.get_message_image()) else: # 未完成下载,计算剩余集数 left_episodes = lefts.get(mediainfo.tmdb_id, {}).get("episodes", []) diff --git a/app/chain/transfer.py b/app/chain/transfer.py index 058f6d37..27503c47 100644 --- a/app/chain/transfer.py +++ b/app/chain/transfer.py @@ -1,10 +1,12 @@ -from pathlib import Path from typing import List, Optional from app.chain import ChainBase from app.core import MetaInfo, MediaInfo, settings +from app.core.meta import MetaBase from app.log import logger -from app.utils.types import TorrentStatus +from app.utils.string import StringUtils +from app.utils.system import SystemUtils +from app.utils.types import TorrentStatus, MediaType class TransferChain(ChainBase): @@ -26,7 +28,7 @@ class TransferChain(ChainBase): # 识别 for torrent in torrents: # 识别元数据 - meta = MetaInfo(torrent.get("title")) + meta: MetaBase = MetaInfo(torrent.get("title")) if not meta.get_name(): logger.warn(f'未识别到元数据,标题:{torrent.get("title")}') continue @@ -34,24 +36,70 @@ class TransferChain(ChainBase): mediainfo: MediaInfo = self.recognize_media(meta=meta) if not mediainfo: logger.warn(f'未识别到媒体信息,标题:{torrent.get("title")}') + self.post_message(title=f"{torrent.get('title')} 未识别到媒体信息,无法入库!") continue logger.info(f"{torrent.get('title')} 识别为:{mediainfo.type.value} {mediainfo.get_title_string()}") # 更新媒体图片 self.obtain_image(mediainfo=mediainfo) # 转移 - dest_path: Path = self.transfer(mediainfo=mediainfo, path=torrent.get("path")) - if not dest_path: - logger.warn(f"{torrent.get('title')} 转移失败") + transferinfo: dict = self.transfer(mediainfo=mediainfo, path=torrent.get("path")) + if not transferinfo or not transferinfo.get("target_path"): + logger.warn(f"{torrent.get('title')} 入库失败") + self.post_message( + title=f"{mediainfo.get_title_string()}{meta.get_season_episode_string()} 入库失败!", + text=f"原因:{transferinfo.get('message') if transferinfo else '未知'}\n" + f"路径:{torrent.get('path')}", + image=mediainfo.get_message_image() + ), continue # 转移完成 self.transfer_completed(hashs=torrent.get("hash")) # 刮剥 - self.scrape_metadata(path=dest_path, mediainfo=mediainfo) + self.scrape_metadata(path=transferinfo.get('target_path'), mediainfo=mediainfo) # 移动模式删除种子 if settings.TRANSFER_TYPE == "move": result = self.remove_torrents(hashs=torrent.get("hash")) if result: logger.info(f"移动模式删除种子成功:{torrent.get('title')} ") + # 发送通知 + self.__send_transfer_message(meta=meta, mediainfo=mediainfo, transferinfo=transferinfo) logger.info("下载器文件转移执行完成") return True + + def __send_transfer_message(self, meta: MetaBase, mediainfo: MediaInfo, transferinfo: dict): + """ + 发送入库成功的消息 + """ + # 文件大小 + file_size = StringUtils.str_filesize( + SystemUtils.get_directory_size( + transferinfo.get('target_path') + ) + ) + if mediainfo.type == MediaType.TV: + # 电影 + msg_title = f"{mediainfo.get_title_string()} {meta.get_season_episode_string()} 已入库" + if mediainfo.vote_average: + msg_str = f"评分:{mediainfo.vote_average},类型:{mediainfo.type.value}" + else: + msg_str = f"类型:{mediainfo.type.value}" + if mediainfo.category: + msg_str = f"{msg_str},类别:{mediainfo.category}" + if meta.total_seasons <= 1 and meta.total_episodes == 1: + msg_str = f"{msg_str},大小:{file_size}" + else: + msg_str = f"{msg_str},共{meta.total_seasons}季{meta.total_episodes}集,总大小:{file_size}" + else: + msg_title = f"{mediainfo.get_title_string()} 已入库" + if mediainfo.vote_average: + msg_str = f"评分:{mediainfo.vote_average},类型:电影" + else: + msg_str = "类型:电影" + if mediainfo.category: + msg_str = f"{msg_str},类别:{mediainfo.category}" + if meta.get_resource_type_string(): + msg_str = f"{msg_str},质量:{meta.get_resource_type_string()}" + msg_str = f"{msg_str}, 大小:{file_size}" + # 发送 + self.post_message(title=msg_title, text=msg_str, image=mediainfo.get_message_image()) diff --git a/app/modules/__init__.py b/app/modules/__init__.py index be4410e2..15f53563 100644 --- a/app/modules/__init__.py +++ b/app/modules/__init__.py @@ -149,7 +149,7 @@ class _ModuleBase(metaclass=ABCMeta): """ pass - def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[Path]: + def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[dict]: """ 转移一个路径下的文件 :param path: 文件路径 diff --git a/app/modules/filetransfer/__init__.py b/app/modules/filetransfer/__init__.py index b368694a..c74c7416 100644 --- a/app/modules/filetransfer/__init__.py +++ b/app/modules/filetransfer/__init__.py @@ -26,7 +26,7 @@ class FileTransferModule(_ModuleBase): def init_setting(self) -> Tuple[str, Union[str, bool]]: pass - def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[Path]: + def transfer(self, path: str, mediainfo: MediaInfo) -> Optional[dict]: """ 文件转移 :param path: 文件路径 @@ -36,14 +36,18 @@ class FileTransferModule(_ModuleBase): if not settings.LIBRARY_PATH: logger.error("未设置媒体库目录,无法转移文件") return None - path, msg = self.transfer_media(in_path=Path(path), - meidainfo=mediainfo, - rmt_mode=settings.TRANSFER_TYPE, - target_dir=Path(settings.LIBRARY_PATH)) + target_path, msg = self.transfer_media(in_path=Path(path), + meidainfo=mediainfo, + rmt_mode=settings.TRANSFER_TYPE, + target_dir=Path(settings.LIBRARY_PATH)) if not path: logger.error(msg) - return path + return { + "path": path, + "target_path": target_path, + "message": msg + } @staticmethod def __transfer_command(file_item: Path, target_file: Path, rmt_mode) -> int: diff --git a/app/utils/system.py b/app/utils/system.py index 3b6bccaf..0ce04795 100644 --- a/app/utils/system.py +++ b/app/utils/system.py @@ -97,3 +97,26 @@ class SystemUtils: files.append(path) return files + + @staticmethod + def get_directory_size(path: Path): + """ + 计算目录的大小 + + 参数: + directory_path (Path): 目录路径 + + 返回: + int: 目录的大小(以字节为单位) + """ + if not path or not path.exists(): + return 0 + if path.is_file(): + return path.stat().st_size + total_size = 0 + for path in path.glob('**/*'): + if path.is_file(): + total_size += path.stat().st_size + + return total_size +