From 22fbea5b8ec7f51bf55049a587713b7ca21f35a7 Mon Sep 17 00:00:00 2001 From: Florian Duguet Date: Mon, 27 May 2019 15:28:51 +0200 Subject: [PATCH] [ameli] total delete --- modules/ameli/__init__.py | 24 ---- modules/ameli/browser.py | 126 -------------------- modules/ameli/module.py | 80 ------------- modules/ameli/pages.py | 238 -------------------------------------- modules/ameli/test.py | 31 ----- 5 files changed, 499 deletions(-) delete mode 100644 modules/ameli/__init__.py delete mode 100644 modules/ameli/browser.py delete mode 100644 modules/ameli/module.py delete mode 100644 modules/ameli/pages.py delete mode 100644 modules/ameli/test.py diff --git a/modules/ameli/__init__.py b/modules/ameli/__init__.py deleted file mode 100644 index 7e647021f3..0000000000 --- a/modules/ameli/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2013-2015 Christophe Lampin -# -# 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 Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this weboob module. If not, see . - - -from .module import AmeliModule - - -__all__ = ['AmeliModule'] diff --git a/modules/ameli/browser.py b/modules/ameli/browser.py deleted file mode 100644 index a1106562b3..0000000000 --- a/modules/ameli/browser.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2013-2015 Christophe Lampin -# -# 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 Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero 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 BrowserIncorrectPassword, ActionNeeded -from .pages import ( - LoginPage, HomePage, CguPage, AccountPage, LastPaymentsPage, PaymentsPage, PaymentDetailsPage, Raw, UnavailablePage, -) -from weboob.tools.compat import basestring - - -__all__ = ['AmeliBrowser'] - - -class AmeliBrowser(LoginBrowser): - BASEURL = 'https://assure.ameli.fr' - - loginp = URL(r'/PortailAS/appmanager/PortailAS/assure\?.*_pageLabel=as_login_page', LoginPage) - homep = URL(r'/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_accueil_page', HomePage) - cgup = URL(r'/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_conditions_generales_page', CguPage) - accountp = URL(r'/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_info_perso_page', AccountPage) - paymentsp = URL(r'/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_paiements_page', PaymentsPage) - paymentdetailsp = URL(r'/PortailAS/paiements.do\?actionEvt=chargerDetailPaiements.*', PaymentDetailsPage) - lastpaymentsp = URL(r'/PortailAS/paiements.do\?actionEvt=afficherPaiements.*', LastPaymentsPage) - pdf_page = URL(r'PortailAS/PDFServletReleveMensuel.dopdf\?PDF.moisRecherche=.*', Raw) - unavailablep = URL(r'/vu/INDISPO_COMPTE_ASSURES.html', UnavailablePage) - - def do_login(self): - self.logger.debug('call Browser.do_login') - - # set this cookie to get login form in response - self.session.cookies['hbc'] = '' - self.loginp.stay_or_go() - if self.homep.is_here(): - return True - - self.page.login(self.username, self.password) - - error = self.page.is_error() - if error: - raise BrowserIncorrectPassword(error) - - self.page.locate_to_cgu_page() - if self.cgup.is_here(): - raise ActionNeeded(self.page.get_cgu()) - - self.homep.stay_or_go() # Redirection not interpreted by browser. Manually redirect on homep - - if not self.homep.is_here(): - raise BrowserIncorrectPassword() - - @need_login - def iter_subscription_list(self): - self.logger.debug('call Browser.iter_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) - for sub in self.iter_subscription_list(): - if id == sub._id: - return sub - return None - - @need_login - def iter_history(self, sub): - transactions = [] - self.logger.debug('call Browser.iter_history') - self.paymentsp.stay_or_go() - payments_url = self.page.get_last_payments_url() - self.location(payments_url) - assert self.lastpaymentsp.is_here() - urls = self.page.iter_last_payments() - for url in urls: - self.location(url) - assert self.paymentdetailsp.is_here() - for payment in self.page.iter_payment_details(sub): - transactions.append(payment) - - # go to a page with a "deconnexion" link so that logged property - # stays True and next call to do_login doesn't crash when using the - # blackbox - self.accountp.go() - - return transactions - - @need_login - def iter_documents(self, sub): - self.logger.debug('call Browser.iter_documents') - self.paymentsp.stay_or_go() - payments_url = self.page.get_last_payments_url() - self.location(payments_url) - assert self.lastpaymentsp.is_here() - for document in self.page.iter_documents(sub): - yield document - - @need_login - def get_document(self, id): - self.logger.debug('call Browser.get_document') - assert isinstance(id, basestring) - subs = self.iter_subscription_list() - for sub in subs: - for b in self.iter_documents(sub): - if id == b.id: - return b - return False diff --git a/modules/ameli/module.py b/modules/ameli/module.py deleted file mode 100644 index a088a27383..0000000000 --- a/modules/ameli/module.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2013-2015 Christophe Lampin -# -# 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 Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this weboob module. If not, see . - -from __future__ import unicode_literals - -from weboob.capabilities.bill import DocumentTypes, CapDocument, SubscriptionNotFound, DocumentNotFound, Subscription, Bill -from weboob.tools.backend import Module, BackendConfig -from weboob.tools.value import ValueBackendPassword -from .browser import AmeliBrowser - -__all__ = ['AmeliModule'] - - -class AmeliModule(Module, CapDocument): - NAME = 'ameli' - DESCRIPTION = 'Ameli website: French Health Insurance' - MAINTAINER = 'Christophe Lampin' - EMAIL = 'weboob@lampin.net' - VERSION = '1.6' - LICENSE = 'AGPLv3+' - BROWSER = AmeliBrowser - CONFIG = BackendConfig(ValueBackendPassword('login', label='Numero de SS', regexp=r'^\d{13}$', masked=False), - ValueBackendPassword('password', label='Password', masked=True)) - - accepted_document_types = (DocumentTypes.BILL,) - - def create_default_browser(self): - return self.create_browser(self.config['login'].get(), - self.config['password'].get()) - - def iter_subscription(self): - return self.browser.iter_subscription_list() - - def get_subscription(self, _id): - subscription = self.browser.get_subscription(_id) - if not subscription: - raise SubscriptionNotFound() - else: - return subscription - - def iter_documents_history(self, subscription): - if not isinstance(subscription, Subscription): - subscription = self.get_subscription(subscription) - return self.browser.iter_history(subscription) - - def iter_documents(self, subscription): - if not isinstance(subscription, Subscription): - subscription = self.get_subscription(subscription) - return self.browser.iter_documents(subscription) - - def get_document(self, id): - bill = self.browser.get_document(id) - if not bill: - raise DocumentNotFound() - else: - return bill - - def download_document(self, bill): - if not isinstance(bill, Bill): - bill = self.get_document(bill) - response = self.browser.open(bill.url, stream=True) - if not response or response.headers['content-type'] != "application/pdf": - return None - return response.content diff --git a/modules/ameli/pages.py b/modules/ameli/pages.py deleted file mode 100644 index 2a91cfee57..0000000000 --- a/modules/ameli/pages.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2013-2015 Christophe Lampin -# -# 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 Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this weboob module. If not, see . - -from __future__ import unicode_literals - -from datetime import datetime -import re -from decimal import Decimal - -from weboob.browser.filters.html import Attr, XPathNotFound -from weboob.browser.pages import HTMLPage, RawPage, LoggedPage -from weboob.capabilities.bill import DocumentTypes, Subscription, Detail, Bill -from weboob.browser.filters.standard import CleanText, Regexp -from weboob.exceptions import BrowserUnavailable - - -# Ugly array to avoid the use of french locale - -FRENCH_MONTHS = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'] - - -class AmeliBasePage(HTMLPage): - @property - def logged(self): - if self.doc.xpath('//a[contains(text(), "Déconnexion")]'): - logged = True - else: - logged = False - self.logger.debug('logged: %s' % (logged)) - return logged - - def is_error(self): - errors = self.doc.xpath('//*[@id="r_errors"]') - if errors: - return errors[0].text_content() - - errors = CleanText('//p[@class="msg_erreur"]', default='')(self.doc) - if errors: - return errors - - errors = CleanText('//div[@class="zone-alerte"]/span')(self.doc) - if errors: - return errors - - return False - - -class LoginPage(AmeliBasePage): - def login(self, login, password): - form = self.get_form('//form[@name="connexionCompteForm"]') - form['connexioncompte_2numSecuriteSociale'] = login.encode('utf8') - form['connexioncompte_2codeConfidentiel'] = password.encode('utf8') - form.submit() - - def locate_to_cgu_page(self): - try: - # they've put a head tag inside body, yes i know... - url = Regexp(Attr('//div[@id="connexioncompte_2"]//meta', 'content'), r'url=(.*)')(self.doc) - except XPathNotFound: - # no cgu to validate - return - self.browser.location(url) - - -class CguPage(AmeliBasePage): - def get_cgu(self): - return CleanText('//div[@class="page_nouvelles_cgus"]/p[1]')(self.doc) - - -class HomePage(AmeliBasePage): - pass - - -class AccountPage(AmeliBasePage): - def iter_subscription_list(self): - names_list = self.doc.xpath('//span[@class="NomEtPrenomLabel"]') - fullname = CleanText(newlines=True).filter(names_list[0]) - number = re.sub(r'[^\d]+', '', CleanText('//span[@class="blocNumSecu"]', replace=[(' ', '')])(self.doc)) - sub = Subscription(number) - sub._id = number - sub.label = fullname - firstname = CleanText('//span[@class="prenom-titulaire"]')(self.doc) - sub.subscriber = firstname - yield sub - - -class PaymentsPage(AmeliBasePage): - def get_last_payments_url(self): - begin_date = self.doc.xpath('//input[@id="paiements_1dateDebut"]/@data-mindate')[0] - end_date = self.doc.xpath('//input[@id="paiements_1dateFin"]/@data-maxdate')[0] - url = ('/PortailAS/paiements.do?actionEvt=afficherPaiementsComplementaires&DateDebut=' - + begin_date + '&DateFin=' + end_date + - '&Beneficiaire=tout_selectionner&afficherReleves=false&afficherIJ=false&afficherInva=false' - '&afficherRentes=false&afficherRS=false&indexPaiement=&idNotif=') - return url - - -class LastPaymentsPage(LoggedPage, AmeliBasePage): - def iter_last_payments(self): - elts = self.doc.xpath('//li[@class="rowitem remboursement"]') - for elt in elts: - items = Regexp(CleanText('./@onclick'), r".*ajaxCallRemoteChargerDetailPaiement \('(\w+={0,2})', '(\w+)', '(\d+)', '(\d+)'\).*", '\\1,\\2,\\3,\\4')(elt).split(',') - yield "/PortailAS/paiements.do?actionEvt=chargerDetailPaiements&idPaiement=" + items[0] + "&naturePaiement=" + items[1] + "&indexGroupe=" + items[2] + "&indexPaiement=" + items[3] - - def iter_documents(self, sub): - elts = self.doc.xpath('//li[@class="rowdate"]') - for elt in elts: - try: - elt.xpath('.//a[contains(@id,"lienPDFReleve")]')[0] - except IndexError: - continue - date_str = elt.xpath('.//span[contains(@id,"moisEnCours")]')[0].text - month_str = date_str.split()[0] - date = datetime.strptime(re.sub(month_str, str(FRENCH_MONTHS.index(month_str) + 1), date_str), "%m %Y").date() - bil = Bill() - bil.id = sub._id + "." + date.strftime("%Y%m") - bil.date = date - bil.format = 'pdf' - bil.type = DocumentTypes.BILL - bil.label = date.strftime("%Y%m%d") - bil.url = '/PortailAS/PDFServletReleveMensuel.dopdf?PDF.moisRecherche=' + date.strftime("%m%Y") - yield bil - - def get_document(self, bill): - self.location(bill.url, params=bill._args) - - -class PaymentDetailsPage(AmeliBasePage): - def iter_payment_details(self, sub): - id_str = self.doc.xpath('//div[@class="entete container"]/h2')[0].text.strip() - m = re.match(r'.*le (.*) pour un montant de.*', id_str) - if m: - blocs_benes = self.doc.xpath('//span[contains(@id,"nomBeneficiaire")]') - blocs_prestas = self.doc.xpath('//table[@id="tableauPrestation"]') - i = 0 - last_bloc = len(blocs_benes) - for i in range(0, last_bloc): - bene = blocs_benes[i].text - id_str = m.group(1) - id_date = datetime.strptime(id_str, '%d/%m/%Y').date() - id = sub._id + "." + datetime.strftime(id_date, "%Y%m%d") - table = blocs_prestas[i].xpath('.//tr') - line = 1 - last_date = None - for tr in table: - tds = tr.xpath('.//td') - if len(tds) == 0: - continue - - det = Detail() - - # TO TEST : Indemnités journalières : Pas pu tester de cas de figure similaire dans la nouvelle mouture du site - if len(tds) == 4: - date_str = Regexp(pattern=r'.*
(\d+/\d+/\d+)\).*').filter(tds[0].text) - det.id = id + "." + str(line) - det.label = tds[0].xpath('.//span')[0].text.strip() - - jours = tds[1].text - if jours is None: - jours = '0' - - montant = tds[2].text - if montant is None: - montant = '0' - - price = tds[3].text - if price is None: - price = '0' - - if date_str is None or date_str == '': - det.infos = '' - det.datetime = last_date - else: - det.infos = date_str + ' (' + re.sub(r'[^\d,-]+', '', jours) + 'j) * ' + re.sub(r'[^\d,-]+', '', montant) + '€' - det.datetime = datetime.strptime(date_str.split(' ')[3], '%d/%m/%Y').date() - last_date = det.datetime - det.price = Decimal(re.sub(r'[^\d,-]+', '', price).replace(',', '.')) - - if len(tds) == 5: - date_str = Regexp(pattern=r'\w*(\d{2})/(\d{2})/(\d{4}).*', template='\\1/\\2/\\3', default="").filter("".join(tds[0].itertext())) - det.id = id + "." + str(line) - det.label = bene + ' - ' + tds[0].xpath('.//span')[0].text.strip() - - paye = tds[1].text - if paye is None: - paye = '0' - - base = tds[2].text - if base is None: - base = '0' - - tdtaux = tds[3].xpath('.//span')[0].text - if tdtaux is None: - taux = '0' - else: - taux = tdtaux.strip() - - tdprice = tds[4].xpath('.//span')[0].text - if tdprice is None: - price = '0' - else: - price = tdprice.strip() - - if date_str is None or date_str == '': - det.infos = '' - det.datetime = last_date - else: - det.infos = ' Payé ' + re.sub(r'[^\d,-]+', '', paye) + '€ / Base ' + re.sub(r'[^\d,-]+', '', base) + '€ / Taux ' + re.sub(r'[^\d,-]+', '', taux) + '%' - det.datetime = datetime.strptime(date_str, '%d/%m/%Y').date() - last_date = det.datetime - det.price = Decimal(re.sub(r'[^\d,-]+', '', price).replace(',', '.')) - line = line + 1 - yield det - - -class Raw(LoggedPage, RawPage): - pass - - -class UnavailablePage(HTMLPage): - def on_load(self): - raise BrowserUnavailable(CleanText('//span[@class="texte-indispo"]')(self.doc)) diff --git a/modules/ameli/test.py b/modules/ameli/test.py deleted file mode 100644 index ea6d09d7dc..0000000000 --- a/modules/ameli/test.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2013-2015 Christophe Lampin -# -# 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 Affero 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 Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this weboob module. If not, see . - - -from weboob.tools.test import BackendTest - - -class AmeliTest(BackendTest): - MODULE = 'ameli' - - def test_ameli(self): - for subscription in self.backend.iter_subscription(): - list(self.backend.iter_documents_history(subscription.id)) - for bill in self.backend.iter_documents(subscription.id): - self.backend.download_document(bill.id) -- GitLab