diff --git a/modules/ameli/__init__.py b/modules/ameli/__init__.py
deleted file mode 100644
index 7e647021f36f266df3b1d2aeba5288df9000d6d5..0000000000000000000000000000000000000000
--- 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 a1106562b37ef58b956fc19b339ee7f93f8c8d4a..0000000000000000000000000000000000000000
--- 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 a088a27383903f73a2c53c8964ea3445a04982ba..0000000000000000000000000000000000000000
--- 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 2a91cfee57767683eb450c4830a878bd1ada013e..0000000000000000000000000000000000000000
--- 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 ea6d09d7dc8694df398d6ad85602b6e9c00e443d..0000000000000000000000000000000000000000
--- 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)