Files
jacklukai-ComfyUI_DeployCash/__init__.py
T
2024-11-22 11:51:36 +08:00

442 lines
16 KiB
Python

import json
import re
import time
import aiohttp
import server
from aiohttp import web
from collections import deque
from .install import *
import os
import uuid
import hashlib
import platform
import stat
import urllib.request
import numpy as np
from .wss import thread_run, update_worker_flow
from .public import (
get_port_from_cmdline,
set_token,
get_token,
get_version,
find_project_root,
args,
get_client_id,
)
import threading
import folder_paths
from PIL import Image
input_directory = (
args.input_directory if args.input_directory else find_project_root() + "input"
)
def get_mac_address():
mac = uuid.getnode()
return ":".join(("%012X" % mac)[i : i + 2] for i in range(0, 12, 2))
def generate_unique_subdomain(mac_address, port):
unique_key = f"{mac_address}:{port}"
hash_object = hashlib.sha256(unique_key.encode())
subdomain = hash_object.hexdigest()[:12]
return subdomain
def set_executable_permission(file_path):
try:
st = os.stat(file_path)
os.chmod(file_path, st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
print(f"Execution permissions set on {file_path}")
except Exception as e:
print(f"Failed to set execution permissions: {e}")
def download_file(url, dest_path):
try:
with urllib.request.urlopen(url) as response, open(dest_path, "wb") as out_file:
data = response.read()
out_file.write(data)
print(f"File downloaded successfully: {dest_path}")
except Exception as e:
print(f"Failed to download the file: {e}")
PLUGIN_DIR = os.path.dirname(os.path.abspath(__file__))
SD_CLIENT_DIR = os.path.join(PLUGIN_DIR, "sdc")
SDC_EXECUTABLE = os.path.join(
SD_CLIENT_DIR, "sdc" if platform.system() != "Windows" else "sdc.exe"
)
INI_FILE = os.path.join(SD_CLIENT_DIR, "sdc.toml")
LOG_FILE = os.path.join(SD_CLIENT_DIR, "sdc.log")
subdomain = ""
thread_run()
def extract_and_verify_images(output):
results = {}
app_img_keys = []
for key, node in output.items():
if node["class_type"] == "DeployCash":
inputs = node.get("inputs", {})
for k, v in inputs.items():
if k.startswith("app_img") and isinstance(v, list) and len(v) > 0:
app_img_keys.append((k, v[0]))
err = 0
err_msg = ""
for app_img_key, img_key in app_img_keys:
if str(img_key) in output:
image_node = output[str(img_key)]
image_path = image_node.get("inputs", {}).get("image")
if image_path:
if verify_image_exists(input_directory + "/" + image_path):
results[app_img_key] = {
"image_path": image_path,
"status": "图片存在",
}
else:
err = err + 1
err_msg = err_msg + f"图片不存在: {app_img_key}\n"
else:
err = err + 1
err_msg = err_msg + f"图片不存在: {app_img_key}\n"
else:
err = err + 1
err_msg = err_msg + f"图片不存在: {app_img_key}\n"
return {"results": results, "err": err, "err_msg": err_msg}
def verify_image_exists(path):
if os.path.exists(path):
valid_extensions = {".jpg", ".jpeg", ".png", ".gif"}
ext = os.path.splitext(path)[1].lower()
if ext in valid_extensions:
return True
return False
@server.PromptServer.instance.routes.post("/manager/tech_main")
async def tech_zhulu(request):
json_data = await request.json()
if "postData" in json_data and isinstance(json_data["postData"], dict):
json_data["postData"]["subdomain"] = subdomain
async with aiohttp.ClientSession() as session:
json_data["version"] = get_version()
techsid = get_token()
upload_url = (
"https://aidep.cn/flow/api/upload/?i=66&t=0&v=1.0&from=wxapp&tech_client=wx&c=entry&a=wxapp&tech_client=sj&do=ttapp&m=tech_huise&r="
+ json_data["r"]
+ "&techsid="
+ techsid + "&client_id=" + get_client_id()
)
if json_data["r"] == "comfyui.apiv2.upload":
output = json_data["postData"]["output"]
workflow = json_data["postData"]["workflow"]
try:
output_verify = extract_and_verify_images(output)
if output_verify["err"] > 0:
err_info = {
"errno": 0,
"message": "ERROR",
"data": {
"data": {
"message": output_verify["err_msg"],
"code": 0,
}
},
}
return web.Response(status=200, text=json.dumps(err_info))
# json_data["postData"].pop("output")
# json_data["postData"].pop("workflow")
form_data = aiohttp.FormData()
form_data.add_field("json_data", json.dumps(json_data))
if "mainImages" in json_data["postData"]:
for item in json_data["postData"]["mainImages"]:
with open(input_directory + "/" + item, "rb") as f:
file_content = f.read()
form_data.add_field(
"mainImages",
file_content,
filename=os.path.basename(item),
content_type="application/octet-stream",
)
except Exception as e:
return web.Response(status=200, text=e)
async with session.post(upload_url, data=form_data) as response:
try:
response_result = await response.text()
result = json.loads(response_result)
if "data" in result and isinstance(result["data"], dict):
if "data" in result["data"] and isinstance(
result["data"]["data"], dict
):
result_data = result["data"]["data"]
if (
techsid != ""
and techsid != "init"
and result_data["code"] == 1
):
await update_worker_flow(result_data["name"], output)
await update_worker_flow(
result_data["name"], workflow, "workflow/"
)
return web.Response(
status=response.status, text=response_result
)
else:
return web.Response(
status=response.status, text=await response.text()
)
except json.JSONDecodeError as e:
return web.Response(
status=response.status, text=await response.text()
)
else:
async with session.post(upload_url, json=json_data) as resp:
if (
resp.status == 200
and resp.headers.get("Content-Type") == "application/json"
):
try:
other_api_data = await resp.json()
result = web.json_response(other_api_data)
if len(other_api_data["data"]["data"]["techsid"]) > len("12345"):
set_token(other_api_data["data"]["data"]["techsid"])
return result
except aiohttp.ContentTypeError:
error_text = await resp.text()
return web.Response(text=error_text, status=400)
if resp.status == 200:
try:
result = await resp.text()
result = json.loads(result)
result_data = result["data"]
if (
isinstance(result_data, dict)
and json_data["r"] == "comfyui.apiv2.code"
and "data" in result_data
and "techsid" in result_data["data"]["data"]
):
if len(result_data["data"]["data"]["techsid"]) > len("12345"):
set_token(result_data["data"]["data"]["techsid"])
return web.json_response(result)
except json.JSONDecodeError as e:
return web.Response(status=resp.status, text=await resp.text())
else:
return web.Response(status=resp.status, text=await resp.text())
@server.PromptServer.instance.routes.post("/manager/do_wss")
async def do_wss(request):
pass
class DeployCash:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"app_title": (
"STRING",
{
"multiline": False,
"default": "这是默认作品标题,请在comfyui中修改",
"placeholder": "",
},
),
"app_desc": (
"STRING",
{
"multiline": False,
"default": "这是默认功能介绍,请在comfyui中修改",
"placeholder": "",
},
),
"app_fee": (
"INT",
{
"default": 18,
"min": 0,
"max": 999999,
"step": 1,
"display": "number",
},
),
"free_times": (
"INT",
{
"default": 0,
"min": 0,
"max": 999999,
"step": 1,
"display": "number",
},
),
},
"optional": {
"app_img1(optional)": ("IMAGE",),
"app_img2(optional)": ("IMAGE",),
"app_img3(optional)": ("IMAGE",),
"custom_img1(optional)": ("IMAGE",),
"custom_img2(optional)": ("IMAGE",),
"custom_img3(optional)": ("IMAGE",),
"custom_video1(optional)": ("IMAGE",),
"custom_video2(optional)": ("IMAGE",),
"custom_video3(optional)": ("IMAGE",),
"custom_text1(optional)": (
"STRING",
{"multiline": False, "forceInput": True, "dynamicPrompts": False},
),
"custom_text2(optional)": (
"STRING",
{"multiline": False, "forceInput": True, "dynamicPrompts": False},
),
"custom_text3(optional)": (
"STRING",
{"multiline": False, "forceInput": True, "dynamicPrompts": False},
),
"custom_img1_desc": (
"STRING",
{"multiline": False, "default": "请上传图片"},
),
"custom_img2_desc": (
"STRING",
{"multiline": False, "default": "请上传图片"},
),
"custom_img3_desc": (
"STRING",
{"multiline": False, "default": "请上传图片"},
),
"custom_video1_desc": (
"STRING",
{"multiline": False, "default": "请上传视频"},
),
"custom_video2_desc": (
"STRING",
{"multiline": False, "default": "请上传视频"},
),
"custom_video3_desc": (
"STRING",
{"multiline": False, "default": "请上传视频"},
),
"custom_text1_desc": (
"STRING",
{"multiline": False, "default": "请输入文本"},
),
"custom_text2_desc": (
"STRING",
{"multiline": False, "default": "请输入文本"},
),
"custom_text3_desc": (
"STRING",
{"multiline": False, "default": "请输入文本"},
),
},
"hidden": {
"custom_text333333": (
"STRING",
{"multiline": False, "default": "输入文本"},
),
},
}
RETURN_TYPES = ()
CATEGORY = "DeployCash"
class DeployCash_textInput:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"text": (
"STRING",
{"default": "", "multiline": True, "placeholder": "文本输入"},
),
}
}
RETURN_TYPES = ("STRING",)
FUNCTION = "main"
CATEGORY = "DeployCash"
@staticmethod
def main(text):
return (text,)
class DeployCash_saveImage:
def __init__(self):
self.output_dir = folder_paths.get_output_directory()
self.type = "output"
self.prefix_append = ""
self.compress_level = 4
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"images": ("IMAGE",),
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
},
}
RETURN_TYPES = ()
FUNCTION = "save_images"
OUTPUT_NODE = True
CATEGORY = "DeployCash"
def save_images(self, images, filename_prefix="DeployCash"):
filename_prefix += self.prefix_append
full_output_folder, filename, counter, subfolder, filename_prefix = (
folder_paths.get_save_image_path(
filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]
)
)
results = list()
for batch_number, image in enumerate(images):
i = 255.0 * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
metadata = None
filename_with_batch_num = filename.replace("%batch_num%", str(batch_number))
file = f"DeployCash_{filename_with_batch_num}_{counter:05}_.png"
img.save(
os.path.join(full_output_folder, file),
pnginfo=metadata,
compress_level=self.compress_level,
)
results.append(
{"filename": file, "subfolder": subfolder, "type": self.type}
)
counter += 1
return {"ui": {"images": results}}
workspace_path = os.path.join(os.path.dirname(__file__))
dist_path = os.path.join(workspace_path, "huise_admin")
if os.path.exists(dist_path):
server.PromptServer.instance.app.add_routes(
[
web.static("/huise_admin/", dist_path),
]
)
WEB_DIRECTORY = "./web"
NODE_CLASS_MAPPINGS = {
"DeployCash": DeployCash,
"DeployCash_textInput": DeployCash_textInput,
"DeployCash_saveImage": DeployCash_saveImage,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"DeployCash": "DeployCash",
"DeployCash_textInput": "textInput",
"DeployCash_saveImage": "saveImage",
}