Last active
September 21, 2021 09:26
-
-
Save xkikeg/0a759db9607e005096c625ded2174deb to your computer and use it in GitHub Desktop.
Greasemonkey script to convert wise.com account to https://github.com/ledger/ledger/ format file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Wise.com to ledger | |
// @version 1 | |
// @grant GM.setClipboard | |
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js | |
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js | |
// @match https://wise.com/user/account/* | |
// ==/UserScript== | |
function getPayee(node) { | |
return node.parents('.css-1t84jn').find('h5.css-7fnyde').text(); | |
} | |
function handleDetailsView(node) { | |
var r= $('<input type="button" value="new button"/>'); | |
node.prepend(r); | |
r.on('click', function() { | |
let typeText = node.find('.css-1d1duka h5').last().text(); | |
var result; | |
if (typeText == 'お客様の銀行口座情報') { | |
result = runTransfer(node); | |
} else if (typeText == '支払い方法') { | |
result = runDebit(node); | |
} else if (typeText == '取引詳細') { | |
result = runExchange(node); | |
} | |
if (result) { | |
GM.setClipboard(result); | |
} | |
}); | |
} | |
function runExchange(node) { | |
var code; | |
var srcCurrency; | |
var srcAmount; | |
var comission; | |
var rate; | |
var dstCurrency; | |
var dstAmount; | |
node.find('.css-1d1duka').each(function(i, detail) { | |
$(detail).find('dl').css('background-color', 'yellow'); | |
$(detail).find('dt').each(function(i, dt) { | |
let dttext = $(dt).text(); | |
let ddtext = $(dt).next().text(); | |
if (dttext == '受取額') { | |
srcCurrency = getCurrency(ddtext); | |
srcAmount = prettyAmount(ddtext); | |
} else if (dttext == '当社の手数料') { | |
comission = prettyAmount(ddtext); | |
} else if (dttext == '為替レート') { | |
rate = ddtext; | |
} else if (dttext == '両替された通貨') { | |
dstCurrency = getCurrency(ddtext); | |
dstAmount = prettyAmount(ddtext); | |
} else if (dttext == '取引番号') { | |
code = ddtext; | |
} | |
}); | |
}); | |
return [ | |
'', | |
'* (' + code + ') Wise.com', | |
' Assets:Wire:Wise -' + srcAmount, | |
' Expenses:Commissions ' + comission, | |
' Assets:Wire:Wise ' + dstAmount + ' @ (1/' + rate + ' ' + srcCurrency + ')', | |
].join('\n'); | |
} | |
function runTransfer(node) { | |
var code; | |
var iban; | |
var swift; | |
var srcCurrency; | |
var srcAmount; | |
var comission; | |
var rate; | |
var dstCurrency; | |
var dstAmount; | |
let payee = getPayee(node).replace(/^受取人: /, ''); | |
node.find('.css-1d1duka').each(function(i, detail) { | |
$(detail).find('dl').css('background-color', 'blue'); | |
$(detail).find('dt').each(function(i, dt) { | |
let dttext = $(dt).text(); | |
let ddtext = $(dt).next().text(); | |
if (dttext == 'IBAN') { | |
iban = ddtext; | |
} else if (dttext == 'Bank code (BIC/SWIFT)') { | |
swift = ddtext; | |
} else if (dttext == '送金額:') { | |
srcCurrency = getCurrency(ddtext); | |
srcAmount = prettyAmount(ddtext); | |
} else if (dttext == '当社の手数料') { | |
comission = prettyAmount(ddtext); | |
} else if (dttext == '為替レート') { | |
rate = ddtext; | |
} else if (dttext == '受取額') { | |
dstCurrency = getCurrency(ddtext); | |
dstAmount = prettyAmount(ddtext); | |
} else if (dttext == '取引番号') { | |
code = ddtext; | |
} | |
}); | |
}); | |
return [ | |
'', | |
'* (' + code + ') ' + payee, | |
' Assets:Wire:Wise -' + srcAmount, | |
' Expenses:Commissions ' + comission + ' ; Payee: Wise.com', | |
' Assets:Wire:BCGE ' + dstAmount + ' @ (1/' + rate + ' ' + srcCurrency + ')', | |
].join('\n'); | |
} | |
class Post { | |
constructor(account, amount, converted=null) { | |
this.account = account; | |
this.amount = amount; | |
this.converted = converted; | |
} | |
print() { | |
var res = " " + this.account + " " + this.amount; | |
if (this.converted != null) { | |
res += " @@ " + this.converted; | |
} | |
return res; | |
} | |
} | |
function runDebit(node) { | |
var date; | |
var code; | |
var posts = []; | |
var comments = []; | |
let payee = getPayee(node).replace(/^場所: /, ''); | |
node.find('.css-1d1duka').each(function(i, detail) { | |
$(detail).find('dl').each(function(i, dl) { | |
$(dl).css('background-color', 'red'); | |
var amount = null; | |
var commission = null; | |
var converted = null; | |
$(dl).find('dt').each(function(i, dt) { | |
let dttext = $(dt).text(); | |
let ddtext = $(dt).next().text(); | |
if (dttext == "取引日") { | |
let match = /(\d+)年(\d+)月(\d+)日/.exec(ddtext); | |
if (match) { | |
var m = match[2]; | |
var d = match[3]; | |
if (m.length == 1) { | |
m = '0' + m; | |
} | |
if (d.length == 1) { | |
d = '0' + d; | |
} | |
date = match[1] + '/' + m + '/' + d; | |
} else { | |
console.warning('unexpected date format: ' + ddtext); | |
} | |
} else if (dttext == '取引場所') { | |
comments.push('place: ' + ddtext); | |
} else if (dttext == '支払額') { | |
posts.push(new Post('Expenses:???', prettyAmount(ddtext))); | |
} else if (dttext == '支払い額') { | |
amount = prettyAmount(ddtext); | |
} else if (dttext == '当社の手数料') { | |
commission = prettyAmount(ddtext); | |
} else if (dttext == '両替された通貨') { | |
converted = prettyAmount(ddtext); | |
} else if (dttext == '為替レート') { | |
comments.push('rate: ' + ddtext); | |
} | |
}); | |
if (amount != null) { | |
if (commission == null) { | |
posts.push(new Post('Assets:Banks:Wise', '-'+amount)); | |
} else { | |
posts.push(new Post('Assets:Banks:Wise', '-'+amount)); | |
posts.push(new Post('Expenses:Commissions', commission)); | |
} | |
} | |
}); | |
let codeBox = $(detail).find('dl + span'); | |
if (codeBox && codeBox.length >= 1) { | |
code = codeBox.text().replace(/^取引番号 /, ''); | |
} | |
}); | |
var lines = ['', date + ' * (' + code + ') ' + payee]; | |
posts.forEach(post => lines.push(post.print())); | |
comments.forEach(comment => lines.push(' ; ' + comment)); | |
lines.push(''); | |
return lines.join('\n'); | |
} | |
function getCurrency(x) { | |
let match = /[0-9,]+(?:\.[0-9]+)? ([A-Z]+)/.exec(x); | |
return match[1]; | |
} | |
function prettyAmount(x) { | |
let match = /([0-9,]+)(\.[0-9]+)? ([A-Z]+)/.exec(x); | |
if (match[3] == "JPY") { | |
return x; | |
} | |
if (match[2]) { | |
return x; | |
} | |
return match[1]+ ".00 " + match[3]; | |
} | |
window.addEventListener('load', init, false); | |
function init() { | |
waitForKeyElements("#activity-details-view-panel-0", handleDetailsView); | |
waitForKeyElements("#activity-details-view-panel-1", handleDetailsView); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment