Exemplo n.º 1
0
 def iter_accounts(self):
     if 'accs' not in self.cache.keys():
         no_accounts_message = None
         self.accounts.stay_or_go(slug=self.SLUG, lang=self.LANG)
         # weird wrongpass
         if not self.accounts.is_here():
             raise BrowserIncorrectPassword()
         multi = self.page.get_multi()
         if len(multi):
             # Handle multi entreprise accounts
             accs = []
             for id in multi:
                 self.page.go_multi(id)
                 self.accounts.go(slug=self.SLUG)
                 if not no_accounts_message:
                     no_accounts_message = self.page.get_no_accounts_message(
                     )
                 for a in self.page.iter_accounts():
                     a._multi = id
                     accs.append(a)
         else:
             no_accounts_message = self.page.get_no_accounts_message()
             accs = [a for a in self.page.iter_accounts()]
         if not len(accs) and no_accounts_message:
             # Accounts list is empty and we found the
             # message on at least one of the spaces:
             raise NoAccountsException(no_accounts_message)
         self.cache['accs'] = accs
     return self.cache['accs']
Exemplo n.º 2
0
    def check_no_accounts(self):
        no_account_message = CleanText(
            u'//span[@id="MM_LblMessagePopinError"]/p[contains(text(), "Aucun compte disponible")]'
        )(self.doc)

        if no_account_message:
            raise NoAccountsException(no_account_message)
Exemplo n.º 3
0
    def get_accounts_list(self):
        if self.accounts is None:
            accounts = []

            self.par_accounts_checking.go()

            pages = [
                self.par_accounts_checking,
                self.par_accounts_savings_and_invests, self.par_accounts_loan
            ]
            no_accounts = 0
            for page in pages:
                page.go()

                if self.page.no_accounts:
                    no_accounts += 1
                    continue

                for account in self.page.iter_accounts():
                    accounts.append(account)

                if self.page.has_mandate_management_space:
                    self.location(self.page.mandate_management_space_link())
                    for mandate_account in self.page.iter_accounts():
                        accounts.append(mandate_account)

            self.accounts = accounts

            # if we are sure there is no accounts on the all visited pages,
            # it is legit.
            if no_accounts == len(pages):
                raise NoAccountsException()

        return self.accounts
Exemplo n.º 4
0
 def on_load(self):
     if self.doc['commun']['statut'] == 'NOK':
         reason = self.doc['commun']['raison']
         if reason == 'SYD-COMPTES-UNAUTHORIZED-ACCESS':
             raise NoAccountsException(
                 "Vous n'avez pas l'autorisation de consulter : {}".format(
                     reason))
         raise BrowserUnavailable(reason)
Exemplo n.º 5
0
 def open(self, *args, **kwargs):
     try:
         return super(HSBCHK, self).open(*args, **kwargs)
     except ClientError as e:
         if e.response.status_code == 401:
             self.auth_token = None
             self.logged = False
             self.session.cookies.clear()
             raise LoggedOut()
         if e.response.status_code == 409:
             raise NoAccountsException()
         raise
Exemplo n.º 6
0
 def on_load(self):
     self.browser.open(
         "https://voscomptesenligne.labanquepostale.fr/voscomptes/canalXHTML/securite/authentification/verifierMotDePasse-identif.ea"
     )
     if self.doc.xpath(
             u'//span[contains(text(), "L\'identifiant utilisé est celui d\'une Entreprise ou d\'une Association")]'
     ):
         raise BrowserIncorrectPassword(
             u"L'identifiant utilisé est celui d'une Entreprise ou d'une Association"
         )
     no_accounts = CleanText(u'//div[@class="textFCK"]')(self.doc)
     if no_accounts:
         raise NoAccountsException(no_accounts)
     MyHTMLPage.on_load(self)
Exemplo n.º 7
0
    def on_load(self):
        no_accounts_message = CleanText(
            '//span[contains(text(), "On this date, you still have no employee savings in this company.")] | \
                        //span[contains(text(), "On this date, you do not yet have any employee savings in this company.")] | \
                        //span[contains(text(), "On this date, you no longer have any employee savings in this company.")]'
        )(self.doc)
        if no_accounts_message:
            raise NoAccountsException(no_accounts_message)

        if CleanText(
                '//a//span[contains(text(), "J\'ACCEPTE LES CONDITIONS GENERALES D\'UTILISATION") or'
                '          contains(text(), "I ACCEPT THE GENERAL CONDITIONS OF USE")]'
        )(self.doc):
            raise ActionNeeded(
                "Veuillez valider les conditions générales d'utilisation")
