Class: MonoVM::Whois::Parser::KeyValue

Inherits:
Base
  • Object
show all
Defined in:
lib/monovm/whois/parser/key_value.rb

Overview

Parses the Key: value shape that nearly every port 43 registry speaks.

There is no standard for this format, only a strong convention, so the work is in the disagreements: keys padded with dots to align values, the same field called Creation Date, created, registered on or paid-till, and fields that legitimately repeat (a domain has several nameservers and several EPP statuses). ALIASES is where that variation is absorbed; everything else here is mechanical.

Direct Known Subclasses

IcannRdd

Constant Summary collapse

LINE =

Key: value, tolerating padded keys and values that contain colons.

/\A(?<key>[^:]{1,64}?)[\s._·-]*:[ \t]*(?<value>.*)\z/
ALIASES =

Canonical field name => the key spellings that mean it, most preferred first. Order matters where a record carries two candidates: a gTLD record has both a registry expiry date and the registrar's copy of it, and the registry is authoritative.

{
  domain: ["domain name", "domain", "ascii", "domain-name", "the domain"],
  registry_id: ["registry domain id"],
  registrar: ["registrar", "sponsoring registrar", "registrar name", "registrar organization"],
  registrar_whois_server: ["registrar whois server", "whois server"],
  registrar_url: ["registrar url", "referral url", "registrar web"],
  registrar_iana_id: ["registrar iana id"],
  registrant: [
    "registrant name", "registrant organization", "registrant organisation",
    "registrant", "holder", "holder name", "organisation", "organization", "org"
  ],
  created_on: [
    "creation date", "created", "created on", "created date", "registered on",
    "registration date", "registered", "domain registration date", "record created",
    "activation date"
  ],
  updated_on: [
    "updated date", "last updated", "last update", "changed", "modified",
    "last modified", "record last updated", "update date"
  ],
  expires_on: [
    "registry expiry date", "expiry date", "expiration date", "expires",
    "expires on", "expire date", "paid-till", "renewal date", "record expires",
    "registrar registration expiration date", "valid until", "expiry"
  ],
  dnssec: ["dnssec", "dnssec signed", "signed"]
}.freeze
MULTI =

Fields that may appear many times; every occurrence is kept.

{
  statuses: ["domain status", "status", "state", "eppstatus"],
  nameservers: ["name server", "nameserver", "nserver", "ns", "dns", "name servers"]
}.freeze
CONTACT_ROLES =

Contact blocks, addressed by key prefix: Admin Email:, Tech Name:.

{
  registrant: %w[registrant],
  admin: ["admin", "administrative contact", "admin contact"],
  tech: ["tech", "technical contact", "tech contact"],
  billing: ["billing", "billing contact"]
}.freeze
CONTACT_ATTRIBUTES =
{
  name: "name",
  organization: "organization",
  email: "email",
  phone: "phone",
  country: "country",
  city: "city",
  state: "state/province"
}.freeze

Constants inherited from Base

Base::DATE_FORMATS, Base::PLAUSIBLE_YEARS

Instance Method Summary collapse

Methods inherited from Base

#name, snake_case

Instance Method Details

#applicable?(response) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
# File 'lib/monovm/whois/parser/key_value.rb', line 77

def applicable?(response)
  return false if response.json?

  # LINE is anchored, so it has to be matched a line at a time — testing it
  # against the whole response fails on anything multi-line, which is every
  # real record.
  response.text.each_line.any? { |line| LINE.match?(line.strip) }
end

#parse(response) ⇒ Object



86
87
88
89
90
# File 'lib/monovm/whois/parser/key_value.rb', line 86

def parse(response)
  pairs = extract_pairs(response.text)

  Record.new(**attributes_from(pairs), fields: flatten(pairs), source: name)
end