From 78b31352762ff0b98064a2f0333bbcd2c82a00d5 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Thu, 28 Sep 2023 12:35:41 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=AA=92=E4=BD=93=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=88=A0=E9=99=A4=E6=8F=92=E4=BB=B6=EF=BC=9A?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=89=8B=E5=8A=A8=E5=88=A0=E9=99=A4=E6=BA=90?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8C=E6=AD=A5=E5=A4=84=E7=90=86=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/history.py | 9 +++++ app/chain/transfer.py | 1 + app/db/downloadhistory_oper.py | 10 ++++++ app/plugins/mediasyncdel/__init__.py | 54 +++++++++++++++------------- app/schemas/types.py | 4 +-- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/app/api/endpoints/history.py b/app/api/endpoints/history.py index 4cd28956..19a4ad13 100644 --- a/app/api/endpoints/history.py +++ b/app/api/endpoints/history.py @@ -6,11 +6,13 @@ from sqlalchemy.orm import Session from app import schemas from app.chain.transfer import TransferChain +from app.core.event import eventmanager from app.core.security import verify_token from app.db import get_db from app.db.models.downloadhistory import DownloadHistory from app.db.models.transferhistory import TransferHistory from app.schemas import MediaType +from app.schemas.types import EventType router = APIRouter() @@ -78,6 +80,13 @@ def delete_transfer_history(history_in: schemas.TransferHistory, # 删除源文件 if deletesrc and history.src: TransferChain(db).delete_files(Path(history.src)) + # 发送事件 + eventmanager.send_event( + EventType.DownloadFileDeleted, + { + "src": history.src + } + ) # 删除记录 TransferHistory.delete(db, history_in.id) return schemas.Response(success=True) diff --git a/app/chain/transfer.py b/app/chain/transfer.py index ad4c6bfd..1ea8f4d2 100644 --- a/app/chain/transfer.py +++ b/app/chain/transfer.py @@ -589,6 +589,7 @@ class TransferChain(ChainBase): def delete_files(path: Path): """ 删除转移后的文件以及空目录 + :param path: 文件路径 """ logger.info(f"开始删除文件以及空目录:{path} ...") if not path.exists(): diff --git a/app/db/downloadhistory_oper.py b/app/db/downloadhistory_oper.py index 926290c1..9012aed7 100644 --- a/app/db/downloadhistory_oper.py +++ b/app/db/downloadhistory_oper.py @@ -74,6 +74,16 @@ class DownloadHistoryOper(DbOper): """ DownloadFiles.delete_by_fullpath(self._db, fullpath) + def get_hash_by_fullpath(self, fullpath: str) -> str: + """ + 按fullpath查询下载文件记录hash + :param fullpath: 数据key + """ + fileinfo: DownloadFiles = DownloadFiles.get_by_fullpath(self._db, fullpath) + if fileinfo: + return fileinfo.download_hash + return "" + def list_by_page(self, page: int = 1, count: int = 30) -> List[DownloadHistory]: """ 分页查询下载历史 diff --git a/app/plugins/mediasyncdel/__init__.py b/app/plugins/mediasyncdel/__init__.py index 43c12a8d..f869ffc8 100644 --- a/app/plugins/mediasyncdel/__init__.py +++ b/app/plugins/mediasyncdel/__init__.py @@ -25,9 +25,9 @@ from app.schemas.types import NotificationType, EventType, MediaType class MediaSyncDel(_PluginBase): # 插件名称 - plugin_name = "媒体库同步删除" + plugin_name = "媒体文件同步删除" # 插件描述 - plugin_desc = "媒体库删除媒体后同步删除历史记录、源文件和下载任务。" + plugin_desc = "同步删除历史记录、源文件和下载任务。" # 插件图标 plugin_icon = "mediasyncdel.png" # 主题色 @@ -187,9 +187,9 @@ class MediaSyncDel(_PluginBase): 'component': 'VSelect', 'props': { 'model': 'sync_type', - 'label': '同步方式', + 'label': '媒体库同步方式', 'items': [ - {'title': 'webhook', 'value': 'webhook'}, + {'title': 'Webhook', 'value': 'webhook'}, {'title': '日志', 'value': 'log'}, {'title': 'Scripter X', 'value': 'plugin'} ] @@ -208,7 +208,7 @@ class MediaSyncDel(_PluginBase): 'component': 'VTextField', 'props': { 'model': 'cron', - 'label': '执行周期', + 'label': '日志检查周期', 'placeholder': '5位cron表达式,留空自动' } } @@ -246,7 +246,7 @@ class MediaSyncDel(_PluginBase): 'props': { 'model': 'library_path', 'rows': '2', - 'label': '媒体库路径', + 'label': '媒体库路径映射', 'placeholder': '媒体服务器路径:MoviePilot路径(一行一个)' } } @@ -266,11 +266,11 @@ class MediaSyncDel(_PluginBase): { 'component': 'VAlert', 'props': { - 'text': '同步方式分为webhook、日志同步和Scripter X。' - 'webhook需要Emby4.8.0.45及以上开启媒体删除的webhook' - '(建议使用媒体库刮削插件覆盖元数据重新刮削剧集路径)。' - '日志同步需要配置执行周期,默认30分钟执行一次。' - 'Scripter X方式需要emby安装并配置Scripter X插件,无需配置执行周期。' + 'text': '媒体库同步方式分为Webhook、日志同步和Scripter X:' + '1、Webhook需要Emby4.8.0.45及以上开启媒体删除的Webhook。' + '2、日志同步需要配置检查周期,默认30分钟执行一次。' + '3、Scripter X方式需要emby安装并配置Scripter X插件,无需配置执行周期。' + '4、启用该插件后,非媒体服务器触发的源文件删除,也会同步处理下载器中的下载任务。' } } ] @@ -1202,21 +1202,27 @@ class MediaSyncDel(_PluginBase): except Exception as e: logger.error("退出插件失败:%s" % str(e)) - @eventmanager.register(EventType.MediaDeleted) - def remote_sync_del(self, event: Event): + @eventmanager.register(EventType.DownloadFileDeleted) + def downloadfile_del_sync(self, event: Event): """ - 媒体库同步删除 + 下载文件删除处理事件 """ - if event: - logger.info("收到命令,开始执行媒体库同步删除 ...") - self.post_message(channel=event.event_data.get("channel"), - title="开始媒体库同步删除 ...", - userid=event.event_data.get("user")) - self.sync_del_by_log() - - if event: - self.post_message(channel=event.event_data.get("channel"), - title="媒体库同步删除完成!", userid=event.event_data.get("user")) + if not self._enabled: + return + if not event: + return + event_data = event.event_data + src = event_data.get("src") + if not src: + return + # 源文件路径 + src_path = Path(src) + # 查询下载hash + download_hash = self._downloadhis.get_hash_by_fullpath(src_path) + if download_hash: + self.handle_torrent(src=src, torrent_hash=download_hash) + else: + logger.warn(f"未查询到文件 {src} 对应的下载记录") @staticmethod def get_tmdbimage_url(path: str, prefix="w500"): diff --git a/app/schemas/types.py b/app/schemas/types.py index e19655bc..340a3e1d 100644 --- a/app/schemas/types.py +++ b/app/schemas/types.py @@ -34,8 +34,8 @@ class EventType(Enum): DownloadAdded = "download.added" # 删除历史记录 HistoryDeleted = "history.deleted" - # 删除媒体库文件 - MediaDeleted = "media.deleted" + # 删除下载源文件 + DownloadFileDeleted = "downloadfile.deleted" # 用户外来消息 UserMessage = "user.message" # 通知消息