{
 "name": "Preguntas de Mercado Libre · IA + aprobación por Telegram",
 "nodes": [
  {
   "id": "3f2a3b57-2b9c-4169-80b1-19e29905f5a9",
   "name": "Nota 56c8",
   "type": "n8n-nodes-base.stickyNote",
   "typeVersion": 1,
   "position": [
    -80,
    -400
   ],
   "parameters": {
    "content": "## Preguntas de Mercado Libre respondidas con IA\nMercado Libre avisa cada pregunta nueva; el flujo lee la pregunta y la publicación (precio, stock, variantes, envío, garantía, ficha y descripción), Claude redacta la respuesta y el código controla las reglas (sin correos, teléfonos, links ni canales de contacto).\n**modo** = `automatico`: publica lo que sale de la publicación y te pide aprobación del resto. **modo** = `aprobar`: todo pasa por Telegram, con los botones **Publicar** y **Descartar**.\n\n**Credenciales:** OAuth2 de Mercado Libre (auth `https://auth.mercadolibre.com.ar/authorization`, token `https://api.mercadolibre.com/oauth/token`), una «Header Auth» `x-api-key` para Anthropic y Telegram. En tu app de ML: tema **questions** y la URL del nodo «Pregunta nueva».",
    "width": 900,
    "height": 300,
    "color": 6
   }
  },
  {
   "id": "dc5983ed-2180-4c85-8c77-24d40e8ea6bf",
   "name": "Pregunta nueva",
   "type": "n8n-nodes-base.webhook",
   "typeVersion": 2.1,
   "position": [
    0,
    80
   ],
   "parameters": {
    "httpMethod": "POST",
    "path": "ml-preguntas",
    "options": {}
   },
   "webhookId": "1f8b8914-b98b-4ef5-b757-476ff3f4e8f5"
  },
  {
   "id": "4e11d1cc-f08a-4d81-b9f3-b9d643864ab6",
   "name": "Configuración",
   "type": "n8n-nodes-base.set",
   "typeVersion": 3.4,
   "position": [
    240,
    80
   ],
   "parameters": {
    "assignments": {
     "assignments": [
      {
       "id": "57fa140b-d0c5-4098-b9f4-b89422e87a40",
       "name": "tienda",
       "value": "Tu Tienda",
       "type": "string"
      },
      {
       "id": "6b7d22be-2205-47ac-85d1-91cf90f1a1df",
       "name": "modo",
       "value": "aprobar",
       "type": "string"
      },
      {
       "id": "47b4f152-4925-4a19-a8c2-1f21434dd261",
       "name": "mlUserId",
       "value": "TU_USER_ID_DE_ML",
       "type": "string"
      },
      {
       "id": "1826ac56-604a-4cd3-90c1-fefc193a54b1",
       "name": "telegramChatId",
       "value": "TU_CHAT_ID",
       "type": "string"
      },
      {
       "id": "571092a9-9fb6-4a4e-ad73-3b96b836328d",
       "name": "infoVendedor",
       "value": "Hacemos factura A y B. Despachamos en el día si se compra antes de las 13 h.",
       "type": "string"
      }
     ]
    },
    "includeOtherFields": true,
    "include": "all",
    "options": {}
   }
  },
  {
   "id": "05ac0ff6-be8a-41a0-ad37-b53e5c329ab2",
   "name": "¿Es una pregunta de mi cuenta?",
   "type": "n8n-nodes-base.if",
   "typeVersion": 2.2,
   "position": [
    480,
    80
   ],
   "parameters": {
    "conditions": {
     "options": {
      "caseSensitive": true,
      "leftValue": "",
      "typeValidation": "loose",
      "version": 2
     },
     "conditions": [
      {
       "id": "a013527a-f2ff-4167-8306-edec0a9ad12c",
       "leftValue": "={{ $('Pregunta nueva').item.json.body.topic === 'questions' && String($('Pregunta nueva').item.json.body.user_id) === String($json.mlUserId) }}",
       "rightValue": "",
       "operator": {
        "type": "boolean",
        "operation": "true",
        "singleValue": true
       }
      }
     ],
     "combinator": "and"
    },
    "options": {}
   }
  },
  {
   "id": "ad88046a-7b25-47d1-ab9f-6eff5becd273",
   "name": "Leer la pregunta",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    720,
    60
   ],
   "parameters": {
    "method": "GET",
    "url": "=https://api.mercadolibre.com{{ $('Pregunta nueva').item.json.body.resource }}?api_version=4",
    "authentication": "genericCredentialType",
    "genericAuthType": "oAuth2Api",
    "options": {}
   }
  },
  {
   "id": "d8f0a35c-e9d5-4ae5-abb3-170e73dae3b0",
   "name": "¿Sin responder?",
   "type": "n8n-nodes-base.if",
   "typeVersion": 2.2,
   "position": [
    960,
    60
   ],
   "parameters": {
    "conditions": {
     "options": {
      "caseSensitive": true,
      "leftValue": "",
      "typeValidation": "loose",
      "version": 2
     },
     "conditions": [
      {
       "id": "65bc42c3-56ee-4505-92af-35d581f9eae2",
       "leftValue": "={{ $json.status }}",
       "rightValue": "UNANSWERED",
       "operator": {
        "type": "string",
        "operation": "equals"
       }
      }
     ],
     "combinator": "and"
    },
    "options": {}
   }
  },
  {
   "id": "36cd56e9-7b53-4b87-985a-a8c3bbe532cc",
   "name": "Leer la publicación",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    1200,
    40
   ],
   "parameters": {
    "method": "GET",
    "url": "=https://api.mercadolibre.com/items/{{ $json.item_id }}",
    "authentication": "genericCredentialType",
    "genericAuthType": "oAuth2Api",
    "options": {}
   }
  },
  {
   "id": "451dc1df-cc3b-4206-919e-019204184320",
   "name": "Leer la descripción",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    1440,
    40
   ],
   "parameters": {
    "method": "GET",
    "url": "=https://api.mercadolibre.com/items/{{ $json.id }}/description",
    "authentication": "genericCredentialType",
    "genericAuthType": "oAuth2Api",
    "options": {}
   },
   "onError": "continueRegularOutput"
  },
  {
   "id": "7a863204-6c8f-4737-9184-87f58f65f454",
   "name": "Armar el pedido a la IA",
   "type": "n8n-nodes-base.code",
   "typeVersion": 2,
   "position": [
    1680,
    40
   ],
   "parameters": {
    "jsCode": "// ── Nodo «Armar el pedido a la IA» (Code) ──\n// Entrada: la pregunta, la publicación y su descripción (tres pedidos a la API de Mercado Libre). Salida: el cuerpo\n// del pedido a Claude con una herramienta de esquema estricto.\nconst cfg = $('Configuración').first().json;\nconst q = $('Leer la pregunta').first().json, it = $('Leer la publicación').first().json, desc = $('Leer la descripción').first().json;\nconst precio = new Intl.NumberFormat('es-AR', { style: 'currency', currency: it.currency_id || 'ARS', minimumFractionDigits: Number.isInteger(it.price) ? 0 : 2 }).format(it.price);\nconst ficha = (it.attributes || []).filter((a) => a.value_name).slice(0, 60).map((a) => `${a.name}: ${a.value_name}`).join('\\n');\nconst variantes = (it.variations || []).map((v) => `${(v.attribute_combinations || []).map((a) => a.value_name).join(' / ')} (${v.available_quantity})`).join('; ');\nconst sistema = `Respondes las preguntas de compradores en Mercado Libre por ${cfg.tienda}. Tono cordial, breve y concreto. Español neutro.\nSaludo breve, la respuesta concreta y un cierre cordial. Entre 1 y 4 oraciones. Texto plano.\nReglas de Mercado Libre: nunca des teléfonos, correos, links ni redes; nunca ofrezcas hablar por fuera; nunca cambies el precio.\nUsa SÓLO los datos de abajo. decision «publicar» si la respuesta sale completa de estos datos; «revisar» si piden algo que no figura, negocian, reclaman o piden contacto (igual redacta el borrador).\n\nTítulo: ${it.title}\nPrecio: ${precio} · Stock: ${it.available_quantity} · Envío ${it.shipping?.free_shipping ? 'gratis' : 'con costo'}\nGarantía: ${it.warranty || 'no figura'}\n${variantes ? 'Variantes: ' + variantes + '\\n' : ''}Ficha técnica:\n${ficha}\nDescripción:\n${String(desc.plain_text || '').slice(0, 5000)}\n${cfg.infoVendedor ? '\\nInformación del vendedor:\\n' + cfg.infoVendedor : ''}`;\nreturn [{ json: { pregunta: q, cuerpo: {\n  model: 'claude-haiku-4-5', max_tokens: 900, system: sistema,\n  tools: [{ name: 'responder_pregunta', strict: true, description: 'La respuesta para el comprador y si se puede publicar sola.',\n    input_schema: { type: 'object', additionalProperties: false, required: ['respuesta', 'decision', 'motivo'], properties: {\n      respuesta: { type: 'string' }, decision: { type: 'string', enum: ['publicar', 'revisar'] }, motivo: { type: 'string' } } } }],\n  tool_choice: { type: 'tool', name: 'responder_pregunta' },\n  messages: [{ role: 'user', content: `Pregunta del comprador: «${q.text}»` }] } } }];\n"
   }
  },
  {
   "id": "1777ccd5-a038-4b71-88d1-42f664a80321",
   "name": "Claude",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    1920,
    40
   ],
   "parameters": {
    "method": "POST",
    "url": "https://api.anthropic.com/v1/messages",
    "authentication": "genericCredentialType",
    "genericAuthType": "httpHeaderAuth",
    "sendBody": true,
    "specifyBody": "json",
    "jsonBody": "={{ JSON.stringify($json.cuerpo) }}",
    "options": {}
   }
  },
  {
   "id": "418750cd-643d-4940-9a11-f29aa5b2f0ff",
   "name": "Controlar las reglas",
   "type": "n8n-nodes-base.code",
   "typeVersion": 2,
   "position": [
    2160,
    40
   ],
   "parameters": {
    "jsCode": "// ── Nodo «Controlar las reglas» (Code) ──\n// La respuesta de la IA + el control en código: con correo, link, teléfono o un canal de contacto no se publica,\n// diga lo que diga el modelo. Guarda el borrador (para aprobarlo desde Telegram) en los datos estáticos.\nconst cfg = $('Configuración').first().json;\nconst memoria = $getWorkflowStaticData('global'); memoria.borradores = memoria.borradores || {};\nconst r = ($input.first().json.content || []).find((c) => c.type === 'tool_use')?.input || {};\nconst q = $('Armar el pedido a la IA').first().json.pregunta, it = $('Leer la publicación').first().json;\nconst t = String(r.respuesta || '');\nlet motivoRegla = '';\nif (/[\\w.+-]+@[\\w-]+\\.[\\w.]+/.test(t)) motivoRegla = 'tiene un correo';\nelse if (/(https?:\\/\\/|www\\.)/i.test(t)) motivoRegla = 'tiene un link';\nelse if (/(\\+?\\d[\\d\\s().-]{7,}\\d)/.test(t.replace(/\\b\\d{1,3}(\\.\\d{3})+(,\\d+)?\\b/g, ''))) motivoRegla = 'tiene un número de teléfono';\nelse if (/\\b(whats\\s*app|wsp|telegram|instagram|facebook)\\b/i.test(t)) motivoRegla = 'menciona un canal de contacto';\nconst publicar = cfg.modo === 'automatico' && r.decision === 'publicar' && !motivoRegla && t.length > 0 && t.length <= 2000;\nif (!publicar) memoria.borradores[q.id] = { respuesta: t, titulo: it.title, pregunta: q.text, creado: Date.now() };\nreturn [{ json: { preguntaId: q.id, pregunta: q.text, titulo: it.title, respuesta: t, publicar,\n  motivo: motivoRegla ? `La respuesta ${motivoRegla}.` : (r.motivo || '') } }];\n"
   }
  },
  {
   "id": "b5f2c5dc-9589-417d-8730-fa2261cd7a8b",
   "name": "¿Publicar sola?",
   "type": "n8n-nodes-base.if",
   "typeVersion": 2.2,
   "position": [
    2400,
    40
   ],
   "parameters": {
    "conditions": {
     "options": {
      "caseSensitive": true,
      "leftValue": "",
      "typeValidation": "loose",
      "version": 2
     },
     "conditions": [
      {
       "id": "1cc733d0-1062-4564-a9fe-4a936bc41dc4",
       "leftValue": "={{ $json.publicar }}",
       "rightValue": "",
       "operator": {
        "type": "boolean",
        "operation": "true",
        "singleValue": true
       }
      }
     ],
     "combinator": "and"
    },
    "options": {}
   }
  },
  {
   "id": "651a106c-d53b-4d6e-ab4e-e7aa314933fd",
   "name": "Publicar la respuesta",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    2640,
    -40
   ],
   "parameters": {
    "method": "POST",
    "url": "https://api.mercadolibre.com/answers",
    "authentication": "genericCredentialType",
    "genericAuthType": "oAuth2Api",
    "sendBody": true,
    "specifyBody": "json",
    "jsonBody": "={{ JSON.stringify({ question_id: Number($json.preguntaId), text: $json.respuesta }) }}",
    "options": {}
   }
  },
  {
   "id": "a10900be-13a0-4142-8d99-b69d299b4a20",
   "name": "Pedir aprobación por Telegram",
   "type": "n8n-nodes-base.telegram",
   "typeVersion": 1.2,
   "position": [
    2640,
    140
   ],
   "parameters": {
    "chatId": "={{ $('Configuración').first().json.telegramChatId }}",
    "text": "=<b>Pregunta para revisar</b> · {{ $json.titulo }}\n«{{ $json.pregunta }}»\n\nBorrador: {{ $json.respuesta }}\n\n<i>{{ $json.motivo }}</i>",
    "replyMarkup": "inlineKeyboard",
    "inlineKeyboard": {
     "rows": [
      {
       "row": {
        "buttons": [
         {
          "text": "Publicar",
          "additionalFields": {
           "callback_data": "=pub:{{ $json.preguntaId }}"
          }
         },
         {
          "text": "Descartar",
          "additionalFields": {
           "callback_data": "=desc:{{ $json.preguntaId }}"
          }
         }
        ]
       }
      }
     ]
    },
    "additionalFields": {
     "parse_mode": "HTML",
     "appendAttribution": false
    }
   }
  },
  {
   "id": "05fcfc14-e484-46e0-819f-f8b1d1398e32",
   "name": "Botón de Telegram",
   "type": "n8n-nodes-base.telegramTrigger",
   "typeVersion": 1.2,
   "position": [
    0,
    480
   ],
   "parameters": {
    "updates": [
     "callback_query"
    ],
    "additionalFields": {}
   },
   "webhookId": "7d7b14d0-e5ac-47c4-9cc1-52f3d83ea0c5"
  },
  {
   "id": "3252d614-0687-453b-a2fd-eae595afaa11",
   "name": "Leer el borrador",
   "type": "n8n-nodes-base.code",
   "typeVersion": 2,
   "position": [
    240,
    480
   ],
   "parameters": {
    "jsCode": "// El botón trae «pub:<id>» o «desc:<id>»; el borrador quedó guardado por «Controlar las reglas».\nconst memoria = $getWorkflowStaticData('global'); memoria.borradores = memoria.borradores || {};\nconst cb = $input.first().json.callback_query || {};\nconst [accion, id] = String(cb.data || '').split(':');\nconst b = memoria.borradores[id];\nif (!b) return [{ json: { accion: 'nada', queryId: cb.id, aviso: 'Ese borrador ya no está (publicado, descartado o vencido).' } }];\ndelete memoria.borradores[id];\nreturn [{ json: { accion, preguntaId: id, respuesta: b.respuesta, queryId: cb.id, aviso: accion === 'pub' ? 'Publicada en Mercado Libre' : 'Descartada' } }];"
   }
  },
  {
   "id": "0cd924ac-0817-4423-96fd-da7615e47d9a",
   "name": "¿Publicar?",
   "type": "n8n-nodes-base.if",
   "typeVersion": 2.2,
   "position": [
    480,
    480
   ],
   "parameters": {
    "conditions": {
     "options": {
      "caseSensitive": true,
      "leftValue": "",
      "typeValidation": "loose",
      "version": 2
     },
     "conditions": [
      {
       "id": "db5da074-004c-4cf5-b554-50bd337edd4e",
       "leftValue": "={{ $json.accion }}",
       "rightValue": "pub",
       "operator": {
        "type": "string",
        "operation": "equals"
       }
      }
     ],
     "combinator": "and"
    },
    "options": {}
   }
  },
  {
   "id": "67d67fbc-4615-4b41-a645-d3b33faee90f",
   "name": "Publicar la respuesta aprobada",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    720,
    420
   ],
   "parameters": {
    "method": "POST",
    "url": "https://api.mercadolibre.com/answers",
    "authentication": "genericCredentialType",
    "genericAuthType": "oAuth2Api",
    "sendBody": true,
    "specifyBody": "json",
    "jsonBody": "={{ JSON.stringify({ question_id: Number($json.preguntaId), text: $json.respuesta }) }}",
    "options": {}
   }
  },
  {
   "id": "71eb9393-08b1-40bb-abfc-a8cf4ba96425",
   "name": "Confirmar en Telegram",
   "type": "n8n-nodes-base.telegram",
   "typeVersion": 1.2,
   "position": [
    960,
    500
   ],
   "parameters": {
    "resource": "callback",
    "operation": "answerQuery",
    "queryId": "={{ $('Leer el borrador').item.json.queryId }}",
    "additionalFields": {
     "text": "={{ $('Leer el borrador').item.json.aviso }}"
    }
   }
  }
 ],
 "settings": {
  "executionOrder": "v1"
 },
 "pinData": {},
 "connections": {
  "Pregunta nueva": {
   "main": [
    [
     {
      "node": "Configuración",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Configuración": {
   "main": [
    [
     {
      "node": "¿Es una pregunta de mi cuenta?",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "¿Es una pregunta de mi cuenta?": {
   "main": [
    [
     {
      "node": "Leer la pregunta",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Leer la pregunta": {
   "main": [
    [
     {
      "node": "¿Sin responder?",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "¿Sin responder?": {
   "main": [
    [
     {
      "node": "Leer la publicación",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Leer la publicación": {
   "main": [
    [
     {
      "node": "Leer la descripción",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Leer la descripción": {
   "main": [
    [
     {
      "node": "Armar el pedido a la IA",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Armar el pedido a la IA": {
   "main": [
    [
     {
      "node": "Claude",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Claude": {
   "main": [
    [
     {
      "node": "Controlar las reglas",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Controlar las reglas": {
   "main": [
    [
     {
      "node": "¿Publicar sola?",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "¿Publicar sola?": {
   "main": [
    [
     {
      "node": "Publicar la respuesta",
      "type": "main",
      "index": 0
     }
    ],
    [
     {
      "node": "Pedir aprobación por Telegram",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Botón de Telegram": {
   "main": [
    [
     {
      "node": "Leer el borrador",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Leer el borrador": {
   "main": [
    [
     {
      "node": "¿Publicar?",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "¿Publicar?": {
   "main": [
    [
     {
      "node": "Publicar la respuesta aprobada",
      "type": "main",
      "index": 0
     }
    ],
    [
     {
      "node": "Confirmar en Telegram",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Publicar la respuesta aprobada": {
   "main": [
    [
     {
      "node": "Confirmar en Telegram",
      "type": "main",
      "index": 0
     }
    ]
   ]
  }
 }
}