Create backup: GLM Hub - Generar ícono con Gemini
This commit is contained in:
@@ -0,0 +1,960 @@
|
||||
{
|
||||
"updatedAt": "2026-07-29T18:48:09.844Z",
|
||||
"createdAt": "2026-07-28T16:18:07.824Z",
|
||||
"id": "F2rMlVS9mBypNNn7",
|
||||
"name": "GLM Hub - Generar ícono con Gemini",
|
||||
"description": null,
|
||||
"active": true,
|
||||
"isArchived": false,
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "glm-hub-generar-icono",
|
||||
"responseMode": "responseNode",
|
||||
"options": {
|
||||
"allowedOrigins": "*"
|
||||
}
|
||||
},
|
||||
"id": "e9002643-523d-436d-8c57-3d37f80f7ec3",
|
||||
"name": "Webhook - Generar ícono",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
-2992,
|
||||
464
|
||||
],
|
||||
"webhookId": "bc20a398-5ecf-42a2-9d17-9396aa278708"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const request = $input.first().json ?? {};\nconst rawBody = request.body ?? request;\nlet body = rawBody;\n\nif (typeof rawBody === 'string') {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n}\n\nconst headers = request.headers ?? {};\nconst headerAuthorization = String(headers.authorization ?? headers.Authorization ?? '').trim();\nconst accessToken = String(body.accessToken ?? '').trim();\nconst authorization = headerAuthorization.toLowerCase().startsWith('bearer ')\n ? headerAuthorization\n : accessToken\n ? `Bearer ${accessToken}`\n : '';\nconst name = String(body.name ?? '').trim();\nconst description = String(body.description ?? '').trim();\n\nlet error = '';\nif (!authorization.toLowerCase().startsWith('bearer ')) {\n error = 'La sesión de Supabase no fue enviada o no es válida.';\n} else if (name.length < 2 || name.length > 60) {\n error = 'El nombre debe contener entre 2 y 60 caracteres.';\n} else if (!description || description.length > 180) {\n error = 'La descripción debe contener entre 1 y 180 caracteres.';\n}\n\nreturn [{ json: { valid: !error, error, authorization, name, description } }];"
|
||||
},
|
||||
"id": "f7b0a22e-2651-4479-86c8-25262faa38c4",
|
||||
"name": "Validar solicitud",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-2736,
|
||||
464
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": "",
|
||||
"typeValidation": "strict",
|
||||
"version": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "308c498d-7c3f-4414-a21f-571276aee28b",
|
||||
"leftValue": "={{ $json.valid }}",
|
||||
"rightValue": true,
|
||||
"operator": {
|
||||
"type": "boolean",
|
||||
"operation": "true",
|
||||
"singleValue": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "0313d3ca-0439-4c2d-bd34-4da5ef6c3950",
|
||||
"name": "¿Solicitud válida?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-2512,
|
||||
464
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 400,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "bcfcc3ea-bbb3-4346-a5b4-1681d226a40c",
|
||||
"name": "Responder 400",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-2272,
|
||||
640
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "https://dbit.digitalcompass.agency/rest/v1/rpc/glm_hub_icon_generation_access",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "apikey",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"value": "={{ $('Validar solicitud').first().json.authorization }}"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "{}",
|
||||
"options": {
|
||||
"response": {
|
||||
"response": {
|
||||
"fullResponse": true,
|
||||
"neverError": true,
|
||||
"responseFormat": "json"
|
||||
}
|
||||
},
|
||||
"timeout": 30000
|
||||
}
|
||||
},
|
||||
"id": "bf1ac078-9362-445b-99d4-cd884ba5a8e1",
|
||||
"name": "Validar administrador en Supabase",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
-2272,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const source = $input.first()?.json ?? {};\nconst request = $('Validar solicitud').first().json ?? {};\n\nconst statusCode = Number(source.statusCode ?? 200);\n\nlet permission = source.body ?? source;\n\nif (typeof permission === 'string') {\n try {\n permission = JSON.parse(permission);\n } catch {\n permission = {};\n }\n}\n\nif (Array.isArray(permission)) {\n permission = permission[0] ?? {};\n}\n\nif (\n permission &&\n typeof permission === 'object' &&\n permission.authorized === undefined &&\n permission.body !== undefined\n) {\n permission = permission.body;\n\n if (typeof permission === 'string') {\n try {\n permission = JSON.parse(permission);\n } catch {\n permission = {};\n }\n }\n}\n\nconst authorized =\n statusCode >= 200 &&\n statusCode < 300 &&\n (\n permission?.authorized === true ||\n String(permission?.authorized ?? '').toLowerCase() === 'true'\n );\n\nlet error = '';\n\nif (statusCode === 401) {\n error =\n 'La sesión de Supabase expiró. Cierra sesión e inicia nuevamente.';\n} else if (statusCode === 403) {\n error =\n 'Supabase rechazó la validación administrativa.';\n} else if (statusCode >= 400) {\n error =\n String(permission?.message ?? permission?.error ?? '') ||\n `Supabase respondió con el código ${statusCode}.`;\n} else if (!authorized) {\n error =\n 'Tu sesión no tiene permisos de administrador para generar íconos.';\n}\n\nreturn [\n {\n json: {\n authorized,\n error,\n name: String(request.name ?? ''),\n description: String(request.description ?? ''),\n email: String(permission?.email ?? ''),\n userId: String(permission?.userId ?? ''),\n supabaseStatus: statusCode\n }\n }\n];"
|
||||
},
|
||||
"id": "0f6af309-436b-49df-8a1b-2120a0290474",
|
||||
"name": "Confirmar autorización",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-2048,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": "",
|
||||
"typeValidation": "strict",
|
||||
"version": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "c9275da4-0bca-4ce9-bd75-cc7d06e4cf56",
|
||||
"leftValue": "={{ $json.authorized }}",
|
||||
"rightValue": true,
|
||||
"operator": {
|
||||
"type": "boolean",
|
||||
"operation": "true",
|
||||
"singleValue": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "c115098c-9289-46ad-902b-d79aa8168bc0",
|
||||
"name": "¿Es administrador?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-1840,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 403,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "c44dee89-da47-43d0-9134-a723f80f7e39",
|
||||
"name": "Responder 403",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-1600,
|
||||
560
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const { name, description } = $input.first().json;\nconst prompt = `Crea un ícono cuadrado 1:1, profesional, minimalista y fácil de reconocer para una aplicación interna de GomezLee Marketing.\n\nNombre de la aplicación: ${name}\nDescripción funcional: ${description}\n\nRequisitos visuales obligatorios:\n- Representa la función principal con un único símbolo simple, claro y reconocible.\n- Estética corporativa moderna, limpia y tecnológica.\n- Paleta inspirada en GLM: azul grisáceo, verde claro y verde azulado.\n- Fondo blanco o transparente.\n- Composición centrada, con buen espacio de respiración.\n- Sin texto, sin letras, sin siglas, sin números, sin marcas comerciales y sin logotipos existentes.\n- Sin mockups, sin fotografías, sin personas, sin sombras exageradas y sin fondos complejos.\n- Debe seguir siendo legible al reducirse a 32 x 32 píxeles.\n- Entrega solamente el ícono final.`;\nreturn [{ json: { prompt } }];"
|
||||
},
|
||||
"id": "4a092f12-4966-4d3e-ba45-f82626f8aff8",
|
||||
"name": "Construir prompt del ícono",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-1600,
|
||||
272
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "image",
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"value": "models/gemini-3-pro-image",
|
||||
"mode": "list",
|
||||
"cachedResultName": "models/gemini-3-pro-image (Nano Banana Pro)"
|
||||
},
|
||||
"prompt": "={{ $json.prompt }}",
|
||||
"options": {
|
||||
"binaryPropertyOutput": "data"
|
||||
}
|
||||
},
|
||||
"id": "0daf0a06-a280-4500-95f6-f76b8945ed63",
|
||||
"name": "Generate an image",
|
||||
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
-1360,
|
||||
272
|
||||
],
|
||||
"credentials": {
|
||||
"googlePalmApi": {
|
||||
"id": "jvsXYwL6IOoY2DBU",
|
||||
"name": "Isaac - Gemini Api Pago"
|
||||
}
|
||||
},
|
||||
"onError": "continueErrorOutput"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "binary",
|
||||
"responseDataSource": "set",
|
||||
"options": {
|
||||
"responseCode": 200,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
},
|
||||
{
|
||||
"name": "Content-Disposition",
|
||||
"value": "inline; filename=\"glm-hub-icon.png\""
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "image/png"
|
||||
},
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "8594ec32-5d88-4435-aa8f-7d95d819eada",
|
||||
"name": "Responder con ícono",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-1072,
|
||||
192
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const input = $input.first().json ?? {};\nconst rawError = input.error ?? input.message ?? input.description ?? input;\nlet message = 'Gemini no pudo generar el ícono. Revisa la credencial, el modelo y la cuota disponible.';\n\nif (typeof rawError === 'string' && rawError.trim()) {\n message = rawError.trim();\n} else if (rawError && typeof rawError === 'object') {\n message = String(rawError.message ?? rawError.description ?? rawError.status ?? message);\n}\n\nreturn [{ json: { ok: false, error: message } }];"
|
||||
},
|
||||
"id": "ef98ab6b-3341-441b-83bc-41eabfe1d839",
|
||||
"name": "Preparar error de Gemini",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-1072,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 502,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "273ca42a-ef45-426d-a5c1-e4a3f9ea704d",
|
||||
"name": "Responder error de Gemini",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-832,
|
||||
384
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Webhook - Generar ícono": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Validar solicitud",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validar solicitud": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "¿Solicitud válida?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"¿Solicitud válida?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Validar administrador en Supabase",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Responder 400",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validar administrador en Supabase": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Confirmar autorización",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Confirmar autorización": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "¿Es administrador?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"¿Es administrador?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Construir prompt del ícono",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Responder 403",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Construir prompt del ícono": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Generate an image",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Generate an image": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Responder con ícono",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Preparar error de Gemini",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Preparar error de Gemini": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Responder error de Gemini",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1",
|
||||
"binaryMode": "separate",
|
||||
"availableInMCP": true
|
||||
},
|
||||
"staticData": null,
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true
|
||||
},
|
||||
"versionId": "ce03fd5f-2d70-44f1-b1e2-b31fc92ddf62",
|
||||
"activeVersionId": "ce03fd5f-2d70-44f1-b1e2-b31fc92ddf62",
|
||||
"versionCounter": 75,
|
||||
"triggerCount": 1,
|
||||
"shared": [
|
||||
{
|
||||
"updatedAt": "2026-07-28T16:18:07.831Z",
|
||||
"createdAt": "2026-07-28T16:18:07.831Z",
|
||||
"role": "workflow:owner",
|
||||
"workflowId": "F2rMlVS9mBypNNn7",
|
||||
"projectId": "PJpTANzTXIFibWsW",
|
||||
"project": {
|
||||
"updatedAt": "2026-04-22T14:25:09.686Z",
|
||||
"createdAt": "2026-04-22T14:22:54.790Z",
|
||||
"id": "PJpTANzTXIFibWsW",
|
||||
"name": "Isaac Aracena <iaracena@gomezleemarketing.com>",
|
||||
"type": "personal",
|
||||
"icon": null,
|
||||
"description": null,
|
||||
"creatorId": "0a88c0b1-928e-4412-896e-c5d1c99b2029"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"activeVersion": {
|
||||
"updatedAt": "2026-07-28T20:24:18.000Z",
|
||||
"createdAt": "2026-07-28T20:23:55.454Z",
|
||||
"versionId": "ce03fd5f-2d70-44f1-b1e2-b31fc92ddf62",
|
||||
"workflowId": "F2rMlVS9mBypNNn7",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "glm-hub-generar-icono",
|
||||
"responseMode": "responseNode",
|
||||
"options": {
|
||||
"allowedOrigins": "*"
|
||||
}
|
||||
},
|
||||
"id": "e9002643-523d-436d-8c57-3d37f80f7ec3",
|
||||
"name": "Webhook - Generar ícono",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
-2992,
|
||||
464
|
||||
],
|
||||
"webhookId": "bc20a398-5ecf-42a2-9d17-9396aa278708"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const request = $input.first().json ?? {};\nconst rawBody = request.body ?? request;\nlet body = rawBody;\n\nif (typeof rawBody === 'string') {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n}\n\nconst headers = request.headers ?? {};\nconst headerAuthorization = String(headers.authorization ?? headers.Authorization ?? '').trim();\nconst accessToken = String(body.accessToken ?? '').trim();\nconst authorization = headerAuthorization.toLowerCase().startsWith('bearer ')\n ? headerAuthorization\n : accessToken\n ? `Bearer ${accessToken}`\n : '';\nconst name = String(body.name ?? '').trim();\nconst description = String(body.description ?? '').trim();\n\nlet error = '';\nif (!authorization.toLowerCase().startsWith('bearer ')) {\n error = 'La sesión de Supabase no fue enviada o no es válida.';\n} else if (name.length < 2 || name.length > 60) {\n error = 'El nombre debe contener entre 2 y 60 caracteres.';\n} else if (!description || description.length > 180) {\n error = 'La descripción debe contener entre 1 y 180 caracteres.';\n}\n\nreturn [{ json: { valid: !error, error, authorization, name, description } }];"
|
||||
},
|
||||
"id": "f7b0a22e-2651-4479-86c8-25262faa38c4",
|
||||
"name": "Validar solicitud",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-2736,
|
||||
464
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": "",
|
||||
"typeValidation": "strict",
|
||||
"version": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "308c498d-7c3f-4414-a21f-571276aee28b",
|
||||
"leftValue": "={{ $json.valid }}",
|
||||
"rightValue": true,
|
||||
"operator": {
|
||||
"type": "boolean",
|
||||
"operation": "true",
|
||||
"singleValue": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "0313d3ca-0439-4c2d-bd34-4da5ef6c3950",
|
||||
"name": "¿Solicitud válida?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-2512,
|
||||
464
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 400,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "bcfcc3ea-bbb3-4346-a5b4-1681d226a40c",
|
||||
"name": "Responder 400",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-2272,
|
||||
640
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "https://dbit.digitalcompass.agency/rest/v1/rpc/glm_hub_icon_generation_access",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "apikey",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"value": "={{ $('Validar solicitud').first().json.authorization }}"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "{}",
|
||||
"options": {
|
||||
"response": {
|
||||
"response": {
|
||||
"fullResponse": true,
|
||||
"neverError": true,
|
||||
"responseFormat": "json"
|
||||
}
|
||||
},
|
||||
"timeout": 30000
|
||||
}
|
||||
},
|
||||
"id": "bf1ac078-9362-445b-99d4-cd884ba5a8e1",
|
||||
"name": "Validar administrador en Supabase",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
-2272,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const source = $input.first()?.json ?? {};\nconst request = $('Validar solicitud').first().json ?? {};\n\nconst statusCode = Number(source.statusCode ?? 200);\n\nlet permission = source.body ?? source;\n\nif (typeof permission === 'string') {\n try {\n permission = JSON.parse(permission);\n } catch {\n permission = {};\n }\n}\n\nif (Array.isArray(permission)) {\n permission = permission[0] ?? {};\n}\n\nif (\n permission &&\n typeof permission === 'object' &&\n permission.authorized === undefined &&\n permission.body !== undefined\n) {\n permission = permission.body;\n\n if (typeof permission === 'string') {\n try {\n permission = JSON.parse(permission);\n } catch {\n permission = {};\n }\n }\n}\n\nconst authorized =\n statusCode >= 200 &&\n statusCode < 300 &&\n (\n permission?.authorized === true ||\n String(permission?.authorized ?? '').toLowerCase() === 'true'\n );\n\nlet error = '';\n\nif (statusCode === 401) {\n error =\n 'La sesión de Supabase expiró. Cierra sesión e inicia nuevamente.';\n} else if (statusCode === 403) {\n error =\n 'Supabase rechazó la validación administrativa.';\n} else if (statusCode >= 400) {\n error =\n String(permission?.message ?? permission?.error ?? '') ||\n `Supabase respondió con el código ${statusCode}.`;\n} else if (!authorized) {\n error =\n 'Tu sesión no tiene permisos de administrador para generar íconos.';\n}\n\nreturn [\n {\n json: {\n authorized,\n error,\n name: String(request.name ?? ''),\n description: String(request.description ?? ''),\n email: String(permission?.email ?? ''),\n userId: String(permission?.userId ?? ''),\n supabaseStatus: statusCode\n }\n }\n];"
|
||||
},
|
||||
"id": "0f6af309-436b-49df-8a1b-2120a0290474",
|
||||
"name": "Confirmar autorización",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-2048,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": "",
|
||||
"typeValidation": "strict",
|
||||
"version": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "c9275da4-0bca-4ce9-bd75-cc7d06e4cf56",
|
||||
"leftValue": "={{ $json.authorized }}",
|
||||
"rightValue": true,
|
||||
"operator": {
|
||||
"type": "boolean",
|
||||
"operation": "true",
|
||||
"singleValue": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "c115098c-9289-46ad-902b-d79aa8168bc0",
|
||||
"name": "¿Es administrador?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-1840,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 403,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "c44dee89-da47-43d0-9134-a723f80f7e39",
|
||||
"name": "Responder 403",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-1600,
|
||||
560
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const { name, description } = $input.first().json;\nconst prompt = `Crea un ícono cuadrado 1:1, profesional, minimalista y fácil de reconocer para una aplicación interna de GomezLee Marketing.\n\nNombre de la aplicación: ${name}\nDescripción funcional: ${description}\n\nRequisitos visuales obligatorios:\n- Representa la función principal con un único símbolo simple, claro y reconocible.\n- Estética corporativa moderna, limpia y tecnológica.\n- Paleta inspirada en GLM: azul grisáceo, verde claro y verde azulado.\n- Fondo blanco o transparente.\n- Composición centrada, con buen espacio de respiración.\n- Sin texto, sin letras, sin siglas, sin números, sin marcas comerciales y sin logotipos existentes.\n- Sin mockups, sin fotografías, sin personas, sin sombras exageradas y sin fondos complejos.\n- Debe seguir siendo legible al reducirse a 32 x 32 píxeles.\n- Entrega solamente el ícono final.`;\nreturn [{ json: { prompt } }];"
|
||||
},
|
||||
"id": "4a092f12-4966-4d3e-ba45-f82626f8aff8",
|
||||
"name": "Construir prompt del ícono",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-1600,
|
||||
272
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "image",
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"value": "models/gemini-3-pro-image",
|
||||
"mode": "list",
|
||||
"cachedResultName": "models/gemini-3-pro-image (Nano Banana Pro)"
|
||||
},
|
||||
"prompt": "={{ $json.prompt }}",
|
||||
"options": {
|
||||
"binaryPropertyOutput": "data"
|
||||
}
|
||||
},
|
||||
"id": "0daf0a06-a280-4500-95f6-f76b8945ed63",
|
||||
"name": "Generate an image",
|
||||
"type": "@n8n/n8n-nodes-langchain.googleGemini",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
-1360,
|
||||
272
|
||||
],
|
||||
"credentials": {
|
||||
"googlePalmApi": {
|
||||
"id": "jvsXYwL6IOoY2DBU",
|
||||
"name": "Isaac - Gemini Api Pago"
|
||||
}
|
||||
},
|
||||
"onError": "continueErrorOutput"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "binary",
|
||||
"responseDataSource": "set",
|
||||
"options": {
|
||||
"responseCode": 200,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
},
|
||||
{
|
||||
"name": "Content-Disposition",
|
||||
"value": "inline; filename=\"glm-hub-icon.png\""
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "image/png"
|
||||
},
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "8594ec32-5d88-4435-aa8f-7d95d819eada",
|
||||
"name": "Responder con ícono",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-1072,
|
||||
192
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const input = $input.first().json ?? {};\nconst rawError = input.error ?? input.message ?? input.description ?? input;\nlet message = 'Gemini no pudo generar el ícono. Revisa la credencial, el modelo y la cuota disponible.';\n\nif (typeof rawError === 'string' && rawError.trim()) {\n message = rawError.trim();\n} else if (rawError && typeof rawError === 'object') {\n message = String(rawError.message ?? rawError.description ?? rawError.status ?? message);\n}\n\nreturn [{ json: { ok: false, error: message } }];"
|
||||
},
|
||||
"id": "ef98ab6b-3341-441b-83bc-41eabfe1d839",
|
||||
"name": "Preparar error de Gemini",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-1072,
|
||||
384
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { ok: false, error: $json.error } }}",
|
||||
"options": {
|
||||
"responseCode": 502,
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-store"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "273ca42a-ef45-426d-a5c1-e4a3f9ea704d",
|
||||
"name": "Responder error de Gemini",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.4,
|
||||
"position": [
|
||||
-832,
|
||||
384
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Webhook - Generar ícono": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Validar solicitud",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validar solicitud": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "¿Solicitud válida?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"¿Solicitud válida?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Validar administrador en Supabase",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Responder 400",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validar administrador en Supabase": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Confirmar autorización",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Confirmar autorización": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "¿Es administrador?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"¿Es administrador?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Construir prompt del ícono",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Responder 403",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Construir prompt del ícono": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Generate an image",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Generate an image": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Responder con ícono",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Preparar error de Gemini",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Preparar error de Gemini": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Responder error de Gemini",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"authors": "Isaac Aracena",
|
||||
"name": "Version ce03fd5f",
|
||||
"description": "",
|
||||
"autosaved": true,
|
||||
"workflowPublishHistory": [
|
||||
{
|
||||
"createdAt": "2026-07-28T20:24:18.060Z",
|
||||
"id": 3595,
|
||||
"workflowId": "F2rMlVS9mBypNNn7",
|
||||
"versionId": "ce03fd5f-2d70-44f1-b1e2-b31fc92ddf62",
|
||||
"event": "activated",
|
||||
"userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user