mirror of
https://github.com/d0zingcat/MoviePilot-Plugins.git
synced 2026-05-13 23:16:47 +00:00
优化了仪表板组件性能
This commit is contained in:
@@ -621,11 +621,12 @@
|
||||
"name": "下载器助手",
|
||||
"description": "自动做种、站点标签、自动删种。",
|
||||
"labels": "下载管理",
|
||||
"version": "1.8",
|
||||
"version": "1.9",
|
||||
"icon": "DownloaderHelper.png",
|
||||
"author": "hotlcc",
|
||||
"level": 2,
|
||||
"history": {
|
||||
"v1.9": "优化了仪表板组件性能。",
|
||||
"v1.8": "新增仪表板活动种子组件,qb完美支持,tr尚未测试,有问题提Issue并@hotlcc",
|
||||
"v1.7": "优化了表单界面和一些逻辑。",
|
||||
"v1.6": "修复事件触发tr打标问题;表单界面优化。"
|
||||
|
||||
@@ -14,6 +14,7 @@ from transmission_rpc.torrent import Torrent, Status as TorrentStatus
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.event import eventmanager, Event
|
||||
from app.core.module import ModuleManager
|
||||
from app.helper.sites import SitesHelper
|
||||
from app.log import logger
|
||||
from app.modules.qbittorrent.qbittorrent import Qbittorrent
|
||||
@@ -32,7 +33,7 @@ class DownloaderHelper(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "DownloaderHelper.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.8"
|
||||
plugin_version = "1.9"
|
||||
# 插件作者
|
||||
plugin_author = "hotlcc"
|
||||
# 作者主页
|
||||
@@ -55,10 +56,6 @@ class DownloaderHelper(_PluginBase):
|
||||
# 任务锁
|
||||
__task_lock: RLock = RLock()
|
||||
|
||||
# 依赖组件
|
||||
# 站点帮助组件
|
||||
__sites_helper: SitesHelper = SitesHelper()
|
||||
|
||||
# 配置相关
|
||||
# 插件缺省配置
|
||||
__config_default: Dict[str, Any] = {
|
||||
@@ -99,6 +96,9 @@ class DownloaderHelper(_PluginBase):
|
||||
"""
|
||||
初始化插件
|
||||
"""
|
||||
# 停止现有服务
|
||||
self.stop_service()
|
||||
|
||||
# 修正配置
|
||||
config = self.__fix_config(config=config)
|
||||
# 加载插件配置
|
||||
@@ -111,9 +111,6 @@ class DownloaderHelper(_PluginBase):
|
||||
self.__exclude_tags = self.__split_tags(tags=exclude_tags)
|
||||
logger.info(f"插件配置加载完成:{config}")
|
||||
|
||||
# 停止现有服务
|
||||
self.stop_service()
|
||||
|
||||
# 如果需要立即运行一次
|
||||
if self.__get_config_item(config_key='run_once'):
|
||||
if self.__check_enable_any_task():
|
||||
@@ -666,6 +663,9 @@ class DownloaderHelper(_PluginBase):
|
||||
"""
|
||||
if not self.get_state() or not self.__check_enable_dashboard_widget():
|
||||
return None
|
||||
if self.__exit_event.is_set():
|
||||
logger.warn('插件服务正在退出,操作取消')
|
||||
return None
|
||||
dashboard_widget_size = self.__get_config_item('dashboard_widget_size')
|
||||
# 列配置
|
||||
cols = {
|
||||
@@ -679,9 +679,10 @@ class DownloaderHelper(_PluginBase):
|
||||
}
|
||||
# 全局配置
|
||||
attrs = {
|
||||
'refresh': self.__get_config_item('dashboard_widget_refresh'),
|
||||
'subtitle': '活动种子'
|
||||
}
|
||||
if self.__check_target_downloader():
|
||||
attrs['refresh'] = self.__get_config_item('dashboard_widget_refresh')
|
||||
# 页面元素
|
||||
elements = self.__get_dashboard_elememts()
|
||||
return cols, attrs, elements
|
||||
@@ -694,7 +695,7 @@ class DownloaderHelper(_PluginBase):
|
||||
logger.info('尝试停止插件服务...')
|
||||
self.__exit_event.set()
|
||||
self.__stop_scheduler()
|
||||
logger.info('插件服务停止成功')
|
||||
logger.info('插件服务停止完成')
|
||||
except Exception as e:
|
||||
logger.error(f"插件服务停止异常: {str(e)}", exc_info=True)
|
||||
finally:
|
||||
@@ -855,9 +856,9 @@ class DownloaderHelper(_PluginBase):
|
||||
:param site_domain: 站点域名
|
||||
:return: 站点信息
|
||||
"""
|
||||
if not site_domain or not self.__sites_helper:
|
||||
if not site_domain:
|
||||
return None
|
||||
return self.__sites_helper.get_indexer(site_domain)
|
||||
return SitesHelper().get_indexer(site_domain)
|
||||
|
||||
def __check_enable_listen(self) -> bool:
|
||||
"""
|
||||
@@ -1264,6 +1265,43 @@ class DownloaderHelper(_PluginBase):
|
||||
text += '\n————————————\n'
|
||||
return text
|
||||
|
||||
def __get_system_module_instance(self, module_id: str) -> Union[Qbittorrent, Transmission]:
|
||||
"""
|
||||
获取系统模块实例
|
||||
"""
|
||||
if not module_id:
|
||||
return None
|
||||
module_manager = ModuleManager()
|
||||
running_modules = module_manager._running_modules
|
||||
if not running_modules:
|
||||
return None
|
||||
module = running_modules.get(module_id)
|
||||
return module if module else None
|
||||
|
||||
def __get_qbittorrent(self) -> Qbittorrent:
|
||||
"""
|
||||
获取qb实例
|
||||
"""
|
||||
module = self.__get_system_module_instance(module_id='QbittorrentModule')
|
||||
if not module:
|
||||
return None
|
||||
qbittorrent = getattr(module, 'qbittorrent')
|
||||
if not qbittorrent or not getattr(qbittorrent, 'qbc'):
|
||||
return None
|
||||
return qbittorrent
|
||||
|
||||
def __get_transmission(self) -> Transmission:
|
||||
"""
|
||||
获取tr实例
|
||||
"""
|
||||
module = self.__get_system_module_instance(module_id='TransmissionModule')
|
||||
if not module:
|
||||
return None
|
||||
transmission = getattr(module, 'transmission')
|
||||
if not transmission or not getattr(transmission, 'trc'):
|
||||
return None
|
||||
return transmission
|
||||
|
||||
def __try_run(self, context: TaskContext = None):
|
||||
"""
|
||||
尝试运行插件任务
|
||||
@@ -1342,8 +1380,8 @@ class DownloaderHelper(_PluginBase):
|
||||
# 任务结果
|
||||
result = TaskResult(downloader_name)
|
||||
try:
|
||||
qbittorrent = Qbittorrent()
|
||||
if not qbittorrent.qbc:
|
||||
qbittorrent = self.__get_qbittorrent()
|
||||
if not qbittorrent:
|
||||
return context
|
||||
|
||||
logger.info(f'下载器[{downloader_name}]任务执行开始...')
|
||||
@@ -1553,8 +1591,8 @@ class DownloaderHelper(_PluginBase):
|
||||
result = TaskResult(downloader_name)
|
||||
|
||||
try:
|
||||
transmission = Transmission()
|
||||
if not transmission.trc:
|
||||
transmission = self.__get_transmission()
|
||||
if not transmission:
|
||||
return context
|
||||
|
||||
logger.info(f'下载器[{downloader_name}]任务执行开始...')
|
||||
@@ -1786,9 +1824,7 @@ class DownloaderHelper(_PluginBase):
|
||||
'content': self.__build_dashboard_widget_table_head_content(fields=fields)
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def __build_dashboard_widget_table_body_content(data: List[List[Any]],
|
||||
fields: List[Union[str, TorrentField]] = None) -> list:
|
||||
def __build_dashboard_widget_table_body_content(self, data: List[List[Any]], fields: List[Union[str, TorrentField]] = None) -> list:
|
||||
"""
|
||||
构造仪表板组件表体内容
|
||||
"""
|
||||
@@ -1807,6 +1843,7 @@ class DownloaderHelper(_PluginBase):
|
||||
} for col in row]
|
||||
} for row in data if row]
|
||||
else:
|
||||
empty_text = '暂无数据' if self.__check_target_downloader() else '目标下载器配置无效'
|
||||
return [{
|
||||
'component': 'tr',
|
||||
'props': {
|
||||
@@ -1818,7 +1855,7 @@ class DownloaderHelper(_PluginBase):
|
||||
'colspan': len(fields),
|
||||
'class': 'text-center'
|
||||
},
|
||||
'text': '暂无数据'
|
||||
'text': empty_text
|
||||
}]
|
||||
}]
|
||||
|
||||
@@ -1832,14 +1869,37 @@ class DownloaderHelper(_PluginBase):
|
||||
'content': self.__build_dashboard_widget_table_body_content(data=data, fields=fields)
|
||||
}
|
||||
|
||||
def __get_target_downloader_id(self) -> str:
|
||||
"""
|
||||
获取目标下载器id
|
||||
"""
|
||||
target_downloader = self.__get_config_item('dashboard_widget_target_downloader')
|
||||
if target_downloader == 'default':
|
||||
target_downloader = settings.DEFAULT_DOWNLOADER
|
||||
if not target_downloader:
|
||||
return None
|
||||
return target_downloader
|
||||
|
||||
def __check_target_downloader(self) -> bool:
|
||||
"""
|
||||
检查目标下载器是否有效
|
||||
"""
|
||||
target_downloader = self.__get_target_downloader_id()
|
||||
if not target_downloader:
|
||||
return False
|
||||
if target_downloader == Downloader.QB.id:
|
||||
return self.__get_qbittorrent() is not None
|
||||
elif target_downloader == Downloader.TR.id:
|
||||
return self.__get_transmission() is not None
|
||||
else:
|
||||
return False
|
||||
|
||||
def __get_downloader_torrent_data(self, fields: List[Union[str, TorrentField]] = None):
|
||||
"""
|
||||
获取下载器种子数据
|
||||
"""
|
||||
# 目标下载器
|
||||
target_downloader = self.__get_config_item('dashboard_widget_target_downloader')
|
||||
if target_downloader == 'default':
|
||||
target_downloader = settings.DEFAULT_DOWNLOADER
|
||||
target_downloader = self.__get_target_downloader_id()
|
||||
if not target_downloader:
|
||||
return None
|
||||
# 字段
|
||||
@@ -1857,19 +1917,29 @@ class DownloaderHelper(_PluginBase):
|
||||
"""
|
||||
获取qb种子数据
|
||||
"""
|
||||
qbittorrent = Qbittorrent()
|
||||
if not qbittorrent.qbc:
|
||||
if self.__exit_event.is_set():
|
||||
logger.warn('插件服务正在退出,操作取消')
|
||||
return None
|
||||
qbittorrent = self.__get_qbittorrent()
|
||||
if not qbittorrent:
|
||||
return None
|
||||
# 字段
|
||||
if not fields:
|
||||
fields = self.__get_config_item('dashboard_widget_display_fields')
|
||||
fields = self.__ensure_torrent_fields(fields=fields)
|
||||
status = [TorrentState.DOWNLOADING.value, TorrentState.UPLOADING.value]
|
||||
torrents, _ = qbittorrent.get_torrents(status=status)
|
||||
if not torrents:
|
||||
# 活动种子
|
||||
torrents, error = qbittorrent.get_torrents(status=['active'])
|
||||
if error:
|
||||
return None
|
||||
# 按状态过滤
|
||||
torrents = list(filter(lambda torrent: torrent.get(TorrentField.STATE.qb) in status, torrents))
|
||||
torrent_hashs = set([torrent.get('hash') for torrent in torrents if torrent and torrent.get('hash')])
|
||||
# 未下载完的种子
|
||||
downloading_torrents, _ = qbittorrent.get_torrents(status=['downloading'])
|
||||
if downloading_torrents:
|
||||
for downloading_torrent in downloading_torrents:
|
||||
torrent_hash = downloading_torrent.get('hash')
|
||||
if not torrent_hash or torrent_hash in torrent_hashs:
|
||||
continue
|
||||
torrents.append(downloading_torrent)
|
||||
# 按添加时间倒序排序
|
||||
torrents = sorted(torrents, key=lambda torrent: torrent.get(TorrentField.ADD_TIME.qb), reverse=True)
|
||||
return self.__convert_qbittorrent_torrents_data(torrents=torrents, fields=fields)
|
||||
@@ -1942,19 +2012,46 @@ class DownloaderHelper(_PluginBase):
|
||||
logger.error(f'从qb种子中提取值异常: {str(e)}, torrent = {str(torrent)}', exc_info=True)
|
||||
return None
|
||||
|
||||
def __build_transmission_field_arguments(self, fields: List[TorrentField]) -> List[str]:
|
||||
"""
|
||||
构造tr字段查询参数
|
||||
"""
|
||||
if not fields:
|
||||
return []
|
||||
arguments = [field.tr for field in fields if field and field.tr and not field.tr.startswith('#')]
|
||||
arguments.append('id')
|
||||
arguments.append(TorrentField.NAME.tr)
|
||||
arguments.append('hashString')
|
||||
# 处理依赖的字段
|
||||
if TorrentField.SELECT_SIZE in fields:
|
||||
arguments.append('wanted')
|
||||
if TorrentField.COMPLETED in fields:
|
||||
arguments.append('fileStats')
|
||||
if TorrentField.REMAINING in fields:
|
||||
arguments.append('wanted')
|
||||
arguments.append('fileStats')
|
||||
if TorrentField.REMAINING_TIME in fields:
|
||||
arguments.append(TorrentField.STATE.tr)
|
||||
arguments.append(TorrentField.DOWNLOAD_SPEED.tr)
|
||||
arguments.append('wanted')
|
||||
arguments.append('fileStats')
|
||||
return list(set(arguments))
|
||||
|
||||
def __get_transmission_torrent_data(self, fields: List[Union[str, TorrentField]] = None):
|
||||
"""
|
||||
获取tr种子数据
|
||||
"""
|
||||
transmission = Transmission()
|
||||
if not transmission.trc:
|
||||
if self.__exit_event.is_set():
|
||||
logger.warn('插件服务正在退出,操作取消')
|
||||
return None
|
||||
transmission = self.__get_transmission()
|
||||
if not transmission:
|
||||
return None
|
||||
# 字段
|
||||
if not fields:
|
||||
fields = self.__get_config_item('dashboard_widget_display_fields')
|
||||
fields = self.__ensure_torrent_fields(fields=fields)
|
||||
status = [TorrentStatus.DOWNLOADING.value, TorrentStatus.SEEDING.value]
|
||||
torrents, _ = transmission.get_torrents(status=status)
|
||||
torrents, _ = transmission.trc.get_recently_active_torrents(arguments=self.__build_transmission_field_arguments(fields=fields))
|
||||
if not torrents:
|
||||
return None
|
||||
# 按添加时间倒序排序
|
||||
@@ -1988,7 +2085,7 @@ class DownloaderHelper(_PluginBase):
|
||||
torrent.fields[TorrentField.REMAINING.tr] = remaining_size
|
||||
# 剩余时间
|
||||
if torrent.get(TorrentField.STATE.tr) == TorrentStatus.DOWNLOADING.value:
|
||||
download_speed = torrent.get(TorrentField.DOWNLOAD_SPEED.qb)
|
||||
download_speed = torrent.get(TorrentField.DOWNLOAD_SPEED.tr)
|
||||
if download_speed <= 0:
|
||||
remaining_time = -1
|
||||
else:
|
||||
@@ -2037,13 +2134,21 @@ class DownloaderHelper(_PluginBase):
|
||||
"""
|
||||
获取仪表板元素
|
||||
"""
|
||||
if self.__exit_event.is_set():
|
||||
logger.warn('插件服务正在退出,操作取消')
|
||||
return None
|
||||
fields = self.__get_config_item('dashboard_widget_display_fields')
|
||||
fields = self.__ensure_torrent_fields(fields=fields)
|
||||
data = self.__get_downloader_torrent_data(fields=fields)
|
||||
if self.__exit_event.is_set():
|
||||
logger.warn('插件服务正在退出,操作取消')
|
||||
return None
|
||||
return [{
|
||||
'component': 'VTable',
|
||||
'props': {
|
||||
'hover': True,
|
||||
'fixed-header': True,
|
||||
'density': 'compact',
|
||||
'style': {
|
||||
'height': '230px'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from qbittorrentapi import TorrentState
|
||||
from transmission_rpc.torrent import Status as TorrentStatus
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from qbittorrentapi import TorrentState
|
||||
|
||||
from app.utils.string import StringUtils
|
||||
from app.utils.singleton import Singleton
|
||||
from app.log import logger
|
||||
@@ -64,11 +63,19 @@ class StateConvertor(IConvertor, metaclass=Singleton):
|
||||
return '做种'
|
||||
if data == TorrentState.DOWNLOADING.value:
|
||||
return '下载中'
|
||||
if data == TorrentState.PAUSED_DOWNLOAD.value:
|
||||
return '暂停'
|
||||
if data == TorrentState.STALLED_DOWNLOAD.value:
|
||||
return '等待'
|
||||
# tr
|
||||
if data == TorrentStatus.SEEDING.value:
|
||||
if data == 6:
|
||||
return '做种'
|
||||
if data == TorrentStatus.DOWNLOADING.value:
|
||||
if data == 4:
|
||||
return '下载中'
|
||||
if data == 0:
|
||||
return '暂停'
|
||||
if data == 3:
|
||||
return '等待'
|
||||
return data
|
||||
except Exception as e:
|
||||
logger.error(f'{__name__} Error: {str(e)}, data = {data}', exc_info=True)
|
||||
|
||||
@@ -275,7 +275,7 @@ class TorrentField(Enum):
|
||||
SELECT_SIZE = ('选定大小', 'size', '#SELECT_SIZE', ByteSizeConvertor())
|
||||
TOTAL_SIZE = ('总大小', 'total_size', 'totalSize', ByteSizeConvertor())
|
||||
PROGRESS = ('已完成', 'progress', 'percentDone', PercentageConvertor())
|
||||
STATE = ('状态', 'state', '_status_str', StateConvertor())
|
||||
STATE = ('状态', 'state', 'status', StateConvertor())
|
||||
DOWNLOAD_SPEED = ('下载速度', 'dlspeed', 'rateDownload', SpeedConvertor())
|
||||
UPLOAD_SPEED = ('上传速度', 'upspeed', 'rateUpload', SpeedConvertor())
|
||||
REMAINING_TIME = ('剩余时间', '#REMAINING_TIME', '#REMAINING_TIME', TimeIntervalConvertor())
|
||||
|
||||
Reference in New Issue
Block a user