Exemplo n.º 8
0
 def on_load(self):
     if self.doc['commun']['statut'].lower() == 'nok':
         reason = self.doc['commun']['raison']
         if reason == 'SYD-COMPTES-UNAUTHORIZED-ACCESS':
             raise NoAccountsException(
                 "Vous n'avez pas l'autorisation de consulter : {}".format(
                     reason))
         elif reason == 'niv_auth_insuff':
             raise BrowserIncorrectPassword(
                 'Vos identifiants sont incorrects')
         elif reason == 'chgt_mdp_oblig':
             raise BrowserPasswordExpired(
                 'Veuillez renouveler votre mot de passe')
         elif reason == 'oob_insc_oblig':
             raise AuthMethodNotImplemented(
                 "L'authentification par Secure Access n'est pas prise en charge"
             )
         raise BrowserUnavailable(reason)
Exemplo n.º 9
0
    def get_accounts_list(self):
        if self.accounts is None:
            accounts = []

            self.par_accounts_checking.go()

            pages = [
                self.par_accounts_checking,
                self.par_accounts_savings_and_invests, self.par_accounts_loan
            ]
            no_accounts = 0
            for page in pages:
                page.go()

                assert page.is_here(), "AccountList type page not reached"
                if self.page.no_accounts:
                    no_accounts += 1
                    continue

                for account in self.page.iter_accounts():
                    if account.type == Account.TYPE_LOAN:
                        self.location(account.url)
                        if 'CreditRenouvelable' not in account.url:
                            for loan in self.page.iter_loans():
                                accounts.append(loan)
                        else:
                            for loan in self.page.iter_revolving_loans():
                                accounts.append(loan)
                    else:
                        accounts.append(account)

                if self.page.has_mandate_management_space:
                    self.location(self.page.mandate_management_space_link())
                    for mandate_account in self.page.iter_accounts():
                        accounts.append(mandate_account)

            self.accounts = accounts

            # if we are sure there is no accounts on the all visited pages,
            # it is legit.
            if no_accounts == len(pages):
                raise NoAccountsException()

        return self.accounts
Exemplo n.º 10
0
    def get_numbers(self):
        if 'listCompteTitulaireCotitulaire' not in self.doc and 'exception' in self.doc:
            raise NoAccountsException()

        ret = {}

        ret.update({
            d['index']: d['numeroContratSouscrit']
            for d in self.doc['listCompteTitulaireCotitulaire']
        })
        ret.update({
            d['index']: d['numeroContratSouscrit']
            for p in self.doc['listCompteMandataire'].values() for d in p
        })
        ret.update({
            d['index']: d['numeroContratSouscrit']
            for p in self.doc['listCompteLegalRep'].values() for d in p
        })

        return ret
Exemplo n.º 11
0
 def on_load(self):
     if self.doc['commun']['statut'].lower() == 'nok':
         reason = self.doc['commun']['raison']
         if reason == 'SYD-COMPTES-UNAUTHORIZED-ACCESS':
             raise NoAccountsException(
                 "Vous n'avez pas l'autorisation de consulter : {}".format(
                     reason))
         elif reason == 'niv_auth_insuff':
             return
         elif reason in ('chgt_mdp_oblig', 'chgt_mdp_init'):
             raise BrowserPasswordExpired(
                 'Veuillez vous rendre sur le site de la banque pour renouveler votre mot de passe'
             )
         elif reason == 'oob_insc_oblig':
             raise AuthMethodNotImplemented(
                 "L'authentification par Secure Access n'est pas prise en charge"
             )
         else:
             # the BrowserUnavailable was raised for every unknown error, and was masking the real error.
             # So users and developers didn't know what kind of error it was.
             assert False, 'Error %s is not handled yet.' % reason
