mirror of
https://github.com/thsrite/MoviePilot-Plugins.git
synced 2026-03-27 10:05:57 +00:00
fix v2 Emby instance fetch
This commit is contained in:
@@ -57,11 +57,12 @@
|
||||
"name": "Emby媒体标签",
|
||||
"description": "自动给媒体库媒体添加标签。",
|
||||
"labels": "Emby",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3",
|
||||
"icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.3": "适配v2多媒体服务器",
|
||||
"v1.2": "支持指定特殊媒体名称添加标签",
|
||||
"v1.1": "添加远程交互命令",
|
||||
"v1.0": "自动给媒体库媒体添加标签"
|
||||
@@ -71,11 +72,12 @@
|
||||
"name": "Emby观影报告",
|
||||
"description": "推送Emby观影报告,需Emby安装Playback Report 插件。",
|
||||
"labels": "Emby",
|
||||
"version": "1.8.1",
|
||||
"version": "1.9",
|
||||
"icon": "Pydiocells_A.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.9": "适配v2多媒体服务器",
|
||||
"v1.8": "推送微信增加时间戳,防止使用缓存",
|
||||
"v1.7": "分块发送,兼容微信推送",
|
||||
"v1.6": "fix #67",
|
||||
@@ -118,11 +120,12 @@
|
||||
"name": "Emby弹幕下载",
|
||||
"description": "通知Emby Danmu插件下载弹幕。",
|
||||
"labels": "Emby,媒体库",
|
||||
"version": "1.2.1",
|
||||
"version": "1.3",
|
||||
"icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.3": "适配v2多媒体服务器",
|
||||
"v1.2": "检查本地弹幕文件是否已存在,避免重复下载。",
|
||||
"v1.1": "解析Emby日志,判断已配置弹幕源是否全部匹配失败。",
|
||||
"v1.0": "通知Emby Danmu插件下载弹幕。"
|
||||
@@ -132,11 +135,12 @@
|
||||
"name": "Emby视频类型检查",
|
||||
"description": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。",
|
||||
"labels": "Emby,媒体库",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1",
|
||||
"icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.1": "适配v2多媒体服务器",
|
||||
"v1.0": "定期检查Emby媒体库中是否包含指定的视频类型,发送通知。"
|
||||
}
|
||||
},
|
||||
@@ -144,11 +148,12 @@
|
||||
"name": "Emby有声书整理",
|
||||
"description": "还在为Emby有声书整理烦恼吗?入库存在很多单集?",
|
||||
"labels": "Emby,媒体库",
|
||||
"version": "1.1.1",
|
||||
"version": "1.2",
|
||||
"icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.2": "适配v2多媒体服务器",
|
||||
"v1.1": "整理完锁定,防止数据被刷新",
|
||||
"v1.0": "还在为Emby有声书整理烦恼吗?入库存在很多单集。"
|
||||
}
|
||||
@@ -157,11 +162,12 @@
|
||||
"name": "Emby合集媒体排序",
|
||||
"description": "Emby保留按照加入时间倒序的前提下,把合集中的媒体按照发布日期排序,修改加入时间已到达顺序排列的目的。",
|
||||
"labels": "媒体库",
|
||||
"version": "1.1.1",
|
||||
"version": "1.2",
|
||||
"icon": "Element_A.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.2": "适配v2多媒体服务器",
|
||||
"v1.1": "优化处理逻辑",
|
||||
"v1.0": "保留按照加入时间倒序的前提下,把合集中的媒体放一块,不用到处找。"
|
||||
}
|
||||
@@ -170,11 +176,12 @@
|
||||
"name": "Emby剧集演员同步",
|
||||
"description": "同步剧演员信息到集演员信息。",
|
||||
"labels": "Emby,媒体库",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4",
|
||||
"icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png",
|
||||
"author": "thsrite",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.4": "适配v2多媒体服务器",
|
||||
"v1.3": "剧集优先使用季演员。",
|
||||
"v1.2": "交互命令返回处理完成信息。",
|
||||
"v1.1": "支持交互命令手动同步单个剧集 /as 媒体库名 剧集名。",
|
||||
|
||||
@@ -11,7 +11,6 @@ from app.core.event import eventmanager, Event
|
||||
from app.helper.mediaserver import MediaServerHelper
|
||||
from app.log import logger
|
||||
from app.plugins import _PluginBase
|
||||
from app.modules.emby import Emby
|
||||
from app.schemas.types import EventType, MediaType
|
||||
from app.utils.http import RequestUtils
|
||||
|
||||
@@ -24,7 +23,7 @@ class EmbyActorSync(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/embyactorsync.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.3.1"
|
||||
plugin_version = "1.4"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -38,7 +37,8 @@ class EmbyActorSync(_PluginBase):
|
||||
|
||||
_onlyonce = False
|
||||
_enabled = False
|
||||
_librarys = None
|
||||
_mediaservers = None
|
||||
|
||||
mediaserver_helper = None
|
||||
_EMBY_HOST = None
|
||||
_EMBY_USER = None
|
||||
@@ -51,20 +51,7 @@ class EmbyActorSync(_PluginBase):
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
self._onlyonce = config.get("onlyonce")
|
||||
self._librarys = config.get("librarys") or []
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
# 加载模块
|
||||
if self._onlyonce:
|
||||
@@ -98,7 +85,7 @@ class EmbyActorSync(_PluginBase):
|
||||
{
|
||||
"enabled": self._enabled,
|
||||
"onlyonce": self._onlyonce,
|
||||
"librarys": self._librarys,
|
||||
"mediaservers": self._mediaservers,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -130,72 +117,85 @@ class EmbyActorSync(_PluginBase):
|
||||
"""
|
||||
Emby剧集演员同步
|
||||
"""
|
||||
# 获取媒体库信息
|
||||
librarys = Emby().get_librarys()
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
# 匹配需要的媒体库
|
||||
for library in librarys:
|
||||
if library.type != MediaType.TV.value:
|
||||
continue
|
||||
if self._librarys and library.name not in self._librarys:
|
||||
continue
|
||||
if library_name and library.name != library_name:
|
||||
continue
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 获取媒体库媒体列表
|
||||
library_items = self.__get_items(library.id)
|
||||
if not library_items:
|
||||
logger.error(f"获取媒体库:{library.name}的媒体列表失败")
|
||||
continue
|
||||
# 获取媒体库信息
|
||||
librarys = emby_server.instance.get_librarys()
|
||||
|
||||
logger.info(f"开始同步媒体库:{library.name},ID:{library.id}")
|
||||
# 匹配需要的媒体库
|
||||
for library in librarys:
|
||||
if library.type != MediaType.TV.value:
|
||||
continue
|
||||
if library_name and library.name != library_name:
|
||||
continue
|
||||
|
||||
# 遍历媒体列表,获取媒体的ID和名称
|
||||
for item in library_items:
|
||||
if media_name:
|
||||
# 电影弹幕
|
||||
matches = re.findall(r'^(.+?)\s\(\d{4}\)$', item.get("Name").strip())
|
||||
if (not matches and media_name != item.get("Name")) or (matches and str(matches[0]) != media_name):
|
||||
continue
|
||||
# 获取媒体库媒体列表
|
||||
library_items = self.__get_items(library.id)
|
||||
if not library_items:
|
||||
logger.error(f"获取媒体库:{library.name}的媒体列表失败")
|
||||
continue
|
||||
|
||||
logger.info(f"开始同步媒体:{item.get('Name')},ID:{item.get('Id')}")
|
||||
item_info = self.__get_item_info(item.get("Id"))
|
||||
seasons = self.__get_items(item.get("Id"))
|
||||
for season in seasons:
|
||||
season_info = self.__get_item_info(season.get("Id"))
|
||||
peoples = season_info.get("People") or item_info.get("People")
|
||||
season_items = self.__get_items(season.get("Id"))
|
||||
for season_item in season_items:
|
||||
retry = 0
|
||||
while retry < 3:
|
||||
season_item_info = self.__get_item_info(season_item.get("Id"))
|
||||
try:
|
||||
if season_item_info.get("People") == peoples:
|
||||
logger.warn(
|
||||
f"媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 演员信息已更新")
|
||||
retry = 3
|
||||
continue
|
||||
season_item_info.update({
|
||||
"People": peoples
|
||||
})
|
||||
season_item_info["LockedFields"].append("Cast")
|
||||
flag = self.__update_item_info(season_item.get("Id"), season_item_info)
|
||||
logger.info(
|
||||
f"更新媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 成功:{flag}")
|
||||
if flag:
|
||||
retry = 3
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
logger.info(f"开始同步媒体库:{library.name},ID:{library.id}")
|
||||
|
||||
# 遍历媒体列表,获取媒体的ID和名称
|
||||
for item in library_items:
|
||||
if media_name:
|
||||
# 电影弹幕
|
||||
matches = re.findall(r'^(.+?)\s\(\d{4}\)$', item.get("Name").strip())
|
||||
if (not matches and media_name != item.get("Name")) or (matches and str(matches[0]) != media_name):
|
||||
continue
|
||||
|
||||
logger.info(f"开始同步媒体:{item.get('Name')},ID:{item.get('Id')}")
|
||||
item_info = self.__get_item_info(item.get("Id"))
|
||||
seasons = self.__get_items(item.get("Id"))
|
||||
for season in seasons:
|
||||
season_info = self.__get_item_info(season.get("Id"))
|
||||
peoples = season_info.get("People") or item_info.get("People")
|
||||
season_items = self.__get_items(season.get("Id"))
|
||||
for season_item in season_items:
|
||||
retry = 0
|
||||
while retry < 3:
|
||||
season_item_info = self.__get_item_info(season_item.get("Id"))
|
||||
try:
|
||||
if season_item_info.get("People") == peoples:
|
||||
logger.warn(
|
||||
f"媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 演员信息已更新")
|
||||
retry = 3
|
||||
continue
|
||||
season_item_info.update({
|
||||
"People": peoples
|
||||
})
|
||||
season_item_info["LockedFields"].append("Cast")
|
||||
flag = self.__update_item_info(season_item.get("Id"), season_item_info)
|
||||
logger.info(
|
||||
f"更新媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 成功:{flag}")
|
||||
if flag:
|
||||
retry = 3
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
retry += 1
|
||||
except Exception as e:
|
||||
retry += 1
|
||||
except Exception as e:
|
||||
retry += 1
|
||||
logger.error(
|
||||
f"更新媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 信息出错:{e} 开始重试...{retry} / 3")
|
||||
if event:
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {media_name} 同步完成",
|
||||
userid=event.event_data.get("user"))
|
||||
logger.info(f"Emby剧集演员同步完成")
|
||||
logger.error(
|
||||
f"更新媒体:{item.get('Name')} {season_item_info.get('SeasonName')} {season_item_info.get('IndexNumber')} {season_item_info.get('Name')} 信息出错:{e} 开始重试...{retry} / 3")
|
||||
if event:
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {media_name} 同步完成",
|
||||
userid=event.event_data.get("user"))
|
||||
logger.info(f"{emby_name} 剧集演员同步完成")
|
||||
|
||||
def __update_item_info(self, item_id, data):
|
||||
headers = {
|
||||
@@ -256,9 +256,6 @@ class EmbyActorSync(_PluginBase):
|
||||
"""
|
||||
拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构
|
||||
"""
|
||||
librarys = Emby().get_librarys()
|
||||
library_options = [{'title': library.name, 'value': library.name} for library in librarys if
|
||||
library.type == MediaType.TV.value]
|
||||
return [
|
||||
{
|
||||
"component": "VForm",
|
||||
@@ -301,26 +298,30 @@ class EmbyActorSync(_PluginBase):
|
||||
]
|
||||
},
|
||||
{
|
||||
"component": "VRow",
|
||||
"content": [
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'md': 4
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'model': 'librarys',
|
||||
'label': '媒体库',
|
||||
'items': library_options
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
@@ -348,7 +349,7 @@ class EmbyActorSync(_PluginBase):
|
||||
], {
|
||||
"enabled": False,
|
||||
"onlyonce": False,
|
||||
"librarys": [],
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -28,7 +28,7 @@ class EmbyAudioBook(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/audiobook.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.1.1"
|
||||
plugin_version = "1.2"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -49,6 +49,7 @@ class EmbyAudioBook(_PluginBase):
|
||||
_cron = None
|
||||
_library_id = None
|
||||
_msgtype = None
|
||||
_mediaservers = None
|
||||
|
||||
mediaserver_helper = None
|
||||
_EMBY_HOST = None
|
||||
@@ -70,20 +71,7 @@ class EmbyAudioBook(_PluginBase):
|
||||
self._notify = config.get("notify")
|
||||
self._rename = config.get("rename")
|
||||
self._msgtype = config.get("msgtype")
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
# 停止现有任务
|
||||
self.stop_service()
|
||||
@@ -132,6 +120,7 @@ class EmbyAudioBook(_PluginBase):
|
||||
"cron": self._cron,
|
||||
"notify": self._notify,
|
||||
"msgtype": self._msgtype,
|
||||
"mediaservers": self._mediaservers,
|
||||
})
|
||||
|
||||
def check(self):
|
||||
@@ -139,48 +128,63 @@ class EmbyAudioBook(_PluginBase):
|
||||
logger.error("请设置有声书文件夹ID!")
|
||||
return
|
||||
|
||||
# 获取所有有声书
|
||||
items = self.__get_items(parent_id=int(self._library_id))
|
||||
if not items:
|
||||
logger.error(f"获取媒体库 {self._library_id} 有声书列表失败!")
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
# 检查有声书是否需要整理
|
||||
for item in items:
|
||||
book_items = self.__get_items(item.get("Id"))
|
||||
if not book_items:
|
||||
logger.error(f"获取 {item.get('Name')} {item.get('Id')} 有声书失败!")
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 获取所有有声书
|
||||
items = self.__get_items(parent_id=int(self._library_id))
|
||||
if not items:
|
||||
logger.error(f"获取媒体库 {self._library_id} 有声书列表失败!")
|
||||
return
|
||||
|
||||
# 检查有声书是否需要整理
|
||||
__need_zl = False
|
||||
for book_item in book_items:
|
||||
if not book_item.get("AlbumId"):
|
||||
__need_zl = True
|
||||
break
|
||||
for item in items:
|
||||
book_items = self.__get_items(item.get("Id"))
|
||||
if not book_items:
|
||||
logger.error(f"获取 {item.get('Name')} {item.get('Id')} 有声书失败!")
|
||||
return
|
||||
|
||||
# 需要整理的提示需要整理
|
||||
if __need_zl:
|
||||
logger.info(f"有声书 {item.get('Name')} 需要整理,共 {len(book_items)} 集")
|
||||
# self.__zl(items, -1)
|
||||
# 发送通知
|
||||
if self._notify:
|
||||
mtype = NotificationType.Manual
|
||||
if self._msgtype:
|
||||
mtype = NotificationType.__getitem__(str(self._msgtype)) or NotificationType.Manual
|
||||
self.post_message(title="Emby有声书整理",
|
||||
mtype=mtype,
|
||||
text=f"有声书 {item.get('Name')} 需要整理,共 {len(book_items)} 集")
|
||||
else:
|
||||
# 不需要整理的锁定
|
||||
other_book_info = self.__get_item_info(item.get("Id"))
|
||||
other_book_info.update({
|
||||
"LockData": True,
|
||||
})
|
||||
self.__update_item_info(item.get("Id"), other_book_info)
|
||||
logger.info(f"有声书 {item.get('Name')} 不需要整理,已锁定")
|
||||
# 检查有声书是否需要整理
|
||||
__need_zl = False
|
||||
for book_item in book_items:
|
||||
if not book_item.get("AlbumId"):
|
||||
__need_zl = True
|
||||
break
|
||||
|
||||
logger.info("Emby有声书整理服务执行完毕")
|
||||
# 需要整理的提示需要整理
|
||||
if __need_zl:
|
||||
logger.info(f"有声书 {item.get('Name')} 需要整理,共 {len(book_items)} 集")
|
||||
# self.__zl(items, -1)
|
||||
# 发送通知
|
||||
if self._notify:
|
||||
mtype = NotificationType.Manual
|
||||
if self._msgtype:
|
||||
mtype = NotificationType.__getitem__(str(self._msgtype)) or NotificationType.Manual
|
||||
self.post_message(title="Emby有声书整理",
|
||||
mtype=mtype,
|
||||
text=f"有声书 {item.get('Name')} 需要整理,共 {len(book_items)} 集")
|
||||
else:
|
||||
# 不需要整理的锁定
|
||||
other_book_info = self.__get_item_info(item.get("Id"))
|
||||
other_book_info.update({
|
||||
"LockData": True,
|
||||
})
|
||||
self.__update_item_info(item.get("Id"), other_book_info)
|
||||
logger.info(f"有声书 {item.get('Name')} 不需要整理,已锁定")
|
||||
|
||||
logger.info(f"{emby_name} 有声书整理服务执行完毕")
|
||||
|
||||
@eventmanager.register(EventType.PluginAction)
|
||||
def audiobook(self, event: Event = None):
|
||||
@@ -573,6 +577,32 @@ class EmbyAudioBook(_PluginBase):
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -604,6 +634,7 @@ class EmbyAudioBook(_PluginBase):
|
||||
"cron": "",
|
||||
"msgtype": "",
|
||||
"library_id": "",
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -27,7 +27,7 @@ class EmbyCollectionSort(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "Element_A.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.1.1"
|
||||
plugin_version = "1.2"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -45,6 +45,8 @@ class EmbyCollectionSort(_PluginBase):
|
||||
_cron = None
|
||||
_sort_type = None
|
||||
_collection_library_id = None
|
||||
_mediaservers = None
|
||||
|
||||
mediaserver_helper = None
|
||||
_EMBY_HOST = None
|
||||
_EMBY_USER = None
|
||||
@@ -62,20 +64,8 @@ class EmbyCollectionSort(_PluginBase):
|
||||
self._cron = config.get("cron")
|
||||
self._sort_type = config.get("sort_type") or "asc"
|
||||
self._collection_library_id = config.get("collection_library_id")
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 加载模块
|
||||
if self._enabled or self._onlyonce:
|
||||
# 定时服务
|
||||
@@ -121,6 +111,7 @@ class EmbyCollectionSort(_PluginBase):
|
||||
"enabled": self._enabled,
|
||||
"sort_type": self._sort_type,
|
||||
"collection_library_id": self._collection_library_id,
|
||||
"mediaservers": self._mediaservers,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -128,93 +119,104 @@ class EmbyCollectionSort(_PluginBase):
|
||||
"""
|
||||
更改合集媒体入库时间
|
||||
"""
|
||||
if "emby" not in settings.MEDIASERVER:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
if not self._collection_library_id:
|
||||
logger.error("未配置合集所在媒体库")
|
||||
return
|
||||
|
||||
# 获取合集列表
|
||||
collections = self.__get_items(self._collection_library_id)
|
||||
handle_times = []
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
for collection in collections:
|
||||
logger.info(f"开始处理合集: {collection.get('Name')} {collection.get('Id')}")
|
||||
items = self.__get_items(collection.get("Id"))
|
||||
item_dict = []
|
||||
for item in items:
|
||||
item_info = self.__get_item_info(item.get("Id"))
|
||||
item_dict.append({"Name": item.get("Name"), "Id": item.get("Id"), "item_info": item_info})
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 按照发布时间排序
|
||||
sorted_items = sorted(item_dict, key=lambda x: x.get("item_info").get("PremiereDate"),
|
||||
reverse=self._sort_type == "降序")
|
||||
# 初始化时间
|
||||
current_time = datetime.strptime(sorted_items[0]["item_info"]["DateCreated"], "%Y-%m-%dT%H:%M:%S.%f0Z")
|
||||
# 获取合集列表
|
||||
collections = self.__get_items(self._collection_library_id)
|
||||
handle_times = []
|
||||
|
||||
# 更新每个 item 的 DateCreated,规则为
|
||||
updated_items = []
|
||||
for collection in collections:
|
||||
logger.info(f"开始处理合集: {collection.get('Name')} {collection.get('Id')}")
|
||||
items = self.__get_items(collection.get("Id"))
|
||||
item_dict = []
|
||||
for item in items:
|
||||
item_info = self.__get_item_info(item.get("Id"))
|
||||
item_dict.append({"Name": item.get("Name"), "Id": item.get("Id"), "item_info": item_info})
|
||||
|
||||
while sorted_items:
|
||||
sub_update_items = []
|
||||
# 按照发布时间排序
|
||||
sorted_items = sorted(item_dict, key=lambda x: x.get("item_info").get("PremiereDate"),
|
||||
reverse=self._sort_type == "降序")
|
||||
# 初始化时间
|
||||
current_time = datetime.strptime(sorted_items[0]["item_info"]["DateCreated"], "%Y-%m-%dT%H:%M:%S.%f0Z")
|
||||
|
||||
# 更新每个 item 的 DateCreated,规则为
|
||||
updated_items = []
|
||||
|
||||
while sorted_items:
|
||||
sub_update_items = []
|
||||
|
||||
for item in sorted_items:
|
||||
with lock:
|
||||
new_date_created = current_time.strftime("%Y-%m-%dT%H:%M:%S.%f0Z")
|
||||
# 时间相同,跳过
|
||||
if str(new_date_created) == str(item['item_info']['DateCreated']):
|
||||
logger.debug(
|
||||
f"合集媒体: {item.get('Name')} 原入库时间 {item['item_info']['DateCreated']} 新入库时间 {new_date_created} 时间相同,跳过")
|
||||
handle_times.append(str(current_time))
|
||||
sub_update_items.append(str(current_time))
|
||||
# 时间减一秒,用于下一个 item 的更新
|
||||
current_time -= timedelta(seconds=1)
|
||||
continue
|
||||
|
||||
if str(current_time) in handle_times:
|
||||
logger.warn(
|
||||
f"合集媒体: {item.get('Name')} {current_time} 时间已被占用,开始增加 {len(sorted_items) + 1} 秒,重新尝试处理")
|
||||
# 处理完成的 items 从列表中移除
|
||||
handle_times = [str(_time) for _time in handle_times if _time not in sub_update_items]
|
||||
# 如果时间已被占用,增加 len(sorted_items) + 1 秒
|
||||
current_time += timedelta(seconds=len(sorted_items) + 1)
|
||||
# 重置已处理的 items 列表和 handle_times 集合
|
||||
updated_items.clear()
|
||||
# 时间已被占用,跳出 for 循环
|
||||
break
|
||||
|
||||
for item in sorted_items:
|
||||
with lock:
|
||||
new_date_created = current_time.strftime("%Y-%m-%dT%H:%M:%S.%f0Z")
|
||||
# 时间相同,跳过
|
||||
if str(new_date_created) == str(item['item_info']['DateCreated']):
|
||||
logger.debug(
|
||||
f"合集媒体: {item.get('Name')} 原入库时间 {item['item_info']['DateCreated']} 新入库时间 {new_date_created} 时间相同,跳过")
|
||||
f"合集媒体: {item.get('Name')} 原入库时间 {item['item_info']['DateCreated']} 新入库时间 {new_date_created}")
|
||||
item["item_info"]["DateCreated"] = new_date_created
|
||||
updated_items.append(item["item_info"])
|
||||
handle_times.append(str(current_time))
|
||||
sub_update_items.append(str(current_time))
|
||||
# 时间减一秒,用于下一个 item 的更新
|
||||
current_time -= timedelta(seconds=1)
|
||||
continue
|
||||
else:
|
||||
# 所有 item 处理完成,跳出 while 循环
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
if str(current_time) in handle_times:
|
||||
logger.warn(
|
||||
f"合集媒体: {item.get('Name')} {current_time} 时间已被占用,开始增加 {len(sorted_items) + 1} 秒,重新尝试处理")
|
||||
# 处理完成的 items 从列表中移除
|
||||
handle_times = [str(_time) for _time in handle_times if _time not in sub_update_items]
|
||||
# 如果时间已被占用,增加 len(sorted_items) + 1 秒
|
||||
current_time += timedelta(seconds=len(sorted_items) + 1)
|
||||
# 重置已处理的 items 列表和 handle_times 集合
|
||||
updated_items.clear()
|
||||
# 时间已被占用,跳出 for 循环
|
||||
break
|
||||
if not updated_items:
|
||||
logger.warn(f"合集: {collection.get('Name')} {collection.get('Id')} 无需更新入库时间")
|
||||
continue
|
||||
|
||||
logger.debug(
|
||||
f"合集媒体: {item.get('Name')} 原入库时间 {item['item_info']['DateCreated']} 新入库时间 {new_date_created}")
|
||||
item["item_info"]["DateCreated"] = new_date_created
|
||||
updated_items.append(item["item_info"])
|
||||
handle_times.append(str(current_time))
|
||||
sub_update_items.append(str(current_time))
|
||||
# 时间减一秒,用于下一个 item 的更新
|
||||
current_time -= timedelta(seconds=1)
|
||||
else:
|
||||
# 所有 item 处理完成,跳出 while 循环
|
||||
break
|
||||
time.sleep(1)
|
||||
logger.debug(f"获取合集排序后最新的入库时间: {current_time}")
|
||||
|
||||
if not updated_items:
|
||||
logger.warn(f"合集: {collection.get('Name')} {collection.get('Id')} 无需更新入库时间")
|
||||
continue
|
||||
# 更新入库时间
|
||||
for item_info in updated_items:
|
||||
update_flag = self.__update_item_info(item_info.get("Id"), item_info)
|
||||
if update_flag:
|
||||
logger.info(f"{item_info.get('Name')} 更新入库时间到{item_info.get('DateCreated')}成功")
|
||||
else:
|
||||
logger.error(f"{item_info.get('Name')} 更新入库时间到{item_info.get('DateCreated')}失败")
|
||||
|
||||
logger.debug(f"获取合集排序后最新的入库时间: {current_time}")
|
||||
logger.info(f"合集处理完成: {collection.get('Name')} {collection.get('Id')}")
|
||||
|
||||
# 更新入库时间
|
||||
for item_info in updated_items:
|
||||
update_flag = self.__update_item_info(item_info.get("Id"), item_info)
|
||||
if update_flag:
|
||||
logger.info(f"{item_info.get('Name')} 更新入库时间到{item_info.get('DateCreated')}成功")
|
||||
else:
|
||||
logger.error(f"{item_info.get('Name')} 更新入库时间到{item_info.get('DateCreated')}失败")
|
||||
|
||||
logger.info(f"合集处理完成: {collection.get('Name')} {collection.get('Id')}")
|
||||
|
||||
logger.info(f"更新Emby合集媒体排序完成")
|
||||
logger.info(f"更新 {emby_name} 合集媒体排序完成")
|
||||
|
||||
@eventmanager.register(EventType.PluginAction)
|
||||
def remote_sync(self, event: Event):
|
||||
@@ -378,7 +380,32 @@ class EmbyCollectionSort(_PluginBase):
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -408,6 +435,7 @@ class EmbyCollectionSort(_PluginBase):
|
||||
"sort_type": "降序",
|
||||
"cron": "5 1 * * *",
|
||||
"collection_library_id": "",
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -20,7 +20,7 @@ class EmbyDanmu(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/danmu.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.2.1"
|
||||
plugin_version = "1.3"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -36,6 +36,7 @@ class EmbyDanmu(_PluginBase):
|
||||
_enabled = False
|
||||
_library_task = {}
|
||||
_danmu_source = []
|
||||
_mediaservers = None
|
||||
|
||||
mediaserver_helper = None
|
||||
_EMBY_HOST = None
|
||||
@@ -49,19 +50,7 @@ class EmbyDanmu(_PluginBase):
|
||||
# 读取配置
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
self._danmu_source = self.__get_danmu_source()
|
||||
|
||||
@@ -95,145 +84,210 @@ class EmbyDanmu(_PluginBase):
|
||||
userid=event.event_data.get("user"))
|
||||
return
|
||||
|
||||
library_name = args_list[0]
|
||||
library_item_name = args_list[1]
|
||||
library_item_season = None
|
||||
if len(args_list) == 3:
|
||||
library_item_season = int(args_list[2])
|
||||
logger.info(
|
||||
f"开始下载弹幕文件:{library_name} - {library_item_name} {f'(季{library_item_season})' if library_item_season else ''}")
|
||||
|
||||
# 获取媒体库信息
|
||||
librarys = self.__get_librarys()
|
||||
|
||||
library_id = None
|
||||
library_options = None
|
||||
library_type = None
|
||||
# 匹配需要的媒体库
|
||||
for library in librarys:
|
||||
if library.get("Name") == library_name:
|
||||
logger.info(f"找到媒体库:{library_name},ID:{library.get('Id')}")
|
||||
library_type = library.get("CollectionType")
|
||||
library_id = library.get("Id")
|
||||
library_options = library.get("LibraryOptions")
|
||||
break
|
||||
|
||||
if not library_id or not library_options:
|
||||
logger.error(f"未找到媒体库:{library_name}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"未找到媒体库:{library_name}",
|
||||
userid=event.event_data.get("user"))
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
# 开启Danmu插件
|
||||
# 检查是否已经禁用了Danmu插件,如禁用则先启用
|
||||
enabled_danmu = False
|
||||
library_disabled_subtitle_fetchers = library_options.get("DisabledSubtitleFetchers", [])
|
||||
if "Danmu" in library_disabled_subtitle_fetchers:
|
||||
library_disabled_subtitle_fetchers.remove("Danmu")
|
||||
library_options.update({
|
||||
"DisabledSubtitleFetchers": library_disabled_subtitle_fetchers,
|
||||
})
|
||||
enabled_danmu = True
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 启用Danmu插件
|
||||
if enabled_danmu:
|
||||
update_flag = self.__update_library(library_id, library_options)
|
||||
if update_flag:
|
||||
logger.info(f"已启用媒体库:{library_name}的Danmu插件")
|
||||
else:
|
||||
logger.error(f"启用媒体库:{library_name}的Danmu插件失败")
|
||||
library_name = args_list[0]
|
||||
library_item_name = args_list[1]
|
||||
library_item_season = None
|
||||
if len(args_list) == 3:
|
||||
library_item_season = int(args_list[2])
|
||||
logger.info(
|
||||
f"开始下载弹幕文件:{library_name} - {library_item_name} {f'(季{library_item_season})' if library_item_season else ''}")
|
||||
|
||||
# 获取媒体库信息
|
||||
librarys = self.__get_librarys()
|
||||
|
||||
library_id = None
|
||||
library_options = None
|
||||
library_type = None
|
||||
# 匹配需要的媒体库
|
||||
for library in librarys:
|
||||
if library.get("Name") == library_name:
|
||||
logger.info(f"找到媒体库:{library_name},ID:{library.get('Id')}")
|
||||
library_type = library.get("CollectionType")
|
||||
library_id = library.get("Id")
|
||||
library_options = library.get("LibraryOptions")
|
||||
break
|
||||
|
||||
if not library_id or not library_options:
|
||||
logger.error(f"未找到媒体库:{library_name}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"启用媒体库:{library_name}的Danmu插件失败",
|
||||
title=f"未找到媒体库:{library_name}",
|
||||
userid=event.event_data.get("user"))
|
||||
return
|
||||
else:
|
||||
logger.info(f"媒体库:{library_name}的Danmu插件已启用")
|
||||
break
|
||||
|
||||
# 媒体库设置为正在任务,不关闭弹幕插件
|
||||
_library_task = self._library_task.get(library_id, [])
|
||||
_library_task.append(library_item_name)
|
||||
self._library_task[library_id] = _library_task
|
||||
# 开启Danmu插件
|
||||
# 检查是否已经禁用了Danmu插件,如禁用则先启用
|
||||
enabled_danmu = False
|
||||
library_disabled_subtitle_fetchers = library_options.get("DisabledSubtitleFetchers", [])
|
||||
if "Danmu" in library_disabled_subtitle_fetchers:
|
||||
library_disabled_subtitle_fetchers.remove("Danmu")
|
||||
library_options.update({
|
||||
"DisabledSubtitleFetchers": library_disabled_subtitle_fetchers,
|
||||
})
|
||||
enabled_danmu = True
|
||||
|
||||
try:
|
||||
# 获取媒体库媒体列表
|
||||
library_items = self.__get_items(library_id)
|
||||
if not library_items:
|
||||
logger.error(f"获取媒体库:{library_name}的媒体列表失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"获取媒体库:{library_name}的媒体列表失败",
|
||||
userid=event.event_data.get("user"))
|
||||
# 启用Danmu插件
|
||||
if enabled_danmu:
|
||||
update_flag = self.__update_library(library_id, library_options)
|
||||
if update_flag:
|
||||
logger.info(f"已启用媒体库:{library_name}的Danmu插件")
|
||||
else:
|
||||
logger.error(f"启用媒体库:{library_name}的Danmu插件失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"启用媒体库:{library_name}的Danmu插件失败",
|
||||
userid=event.event_data.get("user"))
|
||||
return
|
||||
else:
|
||||
found_item = False
|
||||
# 遍历媒体列表,获取媒体的ID和名称
|
||||
for item in library_items:
|
||||
if library_type == "tvshows":
|
||||
if item.get("Name") == library_item_name:
|
||||
found_item = True
|
||||
logger.info(f"找到媒体:{library_item_name},ID:{item.get('Id')}")
|
||||
logger.info(f"媒体库:{library_name}的Danmu插件已启用")
|
||||
|
||||
# 电视剧弹幕
|
||||
seasons = self.__get_items(item.get("Id"))
|
||||
if len(seasons) == 1:
|
||||
season_item = seasons[0]
|
||||
if library_item_season and season_item.get("IndexNumber") != library_item_season:
|
||||
found_item = False
|
||||
break
|
||||
# 媒体库设置为正在任务,不关闭弹幕插件
|
||||
_library_task = self._library_task.get(library_id, [])
|
||||
_library_task.append(library_item_name)
|
||||
self._library_task[library_id] = _library_task
|
||||
|
||||
# 通知Danmu插件获取弹幕
|
||||
season_id = season_item.get("Id")
|
||||
# 判断本地弹幕是否存在
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=True)
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
break
|
||||
try:
|
||||
# 获取媒体库媒体列表
|
||||
library_items = self.__get_items(library_id)
|
||||
if not library_items:
|
||||
logger.error(f"获取媒体库:{library_name}的媒体列表失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"获取媒体库:{library_name}的媒体列表失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
found_item = False
|
||||
# 遍历媒体列表,获取媒体的ID和名称
|
||||
for item in library_items:
|
||||
if library_type == "tvshows":
|
||||
if item.get("Name") == library_item_name:
|
||||
found_item = True
|
||||
logger.info(f"找到媒体:{library_item_name},ID:{item.get('Id')}")
|
||||
|
||||
danmu_flag = self.__download_danmu(season_id)
|
||||
if danmu_flag:
|
||||
logger.info(
|
||||
f"已通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知Emby下载 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕,异步执行,请耐心等候执行完成消息",
|
||||
userid=event.event_data.get("user"))
|
||||
# 电视剧弹幕
|
||||
seasons = self.__get_items(item.get("Id"))
|
||||
if len(seasons) == 1:
|
||||
season_item = seasons[0]
|
||||
if library_item_season and season_item.get("IndexNumber") != library_item_season:
|
||||
found_item = False
|
||||
break
|
||||
|
||||
# 通知Danmu插件获取弹幕
|
||||
season_id = season_item.get("Id")
|
||||
# 判断本地弹幕是否存在
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=False)
|
||||
if danmu_cnt == 0:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} Emby已配置弹幕源全部匹配弹幕失败")
|
||||
only_check=True)
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} Emby已配置弹幕源全部匹配弹幕失败",
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
break
|
||||
|
||||
danmu_flag = self.__download_danmu(season_id)
|
||||
if danmu_flag:
|
||||
logger.info(
|
||||
f"已通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知Emby下载 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕,异步执行,请耐心等候执行完成消息",
|
||||
userid=event.event_data.get("user"))
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=False)
|
||||
if danmu_cnt == 0:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} Emby已配置弹幕源全部匹配弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
title=f"{library_name} {library_item_name} Emby已配置弹幕源全部匹配弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} {library_item_name} 第{season_item.get('IndexNumber')}季 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
for season in seasons:
|
||||
# 指定季度则只获取指定季度的弹幕
|
||||
if library_item_season:
|
||||
found_item = False
|
||||
if season.get("IndexNumber") == library_item_season:
|
||||
found_item = True
|
||||
for season in seasons:
|
||||
# 指定季度则只获取指定季度的弹幕
|
||||
if library_item_season:
|
||||
found_item = False
|
||||
if season.get("IndexNumber") == library_item_season:
|
||||
found_item = True
|
||||
season_id = season.get("Id")
|
||||
# 判断本地弹幕是否存在
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=True)
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
break
|
||||
|
||||
# 通知Danmu插件获取弹幕
|
||||
danmu_flag = self.__download_danmu(season_id)
|
||||
if danmu_flag:
|
||||
logger.info(
|
||||
f"已通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知Emby下载 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕,异步执行,请耐心等候执行完成消息",
|
||||
userid=event.event_data.get("user"))
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=False)
|
||||
if danmu_cnt == 0:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 Emby已配置弹幕源全部匹配弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 Emby已配置弹幕源全部匹配弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
break
|
||||
else:
|
||||
# 未指定季度则获取全部季度的弹幕
|
||||
season_id = season.get("Id")
|
||||
# 判断本地弹幕是否存在
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
@@ -244,7 +298,7 @@ class EmbyDanmu(_PluginBase):
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
break
|
||||
continue
|
||||
|
||||
# 通知Danmu插件获取弹幕
|
||||
danmu_flag = self.__download_danmu(season_id)
|
||||
@@ -281,150 +335,100 @@ class EmbyDanmu(_PluginBase):
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
break
|
||||
else:
|
||||
# 未指定季度则获取全部季度的弹幕
|
||||
season_id = season.get("Id")
|
||||
# 判断本地弹幕是否存在
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=True)
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部存在:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
continue
|
||||
|
||||
# 通知Danmu插件获取弹幕
|
||||
danmu_flag = self.__download_danmu(season_id)
|
||||
if danmu_flag:
|
||||
logger.info(
|
||||
f"已通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知Emby下载 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕,异步执行,请耐心等候执行完成消息",
|
||||
userid=event.event_data.get("user"))
|
||||
danmu_cnt, season_item_cnt = self.__check_danmu_exists(season_id,
|
||||
only_check=False)
|
||||
if danmu_cnt == 0:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 Emby已配置弹幕源全部匹配弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 Emby已配置弹幕源全部匹配弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
if season_item_cnt == danmu_cnt:
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件已全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {library_item_name} 第{season.get('IndexNumber')}季 弹幕文件未全部下载完成:{danmu_cnt}/{season_item_cnt}",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} {library_item_name} 第{season.get('IndexNumber')}季 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
# 电影弹幕
|
||||
matches = re.findall(r'^(.+?)\s\(\d{4}\)', item.get("Name"), re.MULTILINE)
|
||||
if matches and str(matches[0]) == 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"获取 {library_name} {item.get('Name')}的媒体列表失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"获取电影:{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"开始检查路径 {parent_path} 下是是否有弹幕文件")
|
||||
# 检查是否有弹幕文件
|
||||
danmu_path_pattern = Path(item_path).stem + "*.xml"
|
||||
|
||||
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
|
||||
logger.info(f"{parent_path} 下已存在弹幕文件:{danmu_path_pattern}")
|
||||
else:
|
||||
# 电影弹幕
|
||||
matches = re.findall(r'^(.+?)\s\(\d{4}\)', item.get("Name"), re.MULTILINE)
|
||||
if matches and str(matches[0]) == 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"获取 {library_name} {item.get('Name')}的媒体列表失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 弹幕已存在",
|
||||
title=f"获取电影:{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"已通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知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"解析日志判断已配置弹幕源全部匹配弹幕失败")
|
||||
retry_cnt = -1
|
||||
else:
|
||||
retry_cnt -= 1
|
||||
logger.warn(
|
||||
f"{parent_path} 下未找到弹幕文件:{danmu_path_pattern},等待60秒后重试 ({retry_cnt}次)")
|
||||
time.sleep(60)
|
||||
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"开始检查路径 {parent_path} 下是是否有弹幕文件")
|
||||
# 检查是否有弹幕文件
|
||||
danmu_path_pattern = Path(item_path).stem + "*.xml"
|
||||
|
||||
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
|
||||
logger.info(f"{parent_path} 下已找到弹幕文件:{danmu_path_pattern}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 下载弹幕文件成功",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(f"{parent_path} 下未找到弹幕文件:{danmu_path_pattern}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 已配置弹幕源全部匹配弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
|
||||
logger.info(f"{parent_path} 下已存在弹幕文件:{danmu_path_pattern}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 弹幕已存在",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} 电影 {item.get('Name')} {movie_id} 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
if not found_item:
|
||||
logger.error(
|
||||
f"未找到媒体:{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"未找到媒体:{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}",
|
||||
userid=event.event_data.get("user"))
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}获取弹幕任务出错:{str(e)}")
|
||||
# 通知Danmu插件获取弹幕
|
||||
danmu_flag = self.__download_danmu(movie_id)
|
||||
if danmu_flag:
|
||||
logger.info(
|
||||
f"已通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"开始通知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"解析日志判断已配置弹幕源全部匹配弹幕失败")
|
||||
retry_cnt = -1
|
||||
else:
|
||||
retry_cnt -= 1
|
||||
logger.warn(
|
||||
f"{parent_path} 下未找到弹幕文件:{danmu_path_pattern},等待60秒后重试 ({retry_cnt}次)")
|
||||
time.sleep(60)
|
||||
|
||||
# 判断当前媒体库是否有其他任务在执行
|
||||
self._library_task[library_id].remove(library_item_name)
|
||||
if len(self._library_task[library_id]) == 0:
|
||||
# 关闭弹幕插件
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}获取弹幕任务完成,关闭弹幕插件")
|
||||
# 禁用媒体库的Danmu插件
|
||||
library_disabled_subtitle_fetchers = library_options.get("DisabledSubtitleFetchers", [])
|
||||
library_disabled_subtitle_fetchers.append("Danmu")
|
||||
library_options.update({
|
||||
"DisabledSubtitleFetchers": library_disabled_subtitle_fetchers,
|
||||
})
|
||||
update_flag = self.__update_library(library_id, library_options)
|
||||
if update_flag:
|
||||
logger.info(f"已禁用媒体库:{library_name} Danmu插件")
|
||||
else:
|
||||
logger.error(f"禁用媒体库:{library_name} Danmu插件失败")
|
||||
if len(list(parent_path.glob(danmu_path_pattern))) >= 1:
|
||||
logger.info(f"{parent_path} 下已找到弹幕文件:{danmu_path_pattern}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 下载弹幕文件成功",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(f"{parent_path} 下未找到弹幕文件:{danmu_path_pattern}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"{library_name} {item.get('Name')} 已配置弹幕源全部匹配弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
else:
|
||||
logger.error(
|
||||
f"通知弹幕插件获取 {library_name} {item.get('Name')} {movie_id} 的弹幕失败")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"通知弹幕插件获取 {library_name} 电影 {item.get('Name')} {movie_id} 的弹幕失败",
|
||||
userid=event.event_data.get("user"))
|
||||
if not found_item:
|
||||
logger.error(
|
||||
f"未找到媒体:{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}")
|
||||
self.post_message(channel=event.event_data.get("channel"),
|
||||
title=f"未找到媒体:{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}",
|
||||
userid=event.event_data.get("user"))
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}获取弹幕任务出错:{str(e)}")
|
||||
|
||||
# 判断当前媒体库是否有其他任务在执行
|
||||
self._library_task[library_id].remove(library_item_name)
|
||||
if len(self._library_task[library_id]) == 0:
|
||||
# 关闭弹幕插件
|
||||
logger.info(
|
||||
f"{library_name} {library_item_name} {f'第{library_item_season}季 ' if library_item_season else ''}获取弹幕任务完成,关闭弹幕插件")
|
||||
# 禁用媒体库的Danmu插件
|
||||
library_disabled_subtitle_fetchers = library_options.get("DisabledSubtitleFetchers", [])
|
||||
library_disabled_subtitle_fetchers.append("Danmu")
|
||||
library_options.update({
|
||||
"DisabledSubtitleFetchers": library_disabled_subtitle_fetchers,
|
||||
})
|
||||
update_flag = self.__update_library(library_id, library_options)
|
||||
if update_flag:
|
||||
logger.info(f"已禁用媒体库:{library_name} Danmu插件")
|
||||
else:
|
||||
logger.error(f"禁用媒体库:{library_name} Danmu插件失败")
|
||||
|
||||
def get_state(self) -> bool:
|
||||
return self._enabled
|
||||
@@ -705,6 +709,32 @@ class EmbyDanmu(_PluginBase):
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -751,6 +781,7 @@ class EmbyDanmu(_PluginBase):
|
||||
}
|
||||
], {
|
||||
"enabled": False,
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -25,7 +25,7 @@ class EmbyExtendType(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/extendtype.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.0.1"
|
||||
plugin_version = "1.1"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -46,6 +46,7 @@ class EmbyExtendType(_PluginBase):
|
||||
_librarys = None
|
||||
_extend = None
|
||||
_msgtype = None
|
||||
_mediaservers = None
|
||||
|
||||
# 退出事件
|
||||
_event = threading.Event()
|
||||
@@ -66,19 +67,7 @@ class EmbyExtendType(_PluginBase):
|
||||
self._notify = config.get("notify")
|
||||
self._extend = config.get("extend")
|
||||
self._msgtype = config.get("msgtype")
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
# 停止现有任务
|
||||
self.stop_service()
|
||||
@@ -123,30 +112,44 @@ class EmbyExtendType(_PluginBase):
|
||||
logger.error("视频类型为空,不进行检查")
|
||||
return
|
||||
|
||||
if not self._librarys:
|
||||
logger.error("媒体库为空,不进行检查")
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
logger.info(f"开始检查媒体库 {self._librarys} 中是否包含 {self._extend} 类型")
|
||||
for library in self._librarys:
|
||||
library_name, library_id = library.split(" ")
|
||||
logger.info(f"开始检查媒体库 {library_name} 中是否包含 {self._extend} 类型")
|
||||
library_extends = self.__get_extend_type(library_id)
|
||||
if library_extends:
|
||||
for extend in self._extend.split(","):
|
||||
if extend in [item.get("Name") for item in library_extends]:
|
||||
logger.info(f"媒体库 {library_name} 中包含 {extend} 类型")
|
||||
# 发送通知
|
||||
if self._notify:
|
||||
mtype = NotificationType.Manual
|
||||
if self._msgtype:
|
||||
mtype = NotificationType.__getitem__(str(self._msgtype)) or NotificationType.Manual
|
||||
self.post_message(title="Emby视频类型检查",
|
||||
mtype=mtype,
|
||||
text=f"媒体库 {library_name} 命中 {extend} 视频类型")
|
||||
logger.info(f"媒体库 {library_name} 中全部视频类型检查完毕")
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
logger.info(f"媒体库 {self._librarys} 中全部视频类型检查完毕")
|
||||
# 获取媒体库信息
|
||||
librarys = emby_server.instance.get_librarys()
|
||||
for library in librarys:
|
||||
logger.info(f"开始检查媒体库 {emby_name} {library.name} 中是否包含 {self._extend} 类型")
|
||||
library_id = library.id
|
||||
library_name = library.name
|
||||
logger.info(f"开始检查媒体库 {library_name} 中是否包含 {self._extend} 类型")
|
||||
library_extends = self.__get_extend_type(library_id)
|
||||
if library_extends:
|
||||
for extend in self._extend.split(","):
|
||||
if extend in [item.get("Name") for item in library_extends]:
|
||||
logger.info(f"媒体库 {library_name} 中包含 {extend} 类型")
|
||||
# 发送通知
|
||||
if self._notify:
|
||||
mtype = NotificationType.Manual
|
||||
if self._msgtype:
|
||||
mtype = NotificationType.__getitem__(str(self._msgtype)) or NotificationType.Manual
|
||||
self.post_message(title="Emby视频类型检查",
|
||||
mtype=mtype,
|
||||
text=f"媒体库 {library_name} 命中 {extend} 视频类型")
|
||||
logger.info(f"{emby_name} 媒体库 {library_name} 中全部视频类型检查完毕")
|
||||
|
||||
logger.info(f"{emby_name} 媒体库中全部视频类型检查完毕")
|
||||
|
||||
def __get_extend_type(self, parent_id) -> list:
|
||||
"""
|
||||
@@ -179,6 +182,7 @@ class EmbyExtendType(_PluginBase):
|
||||
"extend": self._extend,
|
||||
"notify": self._notify,
|
||||
"msgtype": self._msgtype,
|
||||
"mediaservers": self._mediaservers,
|
||||
})
|
||||
|
||||
def get_state(self) -> bool:
|
||||
@@ -325,7 +329,7 @@ class EmbyExtendType(_PluginBase):
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
@@ -333,13 +337,16 @@ class EmbyExtendType(_PluginBase):
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'model': 'librarys',
|
||||
'label': '媒体库',
|
||||
'items': library_items
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -350,7 +357,7 @@ class EmbyExtendType(_PluginBase):
|
||||
"notify": False,
|
||||
"cron": "",
|
||||
"extend": "",
|
||||
"librarys": [],
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -23,7 +23,7 @@ class EmbyMetaTag(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/tag.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.2.1"
|
||||
plugin_version = "1.3"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -41,6 +41,8 @@ class EmbyMetaTag(_PluginBase):
|
||||
_cron = None
|
||||
_tag_confs = None
|
||||
_name_tag_confs = None
|
||||
_mediaservers = None
|
||||
|
||||
mediaserver_helper = None
|
||||
_EMBY_HOST = None
|
||||
_EMBY_USER = None
|
||||
@@ -62,19 +64,7 @@ class EmbyMetaTag(_PluginBase):
|
||||
self._cron = config.get("cron")
|
||||
self._tag_confs = config.get("tag_confs")
|
||||
self._name_tag_confs = config.get("name_tag_confs")
|
||||
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_HOST = emby_server.config.get("host")
|
||||
self._EMBY_APIKEY = emby_server.config.get("apikey")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
_tags = {}
|
||||
if self._tag_confs:
|
||||
@@ -147,6 +137,7 @@ class EmbyMetaTag(_PluginBase):
|
||||
"enabled": self._enabled,
|
||||
"tag_confs": self._tag_confs,
|
||||
"name_tag_confs": self._name_tag_confs,
|
||||
"mediaservers": self._mediaservers,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -154,85 +145,96 @@ class EmbyMetaTag(_PluginBase):
|
||||
"""
|
||||
给设定媒体库打标签
|
||||
"""
|
||||
if "emby" not in settings.MEDIASERVER:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
if (not self._tags or len(self._tags.keys()) == 0) and (
|
||||
not self._media_tags or len(self._media_tags.keys()) == 0):
|
||||
logger.error("未配置Emby媒体标签")
|
||||
return
|
||||
|
||||
# 媒体库标签
|
||||
if self._tags and len(self._tags.keys()) > 0:
|
||||
# 获取emby 媒体库
|
||||
librarys = Emby().get_librarys()
|
||||
if not librarys:
|
||||
logger.error("获取媒体库失败")
|
||||
return
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
# 遍历媒体库,获取媒体库媒体
|
||||
for library in librarys:
|
||||
# 获取媒体库标签
|
||||
library_tags = self._tags.get(library.name)
|
||||
if not library_tags:
|
||||
continue
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self._EMBY_USER = emby_server.instance.get_user()
|
||||
self._EMBY_APIKEY = emby_server.config.config.get("apikey")
|
||||
self._EMBY_HOST = emby_server.config.config.get("host")
|
||||
if not self._EMBY_HOST.endswith("/"):
|
||||
self._EMBY_HOST += "/"
|
||||
if not self._EMBY_HOST.startswith("http"):
|
||||
self._EMBY_HOST = "http://" + self._EMBY_HOST
|
||||
|
||||
# 获取媒体库媒体
|
||||
library_items = Emby().get_items(library.id)
|
||||
if not library_items:
|
||||
continue
|
||||
# 媒体库标签
|
||||
if self._tags and len(self._tags.keys()) > 0:
|
||||
# 获取emby 媒体库
|
||||
librarys = emby_server.instance.get_librarys()
|
||||
if not librarys:
|
||||
logger.error("获取媒体库失败")
|
||||
return
|
||||
|
||||
for library_item in library_items:
|
||||
if not library_item:
|
||||
continue
|
||||
# 获取item的tag
|
||||
item_tags = self.__get_item_tags(library_item.item_id) or []
|
||||
|
||||
# 获取缺少的tag
|
||||
add_tags = []
|
||||
for library_tag in library_tags:
|
||||
if not item_tags or library_tag not in item_tags:
|
||||
add_tags.append(library_tag)
|
||||
|
||||
# 添加标签
|
||||
if add_tags:
|
||||
tags = [{"Name": str(add_tag)} for add_tag in add_tags]
|
||||
tags = {"Tags": tags}
|
||||
add_flag = self.__add_tag(library_item.item_id, tags)
|
||||
logger.info(f"{library.name} 添加标签成功:{library_item.title} {tags} {add_flag}")
|
||||
|
||||
# 特殊媒体名标签
|
||||
if self._media_tags and len(self._media_tags.keys()) > 0:
|
||||
for media_name, media_tags in self._media_tags.items():
|
||||
|
||||
match_medias = []
|
||||
# 根据Series/Movie搜索媒体
|
||||
for media_type in self._media_type.get(media_name):
|
||||
match_medias += self.__get_medias_by_name(media_name, media_type)
|
||||
|
||||
# 遍历媒体 补充缺失tag
|
||||
for media in match_medias:
|
||||
if not media:
|
||||
# 遍历媒体库,获取媒体库媒体
|
||||
for library in librarys:
|
||||
# 获取媒体库标签
|
||||
library_tags = self._tags.get(library.name)
|
||||
if not library_tags:
|
||||
continue
|
||||
|
||||
# 获取item的tag
|
||||
item_tags = self.__get_item_tags(media.get("Id")) or []
|
||||
# 获取媒体库媒体
|
||||
library_items = emby_server.instance.get_items(library.id)
|
||||
if not library_items:
|
||||
continue
|
||||
|
||||
# 获取缺少的tag
|
||||
add_tags = []
|
||||
for media_tag in media_tags:
|
||||
if not item_tags or media_tag not in item_tags:
|
||||
add_tags.append(media_tag)
|
||||
for library_item in library_items:
|
||||
if not library_item:
|
||||
continue
|
||||
# 获取item的tag
|
||||
item_tags = self.__get_item_tags(library_item.item_id) or []
|
||||
|
||||
# 添加标签
|
||||
if add_tags:
|
||||
tags = [{"Name": str(add_tag)} for add_tag in add_tags]
|
||||
tags = {"Tags": tags}
|
||||
add_flag = self.__add_tag(media.get("Id"), tags)
|
||||
logger.info(f"特殊媒体添加标签成功:{media.get('Name')} {tags} {add_flag}")
|
||||
# 获取缺少的tag
|
||||
add_tags = []
|
||||
for library_tag in library_tags:
|
||||
if not item_tags or library_tag not in item_tags:
|
||||
add_tags.append(library_tag)
|
||||
|
||||
logger.info("Emby媒体标签任务完成")
|
||||
# 添加标签
|
||||
if add_tags:
|
||||
tags = [{"Name": str(add_tag)} for add_tag in add_tags]
|
||||
tags = {"Tags": tags}
|
||||
add_flag = self.__add_tag(library_item.item_id, tags)
|
||||
logger.info(f"{library.name} 添加标签成功:{library_item.title} {tags} {add_flag}")
|
||||
|
||||
# 特殊媒体名标签
|
||||
if self._media_tags and len(self._media_tags.keys()) > 0:
|
||||
for media_name, media_tags in self._media_tags.items():
|
||||
|
||||
match_medias = []
|
||||
# 根据Series/Movie搜索媒体
|
||||
for media_type in self._media_type.get(media_name):
|
||||
match_medias += self.__get_medias_by_name(media_name, media_type)
|
||||
|
||||
# 遍历媒体 补充缺失tag
|
||||
for media in match_medias:
|
||||
if not media:
|
||||
continue
|
||||
|
||||
# 获取item的tag
|
||||
item_tags = self.__get_item_tags(media.get("Id")) or []
|
||||
|
||||
# 获取缺少的tag
|
||||
add_tags = []
|
||||
for media_tag in media_tags:
|
||||
if not item_tags or media_tag not in item_tags:
|
||||
add_tags.append(media_tag)
|
||||
|
||||
# 添加标签
|
||||
if add_tags:
|
||||
tags = [{"Name": str(add_tag)} for add_tag in add_tags]
|
||||
tags = {"Tags": tags}
|
||||
add_flag = self.__add_tag(media.get("Id"), tags)
|
||||
logger.info(f"特殊媒体添加标签成功:{media.get('Name')} {tags} {add_flag}")
|
||||
|
||||
logger.info(f"{emby_name} 媒体标签任务完成")
|
||||
|
||||
@eventmanager.register(EventType.PluginAction)
|
||||
def remote_sync(self, event: Event):
|
||||
@@ -423,6 +425,32 @@ class EmbyMetaTag(_PluginBase):
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -452,6 +480,7 @@ class EmbyMetaTag(_PluginBase):
|
||||
"cron": "5 1 * * *",
|
||||
"tag_confs": "",
|
||||
"name_tag_confs": "",
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
|
||||
@@ -34,7 +34,7 @@ class EmbyReporter(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "Pydiocells_A.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.8.1"
|
||||
plugin_version = "1.9"
|
||||
# 插件作者
|
||||
plugin_author = "thsrite"
|
||||
# 作者主页
|
||||
@@ -58,6 +58,8 @@ class EmbyReporter(_PluginBase):
|
||||
_emby_host = None
|
||||
_emby_api_key = None
|
||||
show_time = True
|
||||
_mediaservers = None
|
||||
|
||||
_scheduler: Optional[BackgroundScheduler] = None
|
||||
mediaserver_helper = None
|
||||
PLAYBACK_REPORTING_TYPE_MOVIE = "ItemName"
|
||||
@@ -69,12 +71,6 @@ class EmbyReporter(_PluginBase):
|
||||
# 停止现有任务
|
||||
self.stop_service()
|
||||
self.mediaserver_helper = MediaServerHelper()
|
||||
emby_server = self.mediaserver_helper.get_service(name="Emby")
|
||||
if not emby_server:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
self.host = emby_server.config.get("host")
|
||||
self.api_key = emby_server.config.get("apikey")
|
||||
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
@@ -88,10 +84,7 @@ class EmbyReporter(_PluginBase):
|
||||
self.show_time = config.get("show_time")
|
||||
self._emby_host = config.get("emby_host")
|
||||
self._emby_api_key = config.get("emby_api_key")
|
||||
if self._emby_host and self._emby_api_key:
|
||||
self.host = f"http://{self._emby_host}" if not str(self._emby_host).startswith(
|
||||
"http") else self._emby_host
|
||||
self.api_key = self._emby_api_key
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
if self._enabled or self._onlyonce:
|
||||
# 定时服务
|
||||
@@ -137,47 +130,62 @@ class EmbyReporter(_PluginBase):
|
||||
if not self._type:
|
||||
return
|
||||
|
||||
# 获取当前时间并格式化
|
||||
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
|
||||
# 获取数据
|
||||
success, movies = self.get_report(types=self.PLAYBACK_REPORTING_TYPE_MOVIE, days=int(self._days),
|
||||
limit=int(self._cnt))
|
||||
if not success:
|
||||
exit(movies)
|
||||
logger.info(f"获取到电影 {movies}")
|
||||
success, tvshows = self.get_report(types=self.PLAYBACK_REPORTING_TYPE_TVSHOWS, days=int(self._days),
|
||||
limit=int(self._cnt))
|
||||
if not success:
|
||||
exit(tvshows)
|
||||
logger.info(f"获取到电视剧 {tvshows}")
|
||||
|
||||
# 绘制海报
|
||||
report_path = self.draw(res_path=self._res_dir,
|
||||
movies=movies,
|
||||
tvshows=tvshows,
|
||||
show_time=self.show_time)
|
||||
|
||||
if not report_path:
|
||||
logger.error("生成海报失败")
|
||||
emby_servers = self.mediaserver_helper.get_services(name_filters=self._mediaservers, type_filter="emby")
|
||||
if not emby_servers:
|
||||
logger.error("未配置Emby媒体服务器")
|
||||
return
|
||||
|
||||
# 示例调用
|
||||
self.__split_image_by_height(report_path, "/public/report", [250, 330, 335])
|
||||
for emby_name, emby_server in emby_servers.items():
|
||||
logger.info(f"开始处理媒体服务器 {emby_name}")
|
||||
self.host = emby_server.config.get("host")
|
||||
self.api_key = emby_server.config.get("apikey")
|
||||
if not self.host.endswith("/"):
|
||||
self.host += "/"
|
||||
if not self.host.startswith("http"):
|
||||
self.host = "http://" + self.host
|
||||
|
||||
# 分块推送
|
||||
for i in range(2, 4):
|
||||
report_path_part = f"/public/report_part_{i}.jpg"
|
||||
report_url = self._mp_host + report_path_part.replace("/public", "") + f"?_timestamp={current_time}"
|
||||
mtype = NotificationType.MediaServer
|
||||
if self._type:
|
||||
mtype = NotificationType.__getitem__(str(self._type)) or NotificationType.MediaServer
|
||||
# 获取当前时间并格式化
|
||||
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
|
||||
self.post_message(
|
||||
title=f'Movies 近{self._days}日观影排行' if i == 2 else f'TV Shows 近{self._days}日观影排行',
|
||||
mtype=mtype,
|
||||
image=report_url)
|
||||
logger.info(f"Emby观影记录推送成功 {report_url}")
|
||||
# 获取数据
|
||||
success, movies = self.get_report(types=self.PLAYBACK_REPORTING_TYPE_MOVIE, days=int(self._days),
|
||||
limit=int(self._cnt))
|
||||
if not success:
|
||||
exit(movies)
|
||||
logger.info(f"获取到电影 {movies}")
|
||||
success, tvshows = self.get_report(types=self.PLAYBACK_REPORTING_TYPE_TVSHOWS, days=int(self._days),
|
||||
limit=int(self._cnt))
|
||||
if not success:
|
||||
exit(tvshows)
|
||||
logger.info(f"获取到电视剧 {tvshows}")
|
||||
|
||||
# 绘制海报
|
||||
report_path = self.draw(res_path=self._res_dir,
|
||||
movies=movies,
|
||||
tvshows=tvshows,
|
||||
show_time=self.show_time,
|
||||
emby_name=emby_name)
|
||||
|
||||
if not report_path:
|
||||
logger.error("生成海报失败")
|
||||
break
|
||||
|
||||
# 示例调用
|
||||
self.__split_image_by_height(report_path, f"/public/report_{emby_name}", [250, 330, 335])
|
||||
|
||||
# 分块推送
|
||||
for i in range(2, 4):
|
||||
report_path_part = f"/public/report_{emby_name}_part_{i}.jpg"
|
||||
report_url = self._mp_host + report_path_part.replace("/public", "") + f"?_timestamp={current_time}"
|
||||
mtype = NotificationType.MediaServer
|
||||
if self._type:
|
||||
mtype = NotificationType.__getitem__(str(self._type)) or NotificationType.MediaServer
|
||||
|
||||
self.post_message(
|
||||
title=f'Movies 近{self._days}日观影排行' if i == 2 else f'TV Shows 近{self._days}日观影排行',
|
||||
mtype=mtype,
|
||||
image=report_url)
|
||||
logger.info(f"{emby_name} 观影记录推送成功 {report_url}")
|
||||
|
||||
@staticmethod
|
||||
def __split_image_by_height(image_path, output_path_prefix, heights):
|
||||
@@ -228,7 +236,8 @@ class EmbyReporter(_PluginBase):
|
||||
"show_time": self.show_time,
|
||||
"emby_host": self._emby_host,
|
||||
"emby_api_key": self._emby_api_key,
|
||||
"res_dir": self._res_dir
|
||||
"res_dir": self._res_dir,
|
||||
"mediaservers": self._mediaservers,
|
||||
})
|
||||
|
||||
def get_state(self) -> bool:
|
||||
@@ -475,6 +484,32 @@ class EmbyReporter(_PluginBase):
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSelect',
|
||||
'props': {
|
||||
'multiple': True,
|
||||
'chips': True,
|
||||
'clearable': True,
|
||||
'model': 'mediaservers',
|
||||
'label': '媒体服务器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.mediaserver_helper.get_configs().values() if
|
||||
config.type == "emby"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -530,7 +565,8 @@ class EmbyReporter(_PluginBase):
|
||||
"emby_api_key": "",
|
||||
"mp_host": "",
|
||||
"show_time": True,
|
||||
"type": ""
|
||||
"type": "",
|
||||
"mediaservers": [],
|
||||
}
|
||||
|
||||
def get_page(self) -> List[dict]:
|
||||
@@ -549,7 +585,7 @@ class EmbyReporter(_PluginBase):
|
||||
except Exception as e:
|
||||
logger.error("退出插件失败:%s" % str(e))
|
||||
|
||||
def draw(self, res_path, movies, tvshows, show_time=True):
|
||||
def draw(self, res_path, movies, tvshows, show_time=True, emby_name=None):
|
||||
# 默认路径 默认图
|
||||
if not res_path:
|
||||
res_path = os.path.join(Path(__file__).parent, "res")
|
||||
@@ -668,7 +704,7 @@ class EmbyReporter(_PluginBase):
|
||||
continue
|
||||
|
||||
if index >= 0:
|
||||
save_path = "/public/report.jpg"
|
||||
save_path = f"/public/report_{emby_name}.jpg"
|
||||
if Path(save_path).exists():
|
||||
Path.unlink(Path(save_path))
|
||||
bg.save(save_path)
|
||||
|
||||
Reference in New Issue
Block a user