# -*- coding: utf-8 -*- # Copyright(C) 2012-2014 Kevin Pouget, Florent Fourcot # # This file is part of weboob. # # weboob is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # weboob is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . import re from weboob.tools.json import json from weboob.capabilities.bank import Account from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage from weboob.browser.filters.standard import Filter, Format, CleanText, CleanDecimal from weboob.browser.elements import ListElement, ItemElement, method class LoginPage(HTMLPage): def login(self, login, password): form = self.get_form(xpath='//form[@id="AuthForm"]') form['j_username'] = login.encode('iso-8859-15') form['j_password'] = password.encode('iso-8859-15') form.submit() class CreditLoggedPage(HTMLPage): def get_error(self): div = self.doc.xpath('//div[@class="errorForm-msg"]') if len(div) == 0: return None msg = u', '.join([li.text.strip() for li in div[0].xpath('.//li')]) return re.sub('[\r\n\t\xa0]+', ' ', msg) class AddType(Filter): types = {u'COMPTE NEF': Account.TYPE_CHECKING, u'CPTE A VUE': Account.TYPE_CHECKING, u'LIVRET AGIR': Account.TYPE_SAVINGS} def filter(self, str_type): for key, acc_type in self.types.items(): if key == str_type: return acc_type return Account.TYPE_UNKNOWN class AccountsPage(LoggedPage, HTMLPage): @method class get_list(ListElement): item_xpath = '//table[has-class("table-synthese")]' class item(ItemElement): klass = Account obj_label = Format('%s %s', CleanText('.//h2[@class="tt_compte"][1]'), CleanText('.//ul[@class="nClient"]/li[1]')) obj_id = CleanText('.//ul[@class="nClient"]/li[last()]', symbols=u'N°') obj_type = AddType(CleanText('.//h2[@class="tt_compte"][1]')) obj_balance = CleanDecimal('.//td[@class="sum_solde"]//span[last()]', replace_dots=True) obj_currency = u'EUR' class Transaction(FrenchTransaction): PATTERNS = [(re.compile('^(?PRETRAIT DAB) (?P
\d{2})-(?P\d{2})-([\d\-]+)'), FrenchTransaction.TYPE_WITHDRAWAL), (re.compile('^RETRAIT DAB (?P
\d{2})-(?P\d{2})-([\d\-]+) (?P.*)'), FrenchTransaction.TYPE_WITHDRAWAL), (re.compile('^CARTE (?P
\d{2})(?P\d{2}) \d+ (?P.*)'), FrenchTransaction.TYPE_CARD), (re.compile('^VIR COOPA (?P
\d{2})/(?P\d{2}) (?P.*)'), FrenchTransaction.TYPE_TRANSFER), (re.compile('^VIR(EMENT|EMT| SEPA EMET :)? (?P.*?)(- .*)?$'), FrenchTransaction.TYPE_TRANSFER), (re.compile('^(PRLV|PRELEVEMENT) (?P.*?)(- .*)?$'), FrenchTransaction.TYPE_ORDER), (re.compile('^CHEQUE.*'), FrenchTransaction.TYPE_CHECK), (re.compile('^(AGIOS /|FRAIS) (?P.*)'), FrenchTransaction.TYPE_BANK), (re.compile('^ABONNEMENT (?P.*)'), FrenchTransaction.TYPE_BANK), (re.compile('^REMISE (?P.*)'), FrenchTransaction.TYPE_DEPOSIT), (re.compile('^(?P.*)( \d+)? QUITTANCE .*'), FrenchTransaction.TYPE_ORDER), (re.compile('^.* LE (?P
\d{2})/(?P\d{2})/(?P\d{2})$'), FrenchTransaction.TYPE_UNKNOWN), ] class TransactionsPage(LoggedPage, HTMLPage): pass class TransactionsJSONPage(LoggedPage, JsonPage): ROW_DATE = 0 ROW_TEXT = 2 ROW_CREDIT = -1 ROW_DEBIT = -2 def get_transactions(self): seen = set() for tr in self.doc['exportData'][1:]: t = Transaction(0) t.parse(tr[self.ROW_DATE], tr[self.ROW_TEXT]) t.set_amount(tr[self.ROW_CREDIT], tr[self.ROW_DEBIT]) t.id = t.unique_id(seen) yield t class ComingTransactionsPage(LoggedPage, HTMLPage): ROW_REF = 0 ROW_TEXT = 1 ROW_DATE = 2 ROW_CREDIT = -1 ROW_DEBIT = -2 def get_transactions(self): data = [] for script in self.doc.xpath('//script'): txt = script.text if txt is None: continue pattern = 'var jsonData =' start = txt.find(pattern) if start < 0: continue txt = txt[start+len(pattern):start+txt[start:].find(';')] data = json.loads(txt) break for tr in data: t = Transaction(0) t.parse(tr[self.ROW_DATE], tr[self.ROW_TEXT]) t.set_amount(tr[self.ROW_CREDIT], tr[self.ROW_DEBIT]) yield t