Merge remote-tracking branch 'origin/main'

This commit is contained in:
thsrite
2024-11-07 15:39:52 +08:00
11 changed files with 193 additions and 152 deletions

View File

@@ -25,7 +25,7 @@ class AutoBackup(_PluginBase):
# 插件图标
plugin_icon = "Time_machine_B.png"
# 插件版本
plugin_version = "2.0"
plugin_version = "2.0.1"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -169,7 +169,7 @@ class AutoBackup(_PluginBase):
shutil.copy(app_file, backup_path)
cookies_path = config_path / "cookies"
if cookies_path.exists():
shutil.copytree(cookies_path, backup_path)
shutil.copytree(cookies_path, f'{backup_path}/cookies')
zip_file = str(backup_path) + '.zip'
if os.path.exists(zip_file):

View File

@@ -20,7 +20,7 @@ class EmbyDanmu(_PluginBase):
# 插件图标
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png"
# 插件版本
plugin_version = "1.5.1"
plugin_version = "1.6"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -37,11 +37,13 @@ class EmbyDanmu(_PluginBase):
_library_task = {}
_danmu_source = []
_mediaservers = None
_dirs = None
mediaserver_helper = None
_EMBY_HOST = None
_EMBY_USER = None
_EMBY_APIKEY = None
_paths = {}
def init_plugin(self, config: dict = None):
self._library_task = {}
@@ -50,8 +52,13 @@ class EmbyDanmu(_PluginBase):
# 读取配置
if config:
self._enabled = config.get("enabled")
self._dirs = config.get("dirs")
self._mediaservers = config.get("mediaservers") or []
if self._dirs:
for path in str(self._dirs).split("\n"):
self._paths[path.split(":")[0]] = path.split(":")[1]
@eventmanager.register(EventType.PluginAction)
def danmu(self, event: Event = None):
if not self._enabled:
@@ -161,7 +168,7 @@ class EmbyDanmu(_PluginBase):
try:
# 获取媒体库媒体列表
library_items = self.__get_items(library_id)
library_items = self.__get_items(library_id, nameStartsWith=library_item_name)
if not library_items:
logger.error(f"{emby_name} 获取媒体库:{library_name}的媒体列表失败")
self.post_message(channel=event.event_data.get("channel"),
@@ -171,6 +178,8 @@ class EmbyDanmu(_PluginBase):
found_item = False
# 遍历媒体列表获取媒体的ID和名称
for item in library_items:
logger.debug(
f"服务器:{emby_name} 媒体库:{library_name} 媒体库类型:{library_type} 媒体:{item}")
if library_type == "tvshows":
if item.get("Name") == library_item_name:
found_item = True
@@ -341,77 +350,69 @@ class EmbyDanmu(_PluginBase):
userid=event.event_data.get("user"))
else:
# 电影弹幕
matches = re.findall(r'^(.+?)\s\(\d{4}\)', item.get("Name"), re.MULTILINE)
matches = re.findall(r'^(.*?)(?= ?\(\d{4}\)?|$)', item.get("Name"), re.MULTILINE)
if matches and str(matches[0]) == library_item_name:
logger.info(f"{emby_name} 开始检查电影:{library_name} {library_item_name}")
found_item = True
movie_id = item.get("Id")
movie_items = self.__get_items(movie_id)
if not movie_items:
logger.error(
f"{emby_name} 获取 {library_name} {item.get('Name')}的媒体列表失败")
# 获取媒体详情
item_info = self.__get_item_info(movie_id)
item_path = item_info.get("Path")
parent_path = Path(self.__get_path(str(Path(item_path).parent)))
logger.info(f"{emby_name} 开始检查MoviePilot路径 {parent_path} 下是是否有弹幕文件")
# 检查是否有弹幕文件
danmu_path_pattern = Path(item_path).stem + "*.xml"
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
logger.info(
f"{emby_name} {parent_path} 下已存在弹幕文件:{danmu_path_pattern}")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} 获取电影:{library_name} {item.get('Name')}的媒体列表失败",
title=f"{emby_name} {library_name} {item.get('Name')} 弹幕已存在",
userid=event.event_data.get("user"))
else:
movie_id = movie_items[0].get("Id")
# 获取媒体详情
item_info = self.__get_item_info(movie_id)
item_path = item_info.get("Path")
parent_path = Path(item_path).parent
logger.info(f"{emby_name} 开始检查路径 {parent_path} 下是是否有弹幕文件")
# 检查是否有弹幕文件
danmu_path_pattern = Path(item_path).stem + "*.xml"
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
# 通知Danmu插件获取弹幕
danmu_flag = self.__download_danmu(movie_id)
if danmu_flag:
logger.info(
f"{emby_name} {parent_path} 下已存在弹幕文件:{danmu_path_pattern}")
f"{emby_name} 已通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} {library_name} {item.get('Name')} 弹幕已存在",
title=f"{emby_name} 开始通知Emby下载 {library_name} {item.get('Name')} 弹幕,异步执行,请耐心等候执行完成消息",
userid=event.event_data.get("user"))
else:
# 通知Danmu插件获取弹幕
danmu_flag = self.__download_danmu(movie_id)
if danmu_flag:
logger.info(
f"{emby_name} 已通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} 开始通知Emby下载 {library_name} {item.get('Name')} 弹幕,异步执行,请耐心等候执行完成消息",
userid=event.event_data.get("user"))
retry_cnt = 3
while len(
list(parent_path.glob(
danmu_path_pattern))) == 0 and retry_cnt > 0:
# 解析日志判断是否全部失败
if self.__check_all_failed_by_log(item_name=item_info.get("Name"),
item_year=item_info.get(
"ProductionYear")):
logger.error(
f"{emby_name} 解析日志判断已配置弹幕源全部匹配弹幕失败")
retry_cnt = -1
else:
retry_cnt -= 1
logger.warn(
f"{emby_name} {parent_path} 下未找到弹幕文件:{danmu_path_pattern}等待60秒后重试 ({retry_cnt}次)")
time.sleep(60)
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
logger.info(
f"{emby_name} {parent_path} 下已找到弹幕文件:{danmu_path_pattern}")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} {library_name} {item.get('Name')} 下载弹幕文件成功",
userid=event.event_data.get("user"))
else:
retry_cnt = 3
while len(
list(parent_path.glob(
danmu_path_pattern))) == 0 and retry_cnt > 0:
# 解析日志判断是否全部失败
if self.__check_all_failed_by_log(item_name=item_info.get("Name"),
item_year=item_info.get(
"ProductionYear")):
logger.error(
f"{emby_name} {parent_path} 下未找到弹幕文件:{danmu_path_pattern}")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} {library_name} {item.get('Name')} 已配置弹幕源全部匹配弹幕失败",
userid=event.event_data.get("user"))
f"{emby_name} 解析日志判断已配置弹幕源全部匹配弹幕失败")
retry_cnt = -1
else:
retry_cnt -= 1
logger.warn(
f"{emby_name} {parent_path} 下未找到弹幕文件:{danmu_path_pattern}等待60秒后重试 ({retry_cnt}次)")
time.sleep(60)
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
logger.info(
f"{emby_name} {parent_path} 下已找到弹幕文件:{danmu_path_pattern}")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} {library_name} {item.get('Name')} 下载弹幕文件成功",
userid=event.event_data.get("user"))
else:
logger.error(
f"{emby_name} 通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕失败")
f"{emby_name} {parent_path} 下未找到弹幕文件:{danmu_path_pattern}")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} 通知弹幕插件获取 {library_name} 电影 {item.get('Name')} {movie_id}弹幕失败",
title=f"{emby_name} {library_name} {item.get('Name')} 已配置弹幕源全部匹配弹幕失败",
userid=event.event_data.get("user"))
else:
logger.error(
f"{emby_name} 通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕失败")
self.post_message(channel=event.event_data.get("channel"),
title=f"{emby_name} 通知弹幕插件获取 {library_name} 电影 {item.get('Name')} {movie_id} 的弹幕失败",
userid=event.event_data.get("user"))
if not found_item:
logger.error(
f"{emby_name} 未找到媒体:{library_name} {library_item_name} {f'{library_item_season}' if library_item_season else ''}")
@@ -462,6 +463,17 @@ class EmbyDanmu(_PluginBase):
logger.error(f"连接媒体库emby/Library/VirtualFolders/Query出错" + str(e))
return []
def __get_path(self, file_path: str):
"""
路径转换
"""
if self._paths and self._paths.keys():
for library_path in self._paths.keys():
if str(file_path).startswith(str(library_path)):
return str(file_path).replace(str(library_path), str(self._paths.get(str(library_path))))
# 未匹配到路径,返回原路径
return file_path
def __update_library(self, library_id, library_options) -> bool:
"""
获取媒体库信息
@@ -480,14 +492,19 @@ class EmbyDanmu(_PluginBase):
return True
return False
def __get_items(self, parent_id) -> list:
def __get_items(self, parent_id, nameStartsWith=None) -> list:
"""
获取媒体库媒体列表
"""
if not self._EMBY_HOST or not self._EMBY_APIKEY:
return []
req_url = f"%semby/Users/%s/Items?ParentId=%s&api_key=%s" % (
self._EMBY_HOST, self._EMBY_USER, parent_id, self._EMBY_APIKEY)
if nameStartsWith:
req_url = f"%semby/Users/%s/Items?ParentId=%s&api_key=%s&NameStartsWith=%s" % (
self._EMBY_HOST, self._EMBY_USER, parent_id, self._EMBY_APIKEY, nameStartsWith)
else:
req_url = f"%semby/Users/%s/Items?ParentId=%s&api_key=%s" % (
self._EMBY_HOST, self._EMBY_USER, parent_id, self._EMBY_APIKEY)
logger.debug(f"开始获取媒体列表:{req_url}")
try:
with RequestUtils().get_res(req_url) as res:
if res:
@@ -497,21 +514,25 @@ class EmbyDanmu(_PluginBase):
else:
return res.json().get("Items")
else:
logger.info(f"获取媒体库媒体列表失败无法连接Emby")
return []
return self.__get_items_488(parent_id)
except Exception as e:
logger.error(f"连接媒体库媒体列表Items出错" + str(e))
return []
def __get_items_488(self, parent_id) -> list:
def __get_items_488(self, parent_id, nameStartsWith=None) -> list:
"""
获取媒体库媒体列表
emby 4.8.8版本
"""
if not self._EMBY_HOST or not self._EMBY_APIKEY:
return []
req_url = f"%semby/Items?ParentId=%s&api_key=%s" % (
self._EMBY_HOST, parent_id, self._EMBY_APIKEY)
if nameStartsWith:
req_url = f"%semby/Items?ParentId=%s&api_key=%s&NameStartsWith=%s" % (
self._EMBY_HOST, parent_id, self._EMBY_APIKEY, nameStartsWith)
else:
req_url = f"%semby/Items?ParentId=%s&api_key=%s" % (
self._EMBY_HOST, parent_id, self._EMBY_APIKEY)
logger.debug(f"开始获取媒体列表488{req_url}")
try:
with RequestUtils().get_res(req_url) as res:
if res:
@@ -564,7 +585,7 @@ class EmbyDanmu(_PluginBase):
season_items = self.__get_items(season_id)
item_info = self.__get_item_info(season_items[0].get("Id"))
item_path = item_info.get("Path")
parent_path = Path(item_path).parent
parent_path = Path(self.__get_path(str(Path(item_path).parent)))
logger.info(f"开始检查路径 {parent_path} 下是是否有弹幕文件")
# 检查是否有弹幕文件
danmu_path_pattern = "*.xml"
@@ -769,6 +790,28 @@ class EmbyDanmu(_PluginBase):
}
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12
},
'content': [
{
'component': 'VTextarea',
'props': {
'model': 'dirs',
'label': '目录映射关系',
'rows': 2,
'placeholder': 'emby目录:mp目录一行一个'
}
}
]
}
]
},
{
'component': 'VRow',
'content': [
@@ -815,6 +858,7 @@ class EmbyDanmu(_PluginBase):
}
], {
"enabled": False,
"dirs": "",
"mediaservers": [],
}

View File

@@ -36,7 +36,7 @@ class EmbyMetaRefresh(_PluginBase):
# 插件图标
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/emby-icon.png"
# 插件版本
plugin_version = "2.1.1"
plugin_version = "2.1.2"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -62,6 +62,7 @@ class EmbyMetaRefresh(_PluginBase):
_ReplaceAllImages = "true"
_actor_path = None
_mediaservers = None
_interval = None
mediaserver_helper = None
_EMBY_HOST = None
_EMBY_USER = None
@@ -85,6 +86,7 @@ class EmbyMetaRefresh(_PluginBase):
self._ReplaceAllMetadata = config.get("ReplaceAllMetadata") or "true"
self._ReplaceAllImages = config.get("ReplaceAllImages") or "true"
self._mediaservers = config.get("mediaservers") or []
self._interval = config.get("interval") or 0
# 加载模块
if self._enabled or self._onlyonce:
@@ -174,6 +176,9 @@ class EmbyMetaRefresh(_PluginBase):
# 刷新媒体库
for transferinfo in transferhistorys:
self.__refresh_emby(transferinfo, emby)
if self._interval:
logger.info(f"等待 {self._interval} 秒后继续刷新")
time.sleep(self._interval)
else:
latest = self.__get_latest_media()
if not latest:
@@ -194,6 +199,9 @@ class EmbyMetaRefresh(_PluginBase):
logger.info(
f"开始刷新媒体库元数据,最新媒体:{'电视剧' if str(item.get('Type')) == 'Episode' else '电影'} {'%s S%02dE%02d %s' % (item.get('SeriesName'), item.get('ParentIndexNumber'), item.get('IndexNumber'), item.get('Name')) if str(item.get('Type')) == 'Episode' else item.get('Name')} {item.get('Id')}")
self.__refresh_emby_library_by_id(item.get("Id"))
if self._interval:
logger.info(f"等待 {self._interval} 秒后继续刷新")
time.sleep(self._interval)
else:
logger.info(
f"最新媒体:{'电视剧' if str(item.get('Type')) == 'Episode' else '电影'} {'%s S%02dE%02d %s' % (item.get('SeriesName'), item.get('ParentIndexNumber'), item.get('IndexNumber'), item.get('Name')) if str(item.get('Type')) == 'Episode' else item.get('Name')} {item.get('Id')} 元数据完整,跳过处理")
@@ -225,8 +233,6 @@ class EmbyMetaRefresh(_PluginBase):
'actors': peoples or item_actors
}
time.sleep(5)
# 处理剧集
for key, value in handle_items.items():
if value:
@@ -1031,7 +1037,25 @@ class EmbyMetaRefresh(_PluginBase):
{
'component': 'VCol',
'props': {
'cols': 12
'cols': 12,
'md': 4
},
'content': [
{
'component': 'VTextField',
'props': {
'model': 'interval',
'label': '刷新间隔(秒)',
'placeholder': '留空默认0秒'
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 4
},
'content': [
{
@@ -1084,7 +1108,8 @@ class EmbyMetaRefresh(_PluginBase):
"refresh_type": "历史记录",
"actor_path": "",
"mediaservers": [],
"num": 5
"num": 5,
"interval": 0,
}
def get_page(self) -> List[dict]:

View File

@@ -34,7 +34,7 @@ class EmbyReporter(_PluginBase):
# 插件图标
plugin_icon = "Pydiocells_A.png"
# 插件版本
plugin_version = "2.1"
plugin_version = "2.1.1"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -644,7 +644,8 @@ class EmbyReporter(_PluginBase):
success, info = self.items(user_id, item_id)
if success and info:
success, parent_info = self.items(user_id, info["ParentId"])
if success and parent_info and parent_info["ParentId"] in self._black_library:
if (success and parent_info
and str(parent_info["ParentId"]) in str(self._black_library).split(",")):
logger.info(f"电影 {name} 已在媒体库黑名单 {self._black_library} 中,已过滤")
continue
exists_movies.append(i)
@@ -675,7 +676,7 @@ class EmbyReporter(_PluginBase):
# 过滤电视剧
if self._black_library:
success, parent_info = self.items(user_id, item_id)
if success and parent_info and parent_info["ParentId"] in self._black_library:
if success and parent_info and str(parent_info["ParentId"]) in str(self._black_library).split(","):
logger.info(f"电视剧 {name} 已在媒体库黑名单 {self._black_library} 中,已过滤")
continue
# 封面图像获取

View File

@@ -26,7 +26,7 @@ class MediaSyncDel(_PluginBase):
# 插件图标
plugin_icon = "mediasyncdel.png"
# 插件版本
plugin_version = "1.8.3"
plugin_version = "1.8.4"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -1103,7 +1103,7 @@ class MediaSyncDel(_PluginBase):
downloader=downloader)
# 暂停辅种
else:
self.chain.stop_torrents(hashs=torrent, download=downloader)
self.chain.stop_torrents(hashs=torrent, downloader=downloader)
logger.info(f"辅种:{downloader} - {torrent} 暂停")
# 处理辅种的辅种

View File

@@ -20,7 +20,7 @@ class SubscribeGroup(_PluginBase):
# 插件图标
plugin_icon = "teamwork.png"
# 插件版本
plugin_version = "2.8"
plugin_version = "2.8.1"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -316,8 +316,7 @@ class SubscribeGroup(_PluginBase):
# 站点 判断是否在订阅站点范围内
rss_sites = self.systemconfig.get(SystemConfigKey.RssSites) or []
if _torrent and _torrent.site and int(_torrent.site) in rss_sites:
sites = json.dumps([_torrent.site])
update_dict['sites'] = sites
update_dict['sites'] = [_torrent.site]
if len(update_dict.keys()) == 0:
logger.info(f"订阅记录:{subscribe.name} 无需填充")