fix coding style and login errors handling

This commit is contained in:
Romain Bignon 2014-04-14 16:41:54 +02:00
commit 558b94e9b9
3 changed files with 54 additions and 40 deletions

View file

@ -20,6 +20,7 @@
from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.capabilities.base import find_object
from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValueBackendPassword, Value
@ -51,12 +52,7 @@ class HSBCBackend(BaseBackend, ICapBank):
yield account
def get_account(self, _id):
with self.browser:
account = self.browser.get_account(_id)
if account:
return account
else:
raise AccountNotFound()
return find_object(self.browser.get_accounts_list(), id=_id, error=AccountNotFound)
def iter_history(self, account):
for tr in self.browser.get_history(account):

View file

@ -18,6 +18,7 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
import ssl
from datetime import timedelta
from weboob.tools.date import LinearDateGuesser
@ -30,22 +31,30 @@ __all__ = ['HSBC']
class HSBC(LoginBrowser):
VERIFY = False
BASEURL = 'https://client.hsbc.fr'
CERTHASH = '48d84a782728eeeb622e9ff721688365e24f555ae1aec49b3be33831c7fe24e6'
connection = URL('https://www.hsbc.fr/1/2/hsbc-france/particuliers/connexion', LoginPage)
login = URL('https://www.hsbc.fr/1/*', LoginPage)
cptPage = URL('/cgi-bin/emcgi.*\&CPT_IdPrestation.*',
'/cgi-bin/emcgi.*\&Ass_IdPrestation.*',
CPTOperationPage)
cbPage = URL('/cgi-bin/emcgi.*\&CB_IdPrestation.*',
CBOperationPage)
accounts = URL('/cgi-bin/emcgi', AccountsPage)
connection = URL(r'https://www.hsbc.fr/1/2/hsbc-france/particuliers/connexion', LoginPage)
login = URL(r'https://www.hsbc.fr/1/*', LoginPage)
cptPage = URL(r'/cgi-bin/emcgi.*\&CPT_IdPrestation.*',
r'/cgi-bin/emcgi.*\&Ass_IdPrestation.*',
CPTOperationPage)
cbPage = URL(r'/cgi-bin/emcgi.*\&CB_IdPrestation.*',
CBOperationPage)
accounts = URL(r'/cgi-bin/emcgi', AccountsPage)
def __init__(self, username, password, secret, *args, **kwargs):
self.secret = secret
LoginBrowser.__init__(self, username, password, *args, **kwargs)
def prepare_request(self, req):
preq = super(HSBC, self).prepare_request(req)
conn = self.session.adapters['https://'].get_connection(preq.url)
conn.ssl_version = ssl.PROTOCOL_TLSv1
return preq
def home(self):
return self.login.go()
@ -58,7 +67,7 @@ class HSBC(LoginBrowser):
raise BrowserIncorrectPassword()
self.location(no_secure_key_link)
self.page.login_w_secure(self.login, self.password, self.secret)
self.page.login_w_secure(self.password, self.secret)
self.page.useless_form()
home_url = self.page.get_frame()
@ -90,7 +99,7 @@ class HSBC(LoginBrowser):
if self.cbPage.is_here():
guesser = LinearDateGuesser(date_max_bump=timedelta(45))
return self.pagination(lambda: self.page.get_history(date_guesser=guesser))
return self.page.get_history(date_guesser=guesser)
else:
return self._get_history()

View file

