mirror of
https://github.com/d0zingcat/MoviePilot-Plugins.git
synced 2026-05-21 07:26:51 +00:00
Merge pull request #486 from InfinityPacer/main
This commit is contained in:
@@ -59,6 +59,18 @@
|
||||
"v1.3": "MoviePilot V2 版本媒体库服务器刷新插件"
|
||||
}
|
||||
},
|
||||
"MediaServerMsg": {
|
||||
"name": "媒体库服务器通知",
|
||||
"description": "发送Emby/Jellyfin/Plex服务器的播放、入库等通知消息。",
|
||||
"labels": "消息通知,媒体库",
|
||||
"version": "1.4",
|
||||
"icon": "mediaplay.png",
|
||||
"author": "jxxghp",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.4": "MoviePilot V2 版本媒体库服务器通知插件"
|
||||
}
|
||||
},
|
||||
"ChatGPT": {
|
||||
"name": "ChatGPT",
|
||||
"description": "消息交互支持与ChatGPT对话。",
|
||||
|
||||
@@ -259,11 +259,11 @@ class BrushFlow(_PluginBase):
|
||||
auth_level = 2
|
||||
|
||||
# 私有属性
|
||||
siteshelper = None
|
||||
siteoper = None
|
||||
torrentschain = None
|
||||
subscribeoper = None
|
||||
downloaderhelper = None
|
||||
sites_helper = None
|
||||
site_oper = None
|
||||
torrents_chain = None
|
||||
subscribe_oper = None
|
||||
downloader_helper = None
|
||||
# 刷流配置
|
||||
_brush_config = None
|
||||
# Brush任务是否启动
|
||||
@@ -280,40 +280,14 @@ class BrushFlow(_PluginBase):
|
||||
# tabs
|
||||
_tabs = None
|
||||
|
||||
# Property
|
||||
|
||||
@property
|
||||
def service_info(self) -> Optional[ServiceInfo]:
|
||||
"""
|
||||
服务信息
|
||||
"""
|
||||
brush_config = self.__get_brush_config()
|
||||
service = self.downloaderhelper.get_service(name=brush_config.downloader)
|
||||
if not service:
|
||||
self.__log_and_notify_error("站点刷流任务出错,获取下载器实例失败,请检查配置")
|
||||
return None
|
||||
|
||||
if service.instance.is_inactive():
|
||||
self.__log_and_notify_error("站点刷流任务出错,下载器未连接")
|
||||
return None
|
||||
|
||||
return service
|
||||
|
||||
@property
|
||||
def downloader(self) -> Optional[Union[Qbittorrent, Transmission]]:
|
||||
"""
|
||||
下载器实例
|
||||
"""
|
||||
return self.service_info.instance if self.service_info else None
|
||||
|
||||
# endregion
|
||||
|
||||
def init_plugin(self, config: dict = None):
|
||||
self.siteshelper = SitesHelper()
|
||||
self.siteoper = SiteOper()
|
||||
self.torrentschain = TorrentsChain()
|
||||
self.subscribeoper = SubscribeOper()
|
||||
self.downloaderhelper = DownloaderHelper()
|
||||
self.sites_helper = SitesHelper()
|
||||
self.site_oper = SiteOper()
|
||||
self.torrents_chain = TorrentsChain()
|
||||
self.subscribe_oper = SubscribeOper()
|
||||
self.downloader_helper = DownloaderHelper()
|
||||
self._task_brush_enable = False
|
||||
|
||||
if not config:
|
||||
@@ -335,7 +309,7 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
# 这里先过滤掉已删除的站点并保存,特别注意的是,这里保留了界面选择站点时的顺序,以便后续站点随机刷流或顺序刷流
|
||||
if brush_config.brushsites:
|
||||
site_id_to_public_status = {site.get("id"): site.get("public") for site in self.siteshelper.get_indexers()}
|
||||
site_id_to_public_status = {site.get("id"): site.get("public") for site in self.sites_helper.get_indexers()}
|
||||
brush_config.brushsites = [
|
||||
site_id for site_id in brush_config.brushsites
|
||||
if site_id in site_id_to_public_status and not site_id_to_public_status[site_id]
|
||||
@@ -401,6 +375,30 @@ class BrushFlow(_PluginBase):
|
||||
self._scheduler.print_jobs()
|
||||
self._scheduler.start()
|
||||
|
||||
@property
|
||||
def service_info(self) -> Optional[ServiceInfo]:
|
||||
"""
|
||||
服务信息
|
||||
"""
|
||||
brush_config = self.__get_brush_config()
|
||||
service = self.downloader_helper.get_service(name=brush_config.downloader)
|
||||
if not service:
|
||||
self.__log_and_notify_error("站点刷流任务出错,获取下载器实例失败,请检查配置")
|
||||
return None
|
||||
|
||||
if service.instance.is_inactive():
|
||||
self.__log_and_notify_error("站点刷流任务出错,下载器未连接")
|
||||
return None
|
||||
|
||||
return service
|
||||
|
||||
@property
|
||||
def downloader(self) -> Optional[Union[Qbittorrent, Transmission]]:
|
||||
"""
|
||||
下载器实例
|
||||
"""
|
||||
return self.service_info.instance if self.service_info else None
|
||||
|
||||
def get_state(self) -> bool:
|
||||
brush_config = self.__get_brush_config()
|
||||
return True if brush_config and brush_config.enabled else False
|
||||
@@ -795,10 +793,10 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
# 站点选项
|
||||
site_options = [{"title": site.get("name"), "value": site.get("id")}
|
||||
for site in self.siteshelper.get_indexers()]
|
||||
for site in self.sites_helper.get_indexers()]
|
||||
# 下载器选项
|
||||
downloader_options = [{"title": config.name, "value": config.name}
|
||||
for config in self.downloaderhelper.get_configs().values()]
|
||||
for config in self.downloader_helper.get_configs().values()]
|
||||
return [
|
||||
{
|
||||
'component': 'VForm',
|
||||
@@ -1908,7 +1906,7 @@ class BrushFlow(_PluginBase):
|
||||
# 获取所有站点的信息,并过滤掉不存在的站点
|
||||
site_infos = []
|
||||
for siteid in brush_config.brushsites:
|
||||
siteinfo = self.siteoper.get(siteid)
|
||||
siteinfo = self.site_oper.get(siteid)
|
||||
if siteinfo:
|
||||
site_infos.append(siteinfo)
|
||||
|
||||
@@ -1943,13 +1941,13 @@ class BrushFlow(_PluginBase):
|
||||
"""
|
||||
针对站点进行刷流
|
||||
"""
|
||||
siteinfo = self.siteoper.get(siteid)
|
||||
siteinfo = self.site_oper.get(siteid)
|
||||
if not siteinfo:
|
||||
logger.warn(f"站点不存在:{siteid}")
|
||||
return True
|
||||
|
||||
logger.info(f"开始获取站点 {siteinfo.name} 的新种子 ...")
|
||||
torrents = self.torrentschain.browse(domain=siteinfo.domain)
|
||||
torrents = self.torrents_chain.browse(domain=siteinfo.domain)
|
||||
if not torrents:
|
||||
logger.info(f"站点 {siteinfo.name} 没有获取到种子")
|
||||
return True
|
||||
@@ -2314,7 +2312,7 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
if need_delete_hashes:
|
||||
# 如果是QB,则重新汇报Tracker
|
||||
if self.downloaderhelper.is_qbittorrent(service=self.service_info):
|
||||
if self.downloader_helper.is_qbittorrent(service=self.service_info):
|
||||
self.__qb_torrents_reannounce(torrent_hashes=need_delete_hashes)
|
||||
# 删除种子
|
||||
if downloader.delete_torrents(ids=need_delete_hashes, delete_file=True):
|
||||
@@ -2356,7 +2354,7 @@ class BrushFlow(_PluginBase):
|
||||
seeding_torrents_dict: Dict[str, Any]):
|
||||
brush_config = self.__get_brush_config()
|
||||
|
||||
if not self.downloaderhelper.is_qbittorrent(service=self.service_info):
|
||||
if not self.downloader_helper.is_qbittorrent(service=self.service_info):
|
||||
logger.info("同步种子刷流标签记录目前仅支持qbittorrent")
|
||||
return
|
||||
|
||||
@@ -3045,7 +3043,7 @@ class BrushFlow(_PluginBase):
|
||||
if not downloader:
|
||||
return None
|
||||
|
||||
if self.downloaderhelper.is_qbittorrent(service=self.service_info):
|
||||
if self.downloader_helper.is_qbittorrent(service=self.service_info):
|
||||
# 限速值转为bytes
|
||||
up_speed = up_speed * 1024 if up_speed else None
|
||||
down_speed = down_speed * 1024 if down_speed else None
|
||||
@@ -3079,7 +3077,7 @@ class BrushFlow(_PluginBase):
|
||||
return torrent_hash
|
||||
return None
|
||||
|
||||
elif self.downloaderhelper.is_transmission(service=self.service_info):
|
||||
elif self.downloader_helper.is_transmission(service=self.service_info):
|
||||
# 如果开启代理下载以及种子地址不是磁力地址,则请求种子到内存再传入下载器
|
||||
if not torrent_content.startswith("magnet"):
|
||||
response = RequestUtils(cookies=cookies,
|
||||
@@ -3127,7 +3125,7 @@ class BrushFlow(_PluginBase):
|
||||
获取种子hash
|
||||
"""
|
||||
try:
|
||||
return torrent.get("hash") if self.downloaderhelper.is_qbittorrent(service=self.service_info) \
|
||||
return torrent.get("hash") if self.downloader_helper.is_qbittorrent(service=self.service_info) \
|
||||
else torrent.hashString
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
@@ -3144,7 +3142,7 @@ class BrushFlow(_PluginBase):
|
||||
all_hashes = []
|
||||
for torrent in torrents:
|
||||
# 根据下载器类型获取Hash值
|
||||
hash_value = torrent.get("hash") if self.downloaderhelper.is_qbittorrent(service=self.service_info) \
|
||||
hash_value = torrent.get("hash") if self.downloader_helper.is_qbittorrent(service=self.service_info) \
|
||||
else torrent.hashString
|
||||
if hash_value:
|
||||
all_hashes.append(hash_value)
|
||||
@@ -3159,7 +3157,7 @@ class BrushFlow(_PluginBase):
|
||||
"""
|
||||
try:
|
||||
return [str(tag).strip() for tag in torrent.get("tags").split(',')] \
|
||||
if self.downloaderhelper.is_qbittorrent(service=self.service_info) else torrent.labels or []
|
||||
if self.downloader_helper.is_qbittorrent(service=self.service_info) else torrent.labels or []
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
return []
|
||||
@@ -3170,7 +3168,7 @@ class BrushFlow(_PluginBase):
|
||||
"""
|
||||
date_now = int(time.time())
|
||||
# QB
|
||||
if self.downloaderhelper.is_qbittorrent(service=self.service_info):
|
||||
if self.downloader_helper.is_qbittorrent(service=self.service_info):
|
||||
"""
|
||||
{
|
||||
"added_on": 1693359031,
|
||||
@@ -3551,7 +3549,7 @@ class BrushFlow(_PluginBase):
|
||||
if not self._subscribe_infos:
|
||||
self._subscribe_infos = {}
|
||||
|
||||
subscribes = self.subscribeoper.list()
|
||||
subscribes = self.subscribe_oper.list()
|
||||
if subscribes:
|
||||
# 遍历订阅
|
||||
for subscribe in subscribes:
|
||||
@@ -3807,7 +3805,7 @@ class BrushFlow(_PluginBase):
|
||||
# 使用StringUtils工具类获取tracker的域名
|
||||
domain = StringUtils.get_url_domain(tracker)
|
||||
|
||||
site_info = self.siteshelper.get_indexer(domain)
|
||||
site_info = self.sites_helper.get_indexer(domain)
|
||||
if site_info:
|
||||
return site_info.get("id"), site_info.get("name")
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class DownloadSiteTag(_PluginBase):
|
||||
# region 全局定义
|
||||
|
||||
# 插件名称
|
||||
plugin_name = "下载任务分类与标签"
|
||||
# 插件描述
|
||||
@@ -49,7 +47,7 @@ class DownloadSiteTag(_PluginBase):
|
||||
# 私有属性
|
||||
downloadhistory_oper = None
|
||||
sites_helper = None
|
||||
downloaderhelper = None
|
||||
downloader_helper = None
|
||||
_scheduler = None
|
||||
_enabled = False
|
||||
_onlyonce = False
|
||||
@@ -65,40 +63,9 @@ class DownloadSiteTag(_PluginBase):
|
||||
_category_anime = None
|
||||
_downloaders = None
|
||||
|
||||
# Property
|
||||
|
||||
@property
|
||||
def service_infos(self) -> Optional[Dict[str, ServiceInfo]]:
|
||||
"""
|
||||
服务信息
|
||||
"""
|
||||
if not self._downloaders:
|
||||
logger.warning("尚未配置下载器,请检查配置")
|
||||
return None
|
||||
|
||||
services = self.downloaderhelper.get_services(name_filters=self._downloaders)
|
||||
if not services:
|
||||
logger.warning("获取下载器实例失败,请检查配置")
|
||||
return None
|
||||
|
||||
active_services = {}
|
||||
for service_name, service_info in services.items():
|
||||
if service_info.instance.is_inactive():
|
||||
logger.warning(f"下载器 {service_name} 未连接,请检查配置")
|
||||
else:
|
||||
active_services[service_name] = service_info
|
||||
|
||||
if not active_services:
|
||||
logger.warning("没有已连接的下载器,请检查配置")
|
||||
return None
|
||||
|
||||
return active_services
|
||||
|
||||
# endregion
|
||||
|
||||
def init_plugin(self, config: dict = None):
|
||||
self.downloadhistory_oper = DownloadHistoryOper()
|
||||
self.downloaderhelper = DownloaderHelper()
|
||||
self.downloader_helper = DownloaderHelper()
|
||||
self.sites_helper = SitesHelper()
|
||||
# 读取配置
|
||||
if config:
|
||||
@@ -137,6 +104,33 @@ class DownloadSiteTag(_PluginBase):
|
||||
self._scheduler.print_jobs()
|
||||
self._scheduler.start()
|
||||
|
||||
@property
|
||||
def service_infos(self) -> Optional[Dict[str, ServiceInfo]]:
|
||||
"""
|
||||
服务信息
|
||||
"""
|
||||
if not self._downloaders:
|
||||
logger.warning("尚未配置下载器,请检查配置")
|
||||
return None
|
||||
|
||||
services = self.downloader_helper.get_services(name_filters=self._downloaders)
|
||||
if not services:
|
||||
logger.warning("获取下载器实例失败,请检查配置")
|
||||
return None
|
||||
|
||||
active_services = {}
|
||||
for service_name, service_info in services.items():
|
||||
if service_info.instance.is_inactive():
|
||||
logger.warning(f"下载器 {service_name} 未连接,请检查配置")
|
||||
else:
|
||||
active_services[service_name] = service_info
|
||||
|
||||
if not active_services:
|
||||
logger.warning("没有已连接的下载器,请检查配置")
|
||||
return None
|
||||
|
||||
return active_services
|
||||
|
||||
def get_state(self) -> bool:
|
||||
return self._enabled
|
||||
|
||||
@@ -668,7 +662,7 @@ class DownloadSiteTag(_PluginBase):
|
||||
'model': 'downloaders',
|
||||
'label': '下载器',
|
||||
'items': [{"title": config.name, "value": config.name}
|
||||
for config in self.downloaderhelper.get_configs().values()]
|
||||
for config in self.downloader_helper.get_configs().values()]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import time
|
||||
from typing import Any, List, Dict, Tuple
|
||||
from typing import Any, List, Dict, Tuple, Optional
|
||||
|
||||
from app.core.event import eventmanager, Event
|
||||
from app.helper.mediaserver import MediaServerHelper
|
||||
from app.log import logger
|
||||
from app.modules.emby import Emby
|
||||
from app.modules.jellyfin import Jellyfin
|
||||
from app.modules.plex import Plex
|
||||
from app.plugins import _PluginBase
|
||||
from app.schemas import WebhookEventInfo
|
||||
from app.schemas import WebhookEventInfo, ServiceInfo
|
||||
from app.schemas.types import EventType, MediaType, MediaImageType, NotificationType
|
||||
from app.utils.web import WebUtils
|
||||
|
||||
@@ -20,7 +18,7 @@ class MediaServerMsg(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "mediaplay.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.3"
|
||||
plugin_version = "1.4"
|
||||
# 插件作者
|
||||
plugin_author = "jxxghp"
|
||||
# 作者主页
|
||||
@@ -32,13 +30,11 @@ class MediaServerMsg(_PluginBase):
|
||||
# 可使用的用户级别
|
||||
auth_level = 1
|
||||
|
||||
# 对像
|
||||
plex = None
|
||||
emby = None
|
||||
jellyfin = None
|
||||
|
||||
# 私有属性
|
||||
mediaserver_helper = None
|
||||
_enabled = False
|
||||
_add_play_link = False
|
||||
_mediaservers = None
|
||||
_types = []
|
||||
_webhook_msg_keys = {}
|
||||
|
||||
@@ -63,13 +59,38 @@ class MediaServerMsg(_PluginBase):
|
||||
}
|
||||
|
||||
def init_plugin(self, config: dict = None):
|
||||
self.mediaserver_helper = MediaServerHelper()
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
self._types = config.get("types") or []
|
||||
if self._enabled:
|
||||
self.emby = Emby()
|
||||
self.plex = Plex()
|
||||
self.jellyfin = Jellyfin()
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
self._add_play_link = config.get("add_play_link", False)
|
||||
|
||||
def service_infos(self, type_filter: Optional[str] = None) -> Optional[Dict[str, ServiceInfo]]:
|
||||
"""
|
||||
服务信息
|
||||
"""
|
||||
if not self._mediaservers:
|
||||
logger.warning("尚未配置媒体服务器,请检查配置")
|
||||
return None
|
||||
|
||||
services = self.mediaserver_helper.get_services(type_filter=type_filter, name_filters=self._mediaservers)
|
||||
if not services:
|
||||
logger.warning("获取媒体服务器实例失败,请检查配置")
|
||||
return None
|
||||
|
||||
active_services = {}
|
||||
for service_name, service_info in services.items():
|
||||
if service_info.instance.is_inactive():
|
||||
logger.warning(f"媒体服务器 {service_name} 未连接,请检查配置")
|
||||
else:
|
||||
active_services[service_name] = service_info
|
||||
|
||||
if not active_services:
|
||||
logger.warning("没有已连接的媒体服务器,请检查配置")
|
||||
return None
|
||||
|
||||
return active_services
|
||||
|
||||
def get_state(self) -> bool:
|
||||
return self._enabled
|
||||
@@ -116,6 +137,47 @@ class MediaServerMsg(_PluginBase):
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VCol',
|
||||
'props': {
|
||||
'cols': 12,
|
||||
'md': 6
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
'component': 'VSwitch',
|
||||
'props': {
|
||||
'model': 'add_play_link',
|
||||
'label': '添加播放链接',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'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()]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -156,7 +218,7 @@ class MediaServerMsg(_PluginBase):
|
||||
'props': {
|
||||
'type': 'info',
|
||||
'variant': 'tonal',
|
||||
'text': '需要设置媒体服务器Webhook,回调相对路径为 /api/v1/webhook?token=moviepilot(3001端口),其中 moviepilot 为设置的 API_TOKEN。'
|
||||
'text': '需要设置媒体服务器Webhook,回调相对路径为 /api/v1/webhook?token=API_TOKEN&source=媒体服务器名(3001端口),其中 API_TOKEN 为设置的 API_TOKEN。'
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -253,15 +315,18 @@ class MediaServerMsg(_PluginBase):
|
||||
if not image_url:
|
||||
image_url = self._webhook_images.get(event_info.channel)
|
||||
|
||||
# 获取链接地址
|
||||
if event_info.channel == "emby":
|
||||
play_link = self.emby.get_play_url(event_info.item_id)
|
||||
elif event_info.channel == "plex":
|
||||
play_link = self.plex.get_play_url(event_info.item_id)
|
||||
elif event_info.channel == "jellyfin":
|
||||
play_link = self.jellyfin.get_play_url(event_info.item_id)
|
||||
else:
|
||||
play_link = None
|
||||
play_link = None
|
||||
if self._add_play_link:
|
||||
if event_info.server_name:
|
||||
service = self.service_infos().get(event_info.server_name)
|
||||
if service:
|
||||
play_link = service.instance.get_play_url(event_info.item_id)
|
||||
elif event_info.channel:
|
||||
services = self.mediaserver_helper.get_services(type_filter=event_info.channel)
|
||||
for service in services.values():
|
||||
play_link = service.instance.get_play_url(event_info.item_id)
|
||||
if play_link:
|
||||
break
|
||||
|
||||
if str(event_info.event) == "playback.stop":
|
||||
# 停止播放消息,添加到过期字典
|
||||
|
||||
@@ -31,13 +31,18 @@ class MediaServerRefresh(_PluginBase):
|
||||
# 可使用的用户级别
|
||||
auth_level = 1
|
||||
|
||||
mediaserver_helper = None
|
||||
# 私有属性
|
||||
mediaserver_helper = None
|
||||
_enabled = False
|
||||
_delay = 0
|
||||
_mediaservers = None
|
||||
|
||||
# Property
|
||||
def init_plugin(self, config: dict = None):
|
||||
self.mediaserver_helper = MediaServerHelper()
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
self._delay = config.get("delay") or 0
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
@property
|
||||
def service_infos(self) -> Optional[Dict[str, ServiceInfo]]:
|
||||
@@ -66,13 +71,6 @@ class MediaServerRefresh(_PluginBase):
|
||||
|
||||
return active_services
|
||||
|
||||
def init_plugin(self, config: dict = None):
|
||||
self.mediaserver_helper = MediaServerHelper()
|
||||
if config:
|
||||
self._enabled = config.get("enabled")
|
||||
self._delay = config.get("delay") or 0
|
||||
self._mediaservers = config.get("mediaservers") or []
|
||||
|
||||
def get_state(self) -> bool:
|
||||
return self._enabled
|
||||
|
||||
|
||||
Reference in New Issue
Block a user