Mercurial > hg > bnpparibas
comparison bnpparibas.py @ 17:80648a7a119c default tip
Update
author | Daniele Nicolodi <daniele@grinta.net> |
---|---|
date | Sun, 21 Jan 2018 01:29:18 +0000 |
parents | af2e222f2dad |
children |
comparison
equal
deleted
inserted
replaced
16:af2e222f2dad | 17:80648a7a119c |
---|---|
9 import subprocess | 9 import subprocess |
10 import sys | 10 import sys |
11 import textwrap | 11 import textwrap |
12 import time | 12 import time |
13 | 13 |
14 from datetime import datetime | |
14 from contextlib import contextmanager | 15 from contextlib import contextmanager |
15 from datetime import datetime | |
16 from email.mime.text import MIMEText | 16 from email.mime.text import MIMEText |
17 from email.utils import format_datetime, localtime, parseaddr | 17 from email.utils import format_datetime, localtime, parseaddr |
18 from io import BytesIO | 18 from io import BytesIO |
19 from pprint import pprint | 19 from pprint import pprint |
20 from urllib.parse import urljoin | 20 from urllib.parse import urljoin |
22 import requests | 22 import requests |
23 import click | 23 import click |
24 | 24 |
25 from html2text import HTML2Text | 25 from html2text import HTML2Text |
26 from PIL import Image | 26 from PIL import Image |
27 | 27 from dateutil.relativedelta import relativedelta |
28 | 28 |
29 URL = 'https://mabanque.bnpparibas/' | 29 URL = 'https://mabanque.bnpparibas/' |
30 | 30 |
31 # message template | 31 # message template |
32 MESSAGE = """\ | 32 MESSAGE = """\ |
172 self.quoted = quoted | 172 self.quoted = quoted |
173 | 173 |
174 @classmethod | 174 @classmethod |
175 def fromjson(cls, x): | 175 def fromjson(cls, x): |
176 data = {'id': x['msg']['id'], | 176 data = {'id': x['msg']['id'], |
177 'date': datetime.strptime(x['msg']['id'], '%Y-%m-%d-%H.%M.%S.%f'), | 177 'date': datetime.datetime.strptime(x['msg']['id'], '%Y-%m-%d-%H.%M.%S.%f'), |
178 'subject': x['msg']['objet'], | 178 'subject': x['msg']['objet'], |
179 'sender': x['msg']['emetteur']['nom'], | 179 'sender': x['msg']['emetteur']['nom'], |
180 'content': x['msg']['contenu'], | 180 'content': x['msg']['contenu'], |
181 'quoted': None, } | 181 'quoted': None, } |
182 quoted = x.get('msgAttache') | 182 quoted = x.get('msgAttache') |
289 url = urljoin(URL, 'serviceinfosclient-wspl/rpc/InfosClient') | 289 url = urljoin(URL, 'serviceinfosclient-wspl/rpc/InfosClient') |
290 r = self.session.get(url, params={'modeAppel': 0}) | 290 r = self.session.get(url, params={'modeAppel': 0}) |
291 v = self.validate(r) | 291 v = self.validate(r) |
292 return v['data'] | 292 return v['data'] |
293 | 293 |
294 def recent(self): | 294 def recent(self, startdate, enddate): |
295 url = urljoin(URL, 'udc-wspl/rest/getlstcpt') | 295 url = urljoin(URL, 'udc-wspl/rest/getlstcpt') |
296 r = self.session.get(url) | 296 r = self.session.get(url) |
297 v = self.validate(r) | 297 v = self.validate(r) |
298 account = v['data']['infoUdc']['familleCompte'][0]['compte'][0] | 298 account = v['data']['infoUdc']['familleCompte'][0]['compte'][0] |
299 | 299 |
300 url = urljoin(URL, 'rop-wspl/rest/releveOp') | 300 url = urljoin(URL, 'rop-wspl/rest/releveOp') |
301 data = json.dumps({'ibanCrypte': account['key'], | 301 data = json.dumps({'ibanCrypte': account['key'], |
302 'pastOrPending': 1, 'triAV': 0, | 302 'pastOrPending': 1, 'triAV': 0, |
303 'startDate': None, # ddmmyyyy | 303 'startDate': '{:%d%m%Y}'.format(startdate), # ddmmyyyy |
304 'endDate': None}) | 304 'endDate': '{:%d%m%Y}'.format(enddate)}) |
305 headers = {'Content-Type': 'application/json'} | 305 headers = {'Content-Type': 'application/json'} |
306 r = self.session.post(url, headers=headers, data=data) | 306 r = self.session.post(url, headers=headers, data=data) |
307 v = self.validate(r) | 307 v = self.validate(r) |
308 return v['data'] | 308 return v['data'] |
309 | 309 |
321 | 321 |
322 url = urljoin(URL, 'bmm-wspl/recupMsg') | 322 url = urljoin(URL, 'bmm-wspl/recupMsg') |
323 r = self.session.get(url, params={'identifiant': mid}) | 323 r = self.session.get(url, params={'identifiant': mid}) |
324 v = self.validate(r) | 324 v = self.validate(r) |
325 return v['data'] | 325 return v['data'] |
326 | |
327 def records0(self): | |
328 # required to set some cookies required by the next call | |
329 url = urljoin(URL, 'fr/connexion/virements-services/releves-en-ligne') | |
330 r = self.session.get(url) | |
331 self.validate(r) | |
332 | |
333 url = urljoin(URL, 'demat-wspl/rest/initialisationDemat') | |
334 r = self.session.get(url) | |
335 v = self.validate(r) | |
336 | |
337 for branch in v['data']['initialisationDemat']['arbres']: | |
338 for leave in branch.get('arbre', ( )): | |
339 if leave['typeDoc'] == 'RELEV': | |
340 data = leave | |
341 break | |
342 | |
343 self.iban = data['ibans'][0]['ibanCrypte'] | |
344 query = {'famDoc': data['codeFamille'], | |
345 'idTypeDocument': data['idBranche'], | |
346 'listeIbanCrypte': [ self.iban, ], | |
347 'typeCpt': data['typeCompte'], | |
348 'typeDoc': data['typeDoc'], | |
349 'typeFamille': 'R001'} # ??? | |
350 | |
351 url = urljoin(URL, 'demat-wspl/rest/consultationDemat') | |
352 data = json.dumps(query) | |
353 headers = {'Content-Type': 'application/json'} | |
354 r = self.session.post(url, headers=headers, data=data) | |
355 v = self.validate(r) | |
356 | |
357 years = v['data']['consultationDemat']['listeCompte'][0]['listeAnnee'] | |
358 query['codeProduit'] = '' | |
359 documents = [] | |
360 | |
361 url = urljoin(URL, 'demat-wspl/rest/rechercheDemat') | |
362 for year in years: | |
363 query['anneeSelectionnee'] = year | |
364 data = json.dumps(query) | |
365 r = self.session.post(url, headers=headers, data=data) | |
366 v = self.validate(r) | |
367 documents += v['data']['consultationDemat']['listeCompte'][0]['listeDocument'] | |
368 | |
369 return documents | |
370 | 326 |
371 def records(self): | 327 def records(self): |
372 url = urljoin(URL, 'fr/connexion/mes-outils/dematerialisation') | 328 url = urljoin(URL, 'fr/connexion/mes-outils/dematerialisation') |
373 r = self.session.get(url) | 329 r = self.session.get(url) |
374 self.validate(r) | 330 self.validate(r) |
401 | 357 |
402 | 358 |
403 def transactions(conf): | 359 def transactions(conf): |
404 db = sqlite3.connect(conf['DATABASE']) | 360 db = sqlite3.connect(conf['DATABASE']) |
405 db.execute('''CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY)''') | 361 db.execute('''CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY)''') |
362 db.execute('''CREATE TABLE IF NOT EXISTS last (date TEXT)''') | |
406 | 363 |
407 sendmail = Mailer(host=conf['SMTPHOST'], | 364 sendmail = Mailer(host=conf['SMTPHOST'], |
408 port=conf['SMTPPORT'], | 365 port=conf['SMTPPORT'], |
409 starttls=conf['SMTPSTARTTLS'], | 366 starttls=conf['SMTPSTARTTLS'], |
410 username=conf['SMTPUSER'], | 367 username=conf['SMTPUSER'], |
413 encrypt = GPG(conf['GNUPGHOME']).encrypt | 370 encrypt = GPG(conf['GNUPGHOME']).encrypt |
414 | 371 |
415 remote = BNPParibas() | 372 remote = BNPParibas() |
416 remote.login(conf['USERNAME'], conf['PASSWORD']) | 373 remote.login(conf['USERNAME'], conf['PASSWORD']) |
417 | 374 |
418 recent = remote.recent() | 375 # last date |
419 data = recent['listerOperations']['compte'] | 376 curs = db.cursor() |
420 transactions = [ Transaction.fromjson(x) for x in data['operationPassee'] ] | 377 curs.execute('''SELECT date FROM last''') |
421 balance = data['soldeDispo'] | 378 row = curs.fetchone() |
379 startdate = datetime.strptime(row[0], '%d-%m-%Y') if row else datetime(2016, 10, 1) | |
380 | |
381 transactions = [] | |
382 while startdate <= datetime.now(): | |
383 enddate = startdate + relativedelta(months=2) | |
384 recent = remote.recent(startdate, enddate) | |
385 data = recent['listerOperations']['compte'] | |
386 transactions += [ Transaction.fromjson(x) for x in data['operationPassee'] ] | |
387 balance = data['soldeDispo'] | |
388 startdate = enddate | |
389 | |
390 transactions.sort(key=lambda x: datetime.strptime(x.date, '%d-%m-%Y')) | |
422 | 391 |
423 curs = db.cursor() | 392 curs = db.cursor() |
424 unseen = [] | 393 unseen = [] |
425 for t in transactions: | 394 for t in transactions: |
426 curs.execute('''SELECT COUNT(*) FROM transactions WHERE id = ?''', (t.id, )) | 395 curs.execute('''SELECT COUNT(*) FROM transactions WHERE id = ?''', (t.id, )) |
447 message['Date'] = format_datetime(localtime()) | 416 message['Date'] = format_datetime(localtime()) |
448 | 417 |
449 sendmail(message) | 418 sendmail(message) |
450 | 419 |
451 curs.executemany('''INSERT INTO transactions (id) VALUES (?)''', ((x.id, ) for x in unseen)) | 420 curs.executemany('''INSERT INTO transactions (id) VALUES (?)''', ((x.id, ) for x in unseen)) |
421 curs.execute('''INSERT OR REPLACE INTO 'last' (date) VALUES (?)''', (transactions[-1].date, )) | |
452 db.commit() | 422 db.commit() |
453 | 423 |
454 | 424 |
455 def messages(conf): | 425 def messages(conf): |
456 db = sqlite3.connect(conf['DATABASE']) | 426 db = sqlite3.connect(conf['DATABASE']) |