Exemplo n.º 12
0
    def get_list(self):
        err = CleanText('//span[@class="error_msg"]', default='')(self.doc)
        if err == 'Vous ne disposez pas de compte consultable.':
            raise NoAccountsException()

        def check_valid_url(url):
            pattern = [
                '/restitution/cns_detailAVPAT.html',
                '/restitution/cns_detailAlterna.html',
            ]

            for p in pattern:
                if url.startswith(p):
                    return False
            return True

        for tr in self.doc.getiterator('tr'):
            if 'LGNTableRow' not in tr.attrib.get('class', '').split():
                continue

            account = Account()
            for td in tr.getiterator('td'):
                if td.attrib.get('headers', '') == 'TypeCompte':
                    a = td.find('a')
                    if a is None:
                        break
                    account.label = CleanText('.')(a)
                    account._link_id = a.get('href', '')
                    for pattern, actype in self.TYPES.items():
                        if account.label.startswith(pattern):
                            account.type = actype
                            break
                    else:
                        if account._link_id.startswith('/asv/asvcns10.html'):
                            account.type = Account.TYPE_LIFE_INSURANCE
                    # Website crashes when going on theses URLs
                    if not check_valid_url(account._link_id):
                        account._link_id = None

                elif td.attrib.get('headers', '') == 'NumeroCompte':
                    account.id = CleanText(u'.', replace=[(' ', '')])(td)

                elif td.attrib.get('headers', '') == 'Libelle':
                    text = CleanText('.')(td)
                    if text != '':
                        account.label = text

                elif td.attrib.get('headers', '') == 'Solde':
                    div = td.xpath('./div[@class="Solde"]')
                    if len(div) > 0:
                        balance = CleanText('.')(div[0])
                        if len(balance) > 0 and balance not in ('ANNULEE',
                                                                'OPPOSITION'):
                            try:
                                account.balance = Decimal(
                                    FrenchTransaction.clean_amount(balance))
                            except InvalidOperation:
                                self.logger.error(
                                    'Unable to parse balance %r' % balance)
                                continue
                            account.currency = account.get_currency(balance)
                        else:
                            account.balance = NotAvailable
            if not account.label or empty(account.balance):
                continue

            if account._link_id and 'CARTE_' in account._link_id:
                account.type = account.TYPE_CARD

            if account.type == Account.TYPE_UNKNOWN:
                self.logger.debug('Unknown account type: %s', account.label)

            yield account
Exemplo n.º 13
0
    def get_accounts_list(self):
        if self.session.cookies.get('indicateur'):
            # Malformed cookie to delete to reach other spaces
            del self.session.cookies['indicateur']

        if self.accounts is None:
            accounts = []
            to_check = []

            self.par_accounts_checking.go()

            pages = [self.par_accounts_checking, self.par_accounts_savings_and_invests, self.par_accounts_loan]
            no_accounts = 0
            for page in pages:
                page.go()

                assert page.is_here(), "AccountList type page not reached"
                if self.page.no_accounts:
                    no_accounts += 1
                    continue

                for account in self.page.iter_accounts():
                    if account.type == Account.TYPE_LOAN:
                        self.location(account.url)
                        if 'initSSO' not in account.url:
                            for loan in self.page.iter_loans():
                                loan.currency = account.currency
                                accounts.append(loan)
                            student_loan = self.page.get_student_loan()
                            if student_loan:
                                # Number of headers and item elements are the same
                                assert len(student_loan._heads) == len(student_loan._items)
                                student_loan.currency = account.currency
                                accounts.append(student_loan)
                        else:
                            # The main revolving page is not accessible, we can reach it by this new way
                            self.location(self.absurl('/voscomptes/canalXHTML/sso/lbpf/souscriptionCristalFormAutoPost.jsp'))
                            self.page.go_revolving()
                            revolving_loan = self.page.get_revolving_attributes(account)
                            accounts.append(revolving_loan)
                        page.go()

                    elif account.type == Account.TYPE_PERP:
                        # PERP balances must be fetched from the details page,
                        # otherwise we just scrape the "Rente annuelle estimée":
                        balance = self.open(account.url).page.get_balance()
                        if balance is not None:
                            account.balance = balance
                        accounts.append(account)

                    else:
                        accounts.append(account)
                        if account.type == Account.TYPE_CHECKING and account._has_cards:
                            to_check.append(account)

                if self.page.has_mandate_management_space:
                    self.location(self.page.mandate_management_space_link())
                    for mandate_account in self.page.iter_accounts():
                        accounts.append(mandate_account)

                for account in to_check:
                    accounts.extend(self.iter_cards(account))
                to_check = []

            self.accounts = accounts

            # if we are sure there is no accounts on the all visited pages,
            # it is legit.
            if no_accounts == len(pages):
                raise NoAccountsException()

        return self.accounts
