from IPython.display import display, Image, clear_output
from IPython import get_ipython
from ipywidgets import widgets
from pathlib import Path
import subprocess
import argparse
import shlex
import json
import sys
import os
import re
SyS = get_ipython().system
CD = os.chdir
iRON = os.environ
REPO = {
'A1111': 'https://github.com/gutris1/A1111',
'Forge': 'https://github.com/lllyasviel/stable-diffusion-webui-forge Forge',
'ReForge': '-b main-old https://github.com/Panchovix/stable-diffusion-webui-reForge ReForge',
'Forge-Classic': 'https://github.com/Haoming02/sd-webui-forge-classic Forge-Classic',
'Forge-Neo': '-b neo https://github.com/Haoming02/sd-webui-forge-classic Forge-Neo',
'ComfyUI': 'https://github.com/comfyanonymous/ComfyUI',
'SwarmUI': 'https://github.com/mcmonkeyprojects/SwarmUI'
}
WEBUI_LIST = ['A1111', 'Forge', 'ReForge', 'Forge-Classic', 'Forge-Neo', 'ComfyUI', 'SwarmUI']
def getENV():
env = {
'Colab': ('/content', '/content', 'COLAB_JUPYTER_TOKEN'),
'Kaggle': ('/kaggle', '/kaggle/working', 'KAGGLE_DATA_PROXY_TOKEN')
}
for name, (base, home, var) in env.items():
if var in iRON:
return name, base, home
return None, None, None
def getArgs():
parser = argparse.ArgumentParser(description='WebUI Installer Script for Kaggle and Google Colab')
parser.add_argument('--webui', required=True, help='available webui: A1111, Forge, ReForge, Forge-Classic, Forge-Neo, ComfyUI, SwarmUI')
parser.add_argument('--civitai_key', required=True, help='your CivitAI API key')
parser.add_argument('--hf_read_token', default=None, help='your Huggingface READ Token (optional)')
args, unknown = parser.parse_known_args()
arg1 = args.webui.lower()
arg2 = args.civitai_key.strip()
arg3 = args.hf_read_token.strip() if args.hf_read_token else ''
if not any(arg1 == option.lower() for option in WEBUI_LIST):
print(f'{ERROR}: invalid webui option: "{args.webui}"')
print(f'Available webui options: {", ".join(WEBUI_LIST)}')
return None, None, None
if not arg2:
print(f'{ERROR}: CivitAI API key is missing.')
return None, None, None
if re.search(r'\s+', arg2):
print(f'{ERROR}: CivitAI API key contains spaces "{arg2}" - not allowed.')
return None, None, None
if len(arg2) < 32:
print(f'{ERROR}: CivitAI API key must be at least 32 characters long.')
return None, None, None
if not arg3: arg3 = ''
if re.search(r'\s+', arg3): arg3 = ''
selected_ui = next(option for option in WEBUI_LIST if arg1 == option.lower())
return selected_ui, arg2, arg3
def getPython():
hao = webui in ['Forge-Classic', 'Forge-Neo']
v = '3.11' if hao else '3.10'
BIN = str(PY / 'bin')
PKG = str(PY / f'lib/python{v}/site-packages')
tar = {
**dict.fromkeys(['ComfyUI', 'SwarmUI'], 'https://huggingface.co/gutris1/webui/resolve/main/env/KC-ComfyUI-SwarmUI-Python310-Torch260-cu124.tar.lz4'),
'Forge-Classic': 'https://huggingface.co/gutris1/webui/resolve/main/env/KC-FC-Python311-Torch260-cu124.tar.lz4',
'Forge-Neo': 'https://huggingface.co/gutris1/webui/resolve/main/env/KC-FN-Python311-Torch280-cu126.tar.lz4',
}
url = tar.get(webui, 'https://huggingface.co/gutris1/webui/resolve/main/env/KC-Python310-Torch260-cu124.tar.lz4')
fn = Path(url).name
CD(Path(ENVBASE).parent)
print(f"\n{ARROW} installing Python Portable {'3.11.13' if hao else '3.10.15'}")
SyS('sudo apt-get -qq -y install aria2 pv lz4 > /dev/null 2>&1')
aria = f'aria2c --console-log-level=error --stderr=true -c -x16 -s16 -k1M -j5 {url} -o {fn}'
p = subprocess.Popen(shlex.split(aria), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
p.wait()
SyS(f'pv {fn} | lz4 -d | tar -xf -')
Path(f'/{fn}').unlink()
sys.path.insert(0, PKG)
if BIN not in iRON['PATH']:
iRON['PATH'] = BIN + ':' + iRON['PATH']
if PKG not in iRON['PYTHONPATH']:
iRON['PYTHONPATH'] = PKG + ':' + iRON['PYTHONPATH']
if ENVNAME == 'Kaggle':
for cmd in [
'pip install ipywidgets jupyterlab_widgets --upgrade',
'rm -f /usr/lib/python3.10/sitecustomize.py'
]:
SyS(f'{cmd} > /dev/null 2>&1')
def marking(p, n, u):
t = p / n
v = {'ui': u, 'launch_args': '', 'tunnel': ''}
if not t.exists(): t.write_text(json.dumps(v, indent=4))
d = json.loads(t.read_text())
d.update(v)
t.write_text(json.dumps(d, indent=4))
def key_inject(C, H):
p = Path(nenen)
v = p.read_text()
v = v.replace("TOKET = ''", f"TOKET = '{C}'")
v = v.replace("TOBRUT = ''", f"TOBRUT = '{H}'")
p.write_text(v)
def install_tunnel():
SyS(f'wget -qO {USR}/cl https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64')
SyS(f'chmod +x {USR}/cl')
bins = {
'zrok': {
'bin': USR / 'zrok',
'url': 'https://github.com/openziti/zrok/releases/download/v1.0.6/zrok_1.0.6_linux_amd64.tar.gz'
},
'ngrok': {
'bin': USR / 'ngrok',
'url': 'https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz'
}
}
for n, b in bins.items():
if b['bin'].exists(): b['bin'].unlink()
url = b['url']
name = Path(url).name
SyS(f'wget -qO {name} {url}')
SyS(f'tar -xzf {name} -C {USR}')
SyS(f'rm -f {name}')
def sym_link(U, M):
configs = {
'A1111': {
'sym': [
f"rm -rf {M / 'Stable-diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'ControlNet'} {TMP}/*"
],
'links': [
(TMP / 'ckpt', M / 'Stable-diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'ControlNet')
]
},
'Forge': {
'sym': [
f"rm -rf {M / 'Stable-diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'ControlNet'}",
f"rm -rf {M / 'svd'} {M / 'z123'} {M / 'clip'} {M / 'clip_vision'} {M / 'diffusers'}",
f"rm -rf {M / 'diffusion_models'} {M / 'text_encoder'} {M / 'unet'} {TMP}/*"
],
'links': [
(TMP / 'ckpt', M / 'Stable-diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'ControlNet'),
(TMP / 'z123', M / 'z123'),
(TMP / 'svd', M / 'svd'),
(TMP / 'clip', M / 'clip'),
(TMP / 'clip_vision', M / 'clip_vision'),
(TMP / 'diffusers', M / 'diffusers'),
(TMP / 'diffusion_models', M / 'diffusion_models'),
(TMP / 'text_encoders', M / 'text_encoder'),
(TMP / 'unet', M / 'unet')
]
},
'ReForge': {
'sym': [
f"rm -rf {M / 'Stable-diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'ControlNet'}",
f"rm -rf {M / 'svd'} {M / 'z123'} {TMP}/*"
],
'links': [
(TMP / 'ckpt', M / 'Stable-diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'ControlNet'),
(TMP / 'z123', M / 'z123'),
(TMP / 'svd', M / 'svd')
]
},
'Forge-Classic': {
'sym': [
f"rm -rf {M / 'Stable-diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'ControlNet'}"
],
'links': [
(TMP / 'ckpt', M / 'Stable-diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'ControlNet')
]
},
'Forge-Neo': {
'sym': [
f"rm -rf {M / 'Stable-diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'ControlNet'}"
],
'links': [
(TMP / 'ckpt', M / 'Stable-diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'ControlNet')
]
},
'ComfyUI': {
'sym': [
f"rm -rf {M / 'checkpoints/tmp_ckpt'} {M / 'loras/tmp_lora'} {M / 'controlnet'}",
f"rm -rf {M / 'clip'} {M / 'clip_vision'} {M / 'diffusers'} {M / 'diffusion_models'}",
f"rm -rf {M / 'text_encoders'} {M / 'unet'} {TMP}/*"
],
'links': [
(TMP / 'ckpt', M / 'checkpoints/tmp_ckpt'),
(TMP / 'lora', M / 'loras/tmp_lora'),
(TMP / 'controlnet', M / 'controlnet'),
(TMP / 'clip', M / 'clip'),
(TMP / 'clip_vision', M / 'clip_vision'),
(TMP / 'diffusers', M / 'diffusers'),
(TMP / 'diffusion_models', M / 'diffusion_models'),
(TMP / 'text_encoders', M / 'text_encoders'),
(TMP / 'unet', M / 'unet')
]
},
'SwarmUI': {
'sym': [
f"rm -rf {M / 'Stable-Diffusion/tmp_ckpt'} {M / 'Lora/tmp_lora'} {M / 'controlnet'}",
f"rm -rf {M / 'clip'} {M / 'unet'} {TMP}/*"
],
'links': [
(TMP / 'ckpt', M / 'Stable-Diffusion/tmp_ckpt'),
(TMP / 'lora', M / 'Lora/tmp_lora'),
(TMP / 'controlnet', M / 'controlnet'),
(TMP / 'clip', M / 'clip'),
(TMP / 'unet', M / 'unet')
]
}
}
cfg = configs.get(U)
[SyS(f'{cmd}') for cmd in cfg['sym']]
if U not in ['ComfyUI', 'SwarmUI']: [(M / d).mkdir(parents=True, exist_ok=True) for d in ['Lora', 'ESRGAN']]
[SyS(f'ln -s {src} {tg}') for src, tg in cfg['links']]
def webui_req(U, W, M):
CD(W)
if U != 'SwarmUI':
pull(f'https://github.com/gutris1/segsmaker {U.lower()} {W}')
else:
M.mkdir(parents=True, exist_ok=True)
for sub in ['Stable-Diffusion', 'Lora', 'Embeddings', 'VAE', 'upscale_models']:
(M / sub).mkdir(parents=True, exist_ok=True)
download(f'https://dot.net/v1/dotnet-install.sh {W}')
dotnet = W / 'dotnet-install.sh'
dotnet.chmod(0o755)
SyS('bash ./dotnet-install.sh --channel 8.0')
sym_link(U, M)
install_tunnel()
scripts = [
f'https://github.com/gutris1/segsmaker/raw/main/script/controlnet.py {W}/asd',
f'https://github.com/gutris1/segsmaker/raw/main/script/KC/segsmaker.py {W}'
]
# Removed upscalers list and download loop
for item in scripts: download(item)
if U not in ['SwarmUI', 'ComfyUI']:
e = 'jpg' if U in ['Forge-Classic', 'Forge-Neo'] else 'png'
SyS(f'rm -f {W}/html/card-no-preview.{e}')
for ass in [
f'https://huggingface.co/gutris1/webui/resolve/main/misc/card-no-preview.png {W}/html card-no-preview.{e}',
f'https://github.com/gutris1/segsmaker/raw/main/config/NoCrypt_miku.json {W}/tmp/gradio_themes',
f'https://github.com/gutris1/segsmaker/raw/main/config/user.css {W} user.css'
]: download(ass)
if U not in ['Forge', 'Forge-Neo']: download(f'https://github.com/gutris1/segsmaker/raw/main/config/config.json {W} config.json')
def webui_extension(U, W, M):
EXT = W / 'custom_nodes' if U == 'ComfyUI' else W / 'extensions'
CD(EXT)
if U == 'ComfyUI':
say('
【{red} Installing Custom Nodes{d} 】{red}')
clone(str(W / 'asd/custom_nodes.txt'))
print()
# Removed face restore models (CodeFormer/GFPGAN) download loop
else:
say('
【{red} Installing Extensions{d} 】{red}')
clone(str(W / 'asd/extension.txt'))
if ENVNAME == 'Kaggle': clone('https://github.com/gutris1/sd-image-encryption')
def webui_installation(U, W):
M = W / 'Models' if U == 'SwarmUI' else W / 'models'
E = M / 'Embeddings' if U == 'SwarmUI' else (M / 'embeddings' if U in ['Forge-Classic', 'Forge-Neo', 'ComfyUI'] else W / 'embeddings')
V = M / 'vae' if U == 'ComfyUI' else M / 'VAE'
webui_req(U, W, M)
# Removed extras download (embeddingsXL, VAE) and unzip command
if U != 'SwarmUI': webui_extension(U, W, M)
def webui_selection(ui):
with output:
output.clear_output(wait=True)
if ui in REPO: (WEBUI, repo) = (HOME / ui, REPO[ui])
say(f'【{{red}} Installing {WEBUI.name}{{d}} 】{{red}}')
clone(repo)
webui_installation(ui, WEBUI)
with loading:
loading.clear_output(wait=True)
say('
【{red} Done{d} 】{red}')
tempe()
CD(HOME)
def webui_installer():
branchs = {
'A1111': 'master',
'ComfyUI': 'master',
'SwarmUI': 'master',
'Forge': 'main',
'ReForge': 'main',
'Forge-Classic': 'classic',
'Forge-Neo': 'neo',
}
CD(HOME)
ui = (json.load(MARKED.open('r')) if MARKED.exists() else {}).get('ui')
WEBUI = HOME / ui if ui else None
if WEBUI is not None and WEBUI.exists():
git_dir = WEBUI / '.git'
if git_dir.exists():
CD(WEBUI)
with output:
output.clear_output(wait=True)
if ui in branchs: SyS(f'git pull origin {branchs[ui]}')
with loading: loading.clear_output()
else:
try:
webui_selection(webui)
except KeyboardInterrupt:
with loading: loading.clear_output()
with output: print('\nCanceled.')
except Exception as e:
with loading: loading.clear_output()
with output: print(f'\n{ERROR}: {e}')
def notebook_scripts():
z = [
(STR / '00-startup.py', f'wget -qO {STR}/00-startup.py https://github.com/gutris1/segsmaker/raw/main/script/KC/00-startup.py'),
(nenen, f'wget -qO {nenen} https://github.com/gutris1/segsmaker/raw/main/script/nenen88.py'),
(melon, f'wget -qO {melon} https://github.com/gutris1/segsmaker/raw/main/script/melon00.py'),
(STR / 'cupang.py', f'wget -qO {STR}/cupang.py https://github.com/gutris1/segsmaker/raw/main/script/cupang.py'),
(MRK, f'wget -qO {MRK} https://github.com/gutris1/segsmaker/raw/main/script/marking.py')
]
[SyS(y) for x, y in z if not Path(x).exists()]
j = {'ENVNAME': ENVNAME, 'HOMEPATH': HOME, 'TEMPPATH': TMP, 'BASEPATH': Path(ENVBASE)}
text = '\n'.join(f"{k} = '{v}'" for k, v in j.items())
Path(KANDANG).write_text(text)
key_inject(civitai_key, hf_read_token)
marking(SRC, MARKED, webui)
sys.path.append(str(STR))
for scripts in [nenen, melon, KANDANG, MRK]: get_ipython().run_line_magic('run', str(scripts))
ENVNAME, ENVBASE, ENVHOME = getENV()
if not ENVNAME:
print('You are not in Kaggle or Google Colab.\nExiting.')
sys.exit()
RESET = '\033[0m'
RED = '\033[31m'
PURPLE = '\033[38;5;135m'
ORANGE = '\033[38;5;208m'
ARROW = f'{ORANGE}▶{RESET}'
ERROR = f'{PURPLE}[{RESET}{RED}ERROR{RESET}{PURPLE}]{RESET}'
IMG = 'https://github.com/gutris1/segsmaker/raw/main/script/loading.png'
HOME = Path(ENVHOME)
TMP = Path(ENVBASE) / 'temp'
PY = Path('/GUTRIS1')
SRC = HOME / 'gutris1'
MRK = SRC / 'marking.py'
KEY = SRC / 'api-key.json'
MARKED = SRC / 'marking.json'
USR = Path('/usr/bin')
STR = Path('/root/.ipython/profile_default/startup')
nenen = STR / 'nenen88.py'
melon = STR / 'melon00.py'
KANDANG = STR / 'KANDANG.py'
TMP.mkdir(parents=True, exist_ok=True)
SRC.mkdir(parents=True, exist_ok=True)
output = widgets.Output()
loading = widgets.Output()
webui, civitai_key, hf_read_token = getArgs()
if civitai_key is None: sys.exit()
display(output, loading)
with loading: display(Image(url=IMG))
with output: PY.exists() or getPython()
notebook_scripts()
from nenen88 import clone, say, download, tempe, pull
webui_installer()