<commit_before>'use strict'

// Force sentry DSN into environment variables
// In the future, will be set by the stack
process.env.SENTRY_DSN =
  process.env.SENTRY_DSN ||
  'https://ae2447d6c4544985ae50a03520a06f89:5371dd68dfea408bbd9fbc8c97a9309a@sentry.cozycloud.cc/14'

const {
  log,
  BaseKonnector,
  saveBills,
  requestFactory
} = require('cozy-konnector-libs')
const moment = require('moment')
const sortBy = require('lodash/sortBy')
moment.locale('fr')
const bluebird = require('bluebird')
const Bill = require('./bill')

const urlService = require('./urlService')

let request = requestFactory()
const j = request.jar()
request = requestFactory({
  // debug: true,
  cheerio: true,
  json: false,
  jar: j
})

module.exports = new BaseKonnector(function fetch(fields) {
  return checkLogin(fields)
    .then(() => logIn(fields))
    .then($ => fetchMainPage($))
    .then($ => parseMainPage($))
    .then(reimbursements => getBills(reimbursements))
    .then(entries => {
      // get custom bank identifier if any
      let identifiers = ['c.p.a.m.', 'caisse', 'cpam', 'ameli']
      if (fields.bank_identifier && fields.bank_identifier.length) {
        identifiers = fields.bank_identifier
      }

      return saveBills(entries, fields.folderPath, {
        timeout: Date.now() + 60 * 1000,
        identifiers,
        dateDelta: 10,
        amountDelta: 0.1
      })
    })
})

const checkLogin = function(fields) {
  log('info', 'Checking the length of the login')
  if (fields.login.length > 13) {
    // remove the key from the social security number
    fields.login = fields.login.substr(0, 13)
    log('debug', `Fixed the login length to 13`)
  }

  return Promise.resolve()
}

// Procedure to login to Ameli website.
const logIn = async function(fields) {
  log('info', 'Now logging in')

  const form = {
    connexioncompte_2numSecuriteSociale: fields.login,
    connexioncompte_2codeConfidentiel: fields.password,
    connexioncompte_2actionEvt: 'connecter',
    submit: 'me+connecter'
  }

  // First request to get the cookie
  await request({
    url: urlService.getLoginUrl(),
    resolveWithFullResponse: true
  })

  const $ = await request({
    method: 'POST',
    form,
    url: urlService.getSubmitUrl()
  })

  const $errors = $('#r_errors')
  if ($errors.length > 0) {
    log('debug', $errors.text(), 'These errors where found on screen')
    throw new Error('LOGIN_FAILED')
  }

  // The user must validate the CGU form
  const $cgu = $('meta[http-equiv=refresh]')
  if (
    $cgu.length > 0 &&
    $cgu.attr('content').includes('as_conditions_generales_page')
  ) {
    log('debug', $cgu.attr('content'))
    throw new Error('USER_ACTION_NEEDED')
  }

  // Default case. Something unexpected went wrong after the login
  if ($('[title="Déconnexion du compte ameli"]').length !== 1) {
    log('debug', $('body').html(), 'No deconnection link found in the html')
    log('debug', 'Something unexpected went wrong after the login')
    if ($('.centrepage h2')) {
      log(
        'error',
        $('.centrepage h2')
          .text()
          .trim()
      )
      throw new Error('VENDOR_DOWN')
    }
    throw new Error('LOGIN_FAILED')
  }

  log('info', 'Correctly logged in')

  return await request(urlService.getReimbursementUrl())
}

