{"version":3,"sources":["jsdelivr-header.js","/npm/stepford@1.4.1/index.js"],"names":[],"mappings":"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","file":"/npm/stepford@1.4.1/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/stepford@1.4.1/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict';\n\nvar moment = require('moment');\nvar numeral = require('numeral');\nvar Browser = require('zombie');\nvar spinner = require('elegant-spinner');\nvar logUpdate = require('log-update').create(process.stderr);\nvar c = require('chalk');\nBrowser.silent = true;\n\nmodule.exports = function(options) {\n\tvar currentMessage = 'loading…';\n\tvar tickSpinner = spinner();\n\tvar log;\n\tif(options.silent) {\n\t\tlog = () => {};\n\t} else if(options.log) {\n\t\tlog = options.log;\n\t} else {\n\t\tlog = msg => currentMessage = msg;\n\t}\n\n\tvar t = (options.silent || options.log) || setInterval(() => {\n\t\tlogUpdate(c.cyan.bold(tickSpinner()) + ' ' + c.grey(currentMessage));\n\t}, 50);\n\n\tvar browser = new Browser();\n\n\tvar afterEarliest = row => row.date >= new Date(options.earliest);\n\tfunction willFilter(tx) {\n\t\treturn options.earliest && !tx.every(afterEarliest);\n\t}\n\tfunction filterTx(tx) {\n\t\treturn tx.filter(afterEarliest);\n\t}\n\n\tfunction parseTx() {\n\t\treturn browser.queryAll(':not(.verttop) > .summaryTable tbody tr')\n\t\t.filter(row => {\n\t\t\tif(row.children[0].textContent.match(/last statement/)) return false;\n\t\t\tif(row.children[1].textContent === 'BROUGHT FORWARD') return false;\n\t\t\treturn true;\n\t\t})\n\t\t.map(row => ({\n\t\t\tdate: moment(row.children[0].textContent, 'DD/MM/YYYY').toDate(),\n\t\t\tpayee: row.children[1].textContent,\n\t\t\tamount: row.children[2].textContent.trim() ?\n\t\t\t\t+numeral(row.children[2].textContent) :\n\t\t\t\t-numeral(row.children[3].textContent)\n\t\t}));\n\t}\n\n\tfunction parseStatementLoop(n, total) {\n\t\tvar p = browser.query('#recentItemsPageCount').textContent.match(/Page (\\d+) of \\d+/)[1];\n\t\tlog(`parsing statement page ${p} + (${n}/${total})`);\n\n\t\tif(browser.query('td.error')) return Promise.resolve([]);\n\n\t\tvar data = parseTx(browser);\n\t\tif(willFilter(data)) {\n\t\t\treturn Promise.resolve(filterTx(data));\n\t\t}\n\n\t\treturn browser.clickLink('[title=previous]').then(() => {\n\t\t\treturn parseStatementLoop(n + 1, total).then(prev => prev.concat(data));\n\t\t});\n\t}\n\n\tfunction cleanup() {\n\t\tclearInterval(t);\n\t\tbrowser.destroy();\n\t}\n\n\treturn browser.visit('https://banking.smile.co.uk/SmileWeb2/start.do')\n\t.then(() => {\n\t\tlog('login');\n\t\tbrowser\n\t\t\t.fill('sortCode', options.sortcode)\n\t\t\t.fill('accountNumber', options.account);\n\n\t\treturn browser.click('[name=ok]');\n\t})\n\t.then(() => {\n\t\tlog('security code');\n\t\tbrowser.assert.text('title', 'enter your security code');\n\t\tvar first  = browser.query('[for=firstPassCodeDigit]') .textContent.match(/^(\\w+)/)[1];\n\t\tvar second = browser.query('[for=secondPassCodeDigit]').textContent.match(/^(\\w+)/)[1];\n\n\t\tvar getDigit = pos => ({\n\t\t\tfirst: options.securityCode[0],\n\t\t\tsecond: options.securityCode[1],\n\t\t\tthird: options.securityCode[2],\n\t\t\tfourth: options.securityCode[3]\n\t\t})[pos];\n\n\t\tbrowser\n\t\t\t.select('firstPassCodeDigit',  getDigit(first))\n\t\t\t.select('secondPassCodeDigit', getDigit(second));\n\n\t\treturn browser.click('[name=ok]');\n\t})\n\t.then(() => {\n\t\tlog('secure personal information');\n\t\tbrowser.assert.text('title', 'enter your secure personal information');\n\t\tvar key = browser.query('#logonBody input').name;\n\n\t\tif(key === 'memorableDay') {\n\t\t\tlet date = moment(options.memorableDate, 'YYYY-MM-DD');\n\t\t\tbrowser\n\t\t\t.fill('memorableDay',   date.format('DD'))\n\t\t\t.fill('memorableMonth', date.format('MM'))\n\t\t\t.fill('memorableYear',  date.format('YYYY'));\n\t\t} else {\n\t\t\tbrowser.fill(key, options[key]);\n\t\t}\n\n\t\treturn browser.click('[name=ok]').catch(() => {\n\t\t\t// yeah, no idea\n\t\t});\n\t})\n\t.then(() => {\n\t\tif(browser.query('title').textContent.trim() === 'smile noticeboard') {\n\t\t\tlog('noticeboard');\n\t\t\treturn browser.click('[name=ok]');\n\t\t}\n\t})\n\t.then(() => {\n\t\tlog('home');\n\t\tbrowser.assert.text('title', 'home'); // what\n\t\tvar acctCell = browser.queryAll('.dataRowBB').find(el =>\n\t\t\tel.textContent.match(new RegExp(options.account))\n\t\t);\n\t\tvar row = acctCell.parentNode;\n\t\tvar linkCell = row.children[0];\n\t\treturn browser.clickLink(linkCell.firstElementChild);\n\t})\n\t.then(() => {\n\t\tlog('parsing recent items');\n\t\tbrowser.assert.text('title', 'recent items');\n\t\tvar recent = parseTx(browser);\n\t\tif(willFilter(recent)) {\n\t\t\treturn filterTx(recent);\n\t\t}\n\n\t\treturn browser.clickLink('[title=\"view previous statements\"]')\n\t\t.then(() => {\n\t\t\tvar total = browser.queryAll('.summaryTable tbody tr').length;\n\t\t\treturn browser.clickLink('[title=\"click here to go to statement\"]')\n\t\t\t.then(() => parseStatementLoop(1, total));\n\t\t})\n\t\t.then(data => recent.concat(data).sort((a, b) => a.date - b.date));\n\t}).then(d => {\n\t\treturn [].concat(options.plugins || []).reduce(\n\t\t\t(last, plugin) => last.then(plugin),\n\t\t\tPromise.resolve()\n\t\t).then(() => d);\n\t}).then(d => {\n\t\tcleanup();\n\t\tlogUpdate(`${c.green('✔︎')} extracted ${d.length} transactions`);\n\t\treturn d;\n\t}, e => {\n\t\tcleanup();\n\t\tthrow e;\n\t});\n};\n"]}