support full list of accounts (closes #1360)
This commit is contained in:
parent
a6e221f56d
commit
c18ba9072c
2 changed files with 83 additions and 21 deletions
|
|
@ -22,7 +22,7 @@ import urllib
|
||||||
|
|
||||||
from weboob.deprecated.browser import Browser, BrowserIncorrectPassword, BrokenPageError
|
from weboob.deprecated.browser import Browser, BrowserIncorrectPassword, BrokenPageError
|
||||||
|
|
||||||
from .pages import LoginPage, IndexPage, AccountsPage, CardsPage, TransactionsPage, \
|
from .pages import LoginPage, IndexPage, AccountsPage, AccountsFullPage, CardsPage, TransactionsPage, \
|
||||||
UnavailablePage, RedirectPage, HomePage, Login2Page
|
UnavailablePage, RedirectPage, HomePage, Login2Page
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,7 +37,8 @@ class BanquePopulaire(Browser):
|
||||||
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=mesComptes.*': AccountsPage,
|
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=mesComptes.*': AccountsPage,
|
||||||
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=maSyntheseGratuite.*': AccountsPage,
|
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=maSyntheseGratuite.*': AccountsPage,
|
||||||
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=accueilSynthese.*': AccountsPage,
|
'https://[^/]+/cyber/internet/StartTask.do\?taskInfoOID=accueilSynthese.*': AccountsPage,
|
||||||
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=EQUIPEMENT_COMPLET.*': AccountsPage,
|
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=EQUIPEMENT_COMPLET.*': AccountsFullPage,
|
||||||
|
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=VUE_COMPLETE.*': AccountsPage,
|
||||||
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=ENCOURS_COMPTE.*': CardsPage,
|
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=ENCOURS_COMPTE.*': CardsPage,
|
||||||
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=SELECTION_ENCOURS_CARTE.*': TransactionsPage,
|
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=SELECTION_ENCOURS_CARTE.*': TransactionsPage,
|
||||||
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=SOLDE.*': TransactionsPage,
|
'https://[^/]+/cyber/internet/ContinueTask.do\?.*dialogActionPerformed=SOLDE.*': TransactionsPage,
|
||||||
|
|
@ -109,14 +110,22 @@ class BanquePopulaire(Browser):
|
||||||
for a in self.page.iter_accounts(next_pages):
|
for a in self.page.iter_accounts(next_pages):
|
||||||
yield a
|
yield a
|
||||||
|
|
||||||
for next_page in next_pages:
|
while len(next_pages) > 0:
|
||||||
if not self.is_on_page(AccountsPage):
|
next_page = next_pages.pop()
|
||||||
|
|
||||||
|
if not self.is_on_page(AccountsFullPage):
|
||||||
self.go_on_accounts_list()
|
self.go_on_accounts_list()
|
||||||
|
# If there is an action needed to go to the "next page", do it.
|
||||||
|
if 'prevAction' in next_page:
|
||||||
|
params = self.page.get_params()
|
||||||
|
params['dialogActionPerformed'] = next_page.pop('prevAction')
|
||||||
|
params['token'] = self.page.build_token(self.page.get_token())
|
||||||
|
self.location('/cyber/internet/ContinueTask.do', urllib.urlencode(params))
|
||||||
|
|
||||||
next_page['token'] = self.page.build_token(self.page.get_token())
|
next_page['token'] = self.page.build_token(self.page.get_token())
|
||||||
self.location('/cyber/internet/ContinueTask.do', urllib.urlencode(next_page))
|
self.location('/cyber/internet/ContinueTask.do', urllib.urlencode(next_page))
|
||||||
|
|
||||||
for a in self.page.iter_accounts():
|
for a in self.page.iter_accounts(next_pages):
|
||||||
yield a
|
yield a
|
||||||
|
|
||||||
def get_account(self, id):
|
def get_account(self, id):
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,24 @@ class BasePage(_BasePage):
|
||||||
token += token[i]
|
token += token[i]
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
params = {}
|
||||||
|
for field in self.document.xpath('//input'):
|
||||||
|
params[field.attrib['name']] = field.attrib.get('value', '')
|
||||||
|
return params
|
||||||
|
|
||||||
|
def get_button_actions(self):
|
||||||
|
actions = {}
|
||||||
|
for script in self.document.xpath('//script'):
|
||||||
|
if script.text is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for id, action, strategy in re.findall(r'''attEvt\(window,"(?P<id>[^"]+)","click","sab\('(?P<action>[^']+)','(?P<strategy>[^']+)'\);"''', script.text, re.MULTILINE):
|
||||||
|
actions[id] = {'dialogActionPerformed': action,
|
||||||
|
'validationStrategy': strategy,
|
||||||
|
}
|
||||||
|
return actions
|
||||||
|
|
||||||
|
|
||||||
class RedirectPage(BasePage):
|
class RedirectPage(BasePage):
|
||||||
"""
|
"""
|
||||||
|
|
@ -276,14 +294,18 @@ class HomePage(BasePage):
|
||||||
|
|
||||||
|
|
||||||
class AccountsPage(BasePage):
|
class AccountsPage(BasePage):
|
||||||
ACCOUNT_TYPES = {u'Mes comptes d\'épargne': Account.TYPE_SAVINGS,
|
ACCOUNT_TYPES = {u'Mes comptes d\'épargne': Account.TYPE_SAVINGS,
|
||||||
u'Mon épargne': Account.TYPE_SAVINGS,
|
u'Mon épargne': Account.TYPE_SAVINGS,
|
||||||
u'Placements': Account.TYPE_SAVINGS,
|
u'Placements': Account.TYPE_SAVINGS,
|
||||||
u'Mes comptes': Account.TYPE_CHECKING,
|
u'Liste complète de mon épargne': Account.TYPE_SAVINGS,
|
||||||
u'Comptes en euros': Account.TYPE_CHECKING,
|
u'Mes comptes': Account.TYPE_CHECKING,
|
||||||
u'Mes emprunts': Account.TYPE_LOAN,
|
u'Comptes en euros': Account.TYPE_CHECKING,
|
||||||
u'Financements': Account.TYPE_LOAN,
|
u'Liste complète de mes comptes': Account.TYPE_CHECKING,
|
||||||
u'Mes services': None, # ignore this kind of accounts (no bank ones)
|
u'Mes emprunts': Account.TYPE_LOAN,
|
||||||
|
u'Financements': Account.TYPE_LOAN,
|
||||||
|
u'Mes services': None, # ignore this kind of accounts (no bank ones)
|
||||||
|
u'Équipements': None, # ignore this kind of accounts (no bank ones)
|
||||||
|
u'Synthèse': None, # ignore this title
|
||||||
}
|
}
|
||||||
|
|
||||||
def is_error(self):
|
def is_error(self):
|
||||||
|
|
@ -307,12 +329,11 @@ class AccountsPage(BasePage):
|
||||||
def iter_accounts(self, next_pages):
|
def iter_accounts(self, next_pages):
|
||||||
account_type = Account.TYPE_UNKNOWN
|
account_type = Account.TYPE_UNKNOWN
|
||||||
|
|
||||||
params = {}
|
params = self.get_params()
|
||||||
for field in self.document.xpath('//input'):
|
actions = self.get_button_actions()
|
||||||
params[field.attrib['name']] = field.attrib.get('value', '')
|
|
||||||
|
|
||||||
for div in self.document.getroot().cssselect('div.btit'):
|
for div in self.document.getroot().cssselect('div.btit'):
|
||||||
if div.text is None:
|
if div.text in (None, u'Synthèse'):
|
||||||
continue
|
continue
|
||||||
account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)
|
account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)
|
||||||
|
|
||||||
|
|
@ -320,6 +341,15 @@ class AccountsPage(BasePage):
|
||||||
# ignore services accounts
|
# ignore services accounts
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Go to the full list of this kind of account, if any.
|
||||||
|
btn = div.getparent().xpath('.//button/span[text()="Suite"]')
|
||||||
|
if len(btn) > 0:
|
||||||
|
btn = btn[0].getparent()
|
||||||
|
_params = params.copy()
|
||||||
|
_params.update(actions[btn.attrib['id']])
|
||||||
|
next_pages.append(_params)
|
||||||
|
continue
|
||||||
|
|
||||||
currency = None
|
currency = None
|
||||||
for th in div.getnext().xpath('.//thead//th'):
|
for th in div.getnext().xpath('.//thead//th'):
|
||||||
m = re.match('.*\((\w+)\)$', th.text)
|
m = re.match('.*\((\w+)\)$', th.text)
|
||||||
|
|
@ -361,9 +391,24 @@ class AccountsPage(BasePage):
|
||||||
if len(tds) >= 5 and len(tds[self.COL_COMING].xpath('.//a')) > 0:
|
if len(tds) >= 5 and len(tds[self.COL_COMING].xpath('.//a')) > 0:
|
||||||
_params = account._params.copy()
|
_params = account._params.copy()
|
||||||
_params['dialogActionPerformed'] = 'ENCOURS_COMPTE'
|
_params['dialogActionPerformed'] = 'ENCOURS_COMPTE'
|
||||||
|
|
||||||
|
# If there is an action needed before going to the cards page, save it.
|
||||||
|
m = re.search('dialogActionPerformed=([\w_]+)', self.url)
|
||||||
|
if m:
|
||||||
|
_params['prevAction'] = m.group(1)
|
||||||
next_pages.append(_params)
|
next_pages.append(_params)
|
||||||
yield account
|
yield account
|
||||||
|
|
||||||
|
# Needed to preserve navigation.
|
||||||
|
btn = self.document.xpath('.//button/span[text()="Retour"]')
|
||||||
|
if len(btn) > 0:
|
||||||
|
btn = btn[0].getparent()
|
||||||
|
_params = params.copy()
|
||||||
|
_params.update(actions[btn.attrib['id']])
|
||||||
|
self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
|
||||||
|
|
||||||
|
class AccountsFullPage(AccountsPage):
|
||||||
|
pass
|
||||||
|
|
||||||
class CardsPage(BasePage):
|
class CardsPage(BasePage):
|
||||||
COL_ID = 0
|
COL_ID = 0
|
||||||
|
|
@ -372,10 +417,8 @@ class CardsPage(BasePage):
|
||||||
COL_DATE = 3
|
COL_DATE = 3
|
||||||
COL_AMOUNT = 4
|
COL_AMOUNT = 4
|
||||||
|
|
||||||
def iter_accounts(self):
|
def iter_accounts(self, next_pages):
|
||||||
params = {}
|
params = self.get_params()
|
||||||
for field in self.document.xpath('//input'):
|
|
||||||
params[field.attrib['name']] = field.attrib.get('value', '')
|
|
||||||
|
|
||||||
account = None
|
account = None
|
||||||
for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'):
|
for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'):
|
||||||
|
|
@ -387,6 +430,7 @@ class CardsPage(BasePage):
|
||||||
yield account
|
yield account
|
||||||
account = Account()
|
account = Account()
|
||||||
account.id = id.replace(' ', '')
|
account.id = id.replace(' ', '')
|
||||||
|
account.type = Account.TYPE_CARD
|
||||||
account.balance = account.coming = Decimal('0')
|
account.balance = account.coming = Decimal('0')
|
||||||
account._next_debit = datetime.date.today()
|
account._next_debit = datetime.date.today()
|
||||||
account._prev_debit = datetime.date(2000,1,1)
|
account._prev_debit = datetime.date(2000,1,1)
|
||||||
|
|
@ -426,6 +470,15 @@ class CardsPage(BasePage):
|
||||||
if account is not None:
|
if account is not None:
|
||||||
yield account
|
yield account
|
||||||
|
|
||||||
|
# Needed to preserve navigation.
|
||||||
|
btn = self.document.xpath('.//button/span[text()="Retour"]')
|
||||||
|
if len(btn) > 0:
|
||||||
|
btn = btn[0].getparent()
|
||||||
|
actions = self.get_button_actions()
|
||||||
|
_params = params.copy()
|
||||||
|
_params.update(actions[btn.attrib['id']])
|
||||||
|
self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
|
||||||
|
|
||||||
|
|
||||||
class Transaction(FrenchTransaction):
|
class Transaction(FrenchTransaction):
|
||||||
PATTERNS = [(re.compile('^RET DAB (?P<text>.*?) RETRAIT (DU|LE) (?P<dd>\d{2})(?P<mm>\d{2})(?P<yy>\d+).*'),
|
PATTERNS = [(re.compile('^RET DAB (?P<text>.*?) RETRAIT (DU|LE) (?P<dd>\d{2})(?P<mm>\d{2})(?P<yy>\d+).*'),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue