annotate bnpparibas.py @ 7:90f4e0bd0c2d

Almost complete rewrite to adapt to the new BNP Paribas website
author Daniele Nicolodi <daniele@grinta.net>
date Mon, 11 Jan 2016 19:01:00 +0100
parents 13a8bc43bc09
children 225885e803b4
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
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
2 import imp
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
3 import itertools
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
4 import json
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
5 import os.path
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
6 import requests
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
7 import smtplib
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
8 import sqlite3
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
9 import textwrap
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
10 import time
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
11
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
12 from contextlib import contextmanager
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
13 from email.mime.text import MIMEText
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
14 from email.utils import format_datetime, localtime, parseaddr
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
15 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
16 from pprint import pprint
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
17 from urllib.parse import urljoin
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
18
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
19 from bs4 import BeautifulSoup
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
20 from html2text import HTML2Text
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
21 from PIL import Image
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
22
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
23
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
24 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
25
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
26 # message template
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
27 MESSAGE = """\
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
28 From: {message.sender:}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
29 Subject: {message.subject:}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
30 Date: {message.date:}
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
31
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
32 {message.body:}
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
33 """
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
34
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
35 # 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
36 TRANSACTION = """{xact.id:14d} {xact.date:10s} {xact.description:54s} {xact.amount:+8.2f}"""
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
37
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
38 # transactions table header
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
39 HEADER = """{:14s} {:10s} {:54s} {:>8s}""".format('Id', 'Date', 'Description', 'Amount')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
40
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
41 # transactions table footer
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
42 FOOTER = """{:14s} {:10s} {:54s} {{balance:8.2f}}""".format('', '', 'BALANCE')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
43
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
44 # 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
45 SEP = """-""" * len(HEADER)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
46
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
47
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
48 def loadconf(filename):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
49 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
50 module.__file__ = filename
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
51 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
52 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
53 conf = {}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
54 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
55 if key.isupper():
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
56 conf[key] = getattr(module, key)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
57 return conf
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
58
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
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 wrap(p, indent):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
61 return textwrap.fill(p, 72, initial_indent=indent, subsequent_indent=indent)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
62
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
63
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
64 def html2text(html):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
65 # 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
66 # 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
67 conv = HTML2Text()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
68 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
69 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
70 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
71 return conv.handle(html)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
72
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
73
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
74 class Mailer:
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
75 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
76 self.host = host
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
77 self.port = port
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
78 self.starttls = starttls
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
79 self.username = username
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
80 self.password = password
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
81
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
82 @contextmanager
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
83 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
84 smtp = smtplib.SMTP(self.host, self.port)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
85 if self.starttls:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
86 smtp.starttls()
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
87 if self.username:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
88 smtp.login(self.username, self.password)
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
89 yield smtp
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
90 smtp.quit()
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
91
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
92 def send(self, message, fromaddr=None, toaddr=None):
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
93 if not fromaddr:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
94 fromaddr = message['From']
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
95 if not toaddr:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
96 toaddr = message['To']
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
97 with self.connect() as conn:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
98 conn.sendmail(fromaddr, toaddr, str(message))
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
99
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
100
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
101 class GPG:
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
102 def __init__(self, homedir):
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
103 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
104
3
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
105 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
106 sender = parseaddr(sender)[1]
1311f6533978 Load configuration from file specified on the command line
Daniele Nicolodi <daniele@grinta.net>
parents: 2
diff changeset
107 recipient = parseaddr(recipient)[1]
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
108 cmd = [ "gpg", "--homedir", self.homedir, "--sign", "--encrypt"
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
109 "--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
110 "--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
111 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
5
Daniele Nicolodi <daniele@grinta.net>
parents: 4
diff changeset
112 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
113 if p.returncode:
b4c2db70bbf2 Detect and report gpg invocations errors
Daniele Nicolodi <daniele@grinta.net>
parents: 3
diff changeset
114 raise RuntimeError(p.returncode, err)
5
Daniele Nicolodi <daniele@grinta.net>
parents: 4
diff changeset
115 return encdata.decode('ascii')
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
116
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
117
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
118 class Transaction:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
119 __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
120
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
121 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
122 self.id = id
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
123 self.date = date
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
124 self.category = category
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
125 self.description = description
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
126 self.amount = amount
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
127 self.currency = currency
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
128
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
129 @classmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
130 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
131 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
132 'date': x['dateOperation'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
133 '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
134 '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
135 '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
136 '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
137 return cls(**data)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
138
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
139 def __str__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
140 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
141
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
142
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
143 class Message:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
144 __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
145
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
146 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
147 self.id = id
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
148 self.date = date
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
149 self.subject = subject
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
150 self.sender = sender
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
151 self.content = content
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
152 self.quoted = quoted
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
153
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
154 @classmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
155 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
156 data = {'id': x['msg']['id'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
157 'date': x['msg']['id'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
158 '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
159 '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
160 '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
161 'quoted': None, }
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
162 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
163 if quoted:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
164 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
165 return cls(**data)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
166
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
167 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
168 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
169 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
170 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
171 return html2text(txt)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
172
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
173 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
174 parts = []
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
175 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
176 p = p.strip()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
177 if p:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
178 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
179 else:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
180 p = indent
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
181 parts.append(p)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
182 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
183
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
184 @property
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
185 def body(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
186 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
187 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
188 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
189 return body
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
190
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
191 def __str__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
192 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
193
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
194
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
195 class Keypad:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
196 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
197 # reference keypad
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
198 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
199 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
200 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
201 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
202
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
203 # decode keypad
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
204 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
205 self.keymap = {}
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
206 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
207 # 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
208 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
209 if tile == key:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
210 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
211 break
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
212
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
213 # verify
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
214 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
215 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
216
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
217 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
218 def imslice(image):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
219 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
220 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
221
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
222 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
223 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
224
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
225
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
226 class BNPParibas:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
227 def __init__(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
228 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
229 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
230
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
231 @staticmethod
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
232 def validate(response):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
233 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
234 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
235 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
236 data = response.json()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
237 # 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
238 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
239 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
240 raise requests.HTTPError()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
241 return data
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
242
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
243 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
244 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
245 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
246 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
247
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
248 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
249 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
250
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
251 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
252 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
253 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
254
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
255 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
256
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
257 # fill authentication template
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
258 auth = authtemplate
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
259 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
260 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
261 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
262
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
263 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
264 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
265 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
266 return v['data']
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 def info(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
269 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
270 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
271 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
272 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
273
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
274 def recent(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
275 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
276 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
277 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
278 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
279
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
280 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
281 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
282 'pastOrPending': 1, 'triAV': 0,
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
283 'startDate': None, # ddmmyyyy
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
284 'endDate': None})
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
285 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
286 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
287 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
288 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
289
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
290 def messages(self):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
291 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
292 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
293 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
294 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
295
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
296 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
297 # 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
298 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
299 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
300 self.validate(r)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
301
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
302 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
303 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
304 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
305 return v['data']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
306
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
307
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
308 def main(conffile):
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
309 conf = loadconf(conffile)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
310
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
311 db = sqlite3.connect(conf['DATABASE'])
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
312 db.execute('''CREATE TABLE IF NOT EXISTS messages (id TEXT PRIMARY KEY)''')
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
313 db.execute('''CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY)''')
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
314
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
315 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
316 port=conf['SMTPPORT'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
317 starttls=conf['SMTPSTARTTLS'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
318 username=conf['SMTPUSER'],
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
319 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
320
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
321 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
322
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
323 remote = BNPParibas()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
324 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
325
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
326 ## transactions
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
327 recent = remote.recent()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
328 data = recent['listerOperations']['compte']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
329 transactions = [ Transaction.fromjson(x) for x in data['operationPassee'] ]
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
330 balance = data['soldeDispo']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
331
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
332 curs = db.cursor()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
333 unseen = []
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
334 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
335 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
336 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
337 # not seen before
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
338 unseen.append(t)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
339
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
340 lines = []
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
341 lines.append(HEADER)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
342 lines.append(SEP)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
343 for t in unseen:
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
344 lines.append(str(t))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
345 lines.append(SEP)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
346 lines.append(FOOTER.format(balance=balance))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
347 body = '\n'.join(lines)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
348
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
349 message = MIMEText(encrypt(body, conf['MAILFROM'], conf['MAILTO']))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
350 message['Subject'] = 'BNP Paribas Account update'
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
351 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
352 message['To'] = conf['MAILTO']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
353 message['Date'] = format_datetime(localtime())
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
354
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
355 sendmail(message)
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
356
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
357 curs.executemany('''INSERT INTO transactions (id) VALUES (?)''', ((x.id, ) for x in unseen))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
358 db.commit()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
359
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
360 ## messages
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
361 data = remote.info()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
362 info = data['abonnement']
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
363 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
364
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
365 data = remote.messages()
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
366 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
367
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
368 curs = db.cursor()
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
369 curs.execute('''SELECT COUNT(*) FROM messages WHERE id = ?), 0)''', (m['id'], ))
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
370 if curs.fetchone()[0]:
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
371 # already handled
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
372 continue
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
373
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
374 body = Message.fromjson(remote.message(m['id']))
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
375
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
376 message = MIMEText(encrypt(str(body), conf['MAILFROM'], conf['MAILTO']))
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
377 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
378 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
379 message['To'] = conf['MAILTO']
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
380 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
381
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
382 sendmail(message)
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
383
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
384 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
385 db.commit()
0
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
386
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
387
Daniele Nicolodi <daniele.nicolodi@obspm.fr>
parents:
diff changeset
388 if __name__ == '__main__':
7
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
389 import sys
90f4e0bd0c2d Almost complete rewrite to adapt to the new BNP Paribas website
Daniele Nicolodi <daniele@grinta.net>
parents: 6
diff changeset
390 main(sys.argv[1])