annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
1 import cgi
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
2 import email
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
3 import imp
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
4 import itertools
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
5 import json
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
6 import os.path
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
7 import smtplib
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
8 import sqlite3
9
Daniele Nicolodi <daniele@grinta.net>
parents: 7
diff changeset
9 import subprocess
Daniele Nicolodi <daniele@grinta.net>
parents: 7
diff changeset
10 import sys
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
11 import textwrap
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
12 import time
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
13
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
14 from datetime import datetime
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
15 from contextlib import contextmanager
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
16 from email.mime.text import MIMEText
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
17 from email.utils import format_datetime, localtime, parseaddr
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
18 from io import BytesIO
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
19 from pprint import pprint
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
20 from urllib.parse import urljoin
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
21
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
22 import requests
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
23 import click
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
24
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
25 from html2text import HTML2Text
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
26 from PIL import Image
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
27 from dateutil.relativedelta import relativedelta
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
28
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
29 URL = 'https://mabanque.bnpparibas/'
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
30
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
31 # message template
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
32 MESSAGE = """\
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
33 From: {message.sender:}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
34 Subject: {message.subject:}
12
4747393db602 Decode messages send time and provide a nicer representation in emails
Daniele Nicolodi <daniele@grinta.net>
parents: 11
diff changeset
35 Date: {message.date:%a, %d %b %Y %H:%M:%S}
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
36
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
37 {message.body:}
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
38 """
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
39
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
40 # transactions table row template
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
41 TRANSACTION = """{xact.id:14d} {xact.date:10s} {xact.description:54s} {xact.amount:+8.2f}"""
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
42
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
43 # transactions table header
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
44 HEADER = """{:14s} {:10s} {:54s} {:>8s}""".format('Id', 'Date', 'Description', 'Amount')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
45
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
46 # transactions table footer
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
47 FOOTER = """{:14s} {:10s} {:54s} {{balance:8.2f}}""".format('', '', 'BALANCE')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
48
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
49 # transactions table horizontal separator
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
50 SEP = """-""" * len(HEADER)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
51
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
52
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
53 # GPG encrypted text is ascii and as such does not require encoding
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
54 # but its decrypted form is utf-8 and therefore the charset header
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
55 # must be set accordingly. define an appropriate charset object
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
56 email.charset.add_charset('utf8 7bit', header_enc=email.charset.SHORTEST,
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
57 body_enc=None, output_charset='utf-8')
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
58
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
59
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
60 def loadconf(filename):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
61 module = imp.new_module('conf')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
62 module.__file__ = filename
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
63 with open(filename) as fd:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
64 exec(compile(fd.read(), filename, 'exec'), module.__dict__)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
65 conf = {}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
66 for key in dir(module):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
67 if key.isupper():
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
68 conf[key] = getattr(module, key)
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
69
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
70 conf['DATADIR'] = os.path.dirname(filename)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
71 for key in 'DATABASE', 'GNUPGHOME':
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
72 # if path is not absolute, it is interpreted as relative
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
73 # to the location of the configuration file
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
74 if not os.path.isabs(conf[key]):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
75 conf[key] = os.path.join(conf['DATADIR'], conf[key])
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
76
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
77 return conf
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
78
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
79
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
80 def wrap(p, indent):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
81 return textwrap.fill(p, 72, initial_indent=indent, subsequent_indent=indent)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
82
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
83
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
84 def html2text(html):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
85 # the html2text module does an ok job, but it can be improved in
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
86 # the quality of the transformation and in the coding style
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
87 conv = HTML2Text()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
88 conv.ignore_links = True
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
89 conv.ignore_images = True
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
90 conv.ignore_emphasis = True
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
91 return conv.handle(html)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
92
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
93
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
94 class Mailer:
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
95 def __init__(self, host='localhost', port=25, starttls=True, username=None, password=None):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
96 self.host = host
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
97 self.port = port
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
98 self.starttls = starttls
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
99 self.username = username
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
100 self.password = password
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
101
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
102 @contextmanager
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
103 def connect(self):
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
104 smtp = smtplib.SMTP(self.host, self.port)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
105 if self.starttls:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
106 smtp.starttls()
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
107 if self.username:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
108 smtp.login(self.username, self.password)
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
109 yield smtp
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
110 smtp.quit()
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
111
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
112 def send(self, message, fromaddr=None, toaddr=None):
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
113 if not fromaddr:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
114 fromaddr = message['From']
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
115 if not toaddr:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
116 toaddr = message['To']
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
117 with self.connect() as conn:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
118 conn.sendmail(fromaddr, toaddr, str(message))
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
119
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
120
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
121 class GPG:
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
122 def __init__(self, homedir):
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
123 self.homedir = homedir
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
124
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
125 def encrypt(self, message, sender, recipient):
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
126 sender = parseaddr(sender)[1]
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
127 recipient = parseaddr(recipient)[1]
10
636ea715af1e Switch to GnuPG v2
Daniele Nicolodi <daniele@grinta.net>
parents: 9
diff changeset
128 cmd = [ "gpg2", "--homedir", self.homedir, "--sign", "--encrypt",
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
129 "--batch", "--no-options", "--yes", "--armor",
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
130 "--local-user", sender, "--recipient", recipient, ]
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
131 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
5
Daniele Nicolodi <daniele@grinta.net>
parents: 4
diff changeset
132 encdata, err = p.communicate(input=message.encode('utf-8'))
4
b4c2db70bbf2 Detect and report gpg invocations errors
Daniele Nicolodi <daniele@grinta.net>
parents: 3
diff changeset
133 if p.returncode:
b4c2db70bbf2 Detect and report gpg invocations errors
Daniele Nicolodi <daniele@grinta.net>
parents: 3
diff changeset
134 raise RuntimeError(p.returncode, err)
5
Daniele Nicolodi <daniele@grinta.net>
parents: 4
diff changeset
135 return encdata.decode('ascii')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
136
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
137
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
138 class Transaction:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
139 __slots__ = 'id', 'date', 'category', 'description', 'amount', 'currency'
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
140
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
141 def __init__(self, id, date, category, description, amount, currency):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
142 self.id = id
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
143 self.date = date
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
144 self.category = category
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
145 self.description = description
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
146 self.amount = amount
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
147 self.currency = currency
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
148
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
149 @classmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
150 def fromjson(cls, x):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
151 data = {'id': int(x['idOperation']),
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
152 'date': x['dateOperation'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
153 'category': int(x['idCategorie']),
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
154 'description': x['libelleOperation'].strip().replace('VIREMENT', 'VIR'),
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
155 'amount': x['montant']['montant'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
156 'currency': x['montant']['currency'], }
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
157 return cls(**data)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
158
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
159 def __str__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
160 return TRANSACTION.format(xact=self)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
161
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
162
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
163 class Message:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
164 __slots__ = 'id', 'date', 'subject', 'sender', 'content', 'quoted'
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
165
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
166 def __init__(self, id, date, subject, sender, content, quoted):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
167 self.id = id
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
168 self.date = date
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
169 self.subject = subject
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
170 self.sender = sender
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
171 self.content = content
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
172 self.quoted = quoted
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
173
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
174 @classmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
175 def fromjson(cls, x):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
176 data = {'id': x['msg']['id'],
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
177 'date': datetime.datetime.strptime(x['msg']['id'], '%Y-%m-%d-%H.%M.%S.%f'),
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
178 'subject': x['msg']['objet'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
179 'sender': x['msg']['emetteur']['nom'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
180 'content': x['msg']['contenu'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
181 'quoted': None, }
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
182 quoted = x.get('msgAttache')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
183 if quoted:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
184 data['quoted'] = quoted['contenu']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
185 return cls(**data)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
186
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
187 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
188 def normalize(txt, indent=''):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
189 if '<div' in txt:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
190 txt = txt.replace('<br></br>','<br/><br/>')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
191 return html2text(txt)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
192
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
193 txt = txt.replace(r'<br/>', '\n')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
194 parts = []
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
195 for p in txt.split('\n'):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
196 p = p.strip()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
197 if p:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
198 p = wrap(p, indent)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
199 else:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
200 p = indent
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
201 parts.append(p)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
202 return '\n'.join(parts)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
203
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
204 @property
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
205 def body(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
206 body = self.normalize(self.content)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
207 if self.quoted is not None:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
208 body = body + '\n\n' + self.normalize(self.quoted, '> ')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
209 return body
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
210
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
211 def __str__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
212 return MESSAGE.format(message=self)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
213
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
214
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
215 class Keypad:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
216 def __init__(self, data):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
217 # reference keypad
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
218 fname = os.path.join(os.path.dirname(__file__), 'keypad.jpeg')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
219 reference = Image.open(fname).convert('L')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
220 symbols = [ 8, 4, 1, 6, 3, 7, 9, 0, 5, 2 ]
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
221 self.keypad = dict(zip(symbols, self.imslice(reference)))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
222
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
223 # decode keypad
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
224 image = Image.open(BytesIO(data)).convert('L')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
225 self.keymap = {}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
226 for n, tile in enumerate(self.imslice(image), 1):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
227 # compare to reference tiles
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
228 for sym, key in self.keypad.items():
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
229 if tile == key:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
230 self.keymap[sym] = n
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
231 break
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
232
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
233 # verify
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
234 if sorted(self.keymap.keys()) != list(range(10)):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
235 raise ValueError('keypad decode failed')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
236
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
237 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
238 def imslice(image):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
239 for j, i in itertools.product(range(2), range(5)):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
240 yield image.crop((83 * i, 80 * j, 83 * (i + 1), 80 * (j + 1)))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
241
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
242 def encode(self, passwd):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
243 return ''.join('%02d' % self.keymap[d] for d in map(int, passwd))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
244
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
245
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
246 class BNPParibas:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
247 def __init__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
248 self.session = requests.Session()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
249 self.session.headers.update({'X-Requested-With': 'XMLHttpRequest'})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
250
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
251 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
252 def validate(response):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
253 response.raise_for_status()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
254 ctype, params = cgi.parse_header(response.headers.get('content-type'))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
255 if ctype == 'application/json':
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
256 data = response.json()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
257 # the status code may sometime be represented as string not int
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
258 code = data.get('codeRetour', -1)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
259 if int(code) != 0:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
260 raise requests.HTTPError()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
261 return data
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
262
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
263 def login(self, username, password):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
264 url = urljoin(URL, 'identification-wspl-pres/identification')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
265 r = self.session.get(url, params={'timestamp': int(time.time())})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
266 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
267
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
268 keypadid = v['data']['grille']['idGrille']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
269 authtemplate = v['data']['authTemplate']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
270
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
271 url = urljoin(URL, 'identification-wspl-pres/grille/' + keypadid)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
272 r = self.session.get(url)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
273 r.raise_for_status()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
274
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
275 keypad = Keypad(r.content)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
276
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
277 # fill authentication template
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
278 auth = authtemplate
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
279 auth = auth.replace('{{ idTelematique }}', username)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
280 auth = auth.replace('{{ password }}', keypad.encode(password))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
281 auth = auth.replace('{{ clientele }}', '')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
282
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
283 url = urljoin(URL, 'SEEA-pa01/devServer/seeaserver')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
284 r = self.session.post(url, data={'AUTH': auth})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
285 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
286 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
287
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
288 def info(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
289 url = urljoin(URL, 'serviceinfosclient-wspl/rpc/InfosClient')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
290 r = self.session.get(url, params={'modeAppel': 0})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
291 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
292 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
293
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
294 def recent(self, startdate, enddate):
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
295 url = urljoin(URL, 'udc-wspl/rest/getlstcpt')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
296 r = self.session.get(url)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
297 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
298 account = v['data']['infoUdc']['familleCompte'][0]['compte'][0]
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
299
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
300 url = urljoin(URL, 'rop-wspl/rest/releveOp')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
301 data = json.dumps({'ibanCrypte': account['key'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
302 'pastOrPending': 1, 'triAV': 0,
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
303 'startDate': '{:%d%m%Y}'.format(startdate), # ddmmyyyy
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
304 'endDate': '{:%d%m%Y}'.format(enddate)})
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
305 headers = {'Content-Type': 'application/json'}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
306 r = self.session.post(url, headers=headers, data=data)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
307 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
308 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
309
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
310 def messages(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
311 url = urljoin(URL, 'bmm-wspl/recupMsgRecu')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
312 r = self.session.get(url, params={'nbMessagesParPage': 200, 'index': 0})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
313 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
314 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
315
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
316 def message(self, mid):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
317 # required to set some cookies required by the next call
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
318 url = urljoin(URL, 'fr/connexion/mes-outils/messagerie')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
319 r = self.session.get(url)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
320 self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
321
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
322 url = urljoin(URL, 'bmm-wspl/recupMsg')
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
323 r = self.session.get(url, params={'identifiant': mid})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
324 v = self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
325 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
326
16
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
327 def records(self):
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
328 url = urljoin(URL, 'fr/connexion/mes-outils/dematerialisation')
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
329 r = self.session.get(url)
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
330 self.validate(r)
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
331
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
332 url = urljoin(URL, 'demat-wspl/rest/listerDocuments')
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
333 r = self.session.get(url)
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
334 v = self.validate(r)
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
335
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
336 data = r.json()['data']
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
337 documents = data['listerDocumentDemat']['mapReleves']['Comptes chèques']['listeDocument']
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
338 return documents
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
339
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
340
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
341 def document(self, x):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
342 url = urljoin(URL, 'demat-wspl/rest/consultationDocumentDemat')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
343 params = {'consulted': x['consulted'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
344 'familleDoc': x['famDoc'],
16
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
345 'ibanCrypte': x['ibanCrypte'],
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
346 'idDocument': x['idDoc'],
16
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
347 'dateDocument': x['dateDoc'],
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
348 'typeCpt': x['typeCompte'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
349 'typeDoc': x['typeDoc'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
350 'viDocDocument': x['viDocDocument'],
16
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
351 'idLocalisation': x['idLocalisation'],
af2e222f2dad Adapt to server side changes
Daniele Nicolodi <daniele@grinta.net>
parents: 14
diff changeset
352 'ikpiPersonne': '',
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
353 'typeFamille': 'R001'}
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
354 r = self.session.get(url, params=params)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
355 self.validate(r)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
356 return r.content
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
357
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
358
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
359 def transactions(conf):
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
360 db = sqlite3.connect(conf['DATABASE'])
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
361 db.execute('''CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY)''')
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
362 db.execute('''CREATE TABLE IF NOT EXISTS last (date TEXT)''')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
363
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
364 sendmail = Mailer(host=conf['SMTPHOST'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
365 port=conf['SMTPPORT'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
366 starttls=conf['SMTPSTARTTLS'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
367 username=conf['SMTPUSER'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
368 password=conf['SMTPPASSWD']).send
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
369
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
370 encrypt = GPG(conf['GNUPGHOME']).encrypt
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
371
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
372 remote = BNPParibas()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
373 remote.login(conf['USERNAME'], conf['PASSWORD'])
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
374
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
375 # last date
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
376 curs = db.cursor()
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
377 curs.execute('''SELECT date FROM last''')
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
378 row = curs.fetchone()
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
379 startdate = datetime.strptime(row[0], '%d-%m-%Y') if row else datetime(2016, 10, 1)
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
380
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
381 transactions = []
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
382 while startdate <= datetime.now():
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
383 enddate = startdate + relativedelta(months=2)
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
384 recent = remote.recent(startdate, enddate)
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
385 data = recent['listerOperations']['compte']
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
386 transactions += [ Transaction.fromjson(x) for x in data['operationPassee'] ]
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
387 balance = data['soldeDispo']
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
388 startdate = enddate
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
389
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
390 transactions.sort(key=lambda x: datetime.strptime(x.date, '%d-%m-%Y'))
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
391
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
392 curs = db.cursor()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
393 unseen = []
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
394 for t in transactions:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
395 curs.execute('''SELECT COUNT(*) FROM transactions WHERE id = ?''', (t.id, ))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
396 if not curs.fetchone()[0]:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
397 # not seen before
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
398 unseen.append(t)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
399
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
400 if unseen:
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
401 lines = []
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
402 lines.append(HEADER)
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
403 lines.append(SEP)
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
404 for t in unseen:
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
405 lines.append(str(t))
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
406 lines.append(SEP)
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
407 lines.append(FOOTER.format(balance=balance))
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
408
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
409 text = '\n'.join(lines)
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
410 payload = encrypt(text, conf['MAILFROM'], conf['MAILTO'])
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
411
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
412 message = MIMEText(payload, _charset='utf8 7bit')
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
413 message['Subject'] = 'BNP Paribas Account update'
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
414 message['From'] = conf['MAILFROM']
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
415 message['To'] = conf['MAILTO']
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
416 message['Date'] = format_datetime(localtime())
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
417
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
418 sendmail(message)
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
419
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
420 curs.executemany('''INSERT INTO transactions (id) VALUES (?)''', ((x.id, ) for x in unseen))
17
Daniele Nicolodi <daniele@grinta.net>
parents: 16
diff changeset
421 curs.execute('''INSERT OR REPLACE INTO 'last' (date) VALUES (?)''', (transactions[-1].date, ))
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
422 db.commit()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
423
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
424
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
425 def messages(conf):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
426 db = sqlite3.connect(conf['DATABASE'])
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
427 db.execute('''CREATE TABLE IF NOT EXISTS messages (id TEXT PRIMARY KEY)''')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
428
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
429 sendmail = Mailer(host=conf['SMTPHOST'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
430 port=conf['SMTPPORT'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
431 starttls=conf['SMTPSTARTTLS'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
432 username=conf['SMTPUSER'],
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
433 password=conf['SMTPPASSWD']).send
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
434
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
435 encrypt = GPG(conf['GNUPGHOME']).encrypt
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
436
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
437 remote = BNPParibas()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
438 remote.login(conf['USERNAME'], conf['PASSWORD'])
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
439
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
440 data = remote.info()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
441 info = data['abonnement']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
442 nnew = info['nombreMessageBMMNonLus'] + info['nombreMessageBilatNonLus']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
443
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
444 data = remote.messages()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
445 for m in data['messages']:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
446
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
447 curs = db.cursor()
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
448 curs.execute('''SELECT COUNT(*) FROM messages WHERE id = ?''', (m['id'], ))
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
449 if curs.fetchone()[0]:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
450 # already handled
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
451 continue
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
452
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
453 text = Message.fromjson(remote.message(m['id']))
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
454 payload = encrypt(str(text), conf['MAILFROM'], conf['MAILTO'])
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
455
11
Daniele Nicolodi <daniele@grinta.net>
parents: 10
diff changeset
456 message = MIMEText(payload, _charset='utf8 7bit')
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
457 message['Subject'] = 'BNP Paribas Message'
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
458 message['From'] = conf['MAILFROM']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
459 message['To'] = conf['MAILTO']
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
460 message['Date'] = format_datetime(localtime())
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
461
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
462 sendmail(message)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
463
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
464 curs.execute('''INSERT INTO messages (id) VALUES (?)''', (m['id'], ))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
465 db.commit()
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
466
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
467
14
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
468 def records(conf):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
469 db = sqlite3.connect(conf['DATABASE'])
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
470 db.execute('''CREATE TABLE IF NOT EXISTS records (id TEXT PRIMARY KEY)''')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
471
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
472 remote = BNPParibas()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
473 data = remote.login(conf['USERNAME'], conf['PASSWORD'])
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
474
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
475 records = remote.records()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
476 for r in records:
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
477
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
478 curs = db.cursor()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
479 curs.execute('''SELECT COUNT(*) FROM records WHERE id = ?''', (r['idDoc'], ))
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
480 if curs.fetchone()[0]:
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
481 # already handled
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
482 continue
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
483
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
484 data = remote.document(r)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
485 date = datetime.strptime(r['dateDoc'], '%d/%m/%Y').strftime('bnpparibas-%Y%m%d.pdf')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
486 filename = os.path.join(conf['DATADIR'], 'data', date)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
487 if conf.get('VERBOSE'):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
488 print(r['idDoc'], filename)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
489 with open(filename, 'wb') as fd:
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
490 fd.write(data)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
491
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
492 curs.execute('''INSERT INTO records (id) VALUES (?)''', (r['idDoc'], ))
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
493 db.commit()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
494
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
495
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
496 @click.command()
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
497 @click.argument('conffile')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
498 @click.option('--transactions', 'what', multiple=True, flag_value='transactions', help='Email new transactions.')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
499 @click.option('--messages', 'what', multiple=True, flag_value='messages', help='Email new messages.')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
500 @click.option('--records', 'what', multiple=True, flag_value='records', help='Download new montly records.')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
501 @click.option('--verbose', is_flag=True, help='Verbose output.')
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
502 def main(conffile, what, verbose):
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
503
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
504 actions = {'transactions': transactions,
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
505 'messages': messages,
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
506 'records': records}
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
507
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
508 conf = loadconf(conffile)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
509 if verbose:
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
510 conf['VERBOSE'] = True
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
511
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
512 for x in what:
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
513 action = actions.get(x)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
514 action(conf)
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
515
0a3509a12762 Implement download of montly records and add command line options
Daniele Nicolodi <daniele@grinta.net>
parents: 13
diff changeset
516
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
517 if __name__ == '__main__':
9
Daniele Nicolodi <daniele@grinta.net>
parents: 7
diff changeset
518 main()