From ef43e138f9c31abcbb434f19ee961d5967d3b381 Mon Sep 17 00:00:00 2001 From: Antoine BOSSY Date: Thu, 28 Feb 2019 00:02:57 +0100 Subject: [PATCH] Add module ticketscesu --- modules/ticketscesu/__init__.py | 26 ++++++++ modules/ticketscesu/browser.py | 60 +++++++++++++++++ modules/ticketscesu/module.py | 110 ++++++++++++++++++++++++++++++++ modules/ticketscesu/pages.py | 99 ++++++++++++++++++++++++++++ 4 files changed, 295 insertions(+) create mode 100644 modules/ticketscesu/__init__.py create mode 100644 modules/ticketscesu/browser.py create mode 100644 modules/ticketscesu/module.py create mode 100644 modules/ticketscesu/pages.py diff --git a/modules/ticketscesu/__init__.py b/modules/ticketscesu/__init__.py new file mode 100644 index 0000000000..ed7b80ad3d --- /dev/null +++ b/modules/ticketscesu/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Antoine BOSSY +# +# 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 TicketsCesuModule + + +__all__ = ['TicketsCesuModule'] diff --git a/modules/ticketscesu/browser.py b/modules/ticketscesu/browser.py new file mode 100644 index 0000000000..646b4629ca --- /dev/null +++ b/modules/ticketscesu/browser.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Antoine BOSSY +# +# 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, URL, need_login +from weboob.exceptions import ActionNeeded + +from .pages import AccountsPage, LoginPage, ProfilePage + + +class TicketCesuBrowser(LoginBrowser): + BASEURL = 'https://ebeneficiaire.cesu-as.fr' + + login_page = URL('/login.aspx', LoginPage) + profile_page = URL('/customerManagement/ProfileManagement.aspx', ProfilePage) + accounts_page = URL('/PaymentManagement/PaymentAccountInfoFullDemat.aspx', AccountsPage) + + + def do_login(self): + self.login_page.go().login(login=self.username, password=self.password) + + if self.profile_page.is_here(): + raise ActionNeeded('Please agree CGU on the CESU website.') + + @need_login + def get_accounts(self): + return self.accounts_page.go().get_accounts() + + @need_login + def get_history(self, id): + accounts = self.get_accounts() + + account = None + for acc in accounts: + if acc.id == id: + account = acc + + if account and self.accounts_page.is_here(): + self.page.go_to_transaction_page(account._page) + return self.page.get_transactions() + + return [] diff --git a/modules/ticketscesu/module.py b/modules/ticketscesu/module.py new file mode 100644 index 0000000000..4c5d9b1fd3 --- /dev/null +++ b/modules/ticketscesu/module.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Antoine BOSSY +# +# 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.capabilities.base import find_object +from weboob.capabilities.bank import CapBank, Account, AccountNotFound + +from weboob.tools.backend import Module, BackendConfig +from weboob.tools.value import ValueBackendPassword, Value + +from .browser import TicketCesuBrowser + + +__all__ = ['TicketsCesuModule'] + + +class TicketsCesuModule(Module, CapBank): + NAME = 'ticketscesu' + DESCRIPTION = 'Tickets CESU Endered' + MAINTAINER = 'Antoine BOSSY' + EMAIL = 'mail+github@abossy.fr' + LICENSE = 'LGPLv3+' + VERSION = '1.6' + + BROWSER = TicketCesuBrowser + + CONFIG = BackendConfig( + Value('login', label='Identifiant', masked=False), + ValueBackendPassword('password', label='Code secret', required=True) + ) + + def create_default_browser(self): + return self.create_browser(self.config['login'].get(), self.config['password'].get()) + + def get_account(self, id): + """ + Get an account from its ID. + + :param id: ID of the account + :type id: :class:`str` + :rtype: :class:`Account` + :raises: :class:`AccountNotFound` + """ + return find_object(self.iter_accounts(), id=id, error=AccountNotFound) + + def iter_accounts(self): + """ + Iter accounts. + + :rtype: iter[:class:`Account`] + """ + return self.browser.get_accounts() + + def iter_coming(self, account): + """ + Iter coming transactions on a specific account. + + :param account: account to get coming transactions + :type account: :class:`Account` + :rtype: iter[:class:`Transaction`] + :raises: :class:`AccountNotFound` + """ + raise NotImplementedError() + + def iter_history(self, account): + """ + Iter history of transactions on a specific account. + + :param account: account to get history + :type account: :class:`Account` + :rtype: iter[:class:`Transaction`] + :raises: :class:`AccountNotFound` + """ + return self.browser.get_history(account.id) + + def iter_resources(self, objs, split_path): + """ + Iter resources. + + Default implementation of this method is to return on top-level + all accounts (by calling :func:`iter_accounts`). + + :param objs: type of objects to get + :type objs: tuple[:class:`BaseObject`] + :param split_path: path to discover + :type split_path: :class:`list` + :rtype: iter[:class:`BaseObject`] + """ + if Account in objs: + self._restrict_level(split_path) + return self.iter_accounts() + + return [] diff --git a/modules/ticketscesu/pages.py b/modules/ticketscesu/pages.py new file mode 100644 index 0000000000..8c99899b8a --- /dev/null +++ b/modules/ticketscesu/pages.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2019 Antoine BOSSY +# +# 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.elements import method, ItemElement, ListElement, SkipItem +from weboob.browser.filters.standard import CleanDecimal, CleanText, Field, Format, Date +from weboob.browser.filters.html import Attr +from weboob.browser.pages import HTMLPage, LoggedPage +from weboob.capabilities.bank import Account, Transaction +from weboob.capabilities.base import NotAvailable + + +class LoginPage(HTMLPage): + def login(self, login, password): + form = self.get_form('//form[@id="frmMain"]') + form['UserLogin'] = login + form['UserPass'] = password + form.submit() + + +class ProfilePage(HTMLPage): + pass + + +class AccountsPage(LoggedPage, HTMLPage): + def go_to_transaction_page(self, page): + form = self.get_form('//form[@id="frmMain"]') + form['%s.x' % page] = 1 + form['%s.y' % page] = 1 + form.submit() + + @method + class get_accounts(ListElement): + item_xpath = '//tr[has-class("ItemH23")]' + + class item(ItemElement): + klass = Account + + obj_id = CleanText('./td[position()=2]') + obj_balance = CleanDecimal('./td[position()=6]', replace_dots=True) + obj_label = Format('Millésime %s', Field('id')) + obj_number = Field('id') + obj_currency = 'EUR' + + obj__page = Attr('./td//input', 'name') + + @method + class get_transactions(ListElement): + item_xpath = '//tr[has-class("ItemH23")]' + + class item(ItemElement): + klass = Transaction + + def obj_date(self): + maybe_date = CleanText('./td[position()=2]')(self) + if maybe_date == '-': + raise SkipItem() + + return Date(CleanText('./td[position()=2]'), dayfirst=True)(self) + + obj_id = CleanText('./td[position()=3]') + + def obj_amount(self): + amount = CleanDecimal('./td[position()=4]', replace_dots=True, + default=NotAvailable)(self) + + if amount is NotAvailable: + return CleanDecimal('./td[position()=5]', replace_dots=True)(self) + + return amount * -1 + + obj_currency = 'EUR' + + def obj_label(self): + label = CleanText('./td[position()=6]')(self) + if label == '-': + return CleanText('./td[position()=7]')(self) + + return label + + obj_raw = Field('label') -- GitLab