@ -20,25 +20,26 @@
from urlparse import urlparse, parse_qs
import re
from weboob.tools.browser2.page import HTMLPage, method, ListElement, ItemElement, SkipItem, LoggedPage
from weboob.tools.browser2.filters import Filter, Env, CleanText, CleanDecimal, Link, Field, DateGuesser, TableCell
from weboob.capabilities import NotAvailable
from weboob.capabilities.bank import Account
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
class Transaction(FrenchTransaction):
PATTERNS = [(re.compile('^VIR(EMENT)? (?P<text>.*)'), FrenchTransaction.TYPE_TRANSFER),
(re.compile('^PRLV (?P<text>.*)'), FrenchTransaction.TYPE_ORDER),
(re.compile('^(?P<text>.*) CARTE \d+ PAIEMENT CB\s+(?P<dd>\d{2})(?P<mm>\d{2}) ?(.*)$'),
FrenchTransaction.TYPE_CARD),
(re.compile('^RETRAIT DAB (?P<dd>\d{2})(?P<mm>\d{2}) (?P<text>.*) CARTE [\*\d]+'),
FrenchTransaction.TYPE_WITHDRAWAL),
(re.compile('^CHEQUE( (?P<text>.*))?$'), FrenchTransaction.TYPE_CHECK),
(re.compile('^(F )?COTIS\.? (?P<text>.*)'),FrenchTransaction.TYPE_BANK),
(re.compile('^(REMISE|REM CHQ) (?P<text>.*)'),FrenchTransaction.TYPE_DEPOSIT),
]
from weboob.tools.browser import BrowserIncorrectPassword
from weboob.tools.browser2.page import HTMLPage, method, ListElement, ItemElement, SkipItem, LoggedPage, pagination
from weboob.tools.browser2.filters import Filter, Env, CleanText, CleanDecimal, Link, Field, DateGuesser, TableCell
_is_coming = False
class Transaction(FrenchTransaction):
PATTERNS = [(re.compile(r'^VIR(EMENT)? (?P<text>.*)'), FrenchTransaction.TYPE_TRANSFER),
(re.compile(r'^PRLV (?P<text>.*)'), FrenchTransaction.TYPE_ORDER),
(re.compile(r'^CB (?P<text>.*)\s+(?P<dd>\d+)/(?P<mm>\d+)\s*(?P<loc>.*)'),
FrenchTransaction.TYPE_CARD),
(re.compile(r'^DAB (?P<dd>\d{2})/(?P<mm>\d{2}) ((?P<HH>\d{2})H(?P<MM>\d{2}) )?(?P<text>.*?)( CB N°.*)?$'),
FrenchTransaction.TYPE_WITHDRAWAL),
(re.compile(r'^CHEQUE$'), FrenchTransaction.TYPE_CHECK),
(re.compile(r'^COTIS\.? (?P<text>.*)'), FrenchTransaction.TYPE_BANK),
(re.compile(r'^REMISE (?P<text>.*)'), FrenchTransaction.TYPE_DEPOSIT),
]
class AccountsPage(LoggedPage, HTMLPage):
def get_frame(self):
@ -114,6 +115,7 @@ class Pagination(object):
class CBOperationPage(LoggedPage, HTMLPage):
@pagination
@method
class get_history(Pagination, Transaction.TransactionsElement):
head_xpath = '//table//tr/th'
@ -127,18 +129,22 @@ class CBOperationPage(LoggedPage, HTMLPage):
class CPTOperationPage(LoggedPage, HTMLPage):
def get_history(self):
for script in self.doc.xpath('//script'):
if script.text is None or script.text.find('\nCL(0') < 0:
continue
for script in self.doc.xpath('//script'):
if script.text is None or script.text.find('\nCL(0') < 0:
continue
for m in re.finditer(r"CL\((\d+),'(.+)','(.+)','(.+)','([\d -\.,]+)',('([\d -\.,]+)',)?'\d+','\d+','[\w\s]+'\);", script.text, flags=re.MULTILINE):
op = Transaction(m.group(1))
op.parse(date=m.group(3), raw=re.sub(u'[ ]+', u' ', m.group(4).replace(u'\n', u' ')))
op.set_amount(m.group(5))
op._coming = (re.match('\d+/\d+/\d+', m.group(2)) is None)
yield op
for m in re.finditer(r"CL\((\d+),'(.+)','(.+)','(.+)','([\d -\.,]+)',('([\d -\.,]+)',)?'\d+','\d+','[\w\s]+'\);", script.text, flags=re.MULTILINE):
op = Transaction(m.group(1))
op.parse(date=m.group(3), raw=re.sub(u'[ ]+', u' ', m.group(4).replace(u'\n', u' ')))
op.set_amount(m.group(5))
op._coming = (re.match(r'\d+/\d+/\d+', m.group(2)) is None)
yield op
class LoginPage(HTMLPage):
def on_load(self):
for message in self.doc.getroot().cssselect('div.csPanelErrors, div.csPanelAlert'):
raise BrowserIncorrectPassword(CleanText('.')(message))
def login(self, login):
form = self.get_form(nr=2)
form['userid'] = login
@ -152,12 +158,15 @@ class LoginPage(HTMLPage):
else:
return a.attrib['href']
def login_w_secure(self, login, password, secret):
def login_w_secure(self, password, secret):
form = self.get_form(nr=0)
form['memorableAnswer'] = secret
inputs = self.doc.xpath(u'//input[starts-with(@id, "keyrcc_password_first")]')
split_pass = u''
for i,inpu in enumerate(inputs):
if len(password) != len(inputs):
raise BrowserIncorrectPassword('Your password must be %d chars long' % len(inputs))
for i, inpu in enumerate(inputs):
#The good field are 1,2,3 and the bad one are 11,12,21,23,24,31 and so one
if int(inpu.attrib['id'].split('first')[1]) < 10:
split_pass += password[i]