// fetch the HTML page with the list of health cares
const fetchMainPage = function($) {
  log('info', 'Fetching the list of bills')

  // Get end date to generate the bill's url
  const endDate = moment($('#paiements_1dateFin').attr('value'), 'DD/MM/YYYY')

  // We can get the history only 6 months back
  const billUrl = urlService.getBillUrl(endDate, 6)
<commit_msg>fix: detect blocked account<commit_after>'use strict'

// Force sentry DSN into environment variables
// In the future, will be set by the stack
process.env.SENTRY_DSN =
  process.env.SENTRY_DSN ||
  'https://ae2447d6c4544985ae50a03520a06f89:5371dd68dfea408bbd9fbc8c97a9309a@sentry.cozycloud.cc/14'

const {
  log,
  BaseKonnector,
  saveBills,
  requestFactory,
  errors
} = require('cozy-konnector-libs')
const moment = require('moment')
const sortBy = require('lodash/sortBy')
moment.locale('fr')
const bluebird = require('bluebird')
const Bill = require('./bill')

const urlService = require('./urlService')

let request = requestFactory()
const j = request.jar()
request = requestFactory({
  // debug: true,
  cheerio: true,
  json: false,
  jar: j
})

module.exports = new BaseKonnector(function fetch(fields) {
  return checkLogin(fields)
    .then(() => logIn(fields))
    .then($ => fetchMainPage($))
    .then($ => parseMainPage($))
    .then(reimbursements => getBills(reimbursements))
    .then(entries => {
      // get custom bank identifier if any
      let identifiers = ['c.p.a.m.', 'caisse', 'cpam', 'ameli']
      if (fields.bank_identifier && fields.bank_identifier.length) {
        identifiers = fields.bank_identifier
      }

      return saveBills(entries, fields.folderPath, {
        timeout: Date.now() + 60 * 1000,
        identifiers,
        dateDelta: 10,
        amountDelta: 0.1
      })
    })
})

const checkLogin = function(fields) {
  log('info', 'Checking the length of the login')
  if (fields.login.length > 13) {
    // remove the key from the social security number
    fields.login = fields.login.substr(0, 13)
    log('debug', `Fixed the login length to 13`)
  }

  return Promise.resolve()
}

// Procedure to login to Ameli website.
const logIn = async function(fields) {
  log('info', 'Now logging in')

  const form = {
    connexioncompte_2numSecuriteSociale: fields.login,
    connexioncompte_2codeConfidentiel: fields.password,
    connexioncompte_2actionEvt: 'connecter',
    submit: 'me+connecter'
  }

  // First request to get the cookie
  await request({
    url: urlService.getLoginUrl(),
    resolveWithFullResponse: true
  })

  const $ = await request({
    method: 'POST',
    form,
    url: urlService.getSubmitUrl()
  })

  const $errors = $('#r_errors')
  if ($errors.length > 0) {
    log('debug', $errors.text(), 'These errors where found on screen')
    throw new Error(errors.LOGIN_FAILED)
  }

  // The user must validate the CGU form
  const $cgu = $('meta[http-equiv=refresh]')
  if (
    $cgu.length > 0 &&
    $cgu.attr('content').includes('as_conditions_generales_page')
  ) {
    log('debug', $cgu.attr('content'))
    throw new Error(errors.USER_ACTION_NEEDED)
  }

  // Default case. Something unexpected went wrong after the login
  if ($('[title="Déconnexion du compte ameli"]').length !== 1) {
    log('debug', $('body').html(), 'No deconnection link found in the html')
    log('debug', 'Something unexpected went wrong after the login')
    if ($('.centrepage h2, .centrepage h1')) {
      const errorMessage = $('.centrepage h1, .centrepage h2').text()
      log('error', errorMessage)
      if (errorMessage === 'Compte bloqué') {
        throw new Error('USER_ACTION_NEEDED.ACCOUNT_LOCKED')
      } else {
        throw new Error(errors.VENDOR_DOWN)
      }
    }
    throw new Error(errors.LOGIN_FAILED)
  }

  log('info', 'Correctly logged in')

  return await request(urlService.getReimbursementUrl())
}

// fetch the HTML page with the list of health cares
const fetchMainPage = function($) {
  log('info', 'Fetching the list of bills')

  // Get end date to generate the bill's url
  const endDate = moment($('#paiements_1dateFin').attr('value'), 'DD/MM/YYYY')

  // We can get the history only 6 months back
  const billUrl = urlService.getBillUrl(endDate, 6)

{'fraction_non_alphanumeric': 0.13693885706673772, 'fraction_numerical': 0.01891567869988011, 'mean_word_length': 3.447867298578199, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2072556', 'n_tokens_mistral': 2543, 'n_tokens_neox': 2425, 'n_words': 642}