The new woob repository is here: https://gitlab.com/woob/woob. This gitlab will be removed soon.

The new woob repository is here: https://gitlab.com/woob/woob. This gitlab will be removed soon.

Commit d32260b6 authored by Eric's avatar Eric Committed by Romain Bignon

new module: ulys for liber-t / vinciautoroutes

parent a19af187
Pipeline #2769 failed with stages
in 1 minute and 34 seconds
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2014 Florent Fourcot
# Copyright(C) 2018 Eric Seigne
#
# 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 .module import UlysModule
__all__ = ['UlysModule']
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2014 Florent Fourcot
# Copyright(C) 2018 Eric Seigne
#
# 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 import LoginBrowser, URL, need_login
from weboob.tools.compat import basestring
from weboob.exceptions import BrowserIncorrectPassword
from weboob.capabilities.bill import Detail
from decimal import Decimal
from .pages import LoginPage, HomePage, AccountPage, BillsPage
__all__ = ['UlysBrowser']
class UlysBrowser(LoginBrowser):
BASEURL = 'https://espaceabonnes.vinci-autoroutes.com'
loginp = URL('/Authentification','https://oidc-bcu.vinci-autoroutes.com/tlp/login', LoginPage)
homep = URL(r'/$', HomePage)
accountp = URL('/InfosPersonnelles/CoordonneesFacturation', AccountPage)
billsp = URL('/FacturesConso/Factures', BillsPage)
logged = False
def __init__(self, config=None, *args, **kwargs):
self.config = config
kwargs['username'] = self.config['login'].get()
kwargs['password'] = self.config['password'].get()
super(UlysBrowser, self).__init__(*args, **kwargs)
def do_login(self):
self.logger.debug('call Browser.do_login')
if self.logged:
return True
assert isinstance(self.username, basestring)
assert isinstance(self.password, basestring)
self.loginp.stay_or_go()
if self.homep.is_here():
self.logged = True
return True
self.page.login(self.username, self.password)
if not self.homep.is_here():
raise BrowserIncorrectPassword()
self.logged = True
@need_login
def get_subscription_list(self):
self.logger.debug('call Browser.get_subscription_list')
self.accountp.stay_or_go()
return self.page.iter_subscription_list()
@need_login
def get_subscription(self, id):
self.logger.debug('call Browser.get_subscription')
assert isinstance(id, basestring)
return self.get_subscription_list()
@need_login
def iter_history(self, subscription):
self.logger.debug('call Browser.iter_history')
self.searchp.stay_or_go()
@need_login
def get_details(self, sub):
self.logger.debug('call Browser.get_details')
det = Detail()
det.id = sub.id
det.label = sub.label
det.infos = ''
det.price = Decimal('0.0')
return det
@need_login
def iter_documents(self,subscription):
self.logger.debug('call Browser.iter_document')
documents = []
self.billsp.go()
for b in self.page.get_bills(subid=subscription.id):
documents.append(b)
return iter(documents)
@need_login
def get_document(self, id):
self.logger.debug('call Browser.get_document')
self.billsp.stay_or_go()
for b in self.page.get_bills(id) :
if id == b.id:
return b
return False
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2014 Florent Fourcot
# Copyright(C) 2018 Eric Seigne
#
# 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.capabilities.bill import DocumentTypes, CapDocument, SubscriptionNotFound, DocumentNotFound, Subscription, Bill
from weboob.tools.backend import Module, BackendConfig
from weboob.tools.value import ValueBackendPassword, Value
from .browser import UlysBrowser
__all__ = ['UlysModule']
class UlysModule(Module, CapDocument):
NAME = 'ulys'
DESCRIPTION = u'Ulys Vinci Autoroute'
MAINTAINER = u'Eric Seigne'
EMAIL = 'weboob@cap-rel.fr'
LICENSE = 'AGPLv3+'
VERSION = '1.5'
CONFIG = BackendConfig(Value('login', label='Account ID'),
ValueBackendPassword('password', label='Password'));
BROWSER = UlysBrowser
accepted_document_types = (DocumentTypes.BILL,)
def create_default_browser(self):
self.logger.debug('call Module.create_default_browser')
return self.create_browser(self.config)
def iter_subscription(self):
self.logger.debug('call Module.iter_subscription')
return self.browser.get_subscription_list()
def get_subscription(self, _id):
self.logger.debug('call Module.get_subscription')
if not _id.isdigit():
raise SubscriptionNotFound()
subscription = self.browser.get_subscription(_id)
if not subscription:
raise SubscriptionNotFound()
else:
return subscription
def iter_documents_history(self, subscription):
self.logger.debug('call Module.iter_documents_history')
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
return self.browser.iter_history(subscription)
def get_details(self, subscription):
self.logger.debug('call Module.get_details')
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
return self.browser.get_details(subscription)
def iter_documents(self, subscription):
self.logger.debug('call Module.iter_document')
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
return self.browser.iter_documents(subscription)
def get_document(self, id):
self.logger.debug('call Module.get_document')
bill = self.browser.get_document(id)
if not bill:
raise DocumentNotFound()
else:
return bill
def download_document(self, bill):
self.logger.debug('call Module.download_document')
if not isinstance(bill, Bill):
bill = self.get_document(bill)
response = self.browser.open(bill.url, stream=True)
if not response :
return None
return response.content
# -*- coding: utf-8 -*-
# Copyright(C) 2015 Vincent Paredes
# Copyright(C) 2018 Eric Seigne
#
# 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/>.
import re
from weboob.browser.pages import HTMLPage, LoggedPage
from weboob.capabilities.base import NotAvailable
from weboob.capabilities.bill import Subscription, DocumentTypes, Bill
from weboob.browser.elements import ItemElement, method, TableElement
from weboob.browser.filters.standard import CleanDecimal, CleanText, Regexp, RegexpError, Date, Currency
from weboob.browser.filters.html import TableCell, AbsoluteLink
from weboob.exceptions import AuthMethodNotImplemented
class LoginPage(HTMLPage):
def on_load(self):
if self.doc.xpath('//p[contains(text(), "You have activated the double factor authentication")]'):
raise AuthMethodNotImplemented('Two-Factor authentication is not supported.')
@method
def is_login_ok(self):
return not self.doc.xpath('//form//input[@placeholder="username"]')
def login(self, login, password):
form = self.get_form(name='form')
form['username'] = login
form['password'] = password
form.submit()
class HomePage(HTMLPage):
def on_loaded(self):
pass
class SubscriptionsPage(LoggedPage, HTMLPage):
@method
class get_item(ItemElement):
klass = Subscription
def obj_subscriber(self):
try:
return Regexp(CleanText('//div[contains(@class, "darkblue")]'), self.page.browser.L_SUBSCRIBER)(self)
except RegexpError:
return self.page.browser.username
obj_id = 'ulys'
def obj_label(self):
return self.page.browser.username
class AccountPage(HTMLPage):
def iter_subscription_list(self):
ident = self.doc.xpath('//span[@class="PaddingLeft20 darkblue"]')[0]
name = re.sub('^.*Bienvenue (.*) - Num.*', '\\1', ident.text)
number = re.sub('^.* Client : ','',ident.text)
sub = Subscription(number)
sub._id = number
sub.label = unicode(name)
sub.subscriber = unicode(name)
return sub
class BillsPage(LoggedPage, HTMLPage):
@method
class get_bills(TableElement):
item_xpath = '//table/tbody/tr'
head_xpath = '//table/thead/tr/th'
flush_at_end = True
col_numero = re.compile(r'.*N.* DE FACTURE.*')
col_amount = 'MONTANT TTC'
col_mois = 'MOIS'
col_date = re.compile(r'.*DATE DE PR.*VEMENT.*')
col_url = re.compile(r'.*FACTURES / RELEV.*S.*')
class item(ItemElement):
klass = Bill
obj_type = DocumentTypes.BILL
obj_format = u"pdf"
obj_label = CleanText(TableCell('mois'))
obj_id = CleanText(TableCell('numero'))
obj_url = AbsoluteLink('.//a', TableCell('url'))
obj_date = TableCell('date') & CleanText() & Date(dayfirst=True)
obj_price = CleanDecimal(Regexp(CleanText(TableCell('amount')), '.*?([\d,]+).*', default=NotAvailable), replace_dots=True, default=NotAvailable)
obj_currency = Currency(TableCell('amount'))
# -*- coding: utf-8 -*-
# Copyright(C) 2013-2014 Florent Fourcot
# Copyright(C) 2018 Eric Seigne
#
# 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.tools.test import BackendTest
class UlysTest(BackendTest):
MODULE = 'ulys'
def test_details(self):
for subscription in self.backend.iter_subscription():
details = list(self.backend.get_details(subscription))
self.assertTrue(len(details) > 4, msg="Not enough details")
def test_history(self):
for subscription in self.backend.iter_subscription():
self.assertTrue(len(list(self.backend.iter_documents_history(subscription))) > 0)
def test_downloadbills(self):
"""
Iter all bills and try to download it.
"""
for subscription in self.backend.iter_subscription():
for bill in self.backend.iter_documents(subscription.id):
self.backend.download_document(bill.id)
def test_list(self):
"""
Test listing of subscriptions.
"""
subscriptions = list(self.backend.iter_subscription())
self.assertTrue(len(subscriptions) > 0, msg="Account listing failed")
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