controlnet_downloader.py =

# controlnet_models_downloader.py
import os
import urllib.parse
import ipywidgets as widgets
from IPython.display import display
import requests
from tqdm import tqdm

# Fetch the JSON file from the GitHub repository
json_url = "https://raw.githubusercontent.com/gokuldaskumar/controlnet-links/main/controlnet_models.json"
response = requests.get(json_url)
models_data = response.json()

sd15_models = models_data["sd15_models"]
xl_models = models_data["xl_models"]

# Create checkboxes for each model (excluding IC light)
sd15_checkboxes = [widgets.Checkbox(value=False, description=key) for key in sd15_models.keys() if key != "IC light"]
xl_checkboxes = [widgets.Checkbox(value=False, description=key) for key in xl_models.keys()]

# "Select All" checkboxes
select_all_sd15 = widgets.Checkbox(description="Select All SD15", value=False)
select_all_xl = widgets.Checkbox(description="Select All XL", value=False)

# Function to update the selection state of all checkboxes based on "Select All" state
def update_selection(checkboxes, select_all_checkbox):
    for cb in checkboxes:
        cb.value = select_all_checkbox.value

# Attach the update_selection function to the "Select All" checkboxes
def attach_select_all(select_all_checkbox, checkboxes):
    def on_select_all_change(change):
        update_selection(checkboxes, select_all_checkbox)
    select_all_checkbox.observe(on_select_all_change, names='value')

attach_select_all(select_all_sd15, sd15_checkboxes)
attach_select_all(select_all_xl, xl_checkboxes)

# Function to display checkboxes for selected model type
checkbox_container = widgets.VBox(children=[])
def display_checkboxes(model_type):
    if model_type == 'sd15':
        checkbox_container.children = [select_all_sd15] + sd15_checkboxes
    elif model_type == 'xl':
        checkbox_container.children = [select_all_xl] + xl_checkboxes

# Create buttons for selecting model type
sd15_button = widgets.Button(description="SD15 Models")
xl_button = widgets.Button(description="XL Models")

# Button click events
sd15_button.on_click(lambda b: display_checkboxes('sd15'))
xl_button.on_click(lambda b: display_checkboxes('xl'))

# Display buttons
buttons_container = widgets.HBox(children=[sd15_button, xl_button])
display(buttons_container)

# Initially empty container for checkboxes
display(checkbox_container)

# Function to download a file with progress bar
def download_file(url, filepath):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))
    chunk_size = 8192
    with open(filepath, 'wb') as f, tqdm(
        total=total_size,
        unit='B',
        unit_scale=True,
        desc=os.path.basename(filepath),
        initial=0,
        miniters=1
    ) as pbar:
        for chunk in response.iter_content(chunk_size=chunk_size):
            f.write(chunk)
            pbar.update(len(chunk))

# Function to download selected models
def download_models(b):
    primary_directory = os.path.expanduser("~/stable-diffusion-webui-forge/models/ControlNet")
    secondary_directory = os.path.expanduser("~/stable-diffusion-webui/extensions/sd-webui-controlnet/models")

    unet_primary_directory = os.path.expanduser("~/stable-diffusion-webui-forge/models/unet")
    unet_secondary_directory = os.path.expanduser("~/stable-diffusion-webui/models/unet")

    # Check for primary directories first
    target_directory = primary_directory if os.path.isdir(primary_directory) else secondary_directory
    unet_target_directory = unet_primary_directory if os.path.isdir(unet_primary_directory) else unet_secondary_directory

    os.makedirs(target_directory, exist_ok=True)
    os.makedirs(unet_target_directory, exist_ok=True)
    downloaded_files = []

    # Loop through SD15 and XL checkboxes
    for checkbox in sd15_checkboxes + xl_checkboxes:
        if checkbox.value:
            model_name = checkbox.description
            model_files = sd15_models.get(model_name) or xl_models.get(model_name)
            _download_models(model_name, model_files, target_directory, unet_target_directory, downloaded_files)

    # Handle "IC light" checkboxes
    if "IC light" in sd15_models:
        if ic_light_checkboxes.children[0].value:
            model_name = "IC light"
            model_files = sd15_models[model_name]["FC"]  # Directly access the list of URLs
            _download_models(model_name, model_files, target_directory, unet_target_directory, downloaded_files)
        if ic_light_checkboxes.children[1].value:
            model_name = "IC light"
            model_files = sd15_models[model_name]["FBC"] # Directly access the list of URLs
            _download_models(model_name, model_files, target_directory, unet_target_directory, downloaded_files)    

    if downloaded_files:
        print(f"\nDownload Complete. Models downloaded: {', '.join(downloaded_files)}")
    else:
        print("\nNo new models were downloaded.")

