Files
ip-manager/n8n/geofeed-export-workflow.json
2026-01-17 20:43:29 +00:00

355 lines
10 KiB
JSON

{
"name": "Geofeed Export to BunnyCDN",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "geofeed-update",
"responseMode": "onReceived",
"options": {}
},
"id": "webhook-trigger",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [240, 200],
"webhookId": "geofeed-update"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"id": "schedule-trigger",
"name": "Daily Backup Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [240, 400]
},
{
"parameters": {
"jsCode": "// Log the trigger source for debugging\nconst webhookData = $('Webhook Trigger').item?.json || null;\nconst scheduleData = $('Daily Backup Trigger').item?.json || null;\n\nlet triggerSource = 'unknown';\nlet triggerReason = '';\nlet entriesAffected = 0;\nlet isImmediate = false;\n\nif (webhookData) {\n triggerSource = 'webhook';\n triggerReason = webhookData.trigger_reason || 'webhook_trigger';\n entriesAffected = webhookData.entries_affected || 0;\n isImmediate = webhookData.immediate || false;\n} else if (scheduleData) {\n triggerSource = 'schedule';\n triggerReason = 'daily_backup';\n}\n\nreturn [{\n json: {\n triggerSource,\n triggerReason,\n entriesAffected,\n isImmediate,\n timestamp: new Date().toISOString()\n }\n}];"
},
"id": "code-merge-triggers",
"name": "Process Trigger",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [460, 300]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT ip_prefix, IFNULL(country_code, '') as country_code, IFNULL(region_code, '') as region_code, IFNULL(city, '') as city, IFNULL(postal_code, '') as postal_code FROM geofeed_entries ORDER BY CASE WHEN ip_prefix LIKE '%:%' THEN 1 ELSE 0 END, INET_ATON(SUBSTRING_INDEX(ip_prefix, '/', 1)), ip_prefix",
"options": {}
},
"id": "mysql-query",
"name": "Query Geofeed Entries",
"type": "n8n-nodes-base.mySql",
"typeVersion": 2.3,
"position": [680, 300],
"credentials": {
"mySql": {
"id": "YOUR_MYSQL_CREDENTIAL_ID",
"name": "MariaDB Geofeed"
}
}
},
{
"parameters": {
"jsCode": "// Build RFC 8805 compliant CSV\nconst items = $input.all();\n\nif (items.length === 0) {\n throw new Error('No entries found in database');\n}\n\n// CSV Header comments\nlet csv = '# Geofeed - Generated by Geofeed Manager\\r\\n';\ncsv += '# Format: ip_prefix,country_code,region_code,city,postal_code\\r\\n';\ncsv += `# Generated: ${new Date().toISOString()}\\r\\n`;\ncsv += `# Total Entries: ${items.length}\\r\\n`;\n\n// Process each entry\nfor (const item of items) {\n const row = item.json;\n \n // Build CSV line - RFC 8805 format\n // Escape any commas in city names\n const city = (row.city || '').replace(/,/g, '');\n const postalCode = (row.postal_code || '').replace(/,/g, '');\n \n csv += `${row.ip_prefix},${row.country_code},${row.region_code},${city},${postalCode}\\r\\n`;\n}\n\n// Return single item with CSV content\nreturn [{\n json: {\n csv: csv,\n entryCount: items.length,\n generatedAt: new Date().toISOString()\n }\n}];"
},
"id": "code-build-csv",
"name": "Build CSV Content",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [900, 300]
},
{
"parameters": {
"method": "PUT",
"url": "=https://storage.bunnycdn.com/{{ $env.BUNNY_STORAGE_ZONE }}/geofeed.csv",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "AccessKey",
"value": "={{ $env.BUNNY_API_KEY }}"
},
{
"name": "Content-Type",
"value": "text/csv; charset=utf-8"
}
]
},
"sendBody": true,
"contentType": "raw",
"body": "={{ $json.csv }}",
"options": {
"response": {
"response": {
"fullResponse": true,
"responseFormat": "text"
}
}
}
},
"id": "http-upload-bunny",
"name": "Upload to BunnyCDN",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1120, 300]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "check-upload-success",
"leftValue": "={{ $json.statusCode }}",
"rightValue": 201,
"operator": {
"type": "number",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-upload-success",
"name": "Check Upload Success",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [1340, 300]
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO geofeed_audit_log (entry_id, action, new_values, changed_by) VALUES (NULL, 'INSERT', JSON_OBJECT('type', 'csv_export', 'status', 'success', 'trigger', '{{ $('Process Trigger').item.json.triggerSource }}', 'reason', '{{ $('Process Trigger').item.json.triggerReason }}', 'entries', {{ $('Build CSV Content').item.json.entryCount }}, 'timestamp', NOW()), 'n8n_workflow')",
"options": {}
},
"id": "mysql-log-success",
"name": "Log Export Success",
"type": "n8n-nodes-base.mySql",
"typeVersion": 2.3,
"position": [1560, 200],
"credentials": {
"mySql": {
"id": "YOUR_MYSQL_CREDENTIAL_ID",
"name": "MariaDB Geofeed"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE geofeed_settings SET setting_value = NOW() WHERE setting_key = 'last_export_at'",
"options": {}
},
"id": "mysql-update-timestamp",
"name": "Update Last Export Time",
"type": "n8n-nodes-base.mySql",
"typeVersion": 2.3,
"position": [1780, 200],
"credentials": {
"mySql": {
"id": "YOUR_MYSQL_CREDENTIAL_ID",
"name": "MariaDB Geofeed"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO geofeed_audit_log (entry_id, action, new_values, changed_by) VALUES (NULL, 'INSERT', JSON_OBJECT('type', 'csv_export', 'status', 'failed', 'trigger', '{{ $('Process Trigger').item.json.triggerSource }}', 'timestamp', NOW()), 'n8n_workflow')",
"options": {}
},
"id": "mysql-log-failure",
"name": "Log Export Failure",
"type": "n8n-nodes-base.mySql",
"typeVersion": 2.3,
"position": [1560, 400],
"credentials": {
"mySql": {
"id": "YOUR_MYSQL_CREDENTIAL_ID",
"name": "MariaDB Geofeed"
}
}
},
{
"parameters": {
"errorMessage": "=Failed to upload geofeed to BunnyCDN"
},
"id": "stop-error",
"name": "Stop and Error",
"type": "n8n-nodes-base.stopAndError",
"typeVersion": 1,
"position": [1780, 400]
},
{
"parameters": {},
"id": "no-op-complete",
"name": "Export Complete",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [2000, 200]
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Process Trigger",
"type": "main",
"index": 0
}
]
]
},
"Daily Backup Trigger": {
"main": [
[
{
"node": "Process Trigger",
"type": "main",
"index": 0
}
]
]
},
"Process Trigger": {
"main": [
[
{
"node": "Query Geofeed Entries",
"type": "main",
"index": 0
}
]
]
},
"Query Geofeed Entries": {
"main": [
[
{
"node": "Build CSV Content",
"type": "main",
"index": 0
}
]
]
},
"Build CSV Content": {
"main": [
[
{
"node": "Upload to BunnyCDN",
"type": "main",
"index": 0
}
]
]
},
"Upload to BunnyCDN": {
"main": [
[
{
"node": "Check Upload Success",
"type": "main",
"index": 0
}
]
]
},
"Check Upload Success": {
"main": [
[
{
"node": "Log Export Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Export Failure",
"type": "main",
"index": 0
}
]
]
},
"Log Export Success": {
"main": [
[
{
"node": "Update Last Export Time",
"type": "main",
"index": 0
}
]
]
},
"Update Last Export Time": {
"main": [
[
{
"node": "Export Complete",
"type": "main",
"index": 0
}
]
]
},
"Log Export Failure": {
"main": [
[
{
"node": "Stop and Error",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "geofeed",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
{
"name": "bunnycdn",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
{
"name": "webhook",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"triggerCount": 0,
"updatedAt": "2024-01-01T00:00:00.000Z",
"versionId": "2"
}