Exemplo n.º 14
0
    def get_accounts_list(self):
        if not self.accounts_list:
            if self.currentSubBank is None:
                self.getCurrentSubBank()

            self.two_cards_page = None
            self.accounts_list = []
            self.revolving_accounts = []
            self.unavailablecards = []
            self.cards_histo_available = []
            self.cards_list =[]
            self.cards_list2 =[]

            # For some cards the validity information is only availaible on these 2 links
            self.cards_hist_available.go(subbank=self.currentSubBank)
            if self.cards_hist_available.is_here():
                self.unavailablecards.extend(self.page.get_unavailable_cards())
                for acc in self.page.iter_accounts():
                    acc._referer = self.cards_hist_available
                    self.accounts_list.append(acc)
                    self.cards_list.append(acc)
                    self.cards_histo_available.append(acc.id)

            if not self.cards_list:
                self.cards_hist_available2.go(subbank=self.currentSubBank)
                if self.cards_hist_available2.is_here():
                    self.unavailablecards.extend(self.page.get_unavailable_cards())
                    for acc in self.page.iter_accounts():
                        acc._referer = self.cards_hist_available2
                        self.accounts_list.append(acc)
                        self.cards_list.append(acc)
                        self.cards_histo_available.append(acc.id)

            for acc in self.revolving_loan_list.stay_or_go(subbank=self.currentSubBank).iter_accounts():
                self.accounts_list.append(acc)
                self.revolving_accounts.append(acc.label.lower())

            # Handle cards on tiers page
            self.cards_activity.go(subbank=self.currentSubBank)
            companies = self.page.companies_link() if self.cards_activity.is_here() else \
                        [self.page] if self.is_new_website else []
            for company in companies:
                # We need to return to the main page to avoid navigation error
                self.cards_activity.go(subbank=self.currentSubBank)
                page = self.open(company).page if isinstance(company, basestring) else company
                for card in page.iter_cards():
                    card2 = find_object(self.cards_list, id=card.id[:16])
                    if card2:
                        # In order to keep the id of the card from the old space, we exchange the following values
                        card._link_id = card2._link_id
                        card._parent_id = card2._parent_id
                        card.coming = card2.coming
                        card._referer = card2._referer
                        card._secondpage = card2._secondpage
                        self.accounts_list.remove(card2)
                    self.accounts_list.append(card)
                    self.cards_list2.append(card)
            self.cards_list.extend(self.cards_list2)

            # Populate accounts from old website
            if not self.is_new_website:
                self.logger.info('On old creditmutuel website')
                self.accounts.stay_or_go(subbank=self.currentSubBank)
                has_no_account = self.page.has_no_account()
                self.accounts_list.extend(self.page.iter_accounts())
                self.iban.go(subbank=self.currentSubBank).fill_iban(self.accounts_list)
                self.por.go(subbank=self.currentSubBank)
                self.page.add_por_accounts(self.accounts_list)
            # Populate accounts from new website
            else:
                self.new_accounts.stay_or_go(subbank=self.currentSubBank)
                has_no_account = self.page.has_no_account()
                self.accounts_list.extend(self.page.iter_accounts())
                self.iban.go(subbank=self.currentSubBank).fill_iban(self.accounts_list)
                self.por.go(subbank=self.currentSubBank)
                self.page.add_por_accounts(self.accounts_list)

            self.li.go(subbank=self.currentSubBank)
            self.accounts_list.extend(self.page.iter_li_accounts())

            # This type of account is like a loan, for splitting payments in smaller amounts.
            # Its history is irrelevant because money is debited from a checking account and
            # the balance is not even correct, so ignore it.
            excluded_label = ['etalis', 'valorisation totale']

            accounts_by_id = {}
            for acc in self.accounts_list:
                if acc.label.lower() not in excluded_label:
                    accounts_by_id[acc.id] = acc

            # Set the parent to loans and cards accounts
            for acc in self.accounts_list:
                if acc.type == Account.TYPE_CARD and not empty(getattr(acc, '_parent_id', None)):
                    acc.parent = accounts_by_id.get(acc._parent_id, NotAvailable)

                elif acc.type in (Account.TYPE_MORTGAGE, Account.TYPE_LOAN) and acc._parent_id:
                    acc.parent = accounts_by_id.get(acc._parent_id, NotAvailable)

            self.accounts_list = list(accounts_by_id.values())

            if has_no_account and not self.accounts_list:
                raise NoAccountsException(has_no_account)

        self.ownership_guesser()

        return self.accounts_list
