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 .pages import LoginPage, IndexPage, AccountsPage, CardsPage, TransactionsPage, \
|
||||
from .pages import LoginPage, IndexPage, AccountsPage, AccountsFullPage, CardsPage, TransactionsPage, \
|
||||
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=maSyntheseGratuite.*': 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=SELECTION_ENCOURS_CARTE.*': 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):
|
||||
yield a
|
||||
|
||||
for next_page in next_pages:
|
||||
if not self.is_on_page(AccountsPage):
|
||||
while len(next_pages) > 0:
|
||||
next_page = next_pages.pop()
|
||||
|
||||
if not self.is_on_page(AccountsFullPage):
|
||||
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())
|
||||
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
|
||||
|
||||
def get_account(self, id):
|
||||
|
|
|
|||
|
|
@ -86,6 +86,24 @@ class BasePage(_BasePage):
|
|||
token += token[i]
|
||||
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):
|
||||
"""
|
||||
|
|
@ -276,14 +294,18 @@ class HomePage(BasePage):
|
|||
|
||||
|
||||
class AccountsPage(BasePage):
|
||||
ACCOUNT_TYPES = {u'Mes comptes d\'épargne': Account.TYPE_SAVINGS,
|
||||
u'Mon épargne': Account.TYPE_SAVINGS,
|
||||
u'Placements': Account.TYPE_SAVINGS,
|
||||
u'Mes comptes': Account.TYPE_CHECKING,
|
||||
u'Comptes en euros': Account.TYPE_CHECKING,
|
||||
u'Mes emprunts': Account.TYPE_LOAN,
|
||||
u'Financements': Account.TYPE_LOAN,
|
||||
u'Mes services': None, # ignore this kind of accounts (no bank ones)
|
||||
ACCOUNT_TYPES = {u'Mes comptes d\'épargne': Account.TYPE_SAVINGS,
|
||||
u'Mon épargne': Account.TYPE_SAVINGS,
|
||||
u'Placements': Account.TYPE_SAVINGS,
|
||||
u'Liste complète de mon épargne': Account.TYPE_SAVINGS,
|
||||
u'Mes comptes': Account.TYPE_CHECKING,
|
||||
u'Comptes en euros': Account.TYPE_CHECKING,
|
||||
u'Liste complète de mes comptes': Account.TYPE_CHECKING,
|
||||
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):
|
||||
|
|
@ -307,12 +329,11 @@ class AccountsPage(BasePage):
|
|||
def iter_accounts(self, next_pages):
|
||||
account_type = Account.TYPE_UNKNOWN
|
||||
|
||||
params = {}
|
||||
for field in self.document.xpath('//input'):
|
||||
params[field.attrib['name']] = field.attrib.get('value', '')
|
||||
params = self.get_params()
|
||||
actions = self.get_button_actions()
|
||||
|
||||
for div in self.document.getroot().cssselect('div.btit'):
|
||||
if div.text is None:
|
||||
if div.text in (None, u'Synthèse'):
|
||||
continue
|
||||
account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)
|
||||
|
||||
|
|
@ -320,6 +341,15 @@ class AccountsPage(BasePage):
|
|||
# ignore services accounts
|
||||
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
|
||||
for th in div.getnext().xpath('.//thead//th'):
|
||||
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:
|
||||
_params = account._params.copy()
|
||||
_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)
|
||||
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):
|
||||
COL_ID = 0
|
||||
|
|
@ -372,10 +417,8 @@ class CardsPage(BasePage):
|
|||
COL_DATE = 3
|
||||
COL_AMOUNT = 4
|
||||
|
||||
def iter_accounts(self):
|
||||
params = {}
|
||||
for field in self.document.xpath('//input'):
|
||||
params[field.attrib['name']] = field.attrib.get('value', '')
|
||||
def iter_accounts(self, next_pages):
|
||||
params = self.get_params()
|
||||
|
||||
account = None
|
||||
for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'):
|
||||
|
|
@ -387,6 +430,7 @@ class CardsPage(BasePage):
|
|||
yield account
|
||||
account = Account()
|
||||
account.id = id.replace(' ', '')
|
||||
account.type = Account.TYPE_CARD
|
||||
account.balance = account.coming = Decimal('0')
|
||||
account._next_debit = datetime.date.today()
|
||||
account._prev_debit = datetime.date(2000,1,1)
|
||||
|
|
@ -426,6 +470,15 @@ class CardsPage(BasePage):
|
|||
if account is not None:
|
||||
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):
|
||||
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