diff --git a/package.json b/package.json index 3d7ddbe..e96e86d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "DoubanSync": { "name": "豆瓣想看", "description": "同步豆瓣想看数据,自动添加订阅。", - "version": "1.1", + "version": "1.2", "icon": "douban.png", "author": "jxxghp", "level": 2 @@ -58,7 +58,7 @@ "DoubanRank": { "name": "豆瓣榜单订阅", "description": "监控豆瓣热门榜单,自动添加订阅。", - "version": "1.2", + "version": "1.4", "icon": "movie.jpg", "author": "jxxghp", "level": 2 @@ -66,7 +66,7 @@ "LibraryScraper": { "name": "媒体库刮削", "description": "定时对媒体库进行刮削,补齐缺失元数据和图片。", - "version": "1.1", + "version": "1.2", "icon": "scraper.png", "author": "jxxghp", "level": 1 @@ -210,7 +210,7 @@ "BrushFlow": { "name": "站点刷流", "description": "自动托管刷流,将会提高对应站点的访问频率。", - "version": "1.0", + "version": "1.1", "icon": "brush.jpg", "author": "jxxghp", "level": 2 @@ -258,7 +258,7 @@ "CloudDiskDel": { "name": "云盘文件删除", "description": "媒体库删除strm文件后同步删除云盘资源。", - "version": "1.1", + "version": "1.2", "icon": "clouddisk.png", "author": "thsrite", "level": 1 @@ -322,7 +322,7 @@ "FFmpegThumb": { "name": "FFmpeg缩略图", "description": "TheMovieDb没有背景图片时使用FFmpeg截取视频文件缩略图", - "version": "1.0", + "version": "1.2", "icon": "ffmpeg.png", "author": "jxxghp", "level": 1 diff --git a/plugins/brushflow/__init__.py b/plugins/brushflow/__init__.py index 8859ee7..44a0c51 100644 --- a/plugins/brushflow/__init__.py +++ b/plugins/brushflow/__init__.py @@ -31,7 +31,7 @@ class BrushFlow(_PluginBase): # 插件图标 plugin_icon = "brush.jpg" # 插件版本 - plugin_version = "1.0" + plugin_version = "1.1" # 插件作者 plugin_author = "jxxghp" # 作者主页 @@ -64,6 +64,7 @@ class BrushFlow(_PluginBase): _downloader = "qbittorrent" _disksize = 0 _freeleech = "free" + _hr = "no" _maxupspeed = 0 _maxdlspeed = 0 _maxdlcount = 0 @@ -96,6 +97,7 @@ class BrushFlow(_PluginBase): self._downloader = config.get("downloader") self._disksize = config.get("disksize") self._freeleech = config.get("freeleech") + self._hr = config.get("hr") self._maxupspeed = config.get("maxupspeed") self._maxdlspeed = config.get("maxdlspeed") self._maxdlcount = config.get("maxdlcount") @@ -411,6 +413,26 @@ class BrushFlow(_PluginBase): } ] }, + { + 'component': 'VCol', + 'props': { + "cols": 12, + "md": 4 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'model': 'hr', + 'label': '排除H&R', + 'items': [ + {'title': '是', 'value': 'yes'}, + {'title': '否', 'value': 'no'}, + ] + } + } + ] + }, { 'component': 'VCol', 'props': { @@ -732,7 +754,28 @@ class BrushFlow(_PluginBase): ] } ] - } + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'type': 'info', + 'variant': 'tonal', + 'text': '注意:排除H&R并不保证能完全适配所有站点(部分站点在列表页不显示H&R标志,但实际上是有H&R的),请注意核对使用!' + } + } + ] + } + ] + } ] } ], { @@ -740,7 +783,8 @@ class BrushFlow(_PluginBase): "notify": True, "onlyonce": False, "clear_task": False, - "freeleech": "free" + "freeleech": "free", + "hr": "yes", } def get_page(self) -> List[dict]: @@ -1215,6 +1259,7 @@ class BrushFlow(_PluginBase): "downloader": self._downloader, "disksize": self._disksize, "freeleech": self._freeleech, + "hr": self._hr, "maxupspeed": self._maxupspeed, "maxdlspeed": self._maxdlspeed, "maxdlcount": self._maxdlcount, @@ -1284,6 +1329,9 @@ class BrushFlow(_PluginBase): continue if self._freeleech == "2xfree" and torrent.uploadvolumefactor != 2: continue + # H&R + if self._hr == "yes" and torrent.hit_and_run: + continue # 包含规则 if self._include and not re.search(r"%s" % self._include, torrent.title, re.I): continue diff --git a/plugins/clouddiskdel/__init__.py b/plugins/clouddiskdel/__init__.py index 4d16f1f..cb54d19 100644 --- a/plugins/clouddiskdel/__init__.py +++ b/plugins/clouddiskdel/__init__.py @@ -20,7 +20,7 @@ class CloudDiskDel(_PluginBase): # 插件图标 plugin_icon = "clouddisk.png" # 插件版本 - plugin_version = "1.1" + plugin_version = "1.2" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -84,9 +84,13 @@ class CloudDiskDel(_PluginBase): season_num = event_data.get("season_num") episode_num = event_data.get("episode_num") + # 不是网盘监控路径,直接排除 + cloud_file_flag = False + # 判断删除媒体路径是否与配置的媒体库路径相符,相符则继续删除,不符则跳过 for library_path in list(self._paths.keys()): if str(media_path).startswith(library_path): + cloud_file_flag = True # 替换网盘路径 media_path = str(media_path).replace(library_path, self._paths.get(library_path)) logger.info(f"获取到moviepilot本地云盘挂载路径 {media_path}") @@ -128,63 +132,64 @@ class CloudDiskDel(_PluginBase): break - # 发送消息 - image = 'https://emby.media/notificationicon.png' - media_type = MediaType.MOVIE if media_type in ["Movie", "MOV"] else MediaType.TV - if self._notify: - backrop_image = self.chain.obtain_specific_image( + if cloud_file_flag: + # 发送消息 + image = 'https://emby.media/notificationicon.png' + media_type = MediaType.MOVIE if media_type in ["Movie", "MOV"] else MediaType.TV + if self._notify: + backrop_image = self.chain.obtain_specific_image( + mediaid=tmdb_id, + mtype=media_type, + image_type=MediaImageType.Backdrop, + season=season_num, + episode=episode_num + ) or image + + # 类型 + if media_type == MediaType.MOVIE: + msg = f'电影 {media_name} {tmdb_id}' + # 删除电视剧 + elif media_type == MediaType.TV and not season_num and not episode_num: + msg = f'剧集 {media_name} {tmdb_id}' + # 删除季 S02 + elif media_type == MediaType.TV and season_num and not episode_num: + msg = f'剧集 {media_name} S{season_num} {tmdb_id}' + # 删除剧集S02E02 + elif media_type == MediaType.TV and season_num and episode_num: + msg = f'剧集 {media_name} S{season_num}E{episode_num} {tmdb_id}' + else: + msg = media_name + + # 发送通知 + self.post_message( + mtype=NotificationType.MediaServer, + title="云盘同步删除任务完成", + image=backrop_image, + text=f"{msg}\n" + f"时间 {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))}" + ) + + # 读取历史记录 + history = self.get_data('history') or [] + + # 获取poster + poster_image = self.chain.obtain_specific_image( mediaid=tmdb_id, mtype=media_type, - image_type=MediaImageType.Backdrop, - season=season_num, - episode=episode_num + image_type=MediaImageType.Poster, ) or image + history.append({ + "type": media_type.value, + "title": media_name, + "path": media_path, + "season": season_num if season_num and str(season_num).isdigit() else None, + "episode": episode_num if episode_num and str(episode_num).isdigit() else None, + "image": poster_image, + "del_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) + }) - # 类型 - if media_type == MediaType.MOVIE: - msg = f'电影 {media_name} {tmdb_id}' - # 删除电视剧 - elif media_type == MediaType.TV and not season_num and not episode_num: - msg = f'剧集 {media_name} {tmdb_id}' - # 删除季 S02 - elif media_type == MediaType.TV and season_num and not episode_num: - msg = f'剧集 {media_name} S{season_num} {tmdb_id}' - # 删除剧集S02E02 - elif media_type == MediaType.TV and season_num and episode_num: - msg = f'剧集 {media_name} S{season_num}E{episode_num} {tmdb_id}' - else: - msg = media_name - - # 发送通知 - self.post_message( - mtype=NotificationType.MediaServer, - title="云盘同步删除任务完成", - image=backrop_image, - text=f"{msg}\n" - f"时间 {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))}" - ) - - # 读取历史记录 - history = self.get_data('history') or [] - - # 获取poster - poster_image = self.chain.obtain_specific_image( - mediaid=tmdb_id, - mtype=media_type, - image_type=MediaImageType.Poster, - ) or image - history.append({ - "type": media_type.value, - "title": media_name, - "path": media_path, - "season": season_num if season_num and str(season_num).isdigit() else None, - "episode": episode_num if episode_num and str(episode_num).isdigit() else None, - "image": poster_image, - "del_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) - }) - - # 保存历史 - self.save_data("history", history) + # 保存历史 + self.save_data("history", history) def get_state(self) -> bool: return self._enabled diff --git a/plugins/doubanrank/__init__.py b/plugins/doubanrank/__init__.py index 3b8f9e1..28ebd52 100644 --- a/plugins/doubanrank/__init__.py +++ b/plugins/doubanrank/__init__.py @@ -27,7 +27,7 @@ class DoubanRank(_PluginBase): # 插件图标 plugin_icon = "movie.jpg" # 插件版本 - plugin_version = "1.2" + plugin_version = "1.4" # 插件作者 plugin_author = "jxxghp" # 作者主页 @@ -48,7 +48,7 @@ class DoubanRank(_PluginBase): _douban_address = { 'movie-ustop': 'https://rsshub.app/douban/movie/ustop', 'movie-weekly': 'https://rsshub.app/douban/movie/weekly', - 'movie-real-time': 'https://rsshub.app/douban/movie/weekly/subject_real_time_hotest', + 'movie-real-time': 'https://rsshub.app/douban/movie/weekly/movie_real_time_hotest', 'show-domestic': 'https://rsshub.app/douban/movie/weekly/show_domestic', 'movie-hot-gaia': 'https://rsshub.app/douban/movie/weekly/movie_hot_gaia', 'tv-hot': 'https://rsshub.app/douban/movie/weekly/tv_hot', @@ -101,10 +101,8 @@ class DoubanRank(_PluginBase): logger.error(f"豆瓣榜单订阅服务启动失败,错误信息:{str(e)}") self.systemmessage.put(f"豆瓣榜单订阅服务启动失败,错误信息:{str(e)}") else: - self._scheduler.add_job(func=self.__refresh_rss, trigger='date', - run_date=datetime.datetime.now( - tz=pytz.timezone(settings.TZ)) + datetime.timedelta(seconds=3) - ) + self._scheduler.add_job(func=self.__refresh_rss, trigger=CronTrigger.from_crontab("0 8 * * *"), + name="豆瓣榜单订阅") logger.info("豆瓣榜单订阅服务启动,周期:每天 08:00") if self._onlyonce: @@ -484,12 +482,14 @@ class DoubanRank(_PluginBase): title = rss_info.get('title') douban_id = rss_info.get('doubanid') + year = rss_info.get('year') unique_flag = f"doubanrank: {title} (DB:{douban_id})" # 检查是否已处理过 if unique_flag in [h.get("unique") for h in history]: continue # 元数据 meta = MetaInfo(title) + meta.year = year # 识别媒体信息 if douban_id: # 识别豆瓣信息 @@ -565,25 +565,36 @@ class DoubanRank(_PluginBase): items = rootNode.getElementsByTagName("item") for item in items: try: + rss_info = {} + # 标题 title = DomUtils.tag_value(item, "title", default="") # 链接 link = DomUtils.tag_value(item, "link", default="") + # 年份 + description = DomUtils.tag_value(item, "description", default="") + if not title and not link: logger.warn(f"条目标题和链接均为空,无法处理") continue + rss_info['title'] = title + rss_info['link'] = link + doubanid = re.findall(r"/(\d+)/", link) if doubanid: doubanid = doubanid[0] if doubanid and not str(doubanid).isdigit(): logger.warn(f"解析的豆瓣ID格式不正确:{doubanid}") continue + rss_info['doubanid'] = doubanid + + # 匹配4位独立数字1900-2099年 + year = re.findall(r"\b(19\d{2}|20\d{2})\b", description) + if year: + rss_info['year'] = year[0] + # 返回对象 - ret_array.append({ - 'title': title, - 'link': link, - 'doubanid': doubanid - }) + ret_array.append(rss_info) except Exception as e1: logger.error("解析RSS条目失败:" + str(e1)) continue diff --git a/plugins/doubansync/__init__.py b/plugins/doubansync/__init__.py index 9925a87..bd7eff3 100644 --- a/plugins/doubansync/__init__.py +++ b/plugins/doubansync/__init__.py @@ -6,6 +6,7 @@ from typing import Optional, Any, List, Dict, Tuple import pytz from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.cron import CronTrigger +from app.schemas.types import MediaType from app.chain.download import DownloadChain from app.chain.search import SearchChain @@ -30,7 +31,7 @@ class DoubanSync(_PluginBase): # 插件图标 plugin_icon = "douban.png" # 插件版本 - plugin_version = "1.1" + plugin_version = "1.2" # 插件作者 plugin_author = "jxxghp" # 作者主页 @@ -475,6 +476,9 @@ class DoubanSync(_PluginBase): continue # 识别媒体信息 meta = MetaInfo(title=title) + douban_info = self.chain.douban_info(doubanid=douban_id) + meta.year = douban_info.get("year") + meta.type = MediaType.MOVIE if douban_info.get("type") == "movie" else MediaType.TV mediainfo = self.chain.recognize_media(meta=meta, doubanid=douban_id) if not mediainfo: logger.warn(f'未识别到媒体信息,标题:{title},豆瓣ID:{douban_id}') diff --git a/plugins/ffmpegthumb/__init__.py b/plugins/ffmpegthumb/__init__.py index b9ebff9..e3b8e93 100644 --- a/plugins/ffmpegthumb/__init__.py +++ b/plugins/ffmpegthumb/__init__.py @@ -1,3 +1,4 @@ +import threading from datetime import datetime, timedelta from pathlib import Path from threading import Event as ThreadEvent @@ -16,6 +17,8 @@ from app.schemas import TransferInfo from app.schemas.types import EventType from app.utils.system import SystemUtils +ffmpeg_lock = threading.Lock() + class FFmpegThumb(_PluginBase): # 插件名称 @@ -25,7 +28,7 @@ class FFmpegThumb(_PluginBase): # 插件图标 plugin_icon = "ffmpeg.png" # 插件版本 - plugin_version = "1.0" + plugin_version = "1.2" # 插件作者 plugin_author = "jxxghp" # 作者主页 @@ -328,18 +331,18 @@ class FFmpegThumb(_PluginBase): """ 处理一个文件 """ - try: - thumb_path = file_path.with_name(file_path.stem + "-thumb.jpg") - if thumb_path.exists(): - logger.info(f"缩略图已存在:{thumb_path}") - return - if FfmpegHelper.get_thumb(video_path=str(file_path), - image_path=str(thumb_path), frames=self._timeline): - logger.info(f"{file_path} 缩略图已生成:{thumb_path}") - else: - logger.warn(f"{file_path} 缩略图生成失败!") - except Exception as err: - logger.error(f"FFmpeg处理文件 {file_path} 时发生错误:{str(err)}") + # 单线程处理 + with ffmpeg_lock: + try: + thumb_path = file_path.with_name(file_path.stem + "-thumb.jpg") + if thumb_path.exists(): + logger.info(f"缩略图已存在:{thumb_path}") + return + if FfmpegHelper.get_thumb(video_path=str(file_path), + image_path=str(thumb_path), frames=self._timeline): + logger.info(f"{file_path} 缩略图已生成:{thumb_path}") + except Exception as err: + logger.error(f"FFmpeg处理文件 {file_path} 时发生错误:{str(err)}") def stop_service(self): """ diff --git a/plugins/libraryscraper/__init__.py b/plugins/libraryscraper/__init__.py index 85938d8..7b78bb5 100644 --- a/plugins/libraryscraper/__init__.py +++ b/plugins/libraryscraper/__init__.py @@ -8,8 +8,7 @@ from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.cron import CronTrigger from app.core.config import settings -from app.core.meta import MetaBase -from app.core.metainfo import MetaInfo +from app.core.metainfo import MetaInfoPath from app.db.transferhistory_oper import TransferHistoryOper from app.helper.nfo import NfoReader from app.log import logger @@ -26,7 +25,7 @@ class LibraryScraper(_PluginBase): # 插件图标 plugin_icon = "scraper.png" # 插件版本 - plugin_version = "1.1" + plugin_version = "1.2" # 插件作者 plugin_author = "jxxghp" # 作者主页 @@ -214,7 +213,7 @@ class LibraryScraper(_PluginBase): 'model': 'scraper_paths', 'label': '削刮路径', 'rows': 5, - 'placeholder': '每一行一个目录,需配置到媒体文件的上级目录,即开了二级分类时需要配置到二级分类目录' + 'placeholder': '每一行一个目录' } } ] @@ -243,27 +242,6 @@ class LibraryScraper(_PluginBase): } ] }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VAlert', - 'props': { - 'type': 'info', - 'variant': 'tonal', - 'text': '刮削路径要配置到二级分类路径(如果配置了LIBRARY_CATEGORY=true);开启插件后默认会实时处理增量整理的媒体文件,需要处理存量媒体文件时才需开启定时。' - } - } - ] - } - ] - }, { 'component': 'VRow', 'content': [ @@ -325,8 +303,9 @@ class LibraryScraper(_PluginBase): logger.warning(f"媒体库刮削路径不存在:{path}") continue logger.info(f"开始刮削媒体库:{path} {mtype} ...") - # 遍历一层文件夹 - for sub_path in scraper_path.iterdir(): + # 遍历所有文件 + files = SystemUtils.list_files(scraper_path, settings.RMT_MEDIAEXT) + for file_path in files: if self._event.is_set(): logger.info(f"媒体库刮削服务停止") return @@ -334,115 +313,71 @@ class LibraryScraper(_PluginBase): exclude_flag = False for exclude_path in exclude_paths: try: - if sub_path.is_relative_to(Path(exclude_path)): + if file_path.is_relative_to(Path(exclude_path)): exclude_flag = True break except Exception as err: print(str(err)) if exclude_flag: - logger.debug(f"{sub_path} 在排除目录中,跳过 ...") + logger.debug(f"{file_path} 在排除目录中,跳过 ...") continue - # 开始刮削目录 - if sub_path.is_dir(): - # 判断目录是不是媒体目录 - dir_meta = MetaInfo(sub_path.name) - if not dir_meta.name or not dir_meta.year: - logger.warn(f"{sub_path} 可能不是媒体目录,请检查刮削目录配置,跳过 ...") - continue - logger.info(f"开始刮削目录:{sub_path} ...") - self.__scrape_dir(path=sub_path, dir_meta=dir_meta, mtype=mtype) - logger.info(f"目录 {sub_path} 刮削完成") + # 开始刮削文件 + self.__scrape_file(file=file_path, mtype=mtype) logger.info(f"媒体库 {path} 刮削完成") - def __scrape_dir(self, path: Path, dir_meta: MetaBase, mtype: MediaType = None): + def __scrape_file(self, file: Path, mtype: MediaType = None): """ 削刮一个目录,该目录必须是媒体文件目录 """ + # 识别元数据 + meta_info = MetaInfoPath(file) + # 强制指定类型 + if mtype: + meta_info.type = mtype - # 媒体信息 - mediainfo = None + # 是否刮削 + force_nfo = self._mode in ["force_all", "force_nfo"] + force_img = self._mode in ["force_all", "force_image"] - # 查找目录下所有的文件 - files = SystemUtils.list_files(path, settings.RMT_MEDIAEXT) - for file in files: - if self._event.is_set(): - logger.info(f"媒体库刮削服务停止") - return + # 优先读取本地nfo文件 + tmdbid = None + if meta_info.type == MediaType.MOVIE: + # 电影 + movie_nfo = file.parent / "movie.nfo" + if movie_nfo.exists(): + tmdbid = self.__get_tmdbid_from_nfo(movie_nfo) + file_nfo = file.with_suffix(".nfo") + if not tmdbid and file_nfo.exists(): + tmdbid = self.__get_tmdbid_from_nfo(file_nfo) + else: + # 电视剧 + tv_nfo = file.parent.parent / "tvshow.nfo" + if tv_nfo.exists(): + tmdbid = self.__get_tmdbid_from_nfo(tv_nfo) + if tmdbid: + # 按TMDBID识别 + logger.info(f"读取到本地nfo文件的tmdbid:{tmdbid}") + mediainfo = self.chain.recognize_media(tmdbid=tmdbid, mtype=meta_info.type) + else: + # 按名称识别 + mediainfo = self.chain.recognize_media(meta=meta_info) + if not mediainfo: + logger.warn(f"未识别到媒体信息:{file}") + return - # 识别元数据 - meta_info = MetaInfo(file.stem) - # 合并 - meta_info.merge(dir_meta) - # 强制指定类型 - if mtype: - meta_info.type = mtype + # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title + if not settings.SCRAP_FOLLOW_TMDB: + transfer_history = self.transferhis.get_by_type_tmdbid(tmdbid=mediainfo.tmdb_id, + mtype=mediainfo.type.value) + if transfer_history: + mediainfo.title = transfer_history.title - # 是否刮削 - scrap_metadata = settings.SCRAP_METADATA - - # 没有媒体信息或者名字出现变化时,需要重新识别 - if not mediainfo \ - or meta_info.name != dir_meta.name: - # 优先读取本地nfo文件 - tmdbid = None - if meta_info.type == MediaType.MOVIE: - # 电影 - movie_nfo = file.parent / "movie.nfo" - if movie_nfo.exists(): - tmdbid = self.__get_tmdbid_from_nfo(movie_nfo) - file_nfo = file.with_suffix(".nfo") - if not tmdbid and file_nfo.exists(): - tmdbid = self.__get_tmdbid_from_nfo(file_nfo) - else: - # 电视剧 - tv_nfo = file.parent.parent / "tvshow.nfo" - if tv_nfo.exists(): - tmdbid = self.__get_tmdbid_from_nfo(tv_nfo) - if tmdbid: - # 按TMDBID识别 - logger.info(f"读取到本地nfo文件的tmdbid:{tmdbid}") - mediainfo = self.chain.recognize_media(tmdbid=tmdbid, mtype=meta_info.type) - else: - # 按名称识别 - mediainfo = self.chain.recognize_media(meta=meta_info) - if not mediainfo: - logger.warn(f"未识别到媒体信息:{file}") - continue - - # 如果未开启新增已入库媒体是否跟随TMDB信息变化则根据tmdbid查询之前的title - if not settings.SCRAP_FOLLOW_TMDB: - transfer_history = self.transferhis.get_by_type_tmdbid(tmdbid=mediainfo.tmdb_id, - mtype=mediainfo.type.value) - if transfer_history: - mediainfo.title = transfer_history.title - - # 覆盖模式时,提前删除nfo - if self._mode in ["force_all", "force_nfo"]: - scrap_metadata = True - nfo_files = SystemUtils.list_files(path, [".nfo"]) - for nfo_file in nfo_files: - try: - logger.warn(f"删除nfo文件:{nfo_file}") - nfo_file.unlink() - except Exception as err: - print(str(err)) - - # 覆盖模式时,提前删除图片文件 - if self._mode in ["force_all", "force_image"]: - scrap_metadata = True - image_files = SystemUtils.list_files(path, [".jpg", ".png"]) - for image_file in image_files: - if ".actors" in str(image_file): - continue - try: - logger.warn(f"删除图片文件:{image_file}") - image_file.unlink() - except Exception as err: - print(str(err)) - - # 刮削单个文件 - if scrap_metadata: - self.chain.scrape_metadata(path=file, mediainfo=mediainfo, transfer_type=settings.TRANSFER_TYPE) + # 刮削 + self.chain.scrape_metadata(path=file, + mediainfo=mediainfo, + transfer_type=settings.TRANSFER_TYPE, + force_nfo=force_nfo, + force_img=force_img) @staticmethod def __get_tmdbid_from_nfo(file_path: Path):