{
 "name": "Corporate site: contact intake",
 "connections": {
  "Poll": {
   "main": [
    [
     {
      "node": "Fetch submissions",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Fetch submissions": {
   "main": [
    [
     {
      "node": "Validate and de-duplicate",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Validate and de-duplicate": {
   "main": [
    [
     {
      "node": "Post to Talk",
      "type": "main",
      "index": 0
     },
     {
      "node": "Format log line",
      "type": "main",
      "index": 0
     }
    ]
   ]
  },
  "Format log line": {
   "main": [
    [
     {
      "node": "Append to leads file",
      "type": "main",
      "index": 0
     }
    ]
   ]
  }
 },
 "settings": {
  "executionOrder": "v1",
  "saveDataErrorExecution": "all",
  "callerPolicy": "workflowsFromSameOwner",
  "availableInMCP": false
 },
 "nodes": [
  {
   "name": "Poll",
   "type": "n8n-nodes-base.scheduleTrigger",
   "typeVersion": 1.2,
   "position": [
    0,
    0
   ],
   "parameters": {
    "rule": {
     "interval": [
      {
       "field": "minutes",
       "minutesInterval": 5
      }
     ]
    }
   }
  },
  {
   "name": "Fetch submissions",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    220,
    0
   ],
   "parameters": {
    "url": "https://api.netlify.com/api/v1/forms/REPLACE_WITH_FORM_ID/submissions?per_page=100",
    "authentication": "genericCredentialType",
    "genericAuthType": "httpHeaderAuth",
    "options": {
     "timeout": 20000
    }
   },
   "credentials": {
    "httpHeaderAuth": {
     "name": "Form host API token"
    }
   }
  },
  {
   "name": "Validate and de-duplicate",
   "type": "n8n-nodes-base.code",
   "typeVersion": 2,
   "position": [
    440,
    0
   ],
   "parameters": {
    "jsCode": "\n// De-duplicate by submission id across runs, validate, and normalise the fields the site form sends.\nconst seen = $getWorkflowStaticData('global');\nseen.ids = seen.ids || [];\nconst out = [];\nfor (const item of $input.all()) {\n  const s = item.json;\n  const id = String(s.id || s.number || '');\n  if (!id || seen.ids.includes(id)) continue;\n  const d = s.data || s;\n  if (d['bot-field'] || d.company_url) { seen.ids.push(id); continue; }        // honeypot filled: spam\n  const clip = (v, n) => String(v || '').replace(/[\\u0000-\\u001f]+/g, ' ').trim().slice(0, n);\n  const email = clip(d.email, 200);\n  if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) { seen.ids.push(id); continue; }\n  if (out.length >= 20) break;                                                  // flood cap per poll\n  out.push({ json: {\n    id, received: s.created_at || new Date().toISOString(),\n    name: clip(d.name, 120), email, org: clip(d.org || d.company, 160),\n    kind: clip(d.kind, 40) || 'general', message: clip(d.message || s.body, 2000),\n  }});\n  seen.ids.push(id);\n}\nseen.ids = seen.ids.slice(-500);\nreturn out;\n"
   }
  },
  {
   "name": "Post to Talk",
   "type": "n8n-nodes-base.httpRequest",
   "typeVersion": 4.2,
   "position": [
    660,
    -100
   ],
   "parameters": {
    "method": "POST",
    "url": "https://REPLACE_WITH_NEXTCLOUD_HOST/ocs/v2.php/apps/spreed/api/v1/chat/REPLACE_WITH_TALK_ROOM",
    "authentication": "genericCredentialType",
    "genericAuthType": "httpBasicAuth",
    "sendHeaders": true,
    "headerParameters": {
     "parameters": [
      {
       "name": "OCS-APIRequest",
       "value": "true"
      },
      {
       "name": "Accept",
       "value": "application/json"
      }
     ]
    },
    "sendBody": true,
    "contentType": "form-urlencoded",
    "bodyParameters": {
     "parameters": [
      {
       "name": "message",
       "value": "=New {{ $json.kind }} enquiry from the corporate site\n\n{{ $json.name }}{{ $json.org ? ' · ' + $json.org : '' }}\n{{ $json.email }}\n\n{{ $json.message }}\n\nreceived {{ $json.received }} · id {{ $json.id }}"
      }
     ]
    },
    "options": {
     "timeout": 20000
    }
   },
   "credentials": {
    "httpBasicAuth": {
     "name": "Nextcloud Talk: homelab-agent (contact intake)"
    }
   }
  },
  {
   "name": "Format log line",
   "type": "n8n-nodes-base.code",
   "typeVersion": 2,
   "position": [
    660,
    100
   ],
   "parameters": {
    "jsCode": "return $input.all().map(i => ({ json: i.json, binary: { data: { data: Buffer.from(`- ${i.json.received} | ${i.json.kind} | ${i.json.name} | ${i.json.org} | ${i.json.email} | ${i.json.message.replace(/\\n/g, ' ')}\\n`).toString('base64'), mimeType: 'text/markdown', fileName: 'corporate-leads.md' } } }));"
   }
  },
  {
   "name": "Append to leads file",
   "type": "n8n-nodes-base.readWriteFile",
   "typeVersion": 1,
   "position": [
    880,
    100
   ],
   "parameters": {
    "operation": "write",
    "fileName": "/REPLACE_WITH_LEADS_DIR/corporate-leads.md",
    "dataPropertyName": "data",
    "options": {
     "append": true
    }
   }
  }
 ]
}
