<commit_before>package immortan.utils

import fr.acinq.eclair._
import immortan.utils.InputParser._
import scala.util.{Failure, Success, Try}
import immortan.{LNParams, RemoteNodeInfo}
import fr.acinq.eclair.payment.PaymentRequest
import scala.util.matching.{Regex, UnanchoredRegex}
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.wire.NodeAddress
import immortan.crypto.Tools.trimmed
import fr.acinq.bitcoin.ScriptElt
import scodec.bits.ByteVector
import immortan.utils.uri.Uri


object InputParser {
  var value: Any = new String
  case object DoNotEraseRecordedValue
  type Checker = PartialFunction[Any, Any]

  def checkAndMaybeErase(fun: Checker): Unit = fun(value) match {
    case DoNotEraseRecordedValue => // Do nothing, value is retained
    case _ => value = null // Erase recorded value
  }

  private[this] val prefixes = PaymentRequest.prefixes.values mkString "|"

  private[this] val lnUrl = "(?im).*?(lnurl)([0-9]+[a-z0-9]+)".r.unanchored

  private[this] val shortNodeLink = "([a-fA-F0-9]{66})@([a-zA-Z0-9:.\\-_]+)".r.unanchored

  val nodeLink: UnanchoredRegex = "([a-fA-F0-9]{66})@([a-zA-Z0-9:.\\-_]+):([0-9]+)".r.unanchored

  val lnPayReq: UnanchoredRegex = s"(?im).*?($prefixes)([0-9]{1,}[a-z0-9]+){1}".r.unanchored

  val identifier: UnanchoredRegex = "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$".r.unanchored

  val lightning: String = "lightning:"

  val bitcoin: String = "bitcoin:"

  def recordValue(raw: String): Unit = value = parse(raw)

  def parse(rawInput: String): Any = rawInput take 2880 match {
    case lnUrl(prefix, data) => LNUrl.fromBech32(s"$prefix$data")
    case nodeLink(key, host, port) => RemoteNodeInfo(PublicKey.fromBin(ByteVector fromValidHex key), NodeAddress.fromParts(host, port.toInt), host)
    case shortNodeLink(key, host) => RemoteNodeInfo(PublicKey.fromBin(ByteVector fromValidHex key), NodeAddress.fromParts(host, port = 9735), host)
    case lnPayReq(prefix, data) => PaymentRequestExt.fromRaw(s"$prefix$data")

    case _ =>
      val isLightning = rawInput.toLowerCase.startsWith(lightning)
      val withoutPrefix = PaymentRequestExt.removePrefix(rawInput).trim
      val isLightningAddress = identifier.findFirstMatchIn(withoutPrefix)
      if (isLightningAddress.isDefined) LNUrl.fromIdentifier(withoutPrefix)
      else if (isLightning) PaymentRequestExt.fromUri(withoutPrefix.toLowerCase)
      else BitcoinUri.fromRaw(s"$bitcoin$withoutPrefix")
  }
}

object PaymentRequestExt {
  def removePrefix(raw: String): String = raw.split(':').toList match {
    case prefix :: content if lightning.startsWith(prefix.toLowerCase) => content.mkString.replace("//", "")
    case prefix :: content if bitcoin.startsWith(prefix.toLowerCase) => content.mkString.replace("//", "")
    case _ => raw
  }

  def fromUri(invoiceWithoutPrefix: String): PaymentRequestExt = {<commit_msg>Fix identifier regex<commit_after>package immortan.utils

import fr.acinq.eclair._
import immortan.utils.InputParser._
import scala.util.{Failure, Success, Try}
import immortan.{LNParams, RemoteNodeInfo}
import fr.acinq.eclair.payment.PaymentRequest
import scala.util.matching.{Regex, UnanchoredRegex}
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.wire.NodeAddress
import immortan.crypto.Tools.trimmed
import fr.acinq.bitcoin.ScriptElt
import scodec.bits.ByteVector
import immortan.utils.uri.Uri


object InputParser {
  var value: Any = new String
  case object DoNotEraseRecordedValue
  type Checker = PartialFunction[Any, Any]

  def checkAndMaybeErase(fun: Checker): Unit = fun(value) match {
    case DoNotEraseRecordedValue => // Do nothing, value is retained
    case _ => value = null // Erase recorded value
  }

  private[this] val prefixes = PaymentRequest.prefixes.values mkString "|"

  private[this] val lnUrl = "(?im).*?(lnurl)([0-9]+[a-z0-9]+)".r.unanchored

  private[this] val shortNodeLink = "([a-fA-F0-9]{66})@([a-zA-Z0-9:.\\-_]+)".r.unanchored

  val nodeLink: UnanchoredRegex = "([a-fA-F0-9]{66})@([a-zA-Z0-9:.\\-_]+):([0-9]+)".r.unanchored

  val lnPayReq: UnanchoredRegex = s"(?im).*?($prefixes)([0-9]{1,}[a-z0-9]+){1}".r.unanchored

  val identifier: UnanchoredRegex = "^[a-zA-Z0-9\\-_.]+@[a-zA-Z0-9](?:[a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*$".r.unanchored

  val lightning: String = "lightning:"

  val bitcoin: String = "bitcoin:"

  def recordValue(raw: String): Unit = value = parse(raw)

  def parse(rawInput: String): Any = rawInput take 2880 match {
    case lnUrl(prefix, data) => LNUrl.fromBech32(s"$prefix$data")
    case nodeLink(key, host, port) => RemoteNodeInfo(PublicKey.fromBin(ByteVector fromValidHex key), NodeAddress.fromParts(host, port.toInt), host)
    case shortNodeLink(key, host) => RemoteNodeInfo(PublicKey.fromBin(ByteVector fromValidHex key), NodeAddress.fromParts(host, port = 9735), host)
    case lnPayReq(prefix, data) => PaymentRequestExt.fromRaw(s"$prefix$data")

    case _ =>
      val isLightning = rawInput.toLowerCase.startsWith(lightning)
      val withoutPrefix = PaymentRequestExt.removePrefix(rawInput).trim
      val isLightningAddress = identifier.findFirstMatchIn(withoutPrefix)
      if (isLightningAddress.isDefined) LNUrl.fromIdentifier(withoutPrefix)
      else if (isLightning) PaymentRequestExt.fromUri(withoutPrefix.toLowerCase)
      else BitcoinUri.fromRaw(s"$bitcoin$withoutPrefix")
  }
}

object PaymentRequestExt {
  def removePrefix(raw: String): String = raw.split(':').toList match {
    case prefix :: content if lightning.startsWith(prefix.toLowerCase) => content.mkString.replace("//", "")
    case prefix :: content if bitcoin.startsWith(prefix.toLowerCase) => content.mkString.replace("//", "")
    case _ => raw
  }

  def fromUri(invoiceWithoutPrefix: String): PaymentRequestExt = {
{'fraction_non_alphanumeric': 0.1573301549463647, 'fraction_numerical': 0.018389238889834836, 'mean_word_length': 4.775811209439528, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, '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': '4733811', 'n_tokens_mistral': 2144, 'n_tokens_neox': 2059, 'n_words': 368}