diff --git a/modules/orange/browser.py b/modules/orange/browser.py index 53ba230637f48e8cf6357fe960955b9bcc115e8e..d0018334ad7f24c6848e023bee77acab9db19ab0 100644 --- a/modules/orange/browser.py +++ b/modules/orange/browser.py @@ -21,16 +21,16 @@ from requests.exceptions import ConnectTimeout -from weboob.browser import LoginBrowser, URL, need_login +from weboob.browser import LoginBrowser, URL, need_login, StatesMixin from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable, ActionNeeded, BrowserPasswordExpired from .pages import LoginPage, BillsPage -from .pages.login import ManageCGI, HomePage, PasswordPage +from .pages.login import ManageCGI, HomePage, PasswordPage, PortalPage from .pages.bills import ( SubscriptionsPage, SubscriptionsApiPage, BillsApiProPage, BillsApiParPage, ContractsPage, ContractsApiPage ) from .pages.profile import ProfilePage -from weboob.browser.exceptions import ClientError, ServerError +from weboob.browser.exceptions import ClientError, ServerError, LoggedOut from weboob.tools.compat import basestring from weboob.tools.decorators import retry @@ -38,12 +38,13 @@ __all__ = ['OrangeBillBrowser'] -class OrangeBillBrowser(LoginBrowser): +class OrangeBillBrowser(LoginBrowser, StatesMixin): TIMEOUT = 60 BASEURL = 'https://espaceclientv3.orange.fr' home_page = URL(r'https://businesslounge.orange.fr/$', HomePage) + portal_page = URL(r'https://www.orange.fr/portail', PortalPage) loginpage = URL( r'https://login.orange.fr/\?service=sosh&return_url=https://www.sosh.fr/', r'https://login.orange.fr/front/login', @@ -83,12 +84,24 @@ class OrangeBillBrowser(LoginBrowser): doc_api_pro = URL(r'https://espaceclientpro.orange.fr/api/contract/(?P\d+)/bill/(?P.*)/(?P.*)/\?(?P)') profile = URL(r'/\?page=profil-infosPerso', ProfilePage) + def locate_browser(self, state): + try: + self.portal_page.go() + except ClientError as e: + if e.response.status_code == 401: + self.do_login() + return + raise + def do_login(self): assert isinstance(self.username, basestring) assert isinstance(self.password, basestring) - try: - self.loginpage.stay_or_go().login(self.username, self.password) + self.loginpage.go() + data = self.page.do_login_and_get_token(self.username, self.password) + self.password_page.go(json=data) + self.portal_page.go() + except ClientError as error: if error.response.status_code == 401: raise BrowserIncorrectPassword() @@ -121,7 +134,9 @@ def get_subscription_list(self): try: self.profile.go() - assert self.profile.is_here() or self.manage_cgi.is_here() + if not (self.profile.is_here() or self.manage_cgi.is_here()): + self.session.cookies.clear() + raise LoggedOut() # we land on manage_cgi page when there is cgu to validate if self.manage_cgi.is_here(): diff --git a/modules/orange/pages/login.py b/modules/orange/pages/login.py index c305eb38dcf9b11d643d14701f5edfe4ea30d374..36256a7e83004bdf3e2276366869cb21c3efeb0e 100644 --- a/modules/orange/pages/login.py +++ b/modules/orange/pages/login.py @@ -23,25 +23,27 @@ from io import StringIO -from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage +from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage, RawPage from weboob.tools.json import json from weboob.browser.filters.standard import CleanText, Format class LoginPage(HTMLPage): - def login(self, username, password): + def do_login_and_get_token(self, username, password): json_data = { + 'force': 'pwd', 'login': username, 'mem': False, } response = self.browser.location('https://login.orange.fr/front/login', json=json_data) + encrypt = json.loads(response.json()['options'])['loginEncrypt'] json_data = { 'login': username, 'password': password, - 'loginEncrypt': json.loads(response.json()['options'])['loginEncrypt'] + 'loginEncrypt': encrypt, } - self.browser.location('https://login.orange.fr/front/password', json=json_data) + return json_data class PasswordPage(JsonPage): @@ -76,3 +78,7 @@ class ManageCGI(HTMLPage): class HomePage(LoggedPage, HTMLPage): def get_error_message(self): return Format('%s %s', CleanText('//div[has-class("modal-dialog")]//h3'), CleanText('//div[has-class("modal-dialog")]//p[1]'))(self.doc) + + +class PortalPage(LoggedPage, RawPage): + pass