diff --git a/app/chain/transfer.py b/app/chain/transfer.py index d294015c..e71318e6 100644 --- a/app/chain/transfer.py +++ b/app/chain/transfer.py @@ -233,256 +233,256 @@ class TransferChain(ChainBase): # 文件或蓝光目录 file_items.append(trans_item) - if formaterHandler: - # 有集自定义格式,过滤文件 - file_items = [f for f in file_items if formaterHandler.match(f.name)] + if formaterHandler: + # 有集自定义格式,过滤文件 + file_items = [f for f in file_items if formaterHandler.match(f.name)] - # 过滤后缀和大小 - file_items = [f for f in file_items - if f.extension and (f".{f.extension.lower()}" in self.all_exts + settings.RMT_AUDIO_TRACK_EXT - and (not min_filesize or f.size > min_filesize * 1024 * 1024))] + # 过滤后缀和大小 + file_items = [f for f in file_items + if f.extension and (f".{f.extension.lower()}" in self.all_exts + settings.RMT_AUDIO_TRACK_EXT + and (not min_filesize or f.size > min_filesize * 1024 * 1024))] - if not file_items: - logger.warn(f"{fileitem.path} 没有找到可整理的媒体文件") - return False, f"{fileitem.name} 没有找到可整理的媒体文件" + if not file_items: + logger.warn(f"{fileitem.path} 没有找到可整理的媒体文件") + return False, f"{fileitem.name} 没有找到可整理的媒体文件" - # 更新总文件数 - total_num = len(file_items) - logger.info(f"正在整理 {len(file_items)} 个文件...") + # 更新总文件数 + total_num = len(file_items) + logger.info(f"正在整理 {len(file_items)} 个文件...") - # 整理所有文件 - for file_item in file_items: - if global_vars.is_system_stopped: - break - file_path = Path(file_item.path) - # 回收站及隐藏的文件不处理 - if file_item.path.find('/@Recycle/') != -1 \ - or file_item.path.find('/#recycle/') != -1 \ - or file_item.path.find('/.') != -1 \ - or file_item.path.find('/@eaDir') != -1: - logger.debug(f"{file_item.path} 是回收站或隐藏的文件") - # 计数 - processed_num += 1 - skip_num += 1 - continue + # 整理所有文件 + for file_item in file_items: + if global_vars.is_system_stopped: + break + file_path = Path(file_item.path) + # 回收站及隐藏的文件不处理 + if file_item.path.find('/@Recycle/') != -1 \ + or file_item.path.find('/#recycle/') != -1 \ + or file_item.path.find('/.') != -1 \ + or file_item.path.find('/@eaDir') != -1: + logger.debug(f"{file_item.path} 是回收站或隐藏的文件") + # 计数 + processed_num += 1 + skip_num += 1 + continue - # 整理屏蔽词不处理 - is_blocked = False - if transfer_exclude_words: - for keyword in transfer_exclude_words: - if not keyword: - continue - if keyword and re.search(r"%s" % keyword, file_item.path, re.IGNORECASE): - logger.info(f"{file_item.path} 命中整理屏蔽词 {keyword},不处理") - is_blocked = True - break - if is_blocked: - err_msgs.append(f"{file_item.name} 命中整理屏蔽词") - # 计数 - processed_num += 1 - skip_num += 1 - continue - - # 整理成功的不再处理 - if not force: - transferd = self.transferhis.get_by_src(file_item.path, storage=file_item.storage) - if transferd and transferd.status: - logger.info(f"{file_item.path} 已成功整理过,如需重新处理,请删除历史记录。") - # 计数 - processed_num += 1 - skip_num += 1 + # 整理屏蔽词不处理 + is_blocked = False + if transfer_exclude_words: + for keyword in transfer_exclude_words: + if not keyword: continue + if keyword and re.search(r"%s" % keyword, file_item.path, re.IGNORECASE): + logger.info(f"{file_item.path} 命中整理屏蔽词 {keyword},不处理") + is_blocked = True + break + if is_blocked: + err_msgs.append(f"{file_item.name} 命中整理屏蔽词") + # 计数 + processed_num += 1 + skip_num += 1 + continue - # 更新进度 - self.progress.update(value=processed_num / total_num * 100, - text=f"正在整理 ({processed_num + 1}/{total_num}){file_item.name} ...", - key=ProgressKey.FileTransfer) - - if not meta: - # 文件元数据 - file_meta = MetaInfoPath(file_path) - else: - file_meta = meta - - # 合并季 - if season is not None: - file_meta.begin_season = season - - if not file_meta: - logger.error(f"{file_path} 无法识别有效信息") - err_msgs.append(f"{file_path} 无法识别有效信息") + # 整理成功的不再处理 + if not force: + transferd = self.transferhis.get_by_src(file_item.path, storage=file_item.storage) + if transferd and transferd.status: + logger.info(f"{file_item.path} 已成功整理过,如需重新处理,请删除历史记录。") # 计数 processed_num += 1 - fail_num += 1 + skip_num += 1 continue - # 自定义识别 - if formaterHandler: - # 开始集、结束集、PART - begin_ep, end_ep, part = formaterHandler.split_episode(file_path.name) - if begin_ep is not None: - file_meta.begin_episode = begin_ep - file_meta.part = part - if end_ep is not None: - file_meta.end_episode = end_ep + # 更新进度 + self.progress.update(value=processed_num / total_num * 100, + text=f"正在整理 ({processed_num + 1}/{total_num}){file_item.name} ...", + key=ProgressKey.FileTransfer) - if not mediainfo: - # 识别媒体信息 - file_mediainfo = self.mediachain.recognize_by_meta(file_meta) - else: - file_mediainfo = mediainfo + if not meta: + # 文件元数据 + file_meta = MetaInfoPath(file_path) + else: + file_meta = meta - if not file_mediainfo: - logger.warn(f'{file_path} 未识别到媒体信息') - # 新增整理失败历史记录 - his = self.transferhis.add_fail( - fileitem=file_item, - mode=transfer_type, - meta=file_meta, - download_hash=download_hash - ) - self.post_message(Notification( - mtype=NotificationType.Manual, - title=f"{file_path.name} 未识别到媒体信息,无法入库!", - text=f"回复:```\n/redo {his.id} [tmdbid]|[类型]\n``` 手动识别整理。", - link=settings.MP_DOMAIN('#/history') - )) - # 计数 - processed_num += 1 - fail_num += 1 - continue + # 合并季 + if season is not None: + file_meta.begin_season = season - # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title - if not settings.SCRAP_FOLLOW_TMDB: - transfer_history = self.transferhis.get_by_type_tmdbid(tmdbid=file_mediainfo.tmdb_id, - mtype=file_mediainfo.type.value) - if transfer_history: - file_mediainfo.title = transfer_history.title + if not file_meta: + logger.error(f"{file_path} 无法识别有效信息") + err_msgs.append(f"{file_path} 无法识别有效信息") + # 计数 + processed_num += 1 + fail_num += 1 + continue - logger.info(f"{file_path.name} 识别为:{file_mediainfo.type.value} {file_mediainfo.title_year}") + # 自定义识别 + if formaterHandler: + # 开始集、结束集、PART + begin_ep, end_ep, part = formaterHandler.split_episode(file_path.name) + if begin_ep is not None: + file_meta.begin_episode = begin_ep + file_meta.part = part + if end_ep is not None: + file_meta.end_episode = end_ep - # 获取集数据 - if file_mediainfo.type == MediaType.TV: - if file_meta.begin_season is None: - file_meta.begin_season = 1 - file_mediainfo.season = file_mediainfo.season or file_meta.begin_season - episodes_info = self.tmdbchain.tmdb_episodes( - tmdbid=file_mediainfo.tmdb_id, - season=file_mediainfo.season - ) - else: - episodes_info = None + if not mediainfo: + # 识别媒体信息 + file_mediainfo = self.mediachain.recognize_by_meta(file_meta) + else: + file_mediainfo = mediainfo - # 获取下载hash - if not download_hash: - download_file = self.downloadhis.get_file_by_fullpath(file_item.path) - if download_file: - download_hash = download_file.download_hash - - # 执行整理 - transferinfo: TransferInfo = self.transfer(fileitem=file_item, - meta=file_meta, - mediainfo=file_mediainfo, - transfer_type=transfer_type, - target_storage=target_storage, - target_path=target_path, - episodes_info=episodes_info, - scrape=scrape) - if not transferinfo: - logger.error("文件整理模块运行失败") - return False, "文件整理模块运行失败" - if not transferinfo.success: - # 整理失败 - logger.warn(f"{file_path.name} 入库失败:{transferinfo.message}") - err_msgs.append(f"{file_path.name} {transferinfo.message}") - # 新增整理失败历史记录 - self.transferhis.add_fail( - fileitem=file_item, - mode=transfer_type, - download_hash=download_hash, - meta=file_meta, - mediainfo=file_mediainfo, - transferinfo=transferinfo - ) - # 发送消息 - self.post_message(Notification( - mtype=NotificationType.Manual, - title=f"{file_mediainfo.title_year} {file_meta.season_episode} 入库失败!", - text=f"原因:{transferinfo.message or '未知'}", - image=file_mediainfo.get_message_image(), - link=settings.MP_DOMAIN('#/history') - )) - # 计数 - processed_num += 1 - fail_num += 1 - continue - - # 汇总信息 - current_transfer_type = transferinfo.transfer_type - mkey = (file_mediainfo.tmdb_id, file_meta.begin_season) - if mkey not in medias: - # 新增信息 - metas[mkey] = file_meta - medias[mkey] = file_mediainfo - season_episodes[mkey] = file_meta.episode_list - transfers[mkey] = transferinfo - else: - # 合并季集清单 - season_episodes[mkey] = list(set(season_episodes[mkey] + file_meta.episode_list)) - # 合并整理数据 - transfers[mkey].file_count += transferinfo.file_count - transfers[mkey].total_size += transferinfo.total_size - transfers[mkey].file_list.extend(transferinfo.file_list) - transfers[mkey].file_list_new.extend(transferinfo.file_list_new) - transfers[mkey].fail_list.extend(transferinfo.fail_list) - - # 新增整理成功历史记录 - self.transferhis.add_success( + if not file_mediainfo: + logger.warn(f'{file_path} 未识别到媒体信息') + # 新增整理失败历史记录 + his = self.transferhis.add_fail( fileitem=file_item, - mode=transfer_type or transferinfo.transfer_type, + mode=transfer_type, + meta=file_meta, + download_hash=download_hash + ) + self.post_message(Notification( + mtype=NotificationType.Manual, + title=f"{file_path.name} 未识别到媒体信息,无法入库!", + text=f"回复:```\n/redo {his.id} [tmdbid]|[类型]\n``` 手动识别整理。", + link=settings.MP_DOMAIN('#/history') + )) + # 计数 + processed_num += 1 + fail_num += 1 + continue + + # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title + if not settings.SCRAP_FOLLOW_TMDB: + transfer_history = self.transferhis.get_by_type_tmdbid(tmdbid=file_mediainfo.tmdb_id, + mtype=file_mediainfo.type.value) + if transfer_history: + file_mediainfo.title = transfer_history.title + + logger.info(f"{file_path.name} 识别为:{file_mediainfo.type.value} {file_mediainfo.title_year}") + + # 获取集数据 + if file_mediainfo.type == MediaType.TV: + if file_meta.begin_season is None: + file_meta.begin_season = 1 + file_mediainfo.season = file_mediainfo.season or file_meta.begin_season + episodes_info = self.tmdbchain.tmdb_episodes( + tmdbid=file_mediainfo.tmdb_id, + season=file_mediainfo.season + ) + else: + episodes_info = None + + # 获取下载hash + if not download_hash: + download_file = self.downloadhis.get_file_by_fullpath(file_item.path) + if download_file: + download_hash = download_file.download_hash + + # 执行整理 + transferinfo: TransferInfo = self.transfer(fileitem=file_item, + meta=file_meta, + mediainfo=file_mediainfo, + transfer_type=transfer_type, + target_storage=target_storage, + target_path=target_path, + episodes_info=episodes_info, + scrape=scrape) + if not transferinfo: + logger.error("文件整理模块运行失败") + return False, "文件整理模块运行失败" + if not transferinfo.success: + # 整理失败 + logger.warn(f"{file_path.name} 入库失败:{transferinfo.message}") + err_msgs.append(f"{file_path.name} {transferinfo.message}") + # 新增整理失败历史记录 + self.transferhis.add_fail( + fileitem=file_item, + mode=transfer_type, download_hash=download_hash, meta=file_meta, mediainfo=file_mediainfo, transferinfo=transferinfo ) - - # 更新进度 + # 发送消息 + self.post_message(Notification( + mtype=NotificationType.Manual, + title=f"{file_mediainfo.title_year} {file_meta.season_episode} 入库失败!", + text=f"原因:{transferinfo.message or '未知'}", + image=file_mediainfo.get_message_image(), + link=settings.MP_DOMAIN('#/history') + )) + # 计数 processed_num += 1 - self.progress.update(value=processed_num / total_num * 100, - text=f"{file_path.name} 整理完成", - key=ProgressKey.FileTransfer) + fail_num += 1 + continue - # 目录或文件整理完成 - self.progress.update(text=f"{trans_item.path} 整理完成,正在执行后续处理 ...", - key=ProgressKey.FileTransfer) + # 汇总信息 + current_transfer_type = transferinfo.transfer_type + mkey = (file_mediainfo.tmdb_id, file_meta.begin_season) + if mkey not in medias: + # 新增信息 + metas[mkey] = file_meta + medias[mkey] = file_mediainfo + season_episodes[mkey] = file_meta.episode_list + transfers[mkey] = transferinfo + else: + # 合并季集清单 + season_episodes[mkey] = list(set(season_episodes[mkey] + file_meta.episode_list)) + # 合并整理数据 + transfers[mkey].file_count += transferinfo.file_count + transfers[mkey].total_size += transferinfo.total_size + transfers[mkey].file_list.extend(transferinfo.file_list) + transfers[mkey].file_list_new.extend(transferinfo.file_list_new) + transfers[mkey].fail_list.extend(transferinfo.fail_list) - # 执行后续处理 - for mkey, media in medias.items(): - transfer_meta = metas[mkey] - transfer_info = transfers[mkey] - # 发送通知 - if transfer_info.need_notify: - se_str = None - if media.type == MediaType.TV: - se_str = f"{transfer_meta.season} {StringUtils.format_ep(season_episodes[mkey])}" - self.send_transfer_message(meta=transfer_meta, - mediainfo=media, - transferinfo=transfer_info, - season_episode=se_str) - # 刮削事件 - if scrape or transfer_info.need_scrape: - self.eventmanager.send_event(EventType.MetadataScrape, { - 'meta': transfer_meta, - 'mediainfo': media, - 'fileitem': transfer_info.target_diritem - }) - # 整理完成事件 - self.eventmanager.send_event(EventType.TransferComplete, { + # 新增整理成功历史记录 + self.transferhis.add_success( + fileitem=file_item, + mode=transfer_type or transferinfo.transfer_type, + download_hash=download_hash, + meta=file_meta, + mediainfo=file_mediainfo, + transferinfo=transferinfo + ) + + # 更新进度 + processed_num += 1 + self.progress.update(value=processed_num / total_num * 100, + text=f"{file_path.name} 整理完成", + key=ProgressKey.FileTransfer) + + # 目录或文件整理完成 + self.progress.update(text=f"{trans_item.path} 整理完成,正在执行后续处理 ...", + key=ProgressKey.FileTransfer) + + # 执行后续处理 + for mkey, media in medias.items(): + transfer_meta = metas[mkey] + transfer_info = transfers[mkey] + # 发送通知 + if transfer_info.need_notify: + se_str = None + if media.type == MediaType.TV: + se_str = f"{transfer_meta.season} {StringUtils.format_ep(season_episodes[mkey])}" + self.send_transfer_message(meta=transfer_meta, + mediainfo=media, + transferinfo=transfer_info, + season_episode=se_str) + # 刮削事件 + if scrape or transfer_info.need_scrape: + self.eventmanager.send_event(EventType.MetadataScrape, { 'meta': transfer_meta, 'mediainfo': media, - 'transferinfo': transfer_info, - 'download_hash': download_hash, + 'fileitem': transfer_info.target_diritem }) + # 整理完成事件 + self.eventmanager.send_event(EventType.TransferComplete, { + 'meta': transfer_meta, + 'mediainfo': media, + 'transferinfo': transfer_info, + 'download_hash': download_hash, + }) # 移动模式处理 if current_transfer_type in ["move"]: