{
  "name": "Vorlux AI | Discord Role Sync",
  "active": false,
  "nodes": [
    {
      "parameters": { "rule": { "interval": [{ "field": "hours", "hoursInterval": 2 }] } },
      "id": "schedule-trigger", "name": "Every 2 Hours", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [220, 300]
    },
    {
      "parameters": { "url": "http://host.docker.internal:3010/api/admin/memberships", "method": "GET", "options": { "timeout": 15000 } },
      "id": "fetch-memberships", "name": "Fetch Hub Memberships", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [460, 200]
    },
    {
      "parameters": { "url": "http://host.docker.internal:3010/api/discord/roles", "method": "GET", "options": { "timeout": 15000 } },
      "id": "fetch-roles", "name": "Fetch Discord Roles", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [460, 400]
    },
    {
      "parameters": { "mode": "runOnceForAllItems", "jsCode": "const memberships = $('Fetch Hub Memberships').first().json.data || [];\nconst roles = $('Fetch Discord Roles').first().json.data || [];\nconst tierMap = { free: 'community-member', basic: 'subscriber', pro: 'pro-member', enterprise: 'vip-member' };\nconst updates = [];\nmemberships.forEach(m => {\n  if (!m.discord_id) return;\n  const expected = tierMap[m.tier] || 'community-member';\n  if (!roles.some(r => r.userId === m.discord_id && r.role === expected)) {\n    updates.push({ userId: m.discord_id, role: expected, action: 'add' });\n  }\n});\nreturn [{ json: { total: memberships.length, updates, syncCount: updates.length } }];" },
      "id": "compare", "name": "Compare & Sync", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [720, 300]
    },
    {
      "parameters": { "url": "http://host.docker.internal:3010/api/discord/roles/configure", "method": "POST", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ updates: $json.updates }) }}", "options": { "timeout": 30000 } },
      "id": "apply", "name": "Apply Role Changes", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [960, 300]
    },
    {
      "parameters": { "method": "POST", "url": "={{$env.DISCORD_OPS_WEBHOOK}}", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ content: '🔄 Discord Role Sync: ' + $('Compare & Sync').first().json.syncCount + ' roles updated out of ' + $('Compare & Sync').first().json.total + ' members' }) }}" },
      "id": "discord-notify", "name": "Discord Notify", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1200, 300]
    }
  ],
  "connections": {
    "Every 2 Hours": { "main": [[{ "node": "Fetch Hub Memberships", "type": "main", "index": 0 }, { "node": "Fetch Discord Roles", "type": "main", "index": 0 }]] },
    "Fetch Hub Memberships": { "main": [[{ "node": "Compare & Sync", "type": "main", "index": 0 }]] },
    "Fetch Discord Roles": { "main": [[{ "node": "Compare & Sync", "type": "main", "index": 0 }]] },
    "Compare & Sync": { "main": [[{ "node": "Apply Role Changes", "type": "main", "index": 0 }]] },
    "Apply Role Changes": { "main": [[{ "node": "Discord Notify", "type": "main", "index": 0 }]] }
  },
  "settings": { "executionOrder": "v1" }
}