def _download_models(model_name, model_files, target_directory, unet_target_directory, downloaded_files):
    for url in model_files:
        if isinstance(url, list):
            url, filename = url
        else:
            filename = urllib.parse.unquote(url.split('/')[-1])

        # Determine the correct directory based on model_name (Corrected Logic)
        if model_name == "IC light":
            filepath = os.path.join(unet_target_directory, filename) 
        else:
            filepath = os.path.join(target_directory, filename)

        if not os.path.isfile(filepath):
            print(f"Downloading {filename} into {filepath}...")
            download_file(url, filepath)
            downloaded_files.append(filename)
        else:
            print(f"File {filename} already exists. Skipping download.")


# Create a button to start the download
download_button = widgets.Button(description="Download Selected Models")
download_button.on_click(download_models)
display(download_button)

# Create checkboxes for "IC light" models within their own group
ic_light_checkboxes = widgets.VBox(children=[
    widgets.Checkbox(value=False, description="FC"),
    widgets.Checkbox(value=False, description="FBC")
])

# Create button for "IC light"
ic_light_button = widgets.Button(description="IC light")

# Function to display checkboxes for "IC light"
def display_ic_light_checkboxes(b):
    checkbox_container.children = [ic_light_checkboxes]

# Attach the display function to the "IC light" button
ic_light_button.on_click(display_ic_light_checkboxes)

# Add the "IC light" button to the buttons container
buttons_container.children = buttons_container.children + (ic_light_button,)


------

controlnet_model.json = 

