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'])