workflows/04-market-dashboard.json Repository StreszCzarka---Krypto-AI-news-serwis Original path workflows/04-market-dashboard.jsonRole CONFIG Size 17831 bytes Lines 567 SHA-256 5b768fa8defc61b2b51a392765df4460696678f4d01c543d436c6626f4f3cc30Displayed range 1–500 Previous file/page · Project index · Next file/page
{
"name": "StreszCzarka - market dashboard",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-224,
384
],
"id": "63a7d5dc-cf2d-4a6e-9b02-bc326695326a",
"name": "Schedule Trigger"
},
{
"parameters": {
"jsCode": "const raw = ($input.first().json.content ?? \"\").toString();\n\nconst commodities = [\"Gold\", \"Silver\", \"Platinum\", \"Copper\", \"Neodymium\", \"Uranium\"];\n\n// pomocnicze funkcje\nfunction cleanNumber(str) {\n if (!str) return null;\n return parseFloat(str.replace(\",\", \".\").replace(\"%\", \"\").trim());\n}\n\n// regex dopasowujący wiersz z dowolnym miesiącem\nfunction extractRow(text, name) {\n const monthRegex = \"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec\";\n const regex = new RegExp(`${name}[\\\\s\\\\S]*?(${monthRegex}\\\\/\\\\d{1,4})`, \"i\");\n const match = text.match(regex);\n if (!match) return null;\n return match[0];\n}\n\nfunction parseRow(row, name) {\n const tokens = row.split(/\\s+/).filter(Boolean);\n\n const unit = tokens[1] || \"\";\n const price = cleanNumber(tokens[2]);\n const day = cleanNumber(tokens[3]);\n const pct = cleanNumber(tokens[4]);\n const weekly = cleanNumber(tokens[5]);\n const monthly = cleanNumber(tokens[6]);\n const ytd = cleanNumber(tokens[7]);\n const yoy = cleanNumber(tokens[8]);\n const date = tokens[tokens.length - 1];\n\n const summary =\n `${name} (${unit}) → ` +\n `Price: ${price} | ` +\n `Daily: ${day} | ` +\n `Change: ${pct}% | ` +\n `Weekly: ${weekly}% | ` +\n `Monthly: ${monthly}% | ` +\n `YTD: ${ytd}% | ` +\n `YoY: ${yoy}% | ` +\n `Date: ${date}`;\n\n return {\n commodity: name,\n summary,\n raw: row\n };\n}\n\nconst results = [];\n\nfor (const name of commodities) {\n const row = extractRow(raw, name);\n if (row) {\n results.push({ json: parseRow(row, name) });\n } else {\n results.push({ json: { commodity: name, summary: \"Not found\", raw: \"\" } });\n }\n}\n\nreturn results;\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
0
],
"id": "4b125f66-afb2-426c-8158-98ae6927d67c",
"name": "wycinator tekstu"
},
{
"parameters": {
"operation": "update",
"tableId": "dashboard",
"matchType": "allFilters",
"filters": {
"conditions": [
{
"keyName": "title",
"condition": "eq",
"keyValue": "={{ $json.commodity }}"
}
]
},
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $json.summary }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
448,
0
],
"id": "2004c2d0-53c4-4cf3-9b16-8372359e9b39",
"name": "Update a row"
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.STRESZCZARKA_EXTRACTOR_URL + '/extract' }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "X-API-Key",
"value": "={{ $env.STRESZCZARKA_INTERNAL_API_KEY }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "=https://tradingeconomics.com/commodities"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
0
],
"id": "ac7ec2cc-2025-4481-b46f-c08b2f6a6e79",
"name": "pobierator surowców",
"retryOnFail": true,
"maxTries": 5,
"waitBetweenTries": 5000
},
{
"parameters": {
"jsCode": "const raw = ($input.first().json.content ?? \"\").toString();\n\n// Mapowanie pełnej nazwy indeksu na możliwe warianty w tekście\nconst indexesMap = {\n \"S&P 500\": [\"S&P 500\"],\n \"Nasdaq Composite\": [\"Nasdaq\", \"Nasdaq Composite\"],\n \"Dow Jones Industrial Average\": [\"Dow Jones\", \"Dow Jones Industrial Average\"],\n \"DAX\": [\"DAX\", \"DAX PERFORMANCE-INDEX\"],\n \"Nikkei 225\": [\"Nikkei 225\"],\n \"Hang Seng Index\": [\"Hang Seng Index\"]\n};\n\nfunction extractLatestIndexFlexible(text, nameVariants) {\n let lastMatch = null;\n\n for (const variant of nameVariants) {\n // Dopasowujemy cenę i dwie kolejne linie\n const regex = new RegExp(\n `${variant}\\\\s*\\\\n\\\\s*(\\\\d{1,3}(?:,\\\\d{3})*(?:\\\\.\\\\d{2})?)\\\\s*\\\\n\\\\s*([+-]?[\\\\d.,]+)\\\\s*\\\\n\\\\s*([+-]?[\\\\d.,]+%?)`,\n \"gi\"\n );\n\n let match;\n while ((match = regex.exec(text)) !== null) {\n lastMatch = match;\n }\n }\n\n if (!lastMatch) return null;\n\n const price = parseFloat(lastMatch[1].replace(/,/g, \"\"));\n\n // Rozpoznaj, która linia to procent, która nominalna\n let line2 = lastMatch[2];\n let line3 = lastMatch[3];\n let changeAbs, changePct;\n\n if (line2.includes(\"%\")) {\n changePct = line2;\n changeAbs = parseFloat(line3.replace(/,/g, \"\"));\n } else if (line3.includes(\"%\")) {\n changePct = line3;\n changeAbs = parseFloat(line2.replace(/,/g, \"\"));\n } else {\n // Jeśli żadna linia nie ma %, bierzemy domyślnie line3 jako procent\n changePct = line3;\n changeAbs = parseFloat(line2.replace(/,/g, \"\"));\n }\n\n const summary = `${nameVariants[0]}: ${price} pkt, zmiana ${changeAbs} (${changePct})`;\n\n return {\n index: nameVariants[0],\n price,\n changeAbs,\n changePct,\n summary\n };\n}\n\nconst results = [];\n\nfor (const [fullName, variants] of Object.entries(indexesMap)) {\n const data = extractLatestIndexFlexible(raw, variants);\n if (data) {\n results.push({ json: data });\n } else {\n results.push({ json: { index: fullName, error: \"Not found\" } });\n }\n}\n\nreturn results;\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
192
],
"id": "a0021291-0a00-4b3d-ae96-a536506b048a",
"name": "indeksy"
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.STRESZCZARKA_EXTRACTOR_URL + '/extract' }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "X-API-Key",
"value": "={{ $env.STRESZCZARKA_INTERNAL_API_KEY }}"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "=https://www.google.com/finance/markets/indexes"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
192
],
"id": "3525b262-0af4-43ac-b4db-f3805763784b",
"name": "pobierator indeksów",
"retryOnFail": true,
"maxTries": 5,
"waitBetweenTries": 5000
},
{
"parameters": {
"operation": "update",
"tableId": "dashboard",
"matchType": "allFilters",
"filters": {
"conditions": [
{
"keyName": "title",
"condition": "eq",
"keyValue": "={{ $json.index }}"
}
]
},
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $json.summary }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
448,
192
],
"id": "85cbb02c-f732-45ba-9ce1-ece31713948c",
"name": "indeksy1"
},
{
"parameters": {
"url": "={{ $env.STRESZCZARKA_MARKETS_API_URL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
848
],
"id": "e20f3072-fb8c-4025-86a7-4ab9f3d6eceb",
"name": "pobierator curlów",
"retryOnFail": true,
"maxTries": 5,
"waitBetweenTries": 5000
},
{
"parameters": {
"operation": "update",
"tableId": "dashboard",
"matchType": "allFilters",
"filters": {
"conditions": [
{
"keyName": "title",
"condition": "eq",
"keyValue": "={{ $json.title }}"
}
]
},
"fieldsUi": {
"fieldValues": [
{
"fieldId": "title",
"fieldValue": "={{ $json.title }}"
},
{
"fieldId": "content",
"fieldValue": "={{ $json.content }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
448,
848
],
"id": "b8c261f4-072f-4e11-b96c-b3d497319ac6",
"name": "c url update"
},
{
"parameters": {
"jsCode": "// Wejściem jest jeden obiekt w tablicy, jak w Twoim przykładzie\nconst input = items[0].json;\n\n// Tworzymy nową tablicę rekordów\nconst output = Object.entries(input).map(([title, data]) => {\n return {\n json: {\n title,\n content: data.price // tylko cena\n // jeśli chcesz też link wrzucać, dodaj np. link: data.link\n }\n };\n});\n\nreturn output;\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
848
],
"id": "893cbd59-9331-4c32-a528-1f603b8f4783",
"name": "waluty"
},
{
"parameters": {
"operation": "update",
"tableId": "dashboard",
"matchType": "allFilters",
"filters": {
"conditions": [
{
"keyName": "title",
"condition": "eq",
"keyValue": "=BTC/USD"
}
]
},
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $json.current_price }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
448,
368
],
"id": "2d682a43-d8e8-47f2-ad7a-11436e877d3a",
"name": "btc update"
},
{
"parameters": {
"jsCode": "let currentPrice = null;\n\n// Sprawdźmy, czy items[0].json jest tablicą\nif (Array.isArray(items[0].json)) {\n currentPrice = items[0].json[0]?.current_price ?? null;\n} else {\n // Jeśli JSON jest obiektem\n currentPrice = items[0].json.current_price ?? null;\n}\n\nreturn [\n {\n json: {\n current_price: currentPrice\n }\n }\n];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
368
],
"id": "b1a021b7-a1e7-457a-ba83-c436a3ba0b99",
"name": "Code in JavaScript"
},
{
"parameters": {
"url": "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=bitcoin&price_change_percentage=24h,7d",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "User-Agent",
"value": "User-Agent"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
368
],
"id": "dd336d5f-5c44-431f-94a5-ad34190d57b8",
"name": "BTC"
},
{
"parameters": {
"url": "https://home.treasury.gov/sites/default/files/interest-rates/yield.xml",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "User-Agent",
"value": "User-Agent"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
560
],
"id": "2b5c7f53-507c-491c-8d73-5ed1e87dda28",
"name": "BTC1"
},
{
"parameters": {
"jsCode": "// Pobieramy XML ze stringa\nconst xmlString = items[0].json.data;\n\n// Szukamy wartośći <BC_10YEAR>\nconst match = xmlString.match(/<BC_10YEAR>([\\d.]+)<\\/BC_10YEAR>/);\n\nlet bc10Year = null;\n\nif (match && match[1]) {\n bc10Year = match[1] + \"%\"; // dodajemy znak %\n}\n\nreturn [\n {\n json: {\n BC_10YEAR: bc10Year\n }\n }\n];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
560
],
"id": "6a50ff79-7920-4405-9f22-92762f48e521",
"name": "bondy"
},
{
"parameters": {
"operation": "update",
"tableId": "dashboard",
"matchType": "allFilters",
"filters": {
"conditions": [
{
"keyName": "title",
"condition": "eq",
"keyValue": "=US 10Y Bond"
}
]
},
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $json.BC_10YEAR }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
448,
560
],
"id": "cd9f631b-d487-42a3-8624-47c4ad896340",
"name": "update bonda"
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "BTC1",
"type": "main",
"index": 0
},
{
"node": "pobierator surowców",
"type": "main",
"index": 0
},
{
"node": "pobierator indeksów",
"type": "main",
"index": 0
},
{
"node": "BTC",
"type": "main",
"index": 0
},
{
"node": "pobierator curlów",
"type": "main",
"index": 0
}
]
]
},
"wycinator tekstu": {
"main": [
[
{
"node": "Update a row",
"type": "main",
"index": 0
}
]
]
},
"pobierator surowców": {
"main": [
[
{
"node": "wycinator tekstu",
"type": "main",
"index": 0
}
]
]
},
"indeksy": {
"main": [
[
{
"node": "indeksy1",
"type": "main",
"index": 0
}
]
]
},
"pobierator indeksów": {
"main": [
[
{
"node": "indeksy",
"type": "main",
"index": 0
}
]
]
},
"pobierator curlów": {
"main": [
[
{
"node": "waluty",
"type": "main",