{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/date.ts","../src/time.ts","../src/parser.ts"],"sourcesContent":["import { makeArrayOfMessages, parseMessages } from './parser';\nimport { Attachment, Message, ParseStringOptions } from './types';\n\nconst newlinesRegex = /(?:\\r\\n|\\r|\\n)/;\n\n/**\n * Parses a string containing a WhatsApp chat log.\n *\n * Returns an array of parsed messages.\n *\n * @since 3.2.0\n * @since 4.0.0 Renamed from parseStringSync\n */\nexport function parseString(\n  string: string,\n  options: ParseStringOptions = { parseAttachments: false },\n): Message[] {\n  const lines = string.split(newlinesRegex);\n  return parseMessages(makeArrayOfMessages(lines), options);\n}\n\nexport type { Attachment, Message, ParseStringOptions };\n","/**\n * Checks that the number at a certain index of an array is greater than a\n * certain value.\n */\nfunction indexAboveValue(index: number, value: number) {\n  return (array: number[]): boolean => array[index] > value;\n}\n\n/**\n * Returns `true` for a negative number, `false` otherwise.\n *\n * `0` and `-0` are considered positive.\n */\nfunction isNegative(number: number): boolean {\n  return number < 0;\n}\n\n/**\n * Takes an array of arrays and an index and groups the inner arrays by the\n * value at the index provided.\n * @see `utils.test.ts` for a better understanding of this function.\n */\nfunction groupArrayByValueAtIndex<T extends unknown[]>(\n  array: T[],\n  index: number,\n): T[][] {\n  return Object.values(\n    array.reduce((obj: { [key: string]: T[] }, item) => {\n      /*\n       * Keys that are numbers (even strings containing a number) get sorted\n       * when using `Object.values()`.\n       * Adding a prefix avoids this issue.\n       */\n      const key = `_${item[index]}`;\n\n      if (!obj[key]) obj[key] = [];\n\n      obj[key].push(item);\n\n      return obj;\n    }, {}),\n  );\n}\n\nexport { indexAboveValue, isNegative, groupArrayByValueAtIndex };\n","import { indexAboveValue, isNegative, groupArrayByValueAtIndex } from './utils';\n\n/**\n * Takes an array of numeric dates and tries to understand if the days come\n * before the month or the other way around by checking if numbers go above\n * `12`.\n *\n * Output is `true` if days are first, `false` if they are second, or `null` if\n * it failed to understand the order.\n */\nfunction checkAbove12(numericDates: number[][]): boolean | null {\n  const daysFirst = numericDates.some(indexAboveValue(0, 12));\n\n  if (daysFirst) return true;\n\n  const daysSecond = numericDates.some(indexAboveValue(1, 12));\n\n  if (daysSecond) return false;\n\n  return null;\n}\n\n/**\n * Takes an array of numeric dates and tries to understand if the days come\n * before the month or the other way around by checking if a set of numbers\n * during the same year decrease at some point.\n *\n * If it does it's probably the days since months can only increase in a given\n * year.\n *\n * Output is `true` if days are first, `false` if they are second, or `null` if\n * it failed to understand the order.\n */\nfunction checkDecreasing(numericDates: number[][]): boolean | null {\n  const datesByYear = groupArrayByValueAtIndex(numericDates, 2);\n  const results = datesByYear.map(dates => {\n    const daysFirst = dates.slice(1).some((date, i) => {\n      const [first1] = dates[i];\n      const [first2] = date;\n\n      return isNegative(first2 - first1);\n    });\n\n    if (daysFirst) return true;\n\n    const daysSecond = dates.slice(1).some((date, i) => {\n      const [, second1] = dates[i];\n      const [, second2] = date;\n\n      return isNegative(second2 - second1);\n    });\n\n    if (daysSecond) return false;\n\n    return null;\n  });\n\n  const anyTrue = results.some(value => value === true);\n\n  if (anyTrue) return true;\n\n  const anyFalse = results.some(value => value === false);\n\n  if (anyFalse) return false;\n\n  return null;\n}\n\n/**\n * Takes an array of numeric dates and tries to understand if the days come\n * before the month or the other way around by looking at which number changes\n * more frequently.\n *\n * Output is `true` if days are first, `false` if they are second, or `null` if\n * it failed to understand the order.\n */\nfunction changeFrequencyAnalysis(numericDates: number[][]): boolean | null {\n  const diffs = numericDates\n    .slice(1)\n    .map((date, i) => date.map((num, j) => Math.abs(numericDates[i][j] - num)));\n  const [first, second] = diffs.reduce(\n    (total, diff) => {\n      const [first1, second1] = total;\n      const [first2, second2] = diff;\n\n      return [first1 + first2, second1 + second2];\n    },\n    [0, 0],\n  );\n\n  if (first > second) return true;\n  if (first < second) return false;\n\n  return null;\n}\n\n/**\n * Takes an array of numeric dates and tries to understand if the days come\n * before the month or the other way around by running the dates through various\n * checks.\n *\n * Output is `true` if days are first, `false` if they are second, or `null` if\n * it failed to understand the order.\n */\nfunction daysBeforeMonths(numericDates: number[][]): boolean | null {\n  const firstCheck = checkAbove12(numericDates);\n\n  if (firstCheck !== null) return firstCheck;\n\n  const secondCheck = checkDecreasing(numericDates);\n\n  if (secondCheck !== null) return secondCheck;\n\n  return changeFrequencyAnalysis(numericDates);\n}\n\n/**\n * Takes `year`, `month` and `day` as strings and pads them to `4`, `2`, `2`\n * digits respectively.\n */\nfunction normalizeDate(\n  year: string,\n  month: string,\n  day: string,\n): [string, string, string] {\n  return [\n    // 2 digit years are assumed to be in the 2000-2099 range\n    year.padStart(4, '2000'),\n    month.padStart(2, '0'),\n    day.padStart(2, '0'),\n  ];\n}\n\n/**\n * Pushes the longest number in a date to the end, if there is one. Necessary to\n * ensure the year is the last number.\n */\nfunction orderDateComponents(date: string): [string, string, string] {\n  const regexSplitDate = /[-/.] ?/;\n  const [a, b, c] = date.split(regexSplitDate);\n  const maxLength = Math.max(a.length, b.length, c.length);\n\n  if (c.length === maxLength) return [a, b, c];\n  if (b.length === maxLength) return [a, c, b];\n  return [b, c, a];\n}\n\nexport {\n  checkAbove12,\n  checkDecreasing,\n  changeFrequencyAnalysis,\n  daysBeforeMonths,\n  normalizeDate,\n  orderDateComponents,\n};\n","const regexSplitTime = /[:.]/;\n\n/**\n * Converts time from 12 hour format to 24 hour format.\n *\n * Reference:\n * {@link https://stackoverflow.com/a/40197728/5303634}\n */\nfunction convertTime12to24(time: string, ampm: string): string {\n  // eslint-disable-next-line prefer-const\n  let [hours, minutes, seconds] = time.split(regexSplitTime);\n\n  if (hours === '12') hours = '00';\n  if (ampm === 'PM') hours = String(parseInt(hours, 10) + 12);\n\n  return `${hours}:${minutes}${seconds ? `:${seconds}` : ''}`;\n}\n\n/**\n * Normalizes a time string to have the following format: `hh:mm:ss`.\n */\nfunction normalizeTime(time: string): string {\n  const [hours, minutes, seconds] = time.split(regexSplitTime);\n\n  return `${hours.padStart(2, '0')}:${minutes}:${seconds || '00'}`;\n}\n\n/**\n * Normalizes `am` / `a.m.` / etc. to `AM` (uppercase, no other characters).\n */\nfunction normalizeAMPM(ampm: string): string {\n  return ampm.replace(/[^apm]/gi, '').toUpperCase();\n}\n\nexport { regexSplitTime, convertTime12to24, normalizeTime, normalizeAMPM };\n","import { daysBeforeMonths, normalizeDate, orderDateComponents } from './date';\nimport {\n  regexSplitTime,\n  convertTime12to24,\n  normalizeAMPM,\n  normalizeTime,\n} from './time';\nimport { Attachment, Message, RawMessage, ParseStringOptions } from './types';\n\nconst sharedRegex =\n  /^(?:\\u200E|\\u200F)*\\[?(\\d{1,4}[-/.]\\s?\\d{1,4}[-/.]\\s?\\d{1,4})[,.]?\\s\\D*?(\\d{1,2}[.:]\\d{1,2}(?:[.:]\\d{1,2})?)(?:\\s([ap]\\.?\\s?m\\.?))?\\]?(?:\\s-|:)?\\s/;\nconst authorAndMessageRegex = /(.+?):\\s([^]*)/;\nconst messageRegex = /([^]+)/;\nconst regexParser = new RegExp(\n  sharedRegex.source + authorAndMessageRegex.source,\n  'i',\n);\nconst regexParserSystem = new RegExp(\n  sharedRegex.source + messageRegex.source,\n  'i',\n);\nconst regexAttachment =\n  /^(?:\\u200E|\\u200F)*(?:<.+:(.+)>|([\\w-]+\\.\\w+)\\s[(<].+[)>])/;\n\n/**\n * Takes an array of lines and detects the lines that are part of a previous\n * message (multiline messages) and merges them.\n *\n * It also labels messages without an author as system messages.\n */\nfunction makeArrayOfMessages(lines: string[]): RawMessage[] {\n  return lines.reduce((acc: RawMessage[], line) => {\n    /*\n     * If the line doesn't match the regex it's probably part of the previous\n     * message or a \"WhatsApp event\"\n     */\n    if (!regexParser.test(line)) {\n      /*\n       * If it doesn't match the first regex but still matches the system regex\n       * it should be considered a \"WhatsApp event\" so it gets labeled \"system\"\n       */\n      if (regexParserSystem.test(line)) {\n        acc.push({ system: true, msg: line });\n      }\n\n      // Else it's part of the previous message and it should be concatenated\n      else if (typeof acc[acc.length - 1] !== 'undefined') {\n        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n        const prevMessage = acc.pop()!;\n\n        acc.push({\n          system: prevMessage.system,\n          msg: `${prevMessage.msg}\\n${line}`,\n        });\n      }\n    } else {\n      acc.push({ system: false, msg: line });\n    }\n\n    return acc;\n  }, []);\n}\n\n/**\n * Parses a message extracting the attachment if it's present.\n */\nfunction parseMessageAttachment(message: string): Attachment | null {\n  const attachmentMatch = message.match(regexAttachment);\n\n  if (!attachmentMatch) return null;\n  return {\n    fileName: (attachmentMatch[1] || attachmentMatch[2]).trim(),\n  };\n}\n\n/**\n * Parses and array of raw messages into an array of structured objects.\n */\nfunction parseMessages(\n  messages: RawMessage[],\n  options: ParseStringOptions = {},\n): Message[] {\n  let { daysFirst } = options;\n  const { parseAttachments } = options;\n\n  // Parse messages with regex\n  const parsed = messages.map(obj => {\n    const { system, msg } = obj;\n\n    // If it's a system message another regex should be used to parse it\n    if (system) {\n      const [, date, time, ampm, message] = regexParserSystem.exec(\n        msg,\n      ) as RegExpExecArray;\n\n      return { date, time, ampm: ampm || null, author: null, message };\n    }\n\n    const [, date, time, ampm, author, message] = regexParser.exec(\n      msg,\n    ) as RegExpExecArray;\n\n    return { date, time, ampm: ampm || null, author, message };\n  });\n\n  // Understand date format if not supplied (do days come first?)\n  if (typeof daysFirst !== 'boolean') {\n    const numericDates = Array.from(\n      new Set(parsed.map(({ date }) => date)),\n      date => orderDateComponents(date).map(Number),\n    );\n\n    daysFirst = daysBeforeMonths(numericDates);\n  }\n\n  // Convert date and time in a `Date` object, return the final object\n  return parsed.map(({ date, time, ampm, author, message }) => {\n    let day: string;\n    let month: string;\n    let year: string;\n    const splitDate = orderDateComponents(date);\n\n    if (daysFirst === false) {\n      [month, day, year] = splitDate;\n    } else {\n      [day, month, year] = splitDate;\n    }\n\n    [year, month, day] = normalizeDate(year, month, day);\n\n    const [hours, minutes, seconds] = normalizeTime(\n      ampm ? convertTime12to24(time, normalizeAMPM(ampm)) : time,\n    ).split(regexSplitTime);\n\n    const finalObject: Message = {\n      date: new Date(+year, +month - 1, +day, +hours, +minutes, +seconds),\n      author,\n      message,\n    };\n\n    // Optionally parse attachments\n    if (parseAttachments) {\n      const attachment = parseMessageAttachment(message);\n      if (attachment) finalObject.attachment = attachment;\n    }\n\n    return finalObject;\n  });\n}\n\nexport { makeArrayOfMessages, parseMessages };\n"],"mappings":"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","names":["src_exports","__export","parseString","__toCommonJS","indexAboveValue","index","value","array","isNegative","number","groupArrayByValueAtIndex","obj","item","key","checkAbove12","numericDates","indexAboveValue","checkDecreasing","results","groupArrayByValueAtIndex","dates","date","i","first1","first2","isNegative","second1","second2","value","changeFrequencyAnalysis","diffs","num","j","first","second","total","diff","daysBeforeMonths","firstCheck","secondCheck","normalizeDate","year","month","day","orderDateComponents","regexSplitDate","a","b","c","maxLength","regexSplitTime","convertTime12to24","time","ampm","hours","minutes","seconds","normalizeTime","normalizeAMPM","sharedRegex","authorAndMessageRegex","messageRegex","regexParser","regexParserSystem","regexAttachment","makeArrayOfMessages","lines","acc","line","prevMessage","parseMessageAttachment","message","attachmentMatch","parseMessages","messages","options","daysFirst","parseAttachments","parsed","obj","system","msg","date","time","ampm","author","numericDates","orderDateComponents","daysBeforeMonths","day","month","year","splitDate","normalizeDate","hours","minutes","seconds","normalizeTime","convertTime12to24","normalizeAMPM","regexSplitTime","finalObject","attachment","newlinesRegex","parseString","string","options","lines","parseMessages","makeArrayOfMessages"]}