{ "nodes": [ { "name": "HTML Extract", "type": "n8n-nodes-base.htmlExtract", "position": [ -220, -390 ], "parameters": { "options": {}, "extractionValues": { "values": [ { "key": "price", "cssSelector": "={{$node[\"initItem\"].json[\"selector\"]}}" } ] } }, "typeVersion": 1 }, { "name": "Cron", "type": "n8n-nodes-base.cron", "position": [ -1290, -390 ], "parameters": { "triggerTimes": { "item": [ { "mode": "everyX", "unit": "minutes", "value": 15 } ] } }, "typeVersion": 1 }, { "name": "getActualPrice", "type": "n8n-nodes-base.functionItem", "position": [ -20, -390 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar price = String(item.price).replace(\",\", \".\");\nprice = parseFloat(price);\n//price = price.replace(/\\D/g, '');\n//item.price = String(item.price).replace(\",\", \".\");\n//item.price = parseFloat(item.price);\n\nitem.priceExists = (price > 0 ? true : false)\nitem.price = price;\n\n// Update its data\nglobalData.actualPrice = item;\n\nreturn item;" }, "typeVersion": 1 }, { "name": "fetchWeb", "type": "n8n-nodes-base.httpRequest", "position": [ -410, -390 ], "parameters": { "url": "={{$node[\"initItem\"].json[\"link\"]}}", "options": {}, "responseFormat": "string" }, "typeVersion": 1 }, { "name": "FunctionItem", "type": "n8n-nodes-base.functionItem", "position": [ 1020, -390 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\nglobalData.iteration = 0;\n//var thiselem = $node[\"initItem\"].json;\n\n//const s1 = {'slug': thiselem.slug, \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n//const s2 = {'slug': thiselem.slug+'2', \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n//const s3 = {'slug': thiselem.slug+'3', \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n\nreturn $node[\"changeME\"].json.myWatchers;\n" }, "typeVersion": 1 }, { "name": "Write Binary File1", "type": "n8n-nodes-base.writeBinaryFile", "position": [ 1850, -390 ], "parameters": { "fileName": "/data/kopacky.json", "dataPropertyName": "=price" }, "typeVersion": 1 }, { "name": "Move Binary Data1", "type": "n8n-nodes-base.moveBinaryData", "position": [ 1420, -390 ], "parameters": { "mode": "jsonToBinary", "options": {}, "destinationKey": "price" }, "typeVersion": 1 }, { "name": "IF1", "type": "n8n-nodes-base.if", "position": [ 550, -370 ], "parameters": { "conditions": { "string": [ { "value1": "={{$node[\"checkifexists\"].json[\"stdout\"]}}", "value2": "Exists", "operation": "notEqual" } ] } }, "typeVersion": 1 }, { "name": "checkifexists", "type": "n8n-nodes-base.executeCommand", "position": [ 410, -370 ], "parameters": { "command": "if [ -r /data/kopacky.json ]; then echo Exists; fi" }, "typeVersion": 1 }, { "name": "IF3", "type": "n8n-nodes-base.if", "position": [ 680, 110 ], "parameters": { "conditions": { "string": [ { "value1": "={{$node[\"checkifexists\"].json[\"stdout\"]}}", "value2": "Exists" } ] } }, "typeVersion": 1 }, { "name": "SaveToFile", "type": "n8n-nodes-base.writeBinaryFile", "position": [ 1650, 110 ], "parameters": { "fileName": "/data/kopacky.json", "dataPropertyName": "=price" }, "typeVersion": 1 }, { "name": "JsonToBinary", "type": "n8n-nodes-base.moveBinaryData", "position": [ 1500, 110 ], "parameters": { "mode": "jsonToBinary", "options": {}, "destinationKey": "price" }, "typeVersion": 1 }, { "name": "changeME", "type": "n8n-nodes-base.functionItem", "color": "#3BDD33", "position": [ -830, -390 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\n//{'slug': 'kopacky', 'link': 'https://www.adsport.sk/kopacky-lisovky-adidas-x-19-3-ll-fg-ef0598/#1131861', 'currency': 'EUR'}[]\nvar myWatchers = [\n{'slug': 'kopacky', 'link': 'https://www.adsport.sk/kopacky-lisovky-adidas-x-19-3-ll-fg-ef0598/#1131861', 'selector':'.prices > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'},\n{'slug': 'kopacky2', 'link': 'https://www.adsport.sk/turfy-adidas-ace-tango-17-3-tf-by2203/', 'selector':'.col-xs-4 > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'},\n{'slug': 'mobilcek', 'link': 'https://mobil.bazos.sk/inzerat/112253662/predam-odolny-doogee-s60-52-4g-lte-nfc.php', 'selector':'.listadvlevo > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(5) > td:nth-child(2) > b:nth-child(2)', 'currency': 'EUR'},\n{'slug': 'ADIZERO RC 2', 'link': 'https://www.adsport.sk/panske-bezecke-topanky-adidas-adizero-rc-2-eg1187/', 'selector':'.col-xs-4 > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'}\n];\n\nitem.myWatchers = myWatchers;\nitem.watchersCount = myWatchers.length;\nglobalData.myWatchers = myWatchers;\n\nreturn item;" }, "typeVersion": 1 }, { "name": "initItem", "type": "n8n-nodes-base.functionItem", "position": [ -620, -390 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar counter = globalData.iteration;\n\nitem.myWatchers[counter].watchersCount = item.watchersCount;\nitem.myWatchers[counter].canContinue = (globalData.iteration < item.watchersCount-1 ? true : false);\n//item.myWatchers[counter].canContinue = false;\n\nglobalData.iteration = counter + 1;\n\nreturn item.myWatchers[counter];" }, "typeVersion": 1 }, { "name": "savedItems", "type": "n8n-nodes-base.readBinaryFile", "position": [ 850, -20 ], "parameters": { "filePath": "/data/kopacky.json", "dataPropertyName": "savedItems" }, "typeVersion": 1, "continueOnFail": true, "alwaysOutputData": true }, { "name": "itemsToJSON", "type": "n8n-nodes-base.moveBinaryData", "position": [ 1020, -20 ], "parameters": { "options": {}, "sourceKey": "savedItems" }, "typeVersion": 1 }, { "name": "IF", "type": "n8n-nodes-base.if", "position": [ 2190, -90 ], "parameters": { "conditions": { "string": [], "boolean": [ { "value1": "={{$node[\"initItem\"].json[\"canContinue\"]}}", "value2": true } ] } }, "typeVersion": 1 }, { "name": "initItem1", "type": "n8n-nodes-base.functionItem", "position": [ -1060, -390 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\nglobalData.iteration = 0;\n\nreturn item;" }, "typeVersion": 1 }, { "name": "IF2", "type": "n8n-nodes-base.if", "position": [ 1850, 110 ], "parameters": { "conditions": { "number": [ { "value1": "={{$node[\"getActualPrice\"].json[\"price\"]}}", "value2": "={{$node[\"updateSavedItems1\"].json[\"oldPrice\"]}}" } ], "string": [] } }, "typeVersion": 1 }, { "name": "updateSavedItems", "type": "n8n-nodes-base.functionItem", "position": [ 1350, 110 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar myitems = [];\nvar i;\nfor (i = 0; i < item.items.length; i++) { \n if($node[\"initItem\"].json.slug == item.items[i].slug && $node[\"getActualPrice\"].json.price < item.items[i].price) {\n item.items[i].price = $node[\"getActualPrice\"].json.price;\n }\n myitems.push(item.items[i]);\n} \n\nreturn myitems;\n" }, "typeVersion": 1 }, { "name": "updateSavedItems1", "type": "n8n-nodes-base.functionItem", "position": [ 1200, -20 ], "parameters": { "functionCode": "const globalData = getWorkflowStaticData('global');\nvar oldPrice = null;\nvar myitems = [];\nvar i;\nfor (i = 0; i < item.length; i++) {\n if($node[\"initItem\"].json.slug == item[i].slug) {\n\n item[i].link = $node[\"initItem\"].json.link;\n item[i].selector = $node[\"initItem\"].json.selector;\n item[i].currency = $node[\"initItem\"].json.currency;\n \n if(!item[i].price){\n item[i].price = $node[\"getActualPrice\"].json.price;\n }\n \n if($node[\"getActualPrice\"].json.price < item[i].price){\n oldPrice = item[i].price;\n item[i].price = $node[\"getActualPrice\"].json.price;\n }\n \n \n }\n \n myitems.push(item[i]);\n} \n\n//item.somar = $node[\"initItem\"].json;\n//return globalData.actualPrice;\n\nvar itemm = {};\nitemm.items = myitems;\nitemm.oldPrice = oldPrice;\nreturn itemm;\n" }, "typeVersion": 1 }, { "name": "cleanData", "type": "n8n-nodes-base.executeCommand", "notes": "This will remove all storaged data.", "position": [ -1290, -560 ], "parameters": { "command": "file=\"/data/kopacky.json\"\n[ -f $file ] && rm $file" }, "typeVersion": 1 }, { "name": "IF4", "type": "n8n-nodes-base.if", "position": [ 150, -390 ], "parameters": { "conditions": { "string": [], "boolean": [ { "value1": "={{$node[\"getActualPrice\"].json[\"priceExists\"]}}" } ] } }, "typeVersion": 1 }, { "name": "NotifyBetterPrice", "type": "n8n-nodes-base.emailSend", "position": [ 1850, -90 ], "parameters": { "html": "=

Nová cena je: {{$node[\"getActualPrice\"].json[\"price\"]}} {{$node[\"initItem\"].json[\"currency\"]}}


\nPôvodná cena bola: {{$node[\"updateSavedItems1\"].json[\"oldPrice\"]}} {{$node[\"initItem\"].json[\"currency\"]}}
\nURL: {{$node[\"initItem\"].json[\"link\"]}}", "text": "=", "options": {}, "subject": "=Nová cena - {{$node[\"initItem\"].json[\"slug\"]}} - {{$node[\"getActualPrice\"].json[\"price\"]}} {{$node[\"initItem\"].json[\"currency\"]}}", "toEmail": "sthosstudio@gmail.com", "fromEmail": "hostovecky@weyou.sk" }, "credentials": { "smtp": "hostovecky@weyou.sk" }, "typeVersion": 1 }, { "name": "NotifyIncorrectPrice", "type": "n8n-nodes-base.emailSend", "position": [ 270, -690 ], "parameters": { "html": "=Please check the link or selector for the item with slug {{$node[\"initItem\"].json[\"slug\"]}}
\nURL: {{$node[\"initItem\"].json[\"link\"]}}", "text": "=", "options": {}, "subject": "={{$node[\"initItem\"].json[\"slug\"]}} - Getting price issue.", "toEmail": "sthosstudio@gmail.com", "fromEmail": "hostovecky@weyou.sk" }, "credentials": { "smtp": "hostovecky@weyou.sk" }, "typeVersion": 1 } ], "connections": { "IF": { "main": [ [ { "node": "changeME", "type": "main", "index": 0 } ] ] }, "IF1": { "main": [ [ { "node": "FunctionItem", "type": "main", "index": 0 } ], [ { "node": "IF3", "type": "main", "index": 0 } ] ] }, "IF2": { "main": [ [ { "node": "NotifyBetterPrice", "type": "main", "index": 0 } ], [ { "node": "IF", "type": "main", "index": 0 } ] ] }, "IF3": { "main": [ [ { "node": "savedItems", "type": "main", "index": 0 } ] ] }, "IF4": { "main": [ [ { "node": "NotifyIncorrectPrice", "type": "main", "index": 0 } ], [ { "node": "checkifexists", "type": "main", "index": 0 } ] ] }, "Cron": { "main": [ [ { "node": "initItem1", "type": "main", "index": 0 } ] ] }, "changeME": { "main": [ [ { "node": "initItem", "type": "main", "index": 0 } ] ] }, "fetchWeb": { "main": [ [ { "node": "HTML Extract", "type": "main", "index": 0 } ] ] }, "initItem": { "main": [ [ { "node": "fetchWeb", "type": "main", "index": 0 } ] ] }, "initItem1": { "main": [ [ { "node": "changeME", "type": "main", "index": 0 } ] ] }, "SaveToFile": { "main": [ [ { "node": "IF2", "type": "main", "index": 0 } ] ] }, "savedItems": { "main": [ [ { "node": "itemsToJSON", "type": "main", "index": 0 } ] ] }, "itemsToJSON": { "main": [ [ { "node": "updateSavedItems1", "type": "main", "index": 0 } ] ] }, "FunctionItem": { "main": [ [ { "node": "Move Binary Data1", "type": "main", "index": 0 } ] ] }, "HTML Extract": { "main": [ [ { "node": "getActualPrice", "type": "main", "index": 0 } ] ] }, "JsonToBinary": { "main": [ [ { "node": "SaveToFile", "type": "main", "index": 0 } ] ] }, "checkifexists": { "main": [ [ { "node": "IF1", "type": "main", "index": 0 } ] ] }, "getActualPrice": { "main": [ [ { "node": "IF4", "type": "main", "index": 0 } ] ] }, "updateSavedItems": { "main": [ [ { "node": "JsonToBinary", "type": "main", "index": 0 } ] ] }, "Move Binary Data1": { "main": [ [ { "node": "Write Binary File1", "type": "main", "index": 0 } ] ] }, "NotifyBetterPrice": { "main": [ [ { "node": "IF", "type": "main", "index": 0 } ] ] }, "updateSavedItems1": { "main": [ [ { "node": "updateSavedItems", "type": "main", "index": 0 } ] ] }, "Write Binary File1": { "main": [ [ { "node": "IF", "type": "main", "index": 0 } ] ] }, "NotifyIncorrectPrice": { "main": [ [ { "node": "checkifexists", "type": "main", "index": 0 } ] ] } } }