{
  "sd15_models": {
    "ControlNet++ Canny": [
      "https://huggingface.co/huchenlei/ControlNet_plus_plus_collection_fp16/resolve/main/controlnet%2B%2B_canny_sd15_fp16.safetensors"
    ],
    "ControlNet++ Depth": [
      "https://huggingface.co/huchenlei/ControlNet_plus_plus_collection_fp16/resolve/main/controlnet%2B%2B_depth_sd15_fp16.safetensors"
    ],
    "ControlNet-v1-1 Inpaint": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15_inpaint_fp16.yaml"
    ],
    "ControlNet++ Lineart": [
      "https://huggingface.co/huchenlei/ControlNet_plus_plus_collection_fp16/resolve/main/controlnet%2B%2B_lineart_sd15_fp16.safetensors"
    ],
    "ControlNet-v1-1 NormalBae": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15_normalbae_fp16.yaml"
    ],
    "ControlNet-v1-1 Openpose": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15_openpose_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15_openpose_fp16.yaml"
    ],
    "ControlNet-v1-1 Tile": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11f1e_sd15_tile_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11f1e_sd15_tile_fp16.yaml"
    ],
    "ControlNet-v1-1 ip2p": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11e_sd15_ip2p_fp16.yaml"
    ],
    "ControlNet-v1-1 shuffle": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11e_sd15_shuffle_fp16.yaml"
    ],
    "ControlNet-v1-1 mlsd": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15_mlsd_fp16.yaml"
    ],
    "ControlNet-v1-1 scribble": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15_scribble_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15_scribble_fp16.yaml"
    ],
    "ControlNet++ segment": [
      "https://huggingface.co/huchenlei/ControlNet_plus_plus_collection_fp16/resolve/main/controlnet%2B%2B_seg_sd15_fp16.safetensors"
    ],
    "ControlNet++ softedge": [
      "https://huggingface.co/huchenlei/ControlNet_plus_plus_collection_fp16/resolve/main/controlnet%2B%2B_hed_softedge_sd15_fp16.safetensors"
    ],
    "ControlNet-v1-1 lineart anime": [
      "https://huggingface.co/ckpt/ControlNet-v1-1/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors",
      "https://huggingface.co/ckpt/ControlNet-v1-1/raw/main/control_v11p_sd15s2_lineart_anime_fp16.yaml"
    ],
    "ControlNet-v1-1 depth anything": [
      ["https://huggingface.co/spaces/LiheYoung/Depth-Anything/resolve/main/checkpoints_controlnet/diffusion_pytorch_model.safetensors", "control_sd15_depth_anything.safetensors"]
    ],
    "IP-Adapter Full Face": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-full-face_sd15.safetensors"
    ],
    "IP-Adapter Plus Face": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus-face_sd15.safetensors"
    ],
    "IP-Adapter Plus": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus_sd15.safetensors"
    ],
    "IP-Adapter": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors"
    ],
    "ControlNet HandRefiner Inpaint Depth": [
      "https://huggingface.co/hr16/ControlNet-HandRefiner-pruned/resolve/main/control_sd15_inpaint_depth_hand_fp16.safetensors"
    ],
    "IP-Adapter FaceID Plus": [
      "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15.bin"
    ],
    "IP-Adapter FaceID Plus V2": [
      "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15.bin"
    ],
    "IP-Adapter FaceID Portrait": [
      "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sd15.bin"
    ],
    "IC light": {
      "FC": [
        "https://huggingface.co/huchenlei/IC-Light-ldm/resolve/main/iclight_sd15_fc_unet_ldm.safetensors"
      ],
      "FBC": [
        "https://huggingface.co/huchenlei/IC-Light-ldm/resolve/main/iclight_sd15_fbc_unet_ldm.safetensors"
      ]
    }
  },
  "xl_models": {
    "SAI XL Canny": [
      "https://huggingface.co/lllyasviel/sd_control_collection/resolve/main/sai_xl_canny_256lora.safetensors"
    ],
    "SAI XL Depth": [
      "https://huggingface.co/lllyasviel/sd_control_collection/resolve/main/sai_xl_depth_256lora.safetensors"
    ],
    "Xinsir XL OpenPose": [
      ["https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", "xinsir_xl_openpose.safetensors"],
      ["https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model_twins.safetensors", "xinsir_xl_openpose_twins.safetensors"]
    ],
    "Xinsir XL Canny": [
      ["https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0/resolve/main/diffusion_pytorch_model_V2.safetensors", "xinsir_xl_canny.safetensors"]
    ],
    "Xinsir XL Scribble": [
      ["https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors", "xinsir_xl_scribble.safetensors"]
    ],
    "XL Tile": [
      "https://huggingface.co/bdsqlsz/qinglong_controlnet-lllite/resolve/main/bdsqlsz_controlllite_xl_tile_realistic.safetensors"
    ],
    "MistoLine": [
      ["https://huggingface.co/TheMistoAI/MistoLine/resolve/main/mistoLine_rank256.safetensors", "mistoLine_softedge_sdxl_fp16.safetensors"]
    ],
    "IP-Adapter Plus SDXL": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors"
    ],
    "IP-Adapter Plus Face SDXL": [
      "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors"
    ],
    "IP-Adapter FaceID Plus V2 SDXL": [
      "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl.bin"
    ],
    "Instant ID SDXL": [
      ["https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin", "ip-adapter_instant_id_sdxl.bin"],
      ["https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors", "control_instant_id_sdxl.safetensors"]
    ]
  }
}

-----------------
when i execute the controlnet_downloader.py file in jupyter notebook using this code "%run controlnet_downloader.py". it shows this error "No new models were downloaded.". i verified that no model already exist in folder. please fix the issue