annotate bnpparibas.py @ 9:225885e803b4

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