<commit_before>#!/usr/bin/env node

// Packages
const ansiEscapes = require('ansi-escapes')
const chalk = require('chalk')
const ccValidator = require('credit-card')

// Ours
const textInput = require('../lib/utils/input/text')
const countries = require('../lib/utils/billing/country-list')
const cardBrands = require('../lib/utils/billing/card-brands')
const geocode = require('../lib/utils/billing/geocode')
const success = require('../lib/utils/output/success')
const wait = require('../lib/utils/output/wait')
const { tick } = require('../lib/utils/output/chars')
const rightPad = require('../lib/utils/output/right-pad')

function expDateMiddleware(data) {
  return data
}

module.exports = function({ creditCards, currentTeam, user }) {
  const state = {
    error: undefined,
    cardGroupLabel: `> ${chalk.bold(
      `Enter your card details for ${chalk.bold(
        (currentTeam && currentTeam.slug) || user.username || user.email
      )}`
    )}`,

    name: {
      label: rightPad('Full Name', 12),
      placeholder: '<NAME>',
      validateValue: data => data.trim().length > 0
    },

    cardNumber: {
      label: rightPad('Number', 12),
      mask: 'cc',
      placeholder: '#### #### #### ####',
      validateKeypress: (data, value) => /\d/.test(data) && value.length < 19,
      validateValue: data => {
        data = data.replace(/ /g, '')
        const type = ccValidator.determineCardType(data)
        if (!type) {
          return false
        }
        return ccValidator.isValidCardNumber(data, type)
      }
    },

    ccv: {
      label: rightPad('CCV', 12),
      mask: 'ccv',
      placeholder: '###',
      validateValue: data => {
        const brand = state.cardNumber.brand.toLowerCase()
        return ccValidator.doesCvvMatchType(data, brand)
      }
    },

    expDate: {
      label: rightPad('Exp. Date', 12),
      mask: 'expDate',
      placeholder: 'mm / yyyy',
      middleware: expDateMiddleware,
      validateValue: data => !ccValidator.isExpired(...data.split(' / '))
    },

    addressGroupLabel: `\n> ${chalk.bold('Enter your billing address')}`,

    country: {
      label: rightPad('Country', 12),
      async autoComplete(value) {
        for (const country in countries) {
          if (!Object.hasOwnProperty.call(countries, country)) {
            continue
          }
          if (country.startsWith(value)) {
            return country.substr(value.length)
          }
        }
        return false
      },
      validateValue: value => countries[value] !== undefined
    },

    zipCode: {
      label: rightPad('ZIP', 12),
      validadeKeypress: data => data.trim().length > 0,
      validateValue: data => data.trim().length > 0
    },

    state: {
      label: rightPad('State', 12),
      validateValue: data => data.trim().length > 0
    },

    city: {
      label: rightPad('City', 12),
      validateValue: data => data.trim().length > 0
    },

    address1: {
      label: rightPad('Address', 12),
      validateValue: data => data.trim().length > 0
    }
  }

  async function render() {
    for (const key in state) {
      if (!Object.hasOwnProperty.call(state, key)) {
        continue
      }
      const piece = state[key]
      if (typeof piece === 'string') {
        console.log(piece)
      } else if (typeof piece === 'object') {
        let result
        try {
          /* eslint-disable no-await-in-loop */
          result = await textInput({
            label: '- ' + piece.label,
            initialValue: piece.initialValue || piece.value,
            placeholder: piece.placeholder,
            mask: piece.mask,
            validateKeypress: piece.validateKeypress,
            validateValue: piece.validateValue,
            autoComplete: piece.autoComplete
          })

          piece.value = result

          if (key === 'cardNumber') {
            let brand = cardBrands[ccValidator.determineCardType(result)]
            piece.brand = brand
            if (brand === 'American Express') {
              state.ccv.placeholder = '#'.repeat(4)
            } else {
              state.ccv.placeholder = '#'.repeat(3)
            }
            brand = chalk.cyan(`[${brand}]`)
            const masked = chalk.gray('#### '.repeat(3)) + result.split(' ')[3]<commit_msg>Made `now cc add` case-unsensitive<commit_after>#!/usr/bin/env node

// Packages
const ansiEscapes = require('ansi-escapes')
const chalk = require('chalk')
const ccValidator = require('credit-card')

// Ours
const textInput = require('../lib/utils/input/text')
const countries = require('../lib/utils/billing/country-list')
const cardBrands = require('../lib/utils/billing/card-brands')
const geocode = require('../lib/utils/billing/geocode')
const success = require('../lib/utils/output/success')
const wait = require('../lib/utils/output/wait')
const { tick } = require('../lib/utils/output/chars')
const rightPad = require('../lib/utils/output/right-pad')

function expDateMiddleware(data) {
  return data
}

module.exports = function({ creditCards, currentTeam, user }) {
  const state = {
    error: undefined,
    cardGroupLabel: `> ${chalk.bold(
      `Enter your card details for ${chalk.bold(
        (currentTeam && currentTeam.slug) || user.username || user.email
      )}`
    )}`,

    name: {
      label: rightPad('Full Name', 12),
      placeholder: '<NAME>',
      validateValue: data => data.trim().length > 0
    },

    cardNumber: {
      label: rightPad('Number', 12),
      mask: 'cc',
      placeholder: '#### #### #### ####',
      validateKeypress: (data, value) => /\d/.test(data) && value.length < 19,
      validateValue: data => {
        data = data.replace(/ /g, '')
        const type = ccValidator.determineCardType(data)
        if (!type) {
          return false
        }
        return ccValidator.isValidCardNumber(data, type)
      }
    },

    ccv: {
      label: rightPad('CCV', 12),
      mask: 'ccv',
      placeholder: '###',
      validateValue: data => {
        const brand = state.cardNumber.brand.toLowerCase()
        return ccValidator.doesCvvMatchType(data, brand)
      }
    },

    expDate: {
      label: rightPad('Exp. Date', 12),
      mask: 'expDate',
      placeholder: 'mm / yyyy',
      middleware: expDateMiddleware,
      validateValue: data => !ccValidator.isExpired(...data.split(' / '))
    },

    addressGroupLabel: `\n> ${chalk.bold('Enter your billing address')}`,

    country: {
      label: rightPad('Country', 12),
      async autoComplete(value) {
        for (const country in countries) {
          if (!Object.hasOwnProperty.call(countries, country)) {
            continue
          }

          if (country.startsWith(value)) {
            return country.substr(value.length)
          }

          const lowercaseCountry = country.toLowerCase()
          const lowercaseValue = value.toLowerCase()

          if (lowercaseCountry.startsWith(lowercaseValue)) {
            return lowercaseCountry.substr(value.length)
          }
        }

        return false
      },
      validateValue: value => {
        for (const country in countries) {
          if (!Object.hasOwnProperty.call(countries, country)) {
            continue
          }

          if (country.toLowerCase() === value.toLowerCase()) {
            return true
          }
        }

        return false
      }
    },

    zipCode: {
      label: rightPad('ZIP', 12),
      validadeKeypress: data => data.trim().length > 0,
      validateValue: data => data.trim().length > 0
    },

    state: {
      label: rightPad('State', 12),
      validateValue: data => data.trim().length > 0
    },

    city: {
      label: rightPad('City', 12),
      validateValue: data => data.trim().length > 0
    },

    address1: {
      label: rightPad('Address', 12),
      validateValue: data => data.trim().length > 0
    }
  }

  async function render() {
    for (const key in state) {
      if (!Object.hasOwnProperty.call(state, key)) {
        continue
      }
      const piece = state[key]
      if (typeof piece === 'string') {
        console.log(piece)
      } else if (typeof piece === 'object') {
        let result
        try {
          /* eslint-disable no-await-in-loop */
          result = await textInput({
            label: '- ' + piece.label,
            initialValue: piece.initialValue || piece.value,
            placeholder: piece.placeholder,
            mask: piece.mask,
            validateKeypress: piece.validateKeypress,
            validateValue: piece.validateValue,
            autoComplete: piece.autoComplete
          })

          piece.value = result

          if (key === 'cardNumber') {
            let brand = cardBrands[ccValidator.determineCardType(result)]
            piece.brand = brand

            if (brand === 'American Express') {
              state.ccv.placeholder = '#'.repeat(4)
            } else {
              state.ccv.placeholder = '#'.repeat(3)
            }

            brand = chalk.cyan(`[${brand}]`)
            const masked = chalk.gray('#### '.repeat(3)) + result.split(' ')[3]
{'fraction_non_alphanumeric': 0.14967485947316214, 'fraction_numerical': 0.006833461919982365, 'mean_word_length': 2.1716183152743795, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '7210911', 'n_tokens_mistral': 2685, 'n_tokens_neox': 2613, 'n_words': 573}