diff --git a/modules/ing/__init__.py b/modules/ing/__init__.py index 134b07d0..7bf141e7 100644 --- a/modules/ing/__init__.py +++ b/modules/ing/__init__.py @@ -20,4 +20,5 @@ from .backend import INGBackend + __all__ = ['INGBackend'] diff --git a/modules/ing/backend.py b/modules/ing/backend.py index 0544e80b..42469f9c 100644 --- a/modules/ing/backend.py +++ b/modules/ing/backend.py @@ -38,9 +38,16 @@ class INGBackend(BaseBackend, ICapBank): VERSION = '0.b' LICENSE = 'AGPLv3+' DESCRIPTION = 'ING Direct French bank website' - CONFIG = BackendConfig(ValueBackendPassword('login', label='Account ID', masked=False), - ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'), - ValueBackendPassword('birthday', label='Birthday', regexp='^(\d{8}|)$', masked=False) + CONFIG = BackendConfig(ValueBackendPassword('login', + label='Account ID', + masked=False), + ValueBackendPassword('password', + label='Password', + regexp='^(\d{6}|)$'), + ValueBackendPassword('birthday', + label='Birthday', + regexp='^(\d{8}|)$', + masked=False) ) BROWSER = Ing @@ -72,4 +79,3 @@ class INGBackend(BaseBackend, ICapBank): with self.browser: for coming in self.browser.get_coming_operations(account.id): yield coming - diff --git a/modules/ing/browser.py b/modules/ing/browser.py index 2555b146..6311de27 100644 --- a/modules/ing/browser.py +++ b/modules/ing/browser.py @@ -29,7 +29,7 @@ __all__ = ['Ing'] class Ing(BaseBrowser): DOMAIN = 'secure.ingdirect.fr' PROTOCOL = 'https' - ENCODING = None # refer to the HTML encoding + ENCODING = None # refer to the HTML encoding PAGES = {'.*displayTRAccountSummary.*': AccountsList, '.*displayLogin.jsf': LoginPage, '.*displayLogin.jsf.*': LoginPage2, @@ -38,7 +38,7 @@ class Ing(BaseBrowser): } def __init__(self, *args, **kwargs): - self.birthday = kwargs.pop('birthday', None) + self.birthday = kwargs.pop('birthday', None) BaseBrowser.__init__(self, *args, **kwargs) def home(self): @@ -55,10 +55,11 @@ class Ing(BaseBrowser): assert self.birthday.isdigit() if not self.is_on_page(LoginPage): - self.location('https://secure.ingdirect.fr/public/displayLogin.jsf') + self.location('https://secure.ingdirect.fr/\ + public/displayLogin.jsf') self.page.prelogin(self.username, self.birthday) - self.page.login(self.password) + self.page.login(self.password) def get_accounts_list(self): if not self.is_on_page(AccountsList): @@ -83,12 +84,16 @@ class Ing(BaseBrowser): account = self.get_account(id) # The first and the second letter of the label are the account type if account.label[0:2] == "CC": - self.location('https://secure.ingdirect.fr/protected/pages/cc/accountDetail.jsf') + self.location('https://secure.ingdirect.fr/\ + protected/pages/cc/accountDetail.jsf') elif account.label[0:2] == "LA": - # we want "displayTRHistoriqueLA" but this fucking page is not directly available... - self.location('https://secure.ingdirect.fr/general?command=goToAccount&account=%d&zone=COMPTE' % int(id)) + # we want "displayTRHistoriqueLA" but this fucking page + # is not directly available... + self.location('https://secure.ingdirect.fr/\ + general?command=goToAccount&account=%d&zone=COMPTE'\ + % int(id)) else: - raise NotImplementedError() + raise NotImplementedError() return self.page.get_transactions() # TODO diff --git a/modules/ing/pages/__init__.py b/modules/ing/pages/__init__.py index 1595c5ef..a1b7737b 100644 --- a/modules/ing/pages/__init__.py +++ b/modules/ing/pages/__init__.py @@ -22,7 +22,9 @@ from .accounts_list import AccountsList from .account_history import AccountHistoryCC, AccountHistoryLA from .login import LoginPage, LoginPage2, ConfirmPage, MessagePage -class AccountPrelevement(AccountsList): pass -__all__ = ['AccountsList', 'AccountHistoryCC', 'AccountHistoryLA', 'LoginPage', 'LoginPage2', - 'ConfirmPage', 'MessagePage', 'AccountPrelevement'] +class AccountPrelevement(AccountsList): + pass + +__all__ = ['AccountsList', 'AccountHistoryCC', 'AccountHistoryLA', 'LoginPage', + 'LoginPage2', 'ConfirmPage', 'MessagePage', 'AccountPrelevement'] diff --git a/modules/ing/pages/account_history.py b/modules/ing/pages/account_history.py index e66514d2..e9efae85 100644 --- a/modules/ing/pages/account_history.py +++ b/modules/ing/pages/account_history.py @@ -27,11 +27,9 @@ from weboob.capabilities.base import NotAvailable __all__ = ['AccountHistoryCC', 'AccountHistoryLA'] - - class AccountHistoryCC(BasePage): - types = { - 'Carte achat': Transaction.TYPE_CARD, + types = { + 'Carte achat': Transaction.TYPE_CARD, 'Virement': Transaction.TYPE_TRANSFER, 'Carte retrait': Transaction.TYPE_WITHDRAWAL, u'Prélèvement': Transaction.TYPE_ORDER, @@ -47,12 +45,13 @@ class AccountHistoryCC(BasePage): texte = tr.text_content().split('\n') op = Transaction(id) op.label = texte[2] - op.raw = texte[2] # nothing to parse + op.raw = texte[2] # nothing to parse op.date = date(*reversed([int(x) for x in texte[0].split('/')])) op.category = texte[4] op.type = self.types.get(texte[4], Transaction.TYPE_UNKNOWN) - amount = texte[5].replace('\t','').strip().replace(u'€', '').replace(',', '.').replace(u'\xa0', u'') + amount = texte[5].replace('\t', '').strip().replace(u'€', '').\ + replace(',', '.').replace(u'\xa0', u'') op.amount = float(amount) self.transactions.append(op) @@ -61,6 +60,7 @@ class AccountHistoryCC(BasePage): def get_transactions(self): return self.transactions + class AccountHistoryLA(BasePage): def on_loaded(self): @@ -69,23 +69,22 @@ class AccountHistoryLA(BasePage): history = self.document.xpath('//tr[@align="center"]') history.pop(0) for tr in history: - id = i - texte = tr.text_content().strip().split('\n') - op = Transaction(id) - # The size is not the same if there are two dates or only one - length = len(texte) - op.raw = unicode(texte[length - 2].strip()) - op.date = date(*reversed([int(x) for x in texte[0].split('/')])) - op.category = NotAvailable + id = i + texte = tr.text_content().strip().split('\n') + op = Transaction(id) + # The size is not the same if there are two dates or only one + length = len(texte) + op.raw = unicode(texte[length - 2].strip()) + op.date = date(*reversed([int(x) for x in texte[0].split('/')])) + op.category = NotAvailable - amount = texte[length - 1].replace('\t','').strip().replace('.', '').replace(u'€', '').replace(',', '.').replace(u'\xa0', u'') - op.amount = float(amount) - - - self.transactions.append(op) - i += 1 + amount = texte[length - 1].replace('\t', '').strip().\ + replace('.', '').replace(u'€', '').\ + replace(',', '.').replace(u'\xa0', u'') + op.amount = float(amount) + self.transactions.append(op) + i += 1 def get_transactions(self): return self.transactions - diff --git a/modules/ing/pages/accounts_list.py b/modules/ing/pages/accounts_list.py index df4ea21d..70a8d3d9 100644 --- a/modules/ing/pages/accounts_list.py +++ b/modules/ing/pages/accounts_list.py @@ -39,15 +39,16 @@ class AccountsList(BasePage): account = Account() link = td.xpath('.//a')[0] account.id = re.search('\d', link.attrib['href']).group(0) - if not ( account.id in ids ) : - ids.append( account.id ) + if not (account.id in ids): + ids.append(account.id) account.label = link.text urltofind = './/a[@href="' + link.attrib['href'] + '"]' linkbis = self.document.xpath(urltofind).pop() - if linkbis.text == link.text : - linkbis=self.document.xpath(urltofind)[1] - account.balance = float( linkbis.text.replace('.','').replace(' ', '').replace(',','.') ) + if linkbis.text == link.text: + linkbis = self.document.xpath(urltofind)[1] + account.balance = float(linkbis.text.replace('.', '').\ + replace(' ', '').replace(',', '.')) account.coming = NotAvailable l.append(account) - return l + return l diff --git a/modules/ing/pages/login.py b/modules/ing/pages/login.py index 280b0eeb..932cb654 100644 --- a/modules/ing/pages/login.py +++ b/modules/ing/pages/login.py @@ -23,33 +23,34 @@ from weboob.tools.mech import ClientForm from logging import error from weboob.tools.browser import BasePage -from weboob.tools.captcha.virtkeyboard import VirtKeyboard,VirtKeyboardError +from weboob.tools.captcha.virtkeyboard import VirtKeyboard, VirtKeyboardError import tempfile + __all__ = ['LoginPage', 'LoginPage2', 'ConfirmPage', 'ChangePasswordPage'] + class INGVirtKeyboard(VirtKeyboard): - symbols={'0':'327208d491507341908cf6920f26b586', - '1':'615ff37b15645da106cebc4605b399de', - '2':'fb04e648c93620f8b187981f9742b57e', - '3':'b786d471a70de83657d57bdedb6a2f38', - '4':'41b5501219e8d8f6d3b0baef3352ce88', - '5':'c72b372fb035160f2ff8dae59cd7e174', - '6':'392fa79e9a1749f5c8c0170f6a8ec68b', - '7':'fb495b5cf7f46201af0b4977899b56d4', - '8':'e8fea1e1aa86f8fca7f771db9a1dca4d', - '9':'82e63914f2e52ec04c11cfc6fecf7e08' - } - color=64 + symbols = {'0': '327208d491507341908cf6920f26b586', + '1': '615ff37b15645da106cebc4605b399de', + '2': 'fb04e648c93620f8b187981f9742b57e', + '3': 'b786d471a70de83657d57bdedb6a2f38', + '4': '41b5501219e8d8f6d3b0baef3352ce88', + '5': 'c72b372fb035160f2ff8dae59cd7e174', + '6': '392fa79e9a1749f5c8c0170f6a8ec68b', + '7': 'fb495b5cf7f46201af0b4977899b56d4', + '8': 'e8fea1e1aa86f8fca7f771db9a1dca4d', + '9': '82e63914f2e52ec04c11cfc6fecf7e08' + } + color = 64 - - def __init__(self,basepage): + def __init__(self, basepage): divkeyboard = basepage.document.find("//div[@id='clavierdisplayLogin']") img = divkeyboard.xpath("img")[1] if img is None: return False - url=img.attrib.get("src") - coords={} + url = img.attrib.get("src") + coords = {} coords["11"] = (5, 5, 33, 33) coords["21"] = (45, 5, 73, 33) coords["31"] = (85, 5, 113, 33) @@ -66,66 +67,66 @@ class INGVirtKeyboard(VirtKeyboard): if basepage.browser.responses_dirname is None: basepage.browser.responses_dirname = \ tempfile.mkdtemp(prefix='weboob_session_') - self.check_symbols(self.symbols,basepage.browser.responses_dirname) + self.check_symbols(self.symbols, basepage.browser.responses_dirname) - def get_string_code(self,string): - code='' + def get_string_code(self, string): + code = '' first = True for c in string: if not first: - code+="," - else : - first = False + code += "," + else: + first = False codesymbol = self.get_symbol_code(self.symbols[c]) - x = (self.coords[codesymbol][0] + self.coords[codesymbol][2]) / 2 # In the middle + x = (self.coords[codesymbol][0] + self.coords[codesymbol][2]) / 2 y = (self.coords[codesymbol][1] + self.coords[codesymbol][3]) / 2 - code+=str(x) - code+="," - code+=str(y) + code += str(x) + code += "," + code += str(y) return code - class LoginPage(BasePage): def on_loaded(self): - pass + pass def prelogin(self, login, birthday): - # First step : login and birthday + # First step : login and birthday self.browser.select_form('zone1Form') self.browser.set_all_readonly(False) - self.browser['zone1Form:numClient'] = login - self.browser['zone1Form:dateDay'] = birthday[0:2] - self.browser['zone1Form:dateMonth'] = birthday[2:4] - self.browser['zone1Form:dateYear'] = birthday[4:9] - self.browser['zone1Form:radioSaveClientNumber'] = False - self.browser.submit(nologin=True) + self.browser['zone1Form:numClient'] = login + self.browser['zone1Form:dateDay'] = birthday[0:2] + self.browser['zone1Form:dateMonth'] = birthday[2:4] + self.browser['zone1Form:dateYear'] = birthday[4:9] + self.browser['zone1Form:radioSaveClientNumber'] = False + self.browser.submit(nologin=True) + class LoginPage2(BasePage): def on_loaded(self): pass def login(self, password): - # 2) And now, the virtual Keyboard + # 2) And now, the virtual Keyboard try: - vk=INGVirtKeyboard(self) - except VirtKeyboardError,err: - error("Error: %s"%err) + vk = INGVirtKeyboard(self) + except VirtKeyboardError, err: + error("Error: %s" % err) return False realpasswd = "" span = self.document.find('//span[@id="digitpaddisplayLogin"]') i = 0 for font in span.getiterator('font'): - if font.attrib.get('class') == "vide": - realpasswd += password[i] - i+=1 + if font.attrib.get('class') == "vide": + realpasswd += password[i] + i += 1 self.browser.logger.debug('We are looking for : ' + realpasswd) self.browser.select_form('mrc') self.browser.set_all_readonly(False) - self.browser.logger.debug("Coordonates: "+ vk.get_string_code(realpasswd)) + self.browser.logger.debug("Coordonates: " + vk.get_string_code(realpasswd)) self.browser.controls.append(ClientForm.TextControl('text', 'mrc:mrg', {'value': ''})) self.browser.controls.append(ClientForm.TextControl('text', 'AJAXREQUEST', {'value': ''})) - self.browser['AJAXREQUEST']='_viewRoot' + self.browser['AJAXREQUEST'] = '_viewRoot' self.browser['mrc:mrldisplayLogin'] = vk.get_string_code(realpasswd) self.browser['mrc:mrg'] = 'mrc:mrg' self.browser.submit(nologin=True) @@ -144,11 +145,12 @@ class ConfirmPage(BasePage): if m: return m.group(1) + class MessagePage(BasePage): def on_loaded(self): pass + class ChangePasswordPage(BasePage): def on_loaded(self): pass - diff --git a/modules/ing/test.py b/modules/ing/test.py index 2ab2aa54..39df82f9 100644 --- a/modules/ing/test.py +++ b/modules/ing/test.py @@ -20,6 +20,7 @@ from weboob.tools.test import BackendTest + class INGTest(BackendTest): BACKEND = 'ing'