223 lines
7.0 KiB
Python
223 lines
7.0 KiB
Python
from server import PromptServer
|
|
import os
|
|
import json
|
|
from aiohttp import web
|
|
|
|
|
|
class GroupExecutorSingle:
|
|
"""单组执行节点"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"group_name": ("STRING", {"default": "", "multiline": False}),
|
|
"repeat_count": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
|
|
"delay_seconds": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 60.0, "step": 0.1}),
|
|
},
|
|
"optional": {
|
|
"signal": ("SIGNAL",),
|
|
},
|
|
"hidden": {
|
|
"unique_id": "UNIQUE_ID"
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("SIGNAL",)
|
|
FUNCTION = "execute_group"
|
|
CATEGORY = "🎈LAOGOU"
|
|
|
|
def execute_group(self, group_name, repeat_count, delay_seconds, unique_id, signal=None):
|
|
try:
|
|
|
|
current_execution = {
|
|
"group_name": group_name,
|
|
"repeat_count": repeat_count,
|
|
"delay_seconds": delay_seconds
|
|
}
|
|
|
|
# 如果有信号输入
|
|
if signal is not None:
|
|
if isinstance(signal, list):
|
|
|
|
signal.append(current_execution)
|
|
return (signal,)
|
|
else:
|
|
return ([signal, current_execution],)
|
|
|
|
return (current_execution,)
|
|
|
|
except Exception as e:
|
|
return ({"error": str(e)},)
|
|
|
|
class GroupExecutorSender:
|
|
"""执行信号发送节点"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"signal": ("SIGNAL",),
|
|
},
|
|
"hidden": {
|
|
"unique_id": "UNIQUE_ID"
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
FUNCTION = "execute"
|
|
CATEGORY = "🎈LAOGOU"
|
|
OUTPUT_NODE = True
|
|
|
|
def execute(self, signal, unique_id):
|
|
try:
|
|
if not signal:
|
|
raise ValueError("没有收到执行信号")
|
|
|
|
execution_list = signal if isinstance(signal, list) else [signal]
|
|
|
|
PromptServer.instance.send_sync(
|
|
"execute_group_list", {
|
|
"node_id": unique_id,
|
|
"execution_list": execution_list
|
|
}
|
|
)
|
|
|
|
return ()
|
|
|
|
except Exception as e:
|
|
print(f"执行错误: {str(e)}")
|
|
return ()
|
|
|
|
class GroupExecutorRepeater:
|
|
"""执行列表重复处理节点"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"signal": ("SIGNAL",),
|
|
"repeat_count": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1
|
|
}),
|
|
"group_delay": ("FLOAT", {
|
|
"default": 0.0,
|
|
"min": 0.0,
|
|
"max": 300.0,
|
|
"step": 0.1
|
|
}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("SIGNAL",)
|
|
FUNCTION = "repeat"
|
|
CATEGORY = "🎈LAOGOU"
|
|
|
|
def repeat(self, signal, repeat_count, group_delay):
|
|
try:
|
|
if not signal:
|
|
raise ValueError("没有收到执行信号")
|
|
|
|
execution_list = signal if isinstance(signal, list) else [signal]
|
|
|
|
repeated_list = []
|
|
for i in range(repeat_count):
|
|
|
|
repeated_list.extend(execution_list)
|
|
|
|
if i < repeat_count - 1:
|
|
|
|
repeated_list.append({
|
|
"group_name": "__delay__",
|
|
"repeat_count": 1,
|
|
"delay_seconds": group_delay
|
|
})
|
|
|
|
return (repeated_list,)
|
|
|
|
except Exception as e:
|
|
print(f"重复处理错误: {str(e)}")
|
|
return ([],)
|
|
|
|
|
|
CONFIG_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "group_configs")
|
|
os.makedirs(CONFIG_DIR, exist_ok=True)
|
|
|
|
routes = PromptServer.instance.routes
|
|
@routes.get("/group_executor/configs")
|
|
async def get_configs(request):
|
|
try:
|
|
|
|
configs = []
|
|
for filename in os.listdir(CONFIG_DIR):
|
|
if filename.endswith('.json'):
|
|
configs.append({
|
|
"name": filename[:-5]
|
|
})
|
|
return web.json_response({"status": "success", "configs": configs})
|
|
except Exception as e:
|
|
print(f"[GroupExecutor] 获取配置失败: {str(e)}")
|
|
return web.json_response({"status": "error", "message": str(e)}, status=500)
|
|
|
|
@routes.post("/group_executor/configs")
|
|
async def save_config(request):
|
|
try:
|
|
print("[GroupExecutor] 收到保存配置请求")
|
|
data = await request.json()
|
|
config_name = data.get('name')
|
|
if not config_name:
|
|
return web.json_response({"status": "error", "message": "配置名称不能为空"}, status=400)
|
|
|
|
safe_name = "".join(c for c in config_name if c.isalnum() or c in (' ', '-', '_'))
|
|
filename = os.path.join(CONFIG_DIR, f"{safe_name}.json")
|
|
|
|
with open(filename, 'w', encoding='utf-8') as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
|
|
print(f"[GroupExecutor] 配置已保存: {filename}")
|
|
return web.json_response({"status": "success"})
|
|
except json.JSONDecodeError as e:
|
|
print(f"[GroupExecutor] JSON解析错误: {str(e)}")
|
|
return web.json_response({"status": "error", "message": f"JSON格式错误: {str(e)}"}, status=400)
|
|
except Exception as e:
|
|
print(f"[GroupExecutor] 保存配置失败: {str(e)}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return web.json_response({"status": "error", "message": str(e)}, status=500)
|
|
|
|
@routes.get('/group_executor/configs/{name}')
|
|
async def get_config(request):
|
|
try:
|
|
config_name = request.match_info.get('name')
|
|
if not config_name:
|
|
return web.json_response({"error": "配置名称不能为空"}, status=400)
|
|
|
|
filename = os.path.join(CONFIG_DIR, f"{config_name}.json")
|
|
if not os.path.exists(filename):
|
|
return web.json_response({"error": "配置不存在"}, status=404)
|
|
|
|
with open(filename, 'r', encoding='utf-8') as f:
|
|
config = json.load(f)
|
|
|
|
return web.json_response(config)
|
|
except Exception as e:
|
|
return web.json_response({"error": str(e)}, status=500)
|
|
|
|
@routes.delete('/group_executor/configs/{name}')
|
|
async def delete_config(request):
|
|
try:
|
|
config_name = request.match_info.get('name')
|
|
if not config_name:
|
|
return web.json_response({"error": "配置名称不能为空"}, status=400)
|
|
|
|
filename = os.path.join(CONFIG_DIR, f"{config_name}.json")
|
|
if not os.path.exists(filename):
|
|
return web.json_response({"error": "配置不存在"}, status=404)
|
|
|
|
os.remove(filename)
|
|
return web.json_response({"status": "success"})
|
|
except Exception as e:
|
|
return web.json_response({"error": str(e)}, status=500) |