From 7efcde89b95198dedf7ac62382db8b2f4658cfeb Mon Sep 17 00:00:00 2001 From: jxxghp Date: Thu, 7 Sep 2023 14:59:32 +0800 Subject: [PATCH] fix --- app/chain/transfer.py | 9 +- app/core/meta/metabase.py | 4 +- app/db/models/transferhistory.py | 66 ++--- app/db/transferhistory_oper.py | 4 +- app/plugins/dirmonitor/__init__.py | 6 +- app/plugins/libraryscraper/__init__.py | 4 +- app/plugins/mediasyncdel/__init__.py | 317 +++++++++++++------------ app/plugins/messageforward/__init__.py | 9 +- 8 files changed, 218 insertions(+), 201 deletions(-) diff --git a/app/chain/transfer.py b/app/chain/transfer.py index 9328532a..69c6eeaa 100644 --- a/app/chain/transfer.py +++ b/app/chain/transfer.py @@ -242,12 +242,14 @@ class TransferChain(ChainBase): f"回复:```\n/redo {his.id} [tmdbid]|[类型]\n``` 手动识别转移。" )) continue + # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title if not settings.SCRAP_FOLLOW_TMDB: transfer_historys = self.transferhis.get_by(tmdbid=file_mediainfo.tmdb_id, - type=file_mediainfo.type.value) + mtype=file_mediainfo.type.value) if transfer_historys: file_mediainfo.title = transfer_historys[0].title + logger.info(f"{file_path.name} 识别为:{file_mediainfo.type.value} {file_mediainfo.title_year}") # 电视剧没有集无法转移 @@ -338,6 +340,8 @@ class TransferChain(ChainBase): mediainfo=file_mediainfo, transferinfo=transferinfo ) + # 刮削单个文件 + self.scrape_metadata(path=transferinfo.target_path, mediainfo=file_mediainfo) # 更新进度 processed_num += 1 self.progress.update(value=processed_num / total_num * 100, @@ -356,8 +360,6 @@ class TransferChain(ChainBase): # 媒体目录 if transfer_info.target_path.is_file(): transfer_info.target_path = transfer_info.target_path.parent - # 刮削 - self.scrape_metadata(path=transfer_info.target_path, mediainfo=media) # 刷新媒体库,根目录或季目录 self.refresh_mediaserver(mediainfo=media, file_path=transfer_info.target_path) # 发送通知 @@ -586,7 +588,6 @@ class TransferChain(ChainBase): """ logger.info(f"开始删除文件以及空目录:{path} ...") if not path.exists(): - logger.error(f"{path} 不存在") return elif path.is_file(): # 删除文件 diff --git a/app/core/meta/metabase.py b/app/core/meta/metabase.py index bd215153..d2b159ef 100644 --- a/app/core/meta/metabase.py +++ b/app/core/meta/metabase.py @@ -15,9 +15,9 @@ class MetaBase(object): """ # 是否处理的文件 isfile: bool = False - # 原标题字符串 + # 原标题字符串(未经过识别词处理) title: str = "" - # 识别用字符串 + # 识别用字符串(经过识别词处理后) org_string: Optional[str] = None # 副标题 subtitle: Optional[str] = None diff --git a/app/db/models/transferhistory.py b/app/db/models/transferhistory.py index e8158aa2..d4c21626 100644 --- a/app/db/models/transferhistory.py +++ b/app/db/models/transferhistory.py @@ -85,38 +85,48 @@ class TransferHistory(Base): return db.query(func.count(TransferHistory.id)).filter(TransferHistory.title.like(f'%{title}%')).first()[0] @staticmethod - def list_by(db: Session, type: str = None, title: str = None, year: int = None, season: str = None, + def list_by(db: Session, mtype: str = None, title: str = None, year: str = None, season: str = None, episode: str = None, tmdbid: int = None): """ 据tmdbid、season、season_episode查询转移记录 + tmdbid + mtype 或 title + year 必输 """ - if tmdbid and type: - return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, - TransferHistory.type == type).all() - if tmdbid and not season and not episode: - return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid).all() - if tmdbid and season and not episode: - return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, - TransferHistory.seasons == season).all() - if tmdbid and season and episode: - return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, - TransferHistory.seasons == season, - TransferHistory.episodes == episode).all() - # 电视剧所有季集|电影 - if not season and not episode: - return db.query(TransferHistory).filter(TransferHistory.title == title, - TransferHistory.year == year).all() - # 电视剧某季 - if season and not episode: - return db.query(TransferHistory).filter(TransferHistory.title == title, - TransferHistory.year == year, - TransferHistory.seasons == season).all() - # 电视剧某季某集 - if season and episode: - return db.query(TransferHistory).filter(TransferHistory.title == title, - TransferHistory.year == year, - TransferHistory.seasons == season, - TransferHistory.episodes == episode).all() + # TMDBID + 类型 + if tmdbid and mtype: + if season and episode: + # 查询一集 + return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, + TransferHistory.type == mtype, + TransferHistory.seasons == season, + TransferHistory.episodes == episode).all() + elif season: + # 查询一季 + return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, + TransferHistory.type == mtype, + TransferHistory.seasons == season).all() + else: + # 查询所有 + return db.query(TransferHistory).filter(TransferHistory.tmdbid == tmdbid, + TransferHistory.type == mtype).all() + # 标题 + 年份 + elif title and year: + # 电视剧某季某集 + if season and episode: + return db.query(TransferHistory).filter(TransferHistory.title == title, + TransferHistory.year == year, + TransferHistory.seasons == season, + TransferHistory.episodes == episode).all() + # 电视剧某季 + elif season: + return db.query(TransferHistory).filter(TransferHistory.title == title, + TransferHistory.year == year, + TransferHistory.seasons == season).all() + # 电视剧所有季集|电影 + else: + return db.query(TransferHistory).filter(TransferHistory.title == title, + TransferHistory.year == year).all() + + return [] @staticmethod def update_download_hash(db: Session, historyid: int = None, download_hash: str = None): diff --git a/app/db/transferhistory_oper.py b/app/db/transferhistory_oper.py index e04bf4c7..da7c86a7 100644 --- a/app/db/transferhistory_oper.py +++ b/app/db/transferhistory_oper.py @@ -51,13 +51,13 @@ class TransferHistoryOper(DbOper): """ return TransferHistory.statistic(self._db, days) - def get_by(self, title: str = None, year: str = None, type: str = None, + def get_by(self, title: str = None, year: str = None, mtype: str = None, season: str = None, episode: str = None, tmdbid: int = None) -> List[TransferHistory]: """ 按类型、标题、年份、季集查询转移记录 """ return TransferHistory.list_by(db=self._db, - type=type, + mtype=mtype, title=title, year=year, season=season, diff --git a/app/plugins/dirmonitor/__init__.py b/app/plugins/dirmonitor/__init__.py index 73887bd5..8a4b3445 100644 --- a/app/plugins/dirmonitor/__init__.py +++ b/app/plugins/dirmonitor/__init__.py @@ -264,7 +264,7 @@ class DirMonitor(_PluginBase): # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title if not settings.SCRAP_FOLLOW_TMDB: transfer_historys = self.transferhis.get_by(tmdbid=mediainfo.tmdb_id, - type=mediainfo.type.value) + mtype=mediainfo.type.value) if transfer_historys: mediainfo.title = transfer_historys[0].title logger.info(f"{file_path.name} 识别为:{mediainfo.type.value} {mediainfo.title_year}") @@ -315,8 +315,8 @@ class DirMonitor(_PluginBase): transferinfo=transferinfo ) - # 刮削元数据,根目录或季目录 - self.chain.scrape_metadata(path=transferinfo.target_path.parent, + # 刮削单个文件 + self.chain.scrape_metadata(path=transferinfo.target_path, mediainfo=mediainfo) """ diff --git a/app/plugins/libraryscraper/__init__.py b/app/plugins/libraryscraper/__init__.py index 8ef79579..8b61fef7 100644 --- a/app/plugins/libraryscraper/__init__.py +++ b/app/plugins/libraryscraper/__init__.py @@ -353,7 +353,7 @@ class LibraryScraper(_PluginBase): # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title if not settings.SCRAP_FOLLOW_TMDB: transfer_historys = self.transferhis.get_by(tmdbid=mediainfo.tmdb_id, - type=mediainfo.type.value) + mtype=mediainfo.type.value) if transfer_historys: mediainfo.title = transfer_historys[0].title @@ -379,7 +379,7 @@ class LibraryScraper(_PluginBase): except Exception as err: print(str(err)) - # 开始刮削 + # 刮削单个文件 self.chain.scrape_metadata(path=file, mediainfo=mediainfo) @staticmethod diff --git a/app/plugins/mediasyncdel/__init__.py b/app/plugins/mediasyncdel/__init__.py index 668ec25f..163f9147 100644 --- a/app/plugins/mediasyncdel/__init__.py +++ b/app/plugins/mediasyncdel/__init__.py @@ -22,7 +22,7 @@ from app.modules.qbittorrent import Qbittorrent from app.modules.themoviedb.tmdbv3api import Episode from app.modules.transmission import Transmission from app.plugins import _PluginBase -from app.schemas.types import NotificationType, EventType +from app.schemas.types import NotificationType, EventType, MediaType from app.utils.path_utils import PathUtils @@ -116,154 +116,154 @@ class MediaSyncDel(_PluginBase): 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 """ return [ - { - 'component': 'VForm', - 'content': [ - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'enabled', - 'label': '启用插件', - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'notify', - 'label': '发送通知', - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'del_source', - 'label': '删除源文件', - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VSelect', - 'props': { - 'model': 'sync_type', - 'label': '同步方式', - 'items': [ - {'title': 'webhook', 'value': 'webhook'}, - {'title': '日志', 'value': 'log'}, - {'title': 'Scripter X', 'value': 'plugin'} - ] - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VTextField', - 'props': { - 'model': 'cron', - 'label': '执行周期', - 'placeholder': '5位cron表达式,留空自动' - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 4 - }, - 'content': [ - { - 'component': 'VTextField', - 'props': { - 'model': 'exclude_path', - 'label': '排除路径' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VAlert', - 'props': { - 'text': '同步方式分为webhook、日志同步和Scripter X。' - 'webhook需要Emby4.8.0.45及以上开启媒体删除的webhook' - '(建议使用媒体库刮削插件覆盖元数据重新刮削剧集路径)。' - '日志同步需要配置执行周期,默认30分钟执行一次。' - 'Scripter X方式需要emby安装并配置Scripter X插件,无需配置执行周期。' - } - } - ] - } - ] - } - ] - } - ], { - "enabled": False, - "notify": True, - "del_source": False, - "sync_type": "webhook", - "cron": "*/30 * * * *", - "exclude_path": "", - } + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'enabled', + 'label': '启用插件', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'notify', + 'label': '发送通知', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'del_source', + 'label': '删除源文件', + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'model': 'sync_type', + 'label': '同步方式', + 'items': [ + {'title': 'webhook', 'value': 'webhook'}, + {'title': '日志', 'value': 'log'}, + {'title': 'Scripter X', 'value': 'plugin'} + ] + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'cron', + 'label': '执行周期', + 'placeholder': '5位cron表达式,留空自动' + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 4 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'exclude_path', + 'label': '排除路径' + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'text': '同步方式分为webhook、日志同步和Scripter X。' + 'webhook需要Emby4.8.0.45及以上开启媒体删除的webhook' + '(建议使用媒体库刮削插件覆盖元数据重新刮削剧集路径)。' + '日志同步需要配置执行周期,默认30分钟执行一次。' + 'Scripter X方式需要emby安装并配置Scripter X插件,无需配置执行周期。' + } + } + ] + } + ] + } + ] + } + ], { + "enabled": False, + "notify": True, + "del_source": False, + "sync_type": "webhook", + "cron": "*/30 * * * *", + "exclude_path": "", + } def get_page(self) -> List[dict]: """ @@ -639,29 +639,36 @@ class MediaSyncDel(_PluginBase): if episode_num: episode_num = str(episode_num).rjust(2, '0') + # 类型 + mtype = MediaType.MOVIE if media_type in ["Movie", "MOV"] else MediaType.TV + # 删除电影 - if media_type == "Movie" or media_type == "MOV": + if mtype == MediaType.MOVIE: msg = f'电影 {media_name} {tmdb_id}' - transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id) + transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id, + mtype=mtype.value) # 删除电视剧 - elif (media_type == "Series" or media_type == "TV") and not season_num and not episode_num: + elif mtype == MediaType.TV and not season_num and not episode_num: msg = f'剧集 {media_name} {tmdb_id}' - transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id) + transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id, + mtype=mtype.value) # 删除季 S02 - elif (media_type == "Season" or media_type == "TV") and season_num and not episode_num: + elif mtype == MediaType.TV and season_num and not episode_num: if not season_num or not str(season_num).isdigit(): logger.error(f"{media_name} 季同步删除失败,未获取到具体季") return msg = f'剧集 {media_name} S{season_num} {tmdb_id}' transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id, + mtype=mtype.value, season=f'S{season_num}') # 删除剧集S02E02 - elif (media_type == "Episode" or media_type == "TV") and season_num and episode_num: + elif mtype == MediaType.TV and season_num and episode_num: if not season_num or not str(season_num).isdigit() or not episode_num or not str(episode_num).isdigit(): logger.error(f"{media_name} 集同步删除失败,未获取到具体集") return msg = f'剧集 {media_name} S{season_num}E{episode_num} {tmdb_id}' transfer_history: List[TransferHistory] = self._transferhis.get_by(tmdbid=tmdb_id, + mtype=mtype.value, season=f'S{season_num}', episode=f'E{episode_num}') else: diff --git a/app/plugins/messageforward/__init__.py b/app/plugins/messageforward/__init__.py index 4927ab2d..fabd5399 100644 --- a/app/plugins/messageforward/__init__.py +++ b/app/plugins/messageforward/__init__.py @@ -275,8 +275,7 @@ class MessageForward(_PluginBase): return access_token, appid def __send_message(self, title: str, text: str = None, userid: str = None, access_token: str = None, - appid: str = None, i: int = None) -> \ - Optional[bool]: + appid: str = None, i: int = None) -> Optional[bool]: """ 发送文本消息 :param title: 消息标题 @@ -305,8 +304,8 @@ class MessageForward(_PluginBase): } return self.__post_request(message_url=message_url, req_json=req_json, i=i, title=title) - def __send_image_message(self, title: str, text: str, image_url: str, userid: str = None, access_token: str = None, - appid: str = None, i: int = None) -> Optional[bool]: + def __send_image_message(self, title: str, text: str, image_url: str, userid: str = None, + access_token: str = None, appid: str = None, i: int = None) -> Optional[bool]: """ 发送图文消息 :param title: 消息标题 @@ -372,7 +371,7 @@ class MessageForward(_PluginBase): logger.error(f"转发消息 {title} 异常,错误信息:{err}") return False - def __get_access_token(self, corpid, appsecret): + def __get_access_token(self, corpid: str, appsecret: str): """ 获取微信Token :return: 微信Token