diff --git a/LICENSE b/LICENSE index 04d2679..093aa37 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Gustavo Honorato +Copyright (c) 2023 Rubens Flinco Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8212580..af4e051 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,2 @@ -# nubank-ofx -Extensão do Chrome que adiciona um botão para exportação do extrato em OFX - -** **ATENÇÃO** ** - -Como não sou mais um usuário deste serviço e estou muito ocupado, não tenho meios mais de manter esse projeto. Se você tem interesse, abra uma issue solicitando a transferência do projeto. +# NuBank OFX - MeuDinheiroWeb +Adiciona um botão para exportação do extrato em OFX do NuBank otimizado para MeuDinheiroWeb, com opção de exportar com a data das transalações na fatura ou com as datas da compra da transalação que geralmente tem uma diferença de 1 dia. \ No newline at end of file diff --git a/extrato-nubank.js b/extrato-nubank.js index 357f73a..4850cb0 100644 --- a/extrato-nubank.js +++ b/extrato-nubank.js @@ -1,4 +1,4 @@ -(function() { +(function () { const startOfx = () => { return ` @@ -36,8 +36,15 @@ NEWFILEUID:NONE ${description} `; - const normalizeAmount = (text) => - text.replace('.', '').replace(',','.'); + const normalizeAmount = (text) => { + let amount = text.replace('.', '').replace(',', '.'); + if (String(amount).includes("-")) { + amount = amount.replace('-', '+'); + } else { + amount = "-" + amount; + } + return amount; + } const normalizeDay = (date) => date.split(' ')[0]; @@ -62,74 +69,128 @@ NEWFILEUID:NONE return months[month]; } - const normalizeYear = (date) => { + const normalizeYear = (date, ifJan = true) => { + const openMonth = (document.querySelector('md-tab.ng-scope.active .period').textContent.trim()).toLocaleUpperCase(); const dateArray = date.split(' '); if (dateArray.length > 2) { - return '20'+dateArray[2]; + return '20' + dateArray[2]; } else { - return new Date().getFullYear(); + if((ifJan) && (openMonth.includes("JAN"))){ + return Number(new Date().getFullYear())-1; + }else{ + return new Date().getFullYear(); + } }; } - const normalizeDate = (date) => - normalizeYear(date)+normalizeMonth(date)+normalizeDay(date); + const normalizeDate = (date, dataCompra = false) => { + const [year, month, day] = [ + normalizeYear(date), + normalizeMonth(date), + normalizeDay(date) + ]; + if (dataCompra === false) { + const dataFatura = `${year}${month}${day}`; + return dataFatura; + } else { + const newDate = new Date(`${year}-${month}-${day}`); + newDate.setDate(newDate.getDate() - 1); - const exportOfx = (ofx) => { + const normalizedDate = newDate.toISOString().slice(0, 10).replace(/-/g, ''); + return normalizedDate; + } + }; + + const exportOfx = (ofx, appendNameFile) => { const openMonth = " " + document.querySelector('md-tab.ng-scope.active .period').textContent.trim(); - const period = normalizeYear(openMonth) + "-" + normalizeMonth(openMonth); + const period = normalizeYear(openMonth, false) + "-" + normalizeMonth(openMonth); link = document.createElement("a"); - link.setAttribute("href", 'data:application/x-ofx,'+encodeURIComponent(ofx)); - link.setAttribute("download", "nubank-" + period + ".ofx"); + link.setAttribute("href", 'data:application/x-ofx,' + encodeURIComponent(ofx)); + link.setAttribute("download", `nubank-${appendNameFile}-${period}.ofx`); link.click(); } const generateOfx = () => { let ofx = startOfx(); - document.querySelectorAll('.charge:not([style=\'display:none\'])').forEach(function(charge){ - const date = normalizeDate(charge.querySelector('.time').textContent); + document.querySelectorAll('.md-tab-content:not(.ng-hide) .charge:not([style=\'display:none\'])').forEach(function (charge) { const description = charge.querySelector('.description').textContent.trim(); + const date = normalizeDate(charge.querySelector('.time').textContent, false); const amount = normalizeAmount(charge.querySelector('.amount').textContent); ofx += bankStatement(date, amount, description); }); ofx += endOfx(); - exportOfx(ofx); + exportOfx(ofx, "data-fatura"); } - const createExportButton = () => { - const button = document.createElement('button'); - button.classList.add('nu-button'); - button.classList.add('secondary'); - button.setAttribute('role', 'gen-ofx'); - button.textContent = "Exportar para OFX"; + const generateOfxDataCompra = () => { + let ofx = startOfx(); - button.addEventListener('click', generateOfx) + document.querySelectorAll('.md-tab-content:not(.ng-hide) .charge:not([style=\'display:none\'])').forEach(function (charge) { + const description = charge.querySelector('.description').textContent.trim(); + const date = normalizeDate(charge.querySelector('.time').textContent, true); + const amount = normalizeAmount(charge.querySelector('.amount').textContent); + + ofx += bankStatement(date, amount, description); + }); - return button; + ofx += endOfx(); + exportOfx(ofx, "data-compra"); } - const exportOfxButtonAlreadyExists = () => - document.querySelectorAll(".summary.open [role=\"gen-ofx\"]").length > 0 + const createExportButtonNew = () => { + const div = document.createElement('div'); + div.classList.add('extension-nubank-ofx-meu-dinheiro-web'); - const insertExportButtonCallback = (mutationList, observer) => { - if(mutationList == undefined || exportOfxButtonAlreadyExists()) return; + const btn1 = document.createElement('button'); + btn1.classList.add('nu-button'); + btn1.classList.add('secondary'); + btn1.setAttribute('role', 'gen-ofx'); + btn1.textContent = "Exportar para OFX (Data da fatura)"; + btn1.addEventListener('click', generateOfx); - const generateBoletoButton = document.querySelector('.summary.open .nu-button'); - if (generateBoletoButton == undefined) return; + const btn2 = document.createElement('button'); + btn2.classList.add('nu-button'); + btn2.classList.add('secondary'); + btn2.setAttribute('role', 'gen-ofx-2'); + btn2.textContent = "Exportar para OFX (Data da compra)"; + btn2.addEventListener('click', generateOfxDataCompra); - const exportOfxButton = createExportButton(); - generateBoletoButton.parentNode.appendChild(exportOfxButton); + div.appendChild(btn1); + div.appendChild(btn2); - observer.disconnect(); + return div; } - const targetElement = document.querySelector('.bills-browser'); - const config = { attributes: true, childList: true, subtree: true } + const insertExportButtonCallback = (mutationList, observer) => { + if (mutationList === null || (mutationList?.length <= 0)) { + return; + }; + + const billsBrowser = document.querySelector('.bills-browser'); + if (billsBrowser === null || (billsBrowser?.length <= 0)) { + return; + }; + + const nuPageBtns = document.querySelectorAll('.bills-browser .summary .nu-button'); + if (nuPageBtns?.length > 0) { + for (let i = 0; i < nuPageBtns.length; i++) { + const exportOfxButton = createExportButtonNew(); + nuPageBtns[i].parentNode.appendChild(exportOfxButton); + } + } + + const extensionActive = document.querySelectorAll('.extension-nubank-ofx-meu-dinheiro-web'); + if (extensionActive?.length > 0) { + observer.disconnect() + return; + } + + } const observer = new MutationObserver(insertExportButtonCallback); - observer.observe(targetElement, config) + observer.observe(document, { attributes: true, childList: true, subtree: true }); })(); - diff --git a/manifest.json b/manifest.json index 2fa76f3..4600da6 100644 --- a/manifest.json +++ b/manifest.json @@ -1,14 +1,25 @@ { - "manifest_version": 2, - - "name": "NuBank OFX", - "description": "Adiciona um botão para exportação do extrato em OFX do NuBank", - "version": "1.1", - "icons": { "16": "nubank-ofx-16.png", - "48": "nubank-ofx-48.png", - "128": "nubank-ofx-128.png" }, + "manifest_version": 3, + "name": "NuBank OFX - MeuDinheiroWeb", + "description": "Adiciona um botão para exportação do extrato em OFX do NuBank otimizado para MeuDinheiroWeb, com opção de exportar com a data das transalações na fatura ou com as datas da compra da transalação que geralmente tem uma diferença de 1 dia.", + "version": "2", + "icons": { + "16": "nubank-ofx-16.png", + "48": "nubank-ofx-48.png", + "128": "nubank-ofx-128.png" + }, + "action": { + "default_icon": { + "16": "nubank-ofx-16.png", + "48": "nubank-ofx-48.png", + "128": "nubank-ofx-128.png" + } + }, + "permissions": [ + "activeTab" + ], "content_scripts": [{ "matches": ["https://*.nubank.com.br/*"], "js": ["extrato-nubank.js"] }] -} +} \ No newline at end of file diff --git a/nubank-ofx-master.crx b/nubank-ofx-master.crx new file mode 100644 index 0000000..ee0b159 Binary files /dev/null and b/nubank-ofx-master.crx differ diff --git a/nubank-ofx-master.pem b/nubank-ofx-master.pem new file mode 100644 index 0000000..0edf928 --- /dev/null +++ b/nubank-ofx-master.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDopQV9MOwzDC2O +63Qx5Ufm4YJOec3td7krTQKmb2i/+zLsqevcML7Gwsud6EojZxkRSvIVleiFh3o7 +rRV831cajLCr43Ry7AQcHnnloqFVl2wmJNcnaNr/M1gKkkv8JkwXTxUfhxg/nqzb +nfByHKrgTEuwdre7rf8aY63UZ9s2ycXOcZTmOHwkjMDwnJm8jeDcAJNcvMx+4JwS +1MK+hOeGKY1ae3iyhg5lujFMET8XzLfmnBpN8andSJhoUJhAWk5yCiSlHjL+tAfR +h9ipc7HhLDhARGGS/1KxPrq4ZPa3MuWDlrzA8L2wSugD389B6RAaVQtJ0iLU5TfS +2pwQxcYNAgMBAAECggEAA+KOQlOw52j+kW/W+iapyiN9wqk6j4q2XdB/U5UHMwjd +xhbQAJaTd6wU7I9j6OObHHnmVobGbK/BPQy2z+XGkC6FccK5NQUXds+/JImld5GG +hbw2QpXNQxc8qGUz3c4Blcm6i32noZeuVnbfUcyEQagh2HHMaiwtlyd50D2mwGtb +L63/ZLuoAUYYPV9Cx0h6AGoJrO0SOtD7FnpXEJJoh5q15uG0LRvodhIo9ZUG00eU +LEIHj4+D0A1gFvW59IG/sy+cy3+C+m43mWcxXcFQOmfBGKXd7EZUmL3h6D7IhvnZ +6I8UXMPVmE+MAwOJHCu6xRx5iPBj6jn18AHLguMYkQKBgQD49yv3uDsoAHAIxpZx +Y0ccMrCpkRtvu716TLJIDCZYWBmW/lYch/wzJe7V72p0XDYtI8AnULJDTUxLKOGy +BGiTbwZULY3PcRftMwkxjVd5G+Mhe1rC+polPSiddYTrIW0f+1jyLD/JRuCzc+Zv +oW5nK54ss6FiaQi/4w0Hxy6NvQKBgQDvN8vxGdx8aQQEzGZM3jx3xJzKrHtBnZBu +cvm1ruzpWd15bZE9VU5AEkAIwMAxfG8eejhoRrzT9dSysDQb9eDNIssONtCfmtG4 +0I/mQmklAx775FMAPbGtnyuoeBDPqWkrIXBQ2F0NGEWUqub2eRUipO9dWXzT2RHm +LTCyPpJWkQKBgD1vYN4kDBT25q6DsqQQR3/h0k5FjGup/DutqWC1/tBWDRqBcGZh ++A33ElSgW7iS+Jty8vvAofyRmn4BfJAdHmEjSICFLTU/RxQ1P9OGeUtdYlLkyaTL +ijYePWN9mGsdOHxn3a8E1EiqwNAHjZmGUGQNE18chHpwSMRxFsoQkKBRAoGAY/OF +VBUBKj5avoKFEAMfcs+Ez64nxe/G5E9IBOC0/n9c6ZqdP+o/yseVV9LpuwOKDkr0 +/KTpywqBN7Ql4bTnm+64txSyMK3oiPcj2QrQkfVu4cKx53zfm3LRNBAOviXD2pCb +NDxjDNCiag7KeBt5eEM//FoirQWa0/j3ytIYJPECgYBOc03/Vm9Po/LhDK2vsoRn +F6JQ7lerqvlO0QWen3VG4qEvXMjzZVm1dD8OCIAVagYOjbiS8qzLSbYMaPSdkCoF +ZaqQ1KQjYLhKbnKM+ZVCZpI6pMFjAujdVb7sgHibXWchi1MgEAbhBcmxsZ9HII6N +6g/9Ikdp2JGXViabkuOFEg== +-----END PRIVATE KEY-----