File size: 6,009 Bytes
360f573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import json, os
OI = json.load(open("/tmp/oi.json", encoding="utf-8"))
OUT = "/workspace/pack_jsons"
os.makedirs(OUT, exist_ok=True)

# pack class -> OFM brand title
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 = []        # (name, default) -> widgets_values
    link_inputs = []    # (name, type) -> input slots needing wiring
    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))
            # unknown custom types -> skip (rare)
    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
    # LoadImage for each IMAGE input
    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]})
    # sink per IMAGE/STRING output
    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
    # note
    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)