fix 远程交互命令

This commit is contained in:
jxxghp
2024-10-20 01:54:24 +08:00
parent c650f1b5e3
commit 08e07625cd
8 changed files with 63 additions and 51 deletions
+14 -24
View File
@@ -19,16 +19,7 @@ from app.utils.object import ObjectUtils
from app.utils.singleton import Singleton from app.utils.singleton import Singleton
class CommandChian(ChainBase): class CommandChain(ChainBase, metaclass=Singleton):
"""
插件处理链
"""
def process(self, *args, **kwargs):
pass
class Command(metaclass=Singleton):
""" """
全局命令管理消费事件 全局命令管理消费事件
""" """
@@ -37,14 +28,14 @@ class Command(metaclass=Singleton):
def __init__(self): def __init__(self):
# 插件管理器 # 插件管理器
super().__init__()
self.pluginmanager = PluginManager() self.pluginmanager = PluginManager()
# 处理链
self.chain = CommandChian()
# 定时服务管理 # 定时服务管理
self.scheduler = Scheduler() self.scheduler = Scheduler()
# 消息管理器 # 消息管理器
self.messagehelper = MessageHelper() self.messagehelper = MessageHelper()
# 内置命令 # 内置命令:标准参数 arg_str: str, channel: MessageChannel, userid: Union[str, int] = None, source: str = None
# 其中 arg_str 为用户输入的参数,channel 为消息渠道,userid 为用户IDsource 为消息来源,arg_str 可选
self._commands = { self._commands = {
"/cookiecloud": { "/cookiecloud": {
"id": "cookiecloud", "id": "cookiecloud",
@@ -148,7 +139,7 @@ class Command(metaclass=Singleton):
for command in plugin_commands: for command in plugin_commands:
self.register( self.register(
cmd=command.get('cmd'), cmd=command.get('cmd'),
func=Command.send_plugin_event, func=self.send_plugin_event,
desc=command.get('desc'), desc=command.get('desc'),
category=command.get('category'), category=command.get('category'),
data={ data={
@@ -158,9 +149,7 @@ class Command(metaclass=Singleton):
) )
# 广播注册命令菜单 # 广播注册命令菜单
if not settings.DEV: if not settings.DEV:
self.chain.register_commands(commands=self.get_commands()) self.register_commands(commands=self.get_commands())
# 重启msg
SystemChain().restart_finish()
def __run_command(self, command: Dict[str, any], data_str: str = "", def __run_command(self, command: Dict[str, any], data_str: str = "",
channel: MessageChannel = None, source: str = None, userid: Union[str, int] = None): channel: MessageChannel = None, source: str = None, userid: Union[str, int] = None):
@@ -170,7 +159,7 @@ class Command(metaclass=Singleton):
if command.get("type") == "scheduler": if command.get("type") == "scheduler":
# 定时服务 # 定时服务
if userid: if userid:
self.chain.post_message( self.post_message(
Notification( Notification(
channel=channel, channel=channel,
source=source, source=source,
@@ -183,7 +172,7 @@ class Command(metaclass=Singleton):
self.scheduler.start(job_id=command.get("id")) self.scheduler.start(job_id=command.get("id"))
if userid: if userid:
self.chain.post_message( self.post_message(
Notification( Notification(
channel=channel, channel=channel,
source=source, source=source,
@@ -203,15 +192,15 @@ class Command(metaclass=Singleton):
data['source'] = source data['source'] = source
data['user'] = userid data['user'] = userid
if data_str: if data_str:
data['args'] = data_str data['arg_str'] = data_str
cmd_data['data'] = data cmd_data['data'] = data
command['func'](**cmd_data) command['func'](**cmd_data)
elif args_num == 3: elif args_num == 3:
# 没有输入参数,只输入渠道来源、用户ID # 没有输入参数,只输入渠道来源、用户ID和消息来源
command['func'](channel, source, userid) command['func'](channel, userid, source)
elif args_num > 3: elif args_num > 3:
# 多个输入参数:用户输入、用户ID # 多个输入参数:用户输入、用户ID
command['func'](data_str, channel, source, userid) command['func'](data_str, channel, userid, source)
else: else:
# 没有参数 # 没有参数
command['func']() command['func']()
@@ -295,4 +284,5 @@ class Command(metaclass=Singleton):
cmd = event_str.split()[0] cmd = event_str.split()[0]
args = " ".join(event_str.split()[1:]) args = " ".join(event_str.split()[1:])
if self.get(cmd): if self.get(cmd):
self.execute(cmd, args, event_channel, event_source, event_user) self.execute(cmd=cmd, data_str=args,
channel=event_channel, source=event_source, userid=event_user)
+1 -1
View File
@@ -874,7 +874,7 @@ class DownloadChain(ChainBase):
# 全部存在 # 全部存在
return True, no_exists return True, no_exists
def remote_downloading(self, channel: MessageChannel, source: str, userid: Union[str, int] = None): def remote_downloading(self, channel: MessageChannel, userid: Union[str, int] = None, source: str = None):
""" """
查询正在下载的任务,并发送消息 查询正在下载的任务,并发送消息
""" """
+20 -7
View File
@@ -504,7 +504,8 @@ class SiteChain(ChainBase):
return False, f"无法打开网站!" return False, f"无法打开网站!"
return True, "连接成功" return True, "连接成功"
def remote_list(self, channel: MessageChannel, userid: Union[str, int] = None): def remote_list(self, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
查询所有站点,发送消息 查询所有站点,发送消息
""" """
@@ -532,10 +533,13 @@ class SiteChain(ChainBase):
# 发送列表 # 发送列表
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=title, text="\n".join(messages), userid=userid, title=title, text="\n".join(messages), userid=userid,
link=settings.MP_DOMAIN('#/site'))) link=settings.MP_DOMAIN('#/site'))
)
def remote_disable(self, arg_str, channel: MessageChannel, userid: Union[str, int] = None): def remote_disable(self, arg_str: str, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
禁用站点 禁用站点
""" """
@@ -557,9 +561,10 @@ class SiteChain(ChainBase):
"is_active": False "is_active": False
}) })
# 重新发送消息 # 重新发送消息
self.remote_list(channel, userid) self.remote_list(channel=channel, userid=userid, source=source)
def remote_enable(self, arg_str, channel: MessageChannel, userid: Union[str, int] = None): def remote_enable(self, arg_str: str, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
启用站点 启用站点
""" """
@@ -582,7 +587,7 @@ class SiteChain(ChainBase):
"is_active": True "is_active": True
}) })
# 重新发送消息 # 重新发送消息
self.remote_list(channel, userid) self.remote_list(channel=channel, userid=userid, source=source)
def update_cookie(self, site_info: Site, def update_cookie(self, site_info: Site,
username: str, password: str, two_step_code: str = None) -> Tuple[bool, str]: username: str, password: str, two_step_code: str = None) -> Tuple[bool, str]:
@@ -613,7 +618,8 @@ class SiteChain(ChainBase):
return True, msg return True, msg
return False, "未知错误" return False, "未知错误"
def remote_cookie(self, arg_str: str, channel: MessageChannel, userid: Union[str, int] = None): def remote_cookie(self, arg_str: str, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
使用用户名密码更新站点Cookie 使用用户名密码更新站点Cookie
""" """
@@ -622,6 +628,7 @@ class SiteChain(ChainBase):
if not arg_str: if not arg_str:
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=err_title, userid=userid)) title=err_title, userid=userid))
return return
arg_str = str(arg_str).strip() arg_str = str(arg_str).strip()
@@ -633,12 +640,14 @@ class SiteChain(ChainBase):
elif len(args) != 3: elif len(args) != 3:
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=err_title, userid=userid)) title=err_title, userid=userid))
return return
site_id = args[0] site_id = args[0]
if not site_id.isdigit(): if not site_id.isdigit():
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=err_title, userid=userid)) title=err_title, userid=userid))
return return
# 站点ID # 站点ID
@@ -648,10 +657,12 @@ class SiteChain(ChainBase):
if not site_info: if not site_info:
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=f"站点编号 {site_id} 不存在!", userid=userid)) title=f"站点编号 {site_id} 不存在!", userid=userid))
return return
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=f"开始更新【{site_info.name}】Cookie&UA ...", userid=userid)) title=f"开始更新【{site_info.name}】Cookie&UA ...", userid=userid))
# 用户名 # 用户名
username = args[1] username = args[1]
@@ -666,11 +677,13 @@ class SiteChain(ChainBase):
logger.error(msg) logger.error(msg)
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=f"{site_info.name}】 Cookie&UA更新失败!", title=f"{site_info.name}】 Cookie&UA更新失败!",
text=f"错误原因:{msg}", text=f"错误原因:{msg}",
userid=userid)) userid=userid))
else: else:
self.post_message(Notification( self.post_message(Notification(
channel=channel, channel=channel,
source=source,
title=f"{site_info.name}】 Cookie&UA更新成功", title=f"{site_info.name}】 Cookie&UA更新成功",
userid=userid)) userid=userid))
+9 -6
View File
@@ -941,13 +941,15 @@ class SubscribeChain(ChainBase):
"doubanid": mediainfo.douban_id "doubanid": mediainfo.douban_id
}) })
def remote_list(self, channel: MessageChannel, userid: Union[str, int] = None): def remote_list(self, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
查询订阅并发送消息 查询订阅并发送消息
""" """
subscribes = self.subscribeoper.list() subscribes = self.subscribeoper.list()
if not subscribes: if not subscribes:
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel,
source=source,
title='没有任何订阅!', userid=userid)) title='没有任何订阅!', userid=userid))
return return
title = f"共有 {len(subscribes)} 个订阅,回复对应指令操作: " \ title = f"共有 {len(subscribes)} 个订阅,回复对应指令操作: " \
@@ -964,15 +966,16 @@ class SubscribeChain(ChainBase):
f"[{subscribe.total_episode - (subscribe.lack_episode or subscribe.total_episode)}" f"[{subscribe.total_episode - (subscribe.lack_episode or subscribe.total_episode)}"
f"/{subscribe.total_episode}]") f"/{subscribe.total_episode}]")
# 发送列表 # 发送列表
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title=title, text='\n'.join(messages), userid=userid)) title=title, text='\n'.join(messages), userid=userid))
def remote_delete(self, arg_str: str, channel: MessageChannel, userid: Union[str, int] = None): def remote_delete(self, arg_str: str, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
删除订阅 删除订阅
""" """
if not arg_str: if not arg_str:
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title="请输入正确的命令格式:/subscribe_delete [id]" title="请输入正确的命令格式:/subscribe_delete [id]"
"[id]为订阅编号", userid=userid)) "[id]为订阅编号", userid=userid))
return return
@@ -984,7 +987,7 @@ class SubscribeChain(ChainBase):
subscribe_id = int(arg_str) subscribe_id = int(arg_str)
subscribe = self.subscribeoper.get(subscribe_id) subscribe = self.subscribeoper.get(subscribe_id)
if not subscribe: if not subscribe:
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title=f"订阅编号 {subscribe_id} 不存在!", userid=userid)) title=f"订阅编号 {subscribe_id} 不存在!", userid=userid))
return return
# 删除订阅 # 删除订阅
@@ -995,7 +998,7 @@ class SubscribeChain(ChainBase):
"doubanid": subscribe.doubanid "doubanid": subscribe.doubanid
}) })
# 重新发送消息 # 重新发送消息
self.remote_list(channel, userid) self.remote_list(channel=channel, userid=userid, source=source)
@staticmethod @staticmethod
def __get_subscribe_no_exits(subscribe_name: str, def __get_subscribe_no_exits(subscribe_name: str,
+11 -6
View File
@@ -19,20 +19,25 @@ class SystemChain(ChainBase, metaclass=Singleton):
_restart_file = "__system_restart__" _restart_file = "__system_restart__"
def remote_clear_cache(self, channel: MessageChannel, userid: Union[int, str]): def __init__(self):
super().__init__()
# 重启完成检测
self.restart_finish()
def remote_clear_cache(self, channel: MessageChannel, userid: Union[int, str], source: str = None):
""" """
清理系统缓存 清理系统缓存
""" """
self.clear_cache() self.clear_cache()
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title=f"缓存清理完成!", userid=userid)) title=f"缓存清理完成!", userid=userid))
def restart(self, channel: MessageChannel, userid: Union[int, str]): def restart(self, channel: MessageChannel, userid: Union[int, str], source: str = None):
""" """
重启系统 重启系统
""" """
if channel and userid: if channel and userid:
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title="系统正在重启,请耐心等候!", userid=userid)) title="系统正在重启,请耐心等候!", userid=userid))
# 保存重启信息 # 保存重启信息
self.save_cache({ self.save_cache({
@@ -59,11 +64,11 @@ class SystemChain(ChainBase, metaclass=Singleton):
title += f"当前前端版本:{front_local_version},远程版本:{front_release_version}" title += f"当前前端版本:{front_local_version},远程版本:{front_release_version}"
return title return title
def version(self, channel: MessageChannel, userid: Union[int, str]): def version(self, channel: MessageChannel, userid: Union[int, str], source: str = None):
""" """
查看当前版本、远程版本 查看当前版本、远程版本
""" """
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title=self.__get_version_message(), title=self.__get_version_message(),
userid=userid)) userid=userid))
+4 -3
View File
@@ -534,13 +534,14 @@ class TransferChain(ChainBase):
return trans_items return trans_items
def remote_transfer(self, arg_str: str, channel: MessageChannel, userid: Union[str, int] = None): def remote_transfer(self, arg_str: str, channel: MessageChannel,
userid: Union[str, int] = None, source: str = None):
""" """
远程重新整理,参数 历史记录ID TMDBID|类型 远程重新整理,参数 历史记录ID TMDBID|类型
""" """
def args_error(): def args_error():
self.post_message(Notification(channel=channel, self.post_message(Notification(channel=channel, source=source,
title="请输入正确的命令格式:/redo [id] [tmdbid/豆瓣id]|[类型]" title="请输入正确的命令格式:/redo [id] [tmdbid/豆瓣id]|[类型]"
"[id]历史记录编号", userid=userid)) "[id]历史记录编号", userid=userid))
@@ -571,7 +572,7 @@ class TransferChain(ChainBase):
mtype=MediaType(type_str), mtype=MediaType(type_str),
mediaid=media_id) mediaid=media_id)
if not state: if not state:
self.post_message(Notification(channel=channel, title="手动整理失败", self.post_message(Notification(channel=channel, title="手动整理失败", source=source,
text=errmsg, userid=userid, link=settings.MP_DOMAIN('#/history'))) text=errmsg, userid=userid, link=settings.MP_DOMAIN('#/history')))
return return
+1 -1
View File
@@ -423,7 +423,7 @@ class EventManager(metaclass=Singleton):
# 如果类不在全局变量中,尝试动态导入模块并创建实例 # 如果类不在全局变量中,尝试动态导入模块并创建实例
try: try:
# 导入模块,除了插件和Command,只有chain能响应事件 # 导入模块,除了插件,只有chain能响应事件
if not class_name.endswith("Chain"): if not class_name.endswith("Chain"):
logger.debug(f"事件处理出错:无效的 Chain 类名: {class_name},类名必须以 'Chain' 结尾") logger.debug(f"事件处理出错:无效的 Chain 类名: {class_name},类名必须以 'Chain' 结尾")
return None return None
+3 -3
View File
@@ -22,9 +22,9 @@ from app.helper.resource import ResourceHelper
from app.helper.message import MessageHelper from app.helper.message import MessageHelper
from app.scheduler import Scheduler from app.scheduler import Scheduler
from app.monitor import Monitor from app.monitor import Monitor
from app.command import Command, CommandChian
from app.schemas import Notification, NotificationType from app.schemas import Notification, NotificationType
from app.db import close_database from app.db import close_database
from app.chain.command import CommandChain
def start_frontend(): def start_frontend():
@@ -79,7 +79,7 @@ def check_auth():
if SitesHelper().auth_level < 2: if SitesHelper().auth_level < 2:
err_msg = "用户认证失败,站点相关功能将无法使用!" err_msg = "用户认证失败,站点相关功能将无法使用!"
MessageHelper().put(f"注意:{err_msg}", title="用户认证", role="system") MessageHelper().put(f"注意:{err_msg}", title="用户认证", role="system")
CommandChian().post_message( CommandChain().post_message(
Notification( Notification(
mtype=NotificationType.Manual, mtype=NotificationType.Manual,
title="MoviePilot用户认证", title="MoviePilot用户认证",
@@ -139,7 +139,7 @@ def start_modules(_: FastAPI):
# 启动定时服务 # 启动定时服务
Scheduler() Scheduler()
# 加载命令 # 加载命令
Command() CommandChain()
# 启动前端服务 # 启动前端服务
start_frontend() start_frontend()
# 检查认证状态 # 检查认证状态