diff --git a/node_red_data/.gitignore b/node_red_data/.gitignore index 11ceecf..853cb39 100644 --- a/node_red_data/.gitignore +++ b/node_red_data/.gitignore @@ -3,4 +3,3 @@ node_modules .*.json .npm flows_cred.json -settings.js diff --git a/node_red_data/flows.json b/node_red_data/flows.json index b50cf48..80a3d1d 100644 --- a/node_red_data/flows.json +++ b/node_red_data/flows.json @@ -1 +1,879 @@ -[{"id":"e79fd0e1.60f55","type":"tab","label":"Get last Netflix Invoice and convert it as PDF","disabled":false,"info":""},{"id":"34256184.7e2b8e","type":"tab","label":"Post a invoice on Leeto","disabled":false,"info":""},{"id":"f120e3b1.f67b38","type":"inject","z":"e79fd0e1.60f55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":40,"wires":[["bf25f228.3c6a5"]]},{"id":"a9e0512d.6cdd7","type":"http request","z":"e79fd0e1.60f55","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://www.netflix.com/BillingActivity","tls":"","persist":false,"proxy":"","authType":"","x":730,"y":100,"wires":[["e03ca39e.a9af28"]],"info":"Get invoice page from Netflix"},{"id":"6d4fb2bd.73cc2c","type":"function","z":"e79fd0e1.60f55","name":"HTTP Headers for Netflix","func":"msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Cookie'] = [\n 'SecureNetflixId=' + msg.secureNetflixId,\n 'NetflixId=' + msg.netflixId,\n].join(';');\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":390,"y":100,"wires":[["4c67f40c.bede9c"]]},{"id":"bf25f228.3c6a5","type":"credentials","z":"e79fd0e1.60f55","name":"Netflix Credentials","props":[{"value":"netflixId","type":"msg"},{"value":"secureNetflixId","type":"msg"}],"x":170,"y":100,"wires":[["6d4fb2bd.73cc2c"]]},{"id":"e03ca39e.a9af28","type":"function","z":"e79fd0e1.60f55","name":"Parse Netflix Billing Page","func":"return {\n url: 'https://www.netflix.com' + /\\/invoice\\/print\\/[^\"]*/.exec(msg.payload)\n};","outputs":1,"noerr":0,"initialize":"","finalize":"","x":390,"y":180,"wires":[["bf25f228.3c6a5","8e61a051.3430c8"]]},{"id":"7ddcb19f.58034","type":"http request","z":"e79fd0e1.60f55","name":"","method":"GET","ret":"txt","paytoqs":false,"url":"","persist":false,"authType":"","x":730,"y":180,"wires":[["b03fda42.1373b","690170f6.3fab38","174093e7.8794e4"]]},{"id":"4c67f40c.bede9c","type":"switch","z":"e79fd0e1.60f55","name":"","property":"url","propertyType":"msg","rules":[{"t":"null"},{"t":"nnull"}],"checkall":"false","repair":false,"outputs":2,"x":570,"y":100,"wires":[["a9e0512d.6cdd7"],["7ddcb19f.58034"]]},{"id":"b03fda42.1373b","type":"file","z":"e79fd0e1.60f55","name":"Save last invoice","filename":"/data/lastInvoice.html","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"utf8","x":990,"y":180,"wires":[[]]},{"id":"6d08e306.82ab1c","type":"file","z":"e79fd0e1.60f55","name":"Save last invoice as a pdf","filename":"/data/lastInvoice.pdf","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":1030,"y":400,"wires":[[]]},{"id":"5dab3bc3.1f8edc","type":"http request","z":"e79fd0e1.60f55","name":"Api Call for converting to PDF","method":"POST","ret":"bin","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1030,"y":300,"wires":[["6d08e306.82ab1c","d2bf2b71.93482"]]},{"id":"eb861026.5c287","type":"function","z":"e79fd0e1.60f55","name":"Config for url-to-pdf-api","func":"msg.headers = {};\nmsg.headers['Content-Type'] = 'text/html';\nmsg.headers['X-Api-Key'] = msg.apiToken;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":770,"y":300,"wires":[["5dab3bc3.1f8edc"]]},{"id":"690170f6.3fab38","type":"credentials","z":"e79fd0e1.60f55","name":"url-to-pdf-api Credentials","props":[{"value":"apiToken","type":"msg"},{"value":"url","type":"msg"}],"x":530,"y":300,"wires":[["eb861026.5c287"]]},{"id":"4c6af2dc.2504bc","type":"link out","z":"e79fd0e1.60f55","name":"Last Netflix Invoice as PDF","links":["848ba398.23bef8"],"x":455,"y":580,"wires":[]},{"id":"debc0868.c889a","type":"inject","z":"34256184.7e2b8e","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":120,"wires":[["ac7c6734.52f8f"]]},{"id":"cfd9259a.79e2a8","type":"credentials","z":"34256184.7e2b8e","name":"Leeto Credentials","props":[{"value":"email","type":"msg"},{"value":"password","type":"msg"}],"x":310,"y":300,"wires":[["e1a3a869.cb50a8"]]},{"id":"e1a3a869.cb50a8","type":"function","z":"34256184.7e2b8e","name":"Leeto payload for Login","func":"msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'application/json';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.payload = {\n user: {\n email: msg.email,\n password: msg.password\n }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":530,"y":300,"wires":[["38582789.81bb28"]]},{"id":"38582789.81bb28","type":"http request","z":"34256184.7e2b8e","name":"Connect to Leeto","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://api.leeto.co/api/v2/users/sign_in?locale=fr","tls":"","persist":false,"proxy":"","authType":"","x":750,"y":300,"wires":[["10c5487b.65eea8"]]},{"id":"ac7c6734.52f8f","type":"file in","z":"34256184.7e2b8e","name":"Test invoice","filename":"/data/test.pdf","format":"","chunk":false,"sendError":false,"encoding":"none","x":270,"y":120,"wires":[["ee1a1e10.8655a8"]]},{"id":"d7867c95.86491","type":"join","z":"34256184.7e2b8e","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":490,"y":580,"wires":[["17d03aa5.9a232d"]]},{"id":"10c5487b.65eea8","type":"change","z":"34256184.7e2b8e","name":"Mark as leetoUser","rules":[{"t":"set","p":"topic","pt":"msg","to":"leetoUser","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":340,"wires":[["d7867c95.86491","8e087080.9c07c8"]]},{"id":"65bdcfce.0c10e8","type":"change","z":"34256184.7e2b8e","name":"Mark as invoice","rules":[{"t":"set","p":"topic","pt":"msg","to":"invoice","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":420,"wires":[["d7867c95.86491"]]},{"id":"f5429dca.a2783","type":"http request","z":"34256184.7e2b8e","name":"Leeto Reimbursement Request","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":710,"y":660,"wires":[["337393c6.282844"]]},{"id":"5571d225.8e12dc","type":"function","z":"34256184.7e2b8e","name":"Leeto payload for reimbursement","func":"msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'multipart/form-data';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Authorization'] = 'Bearer ' + msg.payload.leetoUser.token;\nmsg.payload = {\n 'reimbursement_request[user_id]': msg.payload.leetoUser.id,\n 'reimbursement_request[grantable_id]': msg.payload.leetoUser.id,\n 'reimbursement_request[grantable_type]': 'User',\n 'reimbursement_request[amount]': msg.payload.invoice.amount,\n 'reimbursement_request[quotum_id]': msg.payload.benefit.data.period.quota[0].id,\n 'reimbursement_request[receipts_attributes][][image]': {\n value: msg.payload.invoice.file,\n options: {\n filename: msg.payload.invoice.filename,\n contentType: msg.payload.invoice.contentType,\n }\n }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":420,"y":660,"wires":[["f5429dca.a2783"]]},{"id":"337393c6.282844","type":"debug","z":"34256184.7e2b8e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":910,"y":660,"wires":[]},{"id":"38445ef0.73a4ca","type":"http request","z":"34256184.7e2b8e","name":"Leeto get benefit","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":1010,"y":440,"wires":[["6cb603b8.f9a93c"]]},{"id":"6cb603b8.f9a93c","type":"change","z":"34256184.7e2b8e","name":"Mark as benefit","rules":[{"t":"set","p":"topic","pt":"msg","to":"benefit","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1020,"y":520,"wires":[["d7867c95.86491"]]},{"id":"c63deac6.d6ff18","type":"function","z":"34256184.7e2b8e","name":"Leeto payload for get Benefit","func":"msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'multipart/form-data';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Authorization'] = 'Bearer ' + msg.payload.token;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":780,"y":440,"wires":[["38445ef0.73a4ca"]]},{"id":"8e087080.9c07c8","type":"template","z":"34256184.7e2b8e","name":"Build URL","field":"url","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"https://api.leeto.co/api/v2/organisations/{{payload.organisationId}}/users/{{payload.id}}/benefits/{{payload.authorizedBenefitIds.0}}?locale=fr","output":"str","x":580,"y":440,"wires":[["c63deac6.d6ff18"]]},{"id":"17d03aa5.9a232d","type":"template","z":"34256184.7e2b8e","name":"Build URL","field":"url","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"https://api.leeto.co/api/v2/organisations/{{payload.leetoUser.organisationId}}/reimbursement_requests?locale=fr","output":"str","x":200,"y":660,"wires":[["5571d225.8e12dc"]]},{"id":"848ba398.23bef8","type":"link in","z":"34256184.7e2b8e","name":"Trigged from Netflix Last Invoice","links":["4c6af2dc.2504bc"],"x":375,"y":180,"wires":[["65bdcfce.0c10e8","cfd9259a.79e2a8"]]},{"id":"ee1a1e10.8655a8","type":"change","z":"34256184.7e2b8e","name":"Test payload","rules":[{"t":"move","p":"payload","pt":"msg","to":"file","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.file","pt":"msg","to":"file","tot":"msg"},{"t":"set","p":"payload.filename","pt":"msg","to":"test.pdf","tot":"str"},{"t":"set","p":"payload.amount","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":120,"wires":[["cfd9259a.79e2a8","65bdcfce.0c10e8"]]},{"id":"174093e7.8794e4","type":"html","z":"e79fd0e1.60f55","name":"","property":"payload","outproperty":"payload","tag":".invoiceFooter dd","ret":"text","as":"multi","x":170,"y":400,"wires":[["5f5a3dc9.eab71c"]]},{"id":"6af264f9.2f99dc","type":"join","z":"e79fd0e1.60f55","name":"","mode":"custom","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":110,"y":540,"wires":[["643c6d17.cec784"]]},{"id":"d2bf2b71.93482","type":"change","z":"e79fd0e1.60f55","name":"Move as payload.file","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.file","tot":"msg"},{"t":"set","p":"payload.filename","pt":"msg","to":"netflix-invoice.pdf","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":400,"wires":[["6af264f9.2f99dc"]]},{"id":"73c55749.b6bf7","type":"debug","z":"e79fd0e1.60f55","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":520,"wires":[]},{"id":"8e61a051.3430c8","type":"debug","z":"e79fd0e1.60f55","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"url","targetType":"msg","statusVal":"","statusType":"auto","x":380,"y":220,"wires":[]},{"id":"5f5a3dc9.eab71c","type":"change","z":"e79fd0e1.60f55","name":"parse amount","rules":[{"t":"move","p":"payload","pt":"msg","to":"textAmount","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.amount","pt":"msg","to":"$number($replace($match(textAmount, /[0-9\\,]+/, 1).match, ',', '.'))","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":400,"wires":[["6af264f9.2f99dc"]]},{"id":"643c6d17.cec784","type":"function","z":"e79fd0e1.60f55","name":"Cleaning payload","func":"return {payload: msg.payload};","outputs":1,"noerr":0,"initialize":"","finalize":"","x":290,"y":540,"wires":[["73c55749.b6bf7","4c6af2dc.2504bc"]]}] \ No newline at end of file +[ + { + "id": "e79fd0e1.60f55", + "type": "tab", + "label": "Get last Netflix Invoice and convert it as PDF", + "disabled": false, + "info": "" + }, + { + "id": "34256184.7e2b8e", + "type": "tab", + "label": "Post a invoice on Leeto", + "disabled": false, + "info": "" + }, + { + "id": "f120e3b1.f67b38", + "type": "inject", + "z": "e79fd0e1.60f55", + "name": "", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 100, + "y": 40, + "wires": [ + [ + "bf25f228.3c6a5" + ] + ] + }, + { + "id": "a9e0512d.6cdd7", + "type": "http request", + "z": "e79fd0e1.60f55", + "name": "", + "method": "GET", + "ret": "txt", + "paytoqs": "ignore", + "url": "https://www.netflix.com/BillingActivity", + "tls": "", + "persist": false, + "proxy": "", + "authType": "", + "x": 730, + "y": 100, + "wires": [ + [ + "e03ca39e.a9af28" + ] + ], + "info": "Get invoice page from Netflix" + }, + { + "id": "6d4fb2bd.73cc2c", + "type": "function", + "z": "e79fd0e1.60f55", + "name": "HTTP Headers for Netflix", + "func": "msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Cookie'] = [\n 'SecureNetflixId=' + msg.secureNetflixId,\n 'NetflixId=' + msg.netflixId,\n].join(';');\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 390, + "y": 100, + "wires": [ + [ + "4c67f40c.bede9c" + ] + ] + }, + { + "id": "bf25f228.3c6a5", + "type": "credentials", + "z": "e79fd0e1.60f55", + "name": "Netflix Credentials", + "props": [ + { + "value": "netflixId", + "type": "msg" + }, + { + "value": "secureNetflixId", + "type": "msg" + } + ], + "x": 170, + "y": 100, + "wires": [ + [ + "6d4fb2bd.73cc2c" + ] + ] + }, + { + "id": "e03ca39e.a9af28", + "type": "function", + "z": "e79fd0e1.60f55", + "name": "Parse Netflix Billing Page", + "func": "return {\n url: 'https://www.netflix.com' + /\\/invoice\\/print\\/[^\"]*/.exec(msg.payload)\n};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 390, + "y": 180, + "wires": [ + [ + "bf25f228.3c6a5", + "8e61a051.3430c8" + ] + ] + }, + { + "id": "7ddcb19f.58034", + "type": "http request", + "z": "e79fd0e1.60f55", + "name": "", + "method": "GET", + "ret": "txt", + "paytoqs": false, + "url": "", + "persist": false, + "authType": "", + "x": 730, + "y": 180, + "wires": [ + [ + "b03fda42.1373b", + "690170f6.3fab38", + "174093e7.8794e4" + ] + ] + }, + { + "id": "4c67f40c.bede9c", + "type": "switch", + "z": "e79fd0e1.60f55", + "name": "", + "property": "url", + "propertyType": "msg", + "rules": [ + { + "t": "null" + }, + { + "t": "nnull" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 570, + "y": 100, + "wires": [ + [ + "a9e0512d.6cdd7" + ], + [ + "7ddcb19f.58034" + ] + ] + }, + { + "id": "b03fda42.1373b", + "type": "file", + "z": "e79fd0e1.60f55", + "name": "Save last invoice", + "filename": "/data/lastInvoice.html", + "appendNewline": false, + "createDir": false, + "overwriteFile": "true", + "encoding": "utf8", + "x": 990, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "6d08e306.82ab1c", + "type": "file", + "z": "e79fd0e1.60f55", + "name": "Save last invoice as a pdf", + "filename": "/data/lastInvoice.pdf", + "appendNewline": false, + "createDir": false, + "overwriteFile": "true", + "encoding": "none", + "x": 1030, + "y": 400, + "wires": [ + [] + ] + }, + { + "id": "5dab3bc3.1f8edc", + "type": "http request", + "z": "e79fd0e1.60f55", + "name": "Api Call for converting to PDF", + "method": "POST", + "ret": "bin", + "paytoqs": "ignore", + "url": "", + "tls": "", + "persist": false, + "proxy": "", + "authType": "", + "x": 1030, + "y": 300, + "wires": [ + [ + "6d08e306.82ab1c", + "d2bf2b71.93482" + ] + ] + }, + { + "id": "eb861026.5c287", + "type": "function", + "z": "e79fd0e1.60f55", + "name": "Config for url-to-pdf-api", + "func": "msg.headers = {};\nmsg.headers['Content-Type'] = 'text/html';\nmsg.headers['X-Api-Key'] = msg.apiToken;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 770, + "y": 300, + "wires": [ + [ + "5dab3bc3.1f8edc" + ] + ] + }, + { + "id": "690170f6.3fab38", + "type": "credentials", + "z": "e79fd0e1.60f55", + "name": "url-to-pdf-api Credentials", + "props": [ + { + "value": "apiToken", + "type": "msg" + }, + { + "value": "url", + "type": "msg" + } + ], + "x": 530, + "y": 300, + "wires": [ + [ + "eb861026.5c287" + ] + ] + }, + { + "id": "4c6af2dc.2504bc", + "type": "link out", + "z": "e79fd0e1.60f55", + "name": "Last Netflix Invoice as PDF", + "links": [ + "848ba398.23bef8" + ], + "x": 455, + "y": 580, + "wires": [] + }, + { + "id": "debc0868.c889a", + "type": "inject", + "z": "34256184.7e2b8e", + "name": "", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 180, + "y": 120, + "wires": [ + [ + "ac7c6734.52f8f" + ] + ] + }, + { + "id": "cfd9259a.79e2a8", + "type": "credentials", + "z": "34256184.7e2b8e", + "name": "Leeto Credentials", + "props": [ + { + "value": "email", + "type": "msg" + }, + { + "value": "password", + "type": "msg" + } + ], + "x": 380, + "y": 300, + "wires": [ + [ + "e1a3a869.cb50a8" + ] + ] + }, + { + "id": "e1a3a869.cb50a8", + "type": "function", + "z": "34256184.7e2b8e", + "name": "Leeto payload for Login", + "func": "msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'application/json';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.payload = {\n user: {\n email: msg.email,\n password: msg.password\n }\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 600, + "y": 300, + "wires": [ + [ + "38582789.81bb28" + ] + ] + }, + { + "id": "38582789.81bb28", + "type": "http request", + "z": "34256184.7e2b8e", + "name": "Connect to Leeto", + "method": "POST", + "ret": "obj", + "paytoqs": "ignore", + "url": "https://api.leeto.co/api/v2/users/sign_in?locale=fr", + "tls": "", + "persist": false, + "proxy": "", + "authType": "", + "x": 820, + "y": 300, + "wires": [ + [ + "10c5487b.65eea8" + ] + ] + }, + { + "id": "ac7c6734.52f8f", + "type": "file in", + "z": "34256184.7e2b8e", + "name": "Test invoice", + "filename": "/data/test.pdf", + "format": "", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 340, + "y": 120, + "wires": [ + [ + "ee1a1e10.8655a8" + ] + ] + }, + { + "id": "d7867c95.86491", + "type": "join", + "z": "34256184.7e2b8e", + "name": "", + "mode": "custom", + "build": "object", + "property": "payload", + "propertyType": "msg", + "key": "topic", + "joiner": "\\n", + "joinerType": "str", + "accumulate": false, + "timeout": "", + "count": "3", + "reduceRight": false, + "reduceExp": "", + "reduceInit": "", + "reduceInitType": "num", + "reduceFixup": "", + "x": 560, + "y": 580, + "wires": [ + [ + "17d03aa5.9a232d" + ] + ] + }, + { + "id": "10c5487b.65eea8", + "type": "change", + "z": "34256184.7e2b8e", + "name": "Mark as leetoUser", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "leetoUser", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1040, + "y": 340, + "wires": [ + [ + "d7867c95.86491", + "8e087080.9c07c8" + ] + ] + }, + { + "id": "65bdcfce.0c10e8", + "type": "change", + "z": "34256184.7e2b8e", + "name": "Mark as invoice", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "invoice", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 390, + "y": 420, + "wires": [ + [ + "d7867c95.86491" + ] + ] + }, + { + "id": "f5429dca.a2783", + "type": "http request", + "z": "34256184.7e2b8e", + "name": "Leeto Reimbursement Request", + "method": "POST", + "ret": "obj", + "paytoqs": "ignore", + "url": "", + "tls": "", + "persist": false, + "proxy": "", + "authType": "", + "x": 780, + "y": 660, + "wires": [ + [ + "337393c6.282844" + ] + ] + }, + { + "id": "5571d225.8e12dc", + "type": "function", + "z": "34256184.7e2b8e", + "name": "Leeto payload for reimbursement", + "func": "msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'multipart/form-data';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Authorization'] = 'Bearer ' + msg.payload.leetoUser.token;\nmsg.payload = {\n 'reimbursement_request[user_id]': msg.payload.leetoUser.id,\n 'reimbursement_request[grantable_id]': msg.payload.leetoUser.id,\n 'reimbursement_request[grantable_type]': 'User',\n 'reimbursement_request[amount]': msg.payload.invoice.amount,\n 'reimbursement_request[quotum_id]': msg.payload.benefit.data.period.quota[0].id,\n 'reimbursement_request[receipts_attributes][][image]': {\n value: msg.payload.invoice.file,\n options: {\n filename: msg.payload.invoice.filename,\n contentType: msg.payload.invoice.contentType,\n }\n }\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 490, + "y": 660, + "wires": [ + [ + "f5429dca.a2783" + ] + ] + }, + { + "id": "337393c6.282844", + "type": "debug", + "z": "34256184.7e2b8e", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 980, + "y": 660, + "wires": [] + }, + { + "id": "38445ef0.73a4ca", + "type": "http request", + "z": "34256184.7e2b8e", + "name": "Leeto get benefit", + "method": "GET", + "ret": "obj", + "paytoqs": "ignore", + "url": "", + "tls": "", + "persist": false, + "proxy": "", + "authType": "", + "x": 1080, + "y": 440, + "wires": [ + [ + "6cb603b8.f9a93c" + ] + ] + }, + { + "id": "6cb603b8.f9a93c", + "type": "change", + "z": "34256184.7e2b8e", + "name": "Mark as benefit", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "benefit", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1090, + "y": 520, + "wires": [ + [ + "d7867c95.86491" + ] + ] + }, + { + "id": "c63deac6.d6ff18", + "type": "function", + "z": "34256184.7e2b8e", + "name": "Leeto payload for get Benefit", + "func": "msg.headers = {};\nmsg.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0';\nmsg.headers['Content-Type'] = 'multipart/form-data';\nmsg.headers['Accept'] = 'application/json, text/plain, */*';\nmsg.headers['Accept-Language'] = 'fr-FR,fr;q=0.5';\nmsg.headers['Authorization'] = 'Bearer ' + msg.payload.token;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 850, + "y": 440, + "wires": [ + [ + "38445ef0.73a4ca" + ] + ] + }, + { + "id": "8e087080.9c07c8", + "type": "template", + "z": "34256184.7e2b8e", + "name": "Build URL", + "field": "url", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "https://api.leeto.co/api/v2/organisations/{{payload.organisationId}}/users/{{payload.id}}/benefits/{{payload.authorizedBenefitIds.0}}?locale=fr", + "output": "str", + "x": 650, + "y": 440, + "wires": [ + [ + "c63deac6.d6ff18" + ] + ] + }, + { + "id": "17d03aa5.9a232d", + "type": "template", + "z": "34256184.7e2b8e", + "name": "Build URL", + "field": "url", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "https://api.leeto.co/api/v2/organisations/{{payload.leetoUser.organisationId}}/reimbursement_requests?locale=fr", + "output": "str", + "x": 270, + "y": 660, + "wires": [ + [ + "5571d225.8e12dc" + ] + ] + }, + { + "id": "848ba398.23bef8", + "type": "link in", + "z": "34256184.7e2b8e", + "name": "Trigged from Netflix Last Invoice", + "links": [ + "4c6af2dc.2504bc" + ], + "x": 195, + "y": 360, + "wires": [ + [ + "65bdcfce.0c10e8", + "cfd9259a.79e2a8" + ] + ] + }, + { + "id": "ee1a1e10.8655a8", + "type": "change", + "z": "34256184.7e2b8e", + "name": "Test payload", + "rules": [ + { + "t": "move", + "p": "payload", + "pt": "msg", + "to": "file", + "tot": "msg" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{}", + "tot": "json" + }, + { + "t": "set", + "p": "payload.file", + "pt": "msg", + "to": "file", + "tot": "msg" + }, + { + "t": "set", + "p": "payload.filename", + "pt": "msg", + "to": "test.pdf", + "tot": "str" + }, + { + "t": "set", + "p": "payload.amount", + "pt": "msg", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 580, + "y": 120, + "wires": [ + [ + "cfd9259a.79e2a8", + "65bdcfce.0c10e8" + ] + ] + }, + { + "id": "174093e7.8794e4", + "type": "html", + "z": "e79fd0e1.60f55", + "name": "", + "property": "payload", + "outproperty": "payload", + "tag": ".invoiceFooter dd", + "ret": "text", + "as": "multi", + "x": 170, + "y": 400, + "wires": [ + [ + "5f5a3dc9.eab71c" + ] + ] + }, + { + "id": "6af264f9.2f99dc", + "type": "join", + "z": "e79fd0e1.60f55", + "name": "", + "mode": "custom", + "build": "merged", + "property": "payload", + "propertyType": "msg", + "key": "topic", + "joiner": "\\n", + "joinerType": "str", + "accumulate": false, + "timeout": "", + "count": "2", + "reduceRight": false, + "reduceExp": "", + "reduceInit": "", + "reduceInitType": "num", + "reduceFixup": "", + "x": 110, + "y": 540, + "wires": [ + [ + "643c6d17.cec784" + ] + ] + }, + { + "id": "d2bf2b71.93482", + "type": "change", + "z": "e79fd0e1.60f55", + "name": "Move as payload.file", + "rules": [ + { + "t": "move", + "p": "payload", + "pt": "msg", + "to": "payload.file", + "tot": "msg" + }, + { + "t": "set", + "p": "payload.filename", + "pt": "msg", + "to": "netflix-invoice.pdf", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 660, + "y": 400, + "wires": [ + [ + "6af264f9.2f99dc" + ] + ] + }, + { + "id": "73c55749.b6bf7", + "type": "debug", + "z": "e79fd0e1.60f55", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 490, + "y": 520, + "wires": [] + }, + { + "id": "8e61a051.3430c8", + "type": "debug", + "z": "e79fd0e1.60f55", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "url", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 380, + "y": 220, + "wires": [] + }, + { + "id": "5f5a3dc9.eab71c", + "type": "change", + "z": "e79fd0e1.60f55", + "name": "parse amount", + "rules": [ + { + "t": "move", + "p": "payload", + "pt": "msg", + "to": "textAmount", + "tot": "msg" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{}", + "tot": "json" + }, + { + "t": "set", + "p": "payload.amount", + "pt": "msg", + "to": "$number($replace($match(textAmount, /[0-9\\,]+/, 1).match, ',', '.'))", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 360, + "y": 400, + "wires": [ + [ + "6af264f9.2f99dc" + ] + ] + }, + { + "id": "643c6d17.cec784", + "type": "function", + "z": "e79fd0e1.60f55", + "name": "Cleaning payload", + "func": "return {payload: msg.payload};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 290, + "y": 540, + "wires": [ + [ + "73c55749.b6bf7", + "4c6af2dc.2504bc" + ] + ] + } +] \ No newline at end of file diff --git a/node_red_data/settings.js b/node_red_data/settings.js new file mode 100644 index 0000000..1c6ca03 --- /dev/null +++ b/node_red_data/settings.js @@ -0,0 +1,296 @@ +/** + * This is the default settings file provided by Node-RED. + * + * It can contain any valid JavaScript code that will get run when Node-RED + * is started. + * + * Lines that start with // are commented out. + * Each entry should be separated from the entries above and below by a comma ',' + * + * For more information about individual settings, refer to the documentation: + * https://nodered.org/docs/user-guide/runtime/configuration + **/ + +module.exports = { + // the tcp port that the Node-RED web server is listening on + uiPort: process.env.PORT || 1880, + + // By default, the Node-RED UI accepts connections on all IPv4 interfaces. + // To listen on all IPv6 addresses, set uiHost to "::", + // The following property can be used to listen on a specific interface. For + // example, the following would only allow connections from the local machine. + //uiHost: "127.0.0.1", + + // Retry time in milliseconds for MQTT connections + mqttReconnectTime: 15000, + + // Retry time in milliseconds for Serial port connections + serialReconnectTime: 15000, + + // Retry time in milliseconds for TCP socket connections + //socketReconnectTime: 10000, + + // Timeout in milliseconds for TCP server socket connections + // defaults to no timeout + //socketTimeout: 120000, + + // Maximum number of messages to wait in queue while attempting to connect to TCP socket + // defaults to 1000 + //tcpMsgQueueSize: 2000, + + // Timeout in milliseconds for HTTP request connections + // defaults to 120 seconds + //httpRequestTimeout: 120000, + + // The maximum length, in characters, of any message sent to the debug sidebar tab + debugMaxLength: 1000, + + // The maximum number of messages nodes will buffer internally as part of their + // operation. This applies across a range of nodes that operate on message sequences. + // defaults to no limit. A value of 0 also means no limit is applied. + //nodeMessageBufferMaxLength: 0, + + // To disable the option for using local files for storing keys and certificates in the TLS configuration + // node, set this to true + //tlsConfigDisableLocalFiles: true, + + // Colourise the console output of the debug node + //debugUseColors: true, + + // The file containing the flows. If not set, it defaults to flows_.json + //flowFile: 'flows.json', + + // To enabled pretty-printing of the flow within the flow file, set the following + // property to true: + flowFilePretty: true, + + // By default, credentials are encrypted in storage using a generated key. To + // specify your own secret, set the following property. + // If you want to disable encryption of credentials, set this property to false. + // Note: once you set this property, do not change it - doing so will prevent + // node-red from being able to decrypt your existing credentials and they will be + // lost. + //credentialSecret: "a-secret-key", + + // By default, all user data is stored in a directory called `.node-red` under + // the user's home directory. To use a different location, the following + // property can be used + //userDir: '/home/nol/.node-red/', + + // Node-RED scans the `nodes` directory in the userDir to find local node files. + // The following property can be used to specify an additional directory to scan. + //nodesDir: '/home/nol/.node-red/nodes', + + // By default, the Node-RED UI is available at http://localhost:1880/ + // The following property can be used to specify a different root path. + // If set to false, this is disabled. + //httpAdminRoot: '/admin', + + // Some nodes, such as HTTP In, can be used to listen for incoming http requests. + // By default, these are served relative to '/'. The following property + // can be used to specifiy a different root path. If set to false, this is + // disabled. + //httpNodeRoot: '/red-nodes', + + // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', + // to apply the same root to both parts. + //httpRoot: '/red', + + // When httpAdminRoot is used to move the UI to a different root path, the + // following property can be used to identify a directory of static content + // that should be served at http://localhost:1880/. + //httpStatic: '/home/nol/node-red-static/', + + // The maximum size of HTTP request that will be accepted by the runtime api. + // Default: 5mb + //apiMaxLength: '5mb', + + // If you installed the optional node-red-dashboard you can set it's path + // relative to httpRoot + //ui: { path: "ui" }, + + // Securing Node-RED + // ----------------- + // To password protect the Node-RED editor and admin API, the following + // property can be used. See http://nodered.org/docs/security.html for details. + //adminAuth: { + // type: "credentials", + // users: [{ + // username: "admin", + // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", + // permissions: "*" + // }] + //}, + + // To password protect the node-defined HTTP endpoints (httpNodeRoot), or + // the static content (httpStatic), the following properties can be used. + // The pass field is a bcrypt hash of the password. + // See http://nodered.org/docs/security.html#generating-the-password-hash + //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + + // The following property can be used to enable HTTPS + // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener + // for details on its contents. + // This property can be either an object, containing both a (private) key and a (public) certificate, + // or a function that returns such an object: + //// https object: + //https: { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + //}, + ////https function: + // https: function() { + // // This function should return the options object, or a Promise + // // that resolves to the options object + // return { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + // } + // }, + + // The following property can be used to refresh the https settings at a + // regular time interval in hours. + // This requires: + // - the `https` setting to be a function that can be called to get + // the refreshed settings. + // - Node.js 11 or later. + //httpsRefreshInterval : 12, + + // The following property can be used to cause insecure HTTP connections to + // be redirected to HTTPS. + //requireHttps: true, + + // The following property can be used to disable the editor. The admin API + // is not affected by this option. To disable both the editor and the admin + // API, use either the httpRoot or httpAdminRoot properties + //disableEditor: false, + + // The following property can be used to configure cross-origin resource sharing + // in the HTTP nodes. + // See https://github.com/troygoode/node-cors#configuration-options for + // details on its contents. The following is a basic permissive set of options: + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + // If you need to set an http proxy please set an environment variable + // called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + // For example - http_proxy=http://myproxy.com:8080 + // (Setting it here will have no effect) + // You may also specify no_proxy (or NO_PROXY) to supply a comma separated + // list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + + // The following property can be used to add a custom middleware function + // in front of all http in nodes. This allows custom authentication to be + // applied to all http in nodes, or any other sort of common request processing. + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node by calling next(); + // // Optionally skip our rawBodyParser by setting this to true; + // //req.skipRawBodyParser = true; + // next(); + //}, + + + // The following property can be used to add a custom middleware function + // in front of all admin http routes. For example, to set custom http + // headers + // httpAdminMiddleware: function(req,res,next) { + // // Set the X-Frame-Options header to limit where the editor + // // can be embedded + // //res.set('X-Frame-Options', 'sameorigin'); + // next(); + // }, + + // The following property can be used to pass custom options to the Express.js + // server used by Node-RED. For a full list of available options, refer + // to http://expressjs.com/en/api.html#app.settings.table + //httpServerOptions: { }, + + // The following property can be used to verify websocket connection attempts. + // This allows, for example, the HTTP request headers to be checked to ensure + // they include valid authentication information. + //webSocketNodeVerifyClient: function(info) { + // // 'info' has three properties: + // // - origin : the value in the Origin header + // // - req : the HTTP request + // // - secure : true if req.connection.authorized or req.connection.encrypted is set + // // + // // The function should return true if the connection should be accepted, false otherwise. + // // + // // Alternatively, if this function is defined to accept a second argument, callback, + // // it can be used to verify the client asynchronously. + // // The callback takes three arguments: + // // - result : boolean, whether to accept the connection or not + // // - code : if result is false, the HTTP error status to return + // // - reason: if result is false, the HTTP reason string to return + //}, + + // The following property can be used to seed Global Context with predefined + // values. This allows extra node modules to be made available with the + // Function node. + // For example, + // functionGlobalContext: { os:require('os') } + // can be accessed in a function block as: + // global.get("os") + functionGlobalContext: { + // os:require('os'), + // jfive:require("johnny-five"), + // j5board:require("johnny-five").Board({repl:false}) + }, + // `global.keys()` returns a list of all properties set in global context. + // This allows them to be displayed in the Context Sidebar within the editor. + // In some circumstances it is not desirable to expose them to the editor. The + // following property can be used to hide any property set in `functionGlobalContext` + // from being list by `global.keys()`. + // By default, the property is set to false to avoid accidental exposure of + // their values. Setting this to true will cause the keys to be listed. + exportGlobalContextKeys: false, + + + // Context Storage + // The following property can be used to enable context storage. The configuration + // provided here will enable file-based context that flushes to disk every 30 seconds. + // Refer to the documentation for further options: https://nodered.org/docs/api/context/ + // + //contextStorage: { + // default: { + // module:"localfilesystem" + // }, + //}, + + // The following property can be used to order the categories in the editor + // palette. If a node's category is not in the list, the category will get + // added to the end of the palette. + // If not set, the following default order is used: + //paletteCategories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'], + + // Configure the logging output + logging: { + // Only console logging is currently supported + console: { + // Level of logging to be recorded. Options are: + // fatal - only those errors which make the application unusable should be recorded + // error - record errors which are deemed fatal for a particular request + fatal errors + // warn - record problems which are non fatal + errors + fatal errors + // info - record information about the general running of the application + warn + error + fatal errors + // debug - record information which is more verbose than info + info + warn + error + fatal errors + // trace - record very detailed logging + debug + info + warn + error + fatal errors + // off - turn off all logging (doesn't affect metrics or audit) + level: "info", + // Whether or not to include metric events in the log output + metrics: false, + // Whether or not to include audit events in the log output + audit: false + } + }, + + // Customising the editor + editorTheme: { + projects: { + // To enable the Projects feature, set this value to true + enabled: false + } + } +}