| import json, os |
| OI = json.load(open("/tmp/oi.json", encoding="utf-8")) |
| OUT = "/workspace/pack_jsons" |
| os.makedirs(OUT, exist_ok=True) |
|
|
| |
| PACK = { |
| "NanoBananaAIO": "OFM Image and Video Edit AIO", |
| "GeminiPromptNode": "OFM Prompt Generator", |
| "PromptSelectorNodeMonthly": "OFM Prompt Selector", |
| "SeedreamNode": "OFM Seedream Edit", |
| "DirectoryImageLoaderNode": "OFM Directory Image Loader", |
| "LoadAPIKeysNode": "OFM Load API Keys", |
| "VideoFrameExtractorNode": "OFM Video Frame Extractor", |
| "MetadataRemoveNodeMonthly": "OFM Remove Metadata", |
| "SaveAsPhonePhotoNodeMonthly": "OFM Save as Phone Photo", |
| "LoraCaptionGeneratorNode": "OFM Lora Caption Generator", |
| "AiorBustVideoLoader": "OFM Video Loader", |
| "Aiorbust_Renoise": "OFM Renoise", |
| "Aiorbust_Camera_Look": "OFM Camera Look", |
| "Aiorbust_Apply_LUT": "OFM Apply LUT", |
| } |
| LINK_T = {"IMAGE", "MASK", "LATENT", "CONDITIONING", "MODEL", "VAE", "CLIP", "AUDIO"} |
|
|
| def schema(t): |
| info = OI.get(t) |
| if not info: |
| return None |
| inp = info.get("input", {}) |
| widgets = [] |
| link_inputs = [] |
| for sec in ("required", "optional"): |
| for name, spec in inp.get(sec, {}).items(): |
| tp = spec[0] |
| o = spec[1] if len(spec) > 1 and isinstance(spec[1], dict) else {} |
| if isinstance(tp, list): |
| widgets.append((name, tp[0] if tp else "")) |
| elif tp == "STRING": |
| widgets.append((name, o.get("default", ""))) |
| elif tp == "INT": |
| widgets.append((name, o.get("default", 0))) |
| elif tp == "FLOAT": |
| widgets.append((name, o.get("default", 0.0))) |
| elif tp == "BOOLEAN": |
| widgets.append((name, o.get("default", False))) |
| elif tp in LINK_T: |
| link_inputs.append((name, tp)) |
| |
| onames = info.get("output_name") or info.get("output", []) |
| otypes = info.get("output", []) |
| outs = list(zip(onames, otypes)) |
| return widgets, link_inputs, outs |
|
|
| def build(t, title): |
| s = schema(t) |
| if not s: |
| return None |
| widgets, link_inputs, outs = s |
| nodes, links = [], [] |
| nid, lid = 1, 1 |
| |
| src = {} |
| y = 60 |
| for (iname, itype) in link_inputs: |
| if itype == "IMAGE": |
| nodes.append({"id": nid, "type": "LoadImage", "pos": [60, y], "size": [300, 314], "flags": {}, |
| "order": len(nodes), "mode": 0, "inputs": [], |
| "outputs": [{"name": "IMAGE", "type": "IMAGE", "links": [lid], "slot_index": 0}, |
| {"name": "MASK", "type": "MASK", "links": None}], |
| "properties": {"Node name for S&R": "LoadImage"}, "widgets_values": ["example.png", "image"]}) |
| src[iname] = (nid, 0, lid); lid += 1; nid += 1; y += 360 |
| main_id = nid; nid += 1 |
| main_inputs = [] |
| for slot, (iname, itype) in enumerate(link_inputs): |
| if iname in src: |
| snid, sslot, l = src[iname] |
| main_inputs.append({"name": iname, "type": itype, "link": l}) |
| links.append([l, snid, sslot, main_id, slot, itype]) |
| else: |
| main_inputs.append({"name": iname, "type": itype, "link": None}) |
| main_outputs = [] |
| out_link = {} |
| for oslot, (oname, otype) in enumerate(outs): |
| l = None |
| if otype in ("IMAGE", "STRING"): |
| l = lid; out_link[oslot] = (l, otype, oname); lid += 1 |
| main_outputs.append({"name": oname, "type": otype, "links": [l] if l else None, "slot_index": oslot}) |
| nodes.append({"id": main_id, "type": t, "title": title, "pos": [460, 120], "size": [400, 340], "flags": {}, |
| "order": len(nodes), "mode": 0, "inputs": main_inputs, "outputs": main_outputs, |
| "properties": {"Node name for S&R": t}, "widgets_values": [w[1] for w in widgets]}) |
| |
| y2 = 120 |
| for oslot, (l, otype, oname) in out_link.items(): |
| if otype == "IMAGE": |
| nodes.append({"id": nid, "type": "SaveImage", "pos": [920, y2], "size": [320, 300], "flags": {}, |
| "order": len(nodes), "mode": 0, "inputs": [{"name": "images", "type": "IMAGE", "link": l}], |
| "outputs": [], "properties": {}, "widgets_values": ["OFM_" + t]}) |
| links.append([l, main_id, oslot, nid, 0, "IMAGE"]); nid += 1; y2 += 340 |
| elif otype == "STRING": |
| nodes.append({"id": nid, "type": "ShowText|pysssss", "title": "OFM — текст", "pos": [920, y2], |
| "size": [380, 200], "flags": {}, "order": len(nodes), "mode": 0, |
| "inputs": [{"name": "text", "type": "STRING", "link": l, "widget": {"name": "text"}}], |
| "outputs": [{"name": "STRING", "type": "STRING", "links": None, "shape": 6}], |
| "properties": {"Node name for S&R": "ShowText|pysssss"}, "widgets_values": [""]}) |
| links.append([l, main_id, oslot, nid, 0, "STRING"]); nid += 1; y2 += 240 |
| |
| nodes.append({"id": nid, "type": "Note", "title": title, "pos": [60, 10], "size": [560, 90], "flags": {}, |
| "order": len(nodes), "mode": 0, "inputs": [], "outputs": [], "properties": {}, |
| "widgets_values": [title + " — впиши API-ключ в ноде и Queue. Облачные ноды GPU не требуют."]}) |
| return {"last_node_id": nid, "last_link_id": lid - 1, "nodes": nodes, "links": links, |
| "groups": [], "config": {}, "extra": {}, "version": 0.4} |
|
|
| done = [] |
| for t, title in PACK.items(): |
| g = build(t, title) |
| if g: |
| fn = f"{OUT}/OFM_{t}.json" |
| json.dump(g, open(fn, "w", encoding="utf-8"), ensure_ascii=False, indent=1) |
| done.append(t) |
| print("BUILT", t, "nodes=" + str(len(g["nodes"])), flush=True) |
| else: |
| print("SKIP (not loaded)", t, flush=True) |
| print(f"GRAPHS_DONE {len(done)}/{len(PACK)}", flush=True) |
|
|