chore: auto-commit (61 archivos)
- docs/capabilities/INDEX.md - docs/capabilities/comfyui.md - python/functions/browser/comfyui_export_workflow_ui.md - python/functions/browser/comfyui_export_workflow_ui.py - python/functions/browser/comfyui_load_workflow_ui.md - python/functions/browser/comfyui_load_workflow_ui.py - python/functions/browser/comfyui_queue_prompt_ui.md - python/functions/browser/comfyui_queue_prompt_ui.py - python/functions/browser/comfyui_refresh_nodes_ui.md - python/functions/browser/comfyui_refresh_nodes_ui.py - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""Busca modelos / LoRAs en Civitai via su API publica GET /api/v1/models.
|
||||
|
||||
Normaliza cada resultado a un dict pequeno y reutilizable
|
||||
({name, type, base_model, version_id, download_url, nsfw}) tomando la primera
|
||||
version del modelo. La busqueda publica funciona sin token; pasar un token solo
|
||||
sube el rate limit y desbloquea modelos restringidos.
|
||||
|
||||
Impura: red (HTTP GET a civitai.com). Solo stdlib (urllib, json).
|
||||
"""
|
||||
import json
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
_API = "https://civitai.com/api/v1/models"
|
||||
_TIMEOUT = 30.0
|
||||
|
||||
|
||||
def comfyui_search_civitai_models(
|
||||
query: str,
|
||||
*,
|
||||
types: str = "Checkpoint",
|
||||
base_model: str | None = None,
|
||||
sort: str = "Highest Rated",
|
||||
limit: int = 20,
|
||||
token: str | None = None,
|
||||
) -> dict:
|
||||
"""Busca modelos en Civitai y devuelve resultados normalizados.
|
||||
|
||||
Args:
|
||||
query: texto de busqueda (nombre del modelo, ej. "dreamshaper").
|
||||
types: tipo(s) de modelo, CSV. Valores Civitai: Checkpoint, LORA,
|
||||
TextualInversion, Controlnet, VAE, Upscaler, ... keyword-only.
|
||||
base_model: filtra por modelo base (ej. "SD 1.5", "SDXL 1.0"). None no
|
||||
filtra. keyword-only.
|
||||
sort: orden Civitai ("Highest Rated", "Most Downloaded", "Newest").
|
||||
keyword-only.
|
||||
limit: numero maximo de resultados (1-100). keyword-only.
|
||||
token: API token de Civitai (header Authorization Bearer). Opcional: la
|
||||
busqueda publica funciona sin el. No hardcodear: pasar desde
|
||||
pass/vault. keyword-only.
|
||||
|
||||
Returns:
|
||||
dict {ok, items, count, error}. items es una lista de
|
||||
{name, type, base_model, version_id, download_url, nsfw} (la primera
|
||||
version de cada modelo). ok=False con error si la peticion falla; una
|
||||
busqueda sin resultados devuelve ok=True con items=[] (no es error).
|
||||
"""
|
||||
params = [
|
||||
("query", query),
|
||||
("limit", str(max(1, min(int(limit), 100)))),
|
||||
("sort", sort),
|
||||
]
|
||||
for t in str(types).split(","):
|
||||
t = t.strip()
|
||||
if t:
|
||||
params.append(("types", t))
|
||||
if base_model:
|
||||
for bm in (base_model if isinstance(base_model, (list, tuple)) else [base_model]):
|
||||
params.append(("baseModels", str(bm)))
|
||||
|
||||
url = f"{_API}?{urllib.parse.urlencode(params)}"
|
||||
headers = {"User-Agent": "fn-registry/comfyui_search_civitai_models"}
|
||||
if token:
|
||||
headers["Authorization"] = f"Bearer {token}"
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:
|
||||
data = json.loads(resp.read())
|
||||
except urllib.error.HTTPError as exc:
|
||||
body = exc.read().decode(errors="replace")[:300]
|
||||
return {"ok": False, "items": [], "count": 0,
|
||||
"error": f"HTTP {exc.code} en {url}: {body}"}
|
||||
except urllib.error.URLError as exc:
|
||||
return {"ok": False, "items": [], "count": 0,
|
||||
"error": f"no se pudo conectar a civitai.com: {exc.reason}"}
|
||||
except json.JSONDecodeError as exc:
|
||||
return {"ok": False, "items": [], "count": 0,
|
||||
"error": f"respuesta no es JSON valido: {exc}"}
|
||||
|
||||
items = []
|
||||
for model in data.get("items", []) or []:
|
||||
versions = model.get("modelVersions") or []
|
||||
v0 = versions[0] if versions else {}
|
||||
items.append({
|
||||
"name": model.get("name"),
|
||||
"type": model.get("type"),
|
||||
"base_model": v0.get("baseModel"),
|
||||
"version_id": v0.get("id"),
|
||||
"download_url": v0.get("downloadUrl"),
|
||||
"nsfw": bool(model.get("nsfw", False)),
|
||||
})
|
||||
return {"ok": True, "items": items, "count": len(items), "error": ""}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
out = comfyui_search_civitai_models("dreamshaper", limit=5)
|
||||
print(out["ok"], out["count"])
|
||||
for it in out["items"]:
|
||||
print(f" {it['name']} [{it['base_model']}] v{it['version_id']} -> {it['download_url']}")
|
||||
Reference in New Issue
Block a user