{
  "name": "ezGPT - Webhook Text Upload",
  "active": false,
  "nodes": [
    {
      "id": "upload-request",
      "name": "Upload Request",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        200,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "ezgpt-file-upload",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "check-upload",
      "name": "Check Upload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        420,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('Expected one request');\nconst item = items[0];\nconst body = item.json.body;\nif (!body || typeof body !== 'object' || Array.isArray(body) ||\n    Object.keys(body).length !== 1 ||\n    typeof body.request_id !== 'string' ||\n    !/^demo-[0-9]{3}$/.test(body.request_id)) {\n  throw new Error('Expected only request_id: demo-001');\n}\nconst fields = Object.keys(item.binary ?? {});\nif (fields.length !== 1 || fields[0] !== 'document') {\n  throw new Error('Expected exactly one file in document');\n}\nconst file = item.binary.document;\nif (file.fileName !== 'note-demo.txt' || file.mimeType !== 'text/plain') {\n  throw new Error('Expected note-demo.txt with text/plain');\n}\nconst buffer = await this.helpers.getBinaryDataBuffer(0, 'document');\nif (buffer.length === 0 || buffer.length > 4096) {\n  throw new Error('File must contain 1-4096 bytes');\n}\nconst text = buffer.toString('utf8');\nif (!Buffer.from(text, 'utf8').equals(buffer)) {\n  throw new Error('File must be valid UTF-8');\n}\nif (!text.replace(/^\\uFEFF/, '').trim() || text.includes('\\u0000')) {\n  throw new Error('Expected nonempty text without NUL');\n}\nreturn [{\n  json: { request_id: body.request_id, file_name: 'note-demo.txt', bytes: buffer.length },\n  binary: { document: file },\n}];"
      }
    },
    {
      "id": "read-text",
      "name": "Read Text",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        640,
        300
      ],
      "parameters": {
        "operation": "text",
        "binaryPropertyName": "document",
        "destinationKey": "text",
        "options": {
          "encoding": "utf8",
          "stripBOM": true,
          "keepSource": "json"
        }
      }
    },
    {
      "id": "upload-preview",
      "name": "Upload Preview",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        860,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const item = $input.first();\nconst { request_id, file_name, bytes, text } = item.json;\nif (typeof text !== 'string' || !text.trim() || text.charCodeAt(0) === 0xFEFF) {\n  throw new Error('Check Extract from File: text field and Strip BOM');\n}\nif (!/^demo-[0-9]{3}$/.test(request_id ?? '') ||\n    file_name !== 'note-demo.txt' || !Number.isInteger(bytes)) {\n  throw new Error('Check Keep Source: JSON');\n}\nreturn [{ json: { status: 'preview', request_id, file_name, bytes, text, action: false } }];"
      }
    },
    {
      "id": "send-reply",
      "name": "Send Reply",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        1080,
        300
      ],
      "parameters": {
        "respondWith": "firstIncomingItem",
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Cache-Control",
                "value": "no-store"
              }
            ]
          }
        }
      }
    }
  ],
  "connections": {
    "Upload Request": {
      "main": [
        [
          {
            "node": "Check Upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Upload": {
      "main": [
        [
          {
            "node": "Read Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Text": {
      "main": [
        [
          {
            "node": "Upload Preview",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Preview": {
      "main": [
        [
          {
            "node": "Send Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
