From ec10ec338291dac2dbd36160b9b4f847fa44a4bb Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sun, 2 Mar 2014 20:49:59 +0100 Subject: [PATCH] add module alloresto --- modules/alloresto/__init__.py | 23 ++++++++++ modules/alloresto/backend.py | 68 ++++++++++++++++++++++++++++ modules/alloresto/browser.py | 83 ++++++++++++++++++++++++++++++++++ modules/alloresto/favicon.png | Bin 0 -> 2320 bytes modules/alloresto/pages.py | 74 ++++++++++++++++++++++++++++++ modules/alloresto/test.py | 32 +++++++++++++ 6 files changed, 280 insertions(+) create mode 100644 modules/alloresto/__init__.py create mode 100644 modules/alloresto/backend.py create mode 100644 modules/alloresto/browser.py create mode 100644 modules/alloresto/favicon.png create mode 100644 modules/alloresto/pages.py create mode 100644 modules/alloresto/test.py diff --git a/modules/alloresto/__init__.py b/modules/alloresto/__init__.py new file mode 100644 index 00000000..93d8a07f --- /dev/null +++ b/modules/alloresto/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 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 . + + +from .backend import AlloRestoBackend + +__all__ = ['AlloRestoBackend'] diff --git a/modules/alloresto/backend.py b/modules/alloresto/backend.py new file mode 100644 index 00000000..00c7be85 --- /dev/null +++ b/modules/alloresto/backend.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 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 . + + + +from weboob.capabilities.bank import ICapBank, AccountNotFound +from weboob.tools.backend import BaseBackend, BackendConfig +from weboob.tools.value import ValueBackendPassword + +from .browser import AlloRestoBrowser + + +__all__ = ['AlloRestoBackend'] + + +class AlloRestoBackend(BaseBackend, ICapBank): + NAME = 'alloresto' + MAINTAINER = u'Romain Bignon' + EMAIL = 'romain@weboob.org' + VERSION = '0.i' + DESCRIPTION = u'Allo Resto' + LICENSE = 'AGPLv3+' + CONFIG = BackendConfig(ValueBackendPassword('login', label='Identifiant', masked=False), + ValueBackendPassword('password', label='Mot de passe')) + BROWSER = AlloRestoBrowser + + def create_default_browser(self): + return self.create_browser(self.config['login'].get(), + self.config['password'].get()) + + def iter_accounts(self): + with self.browser: + for account in self.browser.get_accounts_list(): + yield account + + def get_account(self, _id): + with self.browser: + account = self.browser.get_account(_id) + + if account: + return account + else: + raise AccountNotFound() + + def iter_history(self, account): + with self.browser: + return self.browser.get_history(account) + + def iter_coming(self, account): + with self.browser: + return self.browser.get_coming(account) + diff --git a/modules/alloresto/browser.py b/modules/alloresto/browser.py new file mode 100644 index 00000000..3b610a8e --- /dev/null +++ b/modules/alloresto/browser.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 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 . + + +from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword + +from .pages import LoginPage, AccountsPage + + +__all__ = ['AlloRestoBrowser'] + + +class AlloRestoBrowser(BaseBrowser): + DOMAIN = 'www.alloresto.fr' + PROTOCOL = 'http' + ENCODING = 'utf-8' + PAGES = {'http://www.alloresto.fr/identification-requise.*': LoginPage, + 'http://www.alloresto.fr/chez-moi/releve-compte-miams': AccountsPage, + } + + def is_logged(self): + return self.page is not None and not self.is_on_page(LoginPage) + + def home(self): + self.go_on_accounts_list() + + def login(self): + assert isinstance(self.username, basestring) + assert isinstance(self.password, basestring) + + if not self.is_on_page(LoginPage): + self.location('http://www.alloresto.fr/identification-requise', no_login=True) + + self.page.login(self.username, self.password) + + if not self.is_logged(): + raise BrowserIncorrectPassword() + + def go_on_accounts_list(self): + self.location('http://www.alloresto.fr/chez-moi/releve-compte-miams') + + def get_accounts_list(self): + if not self.is_on_page(AccountsPage): + self.go_on_accounts_list() + 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 + + def get_history(self, account): + if not self.is_on_page(AccountsPage): + self.go_on_accounts_list() + + return self.page.get_transactions() + + def get_coming(self, account): + if not self.is_on_page(AccountsPage): + self.go_on_accounts_list() + + return self.page.get_transactions('acquisition') diff --git a/modules/alloresto/favicon.png b/modules/alloresto/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b365c6dac425feb9450fa5c73a1957bb68d000 GIT binary patch literal 2320 zcmV+r3GeoaP)ZSky02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00?+VL_t(|+U;3uaFo>nyN98fD) zX)06{sI)>L0!fSlNz9ETyO~@!*~_=zcb=y|zHisfZZ?UM?XT~d*&n;_d(Qiw=e*}V z?|T;T;lqayA3l8e@ZrOU4<9~!`0(*5qQC{_;fFgJ4tMqT_MVe1H{IQJtgQ_@!1srn zXS8~mh`sVkDR=HX%I0R9mL>M|kX2PZ&d!}LG&VM#{(m9BEL*mZ#z>Nqt*t-KmdgWy z=y3ClRxbs+tn3~}B1U<@`udY?ZEa^1bn(_*cm0SxJ!zxPu3anhElhw$L%>LS0FWpz zznbwlC5h|Ti?e2l!Jv5FdE!ksiS6yKKl}IpwV(v>{r5X1iDhMyBvV$lqtFCYR8$1n z($XbKeC8PuXt9C0A>hm;@GSxdc>VQm6r4EGRj|d|FT8NCBysm{!$pf+gZuV17McLN zvT~Uu@uQDqfgrGw~5`V)zm!tH)dO}8XDci;Vtx%AQjNn%q|vd{#WqerVH ziHjGDz+2h!5O5}gL6?9;LWSA=va%&!h$Wmv;!z$w+MDvf@1ch-DkK36hZB;-Y13qY zpJvNjfC-#B)g_>{m1Dnn+rEPB?U8)h*IBvpcLgQDvfShs49Ws#<|Ihq%e?t!mw+8R z5@WIE(*}L%=~+@VdGgr+psFh9@yDUdE`zG80RTmlCVj7+6$}#4E3qfb@qOHn^;B-ySY#1eBH8lEl@k6$ieQlOtBF zD3>HQH_JKaoIi|h_=iG^C5c~j?=c?Yxl^JO53(C z>*(k>D;A4QHO6vwZLzLS4lqBx zW1h1#MkF2YLy|Rvc6O9{26%+G+#<$eLsx*dE#7yZ2y7brtMB;nK0f`l2;>wz2KYH& zd{I1fNCY;g$86jvI!>;mwY4IUbb#wVi(WVI1p-Z+Ia7S@Iq{QE#6&_2g~ZL9#mg@j zf$lgkZR`mE`US`Vev&O~1WqT=B0vNp8Do00kISH=1FZcldH|3FW~Xcoq1W#K*No-5 zGjD-r0Xz-(8-e2lwi#e?3ou~@U=g@eKo5Xdy+!>K00azoANP1V4|`*W&JnHD z_S@pprD7l;0>^FOJ30D?4vFu*CmuK;wzY||m>aI)u>1S{_lv-qtWx$$0{y)9T5-=F zabQ5~?G^X!vy3sfdc>|0Ahx!Cnm79U#b{JaCf)Cmh}h5|e(-^~ZCiDw4KIS41c(=1 zB(7cS>ROiA-7VJDoixV$DyO9$GU=3;i!)}3fb9S`jHEwkY*iH<;0Ng|9yr$kA+B0A zv_4r201j|9fqp*qlTD<~E)J0mseMd(C9{)EJ9CkH8{2xvP60xU+OZrEe?Y~cf082pn*2oNh z?{-<3Cg7fXYCL=Y$c+GRXBY~JbLXZOvm*g~YBV`a#t<^B_-k$Pq>9geZ9uz=?PORpI7rOb! z7?PypIM(_FfRdpePS$@mw;3!DL})v)TCpK`DJbh9X#l;yj%pVtmH9|t5$XK$Pp3<5%?nj z*z@N7ncKI!xgvEOl1Z_%Gn1^f-W>A@7|xj^ZrC8Uw79i-d%L)GE6oEBY#8AP_42?0 z@%7h-J#LwuWKK&R4%0L>{l~WLD~25G0M`&$H*Ck073Kzbl)zyEeFTiRXp2B6f$}79 zX~z8X3H+Bpj6g4eN&-(?z{MlJR=G{oY6n;}l5PZ;L|`R>V+0Ze+6b(-fN%K!_WJPQ q!-o$aK79D_;lqayA3l8e0R9IFRg;Xs2z5aK0000. + + +import datetime +from decimal import Decimal + +from weboob.tools.browser import BasePage, BrokenPageError +from weboob.capabilities.bank import Account +from weboob.tools.capabilities.bank.transactions import FrenchTransaction as Transaction + + +__all__ = ['LoginPage', 'AccountsPage'] + + +class LoginPage(BasePage): + def login(self, username, password): + self.browser.select_form(nr=0) + self.browser['uname'] = username.encode(self.browser.ENCODING) + self.browser['pass'] = password.encode(self.browser.ENCODING) + self.browser.submit(nologin=True) + + +class AccountsPage(BasePage): + def get_list(self): + a = Account() + a.id = '0' + a.label = u'Compte miams' + a.balance = Decimal(self.parser.tocleanstring(self.document.xpath('//div[@class="compteur"]//strong')[0])) + a.currency = u'MIAM' + try: + a.coming = Decimal(Transaction.clean_amount(self.document.xpath('//table[@id="solde_acquisition_lignes"]//th[@class="col_montant"]')[0].text)) + except BrokenPageError: + a.coming = Decimal('0') + yield a + + COL_DATE = 0 + COL_LABEL = 1 + COL_AMOUNT = 2 + + MONTHS = ['janv', u'févr', u'mars', u'avr', u'mai', u'juin', u'juil', u'août', u'sept', u'oct', u'nov', u'déc'] + def get_transactions(self, _type='consommable'): + for tr in self.document.xpath('//table[@id="solde_%s_lignes"]/tbody/tr' % _type): + cols = tr.findall('td') + + t = Transaction(0) + + day, month, year = self.parser.tocleanstring(cols[self.COL_DATE]).split(' ') + day = int(day) + year = int(year) + month = self.MONTHS.index(month.rstrip('.')) + 1 + date = datetime.date(year, month, day) + + label = self.parser.tocleanstring(cols[self.COL_LABEL]) + t.parse(date, label) + t.set_amount(self.parser.tocleanstring(cols[self.COL_AMOUNT])) + + yield t diff --git a/modules/alloresto/test.py b/modules/alloresto/test.py new file mode 100644 index 00000000..4fc0f837 --- /dev/null +++ b/modules/alloresto/test.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 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 . + + +from weboob.tools.test import BackendTest + + +class AlloRestoTest(BackendTest): + BACKEND = 'alloresto' + + def test_alloresto(self): + l = list(self.backend.iter_accounts()) + + a = l[0] + list(self.backend.iter_history(a)) + list(self.backend.iter_coming(a))