Last active
June 5, 2018 11:38
-
-
Save oloynet/5431603 to your computer and use it in GitHub Desktop.
This casperjs script return balance and statement from bank "Credit Agricole of Languedoc (France)" for a given account. May work with other agencies. Data are return in json
Usage: casperjs credit-agricole.js --auth=12345678912:123456 --json
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
/** | |
* This casperjs script return balance and statement from bank "Credit Agricole of Languedoc (France)" for a given account. | |
* May work with other agencies | |
* | |
* Usage: | |
* | |
* $ casperjs credit-agricole.js --auth=12345678912:123456 | |
* $ casperjs credit-agricole.js --auth=12345678912:123456 --account=12345678912 | |
* $ casperjs credit-agricole.js --auth=12345678912:123456 --account=12345678912 --json | |
* $ casperjs credit-agricole.js http://www.ca-languedoc.fr/ --auth=12345678912:123456 --account=12345678912 --json | |
* | |
* See also python script from brutasse : https://gist.github.com/brutasse/1050830 | |
* | |
*/ | |
var usage = 'casperjs credit-agricole.js [url] --auth=12345678912:123456 [--account=12345678912 --viewport=800x600 --screenshot --verbose --json]'; | |
var casper = require('casper').create(), | |
utils = require('utils'), | |
url = casper.cli.get(0) || 'http://www.ca-languedoc.fr/', | |
user_agent = casper.cli.raw.get('user-agent') || false, // 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4', | |
auth = casper.cli.raw.get('auth') || false, | |
account = casper.cli.raw.get('account') || false, | |
viewport = casper.cli.raw.get('viewport') || '800x600', | |
screenshot = casper.cli.raw.get('screenshot') || false, | |
verbose = casper.cli.raw.get('verbose') || false, | |
json = casper.cli.raw.get('json') || false | |
; | |
var tab_digits = ''; | |
var account_balance = []; | |
var account_statement = []; | |
var account_url = ''; | |
var timestamp = ( new Date() ).toISOString(); | |
var step = 0; | |
if ( !auth || typeof auth === 'boolean' ) { | |
echoAndExit( 'Usage: ' + usage, true ); | |
} | |
var param_auth = auth.split( /:/ ); | |
var username = param_auth[0] || false; | |
var password = param_auth[1] || false; | |
if ( !account ) { | |
account = username; | |
} | |
if ( username.length != 11 || password.length != 6 || account.length != 11 ) { | |
echoAndExit( 'Usage: ' + usage, true ); | |
} | |
function echoAndExit( data, exit_level ) { | |
exit_level = exit_level || false; | |
if ( json == true ) { | |
casper.echo( JSON.stringify( { 'data': data, 'error': exit_level } ) ); | |
} else if ( typeof data == 'object' ) { | |
utils.dump( data ); | |
} else { | |
casper.echo( data ); | |
} | |
casper.exit( exit_level ); | |
} | |
function objectFindByKey( array, key, value ) { // better solution to do with underscore.js | |
for( var i = 0; i < array.length; i++ ) { | |
if( array[i][key] === value ) { | |
return array[i]; | |
} | |
} | |
return null; | |
} | |
var make_screenshot = function () { | |
if ( screenshot ) { | |
verbose && this.echo( utils.format( "Make screenshot for '%s'", this.getCurrentUrl() ) ); | |
this.capture( utils.format( 'screenshot-%s-%s-step-%s.png', account, timestamp, step++ ) ); | |
} | |
} | |
function getTabDigits() { | |
var links = document.querySelectorAll('table#pave-saisie-code td a'); | |
var digits = Array.prototype.map.call(links, function(e) { | |
try { | |
var digit = e.text.replace( /^\s+/, '' ).replace( /\s+$/, '' ); | |
var pos = ( e.getAttribute('tabindex') - 1 ).toString(); | |
pos = pos.length > 1 ? pos : '0' + pos; | |
return new Array(digit, pos); | |
} catch (err) { | |
return ''; | |
} | |
}); | |
digits = digits.sort(); | |
var tab_digits = []; | |
for( i=0; i < digits.length; i++ ) { | |
if( digits[i][0].length > 0 ) { | |
tab_digits.push( digits[i][1] ); | |
} | |
} | |
return tab_digits; | |
} | |
function getAccountBalance() { | |
var rows = document.querySelectorAll( 'table[class="ca-table"] tr[class="colcelligneimpaire"], table[class="ca-table"] tr[class="colcellignepaire"]' ); | |
return Array.prototype.map.call( rows, function(e) { | |
var cells = e.querySelectorAll( 'td a' ); | |
return { | |
'url': cells[0].href, | |
'type': cells[0].textContent.replace( /\s+/g, '' ), | |
'account': cells[2].textContent.replace( /\s+/g, '' ), | |
'amount': parseFloat( cells[4].text.replace( /\s+/g, '' ).replace( ',', '.' ) ), | |
'currency': cells[5].textContent.replace( /\s+/g, '' ), | |
} | |
}); | |
} | |
function getAccountStatement() { | |
function formatDate( date ) { | |
var year = ( new Date() ).getYear() + 1900; | |
var month = ( new Date() ).getMonth() + 1; | |
var date = date.textContent.replace( /[\n\t]+/g, '' ).split( /\// ); | |
return ( new Date( ( ~~date[1] > month ? year - 1 : year ), ~~date[1] - 1, ~~date[0] ) ).toISOString().substring(0, 10); | |
} | |
function formatAmount( amount ) { | |
amount = amount.textContent.replace( /[\s]+/g, '' ).replace( ',', '.' ); | |
return amount.length > 0 ? parseFloat( amount ) : null; | |
} | |
function formatLabel( label ) { | |
return label.textContent.replace( /[\n\t]+/g, '' ).replace( /<br>/g, ' ' ).replace( /[\s]+$/g, '' ).replace( /[ ]{2,}/g, ' ' ) | |
} | |
var table = document.querySelectorAll('table[class="ca-table"] tbody')[1]; | |
var rows = table.querySelectorAll('tr'); | |
return Array.prototype.map.call(rows, function(e) { | |
var cells = e.querySelectorAll('td'); | |
return { | |
'date': formatDate ( cells[0] ), | |
'date_value': formatDate ( cells[1] ), | |
'label': formatLabel ( cells[2] ), | |
'credit': formatAmount( cells[3] ), | |
'debit': formatAmount( cells[4] ), | |
} | |
}); | |
} | |
/* | |
* ===== start ===== | |
*/ | |
casper.start(); | |
/* | |
* ===== home page ===== | |
*/ | |
casper.thenOpen( url, function() { | |
verbose && this.echo( utils.format( "Open url '%s'", url ) ); | |
if( user_agent ) { | |
this.userAgent( user_agent ); | |
} | |
var size_img = viewport.split( /x|×/i ); | |
var width = Math.max( ~~size_img[0], 320 ) || 320; // minimum = 320px | |
var height = Math.max( ~~size_img[1], 240 ) || 240; // minimum = 240px | |
this.viewport( width, height ); | |
}); | |
casper.then( make_screenshot ); | |
casper.thenEvaluate( function() { | |
document.querySelector( 'form[name="bamaccess"]' ).submit(); | |
}); | |
/* | |
* ===== authenticate page ===== | |
*/ | |
casper.waitUntilVisible( '.blc-choix', function() { | |
verbose && this.echo( utils.format( "Authenticate with account '%s'", username ) ); | |
// ---- get tab digits | |
tab_digits = this.evaluate( getTabDigits ); | |
//utils.dump(tab_digits); | |
// ---- encrypt password | |
var encrypted_password = []; | |
for( i=0; i < password.length; i++ ) { | |
encrypted_password.push( tab_digits[ password[i] ] ); | |
} | |
encrypted_password = encrypted_password.join(','); | |
//utils.dump( encrypted_password ); | |
// ---- set authenticate form | |
this.fill( 'form[name="formulaire"]', { | |
CCPTE: username, | |
CCCRYC: encrypted_password, | |
CCCRYC2: '000000', | |
}, false); | |
}); | |
casper.then( make_screenshot ); | |
casper.then( function() { | |
// ---- submit form | |
this.click( 'a.droite:first-of-type' ); | |
}); | |
/* | |
* ===== bank accounts balance page ===== | |
*/ | |
casper.waitUntilVisible( '.ca-table', function() { | |
account_balance = this.evaluate( getAccountBalance ); | |
// ---- find account | |
account_found = objectFindByKey( account_balance, 'account', account ); | |
if( !account_found ) { | |
echoAndExit( utils.format( "No account '%s' found to get statement", account ), true ); | |
} | |
account_url = account_found.url; | |
}); | |
casper.then( make_screenshot ); | |
casper.then( function() { | |
// ---- open new location | |
this.evaluate( function( url ) { | |
return document.location = url; | |
}, account_url ); | |
}); | |
/* | |
* ===== bank account statement page ===== | |
*/ | |
casper.waitUntilVisible( '.ca-table', function() { | |
account_statement = this.evaluate( getAccountStatement ); | |
//utils.dump( account_statement ); | |
}); | |
casper.then( make_screenshot ); | |
/* | |
* ===== return result ===== | |
*/ | |
casper.run(function() { | |
var data = { | |
'balance': account_balance, | |
'statement': account_statement, | |
} | |
echoAndExit( data ); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment