Skip to content

Instantly share code, notes, and snippets.

@oloynet
Last active June 5, 2018 11:38
Show Gist options
  • Save oloynet/5431603 to your computer and use it in GitHub Desktop.
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 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