diff --git a/README.md b/README.md index 2eb4335..0b5119c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ | ShowInt | 显示整型(可指定消息中key值) | | ShowFloat | 显示浮点型(可指定消息中key值) | | ShowNumber | 显示数字(可指定消息中key值) | +| ShowBoolean | 显示布尔值(可指定消息中key值) | +| ImageEqual | 图片是否相等(可用于通过判断遮罩图是否全黑来判定是否有遮罩) | +| SDBaseVerNumber | 判断SD大模型版本是1.5还是xl | Tips: base64格式字符串比较长,会导致界面卡顿,接口请求带宽可能也会有瓶颈,条件允许可以把图片上传到OSS服务器得到URL,然后用LoadImageFromUrl加载,由于无相关OSS账号,上传OSS节点需自行编写,暂不支持。 diff --git a/easyapi/UtilNode.py b/easyapi/UtilNode.py index ccb9b48..1edb906 100644 --- a/easyapi/UtilNode.py +++ b/easyapi/UtilNode.py @@ -1,5 +1,7 @@ import torch +from comfy.model_patcher import ModelPatcher +import comfy.model_base from .util import tensor_to_pil, hex_to_rgba @@ -241,6 +243,27 @@ class ShowNumber: return {"ui": {key: (number,)}, "result": (number,)} +class ShowBoolean: + @classmethod + def INPUT_TYPES(self): + return { + "required": { + "Bool": ("BOOLEAN", {"forceInput": True}), + "key": ('STRING', {"default": "text"}), + } + } + + RETURN_TYPES = ("BOOLEAN",) + + FUNCTION = "show" + + CATEGORY = "EasyApi/Boolean" + OUTPUT_NODE = True + + def show(self, Bool, key): + return {"ui": {key: (Bool,)}, "result": (Bool,)} + + class ColorPicker: @classmethod def INPUT_TYPES(s): @@ -292,6 +315,44 @@ class ImageEqual: return torch.all(a == b), +# from ComfyUI-layer_diffusion +def get_model_sd_version(model: ModelPatcher): + base: comfy.model_base.BaseModel = model.model + model_config: comfy.supported_models.supported_models_base.BASE = base.model_config + if isinstance(model_config, comfy.supported_models.SDXL): + return False, True + elif isinstance( + model_config, (comfy.supported_models.SD15, comfy.supported_models.SD20) + ): + # SD15 and SD20 are compatible with each other. + return True, False + else: + return False, False + + +class SDBaseVerNumber: + @classmethod + def INPUT_TYPES(s): + return {"required": + { + "model": ("MODEL",), + }, + } + + RETURN_TYPES = ("BOOLEAN", "BOOLEAN",) + RETURN_NAMES = ("sd1.5", "sdxl",) + + FUNCTION = "exec" + + CATEGORY = "EasyApi/Logic" + + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False, ) + + def exec(self, model): + return (*get_model_sd_version(model),) + + NODE_CLASS_MAPPINGS = { "GetImageBatchSize": GetImageBatchSize, "JoinList": JoinList, @@ -303,8 +364,10 @@ NODE_CLASS_MAPPINGS = { "ShowInt": ShowInt, "ShowNumber": ShowNumber, "ShowFloat": ShowFloat, + "ShowBoolean": ShowBoolean, "ColorPicker": ColorPicker, "ImageEqual": ImageEqual, + "SDBaseVerNumber": SDBaseVerNumber, } # A dictionary that contains the friendly/humanly readable titles for the nodes @@ -319,6 +382,8 @@ NODE_DISPLAY_NAME_MAPPINGS = { "ShowInt": "Show Int", "ShowNumber": "Show Number", "ShowFloat": "Show Float", + "ShowBoolean": "Show Boolean", "ColorPicker": "Color Picker", "ImageEqual": "Image Equal Judgment", + "SDBaseVerNumber": "SD Base Version Number", } diff --git a/easyapi/mirrorUrlApply.py b/easyapi/mirrorUrlApply.py index a24510d..07a68aa 100644 --- a/easyapi/mirrorUrlApply.py +++ b/easyapi/mirrorUrlApply.py @@ -1,3 +1,5 @@ +from enum import Enum + from .settings import get_settings import copy @@ -24,29 +26,50 @@ mirror_url = [ "u_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0", }, ] +clone_mirror_url = [ + { + "id": "clone_github", + "o_url": "github.com", + # "n_url": "mirror.ghproxy.com/https://github.com" + "n_url": "None", + "u_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0", + }, +] -def get_custom_mirrors(): +class Mirror(Enum): + DOWN_MODEL = 0 + GIT_CLONE = 1 + + +def get_custom_mirrors(mirror_type=None): settings = get_settings() - base_mirrors = copy.deepcopy(mirror_url) - if settings and 'huggingface_mirror' in settings: - base_mirrors[1]['n_url'] = settings['huggingface_mirror'] - if settings and 'rawgithub_mirror' in settings: - base_mirrors[0]['n_url'] = settings['rawgithub_mirror'] - if settings and 'github_mirror' in settings: - base_mirrors[2]['n_url'] = settings['github_mirror'] + if mirror_type is Mirror.GIT_CLONE: + base_mirrors = copy.deepcopy(clone_mirror_url) + if settings and 'clone_github_mirror' in settings: + base_mirrors[0]['n_url'] = settings['clone_github_mirror'] + elif mirror_type is Mirror.DOWN_MODEL: + base_mirrors = copy.deepcopy(mirror_url) + if settings and 'huggingface_mirror' in settings: + base_mirrors[1]['n_url'] = settings['huggingface_mirror'] + if settings and 'rawgithub_mirror' in settings: + base_mirrors[0]['n_url'] = settings['rawgithub_mirror'] + if settings and 'github_mirror' in settings: + base_mirrors[2]['n_url'] = settings['github_mirror'] + else: + base_mirrors = {} return base_mirrors def replace_mirror_url(): from urllib.parse import urlparse - def replace_url(url: str): + def replace_url(url: str, mirror_type: Mirror = None): u = urlparse(url) netloc = u.netloc found = False user_agent = None - for mirror in get_custom_mirrors(): + for mirror in get_custom_mirrors(mirror_type): if netloc is not None and len(netloc) > 0 and netloc.lower() == mirror['o_url'] and mirror['n_url'] != 'None': u = u._replace(netloc=mirror['n_url']) print('[easyapi] origin url: {}, use mirror url: {}'.format(url, u.geturl())) @@ -57,60 +80,22 @@ def replace_mirror_url(): return found, u, user_agent import urllib.request - # not work when using "from urllib.request import urlopen" - # origin_urlopen = urllib.request.urlopen - # def wrap_urlopen(url, *args, **kwargs): - # """ - # implement of lib urllib - # Args: - # url: - # **kwargs: - # - # Returns: - # - # """ - # if isinstance(url, str): - # found, u, user_agent = replace_url(url) - # if found: - # url = u.geturl() - # data = None - # if user_agent is not None: - # headers = {'User-Agent': user_agent} - # if 'data' in kwargs: - # data = kwargs['data'] - # url = urllib.request.Request(url, data=data, headers=headers) - # - # return origin_urlopen.__call__(url, *args, **kwargs) - # else: - # # url is urllib.request.Request - # full_url = url.get_full_url() - # found, u, user_agent = replace_url(full_url) - # if found: - # url.full_url = u.geturl() - # if user_agent is not None: - # if url.headers is not None: - # url.headers['User-Agent'] = user_agent - # else: - # url.headers = {'User-Agent': user_agent} - # - # return origin_urlopen.__call__(url, *args, **kwargs) - - # open(self, fullurl, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT) import socket + # open(self, fullurl, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT) origin_urllib_open = urllib.request.OpenerDirector.open def wrap_open(obj, fullurl, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): """ - implement of lib requests + implement of lib urllib Args: - **args: self, method, url + **args: self, fullurl **kwargs: Returns: """ if isinstance(fullurl, str): - found, u, user_agent = replace_url(fullurl) + found, u, user_agent = replace_url(fullurl, Mirror.DOWN_MODEL) if found: url = u.geturl() if user_agent is not None: @@ -124,7 +109,7 @@ def replace_mirror_url(): else: # url is urllib.request.Request full_url = fullurl.get_full_url() - found, u, user_agent = replace_url(full_url) + found, u, user_agent = replace_url(full_url, Mirror.DOWN_MODEL) if found: fullurl.full_url = u.geturl() if user_agent is not None: @@ -151,12 +136,12 @@ def replace_mirror_url(): if 'url' in kwargs: url = kwargs['url'] - found, u, user_agent = replace_url(url) + found, u, user_agent = replace_url(url, Mirror.DOWN_MODEL) if found: kwargs['url'] = u.geturl() elif len(args) >= 3: url = args[2] - found, u, user_agent = replace_url(url) + found, u, user_agent = replace_url(url, Mirror.DOWN_MODEL) if found: new_updater = list(args) new_updater[2] = u.geturl() @@ -180,12 +165,12 @@ def replace_mirror_url(): if 'str_or_url' in kwargs: url = kwargs['str_or_url'] - found, u, user_agent = replace_url(url) + found, u, user_agent = replace_url(url, Mirror.DOWN_MODEL) if found: kwargs['str_or_url'] = u.geturl() elif len(args) >= 3: url = args[2] - found, u, user_agent = replace_url(url) + found, u, user_agent = replace_url(url, Mirror.DOWN_MODEL) if found: new_updater = list(args) new_updater[2] = u.geturl() @@ -193,14 +178,64 @@ def replace_mirror_url(): return origin_async_request.__call__(*args, **kwargs) + import git + origin_git_clone = git.Repo._clone + + def wrap_git_clone(*args, **kwargs): + """ + implement of lib git clone + Args: + **args: cls, git, url + **kwargs: + + Returns: + + """ + + if 'url' in kwargs: + url = kwargs['url'] + found, u, user_agent = replace_url(url, Mirror.GIT_CLONE) + if found: + kwargs['url'] = u.geturl() + elif len(args) >= 3: + url = args[2] + found, u, user_agent = replace_url(url, Mirror.GIT_CLONE) + if found: + new_updater = list(args) + new_updater[2] = u.geturl() + args = tuple(new_updater) + + return origin_git_clone.__call__(*args, **kwargs) + # urllib.request.urlopen = wrap_urlopen urllib.request.OpenerDirector.open = wrap_open requests.Session.request = wrap_requests aiohttp.ClientSession._request = wrap_aiohttp_requests + git.Repo._clone = wrap_git_clone + + # try: + # manager has been not loaded + # from ComfyUI-Manager.glob import manager_core + # wrap_manager_git_clone = manager_core.gitclone_install + # + # def wrap_manager_git_clone(files): + # urls = copy.deepcopy(files) + # if isinstance(urls, []|list|()): + # for i in range(len(urls)): + # url = urls[i] + # found, u, user_agent = replace_url(url, Mirror.GIT_CLONE) + # if found: + # urls[i]=u.geturl() + # + # return wrap_manager_git_clone.__call__(urls) + # + # manager_core.gitclone_install = wrap_manager_git_clone + # except Exception as e: + # print("[easyapi] fail to apply manager clone patch, error: {} ".format(e)) def init(): try: replace_mirror_url() except Exception as e: - print("[easyapi] load mirror url replace patch fail, error: {} ".format(e)) + print("[easyapi] fail to apply mirror url patch, error: {} ".format(e)) diff --git a/static/js/custom_node.js b/static/js/custom_node.js index 10a082c..bb5e86b 100644 --- a/static/js/custom_node.js +++ b/static/js/custom_node.js @@ -205,7 +205,7 @@ app.registerExtension({ return r; }; - if (nodeData.name === "ShowString" || nodeData.name === "ShowInt" || nodeData.name === "ShowNumber" || nodeData.name === "ShowFloat") { + if (nodeData.name === "ShowString" || nodeData.name === "ShowInt" || nodeData.name === "ShowNumber" || nodeData.name === "ShowFloat" || nodeData.name === "ShowBoolean") { const outSet = function (text) { if (this.widgets) { // if multiline is true, w.type will be customtext