Exemplo n.º 15
0
 def parse(self, el):
     msg = CleanText('//font[@color="#FF0000"]')(self)
     if msg and 'NO INFORMATION AVAILABLE.' in msg:
         raise NoAccountsException()
Exemplo n.º 16
0
 def parse(self, el):
     if not el.get('count', 42):
         raise NoAccountsException()
Exemplo n.º 17
0
 def on_load(self):
     if CleanText(u'//span[contains(text(), "vous ne disposez plus d\'épargne salariale")]')(self.doc):
         raise NoAccountsException()
Exemplo n.º 18
0
    def get_accounts_list(self):
        self.status.go()

        exc = None
        for x in range(3):
            if self.accounts_list is not None:
                break

            self.accounts_list = []
            self.loans_list = []
            # Check that there is at least one account for this user
            has_account = False
            self.pro_accounts.go()
            if self.pro_accounts.is_here():
                self.accounts_list.extend(self.page.iter_accounts())
                has_account = True
            else:
                # We dont want to let has_account=False if we landed on an unknown page
                # it has to be the no_accounts page
                assert self.no_account.is_here()

            try:
                self.accounts.go()
            except BrowserUnavailable as e:
                self.logger.warning('par accounts seem unavailable, retrying')
                exc = e
                self.accounts_list = None
                continue
            else:
                if self.accounts.is_here():
                    self.accounts_list.extend(self.page.iter_accounts())
                    has_account = True
                else:
                    # We dont want to let has_account=False if we landed on an unknown page
                    # it has to be the no_accounts page
                    assert self.no_account.is_here()

                exc = None

            if not has_account:
                # if we landed twice on NoAccountPage, it means there is neither pro accounts nor pp accounts
                raise NoAccountsException()

            for account in list(self.accounts_list):
                if account.type == Account.TYPE_LOAN:
                    # Loans details are present on another page so we create
                    # a Loan object and remove the corresponding Account:
                    self.location(account.url)
                    loan = self.page.get_loan()
                    loan.url = account.url
                    self.loans_list.append(loan)
                    self.accounts_list.remove(account)
            self.accounts_list.extend(self.loans_list)

            self.cards_list = [
                acc for acc in self.accounts_list
                if acc.type == Account.TYPE_CARD
            ]
            if self.cards_list:
                self.go_cards_number(self.cards_list[0].url)
                if self.cards.is_here():
                    self.page.populate_cards_number(self.cards_list)
            # Cards without a number are not activated yet:
            for card in self.cards_list:
                if not card.number:
                    self.accounts_list.remove(card)

            for account in self.accounts_list:
                if account.type not in (Account.TYPE_CARD, Account.TYPE_LOAN,
                                        Account.TYPE_CONSUMER_CREDIT,
                                        Account.TYPE_MORTGAGE,
                                        Account.TYPE_REVOLVING_CREDIT,
                                        Account.TYPE_LIFE_INSURANCE):
                    account.iban = self.iban.go(
                        webid=account._webid).get_iban()

            for card in self.cards_list:
                checking, = [
                    account for account in self.accounts_list
                    if account.type == Account.TYPE_CHECKING
                    and account.url in card.url
                ]
                card.parent = checking

        if exc:
            raise exc

        self.ownership_guesser()
        return self.accounts_list
Exemplo n.º 19
0
 def is_accounts(self):
     error_msg = CleanText('//span[@class="error_msg"]')(self.doc)
     if 'Vous ne disposez pas de compte consultable' in error_msg:
         raise NoAccountsException(error_msg)
Exemplo n.º 20
0
    def get_accounts_list(self):
        if not self.accounts_list:
            if self.currentSubBank is None:
                self.getCurrentSubBank()

            self.two_cards_page = None
            self.accounts_list = []
            self.revolving_accounts = []
            self.unavailablecards = []
            self.cards_histo_available = []
            self.cards_list = []
            self.cards_list2 = []

            # For some cards the validity information is only availaible on these 2 links
            self.cards_hist_available.go(subbank=self.currentSubBank)
            if self.cards_hist_available.is_here():
                self.unavailablecards.extend(self.page.get_unavailable_cards())
                for acc in self.page.iter_accounts():
                    acc._referer = self.cards_hist_available
                    self.accounts_list.append(acc)
                    self.cards_list.append(acc)
                    self.cards_histo_available.append(acc.id)

            if not self.cards_list:
                self.cards_hist_available2.go(subbank=self.currentSubBank)
                if self.cards_hist_available2.is_here():
                    self.unavailablecards.extend(
                        self.page.get_unavailable_cards())
                    for acc in self.page.iter_accounts():
                        acc._referer = self.cards_hist_available2
                        self.accounts_list.append(acc)
                        self.cards_list.append(acc)
                        self.cards_histo_available.append(acc.id)

            for acc in self.revolving_loan_list.stay_or_go(
                    subbank=self.currentSubBank).iter_accounts():
                self.accounts_list.append(acc)
                self.revolving_accounts.append(acc.label.lower())

            # Handle cards on tiers page
            self.cards_activity.go(subbank=self.currentSubBank)
            companies = self.page.companies_link() if self.cards_activity.is_here() else \
                        [self.page] if self.is_new_website else []
            for company in companies:
                # We need to return to the main page to avoid navigation error
                self.cards_activity.go(subbank=self.currentSubBank)
                page = self.open(company).page if isinstance(
                    company, basestring) else company
                for card in page.iter_cards():
                    card2 = find_object(self.cards_list, id=card.id[:16])
                    if card2:
                        # In order to keep the id of the card from the old space, we exchange the following values
                        card._link_id = card2._link_id
                        card._parent_id = card2._parent_id
                        card.coming = card2.coming
                        card._referer = card2._referer
                        card._secondpage = card2._secondpage
                        self.accounts_list.remove(card2)
                    self.accounts_list.append(card)
                    self.cards_list2.append(card)
            self.cards_list.extend(self.cards_list2)

            # Populate accounts from old website
            if not self.is_new_website:
                self.accounts.stay_or_go(subbank=self.currentSubBank)
                has_no_account = self.page.has_no_account()
                self.accounts_list.extend(self.page.iter_accounts())
                self.iban.go(subbank=self.currentSubBank).fill_iban(
                    self.accounts_list)
                self.por.go(subbank=self.currentSubBank).add_por_accounts(
                    self.accounts_list)
            # Populate accounts from new website
            else:
                self.new_accounts.stay_or_go(subbank=self.currentSubBank)
                has_no_account = self.page.has_no_account()
                self.accounts_list.extend(self.page.iter_accounts())
                self.iban.go(subbank=self.currentSubBank).fill_iban(
                    self.accounts_list)
                self.por.go(subbank=self.currentSubBank).add_por_accounts(
                    self.accounts_list)

            self.li.go(subbank=self.currentSubBank)
            self.accounts_list.extend(self.page.iter_li_accounts())

            for acc in self.cards_list:
                if hasattr(acc, '_parent_id'):
                    acc.parent = find_object(self.accounts_list,
                                             id=acc._parent_id)

            excluded_label = ['etalis', 'valorisation totale']
            self.accounts_list = [
                acc for acc in self.accounts_list
                if not any(w in acc.label.lower() for w in excluded_label)
            ]
            if has_no_account and not self.accounts_list:
                raise NoAccountsException(has_no_account)

        self.ownership_guesser()

        return self.accounts_list