Browse Source

Merge branch 'feat/various'

pull/190/head
Dr.Lt.Data 12 months ago
parent
commit
204b975074
  1. 6
      README.md
  2. 83
      __init__.py
  3. 133
      extension-node-map.json
  4. 40
      js/comfyui-manager.js
  5. 88
      js/custom-nodes-downloader.js
  6. 133
      node_db/new/extension-node-map.json
  7. 37
      prestartup_script.py
  8. 28
      scanner.py

6
README.md

@ -193,14 +193,14 @@ NODE_CLASS_MAPPINGS.update({
## Roadmap
- [ ] System displaying information about failed custom nodes import.
- [ ] Guide for missing nodes in ComfyUI vanilla nodes.
- [x] System displaying information about failed custom nodes import.
- [x] Guide for missing nodes in ComfyUI vanilla nodes.
- [x] Collision checking system for nodes with the same ID across extensions.
- [ ] Auto migration for custom nodes with changed structures.
- [ ] Version control feature for nodes.
- [ ] List of currently used custom nodes.
- [ ] Template sharing system.
- [ ] 3rd party API system.
- [ ] Collision checking system for nodes with the same ID across extensions.
# Disclaimer

83
__init__.py

@ -13,8 +13,10 @@ from tqdm.auto import tqdm
import concurrent
import ssl
from urllib.parse import urlparse
import http.client
import re
version = "V1.3"
version = "V1.4"
print(f"### Loading: ComfyUI-Manager ({version})")
@ -84,6 +86,7 @@ from torchvision.datasets.utils import download_url
comfy_ui_required_revision = 1240
comfy_ui_revision = "Unknown"
comfy_ui_commit_date = ""
comfy_path = os.path.dirname(folder_paths.__file__)
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
@ -247,6 +250,8 @@ def try_install_script(url, repo_path, install_cmd):
def print_comfyui_version():
global comfy_ui_revision
global comfy_ui_commit_date
try:
repo = git.Repo(os.path.dirname(folder_paths.__file__))
@ -260,10 +265,11 @@ def print_comfyui_version():
except:
pass
comfy_ui_commit_date = repo.head.commit.committed_datetime.date()
if current_branch == "master":
print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
else:
print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
except:
print("### ComfyUI Revision: UNKNOWN (The currently installed ComfyUI is not a Git repository)")
@ -413,7 +419,7 @@ def git_pull(path):
origin = repo.remote(name='origin')
origin.pull()
repo.git.submodule('update', '--init', '--recursive')
repo.close()
return True
@ -534,10 +540,15 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
try:
if do_update_check and git_repo_has_updates(dir_path, do_fetch, do_update):
item['installed'] = 'Update'
elif sys.__comfyui_manager_is_import_failed_extension(dir_name):
item['installed'] = 'Fail'
else:
item['installed'] = 'True'
except:
item['installed'] = 'True'
if sys.__comfyui_manager_is_import_failed_extension(dir_name):
item['installed'] = 'Fail'
else:
item['installed'] = 'True'
elif os.path.exists(dir_path + ".disabled"):
item['installed'] = 'Disabled'
@ -557,7 +568,10 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
file_path = os.path.join(base_path, dir_name)
if os.path.exists(file_path):
item['installed'] = 'True'
if sys.__comfyui_manager_is_import_failed_extension(dir_name):
item['installed'] = 'Fail'
else:
item['installed'] = 'True'
elif os.path.exists(file_path + ".disabled"):
item['installed'] = 'Disabled'
else:
@ -826,14 +840,14 @@ def get_current_snapshot():
def save_snapshot_with_postfix(postfix):
now = datetime.datetime.now()
now = datetime.datetime.now()
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = f"{date_time_format}_{postfix}"
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = f"{date_time_format}_{postfix}"
path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{file_name}.json")
with open(path, "w") as json_file:
json.dump(get_current_snapshot(), json_file, indent=4)
path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{file_name}.json")
with open(path, "w") as json_file:
json.dump(get_current_snapshot(), json_file, indent=4)
@server.PromptServer.instance.routes.get("/snapshot/get_current")
@ -1368,7 +1382,7 @@ async def install_model(request):
if json_data['url'].startswith('https://github.com') or json_data['url'].startswith('https://huggingface.co'):
model_dir = get_model_dir(json_data)
download_url(json_data['url'], model_dir)
return web.json_response({}, content_type='application/json')
else:
res = download_url_with_agent(json_data['url'], model_path)
@ -1433,6 +1447,37 @@ async def channel_url_list(request):
return web.Response(status=200)
@server.PromptServer.instance.routes.get("/manager/notice")
async def get_notice(request):
url = "github.com"
path = "/ltdrdata/ltdrdata.github.io/wiki/News"
conn = http.client.HTTPSConnection(url)
conn.request("GET", path)
response = conn.getresponse()
try:
if response.status == 200:
html_content = response.read().decode('utf-8')
pattern = re.compile(r'<div class="markdown-body">([\s\S]*?)</div>')
match = pattern.search(html_content)
if match:
markdown_content = match.group(1)
markdown_content += f"<HR>ComfyUI: {comfy_ui_revision} ({comfy_ui_commit_date})"
markdown_content += f"<BR>Manager: {version}"
return web.Response(text=markdown_content, status=200)
else:
return web.Response(text="Unable to retrieve Notice", status=200)
else:
return web.Response(text="Unable to retrieve Notice", status=200)
finally:
conn.close()
@server.PromptServer.instance.routes.get("/manager/share_option")
async def share_option(request):
if "value" in request.rel_url.query:
@ -1554,13 +1599,13 @@ async def share_art(request):
prompt = json_data['prompt']
potential_outputs = json_data['potential_outputs']
selected_output_index = json_data['selected_output_index']
try:
output_to_share = potential_outputs[int(selected_output_index)]
except:
# for now, pick the first output
output_to_share = potential_outputs[0]
assert output_to_share['type'] in ('image', 'output')
output_dir = folder_paths.get_output_directory()
@ -1585,7 +1630,7 @@ async def share_art(request):
if "comfyworkflows" in share_destinations:
share_website_host = "https://comfyworkflows.com"
share_endpoint = f"{share_website_host}/api"
# get presigned urls
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
async with session.post(
@ -1655,7 +1700,7 @@ async def share_art(request):
homeserver = homeserver.replace("http://", "https://")
if not homeserver.startswith("https://"):
homeserver = "https://" + homeserver
client = MatrixClient(homeserver)
try:
token = client.login(username=matrix_auth['username'], password=matrix_auth['password'])
@ -1667,7 +1712,7 @@ async def share_art(request):
matrix = MatrixHttpApi(homeserver, token=token)
with open(asset_filepath, 'rb') as f:
mxc_url = matrix.media_upload(f.read(), content_type, filename=filename)['content_uri']
workflow_json_mxc_url = matrix.media_upload(prompt['workflow'], 'application/json', filename='workflow.json')['content_uri']
text_content = ""
@ -1684,7 +1729,7 @@ async def share_art(request):
import traceback
traceback.print_exc()
return web.json_response({"error" : "An error occurred when sharing your art to Matrix."}, content_type='application/json', status=500)
return web.json_response({
"comfyworkflows" : {
"url" : None if "comfyworkflows" not in share_destinations else f"{share_website_host}/workflows/{workflowId}",

133
extension-node-map.json

@ -2565,6 +2565,138 @@
"title_aux": "comfy-nodes"
}
],
"https://github.com/comfyanonymous/ComfyUI": [
[
"BasicScheduler",
"CLIPLoader",
"CLIPMergeSimple",
"CLIPSave",
"CLIPSetLastLayer",
"CLIPTextEncode",
"CLIPTextEncodeSDXL",
"CLIPTextEncodeSDXLRefiner",
"CLIPVisionEncode",
"CLIPVisionLoader",
"Canny",
"CheckpointLoader",
"CheckpointLoaderSimple",
"CheckpointSave",
"ConditioningAverage",
"ConditioningCombine",
"ConditioningConcat",
"ConditioningSetArea",
"ConditioningSetAreaPercentage",
"ConditioningSetMask",
"ConditioningSetTimestepRange",
"ConditioningZeroOut",
"ControlNetApply",
"ControlNetApplyAdvanced",
"ControlNetLoader",
"CropMask",
"DiffControlNetLoader",
"DiffusersLoader",
"DualCLIPLoader",
"EmptyImage",
"EmptyLatentImage",
"ExponentialScheduler",
"FeatherMask",
"FlipSigmas",
"FreeU",
"FreeU_V2",
"GLIGENLoader",
"GLIGENTextBoxApply",
"GrowMask",
"HyperTile",
"HypernetworkLoader",
"ImageBatch",
"ImageBlend",
"ImageBlur",
"ImageColorToMask",
"ImageCompositeMasked",
"ImageCrop",
"ImageInvert",
"ImageOnlyCheckpointLoader",
"ImagePadForOutpaint",
"ImageQuantize",
"ImageScale",
"ImageScaleBy",
"ImageScaleToTotalPixels",
"ImageSharpen",
"ImageToMask",
"ImageUpscaleWithModel",
"InvertMask",
"JoinImageWithAlpha",
"KSampler",
"KSamplerAdvanced",
"KSamplerSelect",
"KarrasScheduler",
"LatentAdd",
"LatentBlend",
"LatentComposite",
"LatentCompositeMasked",
"LatentCrop",
"LatentFlip",
"LatentFromBatch",
"LatentInterpolate",
"LatentMultiply",
"LatentRotate",
"LatentSubtract",
"LatentUpscale",
"LatentUpscaleBy",
"LoadImage",
"LoadImageMask",
"LoadLatent",
"LoraLoader",
"LoraLoaderModelOnly",
"MaskComposite",
"MaskToImage",
"ModelMergeAdd",
"ModelMergeBlocks",
"ModelMergeSimple",
"ModelMergeSubtract",
"ModelSamplingContinuousEDM",
"ModelSamplingDiscrete",
"PatchModelAddDownscale",
"PolyexponentialScheduler",
"PorterDuffImageComposite",
"PreviewImage",
"RebatchLatents",
"RepeatImageBatch",
"RepeatLatentBatch",
"RescaleCFG",
"SVD_img2vid_Conditioning",
"SamplerCustom",
"SamplerDPMPP_2M_SDE",
"SamplerDPMPP_SDE",
"SaveAnimatedPNG",
"SaveAnimatedWEBP",
"SaveImage",
"SaveLatent",
"SetLatentNoiseMask",
"SolidMask",
"SplitImageWithAlpha",
"SplitSigmas",
"StyleModelApply",
"StyleModelLoader",
"TomePatchModel",
"UNETLoader",
"UpscaleModelLoader",
"VAEDecode",
"VAEDecodeTiled",
"VAEEncode",
"VAEEncodeForInpaint",
"VAEEncodeTiled",
"VAELoader",
"VAESave",
"VPScheduler",
"VideoLinearCFGGuidance",
"unCLIPCheckpointLoader",
"unCLIPConditioning"
],
{
"title_aux": "ComfyUI"
}
],
"https://github.com/comfyanonymous/ComfyUI_experiments": [
[
"ModelMergeBlockNumber",
@ -4274,6 +4406,7 @@
[
"Auto Merge Block Weighted",
"CLIPMergeSimple",
"CheckpointSave",
"ModelMergeBlocks",
"ModelMergeSimple"
],

40
js/comfyui-manager.js vendored

@ -29,6 +29,16 @@ docStyle.innerHTML = `
text-align: center;
height: 45px;
}
.cm-notice-board {
width: 250px;
height: 160px;
overflow: auto;
color: var(--input-text);
border: 1px solid #ccc;
padding: 10px;
overflow-x: hidden;
};
`;
document.head.appendChild(docStyle);
@ -89,6 +99,14 @@ async function init_share_option() {
});
}
async function init_notice(notice) {
api.fetchApi('/manager/notice')
.then(response => response.text())
.then(data => {
notice.innerHTML = data;
})
}
await init_badge_mode();
await init_share_option();
@ -492,7 +510,7 @@ class ManagerMenuDialog extends ComfyDialog {
}
createControlsRight() {
return [
const elts = [
$el("button", {
type: "button",
textContent: "ComfyUI Community Manual",
@ -570,7 +588,16 @@ class ManagerMenuDialog extends ComfyDialog {
textContent: "ComfyUI Nodes Info",
onclick: () => { window.open("https://ltdrdata.github.io/", "comfyui-node-info"); }
}),
$el("br", {}, []),
];
var textarea = document.createElement("div");
textarea.className = "cm-notice-board";
elts.push(textarea);
init_notice(textarea);
return elts;
}
constructor() {
@ -603,7 +630,7 @@ class ManagerMenuDialog extends ComfyDialog {
this.element = $el("div.comfy-modal", { parent: document.body }, [ content ]);
this.element.style.width = '1000px';
this.element.style.height = '400px';
this.element.style.height = '420px';
this.element.style.zIndex = 10000;
}
@ -638,6 +665,7 @@ app.registerExtension({
}
menu.append(managerButton);
const shareButton = document.createElement("button");
shareButton.id = "shareButton";
shareButton.textContent = "Share";
@ -680,6 +708,10 @@ app.registerExtension({
if (nicknames[nodeData.name.trim()]) {
let nick = nicknames[nodeData.name.trim()];
if (nick == 'ComfyUI') {
nick = "🦊"
}
if (nick.length > 25) {
text += nick.substring(0, 23) + "..";
}
@ -726,6 +758,10 @@ app.registerExtension({
if (nicknames[node.type.trim()]) {
let nick = nicknames[node.type.trim()];
if (nick == 'ComfyUI') {
nick = "🦊"
}
if (nick.length > 25) {
text += nick.substring(0, 23) + "..";
}

88
js/custom-nodes-downloader.js

@ -29,6 +29,53 @@ async function getCustomnodeMappings() {
return data;
}
async function getConflictMappings() {
var mode = "url";
if(manager_instance.local_mode_checkbox.checked)
mode = "local";
const response = await api.fetchApi(`/customnode/getmappings?mode=${mode}`);
const data = await response.json();
let node_to_extensions_map = {};
for(let k in data) {
for(let i in data[k][0]) {
let node = data[k][0][i];
let l = node_to_extensions_map[node];
if(!l) {
l = [];
node_to_extensions_map[node] = l;
}
l.push(k);
}
}
let conflict_map = {};
for(let node in node_to_extensions_map) {
if(node_to_extensions_map[node].length > 1) {
for(let i in node_to_extensions_map[node]) {
let extension = node_to_extensions_map[node][i];
let l = conflict_map[extension];
if(!l) {
l = [];
conflict_map[extension] = l;
}
for(let j in node_to_extensions_map[node]) {
let extension2 = node_to_extensions_map[node][j];
if(extension != extension2)
l.push([node, extension2]);
}
}
}
}
return conflict_map;
}
async function getUnresolvedNodesInComponent() {
try {
var mode = "url";
@ -180,6 +227,8 @@ export class CustomNodesInstaller extends ComfyDialog {
// invalidate
this.data = (await getCustomNodes()).custom_nodes;
this.conflict_mappings = await getConflictMappings();
if(this.is_missing_node_mode)
this.data = await this.filter_missing_node(this.data);
@ -369,6 +418,7 @@ export class CustomNodesInstaller extends ComfyDialog {
var data1 = document.createElement('td');
data1.style.textAlign = "center";
data1.innerHTML = i+1;
var data2 = document.createElement('td');
data2.style.maxWidth = "100px";
data2.className = "cm-node-author"
@ -376,14 +426,43 @@ export class CustomNodesInstaller extends ComfyDialog {
data2.style.whiteSpace = "nowrap";
data2.style.overflow = "hidden";
data2.style.textOverflow = "ellipsis";
var data3 = document.createElement('td');
data3.style.maxWidth = "200px";
data3.style.wordWrap = "break-word";
data3.className = "cm-node-name"
data3.innerHTML = `&nbsp;<a href=${data.reference} target="_blank"><font color="skyblue"><b>${data.title}</b></font></a>`;
if(data.installed == 'Fail')
data3.innerHTML = '&nbsp;<font color="BLACK"><B>(IMPORT FAILED)</B></font>' + data3.innerHTML;
var data4 = document.createElement('td');
data4.innerHTML = data.description;
data4.className = "cm-node-desc"
let conflicts = this.conflict_mappings[data.files[0]];
if(conflicts) {
let buf = '<BR><BR><FONT color="#AA3333"><B>Conflicted Nodes:</B><BR>';
for(let k in conflicts) {
let node_name = conflicts[k][0];
let extension_name = conflicts[k][1].split('/').pop();
if(extension_name.endsWith('/')) {
extension_name = extension_name.slice(0, -1);
}
if(node_name.endsWith('.git')) {
extension_name = extension_name.slice(0, -4);
}
buf += `${node_name} [${extension_name}], `;
}
if(buf.endsWith(', ')) {
buf = buf.slice(0, -2);
}
buf += "</FONT>";
data4.innerHTML += buf;
}
var data5 = document.createElement('td');
data5.style.textAlign = "center";
@ -424,6 +503,7 @@ export class CustomNodesInstaller extends ComfyDialog {
installBtn.innerHTML = 'Uninstall';
installBtn.style.backgroundColor = 'red';
break;
case 'Fail':
case 'True':
installBtn3 = document.createElement('button');
installBtn3.innerHTML = 'Disable';
@ -441,7 +521,7 @@ export class CustomNodesInstaller extends ComfyDialog {
installBtn.style.color = 'white';
break;
default:
installBtn.innerHTML = 'Try Install';
installBtn.innerHTML = `Try Install${data.installed}`;
installBtn.style.backgroundColor = 'Gray';
installBtn.style.color = 'white';
}
@ -479,7 +559,10 @@ export class CustomNodesInstaller extends ComfyDialog {
data5.appendChild(installBtn);
dataRow.style.backgroundColor = "var(--bg-color)";
if(data.installed == 'Fail')
dataRow.style.backgroundColor = "#880000";
else
dataRow.style.backgroundColor = "var(--bg-color)";
dataRow.style.color = "var(--fg-color)";
dataRow.style.textAlign = "left";
@ -548,6 +631,7 @@ export class CustomNodesInstaller extends ComfyDialog {
{ value:'Update', text:'Filter: update' },
{ value:'True', text:'Filter: installed' },
{ value:'False', text:'Filter: not-installed' },
{ value:'Fail', text:'Filter: import failed' },
];
items.forEach(item => {

133
node_db/new/extension-node-map.json

@ -2565,6 +2565,138 @@
"title_aux": "comfy-nodes"
}
],
"https://github.com/comfyanonymous/ComfyUI": [
[
"BasicScheduler",
"CLIPLoader",
"CLIPMergeSimple",
"CLIPSave",
"CLIPSetLastLayer",
"CLIPTextEncode",
"CLIPTextEncodeSDXL",
"CLIPTextEncodeSDXLRefiner",
"CLIPVisionEncode",
"CLIPVisionLoader",
"Canny",
"CheckpointLoader",
"CheckpointLoaderSimple",
"CheckpointSave",
"ConditioningAverage",
"ConditioningCombine",
"ConditioningConcat",
"ConditioningSetArea",
"ConditioningSetAreaPercentage",
"ConditioningSetMask",
"ConditioningSetTimestepRange",
"ConditioningZeroOut",
"ControlNetApply",
"ControlNetApplyAdvanced",
"ControlNetLoader",
"CropMask",
"DiffControlNetLoader",
"DiffusersLoader",
"DualCLIPLoader",
"EmptyImage",
"EmptyLatentImage",
"ExponentialScheduler",
"FeatherMask",
"FlipSigmas",
"FreeU",
"FreeU_V2",
"GLIGENLoader",
"GLIGENTextBoxApply",
"GrowMask",
"HyperTile",
"HypernetworkLoader",
"ImageBatch",
"ImageBlend",
"ImageBlur",
"ImageColorToMask",
"ImageCompositeMasked",
"ImageCrop",
"ImageInvert",
"ImageOnlyCheckpointLoader",
"ImagePadForOutpaint",
"ImageQuantize",
"ImageScale",
"ImageScaleBy",
"ImageScaleToTotalPixels",
"ImageSharpen",
"ImageToMask",
"ImageUpscaleWithModel",
"InvertMask",
"JoinImageWithAlpha",
"KSampler",
"KSamplerAdvanced",
"KSamplerSelect",
"KarrasScheduler",
"LatentAdd",
"LatentBlend",
"LatentComposite",
"LatentCompositeMasked",
"LatentCrop",
"LatentFlip",
"LatentFromBatch",
"LatentInterpolate",
"LatentMultiply",
"LatentRotate",
"LatentSubtract",
"LatentUpscale",
"LatentUpscaleBy",
"LoadImage",
"LoadImageMask",
"LoadLatent",
"LoraLoader",
"LoraLoaderModelOnly",
"MaskComposite",
"MaskToImage",
"ModelMergeAdd",
"ModelMergeBlocks",
"ModelMergeSimple",
"ModelMergeSubtract",
"ModelSamplingContinuousEDM",
"ModelSamplingDiscrete",
"PatchModelAddDownscale",
"PolyexponentialScheduler",
"PorterDuffImageComposite",
"PreviewImage",
"RebatchLatents",
"RepeatImageBatch",
"RepeatLatentBatch",
"RescaleCFG",
"SVD_img2vid_Conditioning",
"SamplerCustom",
"SamplerDPMPP_2M_SDE",
"SamplerDPMPP_SDE",
"SaveAnimatedPNG",
"SaveAnimatedWEBP",
"SaveImage",
"SaveLatent",
"SetLatentNoiseMask",
"SolidMask",
"SplitImageWithAlpha",
"SplitSigmas",
"StyleModelApply",
"StyleModelLoader",
"TomePatchModel",
"UNETLoader",
"UpscaleModelLoader",
"VAEDecode",
"VAEDecodeTiled",
"VAEEncode",
"VAEEncodeForInpaint",
"VAEEncodeTiled",
"VAELoader",
"VAESave",
"VPScheduler",
"VideoLinearCFGGuidance",
"unCLIPCheckpointLoader",
"unCLIPConditioning"
],
{
"title_aux": "ComfyUI"
}
],
"https://github.com/comfyanonymous/ComfyUI_experiments": [
[
"ModelMergeBlockNumber",
@ -4274,6 +4406,7 @@
[
"Auto Merge Block Weighted",
"CLIPMergeSimple",
"CheckpointSave",
"ModelMergeBlocks",
"ModelMergeSimple"
],

37
prestartup_script.py

@ -9,6 +9,7 @@ import locale
message_collapses = []
import_failed_extensions = set()
def register_message_collapse(f):
@ -16,10 +17,16 @@ def register_message_collapse(f):
message_collapses.append(f)
def is_import_failed_extension(x):
global import_failed_extensions
return x in import_failed_extensions
sys.__comfyui_manager_register_message_collapse = register_message_collapse
sys.__comfyui_manager_is_import_failed_extension = is_import_failed_extension
comfyui_manager_path = os.path.dirname(__file__)
custom_nodes_path = os.path.join(comfyui_manager_path, "..")
custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, ".."))
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts")
restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json")
git_script_path = os.path.join(comfyui_manager_path, "git_helper.py")
@ -78,7 +85,12 @@ try:
original_stdout = sys.stdout
original_stderr = sys.stderr
tqdm = r'\d+%.*\[(.*?)\]'
pat_tqdm = r'\d+%.*\[(.*?)\]'
pat_import_fail = r'seconds \(IMPORT FAILED\):'
pat_custom_node = r'[/\\]custom_nodes[/\\](.*)$'
is_start_mode = True
is_import_fail_mode = False
log_file = open(f"comfyui{postfix}.log", "w", encoding="utf-8")
log_lock = threading.Lock()
@ -99,11 +111,30 @@ try:
raise ValueError("The object does not have a fileno method")
def write(self, message):
global is_start_mode
global is_import_fail_mode
if any(f(message) for f in message_collapses):
return
if is_start_mode:
if is_import_fail_mode:
match = re.search(pat_custom_node, message)
if match:
import_failed_extensions.add(match.group(1))
is_import_fail_mode = False
else:
match = re.search(pat_import_fail, message)
if match:
is_import_fail_mode = True
else:
is_import_fail_mode = False
if 'Starting server' in message:
is_start_mode = False
if not self.is_stdout:
match = re.search(tqdm, message)
match = re.search(pat_tqdm, message)
if match:
message = re.sub(r'([#|])\d', r'\1▌', message)
message = re.sub('#', '', message)

28
scanner.py

@ -5,9 +5,12 @@ from git import Repo
from torchvision.datasets.utils import download_url
import concurrent
builtin_nodes = ["KSampler", "CheckpointSave"]
builtin_nodes = set()
def scan_in_file(filename, is_builtin=False):
global builtin_nodes
def scan_in_file(filename):
try:
with open(filename, encoding='utf-8') as file:
code = file.read()
@ -63,9 +66,12 @@ def scan_in_file(filename):
key, value = line[1:].strip().split(':')
metadata[key.strip()] = value.strip()
for x in builtin_nodes:
if x in nodes:
nodes.remove(x)
if is_builtin:
builtin_nodes += set(nodes)
else:
for x in builtin_nodes:
if x in nodes:
nodes.remove(x)
return nodes, metadata
@ -113,7 +119,9 @@ def get_git_urls_from_json(json_file):
if node.get('install_type') == 'git-clone':
files = node.get('files', [])
if files:
git_clone_files.append((files[0],node.get('title')))
git_clone_files.append((files[0], node.get('title')))
git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI"))
return git_clone_files
@ -190,7 +198,7 @@ def update_custom_nodes():
with concurrent.futures.ThreadPoolExecutor(10) as executor:
executor.map(download_and_store_info, py_url_titles)
return node_info
@ -198,6 +206,10 @@ def gen_json(node_info):
# scan from .py file
node_files, node_dirs = get_nodes(".tmp")
comfyui_path = os.path.abspath(os.path.join('.tmp', "ComfyUI"))
node_dirs.remove(comfyui_path)
node_dirs = [comfyui_path] + node_dirs
data = {}
for dirname in node_dirs:
py_files = get_py_file_paths(dirname)
@ -205,7 +217,7 @@ def gen_json(node_info):
nodes = set()
for py in py_files:
nodes_in_file, metadata_in_file = scan_in_file(py)
nodes_in_file, metadata_in_file = scan_in_file(py, dirname == "ComfyUI")
nodes.update(nodes_in_file)
metadata.update(metadata_in_file)

Loading…
Cancel
Save