diff --git a/modules/carrefourbanque/backend.py b/modules/carrefourbanque/backend.py
index 909634c9..b8d7060e 100644
--- a/modules/carrefourbanque/backend.py
+++ b/modules/carrefourbanque/backend.py
@@ -18,6 +18,7 @@
# along with weboob. If not, see .
+from weboob.capabilities.base import find_object
from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValueBackendPassword
@@ -35,8 +36,8 @@ class CarrefourBanqueBackend(BaseBackend, ICapBank):
VERSION = '0.i'
DESCRIPTION = u'Carrefour Banque'
LICENSE = 'AGPLv3+'
- CONFIG = BackendConfig(ValueBackendPassword('login', label=u'Référent client', masked=False),
- ValueBackendPassword('password', label=u"Code d'accès", regexp='\d+'))
+ CONFIG = BackendConfig(ValueBackendPassword('login', label=u'Votre Identifiant Internet', masked=False),
+ ValueBackendPassword('password', label=u"Code d'accès", regexp=u'\d+'))
BROWSER = CarrefourBanque
def create_default_browser(self):
@@ -44,26 +45,10 @@ class CarrefourBanqueBackend(BaseBackend, ICapBank):
self.config['password'].get())
def iter_accounts(self):
- with self.browser:
- return self.browser.get_accounts_list()
+ return self.browser.get_accounts_list()
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):
- with self.browser:
- for tr in self.browser.iter_history(account):
- if not tr._coming:
- yield tr
-
- def iter_coming(self, account):
- with self.browser:
- for tr in self.browser.iter_history(account):
- if tr._coming:
- yield tr
+ return self.browser.iter_history(account)
diff --git a/modules/carrefourbanque/browser.py b/modules/carrefourbanque/browser.py
index 8968aefe..6b9eb91a 100644
--- a/modules/carrefourbanque/browser.py
+++ b/modules/carrefourbanque/browser.py
@@ -18,36 +18,23 @@
# along with weboob. If not, see .
-import urllib
+from weboob.tools.browser2 import LoginBrowser, URL, need_login
+from weboob.tools.browser import BrowserIncorrectPassword
-from weboob.tools.browser import BaseBrowser
-
-from .pages import LoginPage, HomePage, AccountsPage, TransactionsPage
+from .pages import LoginPage, HomePage, TransactionsPage
__all__ = ['CarrefourBanque']
-class CarrefourBanque(BaseBrowser):
- PROTOCOL = 'https'
- DOMAIN = 'services.carrefour-banque.fr'
- ENCODING = 'iso-8859-15'
- PAGES = {'https?://services.carrefour-banque.fr/s2pnet/publ/identification.do': LoginPage,
- 'https?://services.carrefour-banque.fr/stscripts/run.stn/s2p/SommairePS2P': HomePage,
- 'https?://services.carrefour-banque.fr/s2pnet/priv/disponible.do': AccountsPage,
- 'https?://services.carrefour-banque.fr/s2pnet/priv/consult.do\?btnTelechargement': (TransactionsPage, 'raw'),
- }
+class CarrefourBanque(LoginBrowser):
+ BASEURL = 'https://www.carrefour-banque.fr'
- def is_logged(self):
- return self.page is not None and not self.is_on_page(LoginPage)
+ login = URL('/espace-client/connexion', LoginPage)
+ home = URL('/espace-client$', HomePage)
+ transactions = URL('/espace-client/carte-credit/solde-dernieres-operations.*', TransactionsPage)
- def home(self):
- if self.is_logged():
- self.location('/s2pnet/priv/disponible.do')
- else:
- self.login()
-
- def login(self):
+ def do_login(self):
"""
Attempt to log in.
Note: this method does nothing if we are already logged in.
@@ -55,41 +42,21 @@ class CarrefourBanque(BaseBrowser):
assert isinstance(self.username, basestring)
assert isinstance(self.password, basestring)
- if self.is_logged():
- return
+ self.login.go()
+ self.page.enter_login(self.username)
+ self.page.enter_password(self.password)
- args = {'login': '',
- 'loginCBPASS': self.username.encode(self.ENCODING),
- 'motPasse': self.password.encode(self.ENCODING),
- 'testJS': 'true',
- 'x': 8,
- 'y': 4,
- }
-
- self.location('https://services.carrefour-banque.fr/s2pnet/publ/identification.do', urllib.urlencode(args), no_login=True)
-
- assert self.is_on_page(LoginPage)
-
- # raises BrowserIncorrectPassword if no redirect form is found
- self.page.redirect()
+ if not self.home.is_here():
+ raise BrowserIncorrectPassword()
+ @need_login
def get_accounts_list(self):
- if not self.is_on_page(AccountsPage):
- self.location('/s2pnet/priv/disponible.do')
+ self.home.stay_or_go()
return self.page.get_list()
- def get_account(self, id):
- assert isinstance(id, basestring)
-
- l = self.get_accounts_list()
- for a in l:
- if a.id == id:
- return a
-
- return None
-
+ @need_login
def iter_history(self, account):
- self.location('/s2pnet/priv/consult.do?btnTelechargement')
+ self.location(account._link)
- assert self.is_on_page(TransactionsPage)
+ assert self.transactions.is_here()
return self.page.get_history(account)
diff --git a/modules/carrefourbanque/pages.py b/modules/carrefourbanque/pages.py
index 4647e952..dc89c1c3 100644
--- a/modules/carrefourbanque/pages.py
+++ b/modules/carrefourbanque/pages.py
@@ -18,102 +18,55 @@
# along with weboob. If not, see .
-import datetime
-from decimal import Decimal
import re
-from mechanize import FormNotFoundError
-from weboob.tools.browser import BasePage, BrowserIncorrectPassword
+from weboob.tools.browser2.page import HTMLPage, ListElement, ItemElement, method, LoggedPage
+from weboob.tools.browser2.filters import Regexp, CleanText, CleanDecimal, Format, Link
+
from weboob.capabilities.bank import Account
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
-__all__ = ['LoginPage', 'AccountsPage', 'TransactionsPage']
+__all__ = ['LoginPage', 'HomePage', 'TransactionsPage']
-class LoginPage(BasePage):
- def redirect(self):
- try:
- self.browser.select_form(name='redirectEpargne')
- self.browser.submit(nologin=True)
- except FormNotFoundError:
- raise BrowserIncorrectPassword()
+class LoginPage(HTMLPage):
+ def enter_login(self, username):
+ form = self.get_form(nr=0)
+ form['name'] = username
+ form.submit()
+
+ def enter_password(self, password):
+ form = self.get_form(nr=0)
+ form['pass'] = password
+ form.submit()
-class HomePage(BasePage):
- pass
+class HomePage(LoggedPage, HTMLPage):
+ @method
+ class get_list(ListElement):
+ item_xpath = '//div[@class="three_contenu_table"]'
+
+ class item(ItemElement):
+ klass = Account
+
+ obj_id = Regexp(CleanText('./div[@class="carte_col_leftcol"]/p'), r'(\d+)')
+ obj_label = CleanText('./div[@class="carte_col_leftcol"]/h2')
+ obj_balance = CleanDecimal(Format('-%s', CleanText('.//div[@class="catre_col_one"]/h2')))
+ obj_currency = FrenchTransaction.Currency('.//div[@class="catre_col_one"]/h2')
+ obj__link = Link('.//a[contains(@href, "solde-dernieres-operations")]')
-class AccountsPage(BasePage):
- def get_list(self):
- div = self.document.xpath('//div[@id="descriptifdroite"]')[0]
-
- account = Account()
-
- account.id = re.search(u'(\d+)', div.xpath('.//div[@class="credithauttexte"]')[0].text).group(1)
- account.label = u'Carte PASS'
- account.balance = Decimal('0')
-
- for tr in div.xpath('.//table/tr'):
- tds = tr.findall('td')
-
- if len(tds) < 3:
- continue
-
- label = u''.join([txt.strip() for txt in tds[1].itertext()])
- value = u''.join([txt.strip() for txt in tds[2].itertext()])
-
- if 'encours depuis le dernier' in label.lower():
- coming = u'-' + value
- account.coming = Decimal(FrenchTransaction.clean_amount(coming))
- account.currency = account.get_currency(coming)
- elif u'arrêté de compte' in label.lower():
- m = re.search(u'(\d+)/(\d+)/(\d+)', label)
- if m:
- account._outstanding_date = datetime.date(*reversed(map(int, m.groups())))
- break
-
- yield account
+class Transaction(FrenchTransaction):
+ PATTERNS = [(re.compile(r'^(?P.*?) (?P\d{2})/(?P\d{2})$'), FrenchTransaction.TYPE_CARD)]
-class TransactionsPage(BasePage):
- COL_DATE = 0
- COL_TEXT = 1
- COL_AMOUNT = 2
+class TransactionsPage(LoggedPage, HTMLPage):
+ @method
+ class get_history(Transaction.TransactionsElement):
+ head_xpath = '//table[@id="creditHistory"]//thead/tr/th'
+ item_xpath = '//table[@id="creditHistory"]/tbody/tr'
- def get_history(self, account):
- transactions = []
- last_order = None
-
- for tr in self.document.split('\n')[1:]:
- cols = tr.split(';')
-
- if len(cols) < 4:
- continue
-
- t = FrenchTransaction(0)
- date = cols[self.COL_DATE]
- raw = cols[self.COL_TEXT]
- amount = cols[self.COL_AMOUNT]
-
- t.parse(date, re.sub(r'[ ]+', ' ', raw))
-
- if t.raw.startswith('PRELEVEMENT ACHATS DIFFERES'):
- t._coming = False
- if last_order is None:
- last_order = t.date
- else:
- t._coming = True
-
- t.set_amount(amount)
- transactions.append(t)
-
- # go to the previous stop date before the last order
- while last_order is not None and last_order.day != account._outstanding_date.day:
- last_order = last_order - datetime.timedelta(days=1)
-
- for t in transactions:
- if t.date <= last_order:
- t._coming = False
-
- return iter(transactions)
+ class item(Transaction.TransactionElement):
+ obj_id = None
+ obj_type = Transaction.TYPE_CARD