{
  "name": "ezGPT - Extract PDF Text",
  "active": false,
  "nodes": [
    {
      "id": "trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        200,
        300
      ],
      "parameters": {}
    },
    {
      "id": "download",
      "name": "Download PDF",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        440,
        300
      ],
      "parameters": {
        "method": "GET",
        "url": "https://ezgpt.ru/storage/article-files/n8n-pdf-text-demo.pdf",
        "authentication": "none",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": false,
              "responseFormat": "file",
              "outputPropertyName": "document"
            }
          },
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "timeout": 15000,
          "allowUnauthorizedCerts": false
        }
      }
    },
    {
      "id": "check-file",
      "name": "Check PDF",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('Expected one download');\nconst item = items[0];\nconst type = String(item.json.headers?.['content-type'] ?? '').split(';')[0].trim().toLowerCase();\nif (item.json.statusCode !== 200 || type !== 'application/pdf') {\n  throw new Error('Expected HTTP 200 with application/pdf');\n}\nif (Object.keys(item.binary ?? {}).join('|') !== 'document') {\n  throw new Error('Expected binary.document');\n}\nconst bytes = await this.helpers.getBinaryDataBuffer(0, 'document');\nif (bytes.length < 5 || bytes.length > 250000 || bytes.subarray(0, 5).toString('ascii') !== '%PDF-') {\n  throw new Error('Expected a PDF up to 250000 bytes');\n}\nreturn [{ json: { source_bytes: bytes.length }, binary: { document: item.binary.document } }];"
      }
    },
    {
      "id": "extract",
      "name": "Read PDF",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        920,
        300
      ],
      "parameters": {
        "operation": "pdf",
        "binaryPropertyName": "document",
        "options": {
          "joinPages": true,
          "keepSource": "both",
          "maxPages": 2
        }
      }
    },
    {
      "id": "check-text",
      "name": "Check Text",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1160,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const item = $input.first();\nif (typeof item.json.text !== 'string' || !item.json.text.trim()) {\n  throw new Error('No extracted text; check PDF text layer and Max Pages');\n}\nif (item.json.numpages !== 2 || !Number.isInteger(item.json.source_bytes) || !item.binary?.document) {\n  throw new Error('Expected two-page sample with source metadata and binary');\n}\nconst normalized = item.json.text.replace(/\\s+/gu, ' ').trim();\nconst markers = [\n  'Учебный PDF для n8n', 'Заявка: DEMO-001', 'Клиент: Тестовая компания',\n  'Страница 2', 'Следующий шаг: ручная проверка.',\n];\nfor (const marker of markers) {\n  if (!normalized.includes(marker)) throw new Error('Missing sample text: ' + marker);\n}\nreturn [{\n  json: {\n    file_name: 'n8n-pdf-text-demo.pdf', pages: item.json.numpages,\n    request_id: 'DEMO-001', text: item.json.text, verified: true, action: false,\n  },\n  binary: { document: item.binary.document },\n}];"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Download PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download PDF": {
      "main": [
        [
          {
            "node": "Check PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check PDF": {
      "main": [
        [
          {
            "node": "Read PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read PDF": {
      "main": [
        [
          {
            "node": "Check Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
