{
  "name": "Peer Monitoring Phase 2 - Jeeva",
  "nodes": [
    {
      "parameters": {},
      "id": "0f008fc7-87e0-44f4-a915-b89fe0658b2d",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1200,
        112
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.Website }}",
        "options": {
          "batching": {
            "batch": {
              "batchInterval": 2000
            }
          },
          "redirect": {
            "redirect": {
              "followRedirects": true,
              "maxRedirects": 50
            }
          }
        }
      },
      "id": "d1d1225c-25ac-4ea9-a251-ecf050c8a0cd",
      "name": "HTTP Request - Fetch Website",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        -528,
        112
      ],
      "retryOnFail": true,
      "waitBetweenTries": 1000,
      "notesInFlow": true,
      "alwaysOutputData": false,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "functionCode": "\nconst crypto = require('crypto');\n\nreturn items.map(item => {\n  const html = item.json;\n  const body = html.body || html.data || '';\n  let text = body.replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n                 .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n                 .replace(/<[^>]*>/g, ' ')\n                 .replace(/\\s+/g, ' ')\n                 .trim();\n  const normalized = text.toLowerCase();\n  const hash = crypto.createHash('md5').update(normalized).digest('hex');\n  return { json: {\n    peer_name: item.json.peer_name,\n    website: item.json.website,\n    linkedin: item.json.linkedin,\n    normalized_text: normalized,\n    current_hash: hash\n  }};\n});\n                "
      },
      "id": "ff0ec409-e61f-4503-bc5a-cb3693c4d15a",
      "name": "Function - Clean & Hash",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        -320,
        112
      ]
    },
    {
      "parameters": {
        "fromEmail": "your-email@example.com",
        "toEmail": "your-email@example.com",
        "ccEmail": "your-email@example.com",
        "subject": "={{\"[Peer Monitor] Change detected on \" + $json[\"peer_name\"]}}",
        "text": "=Peer: {{ $('Get row(s) in sheet').item.json['Peer Name'] }}  \nWebsite:{{ $('Get row(s) in sheet').item.json.Website }}\nLinkedIn: {{ $('Get row(s) in sheet').item.json.LinkedIn }}\nChange detected at: {{$now}}\n\nChange Notes:  {{ $json.normalized_text }}",
        "html": "=<div style=\"font-family: Arial, sans-serif; padding:12px;\">\n  <h2 style=\"color:#135da1;\">Change Detected \u2013 Peer Monitoring</h2>\n  <p>\n    <strong>Peer:</strong> {{ $('Get row(s) in sheet').item.json['Peer Name'] }}<br>\n    <strong>Website:</strong> <a href=\"{{ $('Get row(s) in sheet').item.json.Website }}\" target=\"_blank\">{{ $('Get row(s) in sheet').item.json.Website }}</a><br>\n    <strong>LinkedIn:</strong> \n    <a href=\"{{ $('Get row(s) in sheet').item.json.LinkedIn }}\" target=\"_blank\">\n      {{ $('Get row(s) in sheet').item.json.LinkedIn }}\n    </a><br>\n    <strong>Change detected at:</strong> {{$now}}\n  </p>\n  <h3 style=\"color:#e67e22;\">Change Notes</h3>\n  <div style=\"border:1px solid #e2e2e2; background:#f9f9f9; padding:10px; margin-top:8px;\">\n    {{ $json.normalized_text }}\n  </div>\n</div>\n",
        "options": {}
      },
      "id": "af07c02a-ad11-40f7-b01c-fe7ecb4d3190",
      "name": "Email - Notify",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 1,
      "position": [
        384,
        -160
      ]
    },
    {
      "parameters": {
        "webhookUri": "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN",
        "text": "=**Change Alert!**\n**Peer: ** {{ $('Get row(s) in sheet').item.json['Peer Name'] }}\n**Website: ** {{ $('Get row(s) in sheet').item.json.Website }}\n**LinkedIn: ** {{ $('Get row(s) in sheet').item.json.LinkedIn }}\n**Change detected at: ** {{$now}}",
        "options": {}
      },
      "id": "b91bf83e-4a33-4448-8504-8f00089ffd7a",
      "name": "Discord - Notify",
      "type": "n8n-nodes-base.discord",
      "typeVersion": 1,
      "position": [
        624,
        0
      ]
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "list",
          "cachedResultName": "Your Sheet",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        -992,
        112
      ],
      "id": "8364878f-bbff-4462-bcad-b5b6e87cdf67",
      "name": "Get row(s) in sheet"
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "list",
          "cachedResultName": "Your Sheet",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Last Hash": "={{ $json.current_hash }}",
            "Notes": "={{ $json.preview_text }}",
            "row_number": "={{ $('Get row(s) in sheet').item.json.row_number }}",
            "Last Checked": "={{ $json.last_checked }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": [
            {
              "id": "Peer Name",
              "displayName": "Peer Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Website",
              "displayName": "Website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn",
              "displayName": "LinkedIn",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Hash",
              "displayName": "Last Hash",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Last Checked",
              "displayName": "Last Checked",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Notes",
              "displayName": "Notes",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "displayName": "row_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "readOnly": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        176,
        -304
      ],
      "id": "a8a63b45-421e-4729-9c46-4d3f0aa6869b",
      "name": "Update row in sheet"
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $('Get row(s) in sheet').item.json['Last Hash'] }}",
              "operation": "notEqual",
              "value2": "={{ $json.current_hash }}"
            }
          ]
        }
      },
      "id": "b5666c92-ddf5-45d2-9834-9eeaa2021e44",
      "name": "Change Detected?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        -128,
        112
      ]
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        848,
        128
      ],
      "id": "eb9e7b44-72d2-45f5-81fe-3b3889c34984",
      "name": "No Operation, do nothing"
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "id": "b7f1b102-e46a-4157-a890-71d3ee75811e",
      "name": "SplitInBatches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        -768,
        112
      ]
    },
    {
      "parameters": {
        "jsCode": "// Truncate normalized_text to avoid Google Sheets 50,000 char limit\nreturn items.map(item => {\n  const data = item.json;\n\n  // Truncate normalized_text if too long\n  let previewText = data.normalized_text || \"\";\n  if (previewText.length > 45000) { // safe buffer below 50k limit\n    previewText = previewText.slice(0, 45000) + \"... [truncated]\";\n  }\n\n  return {\n    json: {\n      peer_name: data.peer_name,\n      website: data.website,\n      linkedin: data.linkedin,\n      current_hash: data.current_hash,\n      preview_text: previewText,   // safe truncated version\n      row_number: data.row_number, // comes from your Lookup node\n      last_checked: new Date().toISOString()\n    }\n  };\n});\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        -64
      ],
      "id": "e0a894b1-3f77-45e6-bc72-ee7ce3647aad",
      "name": "Code in JavaScript"
    }
  ],
  "pinData": {},
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request - Fetch Website": {
      "main": [
        [
          {
            "node": "Function - Clean & Hash",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Function - Clean & Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function - Clean & Hash": {
      "main": [
        [
          {
            "node": "Change Detected?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Change Detected?": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email - Notify": {
      "main": [
        [
          {
            "node": "Discord - Notify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update row in sheet": {
      "main": [
        [
          {
            "node": "Email - Notify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Discord - Notify": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Operation, do nothing": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches": {
      "main": [
        [
          {
            "node": "HTTP Request - Fetch Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Update row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "createdAt": "2025-09-09T17:19:57.889Z",
      "updatedAt": "2025-09-09T17:19:57.889Z",
      "id": "q8RjGNJRVkq1Nz9K",
      "name": "Monitoring Agent"
    }
  ]
}