Commit 45440e55 authored by Florian Duguet's avatar Florian Duguet Committed by Romain Bignon

[ldlc] fix login for pro website

Split browser in par and pro browser because of change on pro website
which is now a little bit more different of par website
parent cbc87a4d
...@@ -18,47 +18,92 @@ ...@@ -18,47 +18,92 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.browser import LoginBrowser, URL, need_login from weboob.browser import LoginBrowser, URL, need_login
from weboob.exceptions import BrowserIncorrectPassword from weboob.exceptions import BrowserIncorrectPassword
from .pages import HomePage, BillsPage, LoginPage from .pages import LoginPage, HomePage, ParBillsPage, ProBillsPage
class LdlcBrowser(LoginBrowser):
login = URL('/Account/LoginPage.aspx', LoginPage)
bills = URL('/Account/CommandListingPage.aspx', BillsPage)
home = URL('/$', HomePage)
def __init__(self, website, *args, **kwargs):
self.website = website
if website == 'pro':
self.BASEURL = 'https://secure.ldlc-pro.com/'
else:
self.BASEURL = 'https://secure.ldlc.com/'
super(LdlcBrowser, self).__init__(*args, **kwargs)
class LdlcBrowser(LoginBrowser):
login = URL(r'/Account/LoginPage.aspx', LoginPage)
home = URL(r'/$', HomePage)
def do_login(self): def do_login(self):
self.login.stay_or_go().login(self.username, self.password) self.login.stay_or_go()
website = 'part' if type(self) == LdlcParBrowser else 'pro'
self.page.login(self.username, self.password, website)
if self.login.is_here(): if self.login.is_here():
raise BrowserIncorrectPassword raise BrowserIncorrectPassword(self.page.get_error())
@need_login @need_login
def get_subscription_list(self): def get_subscription_list(self):
return self.home.stay_or_go().get_list() return self.home.stay_or_go().get_list()
class LdlcParBrowser(LdlcBrowser):
BASEURL = 'https://secure.ldlc.com'
bills = URL(r'/Account/CommandListingPage.aspx', ParBillsPage)
@need_login @need_login
def iter_documents(self, subscription): def iter_documents(self, subscription):
self.bills.stay_or_go() self.bills.stay_or_go()
bills = list()
for value in self.page.get_range(): for value in self.page.get_range():
if self.website == 'pro': self.bills.go(data={'ctl00$ctl00$cphMainContent$cphMainContent$ddlDate': value, '__EVENTTARGET': 'ctl00$cphMainContent$ddlDate'})
event = 'ctl00$cphMainContent$ddlDate'
else: for bill in self.page.iter_documents(subid=subscription.id):
event = 'ctl00$ctl00$cphMainContent$cphMainContent$ddlDate' yield bill
self.bills.go(data={event: value, '__EVENTTARGET': 'ctl00$cphMainContent$ddlDate'}) class LdlcProBrowser(LdlcBrowser):
BASEURL = 'https://secure.ldlc-pro.com'
bills = URL(r'/Account/CommandListingPage.aspx', ProBillsPage)
@need_login
def iter_documents(self, subscription):
self.bills.stay_or_go()
for value in self.page.get_range():
self.bills.go(data={'ctl00$cphMainContent$ddlDate': value, '__EVENTTARGET': 'ctl00$cphMainContent$ddlDate'})
view_state = self.page.get_view_state()
# we need position to download file
position = 1
hidden_field = self.page.get_ctl00_actScriptManager_HiddenField()
for bill in self.page.iter_documents(subid=subscription.id):
bill._position = position
bill._view_state = view_state
bill._hidden_field = hidden_field
position += 1
yield bill
@need_login
def download_document(self, bill):
data = {
'__EVENTARGUMENT': '',
'__EVENTTARGET': '',
'__LASTFOCUS': '',
'__SCROLLPOSITIONX': 0,
'__SCROLLPOSITIONY': 0,
'__VIEWSTATE': bill._view_state,
'ctl00$actScriptManager': '',
'ctl00$cphMainContent$DetailCommand$hfCommand': '',
'ctl00$cphMainContent$DetailCommand$txtAltEmail': '',
'ctl00$cphMainContent$ddlDate': bill.date.year,
'ctl00$cphMainContent$hfCancelCommandId': '',
'ctl00$cphMainContent$hfCommandId': '',
'ctl00$cphMainContent$hfCommandSearch': '',
'ctl00$cphMainContent$hfOrderTri': 1,
'ctl00$cphMainContent$hfTypeTri': 1,
'ctl00$cphMainContent$rptCommand$ctl%s$hlFacture.x' % str(bill._position).zfill(2): '7',
'ctl00$cphMainContent$rptCommand$ctl%s$hlFacture.y' % str(bill._position).zfill(2): '11',
'ctl00$cphMainContent$txtCommandSearch': '',
'ctl00$hfCountries': '',
'ctl00$ucHeaderControl$ctrlSuggestedProductPopUp$HiddenCommandeSupplementaire': '',
'ctl00$ucHeaderControl$ctrlSuggestedProductPopUp$hiddenPopUp': '',
'ctl00$ucHeaderControl$txtSearch': 'Rechercher+...',
'ctl00_actScriptManager_HiddenField': bill._hidden_field
}
for i in self.page.get_documents(subid=subscription.id): return self.open(bill.url, data=data).content
bills.append(i)
return bills
...@@ -23,7 +23,7 @@ from weboob.capabilities.base import find_object ...@@ -23,7 +23,7 @@ from weboob.capabilities.base import find_object
from weboob.tools.backend import Module, BackendConfig from weboob.tools.backend import Module, BackendConfig
from weboob.tools.value import ValueBackendPassword, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import LdlcBrowser from .browser import LdlcParBrowser, LdlcProBrowser
__all__ = ['LdlcModule'] __all__ = ['LdlcModule']
...@@ -37,18 +37,17 @@ class LdlcModule(Module, CapDocument): ...@@ -37,18 +37,17 @@ class LdlcModule(Module, CapDocument):
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
VERSION = '1.4' VERSION = '1.4'
CONFIG = BackendConfig(Value('login', label='Email'), CONFIG = BackendConfig(Value('login', label='Email'),
ValueBackendPassword('password', label='Password'), ValueBackendPassword('password', label='Password'),
Value('website', label='Site web', default='part', Value('website', label='Site web', default='part',
choices={'pro': 'Professionnels', choices={'pro': 'Professionnels', 'part': 'Particuliers'}))
'part': 'Particuliers'}))
BROWSER = LdlcBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['website'].get(), if self.config['website'].get() == 'part':
self.config['login'].get(), self.BROWSER = LdlcParBrowser
self.config['password'].get()) else:
self.BROWSER = LdlcProBrowser
return self.create_browser(self.config['login'].get(), self.config['password'].get())
def iter_subscription(self): def iter_subscription(self):
return self.browser.get_subscription_list() return self.browser.get_subscription_list()
...@@ -70,4 +69,7 @@ class LdlcModule(Module, CapDocument): ...@@ -70,4 +69,7 @@ class LdlcModule(Module, CapDocument):
def download_document(self, bill): def download_document(self, bill):
if not isinstance(bill, Bill): if not isinstance(bill, Bill):
bill = self.get_document(bill) bill = self.get_document(bill)
return self.browser.open(bill.url).content if self.config['website'].get() == 'part':
return self.browser.open(bill.url).content
else:
return self.browser.download_document(bill)
...@@ -17,13 +17,22 @@ ...@@ -17,13 +17,22 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.pages import HTMLPage, LoggedPage
from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Format, QueryValue from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Format, QueryValue, TableCell, Currency
from weboob.browser.elements import ListElement, ItemElement, method from weboob.browser.elements import ListElement, ItemElement, method, TableElement
from weboob.browser.filters.html import Attr from weboob.browser.filters.html import Attr
from weboob.capabilities.bill import Bill, Subscription from weboob.capabilities.bill import Bill, Subscription
from weboob.tools.date import parse_french_date from weboob.tools.date import parse_french_date
class HiddenFieldPage(HTMLPage):
def get_ctl00_actScriptManager_HiddenField(self):
param = QueryValue(Attr('//script[contains(@src, "js/CombineScriptsHandler.ashx?")]', 'src'), "_TSM_CombinedScripts_")(self.doc)
return param
class HomePage(LoggedPage, HTMLPage): class HomePage(LoggedPage, HTMLPage):
@method @method
class get_list(ListElement): class get_list(ListElement):
...@@ -36,41 +45,80 @@ class HomePage(LoggedPage, HTMLPage): ...@@ -36,41 +45,80 @@ class HomePage(LoggedPage, HTMLPage):
obj_label = CleanText('.//div[@id="divlblTitleFirstNameLastName"]//span') obj_label = CleanText('.//div[@id="divlblTitleFirstNameLastName"]//span')
class LoginPage(HTMLPage): class LoginPage(HiddenFieldPage):
def login(self, username, password): def login(self, username, password, website):
form = self.get_form(xpath='//form[@id="aspnetForm"]') form = self.get_form(id='aspnetForm')
form["ctl00$ctl00$cphMainContent$cphMainContent$txbMail"] = username if website == 'part':
form["ctl00$ctl00$cphMainContent$cphMainContent$txbPassword"] = password form["ctl00$ctl00$cphMainContent$cphMainContent$txbMail"] = username
form["__EVENTTARGET"] = "ctl00$ctl00$cphMainContent$cphMainContent$butConnexion" form["ctl00$ctl00$cphMainContent$cphMainContent$txbPassword"] = password
form["ctl00_ctl00_actScriptManager_HiddenField"] = self.get_ctl00_actScriptManager_HiddenField() form["__EVENTTARGET"] = "ctl00$ctl00$cphMainContent$cphMainContent$butConnexion"
form["ctl00_ctl00_actScriptManager_HiddenField"] = self.get_ctl00_actScriptManager_HiddenField()
else:
form["ctl00$cphMainContent$txbMail"] = username
form["ctl00$cphMainContent$txbPassword"] = password
form["__EVENTTARGET"] = "ctl00$cphMainContent$butConnexion"
form["ctl00_ctl00_actScriptManager_HiddenField"] = self.get_ctl00_actScriptManager_HiddenField()
form.submit() form.submit()
def get_ctl00_actScriptManager_HiddenField(self): def get_error(self):
param = QueryValue(Attr('//script[contains(@src, "js/CombineScriptsHandler.ashx?")]', 'src'), "_TSM_CombinedScripts_")(self.doc) return CleanText('//span[contains(text(), "Identifiants incorrects")]')(self.doc)
return param
class BillsPage(LoggedPage, HTMLPage): class BillsPage(LoggedPage, HiddenFieldPage):
def get_range(self): def get_range(self):
for value in self.doc.xpath('//div[@class="commandListing content clearfix"]//select/option/@value'): for value in self.doc.xpath('//div[@class="commandListing content clearfix"]//select/option/@value'):
yield value yield value
class ParBillsPage(BillsPage):
@method @method
class get_documents(ListElement): class iter_documents(TableElement):
item_xpath = '//table[@id="TopListing"]//tr' ignore_duplicate = True
item_xpath = '//table[@id="TopListing"]/tr[position()>1]'
head_xpath = '//table[@id="TopListing"]/tr[@class="TopListingHeader"]/td'
col_id = 'N° de commande'
col_date = 'Date'
col_price = 'Montant TTC'
class item(ItemElement): class item(ItemElement):
klass = Bill klass = Bill
obj_id = Format('%s_%s', Env('subid'), CleanText('./td[3]')) obj_id = Format('%s_%s', Env('subid'), CleanText(TableCell('id')))
obj_url = Attr('./td[@class="center" or @class="center pdf"]/a', 'href') obj_url = Attr('./td[@class="center" or @class="center pdf"]/a', 'href')
obj_date = Env('date') obj_format = 'pdf'
obj_format = u"pdf" obj_price = CleanDecimal(TableCell('price'), replace_dots=True)
obj_type = u"bill" obj_currency = Currency(TableCell('price'))
obj_price = CleanDecimal('./td[@class="center montant"]/span', replace_dots=True)
def parse(self, el): def obj_date(self):
self.env['date'] = parse_french_date(el.xpath('./td[2]')[0].text).date() return parse_french_date(CleanText(TableCell('date'))(self)).date()
def condition(self): def condition(self):
return CleanText().filter(self.el.xpath('.//td')[-1]) != "" and len(self.el.xpath('./td[@class="center" or @class="center pdf"]/a/@href')) == 1 return CleanText().filter(self.el.xpath('.//td')[-1]) != "" and len(self.el.xpath('./td[@class="center" or @class="center pdf"]/a/@href')) == 1
class ProBillsPage(BillsPage):
def get_view_state(self):
return Attr('//input[@id="__VIEWSTATE"]', 'value')(self.doc)
@method
class iter_documents(TableElement):
ignore_duplicate = True
item_xpath = '//table[@id="TopListing"]/tr[contains(@class, "rowTable")]'
head_xpath = '//table[@id="TopListing"]/tr[@class="headTable"]/td'
col_id = 'N° de commande'
col_date = 'Date'
col_price = 'Montant HT'
class item(ItemElement):
klass = Bill
obj_id = Format('%s_%s', Env('subid'), CleanText(TableCell('id')))
obj_url = '/Account/CommandListingPage.aspx'
obj_format = 'pdf'
obj_price = CleanDecimal(TableCell('price'), replace_dots=True)
obj_currency = Currency(TableCell('price'))
def obj_date(self):
return parse_french_date(CleanText(TableCell('date'))(self)).date()
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