init after v1 corruption
This commit is contained in:
376
workflows/cSg8UMX1OvzDoLrk.json
Normal file
376
workflows/cSg8UMX1OvzDoLrk.json
Normal file
@@ -0,0 +1,376 @@
|
||||
{
|
||||
"id": "cSg8UMX1OvzDoLrk",
|
||||
"name": "EVE Bazaar Ingest",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"rule": {
|
||||
"interval": [
|
||||
{
|
||||
"field": "minutes",
|
||||
"minutesInterval": 15
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "Schedule Trigger",
|
||||
"name": "Schedule Trigger",
|
||||
"position": [
|
||||
0,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.scheduleTrigger",
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://forums.eveonline.com/c/marketplace/character-bazaar/60.rss",
|
||||
"options": {}
|
||||
},
|
||||
"id": "RSS Feed Read",
|
||||
"name": "RSS Feed Read",
|
||||
"position": [
|
||||
224,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.rssFeedRead",
|
||||
"typeVersion": 1.2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "return $input.all().filter(item => {\n const title = (item.json.title || \"\").toUpperCase();\n return title.includes(\"WTS\") && !title.includes(\"WTB\");\n});"
|
||||
},
|
||||
"id": "Filter WTS",
|
||||
"name": "Filter WTS",
|
||||
"position": [
|
||||
448,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const content = item.json.content || item.json.contentSnippet || \"\";\n const link = item.json.link || \"\";\n const text = content + \" \" + link;\n \n let charId = null;\n let skillqUrl = null;\n \n const patterns = [\n /evewho\\.com\\/character\\/(\\d+)/,\n /zkillboard\\.com\\/character\\/(\\d+)/,\n /qsna\\.eu\\/eve\\/characters?\\/(\\d+)/,\n /eveboard\\.com\\/pilot\\/([^\\/]+)/,\n /images\\.evetech\\.net\\/characters\\/(\\d+)\\//\n ];\n \n for (const pattern of patterns) {\n const match = text.match(pattern);\n if (match) {\n charId = match[1];\n break;\n }\n }\n \n // Look for SkillQ URL if no ID found\n if (!charId) {\n // Updated regex to require /share/ component and capture full path\n const skillqMatch = text.match(/skillq\\.net\\/char\\/([^\\/]+)\\/share\\/([a-f0-9\\-]+)/);\n if (skillqMatch) {\n // Construct full URL with share token\n // match[1] is name, match[2] is token\n skillqUrl = `https://skillq.net/char/${skillqMatch[1]}/share/${skillqMatch[2]}`;\n }\n }\n \n return {\n json: {\n ...item.json,\n character_id: charId,\n skillq_url: skillqUrl\n }\n };\n});"
|
||||
},
|
||||
"id": "Extract Character ID",
|
||||
"name": "Extract Character ID",
|
||||
"position": [
|
||||
672,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const items = $input.all();\nconst ids = items.map(item => item.json.post_id).filter(id => id);\nreturn [{\n json: {\n ids: ids\n }\n}];"
|
||||
},
|
||||
"id": "Prepare ID List",
|
||||
"name": "Prepare ID List",
|
||||
"position": [
|
||||
2016,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "executeQuery",
|
||||
"query": "SELECT * FROM character_bazaar_posts WHERE post_id IN ('{{ $json.ids.join(\"','\") }}')",
|
||||
"options": {}
|
||||
},
|
||||
"id": "Lookup Posts",
|
||||
"name": "Lookup Posts",
|
||||
"position": [
|
||||
2240,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.postgres",
|
||||
"typeVersion": 2.4,
|
||||
"alwaysOutputData": true,
|
||||
"credentials": {
|
||||
"postgres": {
|
||||
"id": "dsnKfvOBMkgU21Lt",
|
||||
"name": "supabase postgres account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "return $input.all().map(item => {\n const json = item.json;\n const escape = (str) => str ? str.replace(/'/g, \"''\") : '';\n \n const post_id = escape(json.post_id);\n const title = escape(json.title);\n const url = escape(json.url);\n const author = escape(json.author);\n const content = escape(json.content);\n const character_id = json.character_id ? `'${json.character_id}'` : 'NULL';\n\n const query = `INSERT INTO character_bazaar_posts (post_id, title, url, author, content, post_status, character_id)\nVALUES ('${post_id}', '${title}', '${url}', '${author}', '${content}', 'new', ${character_id})\nON CONFLICT (post_id) DO UPDATE SET\ntitle = EXCLUDED.title,\nurl = EXCLUDED.url,\nauthor = EXCLUDED.author,\ncontent = EXCLUDED.content,\npost_status = 'updated',\ncharacter_id = EXCLUDED.character_id;`;\n\n return {\n json: {\n ...json,\n query\n }\n };\n});"
|
||||
},
|
||||
"id": "Routing",
|
||||
"name": "Routing",
|
||||
"position": [
|
||||
2464,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "executeQuery",
|
||||
"query": "={{ $json.query }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "Store Results",
|
||||
"name": "Store Results",
|
||||
"position": [
|
||||
2688,
|
||||
-24
|
||||
],
|
||||
"type": "n8n-nodes-base.postgres",
|
||||
"typeVersion": 2.4,
|
||||
"credentials": {
|
||||
"postgres": {
|
||||
"id": "dsnKfvOBMkgU21Lt",
|
||||
"name": "supabase postgres account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"boolean": [
|
||||
{
|
||||
"value1": "={{ $json.skillq_url && !$json.character_id }}",
|
||||
"value2": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "If SkillQ Repair",
|
||||
"name": "If SkillQ Repair",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
896,
|
||||
-24
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "={{ $json.skillq_url }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "Scrape SkillQ",
|
||||
"name": "Scrape SkillQ",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.1,
|
||||
"position": [
|
||||
1120,
|
||||
-24
|
||||
],
|
||||
"onError": "continueRegularOutput"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const items = $input.all();\n\nreturn items.map(item => {\n // HTML should be in skillq_html (from Scrape SkillQ) or data/body\n const html = item.json.skillq_html || item.json.data || item.json.body;\n \n let charId = null;\n let error = null;\n \n try {\n if (html && typeof html === 'string') {\n const match = html.match(/images\\.evetech\\.net\\/characters\\/(\\d+)\\//);\n if (match) {\n charId = match[1];\n } else {\n error = \"Could not find character ID in SkillQ page\";\n }\n } else {\n error = \"Invalid or empty response from SkillQ\";\n }\n } catch (e) {\n error = \"Error parsing SkillQ response: \" + e.message;\n }\n \n return {\n json: {\n ...item.json, // Keep all original data (merged from context)\n character_id: charId || item.json.character_id,\n scraping_error: error\n }\n };\n});"
|
||||
},
|
||||
"id": "Parse Scraped ID",
|
||||
"name": "Parse Scraped ID",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1568,
|
||||
-96
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "let scraped = [];\ntry {\n // Try to get items from Parse Scraped ID\n // This will throw if the node hasn't executed (e.g. no items went to True branch)\n scraped = $('Parse Scraped ID').all();\n} catch (e) {\n // Node didn't execute, which is fine\n scraped = [];\n}\n\nconst skipped = $('If SkillQ Repair').all(1); // Get False branch items\n\nreturn [...scraped, ...skipped];"
|
||||
},
|
||||
"id": "Merge Manual",
|
||||
"name": "Merge Manual",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1792,
|
||||
-24
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "combine",
|
||||
"combineBy": "combineByPosition",
|
||||
"options": {}
|
||||
},
|
||||
"id": "Merge Context",
|
||||
"name": "Merge Context",
|
||||
"type": "n8n-nodes-base.merge",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
1344,
|
||||
-96
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Extract Character ID": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "If SkillQ Repair",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Filter WTS": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "Extract Character ID",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Lookup Posts": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "Routing",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare ID List": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "Lookup Posts",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"RSS Feed Read": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "Filter WTS",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Routing": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "Store Results",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Schedule Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"index": 0,
|
||||
"node": "RSS Feed Read",
|
||||
"type": "main"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"If SkillQ Repair": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Scrape SkillQ",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Merge Context",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Merge Manual",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Parse Scraped ID": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Merge Manual",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Merge Manual": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Prepare ID List",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Scrape SkillQ": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Merge Context",
|
||||
"type": "main",
|
||||
"index": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Merge Context": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Parse Scraped ID",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1",
|
||||
"saveDataErrorExecution": "all",
|
||||
"saveDataSuccessExecution": "all",
|
||||
"saveManualExecutions": true,
|
||||
"saveExecutionProgress": true,
|
||||
"callerPolicy": "workflowsFromSameOwner",
|
||||
"availableInMCP": false
|
||||
},
|
||||
"triggerCount": 0,
|
||||
"versionId": "51b5294b-1a43-4f17-a9e2-440a026e24fd",
|
||||
"owner": {
|
||||
"type": "personal",
|
||||
"projectId": "FeLO36wNUAcn61Wj",
|
||||
"projectName": "Ben W <admin@ben.io>",
|
||||
"personalEmail": "admin@ben.io"
|
||||
},
|
||||
"parentFolderId": "HWgaFb7kLF649L7l",
|
||||
"isArchived": false
|
||||
}
|
||||
Reference in New Issue
Block a user