Commit 463b5256 authored by Romain Bignon's avatar Romain Bignon

Update of modules

parent 1bfb0af7
This diff is collapsed.
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2019 Romain Bignon
#
# 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 <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from decimal import Decimal
import re
import json
from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage
from weboob.exceptions import BrowserUnavailable
from weboob.capabilities import NotAvailable
from weboob.capabilities.bank import (
Account, AccountOwnerType,
)
from weboob.browser.elements import DictElement, ItemElement, method
from weboob.browser.filters.standard import (
CleanText, CleanDecimal, Currency as CleanCurrency, Format, Field, Map, Eval
)
from weboob.browser.filters.json import Dict
def float_to_decimal(f):
return Decimal(str(f))
class KeypadPage(JsonPage):
def build_password(self, password):
# Fake Virtual Keyboard: just get the positions of each digit.
key_positions = [i for i in Dict('keyLayout')(self.doc)]
return str(','.join([str(key_positions.index(i)) for i in password]))
def get_keypad_id(self):
return Dict('keypadId')(self.doc)
class LoginPage(HTMLPage):
def get_login_form(self, username, keypad_password, keypad_id):
form = self.get_form(id="loginForm")
form['j_username'] = username
form['j_password'] = keypad_password
form['keypadId'] = keypad_id
return form
class LoggedOutPage(HTMLPage):
def is_here(self):
return self.doc.xpath('//b[text()="FIN DE CONNEXION"]')
def on_load(self):
self.logger.warning('We have been logged out!')
raise BrowserUnavailable()
class SecurityPage(JsonPage):
def get_accounts_url(self):
return Dict('url')(self.doc)
class ContractsPage(LoggedPage, HTMLPage):
pass
ACCOUNT_TYPES = {
'CCHQ': Account.TYPE_CHECKING, # par
'CCOU': Account.TYPE_CHECKING, # pro
'AUTO ENTRP': Account.TYPE_CHECKING, # pro
'DEVISE USD': Account.TYPE_CHECKING,
'EKO': Account.TYPE_CHECKING,
'DAV NANTI': Account.TYPE_SAVINGS,
'LIV A': Account.TYPE_SAVINGS,
'LIV A ASS': Account.TYPE_SAVINGS,
'LDD': Account.TYPE_SAVINGS,
'PEL': Account.TYPE_SAVINGS,
'CEL': Account.TYPE_SAVINGS,
'CODEBIS': Account.TYPE_SAVINGS,
'LJMO': Account.TYPE_SAVINGS,
'CSL': Account.TYPE_SAVINGS,
'LEP': Account.TYPE_SAVINGS,
'LEF': Account.TYPE_SAVINGS,
'TIWI': Account.TYPE_SAVINGS,
'CSL LSO': Account.TYPE_SAVINGS,
'CSL CSP': Account.TYPE_SAVINGS,
'ESPE INTEG': Account.TYPE_SAVINGS,
'DAV TIGERE': Account.TYPE_SAVINGS,
'CPTEXCPRO': Account.TYPE_SAVINGS,
'CPTEXCENT': Account.TYPE_SAVINGS,
'PRET PERSO': Account.TYPE_LOAN,
'P. ENTREPR': Account.TYPE_LOAN,
'P. HABITAT': Account.TYPE_LOAN,
'PRET 0%': Account.TYPE_LOAN,
'INV PRO': Account.TYPE_LOAN,
'TRES. PRO': Account.TYPE_LOAN,
'PEA': Account.TYPE_PEA,
'PEAP': Account.TYPE_PEA,
'DAV PEA': Account.TYPE_PEA,
'CPS': Account.TYPE_MARKET,
'TITR': Account.TYPE_MARKET,
'TITR CTD': Account.TYPE_MARKET,
'PVERT VITA': Account.TYPE_PERP,
'réserves de crédit': Account.TYPE_CHECKING,
'prêts personnels': Account.TYPE_LOAN,
'crédits immobiliers': Account.TYPE_LOAN,
'épargne disponible': Account.TYPE_SAVINGS,
'épargne à terme': Account.TYPE_DEPOSIT,
'épargne boursière': Account.TYPE_MARKET,
'assurance vie et capitalisation': Account.TYPE_LIFE_INSURANCE,
'PRED': Account.TYPE_LIFE_INSURANCE,
'PREDI9 S2': Account.TYPE_LIFE_INSURANCE,
'V.AVENIR': Account.TYPE_LIFE_INSURANCE,
'FLORIA': Account.TYPE_LIFE_INSURANCE,
'ATOUT LIB': Account.TYPE_REVOLVING_CREDIT,
}
class AccountsPage(LoggedPage, JsonPage):
def build_doc(self, content):
# Store the HTML doc to count the number of spaces
self.html_doc = HTMLPage(self.browser, self.response).doc
# Transform the HTML tag containing the accounts list into a JSON
raw = re.search("syntheseController\.init\((.*)\)'>", content).group(1)
d = json.JSONDecoder()
# De-comment this line to debug the JSON accounts:
# print json.dumps(d.raw_decode(raw)[0])
return d.raw_decode(raw)[0]
def count_spaces(self):
# The total number of spaces corresponds to the number
# of available space choices plus the one we are on now:
return len(self.html_doc.xpath('//div[@class="HubAccounts-content"]/a')) + 1
def get_owner_type(self):
OWNER_TYPES = {
'PARTICULIER': AccountOwnerType.PRIVATE,
'PROFESSIONNEL': AccountOwnerType.ORGANIZATION,
'ASSOC_CA_MODERE': AccountOwnerType.ORGANIZATION,
}
return OWNER_TYPES.get(Dict('marche')(self.doc), NotAvailable)
@method
class get_main_account(ItemElement):
klass = Account
obj_id = CleanText(Dict('comptePrincipal/numeroCompte'))
obj_number = CleanText(Dict('comptePrincipal/numeroCompte'))
obj_label = CleanText(Dict('comptePrincipal/libelleProduit'))
obj_balance = Eval(float_to_decimal, Dict('comptePrincipal/solde'))
obj_currency = CleanCurrency(Dict('comptePrincipal/idDevise'))
obj__index = Dict('comptePrincipal/index')
obj__category = None # Main accounts have no category
obj__id_element_contrat = CleanText(Dict('comptePrincipal/idElementContrat'))
def obj_type(self):
_type = Map(CleanText(Dict('comptePrincipal/libelleUsuelProduit')), ACCOUNT_TYPES, Account.TYPE_UNKNOWN)(self)
if _type == Account.TYPE_UNKNOWN:
self.logger.warning('We got an untyped account: please add "%s" to ACCOUNT_TYPES.' % CleanText(Dict('comptePrincipal/libelleUsuelProduit'))(self))
return _type
class obj__cards(DictElement):
item_xpath = 'comptePrincipal/cartesDD'
class item(ItemElement):
klass = Account
def obj_id(self):
return CleanText(Dict('idCarte'))(self).replace(' ', '')
obj_label = Format('Carte %s %s', Field('id'), CleanText(Dict('titulaire')))
obj_type = Account.TYPE_CARD
obj_coming = Eval(float_to_decimal, Dict('encoursCarteM'))
obj_balance = CleanDecimal(0)
obj__index = Dict('index')
obj__category = None
@method
class iter_accounts(DictElement):
item_xpath = 'grandesFamilles/*/elementsContrats'
class item(ItemElement):
IGNORED_ACCOUNTS = ("MES ASSURANCES",)
klass = Account
obj_id = CleanText(Dict('numeroCompteBam'))
obj_number = CleanText(Dict('numeroCompteBam'))
obj_label = CleanText(Dict('libelleProduit'))
obj_currency = CleanCurrency(Dict('idDevise'))
obj__index = Dict('index')
obj__category = Dict('grandeFamilleProduitCode', default=None)
obj__id_element_contrat = CleanText(Dict('idElementContrat'))
def obj_type(self):
_type = Map(CleanText(Dict('libelleUsuelProduit')), ACCOUNT_TYPES, Account.TYPE_UNKNOWN)(self)
if _type == Account.TYPE_UNKNOWN:
self.logger.warning('We got an untyped account: please add "%s" to ACCOUNT_TYPES.' % CleanText(Dict('libelleUsuelProduit'))(self))
return _type
def obj_balance(self):
balance = Dict('solde', default=None)(self)
if balance:
return Eval(float_to_decimal, balance)(self)
# We will fetch the balance with account_details
return NotAvailable
def condition(self):
# Ignore insurances (plus they all have identical IDs)
return CleanText(Dict('familleProduit/libelle', default=''))(self) not in self.IGNORED_ACCOUNTS
class AccountDetailsPage(LoggedPage, JsonPage):
def get_account_balances(self):
account_balances = {}
for el in self.doc:
value = el.get('solde', el.get('encoursActuel', el.get('valorisationContrat', el.get('montantRestantDu', el.get('capitalDisponible')))))
assert value is not None, 'Could not find the account balance'
account_balances[Dict('numeroCompte')(el)] = float_to_decimal(value)
return account_balances
def get_loan_ids(self):
loan_ids = {}
for el in self.doc:
if el.get('numeroCredit'):
# Loans
loan_ids[Dict('numeroCompte')(el)] = Dict('numeroCredit')(el)
elif el.get('numeroContrat'):
# Revolving credits
loan_ids[Dict('numeroCompte')(el)] = Dict('numeroContrat')(el)
return loan_ids
class IbanPage(LoggedPage, JsonPage):
def get_iban(self):
return Dict('ibanData/ibanCode', default=NotAvailable)(self.doc)
class HistoryPage(LoggedPage, JsonPage):
pass
class InvestmentPage(LoggedPage, JsonPage):
pass
class ProfilePage(LoggedPage, JsonPage):
pass
\ No newline at end of file
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2019 Romain Bignon
#
# 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 <http://www.gnu.org/licenses/>.
from weboob.browser.switch import SwitchingBrowser
from .api.browser import CragrAPI
from .web.browser import Cragr
class ProxyBrowser(SwitchingBrowser):
BROWSERS = {
'main': Cragr,
'api': CragrAPI,
}
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2019 Budget Insight
from weboob.browser.pages import AbstractPage
class LoginPage(AbstractPage):
PARENT = 'cmes'
PARENT_URL = 'login'
BROWSER_ATTR = 'package.browser.CmesBrowser'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment