From a1292378075d6731e4adcb66083a31e4ea43844b Mon Sep 17 00:00:00 2001 From: Vincent A Date: Sat, 24 Aug 2019 20:08:53 +0200 Subject: [PATCH] [wiseed] new CapBankWealth module for crowdlending site --- modules/wiseed/__init__.py | 26 ++++++++++ modules/wiseed/browser.py | 71 ++++++++++++++++++++++++++ modules/wiseed/module.py | 57 +++++++++++++++++++++ modules/wiseed/pages.py | 101 +++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 modules/wiseed/__init__.py create mode 100644 modules/wiseed/browser.py create mode 100644 modules/wiseed/module.py create mode 100644 modules/wiseed/pages.py diff --git a/modules/wiseed/__init__.py b/modules/wiseed/__init__.py new file mode 100644 index 0000000000..685c111381 --- /dev/null +++ b/modules/wiseed/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Vincent A +# +# This file is part of a weboob module. +# +# This weboob module is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This weboob module 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this weboob module. If not, see . + +from __future__ import unicode_literals + + +from .module import WiseedModule + + +__all__ = ['WiseedModule'] diff --git a/modules/wiseed/browser.py b/modules/wiseed/browser.py new file mode 100644 index 0000000000..09632b7ec8 --- /dev/null +++ b/modules/wiseed/browser.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Vincent A +# +# This file is part of a weboob module. +# +# This weboob module is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This weboob module 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this weboob module. If not, see . + +from __future__ import unicode_literals + +from weboob.browser import LoginBrowser, need_login, URL, StatesMixin +from weboob.capabilities.bank import Account + +from .pages import LoginPage, LandPage, InvestPage + + +# TODO implement documents and profile + +class WiseedBrowser(LoginBrowser, StatesMixin): + BASEURL = 'https://www.wiseed.com' + + login = URL('/fr/connexion', LoginPage) + landing = URL('/fr/projets-en-financement', LandPage) + invests = URL('/fr/compte/portefeuille', InvestPage) + + def do_login(self): + self.login.go() + self.page.do_login(self.username, self.password) + + if self.login.is_here(): + self.page.raise_error() + + assert self.landing.is_here() + + @need_login + def iter_accounts(self): + self.invests.stay_or_go() + + acc = Account() + acc.id = '_wiseed_' + acc.type = Account.TYPE_MARKET + acc.number = self.page.get_user_id() + acc.label = 'WiSEED' + acc.currency = 'EUR' + # unfortunately there's little data + acc.balance = sum(inv.valuation for inv in self.iter_investment()) + + return [acc] + + @need_login + def iter_investment(self): + self.invests.stay_or_go() + + yield self.page.get_liquidities() + + for inv in self.page.iter_funded(): + yield inv + + for inv in self.page.iter_funding(): + yield inv diff --git a/modules/wiseed/module.py b/modules/wiseed/module.py new file mode 100644 index 0000000000..480163e5da --- /dev/null +++ b/modules/wiseed/module.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Vincent A +# +# This file is part of a weboob module. +# +# This weboob module is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This weboob module 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this weboob module. If not, see . + +from __future__ import unicode_literals + +from weboob.tools.backend import Module, BackendConfig +from weboob.tools.value import ValueBackendPassword +from weboob.capabilities.bank import CapBankWealth + +from .browser import WiseedBrowser + + +__all__ = ['WiseedModule'] + + +class WiseedModule(Module, CapBankWealth): + NAME = 'wiseed' + DESCRIPTION = 'WiSEED' + MAINTAINER = 'Vincent A' + EMAIL = 'dev@indigo.re' + LICENSE = 'LGPLv3+' + VERSION = '1.6' + + BROWSER = WiseedBrowser + + CONFIG = BackendConfig( + ValueBackendPassword('login', label='E-mail', regexp='.*@.*', masked=False), + ValueBackendPassword('password', label='Mot de passe'), + ) + + def create_default_browser(self): + return self.create_browser( + self.config['login'].get(), + self.config['password'].get() + ) + + def iter_accounts(self): + return self.browser.iter_accounts() + + def iter_investment(self, account): + return self.browser.iter_investment() diff --git a/modules/wiseed/pages.py b/modules/wiseed/pages.py new file mode 100644 index 0000000000..9eb89ce9eb --- /dev/null +++ b/modules/wiseed/pages.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Vincent A +# +# This file is part of a weboob module. +# +# This weboob module is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This weboob module 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this weboob module. If not, see . + +from __future__ import unicode_literals + +from weboob.browser.pages import LoggedPage, HTMLPage +from weboob.browser.filters.html import TableCell +from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp +from weboob.browser.elements import method, ItemElement, TableElement +from weboob.exceptions import BrowserIncorrectPassword +from weboob.capabilities.bank import Investment +from weboob.tools.capabilities.bank.investments import create_french_liquidity + + +class LoginPage(HTMLPage): + def do_login(self, login, password): + form = self.get_form(id='recaptcha') # wtf + form['emailConnexion'] = login + form['motDePasseConnexion'] = password + form.submit() + + def raise_error(self): + msg = CleanText('//div[has-class("alert-danger")]')(self.doc) + if 'Email ou mot de passe invalide' in msg: + raise BrowserIncorrectPassword(msg) + assert False, 'unhandled message %r' % msg + + +class LandPage(LoggedPage, HTMLPage): + pass + + +class InvestPage(LoggedPage, HTMLPage): + def get_user_id(self): + return Regexp( + CleanText('//span[contains(text(), "ID Client")]'), + r'ID Client : (\d+)' + )(self.doc) + + def get_liquidities(self): + value = CleanDecimal.French(CleanText('//a[starts-with(text(),"Compte de paiement")]'))(self.doc) + return create_french_liquidity(value) + + @method + class iter_funded(TableElement): + item_xpath = '//table[@id="portefeuilleAction"]/tbody/tr' + + head_xpath = '//table[@id="portefeuilleAction"]/thead//th' + col_bought = 'Vous avez investi' + col_label = 'Investissement dans' + col_valuation = 'Valeur estimée à date' + col_diff_ratio = 'Coef. de performance intermediaire' + + class item(ItemElement): + klass = Investment + + obj_label = CleanText(TableCell('label')) + + # text is "0000000000000100 100,00 €", wtf + obj_valuation = CleanDecimal.SI( + Regexp(CleanText(TableCell('valuation')), r'^000(\d+)\b') + ) + + obj_diff_ratio = CleanDecimal.SI( + Regexp(CleanText(TableCell('diff_ratio')), r'^000(\d+)\b') + ) + + # unitprice and unitvalue are on a dedicated page, let's forget it + + @method + class iter_funding(TableElement): + item_xpath = '//table[has-class("portefeuille-liste") and not(@id)]/tbody/tr' + + head_xpath = '//table[has-class("portefeuille-liste") and not(@id)]/thead//th' + col_label = 'Opération / Cible' + col_details = 'Détails' + + class item(ItemElement): + klass = Investment + + obj_label = CleanText(TableCell('label')) + obj_valuation = CleanDecimal.French(Regexp( + CleanText(TableCell('details')), + r'^(.*?) €', # can be 100,00 € + Frais de 0,90 € + )) -- GitLab