# HG changeset patch # User Daniele Nicolodi # Date 1452561779 -3600 # Node ID 0a3509a12762eaca5b2b6fadb5862cd5f5129dcc # Parent 37ce0dc68cad27500f4249f7abc5e0bbeb38ac14 Implement download of montly records and add command line options diff -r 37ce0dc68cad -r 0a3509a12762 bnpparibas.py --- a/bnpparibas.py Mon Jan 11 21:39:40 2016 +0100 +++ b/bnpparibas.py Tue Jan 12 02:22:59 2016 +0100 @@ -4,7 +4,6 @@ import itertools import json import os.path -import requests import smtplib import sqlite3 import subprocess @@ -20,6 +19,9 @@ from pprint import pprint from urllib.parse import urljoin +import requests +import click + from html2text import HTML2Text from PIL import Image @@ -64,6 +66,14 @@ for key in dir(module): if key.isupper(): conf[key] = getattr(module, key) + + conf['DATADIR'] = os.path.dirname(filename) + for key in 'DATABASE', 'GNUPGHOME': + # if path is not absolute, it is interpreted as relative + # to the location of the configuration file + if not os.path.isabs(conf[key]): + conf[key] = os.path.join(conf['DATADIR'], conf[key]) + return conf @@ -314,20 +324,68 @@ v = self.validate(r) return v['data'] + def records(self): + # required to set some cookies required by the next call + url = urljoin(URL, 'fr/connexion/virements-services/releves-en-ligne') + r = self.session.get(url) + self.validate(r) -def main(): - conffile = sys.argv[1] - conf = loadconf(conffile) + url = urljoin(URL, 'demat-wspl/rest/initialisationDemat') + r = self.session.get(url) + v = self.validate(r) + + for branch in v['data']['initialisationDemat']['arbres']: + for leave in branch.get('arbre', ( )): + if leave['typeDoc'] == 'RELEV': + data = leave + break + + self.iban = data['ibans'][0]['ibanCrypte'] + query = {'famDoc': data['codeFamille'], + 'idTypeDocument': data['idBranche'], + 'listeIbanCrypte': [ self.iban, ], + 'typeCpt': data['typeCompte'], + 'typeDoc': data['typeDoc'], + 'typeFamille': 'R001'} # ??? + + url = urljoin(URL, 'demat-wspl/rest/consultationDemat') + data = json.dumps(query) + headers = {'Content-Type': 'application/json'} + r = self.session.post(url, headers=headers, data=data) + v = self.validate(r) - datadir = os.path.dirname(conffile) - for key in 'DATABASE', 'GNUPGHOME': - # if path is not absolute, it is interpreted as relative - # to the location of the configuration file - if not os.path.isabs(conf[key]): - conf[key] = os.path.join(datadir, conf[key]) + years = v['data']['consultationDemat']['listeCompte'][0]['listeAnnee'] + query['codeProduit'] = '' + documents = [] + + url = urljoin(URL, 'demat-wspl/rest/rechercheDemat') + for year in years: + query['anneeSelectionnee'] = year + data = json.dumps(query) + r = self.session.post(url, headers=headers, data=data) + v = self.validate(r) + documents += v['data']['consultationDemat']['listeCompte'][0]['listeDocument'] + + return documents + def document(self, x): + url = urljoin(URL, 'demat-wspl/rest/consultationDocumentDemat') + params = {'consulted': x['consulted'], + 'familleDoc': x['famDoc'], + 'ibanCrypte': self.iban, + 'idDocument': x['idDoc'], + 'idLocalisation': 'undefined', + 'typeCpt': x['typeCompte'], + 'typeDoc': x['typeDoc'], + 'viDocDocument': x['viDocDocument'], + 'typeFamille': 'R001'} + r = self.session.get(url, params=params) + self.validate(r) + return r.content + + +def transactions(conf): db = sqlite3.connect(conf['DATABASE']) - db.execute('''CREATE TABLE IF NOT EXISTS messages (id TEXT PRIMARY KEY)''') db.execute('''CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY)''') sendmail = Mailer(host=conf['SMTPHOST'], @@ -341,7 +399,6 @@ remote = BNPParibas() remote.login(conf['USERNAME'], conf['PASSWORD']) - ## transactions recent = remote.recent() data = recent['listerOperations']['compte'] transactions = [ Transaction.fromjson(x) for x in data['operationPassee'] ] @@ -378,7 +435,22 @@ curs.executemany('''INSERT INTO transactions (id) VALUES (?)''', ((x.id, ) for x in unseen)) db.commit() - ## messages + +def messages(conf): + db = sqlite3.connect(conf['DATABASE']) + db.execute('''CREATE TABLE IF NOT EXISTS messages (id TEXT PRIMARY KEY)''') + + sendmail = Mailer(host=conf['SMTPHOST'], + port=conf['SMTPPORT'], + starttls=conf['SMTPSTARTTLS'], + username=conf['SMTPUSER'], + password=conf['SMTPPASSWD']).send + + encrypt = GPG(conf['GNUPGHOME']).encrypt + + remote = BNPParibas() + remote.login(conf['USERNAME'], conf['PASSWORD']) + data = remote.info() info = data['abonnement'] nnew = info['nombreMessageBMMNonLus'] + info['nombreMessageBilatNonLus'] @@ -407,5 +479,54 @@ db.commit() +def records(conf): + db = sqlite3.connect(conf['DATABASE']) + db.execute('''CREATE TABLE IF NOT EXISTS records (id TEXT PRIMARY KEY)''') + + remote = BNPParibas() + data = remote.login(conf['USERNAME'], conf['PASSWORD']) + + records = remote.records() + for r in records: + + curs = db.cursor() + curs.execute('''SELECT COUNT(*) FROM records WHERE id = ?''', (r['idDoc'], )) + if curs.fetchone()[0]: + # already handled + continue + + data = remote.document(r) + date = datetime.strptime(r['dateDoc'], '%d/%m/%Y').strftime('bnpparibas-%Y%m%d.pdf') + filename = os.path.join(conf['DATADIR'], 'data', date) + if conf.get('VERBOSE'): + print(r['idDoc'], filename) + with open(filename, 'wb') as fd: + fd.write(data) + + curs.execute('''INSERT INTO records (id) VALUES (?)''', (r['idDoc'], )) + db.commit() + + +@click.command() +@click.argument('conffile') +@click.option('--transactions', 'what', multiple=True, flag_value='transactions', help='Email new transactions.') +@click.option('--messages', 'what', multiple=True, flag_value='messages', help='Email new messages.') +@click.option('--records', 'what', multiple=True, flag_value='records', help='Download new montly records.') +@click.option('--verbose', is_flag=True, help='Verbose output.') +def main(conffile, what, verbose): + + actions = {'transactions': transactions, + 'messages': messages, + 'records': records} + + conf = loadconf(conffile) + if verbose: + conf['VERBOSE'] = True + + for x in what: + action = actions.get(x) + action(conf) + + if __name__ == '__main__': main()