[
  {
    "path": ".github/workflows/python-package.yml",
    "content": "# This workflow will install Python dependencies, run tests and lint with a variety of Python versions\n# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python\n\nname: Python package\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    types:\n      - opened\n      - reopened\n      - edited\n      - synchronize\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version: [\"3.9\", \"3.10\", \"3.11\", \"3.12\", \"3.13\"]\n\n    steps:\n    - uses: actions/checkout@v4\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v5\n      with:\n        python-version: ${{ matrix.python-version }}\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        python -m pip install flake8 pytest\n        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n    - name: Lint with flake8\n      run: |\n        # stop the build if there are Python syntax errors or undefined names\n        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics\n        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide\n        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\n    - name: Test with pytest\n      run: |\n        python -m pytest\n"
  },
  {
    "path": ".gitignore",
    "content": "*.pyc\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Permission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include whois/data/public_suffix_list.dat\ninclude LICENSE.txt README.md\n"
  },
  {
    "path": "README.md",
    "content": "# Goal\n\n- Create a simple importable Python module which will produce parsed\n  WHOIS data for a given domain.\n- Able to extract data for all the popular TLDs (com, org, net, ...)\n- Query a WHOIS server directly instead of going through an\n  intermediate web service like many others do.\n\n# Example\n\n```python\n>>> import whois\n>>> w = whois.whois('example.com')\n>>> w.expiration_date  # dates converted to datetime object\ndatetime.datetime(2022, 8, 13, 4, 0, tzinfo=tzoffset('UTC', 0))\n>>> w.text  # the content downloaded from whois server\nu'\\nDomain Name: EXAMPLE.COM\nRegistry Domain ID: 2336799_DOMAIN_COM-VRSN\n...'\n\n>>> print(w)  # print values of all found attributes\n{\n  \"creation_date\": \"1995-08-14 04:00:00+00:00\",\n  \"expiration_date\": \"2022-08-13 04:00:00+00:00\",\n  \"updated_date\": \"2021-08-14 07:01:44+00:00\",\n  \"domain_name\": \"EXAMPLE.COM\",\n  \"name_servers\": [\n      \"A.IANA-SERVERS.NET\",\n      \"B.IANA-SERVERS.NET\"\n  ],\n  ...\n```\n\n# Install\n\nInstall from pypi:\n\n```bash\npip install python-whois\n```\n\nOr checkout latest version from repository:\n\n```bash\ngit clone git@github.com:richardpenman/whois.git\npip install -r requirements.txt\n```\n\nRun test cases:\n\n```bash\npython -m pytest\n```\n\n# Using a proxy.\n\nSet your environment SOCKS variable\n```bash\nexport SOCKS=\"username:password@proxy_address:port\"\n```\n\n# Problems?\n\nPull requests are welcome!\n\nThanks to the many who have sent patches for additional TLDs. If you want to add or fix a TLD it's quite straightforward.\nSee example domains in [whois/parser.py](https://github.com/richardpenman/whois/blob/master/whois/parser.py)\n\nBasically each TLD has a similar format to the following:\n\n```python\nclass WhoisOrg(WhoisEntry):\n  \"\"\"Whois parser for .org domains\n  \"\"\"\n  regex = {\n    'domain_name':      'Domain Name: *(.+)',\n    'registrar':        'Registrar: *(.+)',\n    'whois_server':     'Whois Server: *(.+)',\n    ...\n  }\n\n  def __init__(self, domain, text):\n    if text.strip() == 'NOT FOUND':\n      raise WhoisDomainNotFoundError(text)\n    else:\n      WhoisEntry.__init__(self, domain, text, self.regex)\n```\n"
  },
  {
    "path": "requirements.txt",
    "content": "python-dateutil==2.9.0.post0\n"
  },
  {
    "path": "setup.py",
    "content": "import os\nimport setuptools\n\n\ndef read(filename):\n    return open(os.path.join(os.path.dirname(__file__), filename)).read()\n\n\nsetuptools.setup(\n    name=\"python-whois\",\n    version=\"0.9.6\",\n    description=\"Whois querying and parsing of domain registration information.\",\n    long_description=read(\"README.md\"),\n    long_description_content_type=\"text/markdown\",\n    classifiers=[\n        \"Environment :: Web Environment\",\n        \"Intended Audience :: Developers\",\n        \"License :: OSI Approved :: MIT License\",\n        \"Operating System :: OS Independent\",\n        \"Programming Language :: Python\",\n        \"Topic :: Internet :: WWW/HTTP\",\n        \"Programming Language :: Python :: 3\",\n    ],\n    keywords=\"whois, python\",\n    author=\"Richard Penman\",\n    author_email=\"richard.penman@gmail.com\",\n    url=\"https://github.com/richardpenman/whois\",\n    license=\"MIT\",\n    packages=[\"whois\"],\n    package_dir={\"whois\": \"whois\"},\n    install_requires=[\"python-dateutil\"],\n    test_suite=\"nose.collector\",\n    tests_require=[\"nose\", \"simplejson\"],\n    include_package_data=True,\n    zip_safe=False,\n)\n"
  },
  {
    "path": "test/__init__.py",
    "content": ""
  },
  {
    "path": "test/samples/expected/abc.rs",
    "content": "{\"domain_name\": \"abc.rs\", \"expiration_date\": \"2026-03-26 16:18:03+00:00\", \"updated_date\": \"2025-02-11 08:24:15+00:00\", \"registrar\": \"Mainstream Public Cloud Services d.o.o.\", \"registrar_url\": null, \"creation_date\": \"2008-03-26 16:18:03+00:00\", \"status\": \"Active https://www.rnids.rs/en/domain-name-status-codes#Active\"}\n"
  },
  {
    "path": "test/samples/expected/abc.xyz",
    "content": "{\"domain_name\": \"ABC.XYZ\", \"registry_domain_id\": \"D2192285-CNIC\", \"whois_server\": \"D2192285-CNIC\", \"registrar_url\": null, \"updated_date\": \"2025-03-10 15:22:23+00:00\", \"creation_date\": \"2014-03-20 12:59:17+00:00\", \"expiration_date\": \"2026-03-20 23:59:59+00:00\", \"registrar\": \"MarkMonitor, Inc (TLDs)\", \"regisrar_id\": \"292\", \"status\": [\"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\", \"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\"], \"name_servers\": [\"NS2.GOOGLE.COM\", \"NS4.GOOGLE.COM\", \"NS3.GOOGLE.COM\", \"NS1.GOOGLE.COM\"], \"dnssec\": \"unsigned\", \"registrar_email\": \"registryescalations@markmonitor.com\", \"registrar_phone\": \"+1.2083895740\"}\n"
  },
  {
    "path": "test/samples/expected/about.us",
    "content": "{\"domain_name\": \"about.us\", \"expiration_date\": \"2018-04-17 23:59:59+00:00\", \"updated_date\": \"2017-06-02 01:30:53+00:00\", \"registrar\": \"Neustar, Inc.\", \"registrar_url\": \"www.neustarregistry.biz\", \"creation_date\": \"2002-04-18 15:16:22+00:00\", \"status\": [\"serverTransferProhibited https://icann.org/epp#serverTransferProhibited\", \"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/abv.bg",
    "content": "{\"domain_name\": \"abv.bg\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": \"Registered\"}"
  },
  {
    "path": "test/samples/expected/afip.gob.ar",
    "content": "{\"domain_name\": \"afip.gob.ar\", \"expiration_date\": \"2019-05-26 00:00:00+00:00\", \"updated_date\": [\"2018-05-19 12:18:44.329522+00:00\", \"2019-03-21 20:38:40.827111+00:00\"], \"registrar\": \"nicar\", \"registrar_url\": null, \"creation_date\": \"1997-05-26 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/allegro.pl",
    "content": "{\"domain_name\": \"allegro.pl\", \"expiration_date\": \"2018-10-26 15:00:00+00:00\", \"updated_date\": [\"2017-10-17 07:01:25+00:00\", \"2017-03-27 00:00:00+00:00\"], \"registrar\": \"Corporation Service Company\", \"registrar_url\": null, \"creation_date\": \"1999-10-27 13:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/amazon.co.uk",
    "content": "{\"domain_name\": \"amazon.co.uk\", \"expiration_date\": \"2020-12-05 00:00:00+00:00\", \"updated_date\": \"2013-10-23 00:00:00+00:00\", \"registrar\": \"Amazon.com, Inc. t/a Amazon.com, Inc. [Tag = AMAZON-COM]\", \"registrar_url\": \"http://www.amazon.com\", \"creation_date\": \"1996-08-01 00:00:00+00:00\", \"status\": \"Registered until expiry date.\"}\n"
  },
  {
    "path": "test/samples/expected/app.nl",
    "content": "{        \n    \"domain_name\": \"app.nl\",\n    \"expiration_date\": null,\n    \"updated_date\": \"2025-09-12 00:00:00+00:00\",\n    \"creation_date\": \"1998-02-20 00:00:00+00:00\",\n    \"status\": \"active\",\n    \"registrar\": \"Hosting Secure\",\n    \"registrar_address\": \"Weesperstraat 61\",\n    \"registrar_postal_code\": \"1018VN\",\n    \"registrar_city\": \"Amsterdam\",\n    \"registrar_country\": \"Netherlands\",\n    \"reseller\": \"Hoasted\",\n    \"reseller_address\": \"Weesperstraat 61\",\n    \"reseller_postal_code\": \"3512AB\",\n    \"reseller_city\": \"Amsterdam\",\n    \"reseller_country\": \"Netherlands\",\n    \"abuse_phone\": \"+31.0202018165\",\n    \"abuse_email\": \"abuse@hostingsecure.com\",\n    \"dnssec\": \"yes\",\n    \"name_servers\": [\n        \"ns1.hoasted.nl\",\n        \"ns2.hoasted.eu\",\n        \"ns3.hoasted.com\"\n    ]\n}"
  },
  {
    "path": "test/samples/expected/brainly.lat",
    "content": "{\"domain_name\": \"brainly.lat\", \"expiration_date\": \"2019-07-31 15:59:27+00:00\", \"updated_date\": \"2018-07-22 09:01:05+00:00\", \"registrar\": \"Instra Corporation Pty Ltd.\", \"registrar_url\": \"http://www.instra.com/\", \"creation_date\": \"2015-07-31 15:59:27+00:00\", \"status\": \"ok http://www.icann.org/epp#OK\"}\n"
  },
  {
    "path": "test/samples/expected/cbc.ca",
    "content": "{\"domain_name\": \"cbc.ca\", \"expiration_date\": \"2019-11-24 05:00:00+00:00\", \"updated_date\": \"2018-10-26 02:15:16+00:00\", \"registrar\": \"Authentic Web Inc.\", \"registrar_url\": \"authenticweb.com\", \"creation_date\": \"2000-10-16 13:56:05+00:00\", \"status\": [\"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\", \"serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\", \"serverTransferProhibited https://icann.org/epp#serverTransferProhibited\", \"serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/cyberciti.biz",
    "content": "{\"domain_name\": \"CYBERCITI.BIZ\", \"expiration_date\": \"2024-06-30 23:59:59+00:00\", \"updated_date\": \"2018-07-11 05:55:25+00:00\", \"registrar\": \"GoDaddy.com, LLC\", \"registrar_url\": \"http://www.godaddy.com\", \"creation_date\": \"2002-07-01 09:31:21+00:00\", \"status\": [\"clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited http://www.icann.org/epp#clientUpdateProhibited\", \"clientRenewProhibited http://www.icann.org/epp#clientRenewProhibited\", \"clientDeleteProhibited http://www.icann.org/epp#clientDeleteProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/davidwalsh.name",
    "content": "{\"domain_name\": \"DAVIDWALSH.NAME\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\"}"
  },
  {
    "path": "test/samples/expected/digg.com",
    "content": "{\"domain_name\": \"DIGG.COM\", \"expiration_date\": \"2010-02-20 00:00:00+00:00\", \"updated_date\": \"2007-03-13 00:00:00+00:00\", \"registrar\": \"GODADDY.COM, INC.\", \"registrar_url\": null, \"creation_date\": \"2000-02-20 00:00:00+00:00\", \"status\": [\"clientDeleteProhibited\", \"clientRenewProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/druid.fi",
    "content": "{\"domain_name\": \"druid.fi\", \"expiration_date\": \"2022-07-17 00:00:00+00:00\", \"updated_date\": \"2019-03-19 00:00:00+00:00\", \"registrar\": \"CSL Computer Service Langenbach GmbH (d/b/a joker.com)\", \"registrar_url\": null, \"creation_date\": \"2012-07-18 00:00:00+00:00\", \"status\": \"Registered\"}\n"
  },
  {
    "path": "test/samples/expected/drupalcamp.by",
    "content": "{\"domain_name\": \"drupalcamp.by\", \"expiration_date\": \"2020-07-25 00:00:00+00:00\", \"updated_date\": null, \"registrar\": \"Active Technologies LLC\", \"registrar_url\": null, \"creation_date\": \"2018-07-25 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/eurid.eu",
    "content": "{\n    \"domain_name\": \"eurid.eu\",\n    \"script\": \"LATIN\",\n    \"reseller_org\": null,\n    \"reseller_lang\": null,\n    \"reseller_email\": null,\n    \"tech_org\": \"EURid vzw\",\n    \"tech_lang\": \"en\",\n    \"tech_email\": \"tech@eurid.eu\",\n    \"registrar\": \"EURid vzw\",\n    \"registrar_url\": \"https://www.eurid.eu\",\n    \"name_servers\": [\n        \"ns3.eurid.eu (185.36.4.253)\",\n        \"ns3.eurid.eu (2001:67c:9c:3937::253)\",\n        \"nsx.eurid.eu (185.151.141.1)\",\n        \"nsx.eurid.eu (2a02:568:fe00::6575)\",\n        \"ns1.eurid.eu (2001:67c:9c:3937::252)\",\n        \"ns1.eurid.eu (185.36.4.252)\",\n        \"ns2.eurid.eu (2001:67c:40:3937::252)\",\n        \"ns2.eurid.eu (185.36.6.252)\",\n        \"ns4.eurid.eu (2001:67c:40:3937::253)\",\n        \"ns4.eurid.eu (185.36.6.253)\",\n        \"nsp.netnod.se\"\n    ],\n    \"dnssec_flags\": \"KSK\",\n    \"dnssec_protocol\": \"3\",\n    \"dnssec_algorithm\": \"RSA_SHA256\",\n    \"dnssec_pubkey\": \"AwEAAcOQldGtC33GLx8s335UscKMPlWjDXCqbhR2QyAYcfS4CZS6YHg3A1Zz/K3VurTZF68aSaRkNupZuEgt4jozE3v4+t+2qOfiATvoOCrf74hWduBPwk9Go0z7FVlDkok1/qMQmqOtih8TFP85b+w6F/uyLMZS1JowMDUzRurmHJVoT4lW9+OCdrhuQFK9vU24Y8BmacoRy6mWBCFlysizlOIodwmquOf5A+3Nz0B3TLCK4fIYJYVxCUVlpRJ7uaBS+GLD7afuxkEesReYHgPWZFSDMbXk9Ugh+qUi8tEKKFls9TM3lK9BPBcciXUhI1bRJSHftqcNpMmLqg/79SwoWGc=\"\n}"
  },
  {
    "path": "test/samples/expected/google.ai",
    "content": "{\"domain_name\": \"google.ai\", \"expiration_date\": \"2025-09-25 05:37:20+00:00\", \"updated_date\": \"2025-01-23 22:17:03+00:00\", \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": null, \"creation_date\": \"2017-12-16 05:37:20+00:00\", \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.at",
    "content": "{\"domain_name\": \"google.at\", \"expiration_date\": null, \"updated_date\": [\"2011-04-26 17:57:27+00:00\", \"2011-01-11 00:07:31+00:00\", \"2005-06-17 21:36:20+00:00\", \"2011-01-11 00:08:30+00:00\"], \"registrar\": \"MarkMonitor Inc. ( https://nic.at/registrar/434 )\", \"registrar_url\": null, \"creation_date\": null, \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.cl",
    "content": "{\"domain_name\": \"google.cl\", \"expiration_date\": \"2019-11-20 14:48:02+00:00\", \"updated_date\": null, \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": \"https://markmonitor.com/\", \"creation_date\": \"2002-10-22 17:48:23+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.co.cr",
    "content": "{\"domain_name\": \"google.co.cr\", \"expiration_date\": \"2020-04-17 00:00:00+00:00\", \"updated_date\": [\"2017-02-28 06:39:42+00:00\", \"2019-03-28 03:49:37+00:00\", \"2016-03-30 10:37:14+00:00\"], \"registrar\": \"NIC-REG1\", \"registrar_url\": null, \"creation_date\": \"2002-04-18 18:00:00+00:00\", \"status\": [\"Deletion forbidden\", \"Sponsoring registrar change forbidden\", \"Update forbidden\", \"Administratively blocked\", \"Registrant change forbidden\"]}\n"
  },
  {
    "path": "test/samples/expected/google.co.id",
    "content": "{\"domain_name\": \"GOOGLE.CO.ID\", \"expiration_date\": \"2026-09-01 23:59:59+00:00\", \"updated_date\": \"2025-08-05 05:00:20+00:00\", \"registrar\": \"PT Digital Registra Indonesia\", \"registrar_url\": \"www.digitalregistra.co.id\", \"creation_date\": \"2004-12-18 13:33:21+00:00\", \"status\": [\"clientDeleteProhibited\", \"clientRenewProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\", \"serverDeleteProhibited\", \"serverRenewProhibited\", \"serverTransferProhibited\", \"serverUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.co.il",
    "content": "{\"domain_name\": \"google.co.il\", \"expiration_date\": \"2026-06-05 00:00:00+00:00\", \"updated_date\": null, \"registrar\": \"Domain The Net Technologies Ltd\", \"registrar_url\": null, \"creation_date\": \"1999-06-05 00:00:00+00:00\", \"status\": \"Transfer Locked\"}"
  },
  {
    "path": "test/samples/expected/google.co.ve",
    "content": "{\"domain_name\": \"google.co.ve\", \"expiration_date\": \"2018-03-06 00:00:00+00:00\", \"updated_date\": \"2005-11-17 20:35:01+00:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2003-03-06 00:00:00+00:00\", \"status\": \"ACTIVO\"}\n"
  },
  {
    "path": "test/samples/expected/google.com",
    "content": "{\"domain_name\": \"GOOGLE.COM\", \"expiration_date\": \"2011-09-14 00:00:00+00:00\", \"updated_date\": \"2006-04-10 00:00:00+00:00\", \"registrar\": \"MARKMONITOR INC.\", \"registrar_url\": null, \"creation_date\": \"1997-09-15 00:00:00+00:00\", \"status\": [\"clientDeleteProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.com.br",
    "content": "{\"domain_name\": \"google.com.br\", \"expiration_date\": \"2020-05-18 00:00:00+00:00\", \"updated_date\": [\"2019-04-17 00:00:00+00:00\", \"2018-03-24 00:00:00+00:00\", \"2018-10-11 00:00:00+00:00\"], \"registrar\": null, \"registrar_url\": null, \"creation_date\": [\"1999-05-18 00:00:00+00:00\", \"2010-05-20 00:00:00+00:00\", \"2002-06-19 00:00:00+00:00\"], \"status\": \"published\"}\n"
  },
  {
    "path": "test/samples/expected/google.com.pe",
    "content": "{\"domain_name\": \"google.com.pe\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": null, \"creation_date\": null, \"status\": [\"clientTransferProhibited\", \"clientDeleteProhibited\", \"clientUpdateProhibited\"]}"
  },
  {
    "path": "test/samples/expected/google.com.sa",
    "content": "{\"domain_name\": \"google.com.sa\", \"expiration_date\": null, \"updated_date\": \"2019-02-06 00:00:00+00:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2004-01-11 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.com.sg",
    "content": "{\"domain_name\": \"google.com.sg\", \"expiration_date\": \"2025-07-04 16:00:00+00:00\", \"updated_date\": \"2024-06-03 09:54:56+00:00\", \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": null, \"creation_date\": \"2002-07-05 09:42:32+00:00\", \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.com.tr",
    "content": "{\"domain_name\": \"google.com.tr\", \"expiration_date\": \"2019-08-22 00:00:00+00:00\", \"updated_date\": null, \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2001-08-23 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.com.tw",
    "content": "{\"domain_name\": \"google.com.tw\", \"expiration_date\": \"2019-11-09 00:00:00+00:00\", \"updated_date\": null, \"registrar\": \"Markmonitor, Inc.\", \"registrar_url\": \"http://www.markmonitor.com/\", \"creation_date\": \"2000-08-29 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.com.ua",
    "content": "{\"domain_name\": \"google.com.ua\", \"expiration_date\": \"2019-12-04 00:00:00+02:00\", \"updated_date\": \"2018-11-02 11:29:08+02:00\", \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": \"http://markmonitor.com\", \"creation_date\": [\"2002-12-04 00:00:00+02:00\", \"2017-07-28 23:53:31+03:00\"], \"status\": [\"clientDeleteProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\", \"ok\", \"linked\"]}\n"
  },
  {
    "path": "test/samples/expected/google.de",
    "content": "{\"domain_name\": \"google.de\", \"expiration_date\": null, \"updated_date\": \"2018-03-12 21:44:25+01:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": \"connect\"}\n"
  },
  {
    "path": "test/samples/expected/google.do",
    "content": "{\"domain_name\": \"google.do\", \"expiration_date\": \"2020-03-08 04:00:00+00:00\", \"updated_date\": \"2019-02-07 17:54:31.560000+00:00\", \"registrar\": \"Registrar NIC .DO (midominio.do)\", \"registrar_url\": null, \"creation_date\": \"2010-03-08 04:00:00+00:00\", \"status\": \"ok https://icann.org/epp#ok\"}\n"
  },
  {
    "path": "test/samples/expected/google.fr",
    "content": "{\"domain_name\": \"google.fr\", \"expiration_date\": \"2026-12-30 17:16:48+00:00\", \"updated_date\": \"2025-12-03 10:12:00.351952+00:00\", \"registrar\": \"MARKMONITOR Inc.\", \"registrar_url\": null, \"creation_date\": \"2000-07-26 22:00:00+00:00\", \"status\": [\"ACTIVE\", \"serverUpdateProhibited\", \"serverTransferProhibited\", \"serverDeleteProhibited\", \"serverRecoverProhibited\", \"associated\", \"not identified\", \"ok\"]}"
  },
  {
    "path": "test/samples/expected/google.hn",
    "content": "{\"domain_name\": \"google.hn\", \"expiration_date\": \"2020-03-07 05:00:00+00:00\", \"updated_date\": \"2019-02-03 10:43:28.837000+00:00\", \"registrar\": \"MarkMonitor\", \"registrar_url\": \"http://www.markmonitor.com\", \"creation_date\": \"2003-03-07 05:00:00+00:00\", \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.hu",
    "content": "{\"domain_name\": \"google.hu\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2000-03-03 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.ie",
    "content": "{\"domain_name\": \"google.ie\", \"expiration_date\": \"2022-03-21 14:13:27+00:00\", \"updated_date\": null, \"registrar\": \"Markmonitor Inc\", \"registrar_url\": null, \"creation_date\": \"2002-03-21 00:00:00+00:00\", \"status\": [\"serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\", \"serverTransferProhibited https://icann.org/epp#serverTransferProhibited\", \"serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/google.it",
    "content": "{\"domain_name\": \"google.it\", \"expiration_date\": \"2019-04-21 00:00:00+00:00\", \"updated_date\": \"2018-05-07 00:54:15+00:00\", \"registrar\": \"MarkMonitor International Limited\", \"registrar_url\": null, \"creation_date\": \"1999-12-10 00:00:00+00:00\", \"status\": \"ok\"}\n"
  },
  {
    "path": "test/samples/expected/google.kg",
    "content": "{\"domain_name\": \"GOOGLE.KG\", \"expiration_date\": \"2026-03-28 23:59:00+00:00\", \"updated_date\": \"2025-03-05 00:13:49+00:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2004-02-10 09:42:42+00:00\", \"status\": null}"
  },
  {
    "path": "test/samples/expected/google.lu",
    "content": "{\"domain_name\": \"google.lu\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": \"Markmonitor\", \"registrar_url\": null, \"creation_date\": null, \"status\": \"ACTIVE\"}"
  },
  {
    "path": "test/samples/expected/google.lv",
    "content": "{\"domain_name\": \"google.lv\", \"expiration_date\": null, \"updated_date\": \"2024-09-03 17:12:28.647770+00:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.mx",
    "content": "{\"domain_name\": \"google.mx\", \"expiration_date\": \"2020-05-11 00:00:00+00:00\", \"updated_date\": \"2019-04-12 00:00:00+00:00\", \"registrar\": \"MarkMonitor\", \"registrar_url\": null, \"creation_date\": \"2009-05-12 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/google.ro",
    "content": "{\"domain_name\": \"google.ro\", \"expiration_date\": \"2019-09-17 00:00:00+00:00\", \"updated_date\": null, \"registrar\": \"MarkMonitor Inc.\", \"registrar_url\": null, \"creation_date\": \"2000-07-17 00:00:00+00:00\", \"status\": \"UpdateProhibited\"}\n"
  },
  {
    "path": "test/samples/expected/google.sk",
    "content": "{\"domain_name\": \"google.sk\", \"expiration_date\": \"2019-07-24 00:00:00+00:00\", \"updated_date\": \"2018-07-03 00:00:00+00:00\", \"registrar\": \"FAJNOR IP s. r. o.\", \"registrar_url\": null, \"creation_date\": \"2003-07-24 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/imdb.com",
    "content": "{\"domain_name\": \"IMDB.COM\", \"expiration_date\": \"2016-01-04 00:00:00+00:00\", \"updated_date\": \"2008-03-28 00:00:00+00:00\", \"registrar\": \"NETWORK SOLUTIONS, LLC.\", \"registrar_url\": null, \"creation_date\": \"1996-01-05 00:00:00+00:00\", \"status\": \"clientTransferProhibited\"}\n"
  },
  {
    "path": "test/samples/expected/liechtenstein.li",
    "content": "{\"domain_name\": \"liechtenstein.li\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": \"switchplus AG\", \"registrar_url\": null, \"creation_date\": \"1996-02-08 00:00:00+00:00\", \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/microsoft.com",
    "content": "{\"domain_name\": \"MICROSOFT.COM\", \"expiration_date\": \"2014-05-03 00:00:00+00:00\", \"updated_date\": \"2006-10-10 00:00:00+00:00\", \"registrar\": \"CRONON AG BERLIN, NIEDERLASSUNG REGENSBURG\", \"registrar_url\": null, \"creation_date\": \"1991-05-02 00:00:00+00:00\", \"status\": [\"clientDeleteProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/nic.live",
    "content": "{\"domain_name\": \"nic.live\", \"expiration_date\": \"2025-04-27 22:04:24+00:00\", \"updated_date\": \"2024-06-11 22:04:34+00:00\", \"registrar\": \"Registry Operator acts as Registrar (9999)\", \"registrar_url\": \"https://identity.digital\", \"creation_date\": \"2015-04-27 22:04:24+00:00\", \"status\": [\"ACTIVE\", \"serverTransferProhibited https://icann.org/epp#serverTransferProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/nyan.cat",
    "content": "{\"domain_name\": \"nyan.cat\", \"expiration_date\": \"2018-04-13 19:52:17.635000+00:00\", \"updated_date\": \"2017-07-07 17:24:23.746000+00:00\", \"registrar\": \"GANDI SAS\", \"registrar_url\": \"https://www.gandi.net/\", \"creation_date\": \"2011-04-13 19:52:17.635000+00:00\", \"status\": \"ok https://icann.org/epp#ok\"}\n"
  },
  {
    "path": "test/samples/expected/reddit.com",
    "content": "{\"domain_name\": \"REDDIT.COM\", \"expiration_date\": \"2009-04-29 00:00:00+00:00\", \"updated_date\": \"2008-06-04 00:00:00+00:00\", \"registrar\": \"DOMAINBANK\", \"registrar_url\": null, \"creation_date\": \"2005-04-29 00:00:00+00:00\", \"status\": [\"clientDeleteProhibited\", \"clientTransferProhibited\", \"clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/research.google",
    "content": "{\"domain_name\": \"research.google\", \"registrar\": \"MarkMonitor Inc.\", \"whois_server\": \"whois.nic.google\", \"referral_url\": None, \"updated_date\": datetime.datetime(2021, 4, 5, 9, 28, 32), \"creation_date\": datetime.datetime(2019, 5, 2, 17, 16, 59), \"expiration_date\": datetime.datetime(2022, 5, 2, 17, 16, 59), \"name_servers\": [\"ns1.zdns.google\", \"ns2.zdns.google\", \"ns3.zdns.google\", \"ns4.zdns.google\"], \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"], \"emails\": \"abusecomplaints@markmonitor.com\", \"dnssec\": \"signedDelegation\", \"name\": \"REDACTED FOR PRIVACY\", \"org\": \"Charleston Road Registry, Inc.\", \"address\": \"REDACTED FOR PRIVACY\", \"city\": \"REDACTED FOR PRIVACY\", \"state\": \"CA\", \"zipcode\": \"REDACTED FOR PRIVACY\", \"country\": \"US\"}\n"
  },
  {
    "path": "test/samples/expected/sapo.pt",
    "content": "{\"domain_name\": \"sapo.pt\", \"expiration_date\": \"2019-11-02 23:59:00+00:00\", \"updated_date\": null, \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2002-10-30 00:00:00+00:00\", \"status\": \"Registered\"}\n"
  },
  {
    "path": "test/samples/expected/sbc.org.hk",
    "content": "{\"domain_name\": \"SBC.ORG.HK\", \"expiration_date\": \"2020-03-07 00:00:00+00:00\", \"updated_date\": null, \"registrar\": \"Hong Kong Domain Name Registration Company Limited\", \"registrar_url\": null, \"creation_date\": \"1998-07-14 00:00:00+00:00\", \"status\": \"Active\"}\n"
  },
  {
    "path": "test/samples/expected/seal.jobs",
    "content": "{\"domain_name\": \"SEAL.JOBS\", \"expiration_date\": \"2022-02-25 06:26:32+00:00\", \"updated_date\": \"2018-03-22 13:44:07+00:00\", \"registrar\": null, \"registrar_url\": \"http://www.godaddy.com\", \"creation_date\": \"2017-02-25 06:26:32+00:00\", \"status\": \"ok https://icann.org/epp#ok\"}\n"
  },
  {
    "path": "test/samples/expected/shazow.net",
    "content": "{\"domain_name\": \"SHAZOW.NET\", \"expiration_date\": \"2009-09-13 00:00:00+00:00\", \"updated_date\": \"2007-08-08 00:00:00+00:00\", \"registrar\": \"NEW DREAM NETWORK, LLC\", \"registrar_url\": null, \"creation_date\": \"2003-09-13 00:00:00+00:00\", \"status\": \"ok\"}\n"
  },
  {
    "path": "test/samples/expected/slashdot.org",
    "content": "{\"domain_name\": \"SLASHDOT.ORG\", \"expiration_date\": \"2008-10-04 04:00:00+00:00\", \"updated_date\": null, \"registrar\": \"Tucows Inc. (R11-LROR)\", \"registrar_url\": null, \"creation_date\": null, \"status\": \"OK\"}\n"
  },
  {
    "path": "test/samples/expected/squatter.net",
    "content": "{\"domain_name\": \"SQUATTER.NET\", \"expiration_date\": \"2008-11-06 00:00:00+00:00\", \"updated_date\": \"2007-11-07 00:00:00+00:00\", \"registrar\": \"DOMAINDISCOVER\", \"registrar_url\": null, \"creation_date\": \"1999-11-06 00:00:00+00:00\", \"status\": \"clientTransferProhibited\"}\n"
  },
  {
    "path": "test/samples/expected/titech.ac.jp",
    "content": "{\"domain_name\": \"TITECH.AC.JP\", \"expiration_date\": null, \"updated_date\": \"2025-05-29 10:45:59+09:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": \"Connected (2026/03/31)\"}"
  },
  {
    "path": "test/samples/expected/translate.goog",
    "content": "{\"domain_name\": \"translate.goog\", \"registrar\": \"MarkMonitor Inc.\", \"whois_server\": \"whois.nic.google\", \"referral_url\": None, \"updated_date\": datetime.datetime(2020, 11, 8, 10, 37), \"creation_date\": datetime.datetime(2017, 12, 5, 22, 54, 14), \"expiration_date\": datetime.datetime(2021, 12, 5, 22, 54, 14), \"name_servers\": [\"ns1.google.com\", \"ns2.google.com\", \"ns3.google.com\", \"ns4.google.com\"], \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"], \"emails\": \"abusecomplaints@markmonitor.com\", \"dnssec\": \"unsigned\", \"name\": \"REDACTED FOR PRIVACY\", \"org\": \"Charleston Road Registry, Inc.\", \"address\": \"REDACTED FOR PRIVACY\", \"city\": \"REDACTED FOR PRIVACY\", \"state\": \"CA\", \"zipcode\": \"REDACTED FOR PRIVACY\", \"country\": \"US\"}\n"
  },
  {
    "path": "test/samples/expected/urlowl.com",
    "content": "{\"domain_name\": \"URLOWL.COM\", \"expiration_date\": \"2018-02-21 19:24:57+00:00\", \"updated_date\": \"2017-03-31 07:36:34+00:00\", \"registrar\": \"DYNADOT, LLC\", \"registrar_url\": \"http://www.dynadot.com\", \"creation_date\": \"2013-02-21 19:24:57+00:00\", \"status\": \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\"}\n"
  },
  {
    "path": "test/samples/expected/web.de",
    "content": "{\"domain_name\": \"web.de\", \"expiration_date\": null, \"updated_date\": [\"2016-04-11 11:09:54+02:00\", \"2011-08-10 17:09:10+02:00\"], \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": \"connect\"}"
  },
  {
    "path": "test/samples/expected/willhaben.at",
    "content": "{\"domain_name\": \"willhaben.at\", \"expiration_date\": null, \"updated_date\": [\"2014-12-04 14:57:44+00:00\", \"2014-04-22 10:08:35+00:00\", \"2015-10-21 16:23:11+00:00\"], \"registrar\": null, \"registrar_url\": null, \"creation_date\": null, \"status\": null}\n"
  },
  {
    "path": "test/samples/expected/www.gov.uk",
    "content": "{\"domain_name\": \"gov.uk\", \"expiration_date\": null, \"updated_date\": null, \"registrar\": \"No registrar listed.  This domain is directly registered with Nominet.\", \"registrar_url\": null, \"creation_date\": \"1996-08-01 00:00:00+00:00\", \"status\": \"No registration status listed.\"}\n"
  },
  {
    "path": "test/samples/expected/yahoo.co.jp",
    "content": "{\"domain_name\": \"YAHOO.CO.JP\", \"expiration_date\": null, \"updated_date\": \"2024-10-01 01:00:44+09:00\", \"registrar\": null, \"registrar_url\": null, \"creation_date\": \"2019-09-27 00:00:00+00:00\", \"status\": \"Connected (2025/09/30)\"}\n"
  },
  {
    "path": "test/samples/expected/yahoo.co.nz",
    "content": "{\"domain_name\": \"yahoo.co.nz\", \"expiration_date\": null, \"updated_date\": \"2025-04-07 09:13:29+00:00\", \"registrar\": \"MarkMonitor. Inc\", \"registrar_url\": \"https://www.markmonitor.com/\", \"creation_date\": \"1997-05-04 12:00:00+00:00\", \"status\": [\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\"]}\n"
  },
  {
    "path": "test/samples/expected/yandex.kz",
    "content": "{\"domain_name\": \"yandex.kz\", \"expiration_date\": null, \"updated_date\": \"2022-08-04 10:20:10+00:00\", \"registrar\": \"HOSTER.KZ\", \"registrar_url\": null, \"creation_date\": \"2009-07-01 12:44:02+00:00\", \"status\": [\"status : clientTransferProhibited\", \"clientDeleteProhibited\", \"clientRenewProhibited\"]}"
  },
  {
    "path": "test/samples/expected/yandex.ru",
    "content": "{\"domain_name\": \"YANDEX.RU\", \"expiration_date\": \"2018-09-30 21:00:00+00:00\", \"updated_date\": null, \"registrar\": \"RU-CENTER-RU\", \"registrar_url\": null, \"creation_date\": \"1997-09-23 09:45:07+00:00\", \"status\": \"REGISTERED, DELEGATED, VERIFIED\"}\n"
  },
  {
    "path": "test/samples/whois/abc.rs",
    "content": "% The data in the Whois database are provided by RNIDS\n% for information purposes only and to assist persons in obtaining\n% information about or related to a domain name registration record.\n% Data in the database are created by registrants and we do not guarantee\n% their accuracy. We reserve the right to remove access\n% for entities abusing the data, without notice.\n% All timestamps are given in Serbian local time.\n%\nDomain name: abc.rs\nDomain status: Active https://www.rnids.rs/en/domain-name-status-codes#Active\nRegistration date: 26.03.2008 16:18:03\nModification date: 11.02.2025 08:24:15\nExpiration date: 26.03.2026 16:18:03\nConfirmed: 26.03.2008 16:18:03\nRegistrar: Mainstream Public Cloud Services d.o.o.\n\n\nRegistrant: Roda grupa doo\nAddress: Bulevar Oslobodjenja 129, Beograd, Serbia\nPostal Code: 11000\nID Number: 20886374\nTax ID: 107867472\n\nAdministrative contact: Individual\n\nTechnical contact: SERBIA BROADBAND - SRPSKE KABLOVSKE MREZE D.O.O.\nAddress: Bulevar Peka Dapcevica 19, Beograd, Serbia\nPostal Code: 11000\nID Number: 17280554\nTax ID: 101038731\n\n\nDNS: ns1.providus.rs - 164.132.48.70\nDNS: ns2.providus.rs - 104.199.179.254\nDNS: ns3.providus.rs - 52.5.196.189\n\n\nDNSSEC signed: no\n\nWhois Timestamp: 07.11.2025 20:57:08\n"
  },
  {
    "path": "test/samples/whois/abc.xyz",
    "content": "[whois.nic.xyz]\nDomain Name: ABC.XYZ\nRegistry Domain ID: D2192285-CNIC\nRegistrar WHOIS Server: whois.markmonitor.com\nRegistrar URL:\nUpdated Date: 2025-03-10T15:22:23.0Z\nCreation Date: 2014-03-20T12:59:17.0Z\nRegistry Expiry Date: 2026-03-20T23:59:59.0Z\nRegistrar: MarkMonitor, Inc (TLDs)\nRegistrar IANA ID: 292\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nName Server: NS2.GOOGLE.COM\nName Server: NS4.GOOGLE.COM\nName Server: NS3.GOOGLE.COM\nName Server: NS1.GOOGLE.COM\nDNSSEC: unsigned\nRegistrar Abuse Contact Email: registryescalations@markmonitor.com\nRegistrar Abuse Contact Phone: +1.2083895740\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2025-10-10T02:49:26.0Z <<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\n>>> IMPORTANT INFORMATION ABOUT THE DEPLOYMENT OF RDAP: please visit\nhttps://www.centralnicregistry.com/support/information/rdap <<<\n\nThe registration data available in this service is limited. Additional\ndata may be available at https://lookup.icann.org\n\nThe Whois and RDAP services are provided by CentralNic, and contain\ninformation pertaining to Internet domain names registered by our\nour customers. By using this service you are agreeing (1) not to use any\ninformation presented here for any purpose other than determining\nownership of domain names, (2) not to store or reproduce this data in\nany way, (3) not to use any high-volume, automated, electronic processes\nto obtain data from this service. Abuse of this service is monitored and\nactions in contravention of these terms will result in being permanently\nblacklisted. All data is (c) CentralNic Ltd (https://www.centralnicregistry.com)\n\nAccess to the Whois and RDAP services is rate limited. For more\ninformation, visit https://centralnicregistry.com/policies/whois-guidance.\n\n\n"
  },
  {
    "path": "test/samples/whois/about.us",
    "content": "Domain Name: about.us\r\nRegistry Domain ID: D651466-US\r\nRegistrar WHOIS Server:\r\nRegistrar URL: www.neustarregistry.biz\r\nUpdated Date: 2017-06-02T01:30:53Z\r\nCreation Date: 2002-04-18T15:16:22Z\r\nRegistry Expiry Date: 2018-04-17T23:59:59Z\r\nRegistrar: Neustar, Inc.\r\nRegistrar IANA ID: 1111112\r\nRegistrar Abuse Contact Email: reg-support@support.neustar\r\nRegistrar Abuse Contact Phone:\r\nDomain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited\r\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\r\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\r\nDomain Status: serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\r\nRegistry Registrant ID: C37639215-US\r\nRegistrant Name: .US Registration Policy\r\nRegistrant Organization:\r\nRegistrant Street: 46000 Center Oak Plaza\r\nRegistrant Street:\r\nRegistrant Street:\r\nRegistrant City: Sterling\r\nRegistrant State/Province: VA\r\nRegistrant Postal Code: 20166\r\nRegistrant Country: US\r\nRegistrant Phone: +1.5714345728\r\nRegistrant Phone Ext:\r\nRegistrant Fax:\r\nRegistrant Fax Ext:\r\nRegistrant Email: support.us@neustar.us\r\nRegistrant Application Purpose: P5\r\nRegistrant Nexus Category: C21\r\nRegistry Admin ID: C37639215-US\r\nAdmin Name: .US Registration Policy\r\nAdmin Organization:\r\nAdmin Street: 46000 Center Oak Plaza\r\nAdmin Street:\r\nAdmin Street:\r\nAdmin City: Sterling\r\nAdmin State/Province: VA\r\nAdmin Postal Code: 20166\r\nAdmin Country: US\r\nAdmin Phone: +1.5714345728\r\nAdmin Phone Ext:\r\nAdmin Fax:\r\nAdmin Fax Ext:\r\nAdmin Email: support.us@neustar.us\r\nAdmin Application Purpose: P5\r\nAdmin Nexus Category: C21\r\nRegistry Tech ID: C37639215-US\r\nTech Name: .US Registration Policy\r\nTech Organization:\r\nTech Street: 46000 Center Oak Plaza\r\nTech Street:\r\nTech Street:\r\nTech City: Sterling\r\nTech State/Province: VA\r\nTech Postal Code: 20166\r\nTech Country: US\r\nTech Phone: +1.5714345728\r\nTech Phone Ext:\r\nTech Fax:\r\nTech Fax Ext:\r\nTech Email: support.us@neustar.us\r\nTech Application Purpose: P5\r\nTech Nexus Category: C21\r\nName Server: ns1.usatfus.about.us\r\nName Server: ns2.usatfus.about.us\r\nDNSSEC: unsigned\r\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\r\n>>> Last update of WHOIS database: 2017-12-11T22:54:29Z <<<\r\n\r\nFor more information on Whois status codes, please visit https://icann.org/epp\r\n\r\nNeuStar, Inc., the Registry Administrator for .US, has collected this information for the WHOIS database through a .US-Accredited Registrar. This information is provided to you for informational purposes only and is designed to assist persons in determining contents of a domain name registration record in the NeuStar registry database. NeuStar makes this information available to you \"as is\" and does not guarantee its accuracy. By submitting a WHOIS query, you agree that you will use this data only for lawful purposes and that, under no circumstances will you use this data: (1) to allow, enable, or otherwise support the transmission of mass unsolicited, commercial advertising or solicitations via direct mail, electronic mail, or by telephone; (2) in contravention of any applicable data and privacy protection laws; or (3) to enable high volume, automated, electronic processes that apply to the registry (or its systems). Compilation, repackaging, dissemination, or other use of the WHOIS database in its entirety, or of a substantial portion thereof, is not allowed without NeuStar's prior written permission. NeuStar reserves the right to modify or change these conditions at any time without prior or subsequent notification of any kind. By executing this query, in any manner whatsoever, you agree to abide by these terms. NOTE: FAILURE TO LOCATE A RECORD IN THE WHOIS DATABASE IS NOT INDICATIVE OF THE AVAILABILITY OF A DOMAIN NAME. All domain names are subject to certain additional domain name registration rules. For details, please visit our site at www.whois.us."
  },
  {
    "path": "test/samples/whois/abv.bg",
    "content": "\r\nDOMAIN NAME: abv.bg\r\nrequested on: see at www.register.bg\r\nprocessed from: see at www.register.bg\r\nactivated on: see at www.register.bg\r\nexpires at: see at www.register.bg\r\nregistration status: Registered\r\n\r\nREGISTRANT:\r\nDarik Net EAD\r\n  bul. Hristofor Kolumb 41, et. 6\r\n  SOFIA, 1592\r\n  BULGARIA\r\n\r\nADMINISTRATIVE CONTACT:\r\n  Toni Enchev\r\n  noc@netinfo.bg\r\n  Darik Net EAD\r\n  bul. Hristofor Kolumb 41, et. 6\r\n  SOFIA, 1592\r\n  BULGARIA\r\n  tel: +359 2 960 3162\r\n  fax:\r\n  NIC handle: TE230426\r\n\r\nTECHNICAL CONTACT(S):\r\n\r\n  Milen Evtimov\r\n  milen@netinfo.bg\r\n  Net Info.BG JSCo\r\n  bul. \"Cherni vrah\" 1-3, Sofiya 1463\r\n  SOFIA, 1421\r\n  BULGARIA\r\n  tel: +359 2 9603100\r\n  fax: +359 2 9604179\r\n  NIC handle: ME26909\r\n\r\n  Biser Grigorov\r\n  biser@netinfo.bg\r\n  Net Info.BG JSCo\r\n  bul. \"Cherni vrah\" 1-3, Sofiya 1463\r\n  SOFIA, 1421\r\n  BULGARIA\r\n  tel: +359 2 9603100\r\n  fax: +359 2 9604179\r\n  NIC handle: BG26908\r\n\r\nNAME SERVER INFORMATION:\r\nns.netinfo.bg\r\nns2.netinfo.bg\r\n\r\nDNSSEC: Inactive\r\n\r\n"
  },
  {
    "path": "test/samples/whois/afip.gob.ar",
    "content": "% La información a la que estás accediendo se provee exclusivamente para\n% fines relacionados con operaciones sobre nombres de dominios y DNS,\n% quedando absolutamente prohibido su uso para otros fines.\n%\n% La DIRECCIÓN NACIONAL DEL REGISTRO DE DOMINIOS DE INTERNET es depositaria\n% de la información que los usuarios declaran con la sola finalidad de\n% registrar nombres de dominio en ‘.ar’, para ser publicada en el sitio web\n% de NIC Argentina.\n%\n% La información personal que consta en la base de datos generada a partir\n% del sistema de registro de nombres de dominios se encuentra amparada por\n% la Ley N° 25326 “Protección de Datos Personales” y el Decreto\n% Reglamentario 1558/01.\ndomain:\t\tafip.gob.ar\nregistrant:\t33693450239\nregistrar:\tnicar\nregistered:\t1997-05-26 00:00:00\nchanged:\t2018-05-19 12:18:44.329522\nexpire:\t\t2019-05-26 00:00:00\ncontact:\t33693450239\nname:\t\tADMINISTRACION FEDERAL DE INGRESOS PUBLICOS\nregistrar:\tnicar\ncreated:\t2013-10-30 00:00:00\nchanged:\t2019-03-21 20:38:40.827111\nnserver:\tns1.afip.gov.ar (200.1.116.10/32)\nnserver:\tns2.afip.gov.ar (200.1.116.11/32)\nregistrar:\tnicar\ncreated:\t2016-06-30 22:15:47.314461"
  },
  {
    "path": "test/samples/whois/allegro.pl",
    "content": "\r\nDOMAIN NAME:           allegro.pl\r\nregistrant type:       organization\r\nnameservers:           dns1.allegro.pl. [91.194.188.132]\r\n                       dns2.allegro.pl. [91.207.14.244]\r\n                       dns3.allegro.pl. [80.50.230.43]\r\n                       dns4.allegro.pl. [213.180.138.53]\r\ncreated:               1999.10.27 13:00:00\r\nlast modified:         2017.10.17 07:01:25\r\nrenewal date:          2018.10.26 15:00:00\r\n\r\noption created:        2014.06.02 23:44:16\r\noption expiration date:       2020.06.02 23:44:16\r\n\r\ndnssec:                Unsigned\r\n\r\nTECHNICAL CONTACT:\r\ncompany: DNS Administrator\r\n        Grupa Allegro Sp. z o.o.\r\nstreet: ul. Grunwaldzka 182\r\ncity: 60-166 Poznan\r\nlocation: PL\r\nphone:  +48.616271220\r\nfax:  +48.616271220\r\nlast modified: 2017.03.27\r\n\r\n\r\nREGISTRAR:\r\nCorporation Service Company\r\n251 Little Falls Drive\r\nWilmington, Delaware 19808\r\nUnited States\r\ntel: +1.302.636.5400\r\nfax: +1.302.636.5454\r\nemail: registryrelations@cscinfo.com\r\n\r\nWHOIS database responses: http://www.dns.pl/english/opiskomunikatow_en.html\r\n\r\nWHOIS displays data with a delay not exceeding 15 minutes in relation to the .pl Registry system\r\nRegistrant data available at http://dns.pl/cgi-bin/en_whois.pl"
  },
  {
    "path": "test/samples/whois/amazon.co.uk",
    "content": "\n    Domain name:\n        amazon.co.uk\n\n    Data validation:\n        Nominet was able to match the registrant's name and address against a 3rd party data source on 10-Dec-2012\n\n    Registrar:\n        Amazon.com, Inc. t/a Amazon.com, Inc. [Tag = AMAZON-COM]\n        URL: http://www.amazon.com\n\n    Relevant dates:\n        Registered on: before Aug-1996\n        Expiry date:  05-Dec-2020\n        Last updated:  23-Oct-2013\n\n    Registration status:\n        Registered until expiry date.\n\n    Name servers:\n        ns1.p31.dynect.net\n        ns2.p31.dynect.net\n        ns3.p31.dynect.net\n        ns4.p31.dynect.net\n        pdns1.ultradns.net\n        pdns2.ultradns.net\n        pdns3.ultradns.org\n        pdns4.ultradns.org\n        pdns5.ultradns.info\n        pdns6.ultradns.co.uk      204.74.115.1  2610:00a1:1017:0000:0000:0000:0000:0001\n\n    WHOIS lookup made at 11:55:41 18-Apr-2019\n\n--\nThis WHOIS information is provided for free by Nominet UK the central registry\nfor .uk domain names. This information and the .uk WHOIS are:\n\n    Copyright Nominet UK 1996 - 2019.\n\nYou may not access the .uk WHOIS or use any data from it except as permitted\nby the terms of use available in full at https://www.nominet.uk/whoisterms,\nwhich includes restrictions on: (A) use of the data for advertising, or its\nrepackaging, recompilation, redistribution or reuse (B) obscuring, removing\nor hiding any or all of this notice and (C) exceeding query rate or volume\nlimits. The data is provided on an 'as-is' basis and may lag behind the\nregister. Access may be withdrawn or restricted at any time.\n"
  },
  {
    "path": "test/samples/whois/app.nl",
    "content": "Domain name: app.nl\r\nStatus:      active\r\n\r\nReseller:\r\n   Hoasted\r\n   Weesperstraat 61\r\n   3512AB Amsterdam\r\n   Netherlands\r\n\r\nRegistrar:\r\n   Hosting Secure\r\n   Weesperstraat 61\r\n   1018VN Amsterdam\r\n   Netherlands\r\n\r\nAbuse Contact:\r\n   +31.0202018165\r\n   abuse@hostingsecure.com\r\n\r\nDNSSEC:      yes\r\n\r\nDomain nameservers:\r\n   ns1.hoasted.nl\r\n   ns2.hoasted.eu\r\n   ns3.hoasted.com\r\n\r\nCreation Date: 1998-02-20\r\n\r\nUpdated Date: 2025-09-12\r\n\r\nRecord maintained by: SIDN BV"
  },
  {
    "path": "test/samples/whois/brainly.lat",
    "content": "Domain Name: brainly.lat\nRegistry Domain ID: DOMAIN_497-LAT\nRegistrar WHOIS Server:\nRegistrar URL: http://www.instra.com/\nUpdated Date: 2018-07-22T09:01:05Z\nCreation Date: 2015-07-31T15:59:27Z\nRegistry Expiry Date: 2019-07-31T15:59:27Z\nRegistrar: Instra Corporation Pty Ltd.\nRegistrar IANA ID: 1376\nRegistrar Abuse Contact Email:\nRegistrar Abuse Contact Phone:\nDomain Status: ok http://www.icann.org/epp#OK\nRegistry Registrant ID: REDACTED FOR PRIVACY\nRegistrant Name: REDACTED FOR PRIVACY\nRegistrant Organization: Brainly Sp. z o.o.\nRegistrant Street: REDACTED FOR PRIVACY\nRegistrant City: REDACTED FOR PRIVACY\nRegistrant State/Province: Malopolska\nRegistrant Postal Code: REDACTED FOR PRIVACY\nRegistrant Country: PL\nRegistrant Phone: REDACTED FOR PRIVACY\nRegistrant Phone Ext: REDACTED FOR PRIVACY\nRegistrant Fax: REDACTED FOR PRIVACY\nRegistrant Fax Ext: REDACTED FOR PRIVACY\nRegistrant Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name\nRegistry Admin ID: REDACTED FOR PRIVACY\nAdmin Name: REDACTED FOR PRIVACY\nAdmin Organization: REDACTED FOR PRIVACY\nAdmin Street: REDACTED FOR PRIVACY\nAdmin City: REDACTED FOR PRIVACY\nAdmin State/Province: REDACTED FOR PRIVACY\nAdmin Postal Code: REDACTED FOR PRIVACY\nAdmin Country: REDACTED FOR PRIVACY\nAdmin Phone: REDACTED FOR PRIVACY\nAdmin Phone Ext: REDACTED FOR PRIVACY\nAdmin Fax: REDACTED FOR PRIVACY\nAdmin Fax Ext: REDACTED FOR PRIVACY\nAdmin Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name\nRegistry Tech ID: REDACTED FOR PRIVACY\nTech Name: REDACTED FOR PRIVACY\nTech Organization: REDACTED FOR PRIVACY\nTech Street: REDACTED FOR PRIVACY\nTech City: REDACTED FOR PRIVACY\nTech State/Province: REDACTED FOR PRIVACY\nTech Postal Code: REDACTED FOR PRIVACY\nTech Country: REDACTED FOR PRIVACY\nTech Phone: REDACTED FOR PRIVACY\nTech Phone Ext: REDACTED FOR PRIVACY\nTech Fax: REDACTED FOR PRIVACY\nTech Fax Ext: REDACTED FOR PRIVACY\nTech Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name\nName Server: adi.ns.cloudflare.com\nName Server: chad.ns.cloudflare.com\nDNSSEC: unsigned\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\nLast update of WHOIS database: 2019-04-17T13:13:00Z<<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\n% NOTICE: The expiration date displayed in this record is the date the registrar's\n% sponsorship of the domain name registration in the registry is currently set to expire.\n% This date does not necessarily reflect the expiration date of the domain name\n% registrant's agreement with the sponsoring registrar.  Users may consult the sponsoring\n% registrar's Whois database to view the registrar's reported date of expiration for this\n% registration.\n\n% The Data in eCOM-LAC?s .LAT Registry Whois database is provided\n% by eCOM-LAC for information purposes only, and to assist persons in obtaining\n\n% guarantee its accuracy. By submitting a Whois query, you agree to abide by the\n% following terms of use: You agree that you may use this Data only for lawful purposes\n% and that under no circumstances will you use this Data to: (1) allow, enable, or\n% otherwise support the transmission of mass unsolicited, commercial advertising or\n% solicitations via e-mail, telephone, or facsimile; or (2) enable high volume, automated,\n% electronic processes that apply to eCOM-LAC or its service providers (or its computer\n% expressly prohibited without the prior written consent of eCOM-LAC. You agree not to\n% use electronic processes that are automated and high-volume to access or query the\n% Whois database except as reasonably necessary to register domain names or modify\n% existing registrations. eCOM-LAC reserves the right to restrict your access to the Whois\n% database in its sole discretion to ensure operational stability.  eCOM-LAC may restrict\n% or terminate your access to the Whois database for failure to abide by these terms of\n% use. eCOM-LAC reserves the right to modify these terms at any time.\n% URL of the ICANN WHOIS Data Problem Reporting System: http://wdprs.internic.net/\n% NOTA: La fecha de expiraci?n  mostrada en este registro es la fecha indicada por el\n% Registrar en la que finaliza la administraci?n del nombre de dominio en el Registry. Esta\n% fecha no necesariamente refleja la fecha de expiraci?n del nombre de dominio que el\n% registrante acord? con el registrar sponsor. Los usuarios pueden consultar la base de\n% datos del whois del registrar sponsor para ver la fecha de expiraci?n reportada por el\n% registrar para este dominio.\n% Los datos en la base de datos de whois de eCOM-LAC es proporcionada por eCOM-LAC\n% para fines informativos solamente y para ayudar a las personas a obtener informaci?n\n% relacionada a los datos de registro de un nombre de dominio. eCOM-LAC no garantiza su\n% exactitud. Al realizar una consulta al Whois, acepta cumplir con las siguientes condiciones\n% de uso: Acepta que puede usar esta informaci?n solo para fines legales y que bajo ninguna\n% circunstancia usar? esta informaci?n para: (1) permitir, hacer uso o apoyar de alguna\n% manera el env?o masivo de publicidad v?a correo electr?nico, tel?fono o fax; o (2)  realizar\n% procesos automatizados, electr?nicos y de alto volumen que apliquen a eCOM-LAC o sus\n% proveedores de servicio (o sus sistemas computacionales). La recopilaci?n, difusi?n o\n% cualquier otro uso de estos datos sin el consentimiento previo por escrito de eCOM-LAC\n% queda expresamente prohibido. Usted acepta no utilizar procesos electr?nicos\n% automatizados y de alto volumen para acceder o consultar la base de datos de Whois\n% excepto cuando sea razonablemente necesario para registrar nombres de dominio o\n% modificar registros existentes. eCOM-LAC se reserva el derecho de restringir su acceso a la\n% base de datos de whois a su entera discreci?n para asegurar la estabilidad en su\n% operaci?n. eCOM-LAC puede restringir o terminar su acceso a la base de datos de Whois\n% por no cumplir con estas condiciones de uso. eCOM-LAC se reserva el derecho de modificar estos t?rminos en cualquier momento.\n% La URL del sistema de reportes para problemas con la informaci?n de WHOIS del ICANN es: http://wdprs.internic.net/\n"
  },
  {
    "path": "test/samples/whois/cbc.ca",
    "content": "Domain Name: cbc.ca\nRegistry Domain ID: D345334-CIRA\nRegistrar WHOIS Server: whois.ca.fury.ca\nRegistrar URL: authenticweb.com\nUpdated Date: 2018-10-26T02:15:16Z\nCreation Date: 2000-10-16T13:56:05Z\nRegistry Expiry Date: 2019-11-24T05:00:00Z\nRegistrar: Authentic Web Inc.\nRegistrar IANA ID:\nRegistrar Abuse Contact Email:\nRegistrar Abuse Contact Phone:\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nDomain Status: serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\nDomain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited\nDomain Status: serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited\nRegistry Registrant ID: 24345497-CIRA\nRegistrant Name: Canadian Broadcasting Corporation\nRegistrant Organization:\nRegistrant Street: 250 Front St W\nRegistrant City: Toronto\nRegistrant State/Province: ON\nRegistrant Postal Code: M5V3G5\nRegistrant Country: CA\nRegistrant Phone: +1.4162053482\nRegistrant Phone Ext:\nRegistrant Fax: +1.4162057750\nRegistrant Fax Ext:\nRegistrant Email: domain-name@cbc.ca\nRegistry Admin ID: 24345372-CIRA\nAdmin Name: Karen Stephen\nAdmin Organization: Canadian Broadcasting Corporation\nAdmin Street: 250 Front St W\nAdmin City: Toronto\nAdmin State/Province: ON\nAdmin Postal Code: M5V3G5\nAdmin Country: CA\nAdmin Phone: +1.4162053482\nAdmin Phone Ext:\nAdmin Fax: +1.4162057750\nAdmin Fax Ext:\nAdmin Email: domain-name@cbc.ca\nRegistry Tech ID: 24345501-CIRA\nTech Name: Karen Stephen\nTech Organization: Canadian Broadcasting Corporation\nTech Street: 250 Front St W\nTech City: Toronto\nTech State/Province: ON\nTech Postal Code: M5V3G5\nTech Country: CA\nTech Phone: +1.4162053482\nTech Phone Ext:\nTech Fax: +1.4162057750\nTech Fax Ext:\nTech Email: domain-name@cbc.ca\nRegistry Billing ID:\nBilling Name:\nBilling Organization:\nBilling Street:\nBilling City:\nBilling State/Province:\nBilling Postal Code:\nBilling Country:\nBilling Phone:\nBilling Phone Ext:\nBilling Fax:\nBilling Fax Ext:\nBilling Email:\nName Server: a5-65.akam.net\nName Server: a9-66.akam.net\nName Server: a26-67.akam.net\nName Server: a1-29.akam.net\nName Server: a4-64.akam.net\nName Server: a14-66.akam.net\nDNSSEC: unsigned\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2019-04-16T12:20:17Z <<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\n%\n% Use of CIRA's WHOIS service is governed by the Terms of Use in its Legal\n% Notice, available at http://www.cira.ca/legal-notice/?lang=en\n%\n% (c) 2019 Canadian Internet Registration Authority, (http://www.cira.ca/)\n"
  },
  {
    "path": "test/samples/whois/cyberciti.biz",
    "content": "Domain Name: CYBERCITI.BIZ\nRegistry Domain ID: D3209108-BIZ\nRegistrar WHOIS Server: whois.godaddy.com\nRegistrar URL: http://www.godaddy.com\nUpdated Date: 2018-07-11T05:55:25Z\nCreation Date: 2002-07-01T09:31:21Z\nRegistrar Registration Expiration Date: 2024-06-30T23:59:59Z\nRegistrar: GoDaddy.com, LLC\nRegistrar IANA ID: 146\nRegistrar Abuse Contact Email: abuse@godaddy.com\nRegistrar Abuse Contact Phone: +1.4806242505\nDomain Status: clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited http://www.icann.org/epp#clientUpdateProhibited\nDomain Status: clientRenewProhibited http://www.icann.org/epp#clientRenewProhibited\nDomain Status: clientDeleteProhibited http://www.icann.org/epp#clientDeleteProhibited\nRegistry Registrant ID: CR19482819\nRegistrant Name: Registration Private\nRegistrant Organization: Domains By Proxy, LLC\nRegistrant Street: DomainsByProxy.com\nRegistrant Street: 14455 N. Hayden Road\nRegistrant City: Scottsdale\nRegistrant State/Province: Arizona\nRegistrant Postal Code: 85260\nRegistrant Country: US\nRegistrant Phone: +1.4806242599\nRegistrant Phone Ext:\nRegistrant Fax: +1.4806242598\nRegistrant Fax Ext:\nRegistrant Email: CYBERCITI.BIZ@domainsbyproxy.com\nRegistry Admin ID: CR19482821\nAdmin Name: Registration Private\nAdmin Organization: Domains By Proxy, LLC\nAdmin Street: DomainsByProxy.com\nAdmin Street: 14455 N. Hayden Road\nAdmin City: Scottsdale\nAdmin State/Province: Arizona\nAdmin Postal Code: 85260\nAdmin Country: US\nAdmin Phone: +1.4806242599\nAdmin Phone Ext:\nAdmin Fax: +1.4806242598\nAdmin Fax Ext:\nAdmin Email: CYBERCITI.BIZ@domainsbyproxy.com\nRegistry Tech ID: CR19482820\nTech Name: Registration Private\nTech Organization: Domains By Proxy, LLC\nTech Street: DomainsByProxy.com\nTech Street: 14455 N. Hayden Road\nTech City: Scottsdale\nTech State/Province: Arizona\nTech Postal Code: 85260\nTech Country: US\nTech Phone: +1.4806242599\nTech Phone Ext:\nTech Fax: +1.4806242598\nTech Fax Ext:\nTech Email: CYBERCITI.BIZ@domainsbyproxy.com\nName Server: CLAY.NS.CLOUDFLARE.COM\nName Server: FAY.NS.CLOUDFLARE.COM\nDNSSEC: unsigned\nURL of the ICANN WHOIS Data Problem Reporting System: http://wdprs.internic.net/\n>>> Last update of WHOIS database: 2019-04-16T13:00:00Z <<<\n\nFor more information on Whois status codes, please visit https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en\n\nNotes:\n\nIMPORTANT: Port43 will provide the ICANN-required minimum data set per\nICANN Temporary Specification, adopted 17 May 2018.\nVisit https://whois.godaddy.com to look up contact data for domains\nnot covered by GDPR policy.\n\nThe data contained in GoDaddy.com, LLC's WhoIs database,\nwhile believed by the company to be reliable, is provided \"as is\"\nwith no guarantee or warranties regarding its accuracy.  This\ninformation is provided for the sole purpose of assisting you\nin obtaining information about domain name registration records.\nAny use of this data for any other purpose is expressly forbidden without the prior written\npermission of GoDaddy.com, LLC.  By submitting an inquiry,\nyou agree to these terms of usage and limitations of warranty.  In particular,\nyou agree not to use this data to allow, enable, or otherwise make possible,\ndissemination or collection of this data, in part or in its entirety, for any\npurpose, such as the transmission of unsolicited advertising and\nand solicitations of any kind, including spam.  You further agree\nnot to use this data to enable high volume, automated or robotic electronic\nprocesses designed to collect or compile this data for any purpose,\nincluding mining this data for your own personal or commercial purposes.\n\nPlease note: the registrant of the domain name is specified\nin the \"registrant\" section.  In most cases, GoDaddy.com, LLC\nis not the registrant of domain names listed in this database."
  },
  {
    "path": "test/samples/whois/davidwalsh.name",
    "content": "\r\nDisclaimer: VeriSign, Inc. makes every effort to maintain the\r\ncompleteness and accuracy of the Whois data, but cannot guarantee\r\nthat the results are error-free. Therefore, any data provided\r\nthrough the Whois service are on an as is basis without any\r\nwarranties.\r\nBY USING THE WHOIS SERVICE AND THE DATA CONTAINED\r\nHEREIN OR IN ANY REPORT GENERATED WITH RESPECT THERETO, IT IS\r\nACCEPTED THAT VERISIGN, INC. IS NOT LIABLE FOR\r\nANY DAMAGES OF ANY KIND ARISING OUT OF, OR IN CONNECTION WITH, THE\r\nREPORT OR THE INFORMATION PROVIDED BY THE WHOIS SERVICE, NOR\r\nOMISSIONS OR MISSING INFORMATION. THE RESULTS OF ANY WHOIS REPORT OR\r\nINFORMATION PROVIDED BY THE WHOIS SERVICE CANNOT BE RELIED UPON IN\r\nCONTEMPLATION OF LEGAL PROCEEDINGS WITHOUT FURTHER VERIFICATION, NOR\r\nDO SUCH RESULTS CONSTITUTE A LEGAL OPINION. Acceptance of the\r\nresults of the Whois constitutes acceptance of these terms,\r\nconditions and limitations. Whois data may be requested only for\r\nlawful purposes, in particular, to protect legal rights and\r\nobligations. Illegitimate uses of Whois data include, but are not\r\nlimited to, unsolicited email, data mining, direct marketing or any\r\nother improper purpose. Any request made for Whois data will be\r\ndocumented by VeriSign, Inc. but will not be used for any commercial purpose whatsoever.\r\n\r\n ****\r\n\r\n Registry Domain ID: 2852634_DOMAIN_NAME-VRSN\r\n Domain Name: DAVIDWALSH.NAME\r\n Registrar: Name.com, Inc.\r\n Registrar IANA ID: 625\r\n Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\r\n\r\n>>> Last update of whois database: 2017-12-08T23:02:21Z <<<\r\n\r\nFor more information on Whois status codes, please visit https://icann.org/epp\r\n\r\n"
  },
  {
    "path": "test/samples/whois/digg.com",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Domain Name: DIGG.COM\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n   Name Server: UDNS1.ULTRADNS.NET\n   Name Server: UDNS2.ULTRADNS.NET\n   Status: clientDeleteProhibited\n   Status: clientRenewProhibited\n   Status: clientTransferProhibited\n   Status: clientUpdateProhibited\n   Updated Date: 13-mar-2007\n   Creation Date: 20-feb-2000\n   Expiration Date: 20-feb-2010\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:39:08 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.The data contained in GoDaddy.com, Inc.'s WhoIs database,\nwhile believed by the company to be reliable, is provided \"as is\"\nwith no guarantee or warranties regarding its accuracy.  This\ninformation is provided for the sole purpose of assisting you\nin obtaining information about domain name registration records.\nAny use of this data for any other purpose is expressly forbidden without the prior written\npermission of GoDaddy.com, Inc.  By submitting an inquiry,\nyou agree to these terms of usage and limitations of warranty.  In particular,\nyou agree not to use this data to allow, enable, or otherwise make possible,\ndissemination or collection of this data, in part or in its entirety, for any\npurpose, such as the transmission of unsolicited advertising and\nand solicitations of any kind, including spam.  You further agree\nnot to use this data to enable high volume, automated or robotic electronic\nprocesses designed to collect or compile this data for any purpose,\nincluding mining this data for your own personal or commercial purposes. \n\nPlease note: the registrant of the domain name is specified\nin the \"registrant\" field.  In most cases, GoDaddy.com, Inc. \nis not the registrant of domain names listed in this database.\n\n\nRegistrant:\n   Domains by Proxy, Inc.\n\n   Registered through: GoDaddy.com, Inc. (http://www.godaddy.com)\n   Domain Name: DIGG.COM\n\n   Domain servers in listed order:\n      UDNS1.ULTRADNS.NET\n      UDNS2.ULTRADNS.NET\n\n\n   For complete domain details go to:\n   http://who.godaddy.com/whoischeck.aspx?Domain=DIGG.COM\n"
  },
  {
    "path": "test/samples/whois/druid.fi",
    "content": "domain.............: druid.fi\nstatus.............: Registered\ncreated............: 18.7.2012 04:04:23\nexpires............: 17.7.2022 22:16:55\navailable..........: 17.8.2022 22:16:55\nmodified...........: 19.3.2019\nholder transfer....: 28.1.2014\nRegistryLock.......: no\n\nNameservers\n\nnserver............: ns3.digitalocean.com [OK]\nnserver............: ns1.digitalocean.com [OK]\nnserver............: ns2.digitalocean.com [OK]\ndnssec.............: unsigned delegation\n\nHolder\n\nname...............: Druid Oy\nregister number....: 2491789-2\naddress............: Kaupintie 5\naddress............: 00440\naddress............: Helsinki\ncountry............: Finland\nphone..............: 0440479783\nholder email.......:\n\nRegistrar\n\nregistrar..........: CSL Computer Service Langenbach GmbH (d/b/a joker.com)\nwww................: www.joker.com\n\n Last update of WHOIS database: 17.4.2019 8:46:14 (EET) <<<\n\nCopyright (c) Finnish Communications Regulatory Authority\n"
  },
  {
    "path": "test/samples/whois/drupalcamp.by",
    "content": "Domain Name: drupalcamp.by\nRegistrar: Active Technologies LLC\nPerson: HIDDEN!\nEmail: HIDDEN! Details are available at http://www.cctld.by/whois/\nName Server: darwin.ns.cloudflare.com\nName Server: serena.ns.cloudflare.com\nUpdated Date: 2018-08-04\nCreation Date: 2018-07-25\nExpiration Date: 2020-07-25\n-------------------------------------------\nService provided by Reliable Software, Ltd."
  },
  {
    "path": "test/samples/whois/eurid.eu",
    "content": "% The WHOIS service offered by EURid and the access to the records\n% in the EURid WHOIS database are provided for information purposes\n% only. It allows persons to check whether a specific domain name\n% is still available or not and to obtain information related to\n% the registration records of existing domain names.\n%\n% EURid cannot, under any circumstances, be held liable in case the\n% stored information would prove to be wrong, incomplete or not\n% accurate in any sense.\n%\n% By submitting a query, you agree not to use the information made\n% available to:\n%\n% - allow, enable or otherwise support the transmission of unsolicited,\n%   commercial advertising or other solicitations whether via email or\n%   otherwise;\n% - target advertising in any possible way;\n% - cause nuisance in any possible way by sending messages to registrants,\n%   whether by automated, electronic processes capable of enabling\n%   high volumes or by other possible means.\n%\n% Without prejudice to the above, it is explicitly forbidden to extract,\n% copy and/or use or re-utilise in any form and by any means\n% (electronically or not) the whole or a quantitatively or qualitatively\n% substantial part of the contents of the WHOIS database without prior\n% and explicit permission by EURid, nor in any attempt hereof, to apply\n% automated, electronic processes to EURid (or its systems).\n%\n% You agree that any reproduction and/or transmission of data for\n% commercial purposes will always be considered as the extraction of a\n% substantial part of the content of the WHOIS database.\n%\n% By submitting the query, you agree to abide by this policy and accept\n% that EURid can take measures to limit the use of its WHOIS services\n% to protect the privacy of its registrants or the integrity\n% of the database.\n%\n% The EURid WHOIS service on port 43 (textual WHOIS) never discloses\n% any information concerning the registrant.\n% Registrant and on-site contact information can be obtained through use of the\n% web-based WHOIS service available from the EURid website www.eurid.eu\n%\n% WHOIS eurid.eu\nDomain: eurid.eu\nScript: LATIN\n\nRegistrant:\n        NOT DISCLOSED!\n        Visit www.eurid.eu for the web-based WHOIS.\n\nTechnical:\n        Organisation: EURid vzw\n        Language: en\n        Email: tech@eurid.eu\n\nRegistrar:\n        Name: EURid vzw\n        Website: https://www.eurid.eu\n\nName servers:\n        ns3.eurid.eu (185.36.4.253)\n        ns3.eurid.eu (2001:67c:9c:3937::253)\n        nsx.eurid.eu (185.151.141.1)\n        nsx.eurid.eu (2a02:568:fe00::6575)\n        ns1.eurid.eu (2001:67c:9c:3937::252)\n        ns1.eurid.eu (185.36.4.252)\n        ns2.eurid.eu (2001:67c:40:3937::252)\n        ns2.eurid.eu (185.36.6.252)\n        ns4.eurid.eu (2001:67c:40:3937::253)\n        ns4.eurid.eu (185.36.6.253)\n        nsp.netnod.se\n\nKeys:\n        flags:KSK protocol:3 algorithm:RSA_SHA256 pubKey:AwEAAcOQldGtC33GLx8s335UscKMPlWjDXCqbhR2QyAYcfS4CZS6YHg3A1Zz/K3VurTZF68aSaRkNupZuEgt4jozE3v4+t+2qOfiATvoOCrf74hWduBPwk9Go0z7FVlDkok1/qMQmqOtih8TFP85b+w6F/uyLMZS1JowMDUzRurmHJVoT4lW9+OCdrhuQFK9vU24Y8BmacoRy6mWBCFlysizlOIodwmquOf5A+3Nz0B3TLCK4fIYJYVxCUVlpRJ7uaBS+GLD7afuxkEesReYHgPWZFSDMbXk9Ugh+qUi8tEKKFls9TM3lK9BPBcciXUhI1bRJSHftqcNpMmLqg/79SwoWGc=\n\nPlease visit www.eurid.eu for more info."
  },
  {
    "path": "test/samples/whois/google.ai",
    "content": "Domain Name: google.ai\nRegistry Domain ID: 6eddd132ab114b12bd2bd4cf9c492a04-DONUTS\nRegistrar WHOIS Server: whois.markmonitor.com\nRegistrar URL: http://www.markmonitor.com\nUpdated Date: 2025-01-23T22:17:03Z\nCreation Date: 2017-12-16T05:37:20Z\nRegistry Expiry Date: 2025-09-25T05:37:20Z\nRegistrar: MarkMonitor Inc.\nRegistrar IANA ID: 292\nRegistrar Abuse Contact Email: abusecomplaints@markmonitor.com\nRegistrar Abuse Contact Phone: +1.2083895740\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nRegistry Registrant ID: 93b24aca40c6451785c486627aa03267-DONUTS\nRegistrant Name: Domain Administrator\nRegistrant Organization: Google LLC\nRegistrant Street: 1600 Amphitheatre Parkway\nRegistrant City: Mountain View\nRegistrant State/Province: CA\nRegistrant Postal Code: 94043\nRegistrant Country: US\nRegistrant Phone: +1.6502530000\nRegistrant Phone Ext:\nRegistrant Fax: +1.6502530001\nRegistrant Fax Ext:\nRegistrant Email: dns-admin@google.com\nRegistry Admin ID: 93b24aca40c6451785c486627aa03267-DONUTS\nAdmin Name: Domain Administrator\nAdmin Organization: Google LLC\nAdmin Street: 1600 Amphitheatre Parkway\nAdmin City: Mountain View\nAdmin State/Province: CA\nAdmin Postal Code: 94043\nAdmin Country: US\nAdmin Phone: +1.6502530000\nAdmin Phone Ext:\nAdmin Fax: +1.6502530001\nAdmin Fax Ext:\nAdmin Email: dns-admin@google.com\nRegistry Tech ID: 93b24aca40c6451785c486627aa03267-DONUTS\nTech Name: Domain Administrator\nTech Organization: Google LLC\nTech Street: 1600 Amphitheatre Parkway\nTech City: Mountain View\nTech State/Province: CA\nTech Postal Code: 94043\nTech Country: US\nTech Phone: +1.6502530000\nTech Phone Ext:\nTech Fax: +1.6502530001\nTech Fax Ext:\nTech Email: dns-admin@google.com\nName Server: ns2.zdns.google\nName Server: ns3.zdns.google\nName Server: ns4.zdns.google\nName Server: ns1.zdns.google\nDNSSEC: unsigned"
  },
  {
    "path": "test/samples/whois/google.at",
    "content": "% Copyright (c)2019 by NIC.AT (1)\n%\n% Restricted rights.\n%\n% Except  for  agreed Internet  operational  purposes, no  part  of this\n% information  may  be reproduced,  stored  in  a  retrieval  system, or\n% transmitted, in  any  form  or by  any means,  electronic, mechanical,\n% recording, or otherwise, without prior  permission of NIC.AT on behalf\n% of itself and/or the copyright  holders.  Any use of this  material to\n% target advertising  or similar activities is explicitly  forbidden and\n% can be prosecuted.\n%\n% It is furthermore strictly forbidden to use the Whois-Database in such\n% a  way  that  jeopardizes or  could jeopardize  the  stability  of the\n% technical  systems of  NIC.AT  under any circumstances. In particular,\n% this includes  any misuse  of the  Whois-Database and  any  use of the\n% Whois-Database which disturbs its operation.\n%\n% Should the  user violate  these points,  NIC.AT reserves  the right to\n% deactivate  the  Whois-Database   entirely  or  partly  for  the user.\n% Moreover,  the  user  shall be  held liable  for  any  and all  damage\n% arising from a violation of these points.\ndomain:         google.at\nregistrar:      MarkMonitor Inc. ( https://nic.at/registrar/434 )\nregistrant:     GI7803022-NICAT\ntech-c:         GI1919751-NICAT\ntech-c:         GI7803025-NICAT\nnserver:        ns1.google.com\nremarks:        216.239.32.10\nnserver:        ns2.google.com\nremarks:        216.239.34.10\nnserver:        ns3.google.com\nremarks:        216.239.36.10\nnserver:        ns4.google.com\nremarks:        216.239.38.10\nchanged:        20110426 17:57:27\nsource:         AT-DOM\npersonname:     DNS Admin\norganization:   Google Inc.\nstreet address: 1600 Amphitheatre Parkway\npostal code:    94043\ncity:           Mountain View\ncountry:        United States\nphone:          +16502530000\nfax-no:         +16502530001\ne-mail:         dns-admin@google.com\nnic-hdl:        GI7803022-NICAT\nchanged:        20110111 00:07:31\nsource:         AT-DOM\npersonname:\norganization:   Google Inc.\nstreet address: 1600 Amphitheatre Parkway\npostal code:    USA-94043\ncity:           Mountain View, CA\ncountry:        United States\nphone:          +16506234000\nfax-no:         +16506188571\ne-mail:         dns-admin@google.com\nnic-hdl:        GI1919751-NICAT\nchanged:        20050617 21:36:20\nsource:         AT-DOM\npersonname:     DNS Admin\norganization:   Google Inc.\nstreet address: 1600 Amphitheatre Parkway\npostal code:    94043\ncity:           Mountain View\ncountry:        United States\nphone:          +16502530000\nfax-no:         +16502530001\ne-mail:         dns-admin@google.com\nnic-hdl:        GI7803025-NICAT\nchanged:        20110111 00:08:30\nsource:         AT-DOM\n"
  },
  {
    "path": "test/samples/whois/google.cl",
    "content": "%%\n%% This is the NIC Chile Whois server (whois.nic.cl).\n%%\n%% Rights restricted by copyright.\n%% See https://www.nic.cl/normativa/politica-publicacion-de-datos-cl.pdf\n%%\nDomain name: google.cl\nRegistrant name: Google Inc.\nRegistrant organisation:\nRegistrar name: MarkMonitor Inc.\nRegistrar URL: https://markmonitor.com/\nCreation date: 2002-10-22 17:48:23 CLST\nExpiration date: 2019-11-20 14:48:02 CLST\nName server: ns1.google.com\nName server: ns2.google.com\nName server: ns3.google.com\nName server: ns4.google.com\n%%\n%% For communication with domain contacts please use website.\n%% See https://www.nic.cl/registry/Whois.do?d=google.cl\n%%"
  },
  {
    "path": "test/samples/whois/google.co.cr",
    "content": "%  *The information provided by WHOIS is supplied by NIC Costa Rica's database of registered domains. This option has the sole intention of showing information about the domains registered under the CR Top level domain for name assignation purposes. It is absolutely forbidden to collect, store, use or transmit any information displayed by WHOIS for commercial and advertising purposes without prior notice to the persons involved and to NIC Costa Rica. NIC Costa Rica does not guarantee the accuracy of the information displayed by this option. Since it is provided by the contacts, the accuracy is their responsibility. The National Academy of Sciences is not liable for the use of the information here revealed. The National Academy of Sciences undertakes to comply with the terms set forth in the Data Protection laws of the Republic of Costa Rica and therefore protects the data collected from NIC Costa Rica users, regardless of whether they are Costa Rican citizens or not. If you are a contact of a .cr domain name and wish to use the WHOIS Privacy service, select this option in \"Edit account\" once your login with your username and password, or access the following link:\n% https://www.nic.cr/iniciar-sesion/?next=/my-account/\n%\n%\n% *La información mostrada a través de la opción WHOIS es provista de la base de datos de los dominios registrados en NIC Costa Rica. Esta opción tiene el propósito exclusivo de mostrar información sobre los dominios registrados bajo el Dominio Superior .CR para los fines de la delegación de los nombs. Queda absolutamente prohibido compilar, almacenar, usar y/o trasmitir la información mostrada mediante la opción WHOIS para fines comerciales y publicitarios, sin la previa autorización de los afectados y de NIC Costa Rica. NIC Costa Rica no garantiza la exactitud de la información desplegada mediante esta opción, ya que ésta proviene de los contactos, y su veracidad es responsabilidad de estos últimos. La Academia Nacional de Ciencias no se responsabiliza por el uso que se le dé a la información aquí mostrada. La Academia Nacional de Ciencias se compromete a cumplir con los términos establecidos en las leyes de Protección de Datos de la República de Costa Rica y por lo tanto protege los datos recolectados de todos los usuarios de NIC Costa Rica que sean ciudadanos o no de la República de Costa Rica. Si un contacto de un dominio .cr desea hacer uso del servicio de Privacidad WHOIS puede escoger esta opción en \"Editar cuenta\" con su usuario y clave, o ingresar al siguiente link:\n% https://www.nic.cr/iniciar-sesion/?next=/mi-cuenta/\n%\n% Whoisd Server Version: 3.10.2\n% Timestamp: Tue Apr 16 06:51:27 2019\ndomain:       google.co.cr\nregistrant:   CON-66\nadmin-c:      CON-66\nnsset:        GOOGLE_CO_CR\nregistrar:    NIC-REG1\nstatus:       Deletion forbidden\nstatus:       Sponsoring registrar change forbidden\nstatus:       Update forbidden\nstatus:       Administratively blocked\nstatus:       Registrant change forbidden\nregistered:   18.04.2002 18:00:00\nchanged:      28.02.2017 06:39:42\nexpire:       17.04.2020\ncontact:      CON-66\norg:          MarkMonitor Inc.\nname:         MarkMonitor Inc\naddress:      3540 East Longwing Lane, Suite 300\naddress:      Meridian\naddress:      83646\naddress:      Idaho\naddress:      US\nphone:        +1.2083895740\nfax-no:       +1.2083895771\ne-mail:       ccops@markmonitor.com\nregistrar:    NIC-REG1\ncreated:      03.06.2011 16:22:36\nchanged:      28.03.2019 03:49:37\nnsset:        GOOGLE_CO_CR\nnserver:      ns1.google.com\nnserver:      ns2.google.com\nnserver:      ns3.google.com\nnserver:      ns4.google.com\ntech-c:       CON-66\nregistrar:    NIC-REG1\ncreated:      03.06.2011 12:51:41\nchanged:      30.03.2016 10:37:14\n"
  },
  {
    "path": "test/samples/whois/google.co.id",
    "content": "# whois.id\n\nDomain Name: GOOGLE.CO.ID\nRegistry Domain ID: 166626_DOMAIN_ID-ID\nRegistrar WHOIS Server:\nRegistrar URL: www.digitalregistra.co.id\nUpdated Date: 2025-08-05T05:00:20Z\nCreation Date: 2004-12-18T13:33:21Z\nRegistry Expiry Date: 2026-09-01T23:59:59Z\nRegistrar: PT Digital Registra Indonesia\nRegistrar IANA ID: 1\nRegistrar Abuse Contact Email: info@digitalregistra.co.id\nRegistrar Abuse Contact Phone:\nDomain Status: clientDeleteProhibited\nDomain Status: clientRenewProhibited\nDomain Status: clientTransferProhibited\nDomain Status: clientUpdateProhibited\nDomain Status: serverDeleteProhibited\nDomain Status: serverRenewProhibited\nDomain Status: serverTransferProhibited\nDomain Status: serverUpdateProhibited\nName Server: NS1.GOOGLE.COM\nName Server: NS2.GOOGLE.COM\nName Server: NS3.GOOGLE.COM\nName Server: NS4.GOOGLE.COM\nDNSSEC: unsigned\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2025-10-16T19:03:31Z <<<\n"
  },
  {
    "path": "test/samples/whois/google.co.il",
    "content": "% The data in the WHOIS database of the .il registry is provided\n% by ISOC-IL for information purposes, and to assist persons in\n% obtaining information about or related to a domain name\n% registration record. ISOC-IL does not guarantee its accuracy.\n% By submitting a WHOIS query, you agree that you will use this\n% Data only for lawful purposes and that, under no circumstances\n% will you use this Data to: (1) allow, enable, or otherwise\n% support the transmission of mass unsolicited, commercial\n% advertising or solicitations via e-mail (spam);\n% or  (2) enable high volume, automated, electronic processes that\n% apply to ISOC-IL (or its systems).\n% ISOC-IL reserves the right to modify these terms at any time.\n% By submitting this query, you agree to abide by this policy.\n\nquery:        google.co.il\n\nreg-name:     google\ndomain:       google.co.il\n\ndescr:        Google LLC.\ndescr:        1600 Amphitheatre Parkway\ndescr:        Mountain View CA\ndescr:        94043\ndescr:        USA\nphone:        +1 650 3300100\nfax-no:       +1 650 6188571\ne-mail:       dns-admin AT google.com\nadmin-c:      DT-DA20915-IL\ntech-c:       DT-DA19919-IL\nzone-c:       DT-DA19919-IL\nnserver:      ns1.google.com\nnserver:      ns2.google.com\nnserver:      ns3.google.com\nnserver:      ns4.google.com\nassigned:     05-06-1999\nvalidity:     05-06-2026\nDNSSEC:       unsigned\nstatus:       Transfer Locked\nchanged:      registrar AT ns.il 19990605 (Assigned)\nchanged:      domain-registrar AT isoc.org.il 20020926 (Changed)\nchanged:      domain-registrar AT isoc.org.il 20050706 (Changed)\nchanged:      domain-registrar AT isoc.org.il 20070118 (Changed)\nchanged:      domain-registrar AT isoc.org.il 20170517 (Transferred)\nchanged:      domain-registrar AT isoc.org.il 20170517 (Changed)\nchanged:      domain-registrar AT isoc.org.il 20181216 (Changed)\nchanged:      domain-registrar AT isoc.org.il 20181216 (Changed)\n\nperson:       Domain admin\naddress      Google Inc.\naddress      1600 Amphitheatre Parkway\naddress      Mountain View CA\naddress      94043\naddress      USA\nphone:        +1 650 3300100\nfax-no:       +1 650 6188571\ne-mail:       ccops AT markmonitor.com\nnic-hdl:      DT-DA20915-IL\nchanged:      Managing Registrar 20170329\n\nperson:       Domain Admin\naddress      MarkMonitor Inc.\naddress      3540 E Longwing Lane Suite 300\naddress      Meridian ID\naddress      83646\naddress      USA\nphone:        +1 208 3895740\nfax-no:       +1 208 3895771\ne-mail:       ccops AT markmonitor.com\nnic-hdl:      DT-DA19919-IL\nchanged:      Managing Registrar 20161005\nchanged:      Managing Registrar 20170816\n\nregistrar name: Domain The Net Technologies Ltd\nregistrar info: https://www.domainthenet.com\n\n% Rights to the data above are restricted by copyright.\n"
  },
  {
    "path": "test/samples/whois/google.co.ve",
    "content": "Servidor Whois del Centro de Información de Red de Venezuela (NIC.VE)\n\nEste servidor contiene información autoritativa exclusivamente de dominios .VE\nCualquier consulta sobre este servicio, puede hacerla al correo electrónico whois@nic.ve\n\nTitular:\nGoogle Inc. \t\tdns-admin@google.com\n   Google Inc\n   1600 Amphitheatre Parkway\n   Mountain View, CA  US\n   +1.6502530000\n\n   Nombre de Dominio: google.co.ve\n\n   Contacto Administrativo:\n      DNS Admin \t\tdns-admin@google.com\n      Google Inc.\n      1600 Amphitheatre Parkway\n      Mountain View, CA, CA  UNITED STATES\n      +1.6502530000 (FAX) +16506181499\n\n   Contacto Técnico:\n      DNS Admin \t\tdns-admin@google.com\n      Google Inc.\n      1600 Amphitheatre Parkway\n      Mountain View, CA, CA  UNITED STATES\n      +1.6502530000 (FAX) +16506181499\n\n   Contacto de Cobranza:\n      Domain Administrator\t\tVenezueladomains2@markmonitor.com\n      Markmonitor, Inc.\n      391 N. Ancestor Place\n      Boise ID  US\n      1-1 - 2083895740 (FAX) 1 - 2083895740\n\n   Fecha de Vencimiento: 2018-03-06 00:00:00\n   Ultima Actualización: 2005-11-17 20:35:01\n   Fecha de Creación: 2003-03-06 00:00:00\n\n   Estatus del dominio: ACTIVO\n\n   Servidor(es) de Nombres de Dominio:\n\n   - ns1.google.com\n   - ns2.google.com\n   - ns3.google.com\n   - ns4.google.com\n\nNIC-Venezuela - CONATEL\nhttp://www.nic.ve\n"
  },
  {
    "path": "test/samples/whois/google.com",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Server Name: GOOGLE.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM\n   IP Address: 69.41.185.195\n   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM\n   Whois Server: whois.itsyourdomain.com\n   Referral URL: http://www.itsyourdomain.com\n\n   Server Name: GOOGLE.COM.ZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM\n   IP Address: 217.107.217.167\n   Registrar: ONLINENIC, INC.\n   Whois Server: whois.35.com\n   Referral URL: http://www.OnlineNIC.com\n\n   Server Name: GOOGLE.COM.YAHOO.COM.MYSPACE.COM.YOUTUBE.COM.FACEBOOK.COM.THEYSUCK.DNSABOUT.COM\n   IP Address: 72.52.190.30\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n\n   Server Name: GOOGLE.COM.WORDT.DOOR.VEEL.WHTERS.GEBRUIKT.SERVERTJE.NET\n   IP Address: 62.41.27.144\n   Registrar: KEY-SYSTEMS GMBH\n   Whois Server: whois.rrpproxy.net\n   Referral URL: http://www.key-systems.net\n\n   Server Name: GOOGLE.COM.VN\n   Registrar: ONLINENIC, INC.\n   Whois Server: whois.35.com\n   Referral URL: http://www.OnlineNIC.com\n\n   Server Name: GOOGLE.COM.UY\n   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM\n   Whois Server: whois.PublicDomainRegistry.com\n   Referral URL: http://www.PublicDomainRegistry.com\n\n   Server Name: GOOGLE.COM.UA\n   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM\n   Whois Server: whois.PublicDomainRegistry.com\n   Referral URL: http://www.PublicDomainRegistry.com\n\n   Server Name: GOOGLE.COM.TW\n   Registrar: WEB COMMERCE COMMUNICATIONS LIMITED DBA WEBNIC.CC\n   Whois Server: whois.webnic.cc\n   Referral URL: http://www.webnic.cc\n\n   Server Name: GOOGLE.COM.TR\n   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM\n   Whois Server: whois.PublicDomainRegistry.com\n   Referral URL: http://www.PublicDomainRegistry.com\n\n   Server Name: GOOGLE.COM.SUCKS.FIND.CRACKZ.WITH.SEARCH.GULLI.COM\n   IP Address: 80.190.192.24\n   Registrar: EPAG DOMAINSERVICES GMBH\n   Whois Server: whois.enterprice.net\n   Referral URL: http://www.enterprice.net\n\n   Server Name: GOOGLE.COM.SPROSIUYANDEKSA.RU\n   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE\n   Whois Server: whois.melbourneit.com\n   Referral URL: http://www.melbourneit.com\n\n   Server Name: GOOGLE.COM.SERVES.PR0N.FOR.ALLIYAH.NET\n   IP Address: 84.255.209.69\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n\n   Server Name: GOOGLE.COM.SA\n   Registrar: OMNIS NETWORK, LLC\n   Whois Server: whois.omnis.com\n   Referral URL: http://domains.omnis.com\n\n   Server Name: GOOGLE.COM.PLZ.GIVE.A.PR8.TO.AUDIOTRACKER.NET\n   IP Address: 213.251.184.30\n   Registrar: OVH\n   Whois Server: whois.ovh.com\n   Referral URL: http://www.ovh.com\n\n   Server Name: GOOGLE.COM.MX\n   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM\n   Whois Server: whois.PublicDomainRegistry.com\n   Referral URL: http://www.PublicDomainRegistry.com\n\n   Server Name: GOOGLE.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET\n   IP Address: 217.148.161.5\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: GOOGLE.COM.IS.HOSTED.ON.PROFITHOSTING.NET\n   IP Address: 66.49.213.213\n   Registrar: NAME.COM LLC\n   Whois Server: whois.name.com\n   Referral URL: http://www.name.com\n\n   Server Name: GOOGLE.COM.IS.APPROVED.BY.NUMEA.COM\n   IP Address: 213.228.0.43\n   Registrar: GANDI SAS\n   Whois Server: whois.gandi.net\n   Referral URL: http://www.gandi.net\n\n   Server Name: GOOGLE.COM.HAS.LESS.FREE.PORN.IN.ITS.SEARCH.ENGINE.THAN.SECZY.COM\n   IP Address: 209.187.114.130\n   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM\n   Whois Server: whois.itsyourdomain.com\n   Referral URL: http://www.itsyourdomain.com\n\n   Server Name: GOOGLE.COM.DO\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n\n   Server Name: GOOGLE.COM.COLLEGELEARNER.COM\n   IP Address: 72.14.207.99\n   IP Address: 64.233.187.99\n   IP Address: 64.233.167.99\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n\n   Server Name: GOOGLE.COM.CO\n   Registrar: NAMESECURE.COM\n   Whois Server: whois.namesecure.com\n   Referral URL: http://www.namesecure.com\n\n   Server Name: GOOGLE.COM.BR\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: GOOGLE.COM.BEYONDWHOIS.COM\n   IP Address: 203.36.226.2\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: GOOGLE.COM.AU\n   Registrar: PLANETDOMAIN PTY LTD.\n   Whois Server: whois.planetdomain.com\n   Referral URL: http://www.planetdomain.com\n\n   Server Name: GOOGLE.COM.ACQUIRED.BY.CALITEC.NET\n   IP Address: 85.190.27.2\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Domain Name: GOOGLE.COM\n   Registrar: MARKMONITOR INC.\n   Whois Server: whois.markmonitor.com\n   Referral URL: http://www.markmonitor.com\n   Name Server: NS1.GOOGLE.COM\n   Name Server: NS2.GOOGLE.COM\n   Name Server: NS3.GOOGLE.COM\n   Name Server: NS4.GOOGLE.COM\n   Status: clientDeleteProhibited\n   Status: clientTransferProhibited\n   Status: clientUpdateProhibited\n   Updated Date: 10-apr-2006\n   Creation Date: 15-sep-1997\n   Expiration Date: 14-sep-2011\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:39:39 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.\nMarkMonitor.com - The Leader in Corporate Domain Management\n----------------------------------------------------------\nFor Global Domain Consolidation, Research & Intelligence,\nand Enterprise DNS, go to: www.markmonitor.com\n----------------------------------------------------------\n\nThe Data in MarkMonitor.com's WHOIS database is provided by MarkMonitor.com\nfor information purposes, and to assist persons in obtaining information\nabout or related to a domain name registration record.  MarkMonitor.com\ndoes not guarantee its accuracy.  By submitting a WHOIS query, you agree\nthat you will use this Data only for lawful purposes and that, under no\ncircumstances will you use this Data to: (1) allow, enable, or otherwise\nsupport the transmission of mass unsolicited, commercial advertising or\nsolicitations via e-mail (spam); or  (2) enable high volume, automated,\nelectronic processes that apply to MarkMonitor.com (or its systems).\nMarkMonitor.com reserves the right to modify these terms at any time.\nBy submitting this query, you agree to abide by this policy.\n\nRegistrant:\n        Dns Admin\n        Google Inc.\n        Please contact contact-admin@google.com 1600 Amphitheatre Parkway\n         Mountain View CA 94043\n        US\n        dns-admin@google.com +1.6502530000 Fax: +1.6506188571\n\n    Domain Name: google.com\n\n        Registrar Name: Markmonitor.com\n        Registrar Whois: whois.markmonitor.com\n        Registrar Homepage: http://www.markmonitor.com\n\n    Administrative Contact:\n        DNS Admin\n        Google Inc.\n        1600 Amphitheatre Parkway\n         Mountain View CA 94043\n        US\n        dns-admin@google.com +1.6506234000 Fax: +1.6506188571\n    Technical Contact, Zone Contact:\n        DNS Admin\n        Google Inc.\n        2400 E. Bayshore Pkwy\n         Mountain View CA 94043\n        US\n        dns-admin@google.com +1.6503300100 Fax: +1.6506181499\n\n    Created on..............: 1997-09-15.\n    Expires on..............: 2011-09-13.\n    Record last updated on..: 2008-06-08.\n\n    Domain servers in listed order:\n\n    ns4.google.com\n    ns3.google.com\n    ns2.google.com\n    ns1.google.com\n    \n\nMarkMonitor.com - The Leader in Corporate Domain Management\n----------------------------------------------------------\nFor Global Domain Consolidation, Research & Intelligence,\nand Enterprise DNS, go to: www.markmonitor.com\n----------------------------------------------------------\n--\n"
  },
  {
    "path": "test/samples/whois/google.com.br",
    "content": "% Copyright (c) Nic.br\n%  The use of the data below is only permitted as described in\n%  full by the terms of use at https://registro.br/termo/en.html ,\n%  being prohibited its distribution, commercialization or\n%  reproduction, in particular, to use it for advertising or\n%  any similar purpose.\n%  2019-04-19T03:22:06-03:00\n\ndomain:      google.com.br\nowner:       Google Brasil Internet Ltda\nownerid:     06.990.590/0001-23\nresponsible: Domain Administrator\ncountry:     BR\nowner-c:     DOADM17\nadmin-c:     DOADM17\ntech-c:      DOADM17\nbilling-c:   NAB51\nnserver:     ns1.google.com\nnsstat:      20190418 AA\nnslastaa:    20190418\nnserver:     ns2.google.com\nnsstat:      20190418 AA\nnslastaa:    20190418\nnserver:     ns3.google.com\nnsstat:      20190418 AA\nnslastaa:    20190418\nnserver:     ns4.google.com\nnsstat:      20190418 NOT SYNC ZONE\nnslastaa:    20190418\ncreated:     19990518 #162310\nchanged:     20190417\nexpires:     20200518\nstatus:      published\n\nnic-hdl-br:  DOADM17\nperson:      Domain Admin\ne-mail:      ccops@markmonitor.com\ncountry:     BR\ncreated:     20100520\nchanged:     20180324\n\nnic-hdl-br:  NAB51\nperson:      NameAction do Brasil\ne-mail:      mail@nameaction.com\ncountry:     BR\ncreated:     20020619\nchanged:     20181011\n\n% Security and mail abuse issues should also be addressed to\n% cert.br, http://www.cert.br/ , respectivelly to cert@cert.br\n% and mail-abuse@cert.br\n%\n% whois.registro.br accepts only direct match queries. Types\n% of queries are: domain (.br), registrant (tax ID), ticket,\n% provider, contact handle (ID), CIDR block, IP and ASN."
  },
  {
    "path": "test/samples/whois/google.com.pe",
    "content": "Domain Name: google.com.pe\nWHOIS Server: NIC .PE\nSponsoring Registrar: MarkMonitor Inc.\nDomain Status: clientTransferProhibited\nDomain Status: clientDeleteProhibited\nDomain Status: clientUpdateProhibited\nRegistrant Name: Google LLC\nAdmin Name: Google LLC\nAdmin Email: dns-admin@google.com\nName Server: ns1.google.com\nName Server: ns2.google.com\nName Server: ns3.google.com\nName Server: ns4.google.com\nDNSSEC: unsigned\n>>> Last update of WHOIS database: 2019-04-18T05:53:50.968Z <<<\n\nTERMS OF USE: You are not authorized to access or query our Whois\ndatabase through the use of electronic processes that are high-volume and\nautomated.  Whois database is provided as a service to the internet\ncommunity.\n\nThe data is for information purposes only. Red Cientifica Peruana does not\nguarantee its accuracy. By submitting a Whois query, you agree to abide\nby the following terms of use: You agree that you may use this Data only\nfor lawful purposes and that under no circumstances will you use this Data\nto: (1) allow, enable, or otherwise support the transmission of mass\nunsolicited, commercial advertising or solicitations via e-mail, telephone,\nor facsimile; or (2) enable high volume, automated, electronic processes.\n\nThe compilation, repackaging, dissemination or other use of this Data is\nexpressly prohibited.\n"
  },
  {
    "path": "test/samples/whois/google.com.sa",
    "content": "% SaudiNIC Whois server.\n% Rights restricted by copyright.\n% http://nic.sa/en/view/whois-cmd-copyright\n\nDomain Name: google.com.sa\n\n Registrant:\n Google Inc. قوقل انك\n Address: 1600 Amphitheatre Parkway\n  Mountain View\n United States\n\n Administrative Contact:\n  Maan Al Khen\n  Address: Riyadh Olia\n  11423 Riyadh\n  Saudi Arabia\n\n Technical Contact:\n  Domain Administrator\n  Address: 3540 East Longwing Lane Suite 300\n  83646 Idaho\n  United States\n\n Name Servers:\n  ns1.google.com\n  ns2.google.com\n  ns4.google.com\n  ns3.google.com\n\nCreated on: 2004-01-11\nLast Updated on: 2019-02-06"
  },
  {
    "path": "test/samples/whois/google.com.sg",
    "content": "Domain Name: google.com.sg\nUpdated Date: 2024-06-03T09:54:56Z\nCreation Date: 2002-07-05T09:42:32Z\nRegistry Expiry Date: 2025-07-04T16:00:00Z\nRegistrar: MarkMonitor Inc.\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nVerifiedID Status: VerifiedID@SG-Not Required\nRegistry Lock:\nRegistrant Name: GOOGLE LLC\nAdmin Name: MARKMONITOR INC.\nTech Name: GOOGLE LLC\nTech Email: dns-admin@google.com\nName Server: ns1.google.com\nName Server: ns2.google.com\nDNSSEC: unsigned\n>>> Last update of WHOIS database: 2024-06-18T01:45:41Z <<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\n% ----------------------------------------------------------------------\n% SGNIC WHOIS Server\n% ----------------------------------------------------------------------\n%\n% This data is provided for information purposes only.\n"
  },
  {
    "path": "test/samples/whois/google.com.tr",
    "content": "** Domain Name: google.com.tr\n\n** Registrant:\n   Google LLC\n   1600 Amphitheatre Parkway\n   Mountain View\n   Out of Turkey,\n     United States of America\n   dns-admin@google.com\n   + 1-650-2530000-\n   + 1-650-2530001-\n\n\n** Administrative Contact:\nNIC Handle\t\t: mi154-metu\nOrganization Name\t: MarkMonitor, Inc\nAddress\t\t\t: Hidden upon user request\nPhone\t\t\t: Hidden upon user request\nFax\t\t\t: Hidden upon user request\n\n\n** Technical Contact:\nNIC Handle\t\t: btl1-metu\nOrganization Name\t: Beril Teknoloji Bili�im Yay�nc�l�k Ticaret A.�.\nAddress\t\t\t: Hidden upon user request\nPhone\t\t\t: Hidden upon user request\nFax\t\t\t: Hidden upon user request\n\n\n** Billing Contact:\nNIC Handle\t\t: btl1-metu\nOrganization Name\t: Beril Teknoloji Bili�im Yay�nc�l�k Ticaret A.�.\nAddress\t\t\t: Hidden upon user request\nPhone\t\t\t: Hidden upon user request\nFax\t\t\t: Hidden upon user request\n\n\n** Domain Servers:\nns1.google.com\nns2.google.com\nns3.google.com\nns4.google.com\n\n** Additional Info:\nCreated on..............: 2001-Aug-23.\nExpires on..............: 2019-Aug-22."
  },
  {
    "path": "test/samples/whois/google.com.tw",
    "content": "Domain Name: google.com.tw\n   Domain Status: clientUpdateProhibited,clientTransferProhibited,clientDeleteProhibited\n   Registrant:\n      Google Inc.\n      DNS Admin  dns-admin@google.com\n      +1.6502530000\n      +1.6506188571\n      1600 Amphitheatre Parkway\n      Mountain View, CA\n      US\n\n   Administrative Contact:\n      DNS Admin  dns-admin@google.com\n      +1.6502530000\n      +1.6506188571\n\n   Technical Contact:\n      DNS Admin  dns-admin@google.com\n      +1.6502530000\n      +1.6506188571\n\n   Record expires on 2019-11-09 (YYYY-MM-DD)\n   Record created on 2000-08-29 (YYYY-MM-DD)\n\n   Domain servers in listed order:\n      ns1.google.com\n      ns2.google.com\n      ns3.google.com\n      ns4.google.com\n\nRegistration Service Provider: Markmonitor, Inc.\nRegistration Service URL: http://www.markmonitor.com/\n\n[Provided by NeuStar Registry Gateway Services]"
  },
  {
    "path": "test/samples/whois/google.com.ua",
    "content": "% Request from 80.254.2.190\n% This is the Ukrainian Whois query server #F.\n% The Whois is subject to Terms of use\n% See https://hostmaster.ua/services/\n%\n% IN THE PROCESS OF DELEGATION OF A DOMAIN NAME,\n% THE REGISTRANT IS AN ENTITY WHO USES AND MANAGES A CERTAIN DOMAIN NAME,\n% AND THE REGISTRAR IS A BUSINESS ENTITY THAT PROVIDES THE REGISTRANT\n% WITH THE SERVICES NECESSARY FOR THE TECHNICAL MAINTENANCE OF THE REGISTRATION AND OPERATION OF THE DOMAIN NAME.\n% FOR INFORMATION ABOUT THE REGISTRANT OF THE DOMAIN NAME, YOU SHOULD CONTACT THE REGISTRAR.\n\ndomain:           google.com.ua\ndom-public:       NO\nmnt-by:           ua.markmonitor\nnserver:          ns3.google.com\nnserver:          ns1.google.com\nnserver:          ns4.google.com\nnserver:          ns2.google.com\nstatus:           clientDeleteProhibited\nstatus:           clientTransferProhibited\nstatus:           clientUpdateProhibited\ncreated:          2002-12-04 00:00:00+02\nmodified:         2018-11-02 11:29:08+02\nexpires:          2019-12-04 00:00:00+02\nsource:           UAEPP\n\n% Registrar:\n% ==========\nregistrar:        ua.markmonitor\norganization:     MarkMonitor Inc.\norganization-loc: MarkMonitor Inc.\nurl:              http://markmonitor.com\ncity:             Meridian, Idaho\ncountry:          US\nabuse-email:      abusecomplaints@markmonitor.com\nabuse-postal:     83646 Meridian, Idaho 3540 East Longwing Lane, suite 300\nsource:           UAEPP\n\n% Registrant:\n% ===========\nperson:           n/a\nperson-loc:       DNS Admin\norganization-loc: Google Inc.\ne-mail:           dns-admin@google.com\naddress:          n/a\naddress-loc:      1600 Amphitheatre Parkway\naddress-loc:      CA\naddress-loc:      Mountain View\npostal-code-loc:  94043\ncountry-loc:      US\nphone:            +1.6502530000\nfax:              +1.6502530001\nmnt-by:           ua.markmonitor\nstatus:           ok\nstatus:           linked\ncreated:          2017-07-28 23:53:31+03\nsource:           UAEPP\n\n\n% Administrative Contacts:\n% =======================\nperson:           n/a\nperson-loc:       DNS Admin\norganization-loc: Google Inc.\ne-mail:           dns-admin@google.com\naddress:          n/a\naddress-loc:      1600 Amphitheatre Parkway\naddress-loc:      CA\naddress-loc:      Mountain View\npostal-code-loc:  94043\ncountry-loc:      US\nphone:            +1.6502530000\nfax:              +1.6502530001\nmnt-by:           ua.markmonitor\nstatus:           ok\nstatus:           linked\ncreated:          2017-07-28 23:53:31+03\nsource:           UAEPP\n\n\n\n% Query time:     5 msec\n"
  },
  {
    "path": "test/samples/whois/google.de",
    "content": "% Restricted rights.\n%\n% Terms and Conditions of Use\n%\n% The above data may only be used within the scope of technical or\n% administrative necessities of Internet operation or to remedy legal\n% problems.\n% The use for other purposes, in particular for advertising, is not permitted.\n%\n% The DENIC whois service on port 43 doesn't disclose any information concerning\n% the domain holder, general request and abuse contact.\n% This information can be obtained through use of our web-based whois service\n% available at the DENIC website:\n% http://www.denic.de/en/domains/whois-service/web-whois.html\n%\n%\n\nDomain: google.de\nNserver: ns1.google.com\nNserver: ns2.google.com\nNserver: ns3.google.com\nNserver: ns4.google.com\nStatus: connect\nChanged: 2018-03-12T21:44:25+01:00\n"
  },
  {
    "path": "test/samples/whois/google.do",
    "content": "Domain Name: google.do\nWHOIS Server: whois.nic.do\nUpdated Date: 2019-02-07T17:54:31.560Z\nCreation Date: 2010-03-08T04:00:00.0Z\nRegistry Expiry Date: 2020-03-08T04:00:00.0Z\nDomain Status: ok https://icann.org/epp#ok\nRegistrar: Registrar NIC .DO (midominio.do)\nRegistrar Address: Av. R?mulo Betancourt 1108, La Julia   Apartado postal 2748, Santo Domingo\nRegistrar Country: DO\nRegistrar Phone: 8095350111\nRegistrar Fax: 8092860012\nRegistrar Customer Service Contact: info@nic.do\nRegistrar Customer Service Email: info@nic.do\nRegistrant ID: Redacted | EU Data Subject\nRegistrant Name: GOOGLE LLC\nRegistrant Organization: GOOGLE LLC\nRegistrant Street: Redacted | EU Data Subject\nRegistrant City: Redacted | EU Data Subject\nRegistrant State/Province: Redacted | EU Data Subject\nRegistrant Postal Code: Redacted | EU Data Subject\nRegistrant Country: Redacted | EU Data Subject\nRegistrant Phone: Redacted | EU Data Subject\nRegistrant Fax: Redacted | EU Data Subject\nRegistrant Email: Redacted | EU Data Subject\nAdmin ID: Redacted | EU Data Subject\nAdmin Name: Google LLC\nAdmin Organization: GOOGLE LLC\nAdmin Street: Redacted | EU Data Subject\nAdmin City: Redacted | EU Data Subject\nAdmin State/Province: Redacted | EU Data Subject\nAdmin Postal Code: Redacted | EU Data Subject\nAdmin Country: Redacted | EU Data Subject\nAdmin Phone: Redacted | EU Data Subject\nAdmin Fax: Redacted | EU Data Subject\nAdmin Email: Redacted | EU Data Subject\nBilling ID: Redacted | EU Data Subject\nBilling Name: MARKMONITOR\nBilling Organization: MARKMONITOR\nBilling Street: Redacted | EU Data Subject\nBilling Street: Redacted | EU Data Subject\nBilling City: Redacted | EU Data Subject\nBilling State/Province: Redacted | EU Data Subject\nBilling Postal Code: Redacted | EU Data Subject\nBilling Country: Redacted | EU Data Subject\nBilling Phone: Redacted | EU Data Subject\nBilling Fax: Redacted | EU Data Subject\nBilling Email: Redacted | EU Data Subject\nTech ID: Redacted | EU Data Subject\nTech Name: Google LLC\nTech Organization: Google LLC\nTech Street: Redacted | EU Data Subject\nTech City: Redacted | EU Data Subject\nTech State/Province: Redacted | EU Data Subject\nTech Postal Code: Redacted | EU Data Subject\nTech Country: Redacted | EU Data Subject\nTech Phone: Redacted | EU Data Subject\nTech Fax: Redacted | EU Data Subject\nTech Email: Redacted | EU Data Subject\nName Server: ns1.google.com\nName Server: ns2.google.com\nDNSSEC: unsigned\n>>> Last update of WHOIS database: 2019-04-16T13:27:25.387Z <<<\n\nTERMS OF USE: You are not authorized to access or query our WHOIS database through the use of electronic processes that are high-volume and automated.  This WHOIS database is provided by as a service to the internet community.\n\nThe data is for information purposes only. We do not guarantee its accuracy. By submitting a WHOIS query, you agree to abide by the following terms of use: You agree that you may use this Data only for lawful purposes and that under no circumstances will you use this Data to: (1) allow, enable, or otherwise support the transmission of mass unsolicited, commercial advertising or solicitations via e-mail, telephone, or facsimile; or (2) enable high volume, automated, electronic processes that apply to NIC.DO. The compilation, repackaging, dissemination or other use of this Data is expressly prohibited.\n"
  },
  {
    "path": "test/samples/whois/google.fr",
    "content": "%%\n%% This is the AFNIC Whois server.\n%%\n%% complete date format: YYYY-MM-DDThh:mm:ssZ\n%%\n%% Rights restricted by copyright.\n%% See https://www.afnic.fr/en/domain-names-and-support/everything-there-is-to-know-about-domain-names/find-a-domain-name-or-a-holder-using-whois/\n%%\n%%\n\ndomain:                        google.fr\nstatus:                        ACTIVE\neppstatus:                     serverUpdateProhibited\neppstatus:                     serverTransferProhibited\neppstatus:                     serverDeleteProhibited\neppstatus:                     serverRecoverProhibited\nhold:                          NO\nholder-c:                      GIHU100-FRNIC\nadmin-c:                       GIHU101-FRNIC\ntech-c:                        MI3669-FRNIC\nregistrar:                     MARKMONITOR Inc.\nExpiry Date:                   2026-12-30T17:16:48Z\ncreated:                       2000-07-26T22:00:00Z\nlast-update:                   2025-12-03T10:12:00.351952Z\nsource:                        FRNIC\n\nnserver:                       ns1.google.com\nnserver:                       ns2.google.com\nnserver:                       ns3.google.com\nnserver:                       ns4.google.com\nsource:                        FRNIC\n\nregistrar:                     MARKMONITOR Inc.\naddress:                       2150 S. Bonito Way, Suite 150\naddress:                       ID 83642 MERIDIAN\ncountry:                       US\nphone:                         +1.2083895740\nfax-no:                        +1.2083895771\ne-mail:                        registry.admin@markmonitor.com\nwebsite:                       http://www.markmonitor.com\nanonymous:                     No\nregistered:                    2002-01-07T00:00:00Z\nsource:                        FRNIC\n\nnic-hdl:                       GIHU100-FRNIC\ntype:                          ORGANIZATION\ncontact:                       Google Ireland Holdings Unlimited Company\naddress:                       Google Ireland Holdings Unlimited Company\naddress:                       70 Sir John Rogerson's Quay\naddress:                       2 Dublin\ncountry:                       IE\nphone:                         +353.14361000\ne-mail:                        dns-admin@google.com\nregistrar:                     MARKMONITOR Inc.\nchanged:                       2024-06-11T20:04:33.772976Z\nanonymous:                     NO\nobsoleted:                     NO\neppstatus:                     serverUpdateProhibited\neppstatus:                     associated\neligstatus:                    not identified\nreachstatus:                   not identified\nsource:                        FRNIC\n\nnic-hdl:                       GIHU101-FRNIC\ntype:                          ORGANIZATION\ncontact:                       Google Ireland Holdings Unlimited Company\naddress:                       70 Sir John Rogerson's Quay\naddress:                       2 Dublin\ncountry:                       IE\nphone:                         +353.14361000\ne-mail:                        dns-admin@google.com\nregistrar:                     MARKMONITOR Inc.\nanonymous:                     NO\nobsoleted:                     NO\neppstatus:                     associated\neppstatus:                     active\neligstatus:                    not identified\nreachstatus:                   ok\nreachmedia:                    email\nreachsource:                   REGISTRAR\nreachdate:                     2018-03-02T00:00:00Z\nsource:                        FRNIC\n\nnic-hdl:                       MI3669-FRNIC\ntype:                          ORGANIZATION\ncontact:                       MarkMonitor Inc.\naddress:                       2150 S. Bonito Way, Suite 150\naddress:                       83642 Meridian\ncountry:                       US\nphone:                         +1.2083895740\nfax-no:                        +1.2083895771\ne-mail:                        ccops@markmonitor.com\nregistrar:                     MARKMONITOR Inc.\nchanged:                       2026-02-05T20:37:17.379552Z\nanonymous:                     NO\nobsoleted:                     NO\neppstatus:                     associated\neppstatus:                     active\neligstatus:                    ok\neligsource:                    REGISTRAR\neligdate:                      2021-10-05T00:00:00Z\nreachstatus:                   ok\nreachmedia:                    email\nreachsource:                   REGISTRAR\nreachdate:                     2021-10-05T00:00:00Z\nsource:                        FRNIC\n\n>>> Last update of WHOIS database: 2026-02-06T17:22:17.219605Z <<<\n"
  },
  {
    "path": "test/samples/whois/google.hn",
    "content": "Domain Name: google.hn\nDomain ID: 801220-CoCCA\nWHOIS Server: whois.nic.hn\nUpdated Date: 2019-02-03T10:43:28.837Z\nCreation Date: 2003-03-07T05:00:00.0Z\nRegistry Expiry Date: 2020-03-07T05:00:00.0Z\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nRegistrar: MarkMonitor\nRegistrar URL: http://www.markmonitor.com\nRegistrant ID: 490793-CoCCA\nRegistrant Name: Google Inc.\nRegistrant Organization: Google Inc.\nRegistrant Street: 1600 Amphitheatre Parkway\nRegistrant City: Mountain View\nRegistrant State/Province: CA\nRegistrant Postal Code: 94043\nRegistrant Country: US\nRegistrant Phone: +1.6502530000\nRegistrant Fax: +1.6502530001\nRegistrant Email: dns-admin@google.com\nAdmin ID: 490793-CoCCA\nAdmin Name: Google Inc.\nAdmin Organization: Google Inc.\nAdmin Street: 1600 Amphitheatre Parkway\nAdmin City: Mountain View\nAdmin State/Province: CA\nAdmin Postal Code: 94043\nAdmin Country: US\nAdmin Phone: +1.6502530000\nAdmin Fax: +1.6502530001\nAdmin Email: dns-admin@google.com\nBilling ID: 857074-CoCCA\nBilling Name: CCOPs Provisioning\nBilling Organization: MarkMonitor\nBilling Street: 10400 Overland Rd PMB 155\nBilling City: Boise\nBilling State/Province: ID\nBilling Postal Code: 83709\nBilling Country: US\nBilling Phone: +1.2083895740\nBilling Fax: +1.2083895771\nBilling Email: ccops@markmonitor.com\nTech ID: 857074-CoCCA\nTech Name: CCOPs Provisioning\nTech Organization: MarkMonitor\nTech Street: 10400 Overland Rd PMB 155\nTech City: Boise\nTech State/Province: ID\nTech Postal Code: 83709\nTech Country: US\nTech Phone: +1.2083895740\nTech Fax: +1.2083895771\nTech Email: ccops@markmonitor.com\nName Server: ns1.google.com\nName Server: ns2.google.com\nDNSSEC: unsigned\n>>> Last update of WHOIS database: 2019-04-16T12:26:36.280Z <<<\n\nT?rminos de Uso: NIC.HN no se hace responsable por la veracidad de los datos proporcionados, ya que los mismos fueron proporcionados por los Registrantes y Usuarios del Servicio de Registro. La informaci?n desplegada ha sido proporcionada por el Administrador de Nombre de Dominio que corresponda, dicha informaci?n no es generada por NIC.HN.\n\nQueda absolutamente prohibido su uso para otros prop?sitos, incluyendo el env?o de Correos Electr?nicos no solicitados con fines publicitarios o de promoci?n de productos y servicios (SPAM) sin mediar la autorizaci?n de los afectados y de NIC.HN.\n\nLa base de datos generada a partir del sistema de delegaci?n, est? protegida por las leyes de Propiedad Intelectual y todos los tratados internacionales sobre la materia.\n\nSi necesita mayor informaci?n sobre los registros aqu? mostrados, favor de comunicarse a contacto@nic.hn\n"
  },
  {
    "path": "test/samples/whois/google.hu",
    "content": "% Whois server 4.0 serving the hu ccTLD\n\n\ndomain:         google.hu\nrecord created: 2000-03-03\nTovabbi adatokert ld.:\nhttps://www.domain.hu/domain-kereses/\nFor further data see:\nhttps://www.domain.hu/domain-search/\n"
  },
  {
    "path": "test/samples/whois/google.ie",
    "content": "# whois.weare.ie\n\nDomain Name: google.ie\nRegistry Domain ID: 762999-IEDR\nRegistrar WHOIS Server: whois.weare.ie\nRegistrar URL: http://www.eMarkmonitor.com\nUpdated Date: 2021-05-05T14:19:51Z\nCreation Date: 2002-03-21T00:00:00Z\nRegistry Expiry Date: 2022-03-21T14:13:27Z\nRegistrar: Markmonitor Inc\nRegistrar IANA ID: not applicable\nRegistrar Abuse Contact Email: abusecomplaints@markmonitor.com\nRegistrar Abuse Contact Phone: +1.2086851865\nDomain Status: serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\nDomain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited\nDomain Status: serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited\nRegistry Registrant ID: 379250-IEDR\nRegistrant Name: Google LLC\nRegistry Admin ID: 5672149-IEDR\nRegistry Tech ID: 534389-IEDR\nRegistry Billing ID: REDACTED FOR PRIVACY\nName Server: ns1.google.com\nName Server: ns2.google.com\nName Server: ns3.google.com\nDNSSEC: unsigned"
  },
  {
    "path": "test/samples/whois/google.it",
    "content": "*********************************************************************\n* Please note that the following result could be a subgroup of      *\n* the data contained in the database.                               *\n*                                                                   *\n* Additional information can be visualized at:                      *\n* http://web-whois.nic.it                                           *\n* Privacy Information: http://web-whois.nic.it/privacy              *\n*********************************************************************\n\nDomain:             google.it\nStatus:             ok\nSigned:             no\nCreated:            1999-12-10 00:00:00\nLast Update:        2018-05-07 00:54:15\nExpire Date:        2019-04-21\n\nRegistrant\n  Organization:     Google Ireland Holdings Unlimited Company\n  Address:          70 Sir John Rogerson's Quay\n                    Dublin\n                    2\n                    Dublin\n                    IE\n  Created:          2018-03-02 19:04:02\n  Last Update:      2018-03-02 19:04:02\n\nAdmin Contact\n  Name:             Christina Chiou\n  Organization:     Google LLC\n  Address:          1600 Amphitheatre Parkway\n                    Mountain View\n                    94043\n                    CA\n                    US\n  Created:          2018-03-12 23:25:59\n  Last Update:      2018-03-12 23:25:59\n\nTechnical Contacts\n  Name:             Domain Administrator\n  Organization:     Google LLC\n  Address:          1600 Amphitheatre Parkway\n                    Mountain View\n                    94043\n                    CA\n                    US\n  Created:          2017-12-21 19:54:04\n  Last Update:      2017-12-21 19:54:04\n\nRegistrar\n  Organization:     MarkMonitor International Limited\n  Name:             MARKMONITOR-REG\n  Web:              https://www.markmonitor.com/\n  DNSSEC:           no\n\nNameservers\n  ns1.google.com\n  ns2.google.com\n  ns3.google.com\n  ns4.google.com"
  },
  {
    "path": "test/samples/whois/google.kg",
    "content": "% This is the .kg ccTLD Whois server\n% Register your own domain at https://www.cctld.kg\n% Whois web service - https://www.cctld.kg/whois\n\nDomain GOOGLE.KG (ACTIVE)\n\nAdministrative Contact:\n   PID: AI-44973-KG\n   Name:\n   Address: United States Mountain View 1600 Amphitheatre Parkway N/A\n   Email: dns-admin@google.com\n   phone: 16502530000\n   fax: +1.6502530001\n\nTechnical Contact:\n   PID: AI-44973-KG\n   Name:\n   Address: United States Mountain View 1600 Amphitheatre Parkway N/A\n   Email: dns-admin@google.com\n   phone: 16502530000\n   fax: +1.6502530001\n\nBilling Contact:\n   PID: 5935-KG\n   Name:\n   Address: United States Meridian 1120 S. Rackham Way Suite 300\n   Email: ccops@markmonitor.com\n   phone: +12083895740\n   fax: +12083895771\n\n\nRecord created: Tue Feb 10 09:42:42 2004\nRecord last updated on:  Wed Mar  5 00:13:49 2025\nRecord expires on: Sat Mar 28 23:59:00 2026\n\nName servers in the listed order:\n\nNS1.GOOGLE.COM\nNS2.GOOGLE.COM\nNS4.GOOGLE.COM\n"
  },
  {
    "path": "test/samples/whois/google.lu",
    "content": "% Access to RESTENA DNS-LU WHOIS information is provided to assist persons\n% in determining the content of a domain name registration record in the LU\n% registration database. The data in this record is provided by RESTENA DNS-LU\n% for information purposes only, and RESTENA DNS-LU does not guarantee its\n% accuracy. Compilation, repackaging, dissemination or other use of the\n% WHOIS database in its entirety, or of a substantial part thereof, is not\n% allowed without the prior written permission of RESTENA DNS-LU.\n%\n% By submitting a WHOIS query, you agree to abide by this policy. You acknowledge\n% that the use of the WHOIS database is regulated by the ACCEPTABLE USE POLICY\n% (http://www.dns.lu/en/support/domainname-availability/whois-gateway/), that you are aware of its\n% content, and that you accept its terms and conditions.\n%\n% You agree especially that you will use this data only for lawful purposes and\n% that you will not use this data to:\n% (1) allow, enable, or otherwise support the transmission of mass unsolicited,\n% commercial advertising or solicitations via e-mail (spam); or\n% (2) enable high volume, automated, electronic processes that apply to\n% RESTENA DNS-LU (or its systems).\n%\n% All rights reserved.\n%\n% WHOIS google.lu\ndomainname:     google.lu\ndomaintype:     ACTIVE\nnserver:        ns1.google.com\nnserver:        ns2.google.com\nnserver:        ns3.google.com\nnserver:        ns4.google.com\nownertype:      ORGANISATION\norg-country:    US\nregistrar-name:         Markmonitor\nregistrar-email:        ccops@markmonitor.com\nregistrar-url:          http://www.markmonitor.com/\nregistrar-country:      GB\n%\n% More details on the domain may be available at below whois-web URL.\n% Next to possible further data a form to contact domain operator or\n% request further details is available.\nwhois-web:         https://www.dns.lu/en/support/domainname-availability/whois-gateway/"
  },
  {
    "path": "test/samples/whois/google.lv",
    "content": "[Domain]\nDomain: google.lv\nStatus: active\n\n[Holder]\n    Type: Legal person\n    Name: Google LLC\n    Address: 1600 Amphitheatre Parkway, Mountain View, CA, 94043, USA\n    RegNr: None\nVisit: https://www.nic.lv/whois/contact/google.lv to contact.\n\n[Tech]\nType: Natural person\nVisit: https://www.nic.lv/whois/contact/google.lv to contact.\n\n[Registrar]\n    Type: Legal person\n    Name: MarkMonitor Inc.\n    Address: 1120 S. Rackham Way, Suite 300, Meridian, ID, 83642, USA\n    RegNr: 82-0513468\nVisit: https://www.nic.lv/whois/contact/google.lv to contact.\n\n[Nservers]\nNserver: ns1.google.com\nNserver: ns2.google.com\nNserver: ns3.google.com\nNserver: ns4.google.com\n\n[Whois]\nUpdated: 2024-09-03T17:12:28.647770+00:00\n\n[Disclaimer]\n% The WHOIS service is provided solely for informational purposes.\n%\n% It is permitted to use the WHOIS service only for technical or administrative\n% needs associated with the operation of the Internet or in order to contact\n% the domain name holder over legal problems.\n%\n% Requestor will not use information obtained using WHOIS:\n% * To allow, enable or in any other way to support sending of unsolicited mails (spam)\n% * for any kind of advertising\n% * to disrupt Internet stability and security\n%\n% It is not permitted to obtain (including copying) or re-use in any form or\n% by any means all or quantitatively or qualitatively significant part\n% of the WHOIS without NIC's express permission."
  },
  {
    "path": "test/samples/whois/google.mx",
    "content": "Domain Name:       google.mx\n\nCreated On:        2009-05-12\nExpiration Date:   2020-05-11\nLast Updated On:   2019-04-12\nRegistrar:         MarkMonitor\nURL:               http://www.markmonitor.com/\n\nRegistrant:\n   Name:           Google Inc.\n   City:           Mountain View\n   State:          California\n   Country:        United States\n\nAdministrative Contact:\n   Name:           Google Inc.\n   City:           Mountain View\n   State:          California\n   Country:        United States\n\nTechnical Contact:\n   Name:           Google Inc.\n   City:           Mountain View\n   State:          California\n   Country:        United States\n\nBilling Contact:\n   Name:           MarkMonitor\n   City:           Boise\n   State:          Idaho\n   Country:        United States\n\nName Servers:\n   DNS:            ns2.google.com\n   DNS:            ns4.google.com\n   DNS:            ns3.google.com\n   DNS:            ns1.google.com\nDNSSEC DS Records:\n\n\n\n% NOTICE: The expiration date displayed in this record is the date the\n% registrar's sponsorship of the domain name registration in the registry is\n% currently set to expire. This date does not necessarily reflect the\n% expiration date of the domain name registrant's agreement with the sponsoring\n% registrar. Users may consult the sponsoring registrar's Whois database to\n% view the registrar's reported date of expiration for this registration.\n% The requested information (\"Information\") is provided only for the delegation\n% of domain names and the operation of the DNS administered by NIC Mexico.\n% It is absolutely prohibited to use the Information for other purposes,\n% including sending not requested emails for advertising or promoting products\n% and services purposes (SPAM) without the authorization of the owners of the\n% Information and NIC Mexico.\n% The database generated from the delegation system is protected by the\n% intellectual property laws and all international treaties on the matter.\n% If you need more information on the records displayed here, please contact us\n% by email at ayuda@nic.mx .\n% If you want notify the receipt of SPAM or unauthorized access, please send a\n% email to abuse@nic.mx .\n% NOTA: La fecha de expiracion mostrada en esta consulta es la fecha que el\n% registrar tiene contratada para el nombre de dominio en el registry. Esta\n% fecha no necesariamente refleja la fecha de expiracion del nombre de dominio\n% que el registrante tiene contratada con el registrar. Puede consultar la base\n% de datos de Whois del registrar para ver la fecha de expiracion reportada por\n% el registrar para este nombre de dominio.\n% La informacion que ha solicitado se provee exclusivamente para fines\n% relacionados con la delegacion de nombres de dominio y la operacion del DNS\n% administrado por NIC Mexico.\n% Queda absolutamente prohibido su uso para otros propositos, incluyendo el\n% envio de Correos Electronicos no solicitados con fines publicitarios o de\n% promocion de productos y servicios (SPAM) sin mediar la autorizacion de los\n% afectados y de NIC Mexico.\n% La base de datos generada a partir del sistema de delegacion, esta protegida\n% por las leyes de Propiedad Intelectual y todos los tratados internacionales\n% sobre la materia.\n% Si necesita mayor informacion sobre los registros aqui mostrados, favor de\n% comunicarse a ayuda@nic.mx.\n% Si desea notificar sobre correo no solicitado o accesos no autorizados, favor\n% de enviar su mensaje a abuse@nic.mx."
  },
  {
    "path": "test/samples/whois/google.ro",
    "content": "% The WHOIS service offered by ROTLD and the access to the records in the ROTLD WHOIS database\n% are provided for information purposes and to be used within the scope of technical or administrative\n% necessities of Internet operation or to remedy legal problems. The use for other purposes,\n% in particular for advertising and domain hunting, is not permitted.\n\n% Without prejudice to the above, it is explicitly forbidden to extract, copy and/or use or re-utilise\n% in any form and by any means (electronically or not) the whole or a quantitatively or qualitatively\n% substantial part of the contents of the WHOIS database without prior and explicit permission by ROTLD,\n% nor in any attempt hereof, to apply automated, electronic processes to ROTLD (or its systems).\n\n% ROTLD cannot, under any circumstances, be held liable in case the stored information would prove\n% to be wrong, incomplete or not accurate in any sense.\n\n% You agree that any reproduction and/or transmission of data for commercial purposes will always\n% be considered as the extraction of a substantial part of the content of the WHOIS database.\n\n% By submitting the query you agree to abide by this policy and accept that ROTLD can take measures\n% to limit the use of its WHOIS services in order to protect the privacy of its registrants or the\n% integrity of the database.\n\n% The ROTLD WHOIS service on port 43 never discloses any information concerning the registrant.\n\n% Registrant information can be obtained through use of the web-based whois service available from\n% the ROTLD website www.rotld.ro\n\n\n  Domain Name: google.ro\n  Registered On: 2000-07-17\n  Expires On: 2019-09-17\n  Registrar: MarkMonitor Inc.\n  Referral URL: www.markmonitor.com\n\n  DNSSEC: Inactive\n\n  Nameserver: ns1.google.com\n  Nameserver: ns2.google.com\n  Nameserver: ns3.google.com\n  Nameserver: ns4.google.com\n\n  Domain Status: UpdateProhibited"
  },
  {
    "path": "test/samples/whois/google.sk",
    "content": "Domain:                       google.sk\nRegistrant:                   Google\nAdmin Contact:                Google\nTech Contact:                 Google\nRegistrar:                    FAJN-0002\nCreated:                      2003-07-24\nUpdated:                      2018-07-03\nValid Until:                  2019-07-24\nNameserver:                   ns1.google.com\nNameserver:                   ns2.google.com\nNameserver:                   ns3.google.com\nNameserver:                   ns4.google.com\nEPP Status:                   ok\n\nRegistrar:                    FAJN-0002\nName:                         FAJNOR IP s. r. o.\nOrganization:                 FAJNOR IP s. r. o.\nOrganization ID:              46039201\nPhone:                        +421.263811927\nEmail:                        domains@fajnor.sk\nStreet:                       Krasovského 13\nCity:                         Bratislava\nPostal Code:                  851 01\nCountry Code:                 SK\nCreated:                      2017-09-01\nUpdated:                      2019-04-17\n\nContact:                      Google\nName:                         Domain Administrator\nOrganization:                 Google Ireland Holdings Unlimited Company\nPhone:                        +353.14361000\nEmail:                        dns-admin@google.com\nStreet:                       70 Sir John Rogerson's Quay\nCity:                         Dublin\nPostal Code:                  2\nCountry Code:                 IE\nRegistrar:                    FAJN-0002\nCreated:                      2018-01-26\nUpdated:                      2018-07-16\n"
  },
  {
    "path": "test/samples/whois/imdb.com",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Server Name: IMDB.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM\n   IP Address: 203.36.226.2\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Domain Name: IMDB.COM\n   Registrar: NETWORK SOLUTIONS, LLC.\n   Whois Server: whois.networksolutions.com\n   Referral URL: http://www.networksolutions.com\n   Name Server: UDNS1.ULTRADNS.NET\n   Name Server: UDNS2.ULTRADNS.NET\n   Status: clientTransferProhibited\n   Updated Date: 28-mar-2008\n   Creation Date: 05-jan-1996\n   Expiration Date: 04-jan-2016\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:40:25 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.NOTICE AND TERMS OF USE: You are not authorized to access or query our WHOIS\ndatabase through the use of high-volume, automated, electronic processes. The\nData in Network Solutions' WHOIS database is provided by Network Solutions for information\npurposes only, and to assist persons in obtaining information about or related\nto a domain name registration record. Network Solutions does not guarantee its accuracy.\nBy submitting a WHOIS query, you agree to abide by the following terms of use:\nYou agree that you may use this Data only for lawful purposes and that under no\ncircumstances will you use this Data to: (1) allow, enable, or otherwise support\nthe transmission of mass unsolicited, commercial advertising or solicitations\nvia e-mail, telephone, or facsimile; or (2) enable high volume, automated,\nelectronic processes that apply to Network Solutions (or its computer systems). The\ncompilation, repackaging, dissemination or other use of this Data is expressly\nprohibited without the prior written consent of Network Solutions. You agree not to use\nhigh-volume, automated, electronic processes to access or query the WHOIS\ndatabase. Network Solutions reserves the right to terminate your access to the WHOIS\ndatabase in its sole discretion, including without limitation, for excessive\nquerying of the WHOIS database or for failure to otherwise abide by this policy.\nNetwork Solutions reserves the right to modify these terms at any time.\n\nGet a FREE domain name registration, transfer, or renewal with any annual hosting package.\n\nhttp://www.networksolutions.com\n\nVisit AboutUs.org for more information about IMDB.COM\n<a href=\"http://www.aboutus.org/IMDB.COM\">AboutUs: IMDB.COM </a>\n\n\n\n\nRegistrant:\nIMDb.com, Inc.\n   Legal Dept, PO Box 81226\n   Seattle, WA 98108\n   US\n\n   Domain Name: IMDB.COM\n\n   ------------------------------------------------------------------------\n   Promote your business to millions of viewers for only $1 a month\n   Learn how you can get an Enhanced Business Listing here for your domain name.\n   Learn more at http://www.NetworkSolutions.com/\n   ------------------------------------------------------------------------\n\n   Administrative Contact, Technical Contact:\n      Hostmaster, IMDb\t\thostmaster@imdb.com\n      IMDb.com, Inc.\n      Legal Dept, PO Box 81226\n      Seattle, WA 98108\n      US\n      +1.2062664064 fax: +1.2062667010\n\n\n   Record expires on 04-Jan-2016.\n   Record created on 05-Jan-1996.\n   Database last updated on 26-Jun-2008 21:38:42 EDT.\n\n   Domain servers in listed order:\n\n   UDNS1.ULTRADNS.NET           \n   UDNS2.ULTRADNS.NET           \n\n"
  },
  {
    "path": "test/samples/whois/liechtenstein.li",
    "content": "\nDomain name:\nliechtenstein.li\n\nHolder of domain name:\nLiechtensteinische Landesverwaltung\nMartin Matt\nHeiligkreuz 8\nLI-9490 Vaduz\nLiechtenstein\n\nRegistrar:\nswitchplus AG\n\nFirst registration date:\n1996-02-08\n\nDNSSEC:N\n\nName servers:\npdns.llv.li    [193.222.114.65]\nscsnms.switch.ch    [130.59.31.26]\nscsnms.switch.ch    [2001:620:0:ff::a7]"
  },
  {
    "path": "test/samples/whois/microsoft.com",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Server Name: MICROSOFT.COM.ZZZZZZ.MORE.DETAILS.AT.WWW.BEYONDWHOIS.COM\n   IP Address: 203.36.226.2\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: MICROSOFT.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM\n   IP Address: 69.41.185.194\n   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM\n   Whois Server: whois.itsyourdomain.com\n   Referral URL: http://www.itsyourdomain.com\n\n   Server Name: MICROSOFT.COM.ZZZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM\n   IP Address: 217.107.217.167\n   Registrar: ONLINENIC, INC.\n   Whois Server: whois.35.com\n   Referral URL: http://www.OnlineNIC.com\n\n   Server Name: MICROSOFT.COM.ZZZ.IS.0WNED.AND.HAX0RED.BY.SUB7.NET\n   IP Address: 207.44.240.96\n   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM\n   Whois Server: whois.itsyourdomain.com\n   Referral URL: http://www.itsyourdomain.com\n\n   Server Name: MICROSOFT.COM.WILL.LIVE.FOREVER.BECOUSE.UNIXSUCKS.COM\n   IP Address: 185.3.4.7\n   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE\n   Whois Server: whois.melbourneit.com\n   Referral URL: http://www.melbourneit.com\n\n   Server Name: MICROSOFT.COM.WILL.BE.SLAPPED.IN.THE.FACE.BY.MY.BLUE.VEINED.SPANNER.NET\n   IP Address: 216.127.80.46\n   Registrar: COMPUTER SERVICES LANGENBACH GMBH DBA JOKER.COM\n   Whois Server: whois.joker.com\n   Referral URL: http://www.joker.com\n\n   Server Name: MICROSOFT.COM.WILL.BE.BEATEN.WITH.MY.SPANNER.NET\n   IP Address: 216.127.80.46\n   Registrar: COMPUTER SERVICES LANGENBACH GMBH DBA JOKER.COM\n   Whois Server: whois.joker.com\n   Referral URL: http://www.joker.com\n\n   Server Name: MICROSOFT.COM.WAREZ.AT.TOPLIST.GULLI.COM\n   IP Address: 80.190.192.33\n   Registrar: EPAG DOMAINSERVICES GMBH\n   Whois Server: whois.enterprice.net\n   Referral URL: http://www.enterprice.net\n\n   Server Name: MICROSOFT.COM.USERS.SHOULD.HOST.WITH.UNIX.AT.ITSHOSTED.COM\n   IP Address: 74.52.88.132\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: MICROSOFT.COM.TOTALLY.SUCKS.S3U.NET\n   IP Address: 207.208.13.22\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: MICROSOFT.COM.SOFTWARE.IS.NOT.USED.AT.REG.RU\n   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE\n   Whois Server: whois.melbourneit.com\n   Referral URL: http://www.melbourneit.com\n\n   Server Name: MICROSOFT.COM.SHOULD.GIVE.UP.BECAUSE.LINUXISGOD.COM\n   IP Address: 65.160.248.13\n   Registrar: GKG.NET, INC.\n   Whois Server: whois.gkg.net\n   Referral URL: http://www.gkg.net\n\n   Server Name: MICROSOFT.COM.RAWKZ.MUH.WERLD.MENTALFLOSS.CA\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: MICROSOFT.COM.OHMYGODITBURNS.COM\n   IP Address: 216.158.63.6\n   Registrar: DOTSTER, INC.\n   Whois Server: whois.dotster.com\n   Referral URL: http://www.dotster.com\n\n   Server Name: MICROSOFT.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM\n   IP Address: 203.36.226.2\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: MICROSOFT.COM.LOVES.ME.KOSMAL.NET\n   IP Address: 65.75.198.123\n   Registrar: GODADDY.COM, INC.\n   Whois Server: whois.godaddy.com\n   Referral URL: http://registrar.godaddy.com\n\n   Server Name: MICROSOFT.COM.LIVES.AT.SHAUNEWING.COM\n   IP Address: 216.40.250.172\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: MICROSOFT.COM.IS.NOT.YEPPA.ORG\n   Registrar: OVH\n   Whois Server: whois.ovh.com\n   Referral URL: http://www.ovh.com\n\n   Server Name: MICROSOFT.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET\n   IP Address: 217.148.161.5\n   Registrar: ENOM, INC.\n   Whois Server: whois.enom.com\n   Referral URL: http://www.enom.com\n\n   Server Name: MICROSOFT.COM.IS.IN.BED.WITH.CURTYV.COM\n   IP Address: 216.55.187.193\n   Registrar: ABACUS AMERICA, INC. DBA NAMES4EVER\n   Whois Server: whois.names4ever.com\n   Referral URL: http://www.names4ever.com\n\n   Server Name: MICROSOFT.COM.IS.HOSTED.ON.PROFITHOSTING.NET\n   IP Address: 66.49.213.213\n   Registrar: NAME.COM LLC\n   Whois Server: whois.name.com\n   Referral URL: http://www.name.com\n\n   Server Name: MICROSOFT.COM.IS.GOD.BECOUSE.UNIXSUCKS.COM\n   IP Address: 161.16.56.24\n   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE\n   Whois Server: whois.melbourneit.com\n   Referral URL: http://www.melbourneit.com\n\n   Server Name: MICROSOFT.COM.IS.A.STEAMING.HEAP.OF.FUCKING-BULLSHIT.NET\n   IP Address: 63.99.165.11\n   Registrar: THE NAME IT CORPORATION DBA NAMESERVICES.NET\n   Whois Server: whois.aitdomains.com\n   Referral URL: http://www.aitdomains.com\n\n   Server Name: MICROSOFT.COM.IS.A.MESS.TIMPORTER.CO.UK\n   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE\n   Whois Server: whois.melbourneit.com\n   Referral URL: http://www.melbourneit.com\n\n   Server Name: MICROSOFT.COM.HAS.ITS.OWN.CRACKLAB.COM\n   IP Address: 209.26.95.44\n   Registrar: DOTSTER, INC.\n   Whois Server: whois.dotster.com\n   Referral URL: http://www.dotster.com\n\n   Server Name: MICROSOFT.COM.HAS.A.PRESENT.COMING.FROM.HUGHESMISSILES.COM\n   IP Address: 66.154.11.27\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: MICROSOFT.COM.FILLS.ME.WITH.BELLIGERENCE.NET\n   IP Address: 130.58.82.232\n   Registrar: CRONON AG BERLIN, NIEDERLASSUNG REGENSBURG\n   Whois Server: whois.tmagnic.net\n   Referral URL: http://nsi-robo.tmag.de\n\n   Server Name: MICROSOFT.COM.CAN.GO.FUCK.ITSELF.AT.SECZY.COM\n   IP Address: 209.187.114.147\n   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM\n   Whois Server: whois.itsyourdomain.com\n   Referral URL: http://www.itsyourdomain.com\n\n   Server Name: MICROSOFT.COM.ARE.GODDAMN.PIGFUCKERS.NET.NS-NOT-IN-SERVICE.COM\n   IP Address: 216.127.80.46\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n\n   Server Name: MICROSOFT.COM.AND.MINDSUCK.BOTH.SUCK.HUGE.ONES.AT.EXEGETE.NET\n   IP Address: 63.241.136.53\n   Registrar: DOTSTER, INC.\n   Whois Server: whois.dotster.com\n   Referral URL: http://www.dotster.com\n\n   Domain Name: MICROSOFT.COM\n   Registrar: TUCOWS INC.\n   Whois Server: whois.tucows.com\n   Referral URL: http://domainhelp.opensrs.net\n   Name Server: NS1.MSFT.NET\n   Name Server: NS2.MSFT.NET\n   Name Server: NS3.MSFT.NET\n   Name Server: NS4.MSFT.NET\n   Name Server: NS5.MSFT.NET\n   Status: clientDeleteProhibited\n   Status: clientTransferProhibited\n   Status: clientUpdateProhibited\n   Updated Date: 10-oct-2006\n   Creation Date: 02-may-1991\n   Expiration Date: 03-may-2014\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:39:39 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.Registrant:\n Microsoft Corporation\n One Microsoft Way\n Redmond, WA 98052\n US\n\n Domain name: MICROSOFT.COM\n\n\n Administrative Contact:\n    Administrator, Domain  domains@microsoft.com\n    One Microsoft Way\n    Redmond, WA 98052\n    US\n    +1.4258828080\n Technical Contact:\n    Hostmaster, MSN  msnhst@microsoft.com\n    One Microsoft Way\n    Redmond, WA 98052\n    US\n    +1.4258828080\n\n\n Registration Service Provider:\n    DBMS VeriSign, dbms-support@verisign.com\n    800-579-2848 x4\n    Please contact DBMS VeriSign for domain updates, DNS/Nameserver\n    changes, and general domain support questions.\n\n\n Registrar of Record: TUCOWS, INC.\n Record last updated on 15-Nov-2007.\n Record expires on 03-May-2014.\n Record created on 02-May-1991.\n\n Registrar Domain Name Help Center:\n    http://domainhelp.tucows.com\n\n Domain servers in listed order:\n    NS2.MSFT.NET   \n    NS4.MSFT.NET   \n    NS1.MSFT.NET   \n    NS5.MSFT.NET   \n    NS3.MSFT.NET   \n\n\n Domain status: clientDeleteProhibited\n                clientTransferProhibited\n                clientUpdateProhibited\n\nThe Data in the Tucows Registrar WHOIS database is provided to you by Tucows\nfor information purposes only, and may be used to assist you in obtaining\ninformation about or related to a domain name's registration record.\n\nTucows makes this information available \"as is,\" and does not guarantee its\naccuracy.\n\nBy submitting a WHOIS query, you agree that you will use this data only for\nlawful purposes and that, under no circumstances will you use this data to:\na) allow, enable, or otherwise support the transmission by e-mail,\ntelephone, or facsimile of mass, unsolicited, commercial advertising or\nsolicitations to entities other than the data recipient's own existing\ncustomers; or (b) enable high volume, automated, electronic processes that\nsend queries or data to the systems of any Registry Operator or\nICANN-Accredited registrar, except as reasonably necessary to register\ndomain names or modify existing registrations.\n\nThe compilation, repackaging, dissemination or other use of this Data is\nexpressly prohibited without the prior written consent of Tucows.\n\nTucows reserves the right to terminate your access to the Tucows WHOIS\ndatabase in its sole discretion, including without limitation, for excessive\nquerying of the WHOIS database or for failure to otherwise abide by this\npolicy.\n\nTucows reserves the right to modify these terms at any time.\n\nBy submitting this query, you agree to abide by these terms.\n\nNOTE: THE WHOIS DATABASE IS A CONTACT DATABASE ONLY.  LACK OF A DOMAIN\nRECORD DOES NOT SIGNIFY DOMAIN AVAILABILITY.\n\n\n"
  },
  {
    "path": "test/samples/whois/nic.live",
    "content": "% IANA WHOIS server\n% for more information on IANA, visit http://www.iana.org\n% This query returned 1 object\n\nrefer:        whois.nic.live\n\ndomain:       LIVE\n\norganisation: Dog Beach, LLC\naddress:      c/o Identity Digital Limited\naddress:      10500 NE 8th Street, Suite 750\naddress:      Bellevue WA 98004\naddress:      United States of America (the)\n\ncontact:      administrative\nname:         Vice President, Engineering\norganisation: Identity Digital Limited\naddress:      10500 NE 8th Street, Suite 750\naddress:      Bellevue WA 98004\naddress:      United States of America (the)\nphone:        +1.425.298.2200\nfax-no:       +1.425.671.0020\ne-mail:       tldadmin@identity.digital\n\ncontact:      technical\nname:         Senior Director, DNS Infrastructure Group\norganisation: Identity Digital Limited\naddress:      10500 NE 8th Street, Suite 750\naddress:      Bellevue WA 98004\naddress:      United States of America (the)\nphone:        +1.425.298.2200\nfax-no:       +1.425.671.0020\ne-mail:       tldtech@identity.digital\n\nnserver:      V0N0.NIC.LIVE 2a01:8840:16:0:0:0:0:1 65.22.20.1\nnserver:      V0N1.NIC.LIVE 2a01:8840:17:0:0:0:0:1 65.22.21.1\nnserver:      V0N2.NIC.LIVE 2a01:8840:18:0:0:0:0:1 65.22.22.1\nnserver:      V0N3.NIC.LIVE 161.232.10.1 2a01:8840:f4:0:0:0:0:1\nnserver:      V2N0.NIC.LIVE 2a01:8840:19:0:0:0:0:1 65.22.23.1\nnserver:      V2N1.NIC.LIVE 161.232.11.1 2a01:8840:f5:0:0:0:0:1\nds-rdata:     36322 8 2 201df9a9af6766d9cdbc8355756728f2db40ba93f9724f93aeeb1bddd7d564a0\n\nwhois:        whois.nic.live\n\nstatus:       ACTIVE\nremarks:      Registration information: https://www.identity.digital/\n\ncreated:      2015-06-25\nchanged:      2023-09-12\nsource:       IANA\n\n# whois.nic.live\n\nDomain Name: nic.live\nRegistry Domain ID: 4ddd5c8266194b0488fab6a4d20df35d-DONUTS\nRegistrar WHOIS Server: whois.identitydigital.services\nRegistrar URL: https://identity.digital\nUpdated Date: 2024-06-11T22:04:34Z\nCreation Date: 2015-04-27T22:04:24Z\nRegistry Expiry Date: 2025-04-27T22:04:24Z\nRegistrar: Registry Operator acts as Registrar (9999)\nRegistrar IANA ID: 9999\nRegistrar Abuse Contact Email: abuse@identity.digital\nRegistrar Abuse Contact Phone: +1.6664447777\nDomain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited\nRegistry Registrant ID: REDACTED FOR PRIVACY\nRegistrant Name: REDACTED FOR PRIVACY\nRegistrant Organization: United TLD Holdco Ltd.\nRegistrant Street: REDACTED FOR PRIVACY\nRegistrant City: REDACTED FOR PRIVACY\nRegistrant State/Province: Dublin 2\nRegistrant Postal Code: REDACTED FOR PRIVACY\nRegistrant Country: IE\nRegistrant Phone: REDACTED FOR PRIVACY\nRegistrant Phone Ext: REDACTED FOR PRIVACY\nRegistrant Fax: REDACTED FOR PRIVACY\nRegistrant Fax Ext: REDACTED FOR PRIVACY\nRegistrant Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nRegistry Admin ID: REDACTED FOR PRIVACY\nAdmin Name: REDACTED FOR PRIVACY\nAdmin Organization: REDACTED FOR PRIVACY\nAdmin Street: REDACTED FOR PRIVACY\nAdmin City: REDACTED FOR PRIVACY\nAdmin State/Province: REDACTED FOR PRIVACY\nAdmin Postal Code: REDACTED FOR PRIVACY\nAdmin Country: REDACTED FOR PRIVACY\nAdmin Phone: REDACTED FOR PRIVACY\nAdmin Phone Ext: REDACTED FOR PRIVACY\nAdmin Fax: REDACTED FOR PRIVACY\nAdmin Fax Ext: REDACTED FOR PRIVACY\nAdmin Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nRegistry Tech ID: REDACTED FOR PRIVACY\nTech Name: REDACTED FOR PRIVACY\nTech Organization: REDACTED FOR PRIVACY\nTech Street: REDACTED FOR PRIVACY\nTech City: REDACTED FOR PRIVACY\nTech State/Province: REDACTED FOR PRIVACY\nTech Postal Code: REDACTED FOR PRIVACY\nTech Country: REDACTED FOR PRIVACY\nTech Phone: REDACTED FOR PRIVACY\nTech Phone Ext: REDACTED FOR PRIVACY\nTech Fax: REDACTED FOR PRIVACY\nTech Fax Ext: REDACTED FOR PRIVACY\nTech Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nName Server: v0n0.nic.live\nName Server: v0n1.nic.live\nName Server: v0n2.nic.live\nName Server: v0n3.nic.live\nName Server: v2n0.nic.live\nName Server: v2n1.nic.live\nDNSSEC: unsigned\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2024-07-09T23:49:59Z <<<\n\n# whois.identitydigital.services\n\nDomain Name: nic.live\nRegistry Domain ID: 4ddd5c8266194b0488fab6a4d20df35d-DONUTS\nRegistrar WHOIS Server: whois.identitydigital.services\nRegistrar URL: https://identity.digital\nUpdated Date: 2024-06-11T22:04:34Z\nCreation Date: 2015-04-27T22:04:24Z\nRegistry Expiry Date: 2025-04-27T22:04:24Z\nRegistrar: Registry Operator acts as Registrar (9999)\nRegistrar IANA ID: 9999\nRegistrar Abuse Contact Email: abuse@identity.digital\nRegistrar Abuse Contact Phone: +1.6664447777\nDomain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited\nRegistry Registrant ID: REDACTED FOR PRIVACY\nRegistrant Name: REDACTED FOR PRIVACY\nRegistrant Organization: United TLD Holdco Ltd.\nRegistrant Street: REDACTED FOR PRIVACY\nRegistrant City: REDACTED FOR PRIVACY\nRegistrant State/Province: Dublin 2\nRegistrant Postal Code: REDACTED FOR PRIVACY\nRegistrant Country: IE\nRegistrant Phone: REDACTED FOR PRIVACY\nRegistrant Phone Ext: REDACTED FOR PRIVACY\nRegistrant Fax: REDACTED FOR PRIVACY\nRegistrant Fax Ext: REDACTED FOR PRIVACY\nRegistrant Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nRegistry Admin ID: REDACTED FOR PRIVACY\nAdmin Name: REDACTED FOR PRIVACY\nAdmin Organization: REDACTED FOR PRIVACY\nAdmin Street: REDACTED FOR PRIVACY\nAdmin City: REDACTED FOR PRIVACY\nAdmin State/Province: REDACTED FOR PRIVACY\nAdmin Postal Code: REDACTED FOR PRIVACY\nAdmin Country: REDACTED FOR PRIVACY\nAdmin Phone: REDACTED FOR PRIVACY\nAdmin Phone Ext: REDACTED FOR PRIVACY\nAdmin Fax: REDACTED FOR PRIVACY\nAdmin Fax Ext: REDACTED FOR PRIVACY\nAdmin Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nRegistry Tech ID: REDACTED FOR PRIVACY\nTech Name: REDACTED FOR PRIVACY\nTech Organization: REDACTED FOR PRIVACY\nTech Street: REDACTED FOR PRIVACY\nTech City: REDACTED FOR PRIVACY\nTech State/Province: REDACTED FOR PRIVACY\nTech Postal Code: REDACTED FOR PRIVACY\nTech Country: REDACTED FOR PRIVACY\nTech Phone: REDACTED FOR PRIVACY\nTech Phone Ext: REDACTED FOR PRIVACY\nTech Fax: REDACTED FOR PRIVACY\nTech Fax Ext: REDACTED FOR PRIVACY\nTech Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain name.\nName Server: v0n0.nic.live\nName Server: v0n1.nic.live\nName Server: v0n2.nic.live\nName Server: v0n3.nic.live\nName Server: v2n0.nic.live\nName Server: v2n1.nic.live\nDNSSEC: unsigned\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2024-07-09T23:49:59Z <<<\n\n"
  },
  {
    "path": "test/samples/whois/nyan.cat",
    "content": "Domain Name: nyan.cat\r\nRegistry Domain ID: 826532-D\r\nRegistrar WHOIS Server: whois.gandi.net\r\nRegistrar URL: https://www.gandi.net/\r\nUpdated Date: 2017-07-07T17:24:23.746Z\r\nCreation Date: 2011-04-13T19:52:17.635Z\r\nRegistry Expiry Date: 2018-04-13T19:52:17.635Z\r\nRegistrar: GANDI SAS\r\nRegistrar IANA ID: 81\r\nRegistrar Abuse Contact Email: direction@gandi.net\r\nRegistrar Abuse Contact Phone: +1.1111111\r\nDomain Status: ok https://icann.org/epp#ok\r\nRegistry Registrant ID:\r\nRegistrant Name:\r\nRegistrant Organization:\r\nRegistrant Street:\r\nRegistrant City:\r\nRegistrant State/Province:\r\nRegistrant Postal Code:\r\nRegistrant Country:\r\nRegistrant Phone:\r\nRegistrant Phone Ext:\r\nRegistrant Fax:\r\nRegistrant Fax Ext:\r\nRegistrant Email:\r\nRegistry Admin ID:\r\nAdmin Name:\r\nAdmin Organization:\r\nAdmin Street:\r\nAdmin City:\r\nAdmin State/Province:\r\nAdmin Postal Code:\r\nAdmin Country:\r\nAdmin Phone:\r\nAdmin Phone Ext:\r\nAdmin Fax:\r\nAdmin Fax Ext:\r\nAdmin Email:\r\nRegistry Tech ID:\r\nTech Name:\r\nTech Organization:\r\nTech Street:\r\nTech City:\r\nTech State/Province:\r\nTech Postal Code:\r\nTech Country:\r\nTech Phone:\r\nTech Phone Ext:\r\nTech Fax:\r\nTech Fax Ext:\r\nTech Email:\r\nRegistry Billing ID:\r\nBilling Name:\r\nBilling Organization:\r\nBilling Street:\r\nBilling City:\r\nBilling State/Province:\r\nBilling Postal Code:\r\nBilling Country:\r\nBilling Phone:\r\nBilling Phone Ext:\r\nBilling Fax:\r\nBilling Fax Ext:\r\nBilling Email:\r\nName Server: ns1.dreamhost.com\r\nName Server: ns2.dreamhost.com\r\nName Server: ns3.dreamhost.com\r\nDNSSEC: unsigned\r\nIDN Tag:\r\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\r\n>>> Last update of Whois database: 2017-12-11T22:57:02.88Z <<<\r\n\r\nFor more information on Whois status codes, please visit https://icann.org/epp\r\n\r\n\r\nThis domain has chosen privacy settings according to the European\r\ndata protection framework provisions.\r\n\r\nShould you need to contact the registrant, please see\r\nhttp://www.domini.cat/contact-registrant\r\n\r\nFor law enforcement and trademark protection purposes, see\r\nhttp://www.domini.cat/whois-access\r\n\r\nIn case of technical problems, please see\r\nhttp://www.domini.cat/report-problem\r\n\r\nTerms and Conditions of Use\r\n\r\nThe data in this record is provided by puntCAT for informational\r\npurposes only. puntCAT does not guarantee its accuracy and cannot,\r\nunder any circumstances, be held liable in case the stored information would\r\nprove to be wrong, incomplete or not accurate in any sense.\r\n\r\nAll the domain data that is visible in the Whois service is protected by\r\nlaw. It is not permitted to use it for any purpose other than technical or\r\nadministrative requirements associated with the operation of the Internet.\r\nIt is explicitly forbidden to extract, copy and/or use or re-utilise in any\r\nform and by any means (electronically or not) the whole or a quantitatively\r\nor qualitatively substantial part of the contents of the Whois database\r\nwithout prior and explicit written permission by puntCAT It is\r\nprohibited, in particular, to use it for transmission of unsolicited and/or\r\ncommercial and/or advertising by phone, fax, e-mail or for any similar\r\npurposes.\r\n\r\nBy maintaining the connection you assure that you have a legitimate interest\r\nin the data and that you will only use it for the stated purposes. You are\r\naware that puntCAT maintains the right to initiate legal\r\nproceedings against you in the event of any breach of this assurance and to\r\nbar you from using its Whois service.\r\n\r\nEnd of Whois record."
  },
  {
    "path": "test/samples/whois/reddit.com",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Domain Name: REDDIT.COM\n   Registrar: DSTR ACQUISITION PA I, LLC DBA DOMAINBANK.COM\n   Whois Server: rs.domainbank.net\n   Referral URL: http://www.domainbank.net\n   Name Server: ASIA1.AKAM.NET\n   Name Server: ASIA9.AKAM.NET\n   Name Server: AUS2.AKAM.NET\n   Name Server: NS1-1.AKAM.NET\n   Name Server: NS1-195.AKAM.NET\n   Name Server: USE4.AKAM.NET\n   Name Server: USW3.AKAM.NET\n   Name Server: USW5.AKAM.NET\n   Status: clientDeleteProhibited\n   Status: clientTransferProhibited\n   Status: clientUpdateProhibited\n   Updated Date: 04-jun-2008\n   Creation Date: 29-apr-2005\n   Expiration Date: 29-apr-2009\n\n>>> Last update of whois database: Fri, 27 Jun 2008 01:39:54 UTC <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.\nThe information in this whois database is provided for the sole\npurpose of assisting you in obtaining information about domain\nname registration records. This information is available \"as is,\"\nand we do not guarantee its accuracy. By submitting a whois\nquery, you agree that you will use this data only for lawful\npurposes and that, under no circumstances will you use this data\nto: (1) enable high volume, automated, electronic processes that\nstress or load this whois database system providing you this\ninformation; or (2) allow,enable, or otherwise support the\ntransmission of mass, unsolicited, commercial advertising or\nsolicitations via facsimile, electronic mail, or by telephone to\nentitites other than your own existing customers.  The\ncompilation, repackaging, dissemination or other use of this data\nis expressly prohibited without prior written consent from this\ncompany. We reserve the right to modify these terms at any\ntime. By submitting an inquiry, you agree to these terms of usage\nand limitations of warranty.  Please limit your queries to 10 per\nminute and one connection.\n\n   Domain Services Provided By:\n      Domain Bank, support@domainbank.com\n      http:///www.domainbank.com\n\nRegistrant:\n   CONDENET INC\n   Four Times Square\n   New York, NY  10036\n   US\n\n   Registrar: DOMAINBANK\n   Domain Name: REDDIT.COM\n      Created on: 29-APR-05\n      Expires on: 29-APR-09\n      Last Updated on: 04-JUN-08\n\n   Administrative Contact:\n      ,   domain_admin@advancemags.com\n      Advance Magazine Group\n      4 Times Square\n      23rd Floor\n      New York, New York  10036\n      US\n      2122862860\n\n   Technical Contact:\n      ,   domains@advancemags.com\n      Advance Magazine Group\n      1201 N. Market St\n      Wilmington, DE  19801\n      US\n      3028304630\n\n\n   Domain servers in listed order:\n      ASIA1.AKAM.NET \n      ASIA9.AKAM.NET \n      AUS2.AKAM.NET \n      NS1-1.AKAM.NET \n      NS1-195.AKAM.NET \n      USE4.AKAM.NET \n      USW3.AKAM.NET \n      USW5.AKAM.NET \n\nEnd of Whois Information\n"
  },
  {
    "path": "test/samples/whois/sapo.pt",
    "content": "Domain: sapo.pt\r\nDomain Status: Registered\r\nCreation Date: 30/10/2002 00:00:00\r\nExpiration Date: 02/11/2019 23:59:00\r\nOwner Name: MEO - SERVI?OS DE COMUNICA??ES E MULTIM?DIA S.A.\r\nOwner Address: A/C Dire??o de Tecnologias de Informa??o\r\nOwner Locality: Av. Fontes Pereira de Melo, 40\r\nOwner ZipCode: 1069-300\r\nOwner Locality ZipCode: Av. Fontes Pereira de Melo, 40\r\nOwner Email: gestao.dominios@telecom.pt\r\nAdmin Name: MEO - SERVI?OS DE COMUNICA??ES E MULTIM?DIA S.A.\r\nAdmin Address: A/C Dire??o de Tecnologias de Informa??o\r\nAdmin Locality: Av. Fontes Pereira de Melo, 40\r\nAdmin ZipCode: 1069-300\r\nAdmin Locality ZipCode: Av. Fontes Pereira de Melo, 40\r\nAdmin Email: gestao.dominios@telecom.pt\r\nName Server: ns2.sapo.pt | IPv4: 212.55.154.194 and IPv6:\r\nName Server: dns01.sapo.pt | IPv4: 213.13.28.116 and IPv6: 2001:8a0:2106:4:213:13:28:116\r\nName Server: dns02.sapo.pt | IPv4: 213.13.30.116 and IPv6: 2001:8a0:2206:4:213:13:30:116\r\nName Server: ns.sapo.pt | IPv4: 212.55.154.202 and IPv6:"
  },
  {
    "path": "test/samples/whois/sbc.org.hk",
    "content": "\n -------------------------------------------------------------------------------\n Whois server by HKIRC\n -------------------------------------------------------------------------------\n .hk top level Domain names can be registered via HKIRC-Accredited Registrars.\n Go to https://www.hkirc.hk/content.jsp?id=280 for details.\n -------------------------------------------------------------------------------\n\n\nDomain Name:  SBC.ORG.HK\n\nDomain Status: Active\n\nDNSSEC:  unsigned\n\nContract Version:   HKDNR latest version\n\nActive variants\n\nInactive variants\n\nRegistrar Name: Hong Kong Domain Name Registration Company Limited\n\nRegistrar Contact Information: Email: enquiry@hkdnr.hk                       Hotline: +852 2319 1313\n\nReseller:\n\n\nRegistrant Contact Information:\n\nCompany English Name (It should be the same as the registered/corporation name on your Business Register Certificate or relevant documents): SOCIETY OF BOYS' CENTRES\nCompany Chinese name:  香港扶幼會\nAddress:  47 CORNWALL STREET, SHAMSHUIPO, KOWLOON\nCountry: Hong Kong (HK)\nEmail:  admin@sbc.org.hk\nDomain Name Commencement Date: 14-07-1998\nExpiry Date: 07-03-2020\nRe-registration Status:  Complete\n\n\n\nAdministrative Contact Information:\n\nGiven name:  BOYS' CENTRES\nFamily name:  SOCIETY OF\nCompany name:  SOCIETY OF BOYS' CENTRES\nAddress:  47 CORNWALL STREET, SHAMSHUIPO, KOWLOON\nCountry:  Hong Kong (HK)\nPhone:  +852-27796442\nFax:  +852-27793622\nEmail:  admin@sbc.org.hk\nAccount Name:  HK4375390T\n\n\n\nTechnical Contact Information:\n\nGiven name:  BOYS' CENTRES\nFamily name:  SOCIETY OF\nCompany name:  SOCIETY OF BOYS' CENTRES\nAddress:  47 CORNWALL STREET, SHAMSHUIPO, KOWLOON\nCountry:  Hong Kong (HK)\nPhone:  +852-27796442\nFax:  +852-27793622\nEmail:  admin@sbc.org.hk\n\nName Servers Information:\n\nNS19.ODYSSEYHOST.COM\nNS20.ODYSSEYHOST.COM\n\nStatus Information:\n\nDomain Prohibit Status:\n\n\n\n -------------------------------------------------------------------------------\n The Registry contains ONLY .com.hk, .net.hk, .edu.hk, .org.hk,\n .gov.hk, idv.hk. and .hk $domains.\n -------------------------------------------------------------------------------\n\nWHOIS Terms of Use\nBy using this WHOIS search enquiry service you agree to these terms of use.\nThe data in HKDNR's WHOIS search engine is for information purposes only and HKDNR does not guarantee the accuracy of the data. The data is provided to assist people to obtain information about the registration record of domain names registered by HKDNR. You agree to use the data for lawful purposes only.\nYou are not authorised to use high-volume, electronic or automated processes to access, query or harvest data from this WHOIS search enquiry service.\nYou agree that you will not and will not allow anyone else to:\na.    use the data for mass unsolicited commercial advertising of any sort via any medium including telephone, email or fax; or\nb.    enable high volume, automated or electronic processes that apply to HKDNR or its computer systems including the WHOIS search enquiry service; or\nc.    without the prior written consent of HKDNR compile, repackage, disseminate, disclose to any third party or use the data for a purpose other than obtaining information about a domain name registration record; or\nd.    use such data to derive an economic benefit for yourself.\nHKDNR in its sole discretion may terminate your access to the WHOIS search enquiry service (including, without limitation, blocking your IP address) at any time including, without limitation, for excessive use of the WHOIS search enquiry service.\nHKDNR may modify these terms of use at any time by publishing the modified terms of use on its website."
  },
  {
    "path": "test/samples/whois/seal.jobs",
    "content": "   Domain Name: SEAL.JOBS\n   Registry Domain ID: 128797919_DOMAIN_JOBS-VRSN\n   Registrar WHOIS Server: whois.godaddy.com\n   Registrar URL: http://www.godaddy.com\n   Updated Date: 2018-03-22T13:44:07Z\n   Creation Date: 2017-02-25T06:26:32Z\n   Registry Expiry Date: 2022-02-25T06:26:32Z\n   Registrar: GoDaddy.com, LLC\n   Registrar IANA ID: 146\n   Registrar Abuse Contact Email: email@godaddy.com\n   Registrar Abuse Contact Phone: 480-624-2505\n   Domain Status: ok https://icann.org/epp#ok\n   Registry Registrant ID: REDACTED FOR PRIVACY\n   Registrant Name: REDACTED FOR PRIVACY\n   Registrant Organization: Seal Jobs NV\n   Registrant Street: REDACTED FOR PRIVACY\n   Registrant City: REDACTED FOR PRIVACY\n   Registrant State/Province: Oost-Vlaanderen\n   Registrant Postal Code: REDACTED FOR PRIVACY\n   Registrant Country: BE\n   Registrant Phone: REDACTED FOR PRIVACY\n   Registrant Phone Ext: REDACTED FOR PRIVACY\n   Registrant Fax: REDACTED FOR PRIVACY\n   Registrant Fax Ext: REDACTED FOR PRIVACY\n   Registrant Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain.\n   Registry Admin ID: REDACTED FOR PRIVACY\n   Admin Name: REDACTED FOR PRIVACY\n   Admin Organization: REDACTED FOR PRIVACY\n   Admin Street: REDACTED FOR PRIVACY\n   Admin City: REDACTED FOR PRIVACY\n   Admin State/Province: REDACTED FOR PRIVACY\n   Admin Postal Code: REDACTED FOR PRIVACY\n   Admin Country: REDACTED FOR PRIVACY\n   Admin Phone: REDACTED FOR PRIVACY\n   Admin Phone Ext: REDACTED FOR PRIVACY\n   Admin Fax: REDACTED FOR PRIVACY\n   Admin Fax Ext: REDACTED FOR PRIVACY\n   Admin Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain.\n   Registry Tech ID: REDACTED FOR PRIVACY\n   Tech Name: REDACTED FOR PRIVACY\n   Tech Organization: REDACTED FOR PRIVACY\n   Tech Street: REDACTED FOR PRIVACY\n   Tech City: REDACTED FOR PRIVACY\n   Tech State/Province: REDACTED FOR PRIVACY\n   Tech Postal Code: REDACTED FOR PRIVACY\n   Tech Country: REDACTED FOR PRIVACY\n   Tech Phone: REDACTED FOR PRIVACY\n   Tech Phone Ext: REDACTED FOR PRIVACY\n   Tech Fax: REDACTED FOR PRIVACY\n   Tech Fax Ext: REDACTED FOR PRIVACY\n   Tech Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain.\n   Name Server: PDNS13.DOMAINCONTROL.COM\n   Name Server: PDNS14.DOMAINCONTROL.COM\n   DNSSEC: unsigned\n   Registry Billing ID: REDACTED FOR PRIVACY\n   Billing Name: REDACTED FOR PRIVACY\n   Billing Organization: REDACTED FOR PRIVACY\n   Billing Street: REDACTED FOR PRIVACY\n   Billing City: REDACTED FOR PRIVACY\n   Billing State/Province: REDACTED FOR PRIVACY\n   Billing Postal Code: REDACTED FOR PRIVACY\n   Billing Country: REDACTED FOR PRIVACY\n   Billing Phone: REDACTED FOR PRIVACY\n   Billing Phone Ext: REDACTED FOR PRIVACY\n   Billing Fax: REDACTED FOR PRIVACY\n   Billing Fax Ext: REDACTED FOR PRIVACY\n   Billing Email: Please query the RDDS service of the Registrar of Record identified in this output for information on how to contact the Registrant, Admin, or Tech contact of the queried domain.\n   URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of WHOIS database: 2019-04-17T11:27:11Z <<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\nNOTICE: The expiration date displayed in this record is the date the\nregistrar's sponsorship of the domain name registration in the registry is\ncurrently set to expire. This date does not necessarily reflect the\nexpiration date of the domain name registrant's agreement with the\nsponsoring registrar.  Users may consult the sponsoring registrar's\nWhois database to view the registrar's reported date of expiration\nfor this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois\ndatabase through the use of electronic processes that are high-volume and\nautomated except as reasonably necessary to register domain names or\nmodify existing registrations; the Data in VeriSign's (\"VeriSign\") Whois\ndatabase is provided by VeriSign for information purposes only, and to\nassist persons in obtaining information about or related to a domain name\nregistration record. VeriSign does not guarantee its accuracy.\nBy submitting a Whois query, you agree to abide by the following terms of\nuse: You agree that you may use this Data only for lawful purposes and that\nunder no circumstances will you use this Data to: (1) allow, enable, or\notherwise support the transmission of mass unsolicited, commercial\nadvertising or solicitations via e-mail, telephone, or facsimile; or\n(2) enable high volume, automated, electronic processes that apply to\nVeriSign (or its computer systems). The compilation, repackaging,\ndissemination or other use of this Data is expressly prohibited without\nthe prior written consent of VeriSign. You agree not to use electronic\nprocesses that are automated and high-volume to access or query the\nWhois database except as reasonably necessary to register domain names\nor modify existing registrations. VeriSign reserves the right to restrict\nyour access to the Whois database in its sole discretion to ensure\noperational stability.  VeriSign may restrict or terminate your access to the\nWhois database for failure to abide by these terms of use. VeriSign\nreserves the right to modify these terms at any time."
  },
  {
    "path": "test/samples/whois/shazow.net",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Domain Name: SHAZOW.NET\n   Registrar: NEW DREAM NETWORK, LLC\n   Whois Server: whois.dreamhost.com\n   Referral URL: http://www.dreamhost.com\n   Name Server: NS1.DREAMHOST.COM\n   Name Server: NS2.DREAMHOST.COM\n   Name Server: NS3.DREAMHOST.COM\n   Status: ok\n   Updated Date: 08-aug-2007\n   Creation Date: 13-sep-2003\n   Expiration Date: 13-sep-2009\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:39:08 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.\nLegal Stuff:\n\nThe information in DreamHost's whois database is to be used for\ninformational purposes only, and to obtain information on a\ndomain name registration. DreamHost does not guarantee its\naccuracy.\n\nYou are not authorized to query or access DreamHost's whois\ndatabase using high-volume, automated means without written\npermission from DreamHost.\n\nYou are not authorized to query or access DreamHost's whois\ndatabase in order to facilitate illegal activities, or to\nfacilitate the use of unsolicited bulk email, telephone, or\nfacsimile communications.\n\nYou are not authorized to collect, repackage, or redistribute the\ninformation in DreamHost's whois database.\n\nDreamHost may, at its sole discretion, restrict your access to\nthe whois database at any time, with or without notice. DreamHost\nmay modify these Terms of Service at any time, with or without\nnotice.\n\n+++++++++++++++++++++++++++++++++++++++++++\n\n   Domain Name: shazow.net\n\n   Registrant Contact:\n      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com\n      DreamHost Web Hosting\n      417 Associated Rd #324\n      Brea, CA 92821\n      US\n      +1.2139471032\n\n   Administrative Contact:\n      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com\n      DreamHost Web Hosting\n      417 Associated Rd #324\n      Brea, CA 92821\n      US\n      +1.2139471032\n\n   Technical Contact:\n      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com\n      DreamHost Web Hosting\n      417 Associated Rd #324\n      Brea, CA 92821\n      US\n      +1.2139471032\n\n   Billing Contact:\n      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com\n      DreamHost Web Hosting\n      417 Associated Rd #324\n      Brea, CA 92821\n      US\n      +1.2139471032\n\n   Record created on 2003-09-12 21:43:11.\n   Record expires on 2009-09-12 21:43:11.\n\n   Domain servers in listed order:\n\n      ns1.dreamhost.com\n      ns2.dreamhost.com\n      ns3.dreamhost.com\n\nDreamHost whois server terms of service: http://whois.dreamhost.com/terms.html\n"
  },
  {
    "path": "test/samples/whois/slashdot.org",
    "content": "NOTICE: Access to .ORG WHOIS information is provided to assist persons in \r\ndetermining the contents of a domain name registration record in the Public Interest Registry\r\nregistry database. The data in this record is provided by Public Interest Registry\r\nfor informational purposes only, and Public Interest Registry does not guarantee its \r\naccuracy.  This service is intended only for query-based access.  You agree \r\nthat you will use this data only for lawful purposes and that, under no \r\ncircumstances will you use this data to: (a) allow, enable, or otherwise \r\nsupport the transmission by e-mail, telephone, or facsimile of mass \r\nunsolicited, commercial advertising or solicitations to entities other than \r\nthe data recipient's own existing customers; or (b) enable high volume, \r\nautomated, electronic processes that send queries or data to the systems of \r\nRegistry Operator or any ICANN-Accredited Registrar, except as reasonably \r\nnecessary to register domain names or modify existing registrations.  All \r\nrights reserved. Public Interest Registry reserves the right to modify these terms at any \r\ntime. By submitting this query, you agree to abide by this policy. \r\n\r\nDomain ID:D2289308-LROR\r\nDomain Name:SLASHDOT.ORG\r\nCreated On:05-Oct-1997 04:00:00 UTC\r\nLast Updated On:23-Jun-2008 20:00:11 UTC\r\nExpiration Date:04-Oct-2008 04:00:00 UTC\r\nSponsoring Registrar:Tucows Inc. (R11-LROR)\r\nStatus:OK\r\nRegistrant ID:tuIIldggGKu3HogX\r\nRegistrant Name:DNS Administration\r\nRegistrant Organization:SourceForge, Inc.\r\nRegistrant Street1:650 Castro St.\r\nRegistrant Street2:Suite 450\r\nRegistrant Street3:\r\nRegistrant City:Mountain View\r\nRegistrant State/Province:CA\r\nRegistrant Postal Code:94041\r\nRegistrant Country:US\r\nRegistrant Phone:+1.6506942100\r\nRegistrant Phone Ext.:\r\nRegistrant FAX:\r\nRegistrant FAX Ext.:\r\nRegistrant Email:dns-admin@corp.sourceforge.com\r\nAdmin ID:tupyrGGXKEFJLdE5\r\nAdmin Name:DNS Administration\r\nAdmin Organization:SourceForge, Inc.\r\nAdmin Street1:650 Castro St.\r\nAdmin Street2:Suite 450\r\nAdmin Street3:\r\nAdmin City:Mountain View\r\nAdmin State/Province:CA\r\nAdmin Postal Code:94041\r\nAdmin Country:US\r\nAdmin Phone:+1.6506942100\r\nAdmin Phone Ext.:\r\nAdmin FAX:\r\nAdmin FAX Ext.:\r\nAdmin Email:dns-admin@corp.sourceforge.com\r\nTech ID:tuLQk02WUyJi47SS\r\nTech Name:DNS Technical\r\nTech Organization:SourceForge, Inc.\r\nTech Street1:650 Castro St.\r\nTech Street2:Suite 450\r\nTech Street3:\r\nTech City:Mountain View\r\nTech State/Province:CA\r\nTech Postal Code:94041\r\nTech Country:US\r\nTech Phone:+1.6506942100\r\nTech Phone Ext.:\r\nTech FAX:\r\nTech FAX Ext.:\r\nTech Email:dns-tech@corp.sourceforge.com\r\nName Server:NS-1.CH3.SOURCEFORGE.COM\r\nName Server:NS-2.CH3.SOURCEFORGE.COM\r\nName Server:NS-3.CORP.SOURCEFORGE.COM\r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\nName Server: \r\n\r\n\n"
  },
  {
    "path": "test/samples/whois/squatter.net",
    "content": "\nWhois Server Version 2.0\n\nDomain names in the .com and .net domains can now be registered\nwith many different competing registrars. Go to http://www.internic.net\nfor detailed information.\n\n   Domain Name: SQUATTER.NET\n   Registrar: DOMAINDISCOVER\n   Whois Server: whois.domaindiscover.com\n   Referral URL: http://www.domaindiscover.com\n   Name Server: NS1.SBRACK.COM\n   Name Server: NS2.SBRACK.COM\n   Status: clientTransferProhibited\n   Updated Date: 07-nov-2007\n   Creation Date: 06-nov-1999\n   Expiration Date: 06-nov-2008\n\n>>> Last update of whois database: Thu, 26 Jun 2008 21:40:25 EDT <<<\n\nNOTICE: The expiration date displayed in this record is the date the \nregistrar's sponsorship of the domain name registration in the registry is \ncurrently set to expire. This date does not necessarily reflect the expiration \ndate of the domain name registrant's agreement with the sponsoring \nregistrar.  Users may consult the sponsoring registrar's Whois database to \nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois \ndatabase through the use of electronic processes that are high-volume and \nautomated except as reasonably necessary to register domain names or \nmodify existing registrations; the Data in VeriSign Global Registry \nServices' (\"VeriSign\") Whois database is provided by VeriSign for \ninformation purposes only, and to assist persons in obtaining information \nabout or related to a domain name registration record. VeriSign does not \nguarantee its accuracy. By submitting a Whois query, you agree to abide \nby the following terms of use: You agree that you may use this Data only \nfor lawful purposes and that under no circumstances will you use this Data \nto: (1) allow, enable, or otherwise support the transmission of mass \nunsolicited, commercial advertising or solicitations via e-mail, telephone, \nor facsimile; or (2) enable high volume, automated, electronic processes \nthat apply to VeriSign (or its computer systems). The compilation, \nrepackaging, dissemination or other use of this Data is expressly \nprohibited without the prior written consent of VeriSign. You agree not to \nuse electronic processes that are automated and high-volume to access or \nquery the Whois database except as reasonably necessary to register \ndomain names or modify existing registrations. VeriSign reserves the right \nto restrict your access to the Whois database in its sole discretion to ensure \noperational stability.  VeriSign may restrict or terminate your access to the \nWhois database for failure to abide by these terms of use. VeriSign \nreserves the right to modify these terms at any time. \n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars.\nThis WHOIS database is provided for information purposes only. We do\nnot guarantee the accuracy of this data. The following uses of this \nsystem are expressly prohibited: (1) use of this system for unlawful \npurposes; (2) use of this system to collect information used in the \nmass transmission of unsolicited commercial messages in any medium; \n(3) use of high volume, automated, electronic processes against this \ndatabase. By submitting this query, you agree to abide by this \npolicy.\n\nRegistrant:\n   CustomPC\n   4047 N Bayberry St\n   Wichita, KS 67226-2418\n   US\n\n   Domain Name: SQUATTER.NET\n\n   Administrative Contact:\n      CustomPC\n      Derryl Brack\n      4047 N Bayberry St\n      Wichita, KS 67226-2418\n      US\n      3166402868\n      dbrack@cpcsales.com\n\n   Technical Contact, Zone Contact:\n      CustomPC\n      Brack, Derryl\n      4047 N Bayberry St\n      Wichita, KS 67226-2418\n      US\n      316-683-5010\n      316-683-5010 [fax]\n      brack@cpcsales.com\n\n   Domain created on 06-Nov-1999\n   Domain expires on 06-Nov-2008\n   Last updated on 05-Nov-2007\n\n   Domain servers in listed order:\n\n      NS1.SBRACK.COM              \n      NS2.SBRACK.COM              \n\nDomain registration and hosting powered by DomainDiscover\nAs low as $9/year, including FREE: responsive toll-free support, \nURL/frame/email forwarding, easy management system, and full featured DNS.\n\n"
  },
  {
    "path": "test/samples/whois/titech.ac.jp",
    "content": "[ JPRS database provides information on network administration. Its use is    ]\n[ restricted to network administration purposes. For further information,     ]\n[ use 'whois -h whois.jprs.jp help'. To suppress Japanese output, add'/e'     ]\n[ at the end of command, e.g. 'whois -h whois.jprs.jp xxx/e'.                 ]\nDomain Information:\na. [Domain Name]                TITECH.AC.JP\ng. [Organization]               Institute of Science Tokyo\nl. [Organization Type]          University\nm. [Administrative Contact]     YK87359JP\nn. [Technical Contact]          YS79730JP\np. [Name Server]                ns.fujisawa.wide.ad.jp\np. [Name Server]                titechns2-o.noc.titech.ac.jp\np. [Name Server]                titechns2-s.noc.titech.ac.jp\ns. [Signing Key]\n[State]                         Connected (2026/03/31)\n[Registered Date]\n[Connected Date]                2025/05/26\n[Last Update]                   2025/05/29 10:45:59 (JST)\n"
  },
  {
    "path": "test/samples/whois/urlowl.com",
    "content": "\n\n   Domain Name: URLOWL.COM\n   Registry Domain ID: 1781848049_DOMAIN_COM-VRSN\n   Registrar WHOIS Server: whois.dynadot.com\n   Registrar URL: http://www.dynadot.com\n   Updated Date: 2017-03-31T07:36:34Z\n   Creation Date: 2013-02-21T19:24:57Z\n   Registry Expiry Date: 2018-02-21T19:24:57Z\n   Registrar: DYNADOT, LLC\n   Registrar IANA ID: 472\n   Registrar Abuse Contact Email: abuse@dynadot.com\n   Registrar Abuse Contact Phone: +16502620100\n   Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\n   Name Server: NS1.SEDOPARKING.COM\n   Name Server: NS2.SEDOPARKING.COM\n   DNSSEC: unsigned\n   URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/\n>>> Last update of whois database: 2017-12-11T23:35:30Z <<<\n\nFor more information on Whois status codes, please visit https://icann.org/epp\n\nNOTICE: The expiration date displayed in this record is the date the\nregistrar's sponsorship of the domain name registration in the registry is\ncurrently set to expire. This date does not necessarily reflect the expiration\ndate of the domain name registrant's agreement with the sponsoring\nregistrar.  Users may consult the sponsoring registrar's Whois database to\nview the registrar's reported date of expiration for this registration.\n\nTERMS OF USE: You are not authorized to access or query our Whois\ndatabase through the use of electronic processes that are high-volume and\nautomated except as reasonably necessary to register domain names or\nmodify existing registrations; the Data in VeriSign Global Registry\nServices' (\"VeriSign\") Whois database is provided by VeriSign for\ninformation purposes only, and to assist persons in obtaining information\nabout or related to a domain name registration record. VeriSign does not\nguarantee its accuracy. By submitting a Whois query, you agree to abide\nby the following terms of use: You agree that you may use this Data only\nfor lawful purposes and that under no circumstances will you use this Data\nto: (1) allow, enable, or otherwise support the transmission of mass\nunsolicited, commercial advertising or solicitations via e-mail, telephone,\nor facsimile; or (2) enable high volume, automated, electronic processes\nthat apply to VeriSign (or its computer systems). The compilation,\nrepackaging, dissemination or other use of this Data is expressly\nprohibited without the prior written consent of VeriSign. You agree not to\nuse electronic processes that are automated and high-volume to access or\nquery the Whois database except as reasonably necessary to register\ndomain names or modify existing registrations. VeriSign reserves the right\nto restrict your access to the Whois database in its sole discretion to ensure\noperational stability.  VeriSign may restrict or terminate your access to the\nWhois database for failure to abide by these terms of use. VeriSign\nreserves the right to modify these terms at any time.\n\nThe Registry database contains ONLY .COM, .NET, .EDU domains and\nRegistrars."
  },
  {
    "path": "test/samples/whois/web.de",
    "content": "% Copyright (c) 2010 by DENIC\r\n% Version: 2.0\r\n%\r\n% Restricted rights.\r\n%\r\n% Terms and Conditions of Use\r\n%\r\n% The data in this record is provided by DENIC for informational purposes only.\r\n% DENIC does not guarantee its accuracy and cannot, under any circumstances,\r\n% be held liable in case the stored information would prove to be wrong,\r\n% incomplete or not accurate in any sense.\r\n%\r\n% All the domain data that is visible in the whois service is protected by law.\r\n% It is not permitted to use it for any purpose other than technical or\r\n% administrative requirements associated with the operation of the Internet.\r\n% It is explicitly forbidden to extract, copy and/or use or re-utilise in any\r\n% form and by any means (electronically or not) the whole or a quantitatively\r\n% or qualitatively substantial part of the contents of the whois database\r\n% without prior and explicit written permission by DENIC.\r\n% It is prohibited, in particular, to use it for transmission of unsolicited\r\n% and/or commercial and/or advertising by phone, fax, e-mail or for any similar\r\n% purposes.\r\n%\r\n% By maintaining the connection you assure that you have a legitimate interest\r\n% in the data and that you will only use it for the stated purposes. You are\r\n% aware that DENIC maintains the right to initiate legal proceedings against\r\n% you in the event of any breach of this assurance and to bar you from using\r\n% its whois service.\r\n%\r\n% The DENIC whois service on port 43 never discloses any information concerning\r\n% the domain holder/administrative contact. Information concerning the domain\r\n% holder/administrative contact can be obtained through use of our web-based\r\n% whois service available at the DENIC website:\r\n% http://www.denic.de/en/domains/whois-service/web-whois.html\r\n%\r\n\r\nDomain: web.de\r\nNserver: ns-webde.ui-dns.biz\r\nNserver: ns-webde.ui-dns.com\r\nNserver: ns-webde.ui-dns.de\r\nNserver: ns-webde.ui-dns.org\r\nDnskey: 257 3 8 AwEAAcBs30zgmOeYcUYzJetRzRYGQXlnXpv2gO3KWf5BYRn9OqFtUBzFOqO16Ow2XPqR8SWqpAVpnToQICICZyf58SHaefGn94fTj+PlwJi4HhoCbim2U3G5sYtl5xoNfUCaDXDQFJp+HnZlaA9afHutOVFtqCmMHV+2ApSyOFFETQNmq4YoxLxiJoxSjvQAaaiJKVoA4wykjXALMyCmbXGH4aMVbW2m0Fuqe+nKU8myW14nCASBo0mDO6cBNsBwu7IiL4SxxnflDCSTkn/FnCKtzf7aVzzrRM4SqTe4NOm7wPmCZiAGoxOL15PZ7YQSt9BEXU6gMdGxCGVBdtgM13NfziM=\r\nStatus: connect\r\nChanged: 2016-04-11T11:09:54+02:00\r\n\r\n[Tech-C]\r\nType: PERSON\r\nName: Hostmaster of the day\r\nAddress: Elgendorfer Str. 57\r\nPostalCode: 56410\r\nCity: Montabaur\r\nCountryCode: DE\r\nPhone: +49-721-9600\r\nFax: +49-721-91374-215\r\nEmail: ui-hostmaster@1and1.com\r\nChanged: 2011-08-10T17:09:10+02:00\r\n\r\n[Zone-C]\r\nType: PERSON\r\nName: Hostmaster of the day\r\nAddress: Elgendorfer Str. 57\r\nPostalCode: 56410\r\nCity: Montabaur\r\nCountryCode: DE\r\nPhone: +49-721-9600\r\nFax: +49-721-91374-215\r\nEmail: ui-hostmaster@1and1.com\r\nChanged: 2011-08-10T17:09:10+02:00\r\n"
  },
  {
    "path": "test/samples/whois/willhaben.at",
    "content": "% Copyright (c)2017 by NIC.AT (1)\r\n%\r\n% Restricted rights.\r\n%\r\n% Except  for  agreed Internet  operational  purposes, no  part  of this\r\n% information  may  be reproduced,  stored  in  a  retrieval  system, or\r\n% transmitted, in  any  form  or by  any means,  electronic, mechanical,\r\n% recording, or otherwise, without prior  permission of NIC.AT on behalf\r\n% of itself and/or the copyright  holders.  Any use of this  material to\r\n% target advertising  or similar activities is explicitly  forbidden and\r\n% can be prosecuted.\r\n%\r\n% It is furthermore strictly forbidden to use the Whois-Database in such\r\n% a  way  that  jeopardizes or  could jeopardize  the  stability  of the\r\n% technical  systems of  NIC.AT  under any circumstances. In particular,\r\n% this includes  any misuse  of the  Whois-Database and  any  use of the\r\n% Whois-Database which disturbs its operation.\r\n%\r\n% Should the  user violate  these points,  NIC.AT reserves  the right to\r\n% deactivate  the  Whois-Database   entirely  or  partly  for  the user.\r\n% Moreover,  the  user  shall be  held liable  for  any  and all  damage\r\n% arising from a violation of these points.\r\n\r\ndomain:         willhaben.at\r\nregistrant:     WISG8002269-NICAT\r\nadmin-c:        SISG4765752-NICAT\r\ntech-c:         SISG4765752-NICAT\r\nnserver:        srvkkl-dns01.styria.com\r\nnserver:        srvsgr-dns02.styria.com\r\nnserver:        srvvie-dns03.styria.com\r\nchanged:        20141204 14:57:44\r\nsource:         AT-DOM\r\n\r\npersonname:     Mirjam Techt\r\norganization:   willhaben internet service GmbH & Co KG\r\nstreet address: Landstrasser Hauptstrasse 97-101\r\npostal code:    1030\r\ncity:           Wien\r\ncountry:        Austria\r\nphone:          +4312055000\r\ne-mail:         domain@styria-it.com\r\nnic-hdl:        WISG8002269-NICAT\r\nchanged:        20140422 10:08:35\r\nsource:         AT-DOM\r\n\r\npersonname:     Uwe Holzer\r\norganization:   Styria IT Solutions GmbH & Co KG\r\nstreet address: Gadollaplatz 1\r\npostal code:    8010\r\ncity:           Graz\r\ncountry:        Austria\r\nphone:          +434635800304\r\nfax-no:         +434635800296\r\ne-mail:         domain@styria-it.com\r\nnic-hdl:        SISG4765752-NICAT\r\nchanged:        20151021 16:23:11\r\nsource:         AT-DOM\r\n\r\n"
  },
  {
    "path": "test/samples/whois/www.gov.uk",
    "content": "    Domain name:\n        gov.uk\n\n    Registrant:\n        UK Cabinet Office\n\n    Registrant type:\n        UK Government Body\n\n    Registrant's address:\n        Government Digital Service\n        The White Chapel Building 7th Floor\n        10 Whitechapel High Street\n        London\n        E1 8QS\n        GB\n\n    Registrar:\n        No registrar listed.  This domain is directly registered with Nominet.\n\n    Relevant dates:\n        Registered on: before Aug-1996\n    Registration status:\n        No registration status listed.\n\n    Name servers:\n        ns0.ja.net.\n        ns2.ja.net.\n        ns3.ja.net.\n        ns4.ja.net.\n        auth50.ns.de.uu.net.\n        auth00.ns.de.uu.net.\n        ns1.surfnet.nl.\n\n    WHOIS lookup made at 12:02:52 18-Apr-2019\n\n--\nThis WHOIS information is provided for free by Nominet UK the central registry\nfor .uk domain names. This information and the .uk WHOIS are:\n\n    Copyright Nominet UK 1996 - 2019.\n\nYou may not access the .uk WHOIS or use any data from it except as permitted\nby the terms of use available in full at https://www.nominet.uk/whoisterms,\nwhich includes restrictions on: (A) use of the data for advertising, or its\nrepackaging, recompilation, redistribution or reuse (B) obscuring, removing\nor hiding any or all of this notice and (C) exceeding query rate or volume\nlimits. The data is provided on an 'as-is' basis and may lag behind the\nregister. Access may be withdrawn or restricted at any time."
  },
  {
    "path": "test/samples/whois/yahoo.co.jp",
    "content": "[ JPRS database provides information on network administration. Its use is    ]\n[ restricted to network administration purposes. For further information,     ]\n[ use 'whois -h whois.jprs.jp help'. To suppress Japanese output, add'/e'     ]\n[ at the end of command, e.g. 'whois -h whois.jprs.jp xxx/e'.                 ]\nDomain Information:\na. [Domain Name]                YAHOO.CO.JP\ng. [Organization]               LY Corporation\nl. [Organization Type]          Corporation\nm. [Administrative Contact]     HT57990JP\nn. [Technical Contact]          YY47022JP\np. [Name Server]                ns01.yahoo.co.jp\np. [Name Server]                ns02.yahoo.co.jp\np. [Name Server]                ns11.yahoo.co.jp\np. [Name Server]                ns12.yahoo.co.jp\ns. [Signing Key]\n[State]                         Connected (2025/09/30)\n[Lock Status]                   AgentChangeLocked\n[Registered Date]               2019/09/27\n[Connected Date]                2019/09/27\n[Last Update]                   2024/10/01 01:00:44 (JST)\n"
  },
  {
    "path": "test/samples/whois/yahoo.co.nz",
    "content": "Domain Name: yahoo.co.nz\nRegistrar URL: https://www.markmonitor.com/\nUpdated Date: 2025-04-07T09:13:29Z\nCreation Date: 1997-05-04T12:00:00Z\nOriginal Created: 1997-05-04T12:00:00Z\nRegistrar: MarkMonitor. Inc\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nName Server: ns1.yahoo.com\nName Server: ns3.yahoo.com\nName Server: ns4.yahoo.com\nName Server: ns5.yahoo.com\nDNSSEC: unsigned\nURL of the Domain Name Commission Limited Inaccuracy Complaint Form: https://dnc.org.nz/enquiry-form/\n>>> Last update of WHOIS database: 2025-09-23T16:12:23Z <<<\n\n% Terms of Use\n%\n% By submitting a WHOIS query you are entering into an agreement with Domain\n% Name Commission Ltd on the following terms and conditions, and subject to\n% all relevant .nz Policies and procedures as found at https://dnc.org.nz/.\n%\n% It is prohibited to:\n% - Send high volume WHOIS queries with the effect of downloading part of or\n%   all of the .nz Register or collecting register data or records;\n% - Access the .nz Register in bulk through the WHOIS service (ie. where a\n%   user is able to access WHOIS data other than by sending individual queries\n%   to the database);\n% - Use WHOIS data to allow, enable, or otherwise support mass unsolicited\n%   commercial advertising, or mass solicitations to registrants or to\n%   undertake market research via direct mail, electronic mail, SMS, telephone\n%   or any other medium;\n% - Use WHOIS data in contravention of any applicable data and privacy laws,\n%   including the Unsolicited Electronic Messages Act 2007;\n% - Store or compile WHOIS data to build up a secondary register of\n%   information;\n% - Publish historical or non-current versions of WHOIS data; and\n% - Publish any WHOIS data in bulk.\n%\n% Copyright Domain Name Commission Limited (a company wholly-owned by Internet\n% New Zealand Incorporated) which may enforce its rights against any person or\n% entity that undertakes any prohibited activity without its written\n% permission.\n%\n% The WHOIS service is provided by Internet New Zealand Incorporated.\n%\n% Additional information may be available at https://www.dnc.org.nz\n"
  },
  {
    "path": "test/samples/whois/yandex.kz",
    "content": "Whois Server for the KZ top level domain name.\r\nThis server is maintained by KazNIC Organization, a ccTLD manager for Kazakhstan Republic.\r\n\r\nDomain Name............: yandex.kz\r\n\r\nOrganization Using Domain Name\r\nName...................: Yandex.Kazakhstan LLP\r\nOrganization Name......: Yandex.Kazakhstan LLP\r\nStreet Address.........: Dostyk street 43\r\nCity...................: Almaty\r\nState..................: -\r\nPostal Code............: 050051\r\nCountry................: KZ\r\n\r\nAdministrative Contact/Agent\r\nNIC Handle.............: HOSTERKZ-280570\r\nName...................: Domain manager\r\nPhone Number...........: +7.4957397000\r\nFax Number.............: +7.4957397000\r\nEmail Address..........: hostmaster@yandex.net\r\n\r\nNameserver in listed order\r\n\r\nPrimary server.........: ns1.yandex.net\r\nPrimary ip address.....: 213.180.193.1\r\n\r\nSecondary server.......: ns2.yandex.net\r\nSecondary ip address...: 213.180.199.34\r\n\r\n\r\nDomain created: 2009-07-01 12:44:02 (GMT+0:00)\r\nLast modified : 2022-08-04 10:20:10 (GMT+0:00)\r\nDomain status : clientTransferProhibited - status prohibits domain transfer without documents (статус запрещает трансфер домена без предоставления документов)\r\n                clientDeleteProhibited - status prevent domain deletion from the Register (статус предотвращает удаление домена из реестра)\r\n                clientRenewProhibited - status prevent domain auto renewal without payment (статус предотвращает авто продление без оплаты)\r\n\r\nRegistar created: KAZNIC\r\nCurrent Registar: HOSTER.KZ\r\n"
  },
  {
    "path": "test/samples/whois/yandex.ru",
    "content": "% By submitting a query to RIPN's Whois Service\r\n% you agree to abide by the following terms of use:\r\n% http://www.ripn.net/about/servpol.html#3.2 (in Russian)\r\n% http://www.ripn.net/about/en/servpol.html#3.2 (in English).\r\n\r\ndomain:        YANDEX.RU\r\nnserver:       ns1.yandex.ru. 213.180.193.1, 2a02:6b8::1\r\nnserver:       ns2.yandex.ru. 93.158.134.1, 2a02:6b8:0:1::1\r\nnserver:       ns9.z5h64q92x9.net.\r\nstate:         REGISTERED, DELEGATED, VERIFIED\r\norg:           YANDEX, LLC.\r\nregistrar:     RU-CENTER-RU\r\nadmin-contact: https://www.nic.ru/whois\r\ncreated:       1997-09-23T09:45:07Z\r\npaid-till:     2018-09-30T21:00:00Z\r\nfree-date:     2018-11-01\r\nsource:        TCI\r\n\r\nLast updated on 2017-12-08T22:51:30Z\r\n\r\n"
  },
  {
    "path": "test/test_ipv6.py",
    "content": "import unittest\nfrom unittest.mock import patch\nimport socket\n\nfrom whois.whois import NICClient\n\n\nclass TestNICClientIPv6(unittest.TestCase):\n\n    def setUp(self):\n        self.ipv4_info = (socket.AF_INET, socket.SOCK_STREAM, 6, '', ('1.2.3.4', 43))\n        self.ipv6_info = (socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('2001:db8::1', 43, 0, 0))\n        self.mock_addr_info = [self.ipv4_info, self.ipv6_info]\n\n    @patch('socket.getaddrinfo')\n    @patch('socket.socket')\n    def test_connect_prioritizes_ipv6(self, mock_socket, mock_getaddrinfo):\n        mock_getaddrinfo.return_value = self.mock_addr_info\n\n        client = NICClient(prefer_ipv6=True)\n        try:\n            client._connect(\"example.com\", timeout=10)\n        except Exception:\n            pass\n\n        first_call_args = mock_socket.call_args_list[0][0]\n        # Make sure we used IPv6 when creating socket\n        self.assertEqual(first_call_args[0], socket.AF_INET6)\n\n    @patch('socket.getaddrinfo')\n    @patch('socket.socket')\n    def test_connect_keeps_default_order(self, mock_socket, mock_getaddrinfo):\n        mock_getaddrinfo.return_value = self.mock_addr_info\n\n        client = NICClient(prefer_ipv6=False)\n        try:\n            client._connect(\"example.com\", timeout=10)\n        except Exception:\n            pass\n\n        first_call_args = mock_socket.call_args_list[0][0]\n        # Make sure we used IPv4 when creating socket, which is the first appearing in our mock.\n        self.assertEqual(first_call_args[0], socket.AF_INET)\n"
  },
  {
    "path": "test/test_main.py",
    "content": "# coding=utf-8\n\nimport unittest\n\nfrom whois import extract_domain\n\n\nclass TestExtractDomain(unittest.TestCase):\n    def test_simple_ascii_domain(self):\n        url = \"google.com\"\n        domain = url\n        self.assertEqual(domain, extract_domain(url))\n\n    def test_ascii_with_schema_path_and_query(self):\n        url = \"https://www.google.com/search?q=why+is+domain+whois+such+a+mess\"\n        domain = \"google.com\"\n        self.assertEqual(domain, extract_domain(url))\n\n    def test_simple_unicode_domain(self):\n        url = \"http://нарояци.com/\"\n        domain = \"нарояци.com\"\n        self.assertEqual(domain, extract_domain(url))\n\n    def test_unicode_domain_and_tld(self):\n        url = \"http://россия.рф/\"\n        domain = \"россия.рф\"\n        self.assertEqual(domain, extract_domain(url))\n\n    def test_ipv6(self):\n        \"\"\"Verify that ipv6 addresses work\"\"\"\n        url = \"2607:f8b0:4006:802::200e\"\n        domain = \"1e100.net\"\n        # double extract_domain() so we avoid possibly changing hostnames like lga34s12-in-x0e.1e100.net\n        self.assertEqual(domain, extract_domain(extract_domain(url)))\n\n    def test_ipv4(self):\n        \"\"\"Verify that ipv4 addresses work\"\"\"\n        url = \"172.217.3.110\"\n        domain = \"1e100.net\"\n        # double extract_domain() so we avoid possibly changing hostnames like lga34s18-in-f14.1e100.net\n        self.assertEqual(domain, extract_domain(extract_domain(url)))\n\n    def test_second_level_domain(self):\n        \"\"\"Verify that TLDs which only have second-level domains parse correctly\"\"\"\n        url = \"google.co.za\"\n        domain = url\n        self.assertEqual(domain, extract_domain(url))\n"
  },
  {
    "path": "test/test_nicclient.py",
    "content": "# coding=utf-8\n\nimport unittest\n\nfrom whois.whois import NICClient\n\n\nclass TestNICClient(unittest.TestCase):\n    def setUp(self):\n        self.client = NICClient()\n\n    def test_choose_server(self):\n        domain = \"рнидс.срб\"\n        chosen = self.client.choose_server(domain)\n        correct = \"whois.rnids.rs\"\n        self.assertEqual(chosen, correct)\n"
  },
  {
    "path": "test/test_parser.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport datetime\nimport json\nimport os\nimport unittest\nfrom glob import glob\n\nfrom dateutil.tz import tzoffset\n\nfrom whois.exceptions import WhoisUnknownDateFormatError\nfrom whois.parser import (\n    WhoisCa,\n    WhoisEntry,\n    cast_date,\n    datetime_parse,\n)\n\nutc = tzoffset('UTC', 0)\n\n\nclass TestParser(unittest.TestCase):\n    def test_com_expiration(self):\n        data = \"\"\"\n        Status: ok\n        Updated Date: 2017-03-31T07:36:34Z\n        Creation Date: 2013-02-21T19:24:57Z\n        Registry Expiry Date: 2018-02-21T19:24:57Z\n\n        >>> Last update of whois database: Sun, 31 Aug 2008 00:18:23 UTC <<<\n        \"\"\"\n        w = WhoisEntry.load(\"urlowl.com\", data)\n        expires = w.expiration_date.strftime(\"%Y-%m-%d\")\n        self.assertEqual(expires, \"2018-02-21\")\n\n    def test_cast_date(self):\n        dates = [\n            \"14-apr-2008\",\n            \"2008-04-14\",\n            \"2008-04-14 18:55:20Z.0Z\",\n        ]\n        for d in dates:\n            r = cast_date(d).strftime(\"%Y-%m-%d\")\n            self.assertEqual(r, \"2008-04-14\")\n\n    def test_unknown_date_format(self):\n        with self.assertRaises(WhoisUnknownDateFormatError):\n            cast_date(\"UNKNOWN\")\n\n    def test_com_allsamples(self):\n        \"\"\"\n        Iterate over all of the sample/whois/*.com files, read the data,\n        parse it, and compare to the expected values in sample/expected/.\n        Only keys defined in keys_to_test will be tested.\n\n        To generate fresh expected value dumps, see NOTE below.\n        \"\"\"\n        keys_to_test = [\n            \"domain_name\",\n            \"expiration_date\",\n            \"updated_date\",\n            \"registrar\",\n            \"registrar_url\",\n            \"creation_date\",\n            \"status\",\n        ]\n        total = 0\n        whois_path = os.path.join(\n            os.path.dirname(os.path.abspath(__file__)), \"samples\", \"whois\", \"*\"\n        )\n        expect_path = os.path.join(\n            os.path.dirname(os.path.abspath(__file__)), \"samples\", \"expected\"\n        )\n        for path in glob(whois_path):\n            # Parse whois data\n            domain = os.path.basename(path)\n            with open(path, encoding=\"utf-8\") as whois_fp:\n                data = whois_fp.read()\n\n            w = WhoisEntry.load(domain, data)\n            results = {key: w.get(key) for key in keys_to_test}\n\n            # NOTE: Toggle condition below to write expected results from the\n            # parse results This will overwrite the existing expected results.\n            # Only do this if you've manually confirmed that the parser is\n            # generating correct values at its current state.\n            if False:\n\n                def date2str4json(obj):\n                    if isinstance(obj, datetime.datetime):\n                        return str(obj)\n                    raise TypeError(\"{} is not JSON serializable\".format(repr(obj)))\n\n                outfile_name = os.path.join(expect_path, domain)\n                with open(outfile_name, \"w\") as outfil:\n                    expected_results = json.dump(results, outfil, default=date2str4json)\n                continue\n\n            # Load expected result\n            with open(os.path.join(expect_path, domain)) as infil:\n                expected_results = json.load(infil)\n\n            # Compare each key\n            compare_keys = set.union(set(results), set(expected_results))\n            if keys_to_test is not None:\n                compare_keys = compare_keys.intersection(set(keys_to_test))\n            for key in compare_keys:\n                total += 1\n                self.assertIn(key, results)\n\n                result = results.get(key)\n                if isinstance(result, list):\n                    result = [str(element) for element in result]\n                if isinstance(result, datetime.datetime):\n                    result = str(result)\n                expected = expected_results.get(key)\n                self.assertEqual(expected, result, '{}: {} != {} for {}'.format(key, expected, result, domain))\n\n    def test_ca_parse(self):\n        data = \"\"\"\n        Domain name:           testdomain.ca\n        Domain status:         registered\n        Creation date:         2000/11/20\n        Expiry date:           2020/03/08\n        Updated date:          2016/04/29\n        DNSSEC:                Unsigned\n\n        Registrar:             Webnames.ca Inc.\n        Registry Registrant ID: 70\n\n        Registrant Name:       Test Industries\n        Registrant Organization:\n\n        Admin Name:            Test Person1\n        Admin Street:          Test Address\n        Admin City:            Test City, TestVille\n        Admin Phone:           +1.1235434123x123\n        Admin Fax:             +1.123434123\n        Admin Email:           testperson1@testcompany.ca\n\n        Tech Name:             Test Persion2\n        Tech Street:           Other TestAddress\n                               TestTown OCAS Canada\n        Tech Phone:            +1.09876545123\n        Tech Fax:              +1.12312993873\n        Tech Email:            testpersion2@testcompany.ca\n\n        Name server:           a1-1.akam.net\n        Name server:           a2-2.akam.net\n        Name server:           a3-3.akam.net\n        \"\"\"\n        expected_results = {\n            \"admin_name\": \"Test Person1\",\n            \"creation_date\": datetime.datetime(2000, 11, 20, 0, 0, tzinfo=utc),\n            \"dnssec\": \"Unsigned\",\n            \"domain_name\": \"testdomain.ca\",\n            \"emails\": [\"testperson1@testcompany.ca\", \"testpersion2@testcompany.ca\"],\n            \"expiration_date\": datetime.datetime(2020, 3, 8, 0, 0, tzinfo=utc),\n            \"fax\": [\"+1.123434123\", \"+1.12312993873\"],\n            \"name_servers\": [\"a1-1.akam.net\", \"a2-2.akam.net\", \"a3-3.akam.net\"],\n            \"phone\": [\"+1.1235434123x123\", \"+1.09876545123\"],\n            \"registrant_name\": \"Test Industries\",\n            \"registrant_number\": \"70\",\n            \"registrar\": \"Webnames.ca Inc.\",\n            \"registrar_url\": None,\n            \"status\": \"registered\",\n            \"updated_date\": datetime.datetime(2016, 4, 29, 0, 0, tzinfo=utc),\n            \"whois_server\": None,\n        }\n        self._parse_and_compare(\n            \"testcompany.ca\", data, expected_results, whois_entry=WhoisCa\n        )\n\n    def test_ai_parse(self):\n        data = \"\"\"\nDomain Name: google.ai\nRegistry Domain ID: 6eddd132ab114b12bd2bd4cf9c492a04-DONUTS\nRegistrar WHOIS Server: whois.markmonitor.com\nRegistrar URL: http://www.markmonitor.com\nUpdated Date: 2025-01-23T22:17:03Z\nCreation Date: 2017-12-16T05:37:20Z\nRegistry Expiry Date: 2025-09-25T05:37:20Z\nRegistrar: MarkMonitor Inc.\nRegistrar IANA ID: 292\nRegistrar Abuse Contact Email: abusecomplaints@markmonitor.com\nRegistrar Abuse Contact Phone: +1.2083895740\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nRegistry Registrant ID: 93b24aca40c6451785c486627aa03267-DONUTS\nRegistrant Name: Domain Administrator\nRegistrant Organization: Google LLC\nRegistrant Street: 1600 Amphitheatre Parkway\nRegistrant City: Mountain View\nRegistrant State/Province: CA\nRegistrant Postal Code: 94043\nRegistrant Country: US\nRegistrant Phone: +1.6502530000\nRegistrant Phone Ext: \nRegistrant Fax: +1.6502530001\nRegistrant Fax Ext: \nRegistrant Email: dns-admin@google.com\nRegistry Admin ID: 93b24aca40c6451785c486627aa03267-DONUTS\nAdmin Name: Domain Administrator\nAdmin Organization: Google LLC\nAdmin Street: 1600 Amphitheatre Parkway\nAdmin City: Mountain View\nAdmin State/Province: CA\nAdmin Postal Code: 94043\nAdmin Country: US\nAdmin Phone: +1.6502530000\nAdmin Phone Ext: \nAdmin Fax: +1.6502530001\nAdmin Fax Ext: \nAdmin Email: dns-admin@google.com\nRegistry Tech ID: 93b24aca40c6451785c486627aa03267-DONUTS\nTech Name: Domain Administrator\nTech Organization: Google LLC\nTech Street: 1600 Amphitheatre Parkway\nTech City: Mountain View\nTech State/Province: CA\nTech Postal Code: 94043\nTech Country: US\nTech Phone: +1.6502530000\nTech Phone Ext: \nTech Fax: +1.6502530001\nTech Fax Ext: \nTech Email: dns-admin@google.com\nName Server: ns2.zdns.google\nName Server: ns3.zdns.google\nName Server: ns4.zdns.google\nName Server: ns1.zdns.google\nDNSSEC: unsigned\n        \"\"\"\n\n        expected_results = {\n            \"admin_address\": \"1600 Amphitheatre Parkway\",\n            \"admin_city\": \"Mountain View\",\n            \"admin_country\": \"US\",\n            \"admin_email\": \"dns-admin@google.com\",\n            \"admin_name\": \"Domain Administrator\",\n            \"admin_org\": \"Google LLC\",\n            \"admin_phone\": \"+1.6502530000\",\n            \"admin_postal_code\": \"94043\",\n            \"admin_state\": \"CA\",\n            \"billing_address\": None,\n            \"billing_city\": None,\n            \"billing_country\": None,\n            \"billing_email\": None,\n            \"billing_name\": None,\n            \"billing_org\": None,\n            \"billing_phone\": None,\n            \"billing_postal_code\": None,\n            \"billing_state\": None,\n            \"creation_date\": datetime.datetime(2017, 12, 16, 5, 37, 20, tzinfo=utc),\n            \"domain_id\": \"6eddd132ab114b12bd2bd4cf9c492a04-DONUTS\",\n            \"domain_name\": \"google.ai\",\n            'expiration_date': datetime.datetime(2025, 9, 25, 5, 37, 20, tzinfo=utc),\n            \"name_servers\": [\n                \"ns2.zdns.google\",\n                \"ns3.zdns.google\",\n                \"ns4.zdns.google\",\n                \"ns1.zdns.google\",\n            ],\n            \"registrant_address\": \"1600 Amphitheatre Parkway\",\n            \"registrant_city\": \"Mountain View\",\n            \"registrant_country\": \"US\",\n            \"registrant_email\": \"dns-admin@google.com\",\n            \"registrant_name\": \"Domain Administrator\",\n            \"registrant_org\": \"Google LLC\",\n            \"registrant_phone\": \"+1.6502530000\",\n            \"registrant_postal_code\": \"94043\",\n            \"registrant_state\": \"CA\",\n            \"registrar\": \"MarkMonitor Inc.\",\n            \"registrar_email\": \"abusecomplaints@markmonitor.com\",\n            \"registrar_phone\": \"+1.2083895740\",\n            \"tech_address\": \"1600 Amphitheatre Parkway\",\n            \"tech_city\": \"Mountain View\",\n            \"tech_country\": \"US\",\n            \"tech_email\": \"dns-admin@google.com\",\n            \"tech_name\": \"Domain Administrator\",\n            \"tech_org\": \"Google LLC\",\n            \"tech_phone\": \"+1.6502530000\",\n            \"tech_postal_code\": \"94043\",\n            \"tech_state\": \"CA\",\n            \"status\": [\n                'clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited',\n                'clientTransferProhibited https://icann.org/epp#clientTransferProhibited',\n                'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited'\n            ],\n            \"updated_date\": datetime.datetime(2025, 1, 23, 22, 17, 3, tzinfo=utc)\n        }\n        self._parse_and_compare(\"google.ai\", data, expected_results)\n\n    def test_cn_parse(self):\n        data = \"\"\"\n            Domain Name: cnnic.com.cn\n            ROID: 20021209s10011s00047242-cn\n            Domain Status: serverDeleteProhibited\n            Domain Status: serverUpdateProhibited\n            Domain Status: serverTransferProhibited\n            Registrant ID: s1255673574881\n            Registrant: 中国互联网络信息中心\n            Registrant Contact Email: servicei@cnnic.cn\n            Sponsoring Registrar: 北京新网数码信息技术有限公司\n            Name Server: a.cnnic.cn\n            Name Server: b.cnnic.cn\n            Name Server: c.cnnic.cn\n            Name Server: d.cnnic.cn\n            Name Server: e.cnnic.cn\n            Registration Time: 2000-09-14 00:00:00\n            Expiration Time: 2023-08-16 16:26:39\n            DNSSEC: unsigned\n        \"\"\"\n        expected_results = {\n            \"creation_date\": datetime.datetime(2000, 9, 14, 0, 0, tzinfo=utc),\n            \"dnssec\": \"unsigned\",\n            \"domain_name\": \"cnnic.com.cn\",\n            \"emails\": \"servicei@cnnic.cn\",\n            \"expiration_date\": datetime.datetime(2023, 8, 16, 16, 26, 39, tzinfo=utc),\n            \"name\": \"中国互联网络信息中心\",\n            \"name_servers\": [\n                \"a.cnnic.cn\",\n                \"b.cnnic.cn\",\n                \"c.cnnic.cn\",\n                \"d.cnnic.cn\",\n                \"e.cnnic.cn\",\n            ],\n            \"registrar\": \"北京新网数码信息技术有限公司\",\n            \"status\": [\n                \"serverDeleteProhibited\",\n                \"serverUpdateProhibited\",\n                \"serverTransferProhibited\",\n            ],\n        }\n        self._parse_and_compare(\"cnnic.com.cn\", data, expected_results)\n\n    def test_ie_parse(self):\n        data = \"\"\"\n        refer:        whois.weare.ie\n\ndomain:       IE\n\norganisation: University College Dublin\norganisation: Computing Services\norganisation: Computer Centre\naddress:      Belfield\naddress:      Dublin City,  Dublin 4\naddress:      Ireland\n\ncontact:      administrative\nname:         Chief Executive\norganisation: IE Domain Registry Limited\naddress:      2 Harbour Square\naddress:      Dún Laoghaire\naddress:      Co. Dublin\naddress:      Ireland\nphone:        +353 1 236 5412\nfax-no:       +353 1 230 1273\ne-mail:       tld-admin@weare.ie\n\ncontact:      technical\nname:         Technical Services Manager\norganisation: IE Domain Registry Limited\naddress:      2 Harbour Square\naddress:      Dún Laoghaire\naddress:      Co. Dublin\naddress:      Ireland\nphone:        +353 1 236 5421\nfax-no:       +353 1 230 1273\ne-mail:       tld-tech@weare.ie\n\nnserver:      B.NS.IE 2a01:4b0:0:0:0:0:0:2 77.72.72.34\nnserver:      C.NS.IE 194.146.106.98 2001:67c:1010:25:0:0:0:53\nnserver:      D.NS.IE 2a01:3f0:0:309:0:0:0:53 77.72.229.245\nnserver:      G.NS.IE 192.111.39.100 2001:7c8:2:a:0:0:0:64\nnserver:      H.NS.IE 192.93.0.4 2001:660:3005:1:0:0:1:2\nnserver:      I.NS.IE 194.0.25.35 2001:678:20:0:0:0:0:35\nds-rdata:     64134 13 2 77B9519D16B62D0A70A7301945CBB3092A7978BFDE75A3BCFB3D4719396E436A\n\nwhois:        whois.weare.ie\n\nstatus:       ACTIVE\nremarks:      Registration information: http://www.weare.ie\n\ncreated:      1988-01-27\nchanged:      2021-03-11\nsource:       IANA\n\n# whois.weare.ie\n\nDomain Name: rte.ie\nRegistry Domain ID: 672279-IEDR\nRegistrar WHOIS Server: whois.weare.ie\nRegistrar URL: https://www.blacknight.com\nUpdated Date: 2020-11-15T17:55:24Z\nCreation Date: 2000-02-11T00:00:00Z\nRegistry Expiry Date: 2025-03-31T13:20:07Z\nRegistrar: Blacknight Solutions\nRegistrar IANA ID: not applicable\nRegistrar Abuse Contact Email: abuse@blacknight.com\nRegistrar Abuse Contact Phone: +353.599183072\nDomain Status: ok https://icann.org/epp#ok\nRegistry Registrant ID: 354955-IEDR\nRegistrant Name: RTE Commercial Enterprises Limited\nRegistry Admin ID: 202753-IEDR\nRegistry Tech ID: 3159-IEDR\nRegistry Billing ID: REDACTED FOR PRIVACY\nName Server: ns1.rte.ie\nName Server: ns2.rte.ie\nName Server: ns3.rte.ie\nName Server: ns4.rte.ie\nDNSSEC: signedDelegation\n        \"\"\"\n        expected_results = {\n            \"admin_id\": \"202753-IEDR\",\n            \"creation_date\": datetime.datetime(2000, 2, 11, 0, 0, tzinfo=utc),\n            \"domain_name\": \"rte.ie\",\n            \"expiration_date\": datetime.datetime(2025, 3, 31, 13, 20, 7, tzinfo=utc),\n            \"name_servers\": [\"ns1.rte.ie\", \"ns2.rte.ie\", \"ns3.rte.ie\", \"ns4.rte.ie\"],\n            \"registrar\": \"Blacknight Solutions\",\n            \"registrar_contact\": \"abuse@blacknight.com\",\n            \"status\": \"ok https://icann.org/epp#ok\",\n            \"tech_id\": \"3159-IEDR\",\n        }\n        self._parse_and_compare(\"rte.ie\", data, expected_results)\n\n\n    def test_nl_expiration(self):\n        data = \"\"\"\n        domain_name: randomtest.nl\n        Status:      in quarantine\n        Creation Date: 2008-09-24\n        Updated Date: 2020-10-27\n        Date out of quarantine: 2020-12-06T20:31:25\n        \"\"\"\n\n        w = WhoisEntry.load(\"randomtest.nl\", data)\n        expires = w.expiration_date.strftime(\"%Y-%m-%d\")\n        self.assertEqual(expires, \"2020-12-06\")\n\n    def test_dk_parse(self):\n        data = \"\"\"\n#\n# Copyright (c) 2002 - 2019 by DK Hostmaster A/S\n#\n# Version:\n#\n# The data in the DK Whois database is provided by DK Hostmaster A/S\n# for information purposes only, and to assist persons in obtaining\n# information about or related to a domain name registration record.\n# We do not guarantee its accuracy. We will reserve the right to remove\n# access for entities abusing the data, without notice.\n#\n# Any use of this material to target advertising or similar activities\n# are explicitly forbidden and will be prosecuted. DK Hostmaster A/S\n# requests to be notified of any such activities or suspicions thereof.\n\nDomain:               dk-hostmaster.dk\nDNS:                  dk-hostmaster.dk\nRegistered:           1998-01-19\nExpires:              2022-03-31\nRegistration period:  5 years\nVID:                  yes\nDnssec:               Signed delegation\nStatus:               Active\n\nRegistrant\nHandle:               DKHM1-DK\nName:                 DK HOSTMASTER A/S\nAddress:              Ørestads Boulevard 108, 11.\nPostalcode:           2300\nCity:                 København S\nCountry:              DK\n\nNameservers\nHostname:             auth01.ns.dk-hostmaster.dk\nHostname:             auth02.ns.dk-hostmaster.dk\nHostname:             p.nic.dk\n\"\"\"\n\n        expected_results = {\n            \"creation_date\": datetime.datetime(1998, 1, 19, 0, 0, tzinfo=utc),\n            \"dnssec\": \"Signed delegation\",\n            \"domain_name\": \"dk-hostmaster.dk\",\n            \"expiration_date\": datetime.datetime(2022, 3, 31, 0, 0, tzinfo=utc),\n            \"name_servers\": [\n                \"auth01.ns.dk-hostmaster.dk\",\n                \"auth02.ns.dk-hostmaster.dk\",\n                \"p.nic.dk\",\n            ],\n            \"registrant_address\": \"Ørestads Boulevard 108, 11.\",\n            \"registrant_city\": \"København S\",\n            \"registrant_country\": \"DK\",\n            \"registrant_handle\": \"DKHM1-DK\",\n            \"registrant_name\": \"DK HOSTMASTER A/S\",\n            \"registrant_postal_code\": \"2300\",\n            \"registrar\": None,\n            \"status\": \"Active\",\n        }\n        self._parse_and_compare(\"dk-hostmaster.dk\", data, expected_results)\n\n    def _parse_and_compare(\n        self, domain_name, data, expected_results, whois_entry=WhoisEntry\n    ):\n        actual_results = whois_entry.load(domain_name, data)\n        # import pprint; pprint.pprint(actual_results)\n        self.assertEqual(expected_results, actual_results)\n\n    def test_sk_parse(self):\n        data = \"\"\"\n        # whois.sk-nic.sk\n\n        Domain:                       pipoline.sk\n        Registrant:                   H410977\n        Admin Contact:                H410977\n        Tech Contact:                 H410977\n        Registrar:                    PIPO-0002\n        Created:                      2012-07-23\n        Updated:                      2020-07-02\n        Valid Until:                  2021-07-13\n        Nameserver:                   ns1.cloudlikeaboss.com\n        Nameserver:                   ns2.cloudlikeaboss.com\n        EPP Status:                   ok\n\n        Registrar:                    PIPO-0002\n        Name:                         Pipoline s.r.o.\n        Organization:                 Pipoline s.r.o.\n        Organization ID:              48273317\n        Phone:                        +421.949347169\n        Email:                        peter.gonda@pipoline.com\n        Street:                       Ladožská 8\n        City:                         Košice\n        Postal Code:                  040 12\n        Country Code:                 SK\n        Created:                      2017-09-01\n        Updated:                      2020-07-02\n\n        Contact:                      H410977\n        Name:                         Ing. Peter Gonda\n        Organization:                 Pipoline s.r.o\n        Organization ID:              48273317\n        Email:                        info@pipoline.com\n        Street:                       Ladozska 8\n        City:                         Kosice\n        Postal Code:                  04012\n        Country Code:                 SK\n        Registrar:                    PIPO-0002\n        Created:                      2017-11-22\n        Updated:                      2017-11-22\"\"\"\n\n        expected_results = {\n            \"admin\": \"H410977\",\n            \"admin_city\": \"Kosice\",\n            \"admin_country_code\": \"SK\",\n            \"admin_email\": \"info@pipoline.com\",\n            \"admin_organization\": \"Pipoline s.r.o\",\n            \"admin_postal_code\": \"04012\",\n            \"admin_street\": \"Ladozska 8\",\n            \"creation_date\": datetime.datetime(2012, 7, 23, 0, 0, tzinfo=utc),\n            \"domain_name\": \"pipoline.sk\",\n            \"expiration_date\": datetime.datetime(2021, 7, 13, 0, 0, tzinfo=utc),\n            \"name_servers\": [\"ns1.cloudlikeaboss.com\", \"ns2.cloudlikeaboss.com\"],\n            \"registrar\": \"Pipoline s.r.o.\",\n            \"registrar_city\": \"Košice\",\n            \"registrar_country_code\": \"SK\",\n            \"registrar_created\": \"2012-07-23\",\n            \"registrar_email\": \"peter.gonda@pipoline.com\",\n            \"registrar_name\": \"Pipoline s.r.o.\",\n            \"registrar_organization_id\": \"48273317\",\n            \"registrar_phone\": \"+421.949347169\",\n            \"registrar_postal_code\": \"040 12\",\n            \"registrar_street\": \"Ladožská 8\",\n            \"registrar_updated\": \"2020-07-02\",\n            \"updated_date\": datetime.datetime(2020, 7, 2, 0, 0, tzinfo=utc),\n        }\n        self._parse_and_compare(\"pipoline.sk\", data, expected_results)\n\n    def test_bw_parse(self):\n        data = \"\"\"\n% IANA WHOIS server\n% for more information on IANA, visit http://www.iana.org\n% This query returned 1 object\n\nrefer:        whois.nic.net.bw\n\ndomain:       BW\n\norganisation: Botswana Communications Regulatory Authority (BOCRA)\naddress:      Plot 206/207 Independence Avenue\naddress:      Private Bag 00495\naddress:      Gaborone\naddress:      Botswana\n\ncontact:      administrative\nname:         Engineer - ccTLD\norganisation: BOCRA - Botswana Communications Regulatory Authority\naddress:      Plot 206/207 Independence Avenue\naddress:      Private Bag 00495\naddress:      Gaborone\naddress:      Botswana\nphone:        +2673685419\nfax-no:       +267 395 7976\ne-mail:       ramotsababa@bocra.org.bw\n\ncontact:      technical\nname:         Engineer - ccTLD\norganisation: Botswana Communications Regulatory Authority (BOCRA)\naddress:      Plot 206/207 Independence Avenue\naddress:      Private Bag 00495\naddress:      Gaborone\naddress:      Botswana\nphone:        +267 368 5410\nfax-no:       +267 395 7976\ne-mail:       matlapeng@bocra.org.bw\n\nnserver:      DNS1.NIC.NET.BW 168.167.98.226 2c0f:ff00:1:3:0:0:0:226\nnserver:      MASTER.BTC.NET.BW 168.167.168.37 2c0f:ff00:0:6:0:0:0:3 2c0f:ff00:0:6:0:0:0:5\nnserver:      NS-BW.AFRINIC.NET 196.216.168.72 2001:43f8:120:0:0:0:0:72\nnserver:      PCH.NIC.NET.BW 2001:500:14:6070:ad:0:0:1 204.61.216.70\n\nwhois:        whois.nic.net.bw\n\nstatus:       ACTIVE\nremarks:      Registration information: http://nic.net.bw\n\ncreated:      1993-03-19\nchanged:      2022-07-27\nsource:       IANA\n\n# whois.nic.net.bw\n\nDomain Name: google.co.bw\nRegistry Domain ID: 3486-bwnic\nRegistry WHOIS Server: whois.nic.net.bw\nUpdated Date: 2022-11-29T09:33:04.665Z\nCreation Date: 2012-11-12T22:00:00.0Z\nRegistry Expiry Date: 2023-12-31T05:00:00.0Z\nRegistrar Registration Expiration Date: 2023-12-31T05:00:00.0Z\nRegistrar: MarkMonitor Inc\nDomain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited\nDomain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\nDomain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\nRegistry RegistrantID: GcIIG-Z2bWn\nRegistrantName: Google LLC\nRegistrantOrganization: Google LLC\nRegistrantStreet: 1600 Amphitheatre Parkway\nRegistrantCity: Mountain View\nRegistrantState/Province: CA\nRegistrantPostal Code: 94043\nRegistrantCountry: US\nRegistrantPhone: +1.6502530000\nRegistrantFax: +1.6502530001\nRegistrantEmail: dns-adminATgoogle.com\nRegistry AdminID: fDojv-TYe2q\nAdminName: Google LLC\nAdminOrganization: Google LLC\nAdminStreet: 1600 Amphitheatre Parkway\nAdminCity: Mountain View\nAdminState/Province: CA\nAdminPostal Code: 94043\nAdminCountry: US\nAdminPhone: +1.6502530000\nAdminFax: +1.6502530001\nAdminEmail: dns-adminATgoogle.com\nRegistry TechID: 2sYG1-BSVgz\nTechName: Google LLC\nTechOrganization: Google LLC\nTechStreet: 1600 Amphitheatre Parkway\nTechCity: Mountain View\nTechState/Province: CA\nTechPostal Code: 94043\nTechCountry: US\nTechPhone: +1.6502530000\nTechFax: +1.6502530001\nTechEmail: dns-adminATgoogle.com\nRegistry BillingID: C2KQL-UUtMh\nBillingName: MarkMonitor Inc.\nBillingOrganization: CCOPS Billing\nBillingStreet: 3540 East Longwing Lane Suite 300\nBillingCity: Meridian\nBillingState/Province: ID\nBillingPostal Code: 83646\nBillingCountry: US\nBillingPhone: +1.2083895740\nBillingFax: +1.2083895771\nBillingEmail: ccopsbillingATmarkmonitor.com\nName Server: ns1.google.com\nName Server: ns2.google.com\nName Server: ns3.google.com\nName Server: ns4.google.com\nDNSSEC: unsigned\n\"\"\"\n\n        expected_results = {\n            \"admin_address\": \"1600 Amphitheatre Parkway\",\n            \"admin_city\": \"Mountain View\",\n            \"admin_country\": \"US\",\n            \"admin_email\": \"dns-adminATgoogle.com\",\n            \"admin_name\": \"Google LLC\",\n            \"admin_org\": \"Google LLC\",\n            \"admin_phone\": \"+1.6502530000\",\n            \"billing_address\": \"3540 East Longwing Lane Suite 300\",\n            \"billing_city\": \"Meridian\",\n            \"billing_country\": \"US\",\n            \"billing_email\": \"ccopsbillingATmarkmonitor.com\",\n            \"billing_name\": \"MarkMonitor Inc.\",\n            \"billing_org\": \"CCOPS Billing\",\n            \"billing_phone\": \"+1.2083895740\",\n            \"creation_date\": datetime.datetime(2012, 11, 12, 22, 0, tzinfo=utc),\n            \"dnssec\": \"unsigned\",\n            \"domain_id\": \"3486-bwnic\",\n            \"domain_name\": \"google.co.bw\",\n            \"name_servers\": [\n                \"ns1.google.com\",\n                \"ns2.google.com\",\n                \"ns3.google.com\",\n                \"ns4.google.com\",\n            ],\n            \"registrant_address\": \"1600 Amphitheatre Parkway\",\n            \"registrant_city\": \"Mountain View\",\n            \"registrant_country\": \"US\",\n            \"registrant_email\": \"dns-adminATgoogle.com\",\n            \"registrant_name\": \"Google LLC\",\n            \"registrant_org\": \"Google LLC\",\n            \"registrant_phone\": \"+1.6502530000\",\n            \"registrar\": \"MarkMonitor Inc\",\n            \"tech_address\": \"1600 Amphitheatre Parkway\",\n            \"tech_city\": \"Mountain View\",\n            \"tech_country\": \"US\",\n            \"tech_email\": \"dns-adminATgoogle.com\",\n            \"tech_name\": \"Google LLC\",\n            \"tech_org\": \"Google LLC\",\n            \"tech_phone\": \"+1.6502530000\",\n        }\n        self._parse_and_compare(\"google.co.bw\", data, expected_results)\n\n    def test_cm_parse(self):\n        data = \"\"\"\nDomain Name: icp.cm\nRegistry Domain ID: 1104110-RegCM\nUpdated Date: 2025-05-27T04:46:44.214Z\nCreation Date: 2024-08-24T13:17:43.633Z\nRegistry Expiry Date: 2026-08-24T13:17:44.316Z\nDomain Status: ok https://icann.org/epp#ok\nRegistrar: Netcom.cm Sarl\nReseller: NetSto Inc. - https://www.netsto.com\nName Server: ns1.huaweicloud-dns.com\nName Server: ns1.huaweicloud-dns.net\nName Server: ns1.huaweicloud-dns.cn\nName Server: ns1.huaweicloud-dns.org\n>>> Last update of WHOIS database: 2025-05-28T04:47:00.968Z <<<\n\nFor more information on EPP status codes, please visit https://icann.org/epp\n\nTERMS OF USE: You are not authorized to access or query our Whois\ndatabase through the use of electronic processes that are high-volume and\nautomated.  Whois database is provided by ANTIC as a service to the internet\ncommunity on behalf of ANTIC accredited registrars and resellers.\n\nThe data is for information purposes only. ANTIC does not\nguarantee its accuracy. By submitting a Whois query, you agree to abide\nby the following terms of use: You agree that you may use this Data only\nfor lawful purposes and that under no circumstances will you use this Data\nto: (1) allow, enable, or otherwise support the transmission of mass\nunsolicited, commercial advertising or solicitations via e-mail, telephone,\nor facsimile; or (2) enable high volume, automated, electronic processes\nthat apply to ANTIC members (or their computer systems). The\ncompilation, repackaging, dissemination or other use of this Data is prohibited.\n\"\"\"\n\n        expected_results = {\n            \"domain_name\": \"icp.cm\",\n            \"registry_domain_id\": \"1104110-RegCM\",\n            \"updated_date\": datetime.datetime(2025, 5, 27, 4, 46, 44, 214000, tzinfo=utc),\n            \"creation_date\": datetime.datetime(2024, 8, 24, 13, 17, 43, 633000, tzinfo=utc),\n            \"expiration_date\": datetime.datetime(2026, 8, 24, 13, 17, 44, 316000, tzinfo=utc),\n            \"status\": \"ok https://icann.org/epp#ok\",\n            \"registrar\": \"Netcom.cm Sarl\",\n            \"reseller\": \"NetSto Inc. - https://www.netsto.com\",\n            \"name_servers\": ['ns1.huaweicloud-dns.com', 'ns1.huaweicloud-dns.net', 'ns1.huaweicloud-dns.cn',\n                             'ns1.huaweicloud-dns.org']\n        }\n        self._parse_and_compare(\"icp.cm\", data, expected_results)\n\n    def test_fr_parse(self):\n        sample_path = os.path.join(\n            os.path.dirname(os.path.abspath(__file__)), \"samples\", \"whois\", \"google.fr\"\n        )\n        with open(sample_path, encoding=\"utf-8\") as f:\n            data = f.read()\n\n        expected_results = {\n            \"domain_name\": \"google.fr\",\n            \"registrar\": \"MARKMONITOR Inc.\",\n            \"creation_date\": datetime.datetime(2000, 7, 26, 22, 0, tzinfo=utc),\n            \"expiration_date\": datetime.datetime(2026, 12, 30, 17, 16, 48, tzinfo=utc),\n            \"updated_date\": datetime.datetime(2025, 12, 3, 10, 12, 0, 351952, tzinfo=utc),\n            \"name_servers\": [\n                \"ns1.google.com\",\n                \"ns2.google.com\",\n                \"ns3.google.com\",\n                \"ns4.google.com\",\n            ],\n            \"status\": [\n                \"ACTIVE\",\n                \"serverUpdateProhibited\",\n                \"serverTransferProhibited\",\n                \"serverDeleteProhibited\",\n                \"serverRecoverProhibited\",\n                \"associated\",\n                \"not identified\",\n                \"ok\",\n            ],\n            \"emails\": [\n                \"registry.admin@markmonitor.com\",\n                \"dns-admin@google.com\",\n                \"ccops@markmonitor.com\",\n            ],\n            \"registrant_name\": \"Google Ireland Holdings Unlimited Company\",\n            \"registrant_address\": \"Google Ireland Holdings Unlimited Company\\n70 Sir John Rogerson's Quay\\n2 Dublin\",\n            \"registrant_country\": \"IE\",\n            \"registrant_phone\": \"+353.14361000\",\n            \"registrant_email\": \"dns-admin@google.com\",\n            \"registrant_type\": \"ORGANIZATION\",\n            \"admin_name\": \"Google Ireland Holdings Unlimited Company\",\n            \"admin_address\": \"70 Sir John Rogerson's Quay\\n2 Dublin\",\n            \"admin_country\": \"IE\",\n            \"admin_phone\": \"+353.14361000\",\n            \"admin_email\": \"dns-admin@google.com\",\n            \"admin_type\": \"ORGANIZATION\",\n            \"tech_name\": \"MarkMonitor Inc.\",\n            \"tech_address\": \"2150 S. Bonito Way, Suite 150\\n83642 Meridian\",\n            \"tech_country\": \"US\",\n            \"tech_phone\": \"+1.2083895740\",\n            \"tech_email\": \"ccops@markmonitor.com\",\n            \"tech_type\": \"ORGANIZATION\",\n        }\n        self._parse_and_compare(\"google.fr\", data, expected_results)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "test/test_query.py",
    "content": "# coding=utf-8\n\nimport unittest\n\nfrom whois import whois\n\n\nclass TestQuery(unittest.TestCase):\n    def test_simple_ascii_domain(self):\n        domain = \"google.com\"\n        whois(domain)\n\n    def test_simple_unicode_domain(self):\n        domain = \"нарояци.com\"\n        whois(domain)\n\n    def test_unicode_domain_and_tld(self):\n        domain = \"россия.рф\"\n        whois(domain)\n\n    def test_ipv4(self):\n        \"\"\"Verify ipv4 addresses.\"\"\"\n        domain = \"172.217.3.110\"\n        whois_results = whois(domain)\n        if isinstance(whois_results[\"domain_name\"], list):\n            domain_names = [_.lower() for _ in whois_results[\"domain_name\"]]\n        else:\n            domain_names = [whois_results[\"domain_name\"].lower()]\n\n        print(whois_results)\n        self.assertIn(\"1e100.net\", domain_names)\n        self.assertIn(\n            \"ns1.google.com\", [_.lower() for _ in whois_results[\"name_servers\"]]\n        )\n\n    def test_ipv6(self):\n        \"\"\"Verify ipv6 addresses.\"\"\"\n        domain = \"2607:f8b0:4006:802::200e\"\n        whois_results = whois(domain)\n        if isinstance(whois_results[\"domain_name\"], list):\n            domain_names = [_.lower() for _ in whois_results[\"domain_name\"]]\n        else:\n            domain_names = [whois_results[\"domain_name\"].lower()]\n\n        self.assertIn(\"1e100.net\", domain_names)\n        self.assertIn(\n            \"ns1.google.com\", [_.lower() for _ in whois_results[\"name_servers\"]]\n        )\n"
  },
  {
    "path": "whois/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport logging\nimport os\nimport re\nimport socket\nimport subprocess\nimport sys\nfrom typing import Any, Optional, Pattern\n\nfrom .exceptions import WhoisError\nfrom .parser import WhoisEntry\nfrom .whois import NICClient\n\nlogger = logging.getLogger(__name__)\n\n# thanks to https://www.regextester.com/104038\nIPV4_OR_V6: Pattern[str] = re.compile(\n    r\"((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))\"  # noqa: E501\n)\n\n\ndef whois(\n    url: str,\n    command: bool = False,\n    flags: int = 0,\n    executable: str = \"whois\",\n    executable_opts: Optional[list[str]] = None,\n    inc_raw: bool = False,\n    quiet: bool = False,\n    ignore_socket_errors: bool = True,\n    convert_punycode: bool = True,\n    timeout: int = 10,\n) -> dict[str, Any]:\n    \"\"\"\n    url: the URL to search whois\n    command: whether to use the native whois command (default False)\n    executable: executable to use for native whois command (default 'whois')\n    flags: flags to pass to the whois client (default 0)\n    inc_raw: whether to include the raw text from whois in the result (default False)\n    quiet: whether to avoid printing output (default False)\n    ignore_socket_errors: whether to ignore socket errors (default True)\n    convert_punycode: whether to convert the given URL punycode (default True)\n    timeout: timeout for WHOIS request (default 10 seconds)\n    \"\"\"\n    # clean domain to expose netloc\n    ip_match = IPV4_OR_V6.match(url)\n    if ip_match:\n        domain = url\n        try:\n            result = socket.gethostbyaddr(url)\n        except socket.herror:\n            pass\n        else:\n            domain = extract_domain(result[0])\n    else:\n        domain = extract_domain(url)\n    if command:\n        # try native whois command\n        whois_command = [executable, domain]\n        if executable_opts:\n            if isinstance(executable_opts, list):\n                whois_command.extend(executable_opts)\n            else:\n                whois_command.append(executable_opts)\n        r = subprocess.Popen(whois_command, stdout=subprocess.PIPE)\n        if r.stdout is None:\n            raise WhoisError(\"Whois command returned no output\")\n        else:\n            text = r.stdout.read().decode()\n    else:\n        # try builtin client\n        nic_client = NICClient()\n        if convert_punycode:\n            domain = domain.encode(\"idna\").decode(\"utf-8\")\n        text = nic_client.whois_lookup(None, domain, flags, quiet=quiet, ignore_socket_errors=ignore_socket_errors, timeout=timeout)\n        if not text:\n            raise WhoisError(\"Whois command returned no output\")\n    entry = WhoisEntry.load(domain, text)\n    if inc_raw:\n        entry[\"raw\"] = text\n    return entry\n\n\nsuffixes: Optional[set] = None\n\n\ndef extract_domain(url: str) -> str:\n    \"\"\"Extract the domain from the given URL\n\n    >>> logger.info(extract_domain('http://www.google.com.au/tos.html'))\n    google.com.au\n    >>> logger.info(extract_domain('abc.def.com'))\n    def.com\n    >>> logger.info(extract_domain(u'www.公司.hk'))\n    公司.hk\n    >>> logger.info(extract_domain('chambagri.fr'))\n    chambagri.fr\n    >>> logger.info(extract_domain('www.webscraping.com'))\n    webscraping.com\n    >>> logger.info(extract_domain('198.252.206.140'))\n    stackoverflow.com\n    >>> logger.info(extract_domain('102.112.2O7.net'))\n    2o7.net\n    >>> logger.info(extract_domain('globoesporte.globo.com'))\n    globo.com\n    >>> logger.info(extract_domain('1-0-1-1-1-0-1-1-1-1-1-1-1-.0-0-0-0-0-0-0-0-0-0-0-0-0-10-0-0-0-0-0-0-0-0-0-0-0-0-0.info'))\n    0-0-0-0-0-0-0-0-0-0-0-0-0-10-0-0-0-0-0-0-0-0-0-0-0-0-0.info\n    >>> logger.info(extract_domain('2607:f8b0:4006:802::200e'))\n    1e100.net\n    >>> logger.info(extract_domain('172.217.3.110'))\n    1e100.net\n    \"\"\"\n    if IPV4_OR_V6.match(url):\n        # this is an IP address\n        return socket.gethostbyaddr(url)[0]\n\n    # load known TLD suffixes\n    global suffixes\n    if not suffixes:\n        # downloaded from https://publicsuffix.org/list/public_suffix_list.dat\n        tlds_path = os.path.join(\n            os.getcwd(), os.path.dirname(__file__), \"data\", \"public_suffix_list.dat\"\n        )\n        with open(tlds_path, encoding=\"utf-8\") as tlds_fp:\n            suffixes = set(\n                line.encode(\"utf-8\")\n                for line in tlds_fp.read().splitlines()\n                if line and not line.startswith(\"//\")\n            )\n\n    if not isinstance(url, str):\n        url = url.decode(\"utf-8\")\n    url = re.sub(\"^.*://\", \"\", url)\n    url = url.split(\"/\")[0].lower()\n\n    # find the longest suffix match\n    domain = b\"\"\n    split_url = url.split(\".\")\n    for section in reversed(split_url):\n        if domain:\n            domain = b\".\" + domain\n        domain = section.encode(\"utf-8\") + domain\n        if domain not in suffixes:\n            if b\".\" not in domain and len(split_url) >= 2:\n                # If this is the first section and there wasn't a match, try to\n                # match the first two sections - if that works, keep going\n                # See https://github.com/richardpenman/whois/issues/50\n                second_order_tld = \".\".join([split_url[-2], split_url[-1]])\n                if not second_order_tld.encode(\"utf-8\") in suffixes:\n                    break\n            else:\n                break\n    return domain.decode(\"utf-8\")\n\n\nif __name__ == \"__main__\":\n    try:\n        url = sys.argv[1]\n    except IndexError:\n        logger.error(\"Usage: %s url\" % sys.argv[0])\n    else:\n        logger.info(whois(url))\n"
  },
  {
    "path": "whois/exceptions.py",
    "content": "class PywhoisError(Exception):\n    pass\n\n#backwards compatibility\nclass WhoisError(PywhoisError):\n    pass\n\n\nclass UnknownTldError(WhoisError):\n    pass\n\n\nclass WhoisDomainNotFoundError(WhoisError):\n    pass\n\n\nclass FailedParsingWhoisOutputError(WhoisError):\n    pass\n\n\nclass WhoisQuotaExceededError(WhoisError):\n    pass\n\n\nclass WhoisUnknownDateFormatError(WhoisError):\n    pass\n\n\nclass WhoisCommandFailedError(WhoisError):\n    pass\n"
  },
  {
    "path": "whois/parser.py",
    "content": "# -*- coding: utf-8 -*-\n\n# parser.py - Module for parsing whois response data\n# Copyright (c) 2008 Andrey Petrov\n#\n# This module is part of python-whois and is released under\n# the MIT license: http://www.opensource.org/licenses/mit-license.php\nfrom __future__ import annotations\nimport json\nimport re\nfrom datetime import datetime, timezone, timedelta\nfrom typing import Any, Callable, Optional, Union\n\nimport dateutil.parser as dp\nfrom dateutil.utils import default_tzinfo\n\nfrom .exceptions import WhoisDomainNotFoundError, WhoisUnknownDateFormatError\nfrom .time_zones import tz_data\n\nEMAIL_REGEX: str = (\n    r\"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[\"\n    r\"a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\"\n)\n\nKNOWN_FORMATS: list[str] = [\n    \"%d-%b-%Y\",  # 02-jan-2000\n    \"%d-%B-%Y\",  # 11-February-2000\n    \"%d-%m-%Y\",  # 20-10-2000\n    \"%Y-%m-%d\",  # 2000-01-02\n    \"%d.%m.%Y\",  # 2.1.2000\n    \"%Y.%m.%d\",  # 2000.01.02\n    \"%Y/%m/%d\",  # 2000/01/02\n    \"%Y/%m/%d %H:%M:%S\",  # 2011/06/01 01:05:01\n    \"%Y/%m/%d %H:%M:%S (%z)\",  # 2011/06/01 01:05:01 (+0900)\n    \"%Y%m%d\",  # 20170209\n    \"%Y%m%d %H:%M:%S\",  # 20110908 14:44:51\n    \"%d/%m/%Y\",  # 02/01/2013\n    \"%Y. %m. %d.\",  # 2000. 01. 02.\n    \"%Y.%m.%d %H:%M:%S\",  # 2014.03.08 10:28:24\n    \"%d-%b-%Y %H:%M:%S %Z\",  # 24-Jul-2009 13:20:03 UTC\n    \"%a %b %d %H:%M:%S %Z %Y\",  # Tue Jun 21 23:59:59 GMT 2011\n    \"%a %b %d %Y\",  # Tue Dec 12 2000\n    \"%Y-%m-%dT%H:%M:%S\",  # 2007-01-26T19:10:31\n    \"%Y-%m-%dT%H:%M:%SZ\",  # 2007-01-26T19:10:31Z\n    \"%Y-%m-%dT%H:%M:%SZ[%Z]\",  # 2007-01-26T19:10:31Z[UTC]\n    \"%Y-%m-%d %H:%M:%S.%f\",  # 2018-05-19 12:18:44.329522\n    \"%Y-%m-%dT%H:%M:%S.%fZ\",  # 2018-12-01T16:17:30.568Z\n    \"%Y-%m-%dT%H:%M:%S.%f%z\",  # 2011-09-08T14:44:51.622265+03:00\n    \"%Y-%m-%d %H:%M:%S%z\",  # 2018-11-02 11:29:08+02:00\n    \"%Y-%m-%dT%H:%M:%S%z\",  # 2013-12-06T08:17:22-0800\n    \"%Y-%m-%dT%H:%M:%S%zZ\",  # 1970-01-01T02:00:00+02:00Z\n    \"%Y-%m-%dt%H:%M:%S.%f\",  # 2011-09-08t14:44:51.622265\n    \"%Y-%m-%dt%H:%M:%S\",  # 2007-01-26T19:10:31\n    \"%Y-%m-%dt%H:%M:%SZ\",  # 2007-01-26T19:10:31Z\n    \"%Y-%m-%dt%H:%M:%S.%fz\",  # 2007-01-26t19:10:31.00z\n    \"%Y-%m-%dt%H:%M:%S%z\",  # 2011-03-30T19:36:27+0200\n    \"%Y-%m-%dt%H:%M:%S.%f%z\",  # 2011-09-08T14:44:51.622265+03:00\n    \"%Y-%m-%d %H:%M:%SZ\",  # 2000-08-22 18:55:20Z\n    \"%Y-%m-%d %H:%M:%SZ.0Z\",  # 2000-08-22 18:55:20Z.0Z\n    \"%Y-%m-%d %H:%M:%S\",  # 2000-08-22 18:55:20\n    \"%d %b %Y %H:%M:%S\",  # 08 Apr 2013 05:44:00\n    \"%d/%m/%Y %H:%M:%S\",  # 23/04/2015 12:00:07\n    \"%d/%m/%Y %H:%M:%S %Z\",  # 23/04/2015 12:00:07 EEST\n    \"%d/%m/%Y %H:%M:%S.%f %Z\",  # 23/04/2015 12:00:07.619546 EEST\n    \"%B %d %Y\",  # August 14 2017\n    \"%d.%m.%Y %H:%M:%S\",  # 08.03.2014 10:28:24\n    \"before %Y\",  # before 2001\n    \"before %b-%Y\",  # before aug-1996\n    \"before %Y-%m-%d\",  # before 1996-01-01\n    \"before %Y%m%d\",  # before 19960821\n    \"%Y-%m-%d %H:%M:%S (%Z%z)\",  # 2017-09-26 11:38:29 (GMT+00:00)\n    \"%Y-%m-%d %H:%M:%S (%Z+0:00)\",  # 2009-07-01 12:44:02 (GMT+0:00)\n    \"%Y-%b-%d.\",  # 2024-Apr-02.\n]\n\n\ndef datetime_parse(s: str) -> Union[datetime, None]:\n    for known_format in KNOWN_FORMATS:\n        try:\n            parsed = datetime.strptime(s, known_format)\n        except ValueError:\n            pass  # Wrong format, keep trying\n        else:\n            if parsed.tzinfo is None:\n                parsed = parsed.replace(tzinfo=timezone.utc)\n            return parsed\n\n\ndef cast_date(\n    s: str, dayfirst: bool = False, yearfirst: bool = False\n) -> Union[str, datetime]:\n    \"\"\"Convert any date string found in WHOIS to a datetime object.\"\"\"\n\n    # prefer our conversion before dateutil.parser\n    # because dateutil.parser does %m.%d.%Y and ours has %d.%m.%Y which is more logical\n    parsed = datetime_parse(s)\n    if parsed:\n        return parsed\n\n    try:\n        # Use datetime.timezone.utc to support < Python3.9\n        return default_tzinfo(\n            dp.parse(s, tzinfos=tz_data, dayfirst=dayfirst, yearfirst=yearfirst),\n            timezone.utc,\n        )\n    except dp.ParserError:\n        raise WhoisUnknownDateFormatError(f\"Unknown date format: {s}\") from None\n\n\nclass WhoisEntry(dict):\n    \"\"\"Base class for parsing a Whois entries.\"\"\"\n\n    # regular expressions to extract domain data from whois profile\n    # child classes will override this\n    _regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"reseller\": r\"Reseller: *(.+)\",\n        \"whois_server\": r\"Whois Server: *(.+)\",\n        \"referral_url\": r\"Referral URL: *(.+)\",  # http url of whois_server\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expir\\w+ Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"dnssec\": r\"dnssec: *([\\S]+)\",\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"org\": r\"Registrant\\s*Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_org\": r\"Tech Organization: *(.+)\",\n        \"admin_name\": r\"Admin Name: *(.+)\",\n        \"admin_org\": r\"Admin Organization: *(.+)\"\n    }\n\n    # allows for data string manipulation before casting to date\n    _data_preprocessor: Optional[Callable[[str], str]] = None\n\n    dayfirst: bool = False\n    yearfirst: bool = False\n\n    def __init__(self, domain: str, text: str, regex: Optional[dict[str, str]] = None, data_preprocessor: Optional[Callable[[str], str]] = None):\n        if (\n            \"This TLD has no whois server, but you can access the whois database at\"\n            in text\n        ):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            self.domain = domain\n            self.text = text\n            if regex is not None:\n                self._regex = regex\n            if data_preprocessor is not None:\n                self._data_preprocessor = data_preprocessor\n            self.parse()\n\n    def parse(self) -> None:\n        \"\"\"The first time an attribute is called it will be calculated here.\n        The attribute is then set to be accessed directly by subsequent calls.\n        \"\"\"\n        for attr, regex in list(self._regex.items()):\n            if regex:\n                values: list[Union[str, datetime]] = []\n                for data in re.findall(regex, self.text, re.IGNORECASE | re.M):\n                    matches = data if isinstance(data, tuple) else [data]\n                    for value in matches:\n                        value = self._preprocess(attr, value)\n                        if value and str(value).lower() not in [\n                            str(v).lower() for v in values\n                        ]:\n                            # avoid duplicates\n                            values.append(value)\n\n                if values and attr in (\"registrar\", \"whois_server\", \"referral_url\"):\n                    values = values[-1:]  # ignore junk\n                if len(values) == 1:\n                    self[attr] = values[0]\n                elif values:\n                    self[attr] = values\n                else:\n                    self[attr] = None\n\n    def _preprocess(self, attr: str, value: str) -> Union[str, datetime]:\n        value = value.strip()\n        if value and isinstance(value, str) and not value.isdigit() and \"_date\" in attr:\n            # try casting to date format\n\n            # if data_preprocessor is set, use it to preprocess the data string\n            if self._data_preprocessor:\n                value = self._data_preprocessor(value)\n\n            return cast_date(value, dayfirst=self.dayfirst, yearfirst=self.yearfirst)\n        return value\n\n    def __setitem__(self, name: str, value: Any) -> None:\n        super(WhoisEntry, self).__setitem__(name, value)\n\n    def __getattr__(self, name: str) -> Any:\n        return self.get(name)\n\n    def __str__(self) -> str:\n        def handler(e):\n            return str(e)\n\n        return json.dumps(self, indent=2, default=handler, ensure_ascii=False)\n\n    def __getstate__(self) -> dict:\n        return self.__dict__\n\n    def __setstate__(self, state: dict) -> None:\n        self.__dict__ = state\n\n    @staticmethod\n    def load(domain: str, text: str):\n        \"\"\"Given whois output in ``text``, return an instance of ``WhoisEntry``\n        that represents its parsed contents.\n        \"\"\"\n        if text.strip() == \"No whois server is known for this kind of object.\":\n            raise WhoisDomainNotFoundError(text)\n\n        if domain.endswith(\".com\"):\n            return WhoisCom(domain, text)\n        elif domain.endswith(\".net\"):\n            return WhoisNet(domain, text)\n        elif domain.endswith(\".org\"):\n            return WhoisOrg(domain, text)\n        elif domain.endswith(\".name\"):\n            return WhoisName(domain, text)\n        elif domain.endswith(\".me\"):\n            return WhoisMe(domain, text)\n        elif domain.endswith(\".ae\"):\n            return WhoisAe(domain, text)\n        elif domain.endswith(\".au\"):\n            return WhoisAU(domain, text)\n        elif domain.endswith(\".ru\"):\n            return WhoisRu(domain, text)\n        elif domain.endswith(\".us\"):\n            return WhoisUs(domain, text)\n        elif domain.endswith(\".uk\"):\n            return WhoisUk(domain, text)\n        elif domain.endswith(\".fr\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".re\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".pm\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".tf\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".wf\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".yt\"):\n            return WhoisAfnic(domain, text)\n        elif domain.endswith(\".nl\"):\n            return WhoisNl(domain, text)\n        elif domain.endswith(\".lt\"):\n            return WhoisLt(domain, text)\n        elif domain.endswith(\".fi\"):\n            return WhoisFi(domain, text)\n        elif domain.endswith(\".hr\"):\n            return WhoisHr(domain, text)\n        elif domain.endswith(\".hn\"):\n            return WhoisHn(domain, text)\n        elif domain.endswith(\".hk\"):\n            return WhoisHk(domain, text)\n        elif domain.endswith(\".jp\"):\n            return WhoisJp(domain, text)\n        elif domain.endswith(\".pl\"):\n            return WhoisPl(domain, text)\n        elif domain.endswith(\".br\"):\n            return WhoisBr(domain, text)\n        elif domain.endswith(\".eu\"):\n            return WhoisEu(domain, text)\n        elif domain.endswith(\".ee\"):\n            return WhoisEe(domain, text)\n        elif domain.endswith(\".kr\"):\n            return WhoisKr(domain, text)\n        elif domain.endswith(\".pt\"):\n            return WhoisPt(domain, text)\n        elif domain.endswith(\".bg\"):\n            return WhoisBg(domain, text)\n        elif domain.endswith(\".de\"):\n            return WhoisDe(domain, text)\n        elif domain.endswith(\".at\"):\n            return WhoisAt(domain, text)\n        elif domain.endswith(\".ca\"):\n            return WhoisCa(domain, text)\n        elif domain.endswith(\".be\"):\n            return WhoisBe(domain, text)\n        elif domain.endswith(\".рф\"):\n            return WhoisRf(domain, text)\n        elif domain.endswith(\".info\"):\n            return WhoisInfo(domain, text)\n        elif domain.endswith(\".su\"):\n            return WhoisSu(domain, text)\n        elif domain.endswith(\".si\"):\n            return WhoisSi(domain, text)\n        elif domain.endswith(\".kg\"):\n            return WhoisKg(domain, text)\n        elif domain.endswith(\".io\"):\n            return WhoisIo(domain, text)\n        elif domain.endswith(\".biz\"):\n            return WhoisBiz(domain, text)\n        elif domain.endswith(\".mobi\"):\n            return WhoisMobi(domain, text)\n        elif domain.endswith(\".ch\"):\n            return WhoisChLi(domain, text)\n        elif domain.endswith(\".li\"):\n            return WhoisChLi(domain, text)\n        elif domain.endswith(\".id\"):\n            return WhoisID(domain, text)\n        elif domain.endswith(\".sk\"):\n            return WhoisSK(domain, text)\n        elif domain.endswith(\".se\"):\n            return WhoisSe(domain, text)\n        elif domain.endswith(\".no\"):\n            return WhoisNo(domain, text)\n        elif domain.endswith(\".nu\"):\n            return WhoisSe(domain, text)\n        elif domain.endswith(\".is\"):\n            return WhoisIs(domain, text)\n        elif domain.endswith(\".dk\"):\n            return WhoisDk(domain, text)\n        elif domain.endswith(\".it\"):\n            return WhoisIt(domain, text)\n        elif domain.endswith(\".mx\"):\n            return WhoisMx(domain, text)\n        elif domain.endswith(\".ai\"):\n            return WhoisAi(domain, text)\n        elif domain.endswith(\".il\"):\n            return WhoisIl(domain, text)\n        elif domain.endswith(\".in\"):\n            return WhoisIn(domain, text)\n        elif domain.endswith(\".cat\"):\n            return WhoisCat(domain, text)\n        elif domain.endswith(\".ie\"):\n            return WhoisIe(domain, text)\n        elif domain.endswith(\".nz\"):\n            return WhoisNz(domain, text)\n        elif domain.endswith(\".space\"):\n            return WhoisSpace(domain, text)\n        elif domain.endswith(\".lu\"):\n            return WhoisLu(domain, text)\n        elif domain.endswith(\".cz\"):\n            return WhoisCz(domain, text)\n        elif domain.endswith(\".online\"):\n            return WhoisOnline(domain, text)\n        elif domain.endswith(\".cn\"):\n            return WhoisCn(domain, text)\n        elif domain.endswith(\".app\"):\n            return WhoisApp(domain, text)\n        elif domain.endswith(\".money\"):\n            return WhoisMoney(domain, text)\n        elif domain.endswith(\".cl\"):\n            return WhoisCl(domain, text)\n        elif domain.endswith(\".ar\"):\n            return WhoisAr(domain, text)\n        elif domain.endswith(\".by\"):\n            return WhoisBy(domain, text)\n        elif domain.endswith(\".cr\"):\n            return WhoisCr(domain, text)\n        elif domain.endswith(\".do\"):\n            return WhoisDo(domain, text)\n        elif domain.endswith(\".jobs\"):\n            return WhoisJobs(domain, text)\n        elif domain.endswith(\".lat\"):\n            return WhoisLat(domain, text)\n        elif domain.endswith(\".pe\"):\n            return WhoisPe(domain, text)\n        elif domain.endswith(\".ro\"):\n            return WhoisRo(domain, text)\n        elif domain.endswith(\".sa\"):\n            return WhoisSa(domain, text)\n        elif domain.endswith(\".tw\"):\n            return WhoisTw(domain, text)\n        elif domain.endswith(\".tr\"):\n            return WhoisTr(domain, text)\n        elif domain.endswith(\".ve\"):\n            return WhoisVe(domain, text)\n        elif domain.endswith(\".ua\"):\n            if domain.endswith(\".pp.ua\"):\n                return WhoisPpUa(domain, text)\n            return WhoisUA(domain, text)\n        elif domain.endswith(\".укр\") or domain.endswith(\".xn--j1amh\"):\n            return WhoisUkr(domain, text)\n        elif domain.endswith(\".kz\"):\n            return WhoisKZ(domain, text)\n        elif domain.endswith(\".ir\"):\n            return WhoisIR(domain, text)\n        elif domain.endswith(\".中国\"):\n            return WhoisZhongGuo(domain, text)\n        elif domain.endswith(\".website\"):\n            return WhoisWebsite(domain, text)\n        elif domain.endswith(\".sg\"):\n            return WhoisSG(domain, text)\n        elif domain.endswith(\".ml\"):\n            return WhoisML(domain, text)\n        elif domain.endswith(\".ooo\"):\n            return WhoisOoo(domain, text)\n        elif domain.endswith(\".group\"):\n            return WhoisGroup(domain, text)\n        elif domain.endswith(\".market\"):\n            return WhoisMarket(domain, text)\n        elif domain.endswith(\".za\"):\n            return WhoisZa(domain, text)\n        elif domain.endswith(\".bw\"):\n            return WhoisBw(domain, text)\n        elif domain.endswith(\".bz\"):\n            return WhoisBz(domain, text)\n        elif domain.endswith(\".gg\"):\n            return WhoisGg(domain, text)\n        elif domain.endswith(\".city\"):\n            return WhoisCity(domain, text)\n        elif domain.endswith(\".design\"):\n            return WhoisDesign(domain, text)\n        elif domain.endswith(\".studio\"):\n            return WhoisStudio(domain, text)\n        elif domain.endswith(\".style\"):\n            return WhoisStyle(domain, text)\n        elif domain.endswith(\".рус\") or domain.endswith(\".xn--p1acf\"):\n            return WhoisPyc(domain, text)\n        elif domain.endswith(\".life\"):\n            return WhoisLife(domain, text)\n        elif domain.endswith(\".tn\"):\n            return WhoisTN(domain, text)\n        elif domain.endswith(\".rs\"):\n            return WhoisRs(domain, text)\n        elif domain.endswith(\".site\"):\n            return WhoisSite(domain, text)\n        elif domain.endswith(\".edu\"):\n            return WhoisEdu(domain, text)\n        elif domain.endswith(\".lv\"):\n            return WhoisLv(domain, text)\n        elif domain.endswith(\".co\"):\n            return WhoisCo(domain, text)\n        elif domain.endswith(\".ga\"):\n            return WhoisGa(domain, text)\n        elif domain.endswith(\".cm\"):\n            return WhoisCm(domain, text)\n        elif domain.endswith(\".hu\"):\n            return WhoisHu(domain, text)\n        elif domain.endswith(\".xyz\"):\n            return WhoisXyz(domain, text)\n        else:\n            return WhoisEntry(domain, text)\n\n\nclass WhoisCl(WhoisEntry):\n    \"\"\"Whois parser for .cl domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"registrant_name\": r\"Registrant name: *(.+)\",\n        \"registrant_organization\": r\"Registrant organisation: *(.+)\",\n        \"registrar\": r\"registrar name: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"creation_date\": r\"Creation date: *(.+)\",\n        \"expiration_date\": r\"Expiration date: *(.+)\",\n        \"name_servers\": r\"Name server: *(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text or \"no entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(\n                self,\n                domain,\n                text,\n                self.regex,\n                lambda x: x.replace(\" CLST\", \"\").replace(\" CLT\", \"\")\n            )\n\n\nclass WhoisSG(WhoisEntry):\n    \"\"\"Whois parser for .sg domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"registrant_name\": r\"Registrant:\\n\\s+Name:(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"creation_date\": r\"Creation date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"name_servers\": r\"Name server: *(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain Not Found\" in text or text.lstrip().startswith('Not found: '):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n        nsmatch = re.compile(\"Name Servers:(.*?)DNSSEC:\", re.DOTALL).search(text)\n        if nsmatch:\n            self[\"name_servers\"] = [\n                line.strip() for line in nsmatch.groups()[0].strip().splitlines()\n            ]\n\n        techmatch = re.compile(\n            \"Technical Contact:(.*?)Name Servers:\", re.DOTALL\n        ).search(text)\n        if techmatch:\n            for line in techmatch.groups()[0].strip().splitlines():\n                self[\n                    \"technical_contact_\" + line.split(\":\")[0].strip().lower()\n                ] = line.split(\":\")[1].strip()\n\n\nclass WhoisPe(WhoisEntry):\n    \"\"\"Whois parser for .pe domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"whois_server\": r\"WHOIS Server: *(.+)\",\n        \"registrant_name\": r\"Registrant name: *(.+)\",\n        \"registrar\": r\"Sponsoring Registrar: *(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"name_servers\": r\"Name server: *(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text or \"Domain Status: No Object Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSpace(WhoisEntry):\n    \"\"\"Whois parser for .space domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text or \"The queried object does not exist: DOMAIN NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text)\n\n\nclass WhoisCom(WhoisEntry):\n    \"\"\"Whois parser for .com domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text)\n\n\nclass WhoisNet(WhoisEntry):\n    \"\"\"Whois parser for .net domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text)\n\n\nclass WhoisOrg(WhoisEntry):\n    \"\"\"Whois parser for .org domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"whois_server\": r\"Whois Server: *(.+)\",  # empty usually\n        \"referral_url\": r\"Referral URL: *(.+)\",  # http url of whois_server: empty usually\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip().startswith(\"NOT FOUND\") or text.strip().startswith(\n            \"Domain not found\"\n        ):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text)\n\n\nclass WhoisRo(WhoisEntry):\n    \"\"\"Whois parser for .ro domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_status\": r\"Domain Status: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"referral_url\": r\"Referral URL: *(.+)\",  # http url of whois_server: empty usually\n        \"creation_date\": r\"Registered On: *(.+)\",\n        \"expiration_date\": r\"Expires On: *(.+)\",\n        \"name_servers\": r\"Nameserver: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"NOT FOUND\" or \"No entries found for the selected source\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisRu(WhoisEntry):\n    \"\"\"Whois parser for .ru domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"creation_date\": r\"created: *(.+)\",\n        \"expiration_date\": r\"paid-till: *(.+)\",\n        \"free_date\": r\"free-date: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",  # list of name servers\n        \"status\": r\"state: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n        \"org\": r\"org: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisNl(WhoisEntry):\n    \"\"\"Whois parser for .nl domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"expiration_date\": r\"Date\\sout\\sof\\squarantine:\\s*(.+)\",\n        \"updated_date\": r\"Updated\\sDate:\\s*(.+)\",\n        \"creation_date\": r\"Creation\\sDate:\\s*(.+)\",\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"registrar\": r\"Registrar:\\s*(.*\\n)\",\n        \"registrar_address\": r\"Registrar:\\s*(?:.*\\n){1}\\s*(.*)\",\n        \"registrar_postal_code\": r\"Registrar:\\s*(?:.*\\n){2}\\s*(\\S*)\\s(?:.*)\",\n        \"registrar_city\": r\"Registrar:\\s*(?:.*\\n){2}\\s*(?:\\S*)\\s(.*)\",\n        \"registrar_country\": r\"Registrar:\\s*(?:.*\\n){3}\\s*(.*)\",\n        \"reseller\": r\"Reseller:\\s*(.*\\n)\",\n        \"reseller_address\": r\"Reseller:\\s*(?:.*\\n){1}\\s*(.*)\",\n        \"reseller_postal_code\": r\"Reseller:\\s*(?:.*\\n){2}\\s*(\\S*)\\s(?:.*)\",\n        \"reseller_city\": r\"Reseller:\\s*(?:.*\\n){2}\\s*(?:\\S*)\\s(.*)\",\n        \"reseller_country\": r\"Reseller:\\s*(?:.*\\n){3}\\s*(.*)\",\n        \"abuse_phone\": r\"Abuse Contact:\\s*(.*\\n)\",\n        \"abuse_email\": r\"Abuse Contact:\\s*(?:.*\\n){1}\\s*(.*)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.rstrip().endswith(\"is free\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n        match = re.compile(\n            r\"Domain nameservers:(.*?)Record maintained by\", re.DOTALL\n        ).search(text)\n        if match:\n            duplicate_nameservers_with_ip = []\n            for line in match.groups()[0].strip().splitlines():\n                if line.strip() == \"\":\n                    break\n                duplicate_nameservers_with_ip.append(line.strip())\n            duplicate_nameservers_without_ip = [\n                nameserver.split(\" \")[0] for nameserver in duplicate_nameservers_with_ip\n            ]\n            self[\"name_servers\"] = sorted(list(set(duplicate_nameservers_without_ip)))\n\n\nclass WhoisLt(WhoisEntry):\n    \"\"\"Whois parser for .lt domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain:\\s?(.+)\",\n        \"expiration_date\": r\"Expires:\\s?(.+)\",\n        \"creation_date\": r\"Registered:\\s?(.+)\",\n        \"status\": r\"\\nStatus:\\s?(.+)\",  # list of statuses\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.rstrip().endswith(\"available\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n        match = re.compile(\n            r\"Domain nameservers:(.*?)Record maintained by\", re.DOTALL\n        ).search(text)\n        if match:\n            duplicate_nameservers_with_ip = [\n                line.strip() for line in match.groups()[0].strip().splitlines()\n            ]\n            duplicate_nameservers_without_ip = [\n                nameserver.split(\" \")[0] for nameserver in duplicate_nameservers_with_ip\n            ]\n            self[\"name_servers\"] = sorted(list(set(duplicate_nameservers_without_ip)))\n\n\nclass WhoisName(WhoisEntry):\n    \"\"\"Whois parser for .name domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name_id\": r\"Domain Name ID: *(.+)\",\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar_id\": r\"Sponsoring Registrar ID: *(.+)\",\n        \"registrar\": r\"Sponsoring Registrar: *(.+)\",\n        \"registrant_id\": r\"Registrant ID: *(.+)\",\n        \"admin_id\": r\"Admin ID: *(.+)\",\n        \"technical_id\": r\"Tech ID: *(.+)\",\n        \"billing_id\": r\"Billing ID: *(.+)\",\n        \"creation_date\": r\"Created On: *(.+)\",\n        \"expiration_date\": r\"Expires On: *(.+)\",\n        \"updated_date\": r\"Updated On: *(.+)\",\n        \"name_server_ids\": r\"Name Server ID: *(.+)\",  # list of name server ids\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No match for \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisUs(WhoisEntry):\n    \"\"\"Whois parser for .us domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Domain ID: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registry Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_organization\": r\"Registrant Organization: *(.+)\",\n        \"registrant_street\": r\"Registrant Street: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_phone\": r\"Registrant Phone: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"registrant_fax\": r\"Registrant Fax: *(.+)\",\n        \"registrant_application_purpose\": r\"Registrant Application Purpose: *(.+)\",\n        \"registrant_nexus_category\": r\"Registrant Nexus Category: *(.+)\",\n        \"admin_id\": r\"Registry Admin ID: *(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_street\": r\"Admin Street: *(.+)\",\n        \"admin_city\": r\"Admin City: *(.+)\",\n        \"admin_state_province\": r\"Admin State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code: *(.+)\",\n        \"admin_country\": r\"Admin Country: *(.+)\",\n        \"admin_phone\": r\"Admin Phone: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"admin_fax\": r\"Admin Fax: *(.+)\",\n        \"admin_application_purpose\": r\"Admin Application Purpose: *(.+)\",\n        \"admin_nexus_category\": r\"Admin Nexus Category: *(.+)\",\n        \"tech_id\": r\"Registry Tech ID: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_organization\": r\"Tech Organization: *(.+)\",\n        \"tech_street\": r\"Tech Street: *(.+)\",\n        \"tech_city\": r\"Tech City: *(.+)\",\n        \"tech_state_province\": r\"Tech State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code: *(.+)\",\n        \"tech_country\": r\"Tech Country: *(.+)\",\n        \"tech_phone\": r\"Tech Phone: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"tech_fax\": r\"Tech Fax: *(.+)\",\n        \"tech_application_purpose\": r\"Tech Application Purpose: *(.+)\",\n        \"tech_nexus_category\": r\"Tech Nexus Category: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n    }\n\n    def __init__(self, domain, text):\n        if \"No Data Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisPl(WhoisEntry):\n    \"\"\"Whois parser for .pl domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"DOMAIN NAME: *(.+)\\n\",\n        \"name_servers\": r\"nameservers:(?:\\s+(\\S+)\\.[^\\n]*\\n)(?:\\s+(\\S+)\\.[^\\n]*\\n)?(?:\\s+(\\S+)\\.[^\\n]*\\n)?(?:\\s+(\\S+)\\.[^\\n]*\\n)?\",  # up to 4\n        \"registrar\": r\"REGISTRAR:\\s*(.+)\",\n        \"registrar_url\": r\"URL: *(.+)\",  # not available\n        \"status\": r\"Registration status:\\n\\s*(.+)\",  # not available\n        \"registrant_name\": r\"Registrant:\\n\\s*(.+)\",  # not available\n        \"creation_date\": r\"(?<! )created: *(.+)\\n\",\n        \"expiration_date\": r\"renewal date: *(.+)\",\n        \"updated_date\": r\"last modified: *(.+)\\n\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No information available about domain name\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisGroup(WhoisEntry):\n    \"\"\"Whois parser for .group domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Registry Domain ID:(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"updated_date\": r\"Updated Date: (.+)\",\n        \"creation_date\": r\"Creation Date: (.+)\",\n        \"expiration_date\": r\"Expir\\w+ Date:\\s?(.+)\",\n        \"registrar\": r\"Registrar:(.+)\",\n        \"status\": r\"Domain status: *(.+)\",\n        \"registrant_name\": r\"Registrant Name:(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain not found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCa(WhoisEntry):\n    \"\"\"Whois parser for .ca domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_number\": r\"Registry Registrant ID: *(.+)\",\n        \"admin_name\": r\"Admin Name: *(.+)\",\n        \"status\": r\"Domain status: *(.+)\",\n        \"emails\": r\"Email: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expiry Date: *(.+)\",\n        \"phone\": r\"Phone: *(.+)\",\n        \"fax\": r\"Fax: *(.+)\",\n        \"dnssec\": r\"dnssec: *([\\S]+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain status:         available\" in text or \"Not found:\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisMe(WhoisEntry):\n    \"\"\"Whois parser for .me domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_id\": r\"Registry Domain ID:(.+)\",\n        \"domain_name\": r\"Domain Name:(.+)\",\n        \"creation_date\": r\"Creation Date:(.+)\",\n        \"updated_date\": r\"Updated Date:(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: (.+)\",\n        \"registrar\": r\"Registrar:(.+)\",\n        \"status\": r\"Domain Status:(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registrant ID:(.+)\",\n        \"registrant_name\": r\"Registrant Name:(.+)\",\n        \"registrant_org\": r\"Registrant Organization:(.+)\",\n        \"registrant_address\": r\"Registrant Address:(.+)\",\n        \"registrant_address2\": r\"Registrant Address2:(.+)\",\n        \"registrant_address3\": r\"Registrant Address3:(.+)\",\n        \"registrant_city\": r\"Registrant City:(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province:(.+)\",\n        \"registrant_country\": r\"Registrant Country/Economy:(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code:(.+)\",\n        \"registrant_phone\": r\"Registrant Phone:(.+)\",\n        \"registrant_phone_ext\": r\"Registrant Phone Ext\\.:(.+)\",\n        \"registrant_fax\": r\"Registrant FAX:(.+)\",\n        \"registrant_fax_ext\": r\"Registrant FAX Ext\\.:(.+)\",\n        \"registrant_email\": r\"Registrant E-mail:(.+)\",\n        \"admin_id\": r\"Admin ID:(.+)\",\n        \"admin_name\": r\"Admin Name:(.+)\",\n        \"admin_org\": r\"Admin Organization:(.+)\",\n        \"admin_address\": r\"Admin Address:(.+)\",\n        \"admin_address2\": r\"Admin Address2:(.+)\",\n        \"admin_address3\": r\"Admin Address3:(.+)\",\n        \"admin_city\": r\"Admin City:(.+)\",\n        \"admin_state_province\": r\"Admin State/Province:(.+)\",\n        \"admin_country\": r\"Admin Country/Economy:(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code:(.+)\",\n        \"admin_phone\": r\"Admin Phone:(.+)\",\n        \"admin_phone_ext\": r\"Admin Phone Ext\\.:(.+)\",\n        \"admin_fax\": r\"Admin FAX:(.+)\",\n        \"admin_fax_ext\": r\"Admin FAX Ext\\.:(.+)\",\n        \"admin_email\": r\"Admin E-mail:(.+)\",\n        \"tech_id\": r\"Tech ID:(.+)\",\n        \"tech_name\": r\"Tech Name:(.+)\",\n        \"tech_org\": r\"Tech Organization:(.+)\",\n        \"tech_address\": r\"Tech Address:(.+)\",\n        \"tech_address2\": r\"Tech Address2:(.+)\",\n        \"tech_address3\": r\"Tech Address3:(.+)\",\n        \"tech_city\": r\"Tech City:(.+)\",\n        \"tech_state_province\": r\"Tech State/Province:(.+)\",\n        \"tech_country\": r\"Tech Country/Economy:(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code:(.+)\",\n        \"tech_phone\": r\"Tech Phone:(.+)\",\n        \"tech_phone_ext\": r\"Tech Phone Ext\\.:(.+)\",\n        \"tech_fax\": r\"Tech FAX:(.+)\",\n        \"tech_fax_ext\": r\"Tech FAX Ext\\.:(.+)\",\n        \"tech_email\": r\"Tech E-mail:(.+)\",\n        \"name_servers\": r\"Nameservers:(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"NOT FOUND\" in text or \"Domain not found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisUk(WhoisEntry):\n    \"\"\"Whois parser for .uk domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name:\\s*(.+)\",\n        \"registrar\": r\"Registrar:\\s*(.+)\",\n        \"registrar_url\": r\"URL:\\s*(.+)\",\n        \"status\": r\"Registration status:\\s*(.+)\",  # list of statuses\n        \"registrant_name\": r\"Registrant:\\s*(.+)\",\n        \"registrant_type\": r\"Registrant type:\\s*(.+)\",\n        \"registrant_street\": r\"Registrant\\'s address:\\s*(?:.*\\n){2}\\s+(.*)\",\n        \"registrant_city\": r\"Registrant\\'s address:\\s*(?:.*\\n){3}\\s+(.*)\",\n        \"registrant_country\": r\"Registrant\\'s address:\\s*(?:.*\\n){5}\\s+(.*)\",\n        \"creation_date\": r\"Registered on:\\s*(.+)\",\n        \"expiration_date\": r\"Expiry date:\\s*(.+)\",\n        \"updated_date\": r\"Last updated:\\s*(.+)\",\n        \"name_servers\": r\"([\\w.-]+\\.(?:[\\w-]+\\.){1,2}[a-zA-Z]{2,}(?!\\s+Relevant|\\s+Data))\\s+\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No match for \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisAfnic(WhoisEntry):\n    \"\"\"Whois parser for AFNIC domains (.fr, .re, .pm, .tf, .wf, .yt)\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"creation_date\": r\"created: *(.+)\",\n        \"expiration_date\": r\"Expir\\w+ Date:\\s?(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",  # list of name servers\n        \"status\": r\"status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n        \"updated_date\": r\"last-update: *(.+)\",\n        \"holder_c\": r\"holder-c: *(.+)\",\n        \"admin_c\": r\"admin-c: *(.+)\",\n        \"tech_c\": r\"tech-c: *(.+)\",\n    }\n\n    # AFNIC field names to standard WhoisEntry field suffixes\n    _contact_field_mapping = {\n        \"contact\": \"name\",\n        \"type\": \"type\",\n        \"address\": \"address\",\n        \"country\": \"country\",\n        \"phone\": \"phone\",\n        \"e-mail\": \"email\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found\" in text or \"NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n            self._resolve_contacts(text)\n\n    def _resolve_contacts(self, text: str) -> None:\n        \"\"\"Resolve AFNIC handle references (holder-c, admin-c, tech-c) to contact fields.\"\"\"\n        handle_to_prefix = [\n            (self.pop(\"holder_c\", None), \"registrant\"),\n            (self.pop(\"admin_c\", None), \"admin\"),\n            (self.pop(\"tech_c\", None), \"tech\"),\n        ]\n\n        contact_blocks = self._extract_contact_blocks(text)\n\n        for handle, prefix in handle_to_prefix:\n            if handle and handle in contact_blocks:\n                for afnic_field, suffix in self._contact_field_mapping.items():\n                    value = contact_blocks[handle].get(afnic_field)\n                    if value is not None:\n                        self[f\"{prefix}_{suffix}\"] = value\n\n    @staticmethod\n    def _extract_contact_blocks(text: str) -> dict[str, dict[str, Any]]:\n        \"\"\"Parse all nic-hdl contact blocks from AFNIC whois text.\"\"\"\n        contacts: dict[str, dict[str, Any]] = {}\n\n        for block in re.split(r\"\\n\\s*\\n\", text):\n            hdl_match = re.search(r\"^nic-hdl:\\s*(.+)$\", block, re.M | re.I)\n            if not hdl_match:\n                continue\n\n            handle = hdl_match.group(1).strip()\n            data: dict[str, Any] = {}\n\n            for line in block.splitlines():\n                if \":\" not in line:\n                    continue\n                field, value = line.split(\":\", 1)\n                field = field.strip().lower()\n                value = value.strip()\n                if not value:\n                    continue\n\n                if field == \"address\":\n                    data.setdefault(\"address\", [])\n                    data[\"address\"].append(value)\n                elif field not in data:\n                    data[field] = value\n\n            # Join multi-line addresses\n            if \"address\" in data:\n                data[\"address\"] = \"\\n\".join(data[\"address\"])\n\n            contacts[handle] = data\n\n        return contacts\n\n\nclass WhoisFi(WhoisEntry):\n    \"\"\"Whois parser for .fi domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain\\.*: *([\\S]+)\",\n        \"name\": r\"Holder\\s*name\\.*: (.+)\",\n        \"address\": r\"[Holder\\w\\W]address\\.*: (.+)\",\n        \"phone\": r\"Holder[\\s\\w\\W]+phone\\.*: (.+)\",\n        \"email\": r\"holder email\\.*: *([\\S]+)\",\n        \"status\": r\"status\\.*: (.+)\",  # list of statuses\n        \"creation_date\": r\"created\\.*: *([\\S]+)\",\n        \"updated_date\": r\"modified\\.*: *([\\S]+)\",\n        \"expiration_date\": r\"expires\\.*: *([\\S]+)\",\n        \"name_servers\": r\"nserver\\.*: *([\\S]+) \\[\\S+\\]\",  # list of name servers\n        \"name_server_statuses\": r\"nserver\\.*: *([\\S]+ \\[\\S+\\])\",  # list of name servers and statuses\n        \"dnssec\": r\"dnssec\\.*: *([\\S]+)\",\n        \"registrar\": r\"Registrar\\s*registrar\\.*: (.+)\",\n        \"registrar_site\": r\"Registrar[\\s\\w\\W]+www\\.*: (.+)\",\n    }\n\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain not \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisJp(WhoisEntry):\n    \"\"\"Parser for .jp domains\n\n    For testing, try *both* of:\n        nintendo.jp\n        nintendo.co.jp\n\n    \"\"\"\n\n    not_found = \"No match!!\"\n    regex: dict[str, str] = {\n        \"domain_name\": r\"^(?:a\\. )?\\[Domain Name\\]\\s*(.+)\",\n        \"registrant_org\": r\"^(?:g\\. )?\\[(?:Organization|Registrant)\\](.+)\",\n        \"creation_date\": r\"\\[(?:Registered Date|Created on)\\][ \\t]*(.+)\",\n        \"organization_type\": r\"^(?:l\\. )?\\[Organization Type\\]\\s*(.+)$\",\n        \"technical_contact_name\": r\"^(?:n. )?\\[(?:Technical Contact)\\]\\s*(.+)\",\n        \"administrative_contact_name\": r\"^(?:m. )?(?:\\[Administrative Contact\\]\\s*(.+)|Contact Information:\\s+^\\[Name\\](.*))\",\n        # These don't need the X. at the beginning, I just was too lazy to split the pattern off\n        \"administrative_contact_email\": r\"^(?:X. )?(?:\\[Administrative Contact\\]\\s*(?:.+)|Contact Information:\\s+)(?:^\\s*.*\\s+)*(?:^\\[Email\\]\\s*(.*))\",\n        \"administrative_contact_phone\": r\"^(?:X. )?(?:\\[Administrative Contact\\]\\s*(?:.+)|Contact Information:\\s+)(?:^\\s*.*\\s+)*(?:^\\[Phone\\]\\s*(.*))\",\n        \"administrative_contact_fax\": r\"^(?:X. )?(?:\\[Administrative Contact\\]\\s*(?:.+)|Contact Information:\\s+)(?:^\\s*.*\\s+)*(?:^\\[Fax\\]\\s*(.*))\",\n        \"administrative_contact_post_code\": r\"^(?:X. )?(?:\\[Administrative Contact\\]\\s*(?:.+)|Contact Information:\\s+)(?:^\\s*.*\\s+)*(?:^\\[Postal code\\]\\s*(.*))\",\n        \"administrative_contact_postal_address\": r\"^(?:X. )?(?:\\[Administrative Contact\\]\\s*(?:.+)|Contact Information:\\s+)(?:^\\s*.*\\s+)*(?:^\\[Postal Address\\]\\s*(.*))\",\n        \"expiration_date\": r\"\\[Expires on\\]\\s*(.+)\",\n        \"name_servers\": r\"^(?:p\\. )?\\[Name Server\\]\\s*(.+)\",  # list\n        \"updated_date\": r\"^\\[Last Updated?\\]\\s?(.+)\",\n        \"signing_key\": r\"^(?:s\\. )?\\[Signing Key\\](.+)$\",\n        \"status\": r\"\\[(?:State|Status)\\]\\s*(.+)\",  # list\n    }\n\n    def __init__(self, domain: str, text: str):\n        if self.not_found in text:\n            raise WhoisDomainNotFoundError(text)\n\n        super().__init__(domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        # handle named timezone.  cast_date can't handle it, since datetime.parse doesn't support the format and\n        # strptime doesn't handle custom timezone names.\n        value = value.strip()\n        if value and isinstance(value, str) and \"_date\" in attr and value.endswith(\" (JST)\"):\n            value = value.replace(' (JST)', '')\n            value = cast_date(value, dayfirst=self.dayfirst, yearfirst=self.yearfirst)\n            value = value.replace(tzinfo=timezone(timedelta(seconds=tz_data['JST'])))\n            return value\n        else:\n            return super()._preprocess(attr, value)\n\nclass WhoisAU(WhoisEntry):\n    \"\"\"Whois parser for .au domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\\n\",\n        \"updated_date\": r\"Last Modified: *(.+)\\n\",\n        \"registrar\": r\"Registrar Name: *(.+)\\n\",\n        \"status\": r\"Status: *(.+)\",\n        \"registrant_name\": r\"Registrant: *(.+)\",\n        \"registrant_contact_name\": r\"Registrant Contact Name: (.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"registrant_id\": r\"Registrant ID: *(.+)\",\n        \"eligibility_type\": r\"Eligibility Type: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No Data Found\" or text.lstrip().startswith(\"Domain not found\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisRs(WhoisEntry):\n    \"\"\"Whois parser for .rs domains\"\"\"\n\n    _regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"status\": r\"Domain status: *(.+)\",  # list of statuses\n        \"creation_date\": r\"Registration date: *(.+)\",\n        \"updated_date\": r\"Modification date: *(.+)\",\n        \"expiration_date\": r\"Expiration date: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"name\": r\"Registrant: *(.+)\",\n        \"address\": r\"Registrant: *.+\\nAddress: *(.+)\",\n        \"admin_name\": r\"Administrative contact: *(.+)\",\n        \"admin_address\": r\"Administrative contact: *.+\\nAddress: *(.+)\",\n        \"tech_name\": r\"Technical contact: *(.+)\",\n        \"tech_address\": r\"Technical contact: *.+\\nAddress: *(.+)\",\n        \"name_servers\": r\"DNS: *(\\S+)\",  # list of name servers\n        \"dnssec\": r\"DNSSEC signed: *(\\S+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"%ERROR:103: Domain is not registered\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisEu(WhoisEntry):\n    \"\"\"Whois parser for .eu domains\"\"\"\n\n    _SECTION_BOUNDARY = r\"(?:Registrar|On-site(s)|Reseller|Registrant|Name servers|Keys|Please visit www.eurid.eu for more information.)\"\n\n    regex = {\n        \"domain_name\": r\"Domain:\\s*([^\\n\\r]+)\",\n        \"script\": r\"Script:\\s*([^\\n\\r]+)\",\n        \"reseller_org\": rf\"Reseller:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Organisation:\\s*([^\\n\\r]+)\",\n        \"reseller_lang\": rf\"Reseller:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Language:\\s*([^\\n\\r]+)\",\n        \"reseller_email\": rf\"Reseller:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Email:\\s*([^\\n\\r]+)\",\n        \"tech_org\": rf\"Technical:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Organisation:\\s*([^\\n\\r]+)\",\n        \"tech_lang\": rf\"Technical:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Language:\\s*([^\\n\\r]+)\",\n        \"tech_email\": rf\"Technical:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Email:\\s*([^\\n\\r]+)\",\n        \"registrar\": rf\"Registrar:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Name:\\s*([^\\n\\r]+)\",\n        \"registrar_url\": rf\"Registrar:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?^\\s*Website:\\s*([^\\n\\r]+)\",\n        \"name_servers\": rf\"Name servers:\\s*((?:^(?!\\s*$)(?!^(?:{_SECTION_BOUNDARY})\\s*:).+\\n)+)\",\n        \"dnssec_flags\": rf\"Keys:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?flags:\\s*([^\\s]+)\",\n        \"dnssec_protocol\": rf\"Keys:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?protocol:\\s*([0-9]+)\",\n        \"dnssec_algorithm\": rf\"Keys:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?algorithm:\\s*([A-Z0-9_]+)\",\n        \"dnssec_pubkey\": rf\"Keys:\\s*(?:(?!\\n(?:{_SECTION_BOUNDARY})\\s*:)[\\s\\S])*?pubKey:\\s*([A-Za-z0-9+/=]+)\",\n    }\n\n    def __init__(self, domain, text):\n        if text.strip().endswith(\"Status: AVAILABLE\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n            \n    def _preprocess(self, attr, value):\n        if attr == \"name_servers\" and isinstance(value, str):\n            return [ln.strip() for ln in value.strip().splitlines() if ln.strip()]\n        return value\n\n\nclass WhoisEe(WhoisEntry):\n    \"\"\"Whois parser for .ee domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *[\\n\\r]+\\s*name: *([^\\n\\r]+)\",\n        \"status\": r\"Domain: *[\\n\\r]+\\s*name: *[^\\n\\r]+\\sstatus: *([^\\n\\r]+)\",\n        \"creation_date\": r\"Domain: *[\\n\\r]+\\s*name: *[^\\n\\r]+\\sstatus: *[^\\n\\r]+\\sregistered: *([^\\n\\r]+)\",\n        \"updated_date\": r\"Domain: *[\\n\\r]+\\s*name: *[^\\n\\r]+\\sstatus: *[^\\n\\r]+\\sregistered: *[^\\n\\r]+\\schanged: \"\n        r\"*([^\\n\\r]+)\",\n        \"expiration_date\": r\"Domain: *[\\n\\r]+\\s*name: *[^\\n\\r]+\\sstatus: *[^\\n\\r]+\\sregistered: *[^\\n\\r]+\\schanged: \"\n        r\"*[^\\n\\r]+\\sexpire: *([^\\n\\r]+)\",\n        # 'tech_name': r'Technical: *Name: *([^\\n\\r]+)',\n        # 'tech_org': r'Technical: *Name: *[^\\n\\r]+\\s*Organisation: *([^\\n\\r]+)',\n        # 'tech_phone': r'Technical: *Name: *[^\\n\\r]+\\s*\n        # Organisation: *[^\\n\\r]+\\s*Language: *[^\\n\\r]+\\s*Phone: *([^\\n\\r]+)',\n        # 'tech_fax': r'Technical: *Name: *[^\\n\\r]+\\s*\n        # Organisation: *[^\\n\\r]+\\s*Language: *[^\\n\\r]+\\s*Phone: *[^\\n\\r]+\\s*Fax: *([^\\n\\r]+)',\n        # 'tech_email': r'Technical: *Name: *[^\\n\\r]+\\s*\n        # Organisation: *[^\\n\\r]+\\s*Language: *[^\\n\\r]+\\s*Phone: *[^\\n\\r]+\\s*Fax: *[^\\n\\r]+\\s*Email: *([^\\n\\r]+)',\n        \"registrar\": r\"Registrar: *[\\n\\r]+\\s*name: *([^\\n\\r]+)\",\n        \"name_servers\": r\"nserver: *(.*)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip().startswith(\"Domain not found\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBr(WhoisEntry):\n    \"\"\"Whois parser for .br domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\\n\",\n        \"registrant_name\": r\"owner: *([\\S ]+)\",\n        \"registrant_id\": r\"ownerid: *(.+)\",\n        \"country\": r\"country: *(.+)\",\n        \"owner_c\": r\"owner-c: *(.+)\",\n        \"admin_c\": r\"admin-c: *(.+)\",\n        \"tech_c\": r\"tech-c: *(.+)\",\n        \"billing_c\": r\"billing-c: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"nsstat\": r\"nsstat: *(.+)\",\n        \"nslastaa\": r\"nslastaa: *(.+)\",\n        \"saci\": r\"saci: *(.+)\",\n        \"creation_date\": r\"created: *(.+)\",\n        \"updated_date\": r\"changed: *(.+)\",\n        \"expiration_date\": r\"expires: *(.+)\",\n        \"status\": r\"status: *(.+)\",\n        \"nic_hdl_br\": r\"nic-hdl-br: *(.+)\",\n        \"person\": r\"person: *([\\S ]+)\",\n        \"email\": r\"e-mail: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Not found:\" in text or \"No match for \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        value = value.strip()\n        if value and isinstance(value, str) and \"_date\" in attr:\n            # try casting to date format\n            value = re.findall(r\"[\\w\\s:.-\\\\/]+\", value)[0].strip()\n            value = cast_date(value, dayfirst=self.dayfirst, yearfirst=self.yearfirst)\n        return value\n\n\nclass WhoisKr(WhoisEntry):\n    \"\"\"Whois parser for .kr domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name\\s*: *(.+)\",\n        \"registrant_name\": r\"Registrant\\s*: *(.+)\",\n        \"registrant_address\": r\"Registrant Address\\s*: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Zip Code\\s*: *(.+)\",\n        \"admin_name\": r\"Administrative Contact\\(AC\\)\\s*: *(.+)\",\n        \"admin_email\": r\"AC E-Mail\\s*: *(.+)\",\n        \"admin_phone\": r\"AC Phone Number\\s*: *(.+)\",\n        \"creation_date\": r\"Registered Date\\s*: *(.+)\",\n        \"updated_date\": r\"Last updated Date\\s*: *(.+)\",\n        \"expiration_date\": r\"Expiration Date\\s*: *(.+)\",\n        \"registrar\": r\"Authorized Agency\\s*: *(.+)\",\n        \"name_servers\": r\"Host Name\\s*: *(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.endswith(\" no match\") or \"The requested domain was not found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisPt(WhoisEntry):\n    \"\"\"Whois parser for .pt domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expiration Date: *(.+)\",\n        \"registrant_name\": r\"Owner Name: *(.+)\",\n        \"registrant_street\": r\"Owner Address: *(.+)\",\n        \"registrant_city\": r\"Owner Locality: *(.+)\",\n        \"registrant_postal_code\": r\"Owner ZipCode: *(.+)\",\n        \"registrant_email\": r\"Owner Email: *(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_street\": r\"Admin Address: *(.+)\",\n        \"admin_city\": r\"Admin Locality: *(.+)\",\n        \"admin_postal_code\": r\"Admin ZipCode: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+) \\|\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n    }\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No entries found\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBg(WhoisEntry):\n    \"\"\"Whois parser for .bg domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"DOMAIN NAME: *(.+)\\n\",\n        \"status\": r\"registration status: s*(.+)\",\n    }\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if \"does not exist in database!\" in text or \"registration status: available\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisDe(WhoisEntry):\n    \"\"\"Whois parser for .de domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"status\": r\"Status: *(.+)\",\n        \"updated_date\": r\"Changed: *(.+)\",\n        \"name\": r\"name: *(.+)\",\n        \"org\": r\"Organisation: *(.+)\",\n        \"address\": r\"Address: *(.+)\",\n        \"registrant_postal_code\": r\"PostalCode: *(.+)\",\n        \"city\": r\"City: *(.+)\",\n        \"country_code\": r\"CountryCode: *(.+)\",\n        \"phone\": r\"Phone: *(.+)\",\n        \"fax\": r\"Fax: *(.+)\",\n        \"name_servers\": r\"Nserver: *(.+)\",  # list of name servers\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n        \"created\": r\"created: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Status: free\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisAt(WhoisEntry):\n    \"\"\"Whois parser for .at domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"name\": r\"personname: *(.+)\",\n        \"org\": r\"organization: *(.+)\",\n        \"address\": r\"street address: *(.+)\",\n        \"registrant_postal_code\": r\"postal code: *(.+)\",\n        \"city\": r\"city: *(.+)\",\n        \"country\": r\"country: *(.+)\",\n        \"phone\": r\"phone: *(.+)\",\n        \"fax\": r\"fax-no: *(.+)\",\n        \"updated_date\": r\"changed: *(.+)\",\n        \"email\": r\"e-mail: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Status: free\" in text or text.rstrip().endswith('nothing found'):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBe(WhoisEntry):\n    \"\"\"Whois parser for .be domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"status\": r\"Status: *(.+)\",\n        \"name\": r\"Name: *(.+)\",\n        \"org\": r\"Organisation: *(.+)\",\n        \"phone\": r\"Phone: *(.+)\",\n        \"fax\": r\"Fax: *(.+)\",\n        \"email\": r\"Email: *(.+)\",\n        \"creation_date\": r\"Registered: *(.+)\",\n        \"name_servers\": r\"Nameservers:\\s((?:\\s+?[\\w.]+\\s)*)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Status: AVAILABLE\" in text or \"Status:\\tAVAILABLE\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisInfo(WhoisEntry):\n    \"\"\"Whois parser for .info domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"whois_server\": r\"Whois Server: *(.+)\",  # empty usually\n        \"referral_url\": r\"Referral URL: *(.+)\",  # http url of whois_server: empty usually\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"org\": r\"Registrant Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n    }\n\n    def __init__(self, domain, text):\n        if \"Domain not found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisRf(WhoisRu):\n    \"\"\"Whois parser for .su domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        WhoisRu.__init__(self, domain, text)\n\n\nclass WhoisSu(WhoisRu):\n    \"\"\"Whois parser for .su domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        WhoisRu.__init__(self, domain, text)\n\n\nclass WhoisBz(WhoisRu):\n    \"\"\"Whois parser for .bz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registry Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_organization\": r\"Registrant Organization: *(.+)\",\n        \"registrant_street\": r\"Registrant Street: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_phone_number\": r\"(?:Registrant Phone|Registrar Abuse Contact Phone): *(.+)\",\n        \"registrant_phone_number_ext\": r\"Registrant Phone Ext: *(.+)\",\n        \"registrant_email\": r\"(?:Registrant Email|Registrar Abuse Contact Email): *(.+)\",\n        \"admin_id\": r\"Registry Admin ID: *(.+)\",\n        \"admin_name\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_street\": r\"Admin Street: *(.+)\",\n        \"admin_city\": r\"Admin City: *(.+)\",\n        \"admin_state_province\": r\"Admin State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code: *(.+)\",\n        \"admin_country\": r\"Admin Country: *(.+)\",\n        \"admin_country_code\": r\"Administrative Contact Country Code: *(.+)\",\n        \"admin_phone_number\": r\"Admin Phone: *(.+)\",\n        \"admin_phone_number_ext\": r\"Admin Phone Ext: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"tech_id\": r\"Registry Tech ID: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_organization\": r\"Tech Organization: *(.+)\",\n        \"tech_street\": r\"Tech Street: *(.+)\",\n        \"tech_city\": r\"Tech City: *(.+)\",\n        \"tech_state_province\": r\"Tech State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code: *(.+)\",\n        \"tech_country\": r\"Tech Country: *(.+)\",\n        \"tech_phone_number\": r\"Tech Phone: *(.+)\",\n        \"tech_phone_number_ext\": r\"Tech Phone Ext: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registrar Registration Expiration Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCity(WhoisRu):\n    \"\"\"Whois parser for .city domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        WhoisRu.__init__(self, domain, text)\n\n\nclass WhoisStudio(WhoisBz):\n    \"\"\"Whois parser for .studio domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisStyle(WhoisRu):\n    \"\"\"Whois parser for .style domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        WhoisRu.__init__(self, domain, text)\n\n\nclass WhoisPyc(WhoisRu):\n    \"\"\"Whois parser for .рус domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        WhoisRu.__init__(self, domain, text)\n\n\nclass WhoisClub(WhoisEntry):\n    \"\"\"Whois parser for .us domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Domain ID: *(.+)\",\n        \"registrar\": r\"Sponsoring Registrar: *(.+)\",\n        \"registrar_id\": r\"Sponsoring Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL \\(registration services\\): *(.+)\",\n        # list of statuses\n        \"status\": r\"Domain Status: *(.+)\",\n        \"registrant_id\": r\"Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_address1\": r\"Registrant Address1: *(.+)\",\n        \"registrant_address2\": r\"Registrant Address2: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_country_code\": r\"Registrant Country Code: *(.+)\",\n        \"registrant_phone_number\": r\"Registrant Phone Number: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"registrant_application_purpose\": r\"Registrant Application Purpose: *(.+)\",\n        \"registrant_nexus_category\": r\"Registrant Nexus Category: *(.+)\",\n        \"admin_id\": r\"Administrative Contact ID: *(.+)\",\n        \"admin_name\": r\"Administrative Contact Name: *(.+)\",\n        \"admin_address1\": r\"Administrative Contact Address1: *(.+)\",\n        \"admin_address2\": r\"Administrative Contact Address2: *(.+)\",\n        \"admin_city\": r\"Administrative Contact City: *(.+)\",\n        \"admin_state_province\": r\"Administrative Contact State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Administrative Contact Postal Code: *(.+)\",\n        \"admin_country\": r\"Administrative Contact Country: *(.+)\",\n        \"admin_country_code\": r\"Administrative Contact Country Code: *(.+)\",\n        \"admin_phone_number\": r\"Administrative Contact Phone Number: *(.+)\",\n        \"admin_email\": r\"Administrative Contact Email: *(.+)\",\n        \"admin_application_purpose\": r\"Administrative Application Purpose: *(.+)\",\n        \"admin_nexus_category\": r\"Administrative Nexus Category: *(.+)\",\n        \"billing_id\": r\"Billing Contact ID: *(.+)\",\n        \"billing_name\": r\"Billing Contact Name: *(.+)\",\n        \"billing_address1\": r\"Billing Contact Address1: *(.+)\",\n        \"billing_address2\": r\"Billing Contact Address2: *(.+)\",\n        \"billing_city\": r\"Billing Contact City: *(.+)\",\n        \"billing_state_province\": r\"Billing Contact State/Province: *(.+)\",\n        \"billing_postal_code\": r\"Billing Contact Postal Code: *(.+)\",\n        \"billing_country\": r\"Billing Contact Country: *(.+)\",\n        \"billing_country_code\": r\"Billing Contact Country Code: *(.+)\",\n        \"billing_phone_number\": r\"Billing Contact Phone Number: *(.+)\",\n        \"billing_email\": r\"Billing Contact Email: *(.+)\",\n        \"billing_application_purpose\": r\"Billing Application Purpose: *(.+)\",\n        \"billing_nexus_category\": r\"Billing Nexus Category: *(.+)\",\n        \"tech_id\": r\"Technical Contact ID: *(.+)\",\n        \"tech_name\": r\"Technical Contact Name: *(.+)\",\n        \"tech_address1\": r\"Technical Contact Address1: *(.+)\",\n        \"tech_address2\": r\"Technical Contact Address2: *(.+)\",\n        \"tech_city\": r\"Technical Contact City: *(.+)\",\n        \"tech_state_province\": r\"Technical Contact State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Technical Contact Postal Code: *(.+)\",\n        \"tech_country\": r\"Technical Contact Country: *(.+)\",\n        \"tech_country_code\": r\"Technical Contact Country Code: *(.+)\",\n        \"tech_phone_number\": r\"Technical Contact Phone Number: *(.+)\",\n        \"tech_email\": r\"Technical Contact Email: *(.+)\",\n        \"tech_application_purpose\": r\"Technical Application Purpose: *(.+)\",\n        \"tech_nexus_category\": r\"Technical Nexus Category: *(.+)\",\n        # list of name servers\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"created_by_registrar\": r\"Created by Registrar: *(.+)\",\n        \"last_updated_by_registrar\": r\"Last Updated by Registrar: *(.+)\",\n        \"creation_date\": r\"Domain Registration Date: *(.+)\",\n        \"expiration_date\": r\"Domain Expiration Date: *(.+)\",\n        \"updated_date\": r\"Domain Last Updated Date: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Not found:\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIo(WhoisEntry):\n    \"\"\"Whois parser for .io domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Registry Domain ID: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"registrant_name\": r\"Registrant Organization: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"is available for purchase\" in text or 'Domain not found.' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBiz(WhoisEntry):\n    \"\"\"Whois parser for .biz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Domain ID: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_address\": r\"Registrant Street: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_country_code\": r\"Registrant Country Code: *(.+)\",\n        \"registrant_phone_number\": r\"Registrant Phone: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"admin_id\": r\"Registry Admin ID: *(.+)\",\n        \"admin_name\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_address\": r\"Admin Street: *(.+)\",\n        \"admin_city\": r\"Admin City: *(.+)\",\n        \"admin_state_province\": r\"Admin State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code: *(.+)\",\n        \"admin_country\": r\"Admin Country: *(.+)\",\n        \"admin_phone_number\": r\"Admin Phone: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"tech_id\": r\"Registry Tech ID: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_organization\": r\"Tech Organization: *(.+)\",\n        \"tech_address\": r\"Tech Street: *(.+)\",\n        \"tech_city\": r\"Tech City: *(.+)\",\n        \"tech_state_province\": r\"Tech State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code: *(.+)\",\n        \"tech_country\": r\"Tech Country: *(.+)\",\n        \"tech_phone_number\": r\"Tech Phone: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registrar Registration Expiration Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No Data Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisMobi(WhoisEntry):\n    \"\"\"Whois parser for .mobi domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_id\": r\"Registry Domain ID:(.+)\",\n        \"domain_name\": r\"Domain Name:(.+)\",\n        \"creation_date\": r\"Creation Date:(.+)\",\n        \"updated_date\": r\"Updated Date:(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: (.+)\",\n        \"registrar\": r\"Registrar:(.+)\",\n        \"status\": r\"Domain Status:(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registrant ID:(.+)\",\n        \"registrant_name\": r\"Registrant Name:(.+)\",\n        \"registrant_org\": r\"Registrant Organization:(.+)\",\n        \"registrant_address\": r\"Registrant Address:(.+)\",\n        \"registrant_address2\": r\"Registrant Address2:(.+)\",\n        \"registrant_address3\": r\"Registrant Address3:(.+)\",\n        \"registrant_city\": r\"Registrant City:(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province:(.+)\",\n        \"registrant_country\": r\"Registrant Country/Economy:(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code:(.+)\",\n        \"registrant_phone\": r\"Registrant Phone:(.+)\",\n        \"registrant_phone_ext\": r\"Registrant Phone Ext\\.:(.+)\",\n        \"registrant_fax\": r\"Registrant FAX:(.+)\",\n        \"registrant_fax_ext\": r\"Registrant FAX Ext\\.:(.+)\",\n        \"registrant_email\": r\"Registrant E-mail:(.+)\",\n        \"admin_id\": r\"Admin ID:(.+)\",\n        \"admin_name\": r\"Admin Name:(.+)\",\n        \"admin_org\": r\"Admin Organization:(.+)\",\n        \"admin_address\": r\"Admin Address:(.+)\",\n        \"admin_address2\": r\"Admin Address2:(.+)\",\n        \"admin_address3\": r\"Admin Address3:(.+)\",\n        \"admin_city\": r\"Admin City:(.+)\",\n        \"admin_state_province\": r\"Admin State/Province:(.+)\",\n        \"admin_country\": r\"Admin Country/Economy:(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code:(.+)\",\n        \"admin_phone\": r\"Admin Phone:(.+)\",\n        \"admin_phone_ext\": r\"Admin Phone Ext\\.:(.+)\",\n        \"admin_fax\": r\"Admin FAX:(.+)\",\n        \"admin_fax_ext\": r\"Admin FAX Ext\\.:(.+)\",\n        \"admin_email\": r\"Admin E-mail:(.+)\",\n        \"tech_id\": r\"Tech ID:(.+)\",\n        \"tech_name\": r\"Tech Name:(.+)\",\n        \"tech_org\": r\"Tech Organization:(.+)\",\n        \"tech_address\": r\"Tech Address:(.+)\",\n        \"tech_address2\": r\"Tech Address2:(.+)\",\n        \"tech_address3\": r\"Tech Address3:(.+)\",\n        \"tech_city\": r\"Tech City:(.+)\",\n        \"tech_state_province\": r\"Tech State/Province:(.+)\",\n        \"tech_country\": r\"Tech Country/Economy:(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code:(.+)\",\n        \"tech_phone\": r\"Tech Phone:(.+)\",\n        \"tech_phone_ext\": r\"Tech Phone Ext\\.:(.+)\",\n        \"tech_fax\": r\"Tech FAX:(.+)\",\n        \"tech_fax_ext\": r\"Tech FAX Ext\\.:(.+)\",\n        \"tech_email\": r\"Tech E-mail:(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisKg(WhoisEntry):\n    \"\"\"Whois parser for .kg domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain\\s*([\\w]+\\.[\\w]{2,5})\",\n        \"registrar\": r\"Domain support: \\s*(.+)\",\n        \"registrant_name\": r\"Name: *(.+)\",\n        \"registrant_address\": r\"Address: *(.+)\",\n        \"registrant_phone_number\": r\"phone: *(.+)\",\n        \"registrant_email\": r\"Email: *(.+)\",\n        # # list of name servers\n        \"name_servers\": r\"Name servers in the listed order: *([\\d\\w\\.\\s]+)\",\n        # 'name_servers':                 r'([\\w]+\\.[\\w]+\\.[\\w]{2,5}\\s*\\d{1,3}\\.\\d]{1,3}\\.[\\d]{1-3}\\.[\\d]{1-3})',\n        \"creation_date\": r\"Record created: *(.+)\",\n        \"expiration_date\": r\"Record expires on:\\s*(.+)\",\n        \"updated_date\": r\"Record last updated on:\\s*(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Data not found. This domain is available for registration\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisChLi(WhoisEntry):\n    \"\"\"Whois Parser for .ch and .li domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"\\nDomain name:\\n*(.+)\",\n        \"registrant_name\": r\"Holder of domain name:\\s*(?:.*\\n){1}\\s*(.+)\",\n        \"registrant_address\": r\"Holder of domain name:\\s*(?:.*\\n){2}\\s*(.+)\",\n        \"registrar\": r\"Registrar:\\n*(.+)\",\n        \"creation_date\": r\"First registration date:\\n*(.+)\",\n        \"dnssec\": r\"DNSSEC:*([\\S]+)\",\n        \"tech-c\": r\"Technical contact:\\n*([\\n\\s\\S]+)\\nRegistrar:\",\n        \"name_servers\": r\"Name servers:\\n *([\\n\\S\\s]+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"We do not have an entry in our database matching your query.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisID(WhoisEntry):\n    \"\"\"Whois parser for .id domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_id\": r\"Registry Domain ID:(.+)\",\n        \"domain_name\": r\"Domain Name:(.+)\",\n        \"creation_date\": r\"Creation Date:(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date:(.+)\",\n        \"updated_date\": r\"Updated Date:(.+)\",\n        \"dnssec\": r\"DNSSEC:(.+)\",\n        \"registrar\": r\"Registrar:(.+)\",\n        \"registrar_city\": r\"Sponsoring Registrar City:(.+)\",\n        \"registrar_postal_code\": r\"Sponsoring Registrar Postal Code:(.+)\",\n        \"registrar_country\": r\"Sponsoring Registrar Country:(.+)\",\n        \"registrar_phone\": r\"Sponsoring Registrar Phone:(.+)\",\n        \"registrar_email\": r\"Sponsoring Registrar Contact Email:(.+)\",\n        \"registrar_url\": r\"Registrar URL:(.+)\",\n        \"status\": r\"Status:(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registrant ID:(.+)\",\n        \"registrant_name\": r\"Registrant Name:(.+)\",\n        \"registrant_org\": r\"Registrant Organization:(.+)\",\n        \"registrant_address\": r\"Registrant Street1:(.+)\",\n        \"registrant_address2\": r\"Registrant Street2:(.+)\",\n        \"registrant_address3\": r\"Registrant Street3:(.+)\",\n        \"registrant_city\": r\"Registrant City:(.+)\",\n        \"registrant_country\": r\"Registrant Country:(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code:(.+)\",\n        \"registrant_phone\": r\"Registrant Phone:(.+)\",\n        \"registrant_fax\": r\"Registrant FAX:(.+)\",\n        \"registrant_email\": r\"Registrant Email:(.+)\",\n        \"name_servers\": r\"Name Server:(.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSe(WhoisEntry):\n    \"\"\"Whois parser for .se domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain\\.*: *(.+)\",\n        \"registrant_name\": r\"holder\\.*: *(.+)\",\n        \"creation_date\": r\"created\\.*: *(.+)\",\n        \"updated_date\": r\"modified\\.*: *(.+)\",\n        \"expiration_date\": r\"expires\\.*: *(.+)\",\n        \"transfer_date\": r\"transferred\\.*: *(.+)\",\n        \"name_servers\": r\"nserver\\.*: *(.+)\",  # list of name servers\n        \"dnssec\": r\"dnssec\\.*: *(.+)\",\n        \"status\": r\"status\\.*: *(.+)\",  # list of statuses\n        \"registrar\": r\"registrar: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisJobs(WhoisEntry):\n    \"\"\"Whois parser for .jobs domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_name\": r\"Registrar: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: (.+)\",\n        \"registrant_id\": r\"Registry Registrant ID: (.+)\",\n        \"registrant_organization\": r\"Registrant Organization: (.+)\",\n        \"registrant_city\": r\"Registrant City: (.*)\",\n        \"registrant_street\": r\"Registrant Street: (.*)\",\n        \"registrant_state_province\": r\"Registrant State/Province: (.*)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: (.*)\",\n        \"registrant_country\": r\"Registrant Country: (.+)\",\n        \"registrant_phone\": r\"Registrant Phone: (.+)\",\n        \"registrant_fax\": r\"Registrant Fax: (.+)\",\n        \"registrant_email\": r\"Registrant Email: (.+)\",\n        \"admin_name\": r\"Admin Name: (.+)\",\n        \"admin_id\": r\"Registry Admin ID: (.+)\",\n        \"admin_organization\": r\"Admin Organization: (.+)\",\n        \"admin_city\": r\"Admin City: (.*)\",\n        \"admin_street\": r\"Admin Street: (.*)\",\n        \"admin_state_province\": r\"Admin State/Province: (.*)\",\n        \"admin_postal_code\": r\"Admin Postal Code: (.*)\",\n        \"admin_country\": r\"Admin Country: (.+)\",\n        \"admin_phone\": r\"Admin Phone: (.+)\",\n        \"admin_fax\": r\"Admin Fax: (.+)\",\n        \"admin_email\": r\"Admin Email: (.+)\",\n        \"billing_name\": r\"Billing Name: (.+)\",\n        \"billing_id\": r\"Registry Billing ID: (.+)\",\n        \"billing_organization\": r\"Billing Organization: (.+)\",\n        \"billing_city\": r\"Billing City: (.*)\",\n        \"billing_street\": r\"Billing Street: (.*)\",\n        \"billing_state_province\": r\"Billing State/Province: (.*)\",\n        \"billing_postal_code\": r\"Billing Postal Code: (.*)\",\n        \"billing_country\": r\"Billing Country: (.+)\",\n        \"billing_phone\": r\"Billing Phone: (.+)\",\n        \"billing_fax\": r\"Billing Fax: (.+)\",\n        \"billing_email\": r\"Billing Email: (.+)\",\n        \"tech_name\": r\"Tech Name: (.+)\",\n        \"tech_id\": r\"Registry Tech ID: (.+)\",\n        \"tech_organization\": r\"Tech Organization: (.+)\",\n        \"tech_city\": r\"Tech City: (.*)\",\n        \"tech_street\": r\"Tech Street: (.*)\",\n        \"tech_state_province\": r\"Tech State/Province: (.*)\",\n        \"tech_postal_code\": r\"Tech Postal Code: (.*)\",\n        \"tech_country\": r\"Tech Country: (.+)\",\n        \"tech_phone\": r\"Tech Phone: (.+)\",\n        \"tech_fax\": r\"Tech Fax: (.+)\",\n        \"tech_email\": r\"Tech Email: (.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIt(WhoisEntry):\n    \"\"\"Whois parser for .it domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"creation_date\": r\"(?<! )Created: *(.+)\",\n        \"updated_date\": r\"(?<! )Last Update: *(.+)\",\n        \"expiration_date\": r\"(?<! )Expire Date: *(.+)\",\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"name_servers\": r\"Nameservers[\\s]((?:.+\\n)*)\",  # servers in one string sep by \\n\n        \"registrant_organization\": r\"(?<=Registrant)[\\s\\S]*?Organization:(.*)\",\n        \"registrant_address\": r\"(?<=Registrant)[\\s\\S]*?Address:(.*)\",\n        \"admin_address\": r\"(?<=Admin Contact)[\\s\\S]*?Address:(.*)\",\n        \"admin_organization\": r\"(?<=Admin Contact)[\\s\\S]*?Organization:(.*)\",\n        \"admin_name\": r\"(?<=Admin Contact)[\\s\\S]*?Name:(.*)\",\n        \"tech_address\": r\"(?<=Technical Contacts)[\\s\\S]*?Address:(.*)\",\n        \"tech_organization\": r\"(?<=Technical Contacts)[\\s\\S]*?Organization:(.*)\",\n        \"tech_name\": r\"(?<=Technical Contacts)[\\s\\S]*?Name:(.*)\",\n        \"registrar_address\": r\"(?<=Registrar)[\\s\\S]*?Address:(.*)\",\n        \"registrar\": r\"(?<=Registrar)[\\s\\S]*?Organization:(.*)\",\n        \"registrar_name\": r\"(?<=Registrar)[\\s\\S]*?Name:(.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text or \"Status:             AVAILABLE\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSa(WhoisEntry):\n    \"\"\"Whois parser for .sa domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"creation_date\": r\"Created on: *(.+)\",\n        \"updated_date\": r\"Last Updated on: *(.+)\",\n        \"name_servers\": r\"Name Servers:[\\s]((?:.+\\n)*)\",  # servers in one string sep by \\n\n        \"registrant_name\": r\"Registrant:\\s*(.+)\",\n        \"registrant_address\": r\"(?<=Registrant)[\\s\\S]*?Address:((?:.+\\n)*)\",\n        \"admin_address\": r\"(?<=Administrative Contact)[\\s\\S]*?Address:((?:.+\\n)*)\",\n        \"admin\": r\"Administrative Contact:\\s*(.*)\",\n        \"tech_address\": r\"(?<=Technical Contact)[\\s\\S]*?Address:((?:.+\\n)*)\",\n        \"tech\": r\"Technical Contact:\\s*(.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSK(WhoisEntry):\n    \"\"\"Whois parser for .sk domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"creation_date\": r\"(?<=Domain:)[\\s\\w\\W]*?Created: *(.+)\",\n        \"updated_date\": r\"(?<=Domain:)[\\s\\w\\W]*?Updated: *(.+)\",\n        \"expiration_date\": r\"Valid Until: *(.+)\",\n        \"name_servers\": r\"Nameserver: *(.+)\",\n        \"registrar\": r\"(?<=Registrar)[\\s\\S]*?Organization:(.*)\",\n        \"registrar_organization_id\": r\"(?<=Registrar)[\\s\\S]*?Organization ID:(.*)\",\n        \"registrar_name\": r\"(?<=Registrar)[\\s\\S]*?Name:(.*)\",\n        \"registrar_phone\": r\"(?<=Registrar)[\\s\\S]*?Phone:(.*)\",\n        \"registrar_email\": r\"(?<=Registrar)[\\s\\S]*?Email:(.*)\",\n        \"registrar_street\": r\"(?<=Registrar)[\\s\\S]*?Street:(.*)\",\n        \"registrar_city\": r\"(?<=Registrar)[\\s\\S]*?City:(.*)\",\n        \"registrar_postal_code\": r\"(?<=Registrar)[\\s\\S]*?Postal Code:(.*)\",\n        \"registrar_country_code\": r\"(?<=Registrar)[\\s\\S]*?Country Code:(.*)\",\n        \"registrar_created\": r\"(?<=Registrant)[\\s\\S]*?Created:(.*)\",\n        \"registrar_updated\": r\"(?<=Registrant)[\\s\\S]*?Updated:(.*)\",\n        \"admin\": r\"Contact:\\s*(.*)\",\n        \"admin_organization\": r\"(?<=Contact)[\\s\\S]*Organization:(.*)\",\n        \"admin_email\": r\"(?<=Contact)[\\s\\S]*Email:(.*)\",\n        \"admin_street\": r\"(?<=Contact)[\\s\\S]*Street:(.*)\",\n        \"admin_city\": r\"(?<=Contact)[\\s\\S]*City:(.*)\",\n        \"admin_postal_code\": r\"(?<=Contact)[\\s\\S]*Postal Code:(.*)\",\n        \"admin_country_code\": r\"(?<=Contact)[\\s\\S]*Country Code:(.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisMx(WhoisEntry):\n    \"\"\"Whois parser for .mx domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"creation_date\": r\"Created On: *(.+)\",\n        \"updated_date\": r\"Last Updated On: *(.+)\",\n        \"expiration_date\": r\"Expiration Date: *(.+)\",\n        \"url\": r\"URL: *(.+)\",\n        \"name_servers\": r\"DNS: (.*)\",  # servers in one string sep by \\n\n        \"registrar\": r\"Registrar:\\s*(.+)\",\n        \"registrant_name\": r\"(?<=Registrant)[\\s\\S]*?Name:(.*)\",\n        \"registrant_city\": r\"(?<=Registrant)[\\s\\S]*?City:(.*)\",\n        \"registrant_state\": r\"(?<=Registrant)[\\s\\S]*?State:(.*)\",\n        \"registrant_country\": r\"(?<=Registrant)[\\s\\S]*?Country:(.*)\",\n        \"admin\": r\"(?<=Administrative Contact)[\\s\\S]*?Name:(.*)\",\n        \"admin_city\": r\"(?<=Administrative Contact)[\\s\\S]*?City:(.*)\",\n        \"admin_country\": r\"(?<=Administrative Contact)[\\s\\S]*?Country:(.*)\",\n        \"admin_state\": r\"(?<=Administrative Contact)[\\s\\S]*?State:(.*)\",\n        \"tech_name\": r\"(?<=Technical Contact)[\\s\\S]*?Name:(.*)\",\n        \"tech_city\": r\"(?<=Technical Contact)[\\s\\S]*?City:(.*)\",\n        \"tech_state\": r\"(?<=Technical Contact)[\\s\\S]*?State:(.*)\",\n        \"tech_country\": r\"(?<=Technical Contact)[\\s\\S]*?Country:(.*)\",\n        \"billing_name\": r\"(?<=Billing Contact)[\\s\\S]*?Name:(.*)\",\n        \"billing_city\": r\"(?<=Billing Contact)[\\s\\S]*?City:(.*)\",\n        \"billing_state\": r\"(?<=Billing Contact)[\\s\\S]*?State:(.*)\",\n        \"billing_country\": r\"(?<=Billing Contact)[\\s\\S]*?Country:(.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text or \"Object_Not_Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisTw(WhoisEntry):\n    \"\"\"Whois parser for .tw domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"creation_date\": r\"Record created on (.+) \",\n        \"expiration_date\": r\"Record expires on (.+) \",\n        # servers in one string sep by \\n\n        \"name_servers\": r\"Domain servers in listed order:((?:\\s.+)*)\",\n        \"registrar\": r\"Registration Service Provider: *(.+)\",\n        \"registrar_url\": r\"Registration Service URL: *(.+)\",\n        \"registrant_name\": r\"(?<=Registrant:)\\s+(.*)\",\n        \"registrant_organization\": r\"(?<=Registrant:)\\s*(.*)\",\n        \"registrant_city\": r\"(?<=Registrant:)\\s*(?:.*\\n){5}\\s+(.*),\",\n        \"registrant_street\": r\"(?<=Registrant:)\\s*(?:.*\\n){4}\\s+(.*)\",\n        \"registrant_state_province\": r\"(?<=Registrant:)\\s*(?:.*\\n){5}.*, (.*)\",\n        \"registrant_country\": r\"(?<=Registrant:)\\s*(?:.*\\n){6}\\s+(.*)\",\n        \"registrant_phone\": r\"(?<=Registrant:)\\s*(?:.*\\n){2}\\s+(\\+*\\d.*)\",\n        \"registrant_fax\": r\"(?<=Registrant:)\\s*(?:.*\\n){3}\\s+(\\+*\\d.*)\",\n        \"registrant_email\": r\"(?<=Registrant:)\\s*(?:.*\\n){1}.*  (.*)\",\n        \"admin\": r\"(?<=Administrative Contact:\\n)\\s+(.*)  \",\n        \"admin_email\": r\"(?<=Administrative Contact:)\\s*.*  (.*)\",\n        \"admin_phone\": r\"(?<=Administrative Contact:\\n)\\s*(?:.*\\n){1}\\s+(\\+*\\d.*)\",\n        \"admin_fax\": r\"(?<=Administrative Contact:\\n)\\s*(?:.*\\n){2}\\s+(\\+*\\d.*)\",\n        \"tech\": r\"(?<=Technical Contact:\\n)\\s+(.*)  \",\n        \"tech_email\": r\"(?<=Technical Contact:)\\s*.*  (.*)\",\n        \"tech_phone\": r\"(?<=Technical Contact:\\n)\\s*(?:.*\\n){1}\\s+(\\+*\\d.*)\",\n        \"tech_fax\": r\"(?<=Technical Contact:\\n)\\s*(?:.*\\n){2}\\s+(\\+*\\d.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text or \"No Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisTr(WhoisEntry):\n    \"\"\"Whois parser for .tr domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"[**] Domain Name: *(.+)\",\n        \"creation_date\": r\"Created on.*: *(.+)\",\n        \"expiration_date\": r\"Expires on.*: *(.+)\",\n        \"frozen_status\": r\"Frozen Status: *(.+)\",\n        \"status\": r\"Transfer Status: *(.+)\",\n        \"name_servers\": r\"[**] Domain servers:((?:\\s.+)*)\",  # servers in one string sep by \\n\n        \"registrant_name\": r\"(?<=[**] Registrant:)[\\s\\S]((?:\\s.+)*)\",\n        \"admin\": r\"(?<=[**] Administrative Contact:)[\\s\\S]*?NIC Handle\\s+: (.*)\",\n        \"admin_organization\": r\"(?<=[**] Administrative Contact:)[\\s\\S]*?Organization Name\\s+: (.*)\",\n        \"admin_address\": r\"(?<=[**] Administrative Contact)[\\s\\S]*?Address\\s+: (.*)\",\n        \"admin_phone\": r\"(?<=[**] Administrative Contact)[\\s\\S]*?Phone\\s+: (.*)\",\n        \"admin_fax\": r\"(?<=[**] Administrative Contact)[\\s\\S]*?Fax\\s+: (.*)\",\n        \"tech\": r\"(?<=[**] Technical Contact:)[\\s\\S]*?NIC Handle\\s+: (.*)\",\n        \"tech_organization\": r\"(?<=[**] Technical Contact:)[\\s\\S]*?Organization Name\\s+: (.*)\",\n        \"tech_address\": r\"(?<=[**] Technical Contact)[\\s\\S]*?Address\\s+: (.*)\",\n        \"tech_phone\": r\"(?<=[**] Technical Contact)[\\s\\S]*?Phone\\s+: (.*)\",\n        \"tech_fax\": r\"(?<=[**] Technical Contact)[\\s\\S]*?Fax\\s+: (.*)\",\n        \"billing\": r\"(?<=[**] Billing Contact:)[\\s\\S]*?NIC Handle\\s+: (.*)\",\n        \"billing_organization\": r\"(?<=[**] Billing Contact:)[\\s\\S]*?Organization Name\\s+: (.*)\",\n        \"billing_address\": r\"(?<=[**] Billing Contact)[\\s\\S]*?Address\\s+: (.*)\",\n        \"billing_phone\": r\"(?<=[**] Billing Contact)[\\s\\S]*?Phone\\s+: (.*)\",\n        \"billing_fax\": r\"(?<=[**] Billing Contact)[\\s\\S]*?Fax\\s+: (.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not found.\" in text or \"No match found for \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIs(WhoisEntry):\n    \"\"\"Whois parser for .se domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain\\.*: *(.+)\",\n        \"registrant_name\": r\"registrant: *(.+)\",\n        \"name\": r\"person\\.*: *(.+)\",\n        \"address\": r\"address\\.*: *(.+)\",\n        \"creation_date\": r\"created\\.*: *(.+)\",\n        \"expiration_date\": r\"expires\\.*: *(.+)\",\n        \"email\": r\"e-mail: *(.+)\",\n        \"name_servers\": r\"nserver\\.*: *(.+)\",  # list of name servers\n        \"dnssec\": r\"dnssec\\.*: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisDk(WhoisEntry):\n    \"\"\"Whois parser for .dk domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain: *(.+)\",\n        \"creation_date\": r\"Registered: *(.+)\",\n        \"expiration_date\": r\"Expires: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"dnssec\": r\"Dnssec: *(.+)\",\n        \"status\": r\"Status: *(.+)\",\n        \"registrant_handle\": r\"Registrant\\s*(?:.*\\n){1}\\s*Handle: *(.+)\",\n        \"registrant_name\": r\"Registrant\\s*(?:.*\\n){2}\\s*Name: *(.+)\",\n        \"registrant_address\": r\"Registrant\\s*(?:.*\\n){3}\\s*Address: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant\\s*(?:.*\\n){4}\\s*Postalcode: *(.+)\",\n        \"registrant_city\": r\"Registrant\\s*(?:.*\\n){5}\\s*City: *(.+)\",\n        \"registrant_country\": r\"Registrant\\s*(?:.*\\n){6}\\s*Country: *(.+)\",\n        \"name_servers\": r\"Nameservers\\n *([\\n\\S\\s]+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No match for \" in text or \"No entries found for the selected source\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        if attr == \"name_servers\":\n            return [\n                line.split(\":\")[-1].strip()\n                for line in value.split(\"\\n\")\n                if line.startswith(\"Hostname\")\n            ]\n        return super(WhoisDk, self)._preprocess(attr, value)\n\n\nclass WhoisAi(WhoisEntry):\n    \"\"\"Whois parser for .ai domains\"\"\"\n\n    # More permissive with postal code\n    # Should be compatible with the previous format in case it returns\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name\\s*:\\s*(.+)\",\n        \"domain_id\": r\"Registry Domain ID\\s*:\\s*(.+)\",\n        \"status\": r\"Domain Status:\\s*(.+)\",\n        \"creation_date\": r\"Creation Date:\\s*(.+)\",\n        \"updated_date\": r\"Updated Date:\\s*(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"registrar\": r\"Registrar:\\s*(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone:\\s*(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email:\\s*(.+)\",\n        \"registrant_name\": r\"Registrant\\s*Name:\\s*(.+)\",\n        \"registrant_org\": r\"Registrant\\s*Organization:\\s*(.+)\",\n        \"registrant_address\": r\"Registrant\\s*Street:\\s*(.+)\",\n        \"registrant_city\": r\"Registrant\\s*City:\\s*(.+)\",\n        \"registrant_state\": r\"Registrant\\s*State.*:\\s*(.+)\",\n        \"registrant_postal_code\": r\"Registrant\\s*Postal\\s*Code\\s*:\\s*(.+)\",\n        \"registrant_country\": r\"Registrant\\s*Country\\s*:\\s*(.+)\",\n        \"registrant_phone\": r\"Registrant\\s*Phone\\.*:\\s*(.+)\",\n        \"registrant_email\": r\"Registrant\\s*Email\\.*:\\s*(.+)\",\n        \"admin_name\": r\"Admin\\s*Name:\\s*(.+)\",\n        \"admin_org\": r\"Admin\\s*Organization:\\s*(.+)\",\n        \"admin_address\": r\"Admin\\s*Street:\\s*(.+)\",\n        \"admin_city\": r\"Admin\\s*City:\\s*(.+)\",\n        \"admin_state\": r\"Admin\\s*State(?:/Province)?\\s*:\\s*(.+)\",\n        \"admin_postal_code\": r\"Admin\\s*Postal Code\\s*:\\s*(.+)\",\n        \"admin_country\": r\"Admin\\s*Country\\.*:\\s*(.+)\",\n        \"admin_phone\": r\"Admin\\s*Phone\\.*:\\s*(.+)\",\n        \"admin_email\": r\"Admin\\s*Email\\.*:\\s*(.+)\",\n        \"tech_name\": r\"Tech\\s*Name:\\s*(.+)\",\n        \"tech_org\": r\"Tech\\s*Organization:\\s*(.+)\",\n        \"tech_address\": r\"Tech\\s*Street:\\s*(.+)\",\n        \"tech_city\": r\"Tech\\s*City:\\s*(.+)\",\n        \"tech_state\": r\"Tech\\s*State.*:\\s*(.+)\",\n        \"tech_postal_code\": r\"Tech\\s*Postal\\s*Code\\s*:\\s*(.+)\",\n        \"tech_country\": r\"Tech\\s*Country\\s*:\\s*(.+)\",\n        \"tech_phone\": r\"Tech\\s*Phone\\s*:\\s*(.+)\",\n        \"tech_email\": r\"Tech\\s*Email\\s*:\\s*(.+)\",\n        # NOTE: As of 6/2024, I don't see any domains that have billing fields for .ai\n        \"billing_name\": r\"Billing\\s*Name:\\s*(.+)\",\n        \"billing_org\": r\"Billing\\s*Organization:\\s*(.+)\",\n        \"billing_address\": r\"Billing\\s*Street:\\s*(.+)\",\n        \"billing_city\": r\"Billing\\s*City:\\s*(.+)\",\n        \"billing_state\": r\"Billing\\s*State.*:\\s*(.+)\",\n        \"billing_postal_code\": r\"Billing\\s*Postal Code\\s*:\\s*(.+)\",\n        \"billing_country\": r\"Billing\\s*Country\\.*:\\s*(.+)\",\n        \"billing_phone\": r\"Billing\\s*Phone\\.*:\\s*(.+)\",\n        \"billing_email\": r\"Billing\\s*Email\\.*:\\s*(.+)\",\n        \"name_servers\": r\"Name Server\\.*:\\s*(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not registered\" in text or text.startswith(\"Domain not found.\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIl(WhoisEntry):\n    \"\"\"Whois parser for .il domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"expiration_date\": r\"validity: *(.+)\",\n        \"creation_date\": r\"assigned: *(.+)\",\n        \"registrant_name\": r\"person: *(.+)\",\n        \"registrant_address\": r\"address *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"status\": r\"status: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"emails\": r\"e-mail: *(.+)\",\n        \"phone\": r\"phone: *(.+)\",\n        \"registrar\": r\"registrar name: *(.+)\",\n        \"referral_url\": r\"registrar info: *(.+)\",\n    }\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if \"No data was found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        if attr == \"emails\":\n            value = value.replace(\" AT \", \"@\")\n        return super(WhoisIl, self)._preprocess(attr, value)\n\n\nclass WhoisIn(WhoisEntry):\n    \"\"\"Whois parser for .in domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_iana\": r\"Registrar IANA ID: *(\\d+)\",\n        \"updated_date\": r\"Updated Date: *(.+)|Last Updated On: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)|Created On: *(.+)\",\n        \"expiration_date\": r\"Expiration Date: *(.+)|Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"organization\": r\"Registrant Organization: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"status\": r\"Status: *(.+)\",\n        \"emails\": EMAIL_REGEX,\n        \"country\": r\"Registrant Country: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *([\\S]+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"NOT FOUND\" in text or \"is available for registration\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCat(WhoisEntry):\n    \"\"\"Whois parser for .cat domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"status\": r\"Domain status: *(.+)\",\n        \"emails\": EMAIL_REGEX,\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"no matching objects\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            # Merge base class regex with specifics\n            self._regex.copy().update(self.regex)\n            self.regex = self._regex\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIe(WhoisEntry):\n    \"\"\"Whois parser for .ie domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"status\": r\"Domain status: *(.+)\",\n        \"admin_id\": r\"Registry Admin ID: *(.+)\",\n        \"tech_id\": r\"Registry Tech ID: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_contact\": r\"Registrar Abuse Contact Email: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"no matching objects\" in text or \"Not found: \" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisNz(WhoisEntry):\n    \"\"\"Whois parser for .nz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"(?:Domain Name|domain_name):\\s*([^\\n\\r]+)\",\n        \"registrar\": r\"(?:Registrar|registrar_name):\\s*([^\\n\\r]+)\",\n        \"registrar_url\": r\"Registrar URL:\\s*([^\\n\\r]+)\",\n        \"updated_date\": r\"(?:Updated Date|domain_datelastmodified):\\s*([^\\n\\r]+)\",\n        \"creation_date\": r\"(?:Creation Date|domain_dateregistered|created):\\s*([^\\n\\r]+)\",\n        \"expiration_date\": r\"domain_datebilleduntil:\\s*([^\\n\\r]+)\",\n        \"name_servers\": r\"(?:Name Server|ns_name_\\d*):\\s*([^\\n\\r]+)\",  # list of name servers\n        \"status\": r\"(?:Domain Status|status):\\s*([^\\n\\r]+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"name\": r\"registrant_contact_name:\\s*([^\\n\\r]+)\",\n        \"address\": r\"registrant_contact_address\\d*:\\s*([^\\n\\r]+)\",\n        \"city\": r\"registrant_contact_city:\\s*([^\\n\\r]+)\",\n        \"registrant_postal_code\": r\"registrant_contact_postalcode:\\s*([^\\n\\r]+)\",\n        \"country\": r\"registrant_contact_country:\\s*([^\\n\\r]+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"no matching objects\" in text or text.startswith('Not found'):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisLu(WhoisEntry):\n    \"\"\"Whois parser for .lu domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domainname: *(.+)\",\n        \"creation_date\": r\"registered: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"status\": r\"domaintype: *(.+)\",\n        \"registrar\": r\"registrar-name: *(.+)\",\n        \"registrant_name\": r\"org-name: *(.+)\",\n        \"registrant_address\": r\"org-address: *(.+)\",\n        \"registrant_postal_code\": r\"org-zipcode:*(.+)\",\n        \"registrant_city\": r\"org-city: *(.+)\",\n        \"registrant_country\": r\"org-country: *(.+)\",\n        \"admin_name\": r\"adm-name: *(.+)\",\n        \"admin_address\": r\"adm-address: *(.+)\",\n        \"admin_postal_code\": r\"adm-zipcode: *(.+)\",\n        \"admin_city\": r\"adm-city: *(.+)\",\n        \"admin_country\": r\"adm-country: *(.+)\",\n        \"admin_email\": r\"adm-email: *(.+)\",\n        \"tech_name\": r\"tec-name: *(.+)\",\n        \"tech_address\": r\"tec-address: *(.+)\",\n        \"tech_postal_code\": r\"tec-zipcode: *(.+)\",\n        \"tech_city\": r\"tec-city: *(.+)\",\n        \"tech_country\": r\"tec-country: *(.+)\",\n        \"tech_email\": r\"tec-email: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No such domain\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCz(WhoisEntry):\n    \"\"\"Whois parser for .cz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrant_name\": r\"registrant: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"creation_date\": r\"registered: *(.+)\",\n        \"updated_date\": r\"changed: *(.+)\",\n        \"expiration_date\": r\"expire: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"status\": r\"status: *(.+)\",\n    }\n\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if \"% No entries found.\" in text or \"Your connection limit exceeded\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisOnline(WhoisEntry):\n    \"\"\"Whois parser for .online domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Domain ID: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"billing_email\": r\"Billing Email: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *([\\S]+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Not found:\" in text or \"The queried object does not exist: DOMAIN NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisHr(WhoisEntry):\n    \"\"\"Whois parser for .hr domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registrar Registration Expiration Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n        \"registrant_name\": r\"Registrant Name:\\s(.+)\",\n        \"registrant_address\": r\"Reigstrant Street:\\s*(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"ERROR: No entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisHk(WhoisEntry):\n    \"\"\"Whois parser for .hk domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar\": r\"Registrar Name: *(.+)\",\n        \"registrar_email\": r\"Registrar Contact Information: Email: *(.+)\",\n        \"registrant_company_name\": r\"Registrant Contact Information:\\s*Company English Name.*:(.+)\",\n        \"registrant_address\": r\"(?<=Registrant Contact Information:)[\\s\\S]*?Address: (.*)\",\n        \"registrant_country\": r\"[Registrant Contact Information\\w\\W]+Country: ([\\S\\ ]+)\",\n        \"registrant_email\": r\"[Registrant Contact Information\\w\\W]+Email: ([\\S\\ ]+)\",\n        \"admin_name\": r\"[Administrative Contact Information\\w\\W]+Given name: ([\\S\\ ]+)\",\n        \"admin_family_name\": r\"[Administrative Contact Information\\w\\W]+Family name: ([\\S\\ ]+)\",\n        \"admin_company_name\": r\"[Administrative Contact Information\\w\\W]+Company name: ([\\S\\ ]+)\",\n        \"admin_address\": r\"(?<=Administrative Contact Information:)[\\s\\S]*?Address: (.*)\",\n        \"admin_country\": r\"[Administrative Contact Information\\w\\W]+Country: ([\\S\\ ]+)\",\n        \"admin_phone\": r\"[Administrative Contact Information\\w\\W]+Phone: ([\\S\\ ]+)\",\n        \"admin_fax\": r\"[Administrative Contact Information\\w\\W]+Fax: ([\\S\\ ]+)\",\n        \"admin_email\": r\"[Administrative Contact Information\\w\\W]+Email: ([\\S\\ ]+)\",\n        \"admin_account_name\": r\"[Administrative Contact Information\\w\\W]+Account Name: ([\\S\\ ]+)\",\n        \"tech_name\": r\"[Technical Contact Information\\w\\W]+Given name: (.+)\",\n        \"tech_family_name\": r\"[Technical Contact Information\\w\\W]+Family name: (.+)\",\n        \"tech_company_name\": r\"[Technical Contact Information\\w\\W]+Company name: (.+)\",\n        \"tech_address\": r\"(?<=Technical Contact Information:)[\\s\\S]*?Address: (.*)\",\n        \"tech_country\": r\"[Technical Contact Information\\w\\W]+Country: (.+)\",\n        \"tech_phone\": r\"[Technical Contact Information\\w\\W]+Phone: (.+)\",\n        \"tech_fax\": r\"[Technical Contact Information\\w\\W]+Fax: (.+)\",\n        \"tech_email\": r\"[Technical Contact Information\\w\\W]+Email: (.+)\",\n        \"tech_account_name\": r\"[Technical Contact Information\\w\\W]+Account Name: (.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"[Registrant Contact Information\\w\\W]+Domain Name Commencement Date: (.+)\",\n        \"expiration_date\": r\"[Registrant Contact Information\\w\\W]+Expiry Date: (.+)\",\n        \"name_servers\": r\"Name Servers Information:\\s+((?:.+\\n)*)\",\n    }\n    dayfirst = True\n\n    def __init__(self, domain: str, text: str):\n        if (\n            \"ERROR: No entries found\" in text\n            or \"The domain has not been registered\" in text\n        ):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisUA(WhoisEntry):\n    \"\"\"Whois parser for .ua domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"status\": r\"status: *(.+)\",\n        \"registrar\": r\"(?<=Registrar:)[\\s\\W\\w]*?organization-loc:(.*)\",\n        \"registrar_name\": r\"(?<=Registrar:)[\\s\\W\\w]*?registrar:(.*)\",\n        \"registrar_url\": r\"(?<=Registrar:)[\\s\\W\\w]*?url:(.*)\",\n        \"registrar_country\": r\"(?<=Registrar:)[\\s\\W\\w]*?country:(.*)\",\n        \"registrar_city\": r\"(?<=Registrar:)[\\s\\W\\w]*?city:\\s+(.*)\\n\",\n        \"registrar_address\": r\"(?<=Registrar:)[\\s\\W\\w]*?abuse-postal:\\s+(.*)\\n\",\n        \"registrar_email\": r\"(?<=Registrar:)[\\s\\W\\w]*?abuse-email:(.*)\",\n        \"registrant_name\": r\"(?<=Registrant:)[\\s\\W\\w]*?organization-loc:(.*)\",\n        \"registrant_country\": r\"(?<=Registrant:)[\\s\\W\\w]*?country-loc:(.*)\",\n        \"registrant_city\": r\"(?<=Registrant:)[\\s\\W\\w]*?(?:address\\-loc:\\s+.*\\n){2}address-loc:\\s+(.*)\\n\",\n        \"registrant_state\": r\"(?<=Registrant:)[\\s\\W\\w]*?(?:address\\-loc:\\s+.*\\n){1}address-loc:\\s+(.*)\\n\",\n        \"registrant_address\": r\"(?<=Registrant:)[\\s\\W\\w]*?address-loc:\\s+(.*)\\n\",\n        \"registrant_email\": r\"(?<=Registrant:)[\\s\\W\\w]*?e-mail:(.*)\",\n        \"registrant_postal_code\": r\"(?<=Registrant:)[\\s\\W\\w]*?postal-code-loc:(.*)\",\n        \"registrant_phone\": r\"(?<=Registrant:)[\\s\\W\\w]*?phone:(.*)\",\n        \"registrant_fax\": r\"(?<=Registrant:)[\\s\\W\\w]*?fax:(.*)\",\n        \"admin\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?organization-loc:(.*)\",\n        \"admin_country\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?country-loc:(.*)\",\n        \"admin_city\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?(?:address\\-loc:\\s+.*\\n){\"\n        r\"2}address-loc:\\s+(.*)\\n\",\n        \"admin_state\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?(?:address\\-loc:\\s+.*\\n){\"\n        r\"1}address-loc:\\s+(.*)\\n\",\n        \"admin_address\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?address-loc:\\s+(.*)\\n\",\n        \"admin_email\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?e-mail:(.*)\",\n        \"admin_postal_code\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?postal-code-loc:(.*)\",\n        \"admin_phone\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?phone:(.*)\",\n        \"admin_fax\": r\"(?<=Administrative Contacts:)[\\s\\W\\w]*?fax:(.*)\",\n        \"updated_date\": r\"modified: *(.+)\",\n        \"creation_date\": r\"created: (.+)\",\n        \"expiration_date\": r\"expires: (.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(\n                self,\n                domain,\n                text,\n                self.regex,\n                lambda x: re.sub(r\"([+-]\\d{2})(?!:)(?=\\d*$)\", r\"\\1:00\", x)\n                )\n\n\nclass WhoisUkr(WhoisEntry):\n    \"\"\"Whois parser for .укр domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name \\(UTF8\\): *(.+)\",\n        \"domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"status\": r\"Registry Status: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"registrant_name\": r\"Registrant Name \\(Organization\\): *(.+)\",\n        \"registrant_address\": r\"Registrant Street:(.+)\",\n        \"registrant_city\": r\"Registrant City:(.+)\",\n        \"registrant_country\": r\"Registrant Country:(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code:(.+)\",\n        \"registrant_phone\": r\"Registrant Phone:(.+)\",\n        \"registrant_fax\": r\"Registrant Fax:(.+)\",\n        \"registrant_email\": r\"Registrant Email:(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_address\": r\"Admin Street:(.+)\",\n        \"admin_city\": r\"Admin City:(.+)\",\n        \"admin_country\": r\"Admin Country:(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code:(.+)\",\n        \"admin_phone\": r\"Admin Phone:(.+)\",\n        \"admin_fax\": r\"Admin Fax:(.+)\",\n        \"admin_email\": r\"Admin Email:(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: (.+)\",\n        \"expiration_date\": r\"Expiration Date: (.+)\",\n        \"name_servers\": r\"Domain servers in listed order:\\s+((?:.+\\n)*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No match for domain\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        if attr == \"name_servers\":\n            return [line.strip() for line in value.split(\"\\n\") if line != \"\"]\n        return super(WhoisUkr, self)._preprocess(attr, value)\n\n\nclass WhoisPpUa(WhoisEntry):\n    \"\"\"Whois parser for .pp.ua domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Domain ID: *(.+)\",\n        \"status\": r\"status: *(.+)\",\n        \"registrar\": r\"Sponsoring Registrar: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_organization\": r\"Registrant Organization: *(.+)\",\n        \"registrant_address\": r\"Registrant Street1:(.+)\",\n        \"registrant_address2\": r\"Registrant Street2:(.+)\",\n        \"registrant_address3\": r\"Registrant Street3:(.+)\",\n        \"registrant_city\": r\"Registrant City:(.+)\",\n        \"registrant_country\": r\"Registrant Country:(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code:(.+)\",\n        \"registrant_phone\": r\"Registrant Phone:(.+)\",\n        \"registrant_fax\": r\"Registrant Fax:(.+)\",\n        \"registrant_email\": r\"Registrant Email:(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_address\": r\"Admin Street1:(.+)\",\n        \"admin_address2\": r\"Admin Street2:(.+)\",\n        \"admin_address3\": r\"Admin Street3:(.+)\",\n        \"admin_city\": r\"Admin City:(.+)\",\n        \"admin_country\": r\"Admin Country:(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code:(.+)\",\n        \"admin_phone\": r\"Admin Phone:(.+)\",\n        \"admin_fax\": r\"Admin Fax:(.+)\",\n        \"admin_email\": r\"Admin Email:(.+)\",\n        \"updated_date\": r\"Last Updated On: *(.+)\",\n        \"creation_date\": r\"Created On: (.+)\",\n        \"expiration_date\": r\"Expiration Date: (.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisHn(WhoisEntry):\n    \"\"\"Whois parser for .hn domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Domain ID: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"whois_server\": r\"WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: (.+)\",\n        \"registrant_id\": r\"Registrant ID: (.+)\",\n        \"registrant_organization\": r\"Registrant Organization: (.+)\",\n        \"registrant_city\": r\"Registrant City: (.*)\",\n        \"registrant_street\": r\"Registrant Street: (.*)\",\n        \"registrant_state_province\": r\"Registrant State/Province: (.*)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: (.*)\",\n        \"registrant_country\": r\"Registrant Country: (.+)\",\n        \"registrant_phone\": r\"Registrant Phone: (.+)\",\n        \"registrant_fax\": r\"Registrant Fax: (.+)\",\n        \"registrant_email\": r\"Registrant Email: (.+)\",\n        \"admin_name\": r\"Admin Name: (.+)\",\n        \"admin_id\": r\"Admin ID: (.+)\",\n        \"admin_organization\": r\"Admin Organization: (.+)\",\n        \"admin_city\": r\"Admin City: (.*)\",\n        \"admin_street\": r\"Admin Street: (.*)\",\n        \"admin_state_province\": r\"Admin State/Province: (.*)\",\n        \"admin_postal_code\": r\"Admin Postal Code: (.*)\",\n        \"admin_country\": r\"Admin Country: (.+)\",\n        \"admin_phone\": r\"Admin Phone: (.+)\",\n        \"admin_fax\": r\"Admin Fax: (.+)\",\n        \"admin_email\": r\"Admin Email: (.+)\",\n        \"billing_name\": r\"Billing Name: (.+)\",\n        \"billing_id\": r\"Billing ID: (.+)\",\n        \"billing_organization\": r\"Billing Organization: (.+)\",\n        \"billing_city\": r\"Billing City: (.*)\",\n        \"billing_street\": r\"Billing Street: (.*)\",\n        \"billing_state_province\": r\"Billing State/Province: (.*)\",\n        \"billing_postal_code\": r\"Billing Postal Code: (.*)\",\n        \"billing_country\": r\"Billing Country: (.+)\",\n        \"billing_phone\": r\"Billing Phone: (.+)\",\n        \"billing_fax\": r\"Billing Fax: (.+)\",\n        \"billing_email\": r\"Billing Email: (.+)\",\n        \"tech_name\": r\"Tech Name: (.+)\",\n        \"tech_id\": r\"Tech ID: (.+)\",\n        \"tech_organization\": r\"Tech Organization: (.+)\",\n        \"tech_city\": r\"Tech City: (.*)\",\n        \"tech_street\": r\"Tech Street: (.*)\",\n        \"tech_state_province\": r\"Tech State/Province: (.*)\",\n        \"tech_postal_code\": r\"Tech Postal Code: (.*)\",\n        \"tech_country\": r\"Tech Country: (.+)\",\n        \"tech_phone\": r\"Tech Phone: (.+)\",\n        \"tech_fax\": r\"Tech Fax: (.+)\",\n        \"tech_email\": r\"Tech Email: (.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No matching record.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisLat(WhoisEntry):\n    \"\"\"Whois parser for .lat domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: (.+)\",\n        \"registrant_id\": r\"Registry Registrant ID: (.+)\",\n        \"registrant_organization\": r\"Registrant Organization: (.+)\",\n        \"registrant_city\": r\"Registrant City: (.*)\",\n        \"registrant_street\": r\"Registrant Street: (.*)\",\n        \"registrant_state_province\": r\"Registrant State/Province: (.*)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: (.*)\",\n        \"registrant_country\": r\"Registrant Country: (.+)\",\n        \"registrant_phone\": r\"Registrant Phone: (.+)\",\n        \"registrant_fax\": r\"Registrant Fax: (.+)\",\n        \"registrant_email\": r\"Registrant Email: (.+)\",\n        \"admin_name\": r\"Admin Name: (.+)\",\n        \"admin_id\": r\"Registry Admin ID: (.+)\",\n        \"admin_organization\": r\"Admin Organization: (.+)\",\n        \"admin_city\": r\"Admin City: (.*)\",\n        \"admin_street\": r\"Admin Street: (.*)\",\n        \"admin_state_province\": r\"Admin State/Province: (.*)\",\n        \"admin_postal_code\": r\"Admin Postal Code: (.*)\",\n        \"admin_country\": r\"Admin Country: (.+)\",\n        \"admin_phone\": r\"Admin Phone: (.+)\",\n        \"admin_fax\": r\"Admin Fax: (.+)\",\n        \"admin_email\": r\"Admin Email: (.+)\",\n        \"tech_name\": r\"Tech Name: (.+)\",\n        \"tech_id\": r\"Registry Tech ID: (.+)\",\n        \"tech_organization\": r\"Tech Organization: (.+)\",\n        \"tech_city\": r\"Tech City: (.*)\",\n        \"tech_street\": r\"Tech Street: (.*)\",\n        \"tech_state_province\": r\"Tech State/Province: (.*)\",\n        \"tech_postal_code\": r\"Tech Postal Code: (.*)\",\n        \"tech_country\": r\"Tech Country: (.+)\",\n        \"tech_phone\": r\"Tech Phone: (.+)\",\n        \"tech_fax\": r\"Tech Fax: (.+)\",\n        \"tech_email\": r\"Tech Email: (.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No matching record.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCn(WhoisEntry):\n    \"\"\"Whois parser for .cn domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"creation_date\": r\"Registration Time: *(.+)\",\n        \"expiration_date\": r\"Expiration Time: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"dnssec\": r\"dnssec: *([\\S]+)\",\n        \"name\": r\"Registrant: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No matching record.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisApp(WhoisEntry):\n    \"\"\"Whois parser for .app domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"whois_server\": r\"Whois Server: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expir\\w+ Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"registrant_email\": r\"Registrant Email: *(.+)\",  # registrant email\n        \"registrant_phone\": r\"Registrant Phone: *(.+)\",  # registrant phone\n        \"dnssec\": r\"dnssec: *([\\S]+)\",\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"org\": r\"Registrant\\s*Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"Domain not found.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisMoney(WhoisEntry):\n    \"\"\"Whois parser for .money domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",\n        \"emails\": EMAIL_REGEX,  # list of emails\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"registrant_phone\": r\"Registrant Phone: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"org\": r\"Registrant Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"Domain not found.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisAr(WhoisEntry):\n    \"\"\"Whois parser for .ar domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"whois_server\": r\"whois: *(.+)\",\n        \"updated_date\": r\"changed: *(.+)\",\n        \"creation_date\": r\"registered: *(.+)\",\n        \"expiration_date\": r\"expire: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+) \\(.*\\)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",\n        \"emails\": EMAIL_REGEX,  # list of emails\n        \"name\": r\"name: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"El dominio no se encuentra registrado en NIC Argentina\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBy(WhoisEntry):\n    \"\"\"Whois parser for .by domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"updated_date\": r\"Update Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expiration Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",  # could not be found in sample, but might be correct\n        \"name\": r\"Person: *(.+)\",  # could not be found in sample, but might be correct\n        \"org\": r\"Org: *(.+)\",\n        \"registrant_country\": r\"Country: *(.+)\",\n        \"registrant_address\": r\"Address: *(.+)\",\n        \"registrant_phone\": r\"Phone: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"Object does not exist\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCr(WhoisEntry):\n    \"\"\"Whois parser for .cr domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrant_name\": r\"registrant: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"updated_date\": r\"changed: *(.+)\",\n        \"creation_date\": r\"registered: *(.+)\",\n        \"expiration_date\": r\"expire: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",  # list of name servers\n        \"status\": r\"status: *(.+)\",\n        \"contact\": r\"contact: *(.+)\",\n        \"name\": r\"name: *(.+)\",\n        \"org\": r\"org: *(.+)\",\n        \"address\": r\"address: *(.+)\",\n        \"phone\": r\"phone: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"El dominio no existe.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisVe(WhoisEntry):\n    \"\"\"Whois parser for .ve domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Nombre de Dominio: *(.+)\",\n        \"status\": r\"Estatus del dominio: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"updated_date\": r\"Ultima Actualización: *(.+)\",\n        \"creation_date\": r\"Fecha de Creación: *(.+)\",\n        \"expiration_date\": r\"Fecha de Vencimiento: *(.+)\",\n        \"name_servers\": r\"Nombres de Dominio:((?:\\s+- .*)*)\",\n        \"registrant_name\": r\"Titular:\\s*(?:.*\\n){1}\\s+(.*)\",\n        \"registrant_city\": r\"Titular:\\s*(?:.*\\n){3}\\s+([\\s\\w]*)\",\n        \"registrant_street\": r\"Titular:\\s*(?:.*\\n){2}\\s+(.*)\",\n        \"registrant_state_province\": r\"Titular:\\s*(?:.*\\n){3}\\s+.*?,(.*),\",\n        \"registrant_country\": r\"Titular:\\s*(?:.*\\n){3}\\s+.*, .+  (.*)\",\n        \"registrant_phone\": r\"Titular:\\s*(?:.*\\n){4}\\s+(\\+*\\d.+)\",\n        \"registrant_email\": r\"Titular:\\s*.*\\t(.*)\",\n        \"tech\": r\"Contacto Técnico:\\s*(?:.*\\n){1}\\s+(.*)\",\n        \"tech_city\": r\"Contacto Técnico:\\s*(?:.*\\n){3}\\s+([\\s\\w]*)\",\n        \"tech_street\": r\"Contacto Técnico:\\s*(?:.*\\n){2}\\s+(.*)\",\n        \"tech_state_province\": r\"Contacto Técnico:\\s*(?:.*\\n){3}\\s+.*?,(.*),\",\n        \"tech_country\": r\"Contacto Técnico:\\s*(?:.*\\n){3}\\s+.*, .+  (.*)\",\n        \"tech_phone\": r\"Contacto Técnico:\\s*(?:.*\\n){4}\\s+(\\+*\\d.*)\\(\",\n        \"tech_fax\": r\"Contacto Técnico:\\s*(?:.*\\n){4}\\s+.*\\(FAX\\) (.*)\",\n        \"tech_email\": r\"Contacto Técnico:\\s*.*\\t(.*)\",\n        \"admin\": r\"Contacto Administrativo:\\s*(?:.*\\n){1}\\s+(.*)\",\n        \"admin_city\": r\"Contacto Administrativo:\\s*(?:.*\\n){3}\\s+([\\s\\w]*)\",\n        \"admin_street\": r\"Contacto Administrativo:\\s*(?:.*\\n){2}\\s+(.*)\",\n        \"admin_state_province\": r\"Contacto Administrativo:\\s*(?:.*\\n){3}\\s+.*?,(.*),\",\n        \"admin_country\": r\"Contacto Administrativo:\\s*(?:.*\\n){3}\\s+.*, .+  (.*)\",\n        \"admin_phone\": r\"Contacto Administrativo:\\s*(?:.*\\n){4}\\s+(\\+*\\d.*)\\(\",\n        \"admin_fax\": r\"Contacto Administrativo:\\s*(?:.*\\n){4}\\s+.*\\(FAX\\) (.*)\",\n        \"admin_email\": r\"Contacto Administrativo:\\s*.*\\t(.*)\",\n        \"billing\": r\"Contacto de Cobranza:\\s*(?:.*\\n){1}\\s+(.*)\",\n        \"billing_city\": r\"Contacto de Cobranza:\\s*(?:.*\\n){3}\\s+([\\s\\w]*)\",\n        \"billing_street\": r\"Contacto de Cobranza:\\s*(?:.*\\n){2}\\s+(.*)\",\n        \"billing_state_province\": r\"Contacto de Cobranza:\\s*(?:.*\\n){3}\\s+.*?,(.*),\",\n        \"billing_country\": r\"Contacto de Cobranza:\\s*(?:.*\\n){3}\\s+.*, .+  (.*)\",\n        \"billing_phone\": r\"Contacto de Cobranza:\\s*(?:.*\\n){4}\\s+(\\+*\\d.*)\\(\",\n        \"billing_fax\": r\"Contacto de Cobranza:\\s*(?:.*\\n){4}\\s+.*\\(FAX\\) (.*)\",\n        \"billing_email\": r\"Contacto de Cobranza:\\s*.*\\t(.*)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"El dominio no existe.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisDo(WhoisEntry):\n    \"\"\"Whois parser for .do domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"whois_server\": r\"WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_email\": r\"Registrar Customer Service Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Phone: *(.+)\",\n        \"registrar_address\": r\"Registrar Address: *(.+)\",\n        \"registrar_country\": r\"Registrar Country: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"registrant_id\": r\"Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_organization\": r\"Registrant Organization: *(.+)\",\n        \"registrant_address\": r\"Registrant Street: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_phone_number\": r\"Registrant Phone: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"admin_id\": r\"Admin ID: *(.+)\",\n        \"admin_name\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_address\": r\"Admin Street: *(.+)\",\n        \"admin_city\": r\"Admin City: *(.+)\",\n        \"admin_state_province\": r\"Admin State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code: *(.+)\",\n        \"admin_country\": r\"Admin Country: *(.+)\",\n        \"admin_phone_number\": r\"Admin Phone: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"billing_id\": r\"Billing ID: *(.+)\",\n        \"billing_name\": r\"Billing Name: *(.+)\",\n        \"billing_address\": r\"Billing Street: *(.+)\",\n        \"billing_city\": r\"Billing City: *(.+)\",\n        \"billing_state_province\": r\"Billing State/Province: *(.+)\",\n        \"billing_postal_code\": r\"Billing Postal Code: *(.+)\",\n        \"billing_country\": r\"Billing Country: *(.+)\",\n        \"billing_phone_number\": r\"Billing Phone: *(.+)\",\n        \"billing_email\": r\"Billing Email: *(.+)\",\n        \"tech_id\": r\"Tech ID: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_organization\": r\"Tech Organization: *(.+)\",\n        \"tech_address\": r\"Tech Street: *(.+)\",\n        \"tech_city\": r\"Tech City: *(.+)\",\n        \"tech_state_province\": r\"Tech State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code: *(.+)\",\n        \"tech_country\": r\"Tech Country: *(.+)\",\n        \"tech_phone_number\": r\"Tech Phone: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"Extensión de dominio no válido.\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisAe(WhoisEntry):\n    \"\"\"Whois parser for .ae domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"status\": r\"Status: *(.+)\",\n        \"registrant_name\": r\"Registrant Contact Name: *(.+)\",\n        \"tech_name\": r\"Tech Contact Name: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No Data Found\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSi(WhoisEntry):\n    \"\"\"Whois parser for .si domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrar\": r\"registrar: *(.+)\",\n        \"name_servers\": r\"nameserver: *(.+)\",\n        \"registrant_name\": r\"registrant: *(.+)\",\n        \"creation_date\": r\"created: *(.+)\",\n        \"expiration_date\": r\"expire: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found for the selected source(s).\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisNo(WhoisEntry):\n    \"\"\"Whois parser for .no domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name.*:\\s*(.+)\",\n        \"creation_date\": r\"Additional information:\\nCreated:\\s*(.+)\",\n        \"updated_date\": r\"Additional information:\\n(?:.*\\n)Last updated:\\s*(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No match\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisKZ(WhoisEntry):\n    \"\"\"Whois parser for .kz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name............: *(.+)\",\n        \"registrar_created\": r\"Registr?ar Created: *(.+)\",\n        \"registrar\": r\"Current Registr?ar: *(.+)\",\n        \"creation_date\": r\"Domain created: *(.+)\",\n        \"updated_date\": r\"Last modified : *(.+)\",\n        \"name_servers\": r\"server.*: *(.+)\",  # list of name servers\n        \"status\": r\" (.+?) -\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email addresses\n        \"org\": r\"Organization Name.*: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"*** Nothing found for this query.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisIR(WhoisEntry):\n    \"\"\"Whois parser for .ir domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"registrant_name\": r\"person: *(.+)\",\n        \"registrant_organization\": r\"org: *(.+)\",\n        \"updated_date\": r\"last-updated: *(.+)\",\n        \"expiration_date\": r\"expire-date: *(.+)\",\n        \"name_servers\": r\"nserver: *(.+)\",  # list of name servers\n        \"emails\": EMAIL_REGEX,\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisLife(WhoisEntry):\n    \"\"\"Whois parser for .ir domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name:: *(.+)\",\n        \"registrant_name\": r\"Registrar: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"emails\": EMAIL_REGEX,\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Domain not found.\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisZhongGuo(WhoisEntry):\n    \"\"\"Whois parser for .中国 domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"creation_date\": r\"Registration Time: *(.+)\",\n        \"registrant_name\": r\"Registrant: *(.+)\",\n        \"registrar\": r\"Sponsoring Registrar: *(.+)\",\n        \"expiration_date\": r\"Expiration Time: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"emails\": EMAIL_REGEX,\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisWebsite(WhoisEntry):\n    \"\"\"Whois parser for .website domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text)\n\n\nclass WhoisML(WhoisEntry):\n    \"\"\"Whois parser for .ml domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name:\\s*([^(i|\\n)]+)\",\n        \"registrar\": r\"Organization: *(.+)\",\n        \"creation_date\": r\"Domain registered: *(.+)\",\n        \"expiration_date\": r\"Record will expire on: *(.+)\",\n        \"name_servers\": r\"Domain Nameservers:\\s+((?:.+\\n)*)\",\n        \"emails\": EMAIL_REGEX,\n    }\n\n    def __init__(self, domain: str, text: str):\n        if (\n            \"Invalid query or domain name not known in the Point ML Domain Registry\"\n            in text\n        ):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n    def _preprocess(self, attr, value):\n        if attr == \"name_servers\":\n            return [line.strip() for line in value.split(\"\\n\") if line != \"\"]\n        return super(WhoisML, self)._preprocess(attr, value)\n\n\nclass WhoisOoo(WhoisEntry):\n    \"\"\"Whois parser for .ooo domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found for the selected source(s).\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisMarket(WhoisEntry):\n    \"\"\"Whois parser for .market domains\"\"\"\n\n    def __init__(self, domain: str, text: str):\n        if \"No entries found for the selected source(s).\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisZa(WhoisEntry):\n    \"\"\"Whois parser for .za domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"domain__id\": r\"Domain ID: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\",\n        \"registrant_id\": r\"Registry Registrant ID: *(.+)\",\n        \"registrant_name\": r\"Registrant Name: *(.+)\",\n        \"registrant_organization\": r\"Registrant Organization: *(.+)\",\n        \"registrant_street\": r\"Registrant Street: *(.+)\",\n        \"registrant_city\": r\"Registrant City: *(.+)\",\n        \"registrant_state_province\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"registrant_country\": r\"Registrant Country: *(.+)\",\n        \"registrant_phone\": r\"Registrant Phone: *(.+)\",\n        \"registrant_email\": r\"Registrant Email: *(.+)\",\n        \"registrant_fax\": r\"Registrant Fax: *(.+)\",\n        \"admin_id\": r\"Registry Admin ID: *(.+)\",\n        \"admin\": r\"Admin Name: *(.+)\",\n        \"admin_organization\": r\"Admin Organization: *(.+)\",\n        \"admin_street\": r\"Admin Street: *(.+)\",\n        \"admin_city\": r\"Admin City: *(.+)\",\n        \"admin_state_province\": r\"Admin State/Province: *(.+)\",\n        \"admin_postal_code\": r\"Admin Postal Code: *(.+)\",\n        \"admin_country\": r\"Admin Country: *(.+)\",\n        \"admin_phone\": r\"Admin Phone: *(.+)\",\n        \"admin_phone_ext\": r\"Admin Phone Ext: *(.+)\",\n        \"admin_email\": r\"Admin Email: *(.+)\",\n        \"admin_fax\": r\"Admin Fax: *(.+)\",\n        \"admin_fax_ext\": r\"Admin Fax Ext: *(.+)\",\n        \"admin_application_purpose\": r\"Admin Application Purpose: *(.+)\",\n        \"billing_name\": r\"Billing Name: *(.+)\",\n        \"billing_organization\": r\"Billing Organization: *(.+)\",\n        \"billing_street\": r\"Billing Street: *(.+)\",\n        \"billing_city\": r\"Billing City: *(.+)\",\n        \"billing_state_province\": r\"Billing State/Province: *(.+)\",\n        \"billing_postal_code\": r\"Billing Postal Code: *(.+)\",\n        \"billing_country\": r\"Billing Country: *(.+)\",\n        \"billing_phone\": r\"Billing Phone: *(.+)\",\n        \"billing_phone_ext\": r\"Billing Phone Ext: *(.+)\",\n        \"billing_fax\": r\"Billing Fax: *(.+)\",\n        \"billing_fax_ext\": r\"Billing Fax Ext: *(.+)\",\n        \"billing_email\": r\"Billing Email: *(.+)\",\n        \"tech_id\": r\"Registry Tech ID: *(.+)\",\n        \"tech_name\": r\"Tech Name: *(.+)\",\n        \"tech_organization\": r\"Tech Organization: *(.+)\",\n        \"tech_street\": r\"Tech Street: *(.+)\",\n        \"tech_city\": r\"Tech City: *(.+)\",\n        \"tech_state_province\": r\"Tech State/Province: *(.+)\",\n        \"tech_postal_code\": r\"Tech Postal Code: *(.+)\",\n        \"tech_country\": r\"Tech Country: *(.+)\",\n        \"tech_phone\": r\"Tech Phone: *(.+)\",\n        \"tech_email\": r\"Tech Email: *(.+)\",\n        \"tech_fax\": r\"Tech Fax: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.startswith(\"Available\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisGg(WhoisEntry):\n    \"\"\"Whois parser for .gg domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain:\\n +(.+)\",\n        \"registrar\": r\"Registrar:\\n\\s+(.+)\",\n        \"creation_date\": r\"Relevant dates:\\n\\s+Registered on (.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisBw(WhoisEntry):\n    \"\"\"Whois parser for .bw domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name\\.*: *(.+)\",\n        \"domain_id\": r\"Registry Domain ID\\.*: *(.+)\",\n        \"creation_date\": r\"Creation Date: (.+)\",\n        \"registrar\": r\"Registrar: (.+)\",\n        \"registrant_name\": r\"RegistrantName: *(.+)\",\n        \"registrant_org\": r\"RegistrantOrganization: (.+)\",\n        \"registrant_address\": r\"RegistrantStreet: *(.+)\",\n        \"registrant_city\": r\"RegistrantCity: *(.+)\",\n        \"registrant_country\": r\"RegistrantCountry\\.*: *(.+)\",\n        \"registrant_phone\": r\"RegistrantPhone\\.*: *(.+)\",\n        \"registrant_email\": r\"RegistrantEmail\\.*: *(.+)\",\n        \"admin_name\": r\"AdminName: *(.+)\",\n        \"admin_org\": r\"AdminOrganization: (.+)\",\n        \"admin_address\": r\"AdminStreet: *(.+)\",\n        \"admin_city\": r\"AdminCity: *(.+)\",\n        \"admin_country\": r\"AdminCountry\\.*: *(.+)\",\n        \"admin_phone\": r\"AdminPhone\\.*: *(.+)\",\n        \"admin_email\": r\"AdminEmail\\.*: *(.+)\",\n        \"tech_name\": r\"TechName: *(.+)\",\n        \"tech_org\": r\"TechOrganization: (.+)\",\n        \"tech_address\": r\"TechStreet: *(.+)\",\n        \"tech_city\": r\"TechCity: *(.+)\",\n        \"tech_country\": r\"TechCountry\\.*: *(.+)\",\n        \"tech_phone\": r\"TechPhone\\.*: *(.+)\",\n        \"tech_email\": r\"TechEmail\\.*: *(.+)\",\n        \"billing_name\": r\"BillingName: *(.+)\",\n        \"billing_org\": r\"BillingOrganization: (.+)\",\n        \"billing_address\": r\"BillingStreet: *(.+)\",\n        \"billing_city\": r\"BillingCity: *(.+)\",\n        \"billing_country\": r\"BillingCountry\\.*: *(.+)\",\n        \"billing_phone\": r\"BillingPhone\\.*: *(.+)\",\n        \"billing_email\": r\"BillingEmail\\.*: *(.+)\",\n        \"name_servers\": r\"Name Server\\.*: *(.+)\",\n        \"dnssec\": r\"dnssec\\.*: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"not registered\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisTN(WhoisEntry):\n    \"\"\"Whois parser for .tn domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain name.*: (.+)\",\n        \"registrar\": r\"Registrar.*: (.+)\",\n        \"creation_date\": r\"Creation date.*: (.+)\",\n        \"status\": r\"Domain status.*: (.+)\",\n        \"registrant_name\": r\"(?:Owner Contact\\nName.*: )(.+)\",\n        \"registrant_address\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*: )(.+)\",\n        \"registrant_address2\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_city\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_state\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"aregistrant_zip\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_country\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_phone\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_fax\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"registrant_email\": r\"(?:Owner Contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*:)(.+)\",\n        \"admin_name\": r\"(?:Administrativ contact\\nName.*: )(.+)\",\n        \"admin_first_name\": r\"(?:Administrativ contact\\n.*:.*\\n.*: )(.+)\",\n        \"admin_address\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*: )(.+)\",\n        \"admin_address2\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_city\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_state\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_zip\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_country\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_phone\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_fax\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"admin_email\": r\"(?:Administrativ contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*:)(.+)\",\n        \"tech_name\": r\"(?:Technical contact\\nName.*: )(.+)\",\n        \"tech_first_name\": r\"(?:Technical contact\\n.*:.*\\n.*: )(.+)\",\n        \"tech_address\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*: )(.+)\",\n        \"tech_address2\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_city\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_state\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_zip\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_country\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_phone\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_fax\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*: )(.+)\",\n        \"tech_email\": r\"(?:Technical contact\\n.*:.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*:)(.+)\",\n        \"name_servers\": r\"(?:servers\\nName.*:) (.+)(?:\\nName.*:) (.+)\",  # list of name servers\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.startswith(\"Available\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisSite(WhoisEntry):\n    \"\"\"Whois parser for .site domains\"\"\"\n\n    _regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"whois_server\": r\"Whois Server: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"dnssec\": r\"DNSSEC: *([\\S]+)\",\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"org\": r\"Registrant\\s*Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"DOMAIN NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisDesign(WhoisEntry):\n    \"\"\"Whois parser for .design domains\"\"\"\n\n    _regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registrar\": r\"Registrar URL: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Domain Status: *(.+)\",  # list of statuses\n        \"emails\": EMAIL_REGEX,  # list of email s\n        \"dnssec\": r\"DNSSEC: *([\\S]+)\",\n        \"name\": r\"Registrant Name: *(.+)\",\n        \"phone\": r\"Registrant Phone: *(.+)\",\n        \"org\": r\"Registrant\\s*Organization: *(.+)\",\n        \"address\": r\"Registrant Street: *(.+)\",\n        \"city\": r\"Registrant City: *(.+)\",\n        \"state\": r\"Registrant State/Province: *(.+)\",\n        \"registrant_postal_code\": r\"Registrant Postal Code: *(.+)\",\n        \"country\": r\"Registrant Country: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"No Data Found\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisEdu(WhoisEntry):\n    \"\"\"Whois parser for .edu domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": \"Domain name: *(.+)\",\n        \"creation_date\": \"Domain record activated: *(.+)\",\n        \"updated_date\": \"Domain record last updated: *(.+)\",\n        \"expiration_date\": \"Domain expires: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip() == \"No entries found\":\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisLv(WhoisEntry):\n    \"\"\"Whois parser for .lv domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"\\[Domain\\]\\nDomain: *(.+)\",\n        \"registrant_name\": r\"\\[Holder\\]\\s*Type:\\s*.*?\\s*Country:\\s*.*?\\s*Name:\\s*(.+)\",        \n        \"registrant_address\": r\"\\[Holder\\]\\s*Type:\\s*.*?\\s*Country:\\s*.*?\\s*Name:\\s*.*?\\s*Address:\\s*(.+)\",\n        \"tech_name\": r\"\\[Tech\\]\\n\\s+Type:\\s*.*?\\s*Country:\\s*.*?\\s*Name:\\s*(.+)\",\n        \"tech_address\": r\"\\[Tech\\]\\s*Type:\\s*.*?\\s*Country:\\s*.*?\\s*Name: .*\\n\\s+Address: *(.+)\",\n        \"registrar_name\": r\"\\[Registrar\\]\\s*Type: .*\\s*Name: *(.+)\",\n        \"registrar_address\": r\"\\[Registrar\\]\\s*Type: .*\\s*Name: .*\\s*Address: *(.+)\",\n        \"name_servers\": r\"Nserver: *(.+)\",\n        \"updated_date\": r\"\\[Whois\\]\\nUpdated: (.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"Status: free\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisGa(WhoisEntry):\n    \"\"\"Whois parser for .ga domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Nom de domaine: *(.+)\",\n        \"registrant_name\": r\"\\[HOLDER\\]\\r\\nID Contact:.+\\r\\nType:.+\\r\\nNom:\\s+(.*)\",\n        \"registrant_address\": r\"\\[HOLDER\\]\\r\\nID Contact:.+\\r\\nType:.+\\r\\nNom:\\s+.*\\r\\nAdresse:\\s+(.*)\",\n        \"tech_name\": r\"\\[TECH_C\\]\\r\\nID Contact:.+\\r\\nType:.+\\r\\nNom:\\s+(.*)\",\n        \"tech_address\": r\"\\[TECH_C\\]\\r\\nID Contact:.+\\r\\nType:.+\\r\\nNom:\\s+.*\\r\\nAdresse:\\s+(.*)\",\n        \"registrar_name\": r\"Registrar: +(.+)\",\n        \"name_servers\": r\"Serveur de noms: +(.+)\",\n        \"creation_date\": r\"Date de création: +(.+)\",\n        \"updated_date\": r\"Dernière modification: +(.+)\",\n        \"expiration_date\": r\"Date d'expiration: +(.+)\"\n    }\n\n    def __init__(self, domain: str, text: str):\n        if \"%% NOT FOUND\" in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCo(WhoisEntry):\n    \"\"\"Whois parser for .co domains\"\"\"\n\n    def __init__(self, domain, text):\n        if \"No Data Found\" in text or 'The queried object does not exist: DOMAIN NOT FOUND' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisCm(WhoisEntry):\n    \"\"\"Whois parser for .cm domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registry_domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"reseller\": r\"Reseller: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Expir\\w+ Date: *(.+)\",\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"status\": r\"Status: *(.+)\",  # list of statuses\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'No match for \"' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisHu(WhoisEntry):\n    \"\"\"Whois parser for .hu domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"domain: *(.+)\",\n        \"creation_date\": r\"record created: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if text.strip().endswith(\"No match\"):\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\nclass WhoisXyz(WhoisEntry):\n    \"\"\"Whois parser for .xyz domains\"\"\"\n\n    regex: dict[str, str] = {\n        \"domain_name\": r\"Domain Name: *(.+)\",\n        \"registry_domain_id\": r\"Registry Domain ID: *(.+)\",\n        \"whois_server\": r\"Registrar WHOIS Server: *(.+)\",\n        \"registrar_url\": r\"Registrar URL: *(.+)\",\n        \"updated_date\": r\"Updated Date: *(.+)\",\n        \"creation_date\": r\"Creation Date: *(.+)\",\n        \"expiration_date\": r\"Registry Expiry Date: *(.+)\",\n        \"registrar\": r\"Registrar: *(.+)\",\n        \"registrar_id\": r\"Registrar IANA ID: *(.+)\",\n        \"status\": r\"Domain Status: *(.+)\", # list of statuses\n        \"name_servers\": r\"Name Server: *(.+)\",  # list of name servers\n        \"dnssec\": r\"DNSSEC: *(.+)\",\n        \"registrar_email\": r\"Registrar Abuse Contact Email: *(.+)\",\n        \"registrar_phone\": r\"Registrar Abuse Contact Phone: *(.+)\",\n    }\n\n    def __init__(self, domain: str, text: str):\n        if 'The queried object does not exist: DOMAIN NOT FOUND' in text:\n            raise WhoisDomainNotFoundError(text)\n        else:\n            WhoisEntry.__init__(self, domain, text, self.regex)\n\n\n"
  },
  {
    "path": "whois/time_zones.py",
    "content": "_tz_string = \"\"\"-12 Y\n-11 X NUT SST\n-10 W CKT HAST HST TAHT TKT\n-9 V AKST GAMT GIT HADT HNY\n-8 U AKDT CIST HAY HNP PST PT\n-7 T HAP HNR MST PDT\n-6 S CST EAST GALT HAR HNC MDT\n-5 R CDT COT EASST ECT EST ET HAC HNE PET\n-4 Q AST BOT CLT COST EDT FKT GYT HAE HNA PYT\n-3 P ADT ART BRT CLST FKST GFT HAA PMST PYST SRT UYT WGT\n-2 O BRST FNT PMDT UYST WGST\n-1 N AZOT CVT EGT\n0 Z EGST GMT UTC WET WT\n1 A CET DFT WAT WEDT WEST\n2 B CAT CEDT CEST EET SAST WAST\n3 C EAT EEDT EEST IDT MSK\n4 D AMT AZT GET GST KUYT MSD MUT RET SAMT SCT\n5 E AMST AQTT AZST HMT MAWT MVT PKT TFT TJT TMT UZT YEKT\n6 F ALMT BIOT BTT IOT KGT NOVT OMST YEKST\n7 G CXT DAVT HOVT ICT KRAT NOVST OMSST THA WIB\n8 H ACT AWST BDT BNT CAST HKT IRKT KRAST MYT PHT SGT ULAT WITA WST\n9 I AWDT IRKST JST KST PWT TLT WDT WIT YAKT\n10 K AEST ChST PGT VLAT YAKST YAPT\n11 L AEDT LHDT MAGT NCT PONT SBT VLAST VUT\n12 M ANAST ANAT FJT GILT MAGST MHT NZST PETST PETT TVT WFT\n13 FJST NZDT\n11.5 NFT\n10.5 ACDT LHST\n9.5 ACST\n6.5 CCT MMT\n5.75 NPT\n5.5 SLT\n4.5 AFT IRDT\n3.5 IRST\n-2.5 HAT NDT\n-3.5 HNT NST NT\n-4.5 HLV VET\n-9.5 MART MIT\"\"\"\n\ntz_data = {}\n\nfor tz_descr in (tz_spec.split() for tz_spec in _tz_string.split(\"\\n\")):\n    tz_offset = int(float(tz_descr[0]) * 3600)\n    for tz_code in tz_descr[1:]:\n        tz_data[tz_code] = tz_offset\n"
  },
  {
    "path": "whois/whois.py",
    "content": "# -*- coding: utf-8 -*-\n\n\"\"\"\nWhois client for python\n\ntransliteration of:\nhttp://www.opensource.apple.com/source/adv_cmds/adv_cmds-138.1/whois/whois.c\n\nCopyright (c) 2010 Chris Wolf\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\"\"\"\nfrom __future__ import annotations\nimport logging\nimport optparse\nimport os\nimport re\nimport socket\nimport sys\nfrom typing import Optional, Pattern\n\nlogger = logging.getLogger(__name__)\n\n\nclass NICClient:\n    ABUSEHOST = \"whois.abuse.net\"\n    AI_HOST = \"whois.nic.ai\"\n    ANICHOST = \"whois.arin.net\"\n    APP_HOST = \"whois.nic.google\"\n    AR_HOST = \"whois.nic.ar\"\n    BNICHOST = \"whois.registro.br\"\n    BW_HOST = \"whois.nic.net.bw\"\n    BY_HOST = \"whois.cctld.by\"\n    CA_HOST = \"whois.ca.fury.ca\"\n    CHAT_HOST = \"whois.nic.chat\"\n    CL_HOST = \"whois.nic.cl\"\n    CM_HOST = \"whois.netcom.cm\"\n    CR_HOST = \"whois.nic.cr\"\n    DEFAULT_PORT = \"nicname\"\n    DENICHOST = \"whois.denic.de\"\n    DEV_HOST = \"whois.nic.google\"\n    DE_HOST = \"whois.denic.de\"\n    DK_HOST = \"whois.dk-hostmaster.dk\"\n    DNICHOST = \"whois.nic.mil\"\n    DO_HOST = \"whois.nic.do\"\n    GAMES_HOST = \"whois.nic.games\"\n    GNICHOST = \"whois.nic.gov\"\n    GOOGLE_HOST = \"whois.nic.google\"\n    GROUP_HOST = \"whois.namecheap.com\"\n    HK_HOST = \"whois.hkirc.hk\"\n    HN_HOST = \"whois.nic.hn\"\n    HR_HOST = \"whois.dns.hr\"\n    IANAHOST = \"whois.iana.org\"\n    INICHOST = \"whois.networksolutions.com\"\n    IST_HOST = \"whois.afilias-srs.net\"\n    JOBS_HOST = \"whois.nic.jobs\"\n    JP_HOST = \"whois.jprs.jp\"\n    KZ_HOST = \"whois.nic.kz\"\n    LAT_HOST = \"whois.nic.lat\"\n    LI_HOST = \"whois.nic.li\"\n    LIVE_HOST = \"whois.nic.live\"\n    LNICHOST = \"whois.lacnic.net\"\n    LT_HOST = \"whois.domreg.lt\"\n    MARKET_HOST = \"whois.nic.market\"\n    MNICHOST = \"whois.ra.net\"\n    MONEY_HOST = \"whois.nic.money\"\n    MX_HOST = \"whois.mx\"\n    NICHOST = \"whois.crsnic.net\"\n    NL_HOST = \"whois.domain-registry.nl\"\n    NORIDHOST = \"whois.norid.no\"\n    ONLINE_HOST = \"whois.nic.online\"\n    OOO_HOST = \"whois.nic.ooo\"\n    PAGE_HOST = \"whois.nic.page\"\n    PANDIHOST = \"whois.pandi.or.id\"\n    PE_HOST = \"kero.yachay.pe\"\n    PNICHOST = \"whois.apnic.net\"\n    QNICHOST_TAIL = \".whois-servers.net\"\n    QNICHOST_HEAD = \"whois.nic.\"\n    RNICHOST = \"whois.ripe.net\"\n    SNICHOST = \"whois.6bone.net\"\n    WEBSITE_HOST = \"whois.nic.website\"\n    ZA_HOST = \"whois.registry.net.za\"\n    RU_HOST = \"whois.tcinet.ru\"\n    IDS_HOST = \"whois.identitydigital.services\"\n    GDD_HOST = \"whois.dnrs.godaddy\"\n    SHOP_HOST = \"whois.nic.shop\"\n    SG_HOST = \"whois.sgnic.sg\"\n    STORE_HOST = \"whois.centralnic.com\"\n    STUDIO_HOST = \"whois.nic.studio\"\n    DETI_HOST = \"whois.nic.xn--d1acj3b\"\n    MOSKVA_HOST = \"whois.registry.nic.xn--80adxhks\"\n    RF_HOST = \"whois.registry.tcinet.ru\"\n    PIR_HOST = \"whois.publicinterestregistry.org\"\n    NG_HOST = \"whois.nic.net.ng\"\n    PPUA_HOST = \"whois.pp.ua\"\n    UKR_HOST = \"whois.dotukr.com\"\n    TN_HOST = \"whois.ati.tn\"\n    SBS_HOST = \"whois.nic.sbs\"\n    GA_HOST = \"whois.nic.ga\"\n    XYZ_HOST = \"whois.nic.xyz\"\n\n    SITE_HOST = \"whois.nic.site\"\n    DESIGN_HOST = \"whois.nic.design\"\n\n    WHOIS_RECURSE = 0x01\n    WHOIS_QUICK = 0x02\n\n    ip_whois: list[str] = [LNICHOST, RNICHOST, PNICHOST, BNICHOST, PANDIHOST]\n\n    def __init__(self, prefer_ipv6: bool = False):\n        self.use_qnichost: bool = False\n        self.prefer_ipv6 = prefer_ipv6\n\n    @staticmethod\n    def findwhois_server(buf: str, hostname: str, query: str) -> Optional[str]:\n        \"\"\"Search the initial TLD lookup results for the regional-specific\n        whois server for getting contact details.\n        \"\"\"\n        nhost = None\n        match = re.compile(\n            r\"Domain Name: {}\\s*.*?Whois Server: (.*?)\\s\".format(query),\n            flags=re.IGNORECASE | re.DOTALL,\n        ).search(buf)\n        if match:\n            nhost = match.group(1)\n            # if the whois address is domain.tld/something then\n            # s.connect((hostname, 43)) does not work\n            if nhost.count(\"/\") > 0:\n                nhost = None\n        elif hostname == NICClient.ANICHOST:\n            for nichost in NICClient.ip_whois:\n                if buf.find(nichost) != -1:\n                    nhost = nichost\n                    break\n        return nhost\n\n    @staticmethod\n    def get_socks_socket():\n        try:\n            import socks\n        except ImportError as e:\n            logger.error(\n                \"You need to install the Python socks module. Install PIP \"\n                \"(https://bootstrap.pypa.io/get-pip.py) and then 'pip install PySocks'\"\n            )\n            raise e\n        socks_user, socks_password = None, None\n        if \"@\" in os.environ[\"SOCKS\"]:\n            creds, proxy = os.environ[\"SOCKS\"].split(\"@\")\n            socks_user, socks_password = creds.split(\":\")\n        else:\n            proxy = os.environ[\"SOCKS\"]\n        socksproxy, port = proxy.split(\":\")\n        socks_proto = socket.AF_INET\n        if socket.AF_INET6 in [\n            sock[0] for sock in socket.getaddrinfo(socksproxy, port)\n        ]:\n            socks_proto = socket.AF_INET6\n        s = socks.socksocket(socks_proto)\n        s.set_proxy(\n            socks.SOCKS5, socksproxy, int(port), True, socks_user, socks_password\n        )\n        return s\n\n    def _connect(self, hostname: str, timeout: int) -> socket.socket:\n        \"\"\"Resolve WHOIS IP address and connect to its TCP 43 port.\"\"\"\n        port = 43\n\n        if \"SOCKS\" in os.environ:\n            s = NICClient.get_socks_socket()\n            s.settimeout(timeout)\n            s.connect((hostname, port))\n            return s\n\n        # Resolve all IP addresses for the WHOIS server\n        addr_infos = socket.getaddrinfo(hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM)\n\n        if self.prefer_ipv6:\n            # Sort by family to prioritize AF_INET6 (10) over AF_INET (2)\n            addr_infos.sort(key=lambda x: x[0], reverse=True)\n\n        last_err = None\n        # Attempt to connect to each related IP address until one works\n        for family, sock_type, proto, __, sockaddr in addr_infos:\n            s = None\n            try:\n                s = socket.socket(family, sock_type, proto)\n                s.settimeout(timeout)\n                s.connect(sockaddr)\n                return s\n            except socket.error as e:\n                last_err = e\n                if s:\n                    s.close()\n                continue\n\n        raise last_err or socket.error(f\"Could not connect to {hostname}\")\n\n    def findwhois_iana(self, tld: str, timeout: int = 10) -> Optional[str]:\n        s = self._connect(\"whois.iana.org\", timeout)\n        s.send(bytes(tld, \"utf-8\") + b\"\\r\\n\")\n        response = b\"\"\n        while True:\n            d = s.recv(4096)\n            response += d\n            if not d:\n                break\n        s.close()\n        match = re.search(r\"whois:[ \\t]+(.*?)\\n\", response.decode(\"utf-8\"))\n        if match and match.group(1):\n            return match.group(1)\n        else:\n            return None\n\n    def whois(\n        self,\n        query: str,\n        hostname: str,\n        flags: int,\n        many_results: bool = False,\n        quiet: bool = False,\n        timeout: int = 10,\n        ignore_socket_errors: bool = True\n    ) -> str:\n        \"\"\"Perform initial lookup with TLD whois server\n        then, if the quick flag is false, search that result\n        for the region-specific whois server and do a lookup\n        there for contact details.  If `quiet` is `True`, will\n        not send a message to logger when a socket error\n        is encountered. Uses `timeout` as a number of seconds\n        to set as a timeout on the socket. If `ignore_socket_errors`\n        is `False`, will raise an exception instead of returning\n        a string containing the error.\n        \"\"\"\n        response = b\"\"\n        s = None\n        try:  # socket.connect in a try, in order to allow things like looping whois on different domains without\n            # stopping on timeouts: https://stackoverflow.com/questions/25447803/python-socket-connection-exception\n            s = self._connect(hostname, timeout)\n            if hostname == NICClient.DENICHOST:\n                query_bytes = \"-T dn,ace -C UTF-8 \" + query\n            elif hostname == NICClient.DK_HOST:\n                query_bytes = \" --show-handles \" + query\n            elif hostname.endswith(\".jp\"):\n                query_bytes = query + \"/e\"\n            elif hostname.endswith(NICClient.QNICHOST_TAIL) and many_results:\n                query_bytes = \"=\" + query\n            else:\n                query_bytes = query\n            s.send(bytes(query_bytes, \"utf-8\") + b\"\\r\\n\")\n            # recv returns bytes\n            while True:\n                d = s.recv(4096)\n                response += d\n                if not d:\n                    break\n\n            nhost = None\n            response_str = response.decode(\"utf-8\", \"replace\")\n            if 'with \"=xxx\"' in response_str:\n                return self.whois(query, hostname, flags, True, quiet=quiet, ignore_socket_errors=ignore_socket_errors, timeout=timeout)\n            if flags & NICClient.WHOIS_RECURSE and nhost is None:\n                nhost = self.findwhois_server(response_str, hostname, query)\n            if nhost is not None and nhost != \"\":\n                response_str += self.whois(query, nhost, 0, quiet=quiet, ignore_socket_errors=ignore_socket_errors, timeout=timeout)\n        except socket.error as e:\n            if not quiet:\n                logger.error(\n                    \"Error trying to connect to socket: closing socket - {}\".format(e)\n                )\n            if ignore_socket_errors:\n                # 'response' is assigned a value (also a str) even on socket timeout\n                response_str = \"Socket not responding: {}\".format(e)\n            else:\n                raise e\n        finally:\n            if s:\n                s.close()\n        return response_str\n\n    def choose_server(self, domain: str, timeout: int = 10) -> Optional[str]:\n        \"\"\"Choose initial lookup NIC host\"\"\"\n        domain = domain.encode(\"idna\").decode(\"utf-8\")\n        if domain.endswith(\"-NORID\"):\n            return NICClient.NORIDHOST\n        if domain.endswith(\"id\"):\n            return NICClient.PANDIHOST\n        if domain.endswith(\"hr\"):\n            return NICClient.HR_HOST\n        if domain.endswith(\".pp.ua\"):\n            return NICClient.PPUA_HOST\n\n        domain_parts = domain.split(\".\")\n        if len(domain_parts) < 2:\n            return None\n        tld = domain_parts[-1]\n        if tld[0].isdigit():\n            return NICClient.ANICHOST\n        elif tld == \"ai\":\n            return NICClient.AI_HOST\n        elif tld == \"app\":\n            return NICClient.APP_HOST\n        elif tld == \"ar\":\n            return NICClient.AR_HOST\n        elif tld == \"bw\":\n            return NICClient.BW_HOST\n        elif tld == \"by\":\n            return NICClient.BY_HOST\n        elif tld == \"ca\":\n            return NICClient.CA_HOST\n        elif tld == \"chat\":\n            return NICClient.CHAT_HOST\n        elif tld == \"cl\":\n            return NICClient.CL_HOST\n        elif tld == \"cm\":\n            return NICClient.CM_HOST\n        elif tld == \"cr\":\n            return NICClient.CR_HOST\n        elif tld == \"de\":\n            return NICClient.DE_HOST\n        elif tld == \"dev\":\n            return NICClient.DEV_HOST\n        elif tld == \"dk\":\n            return NICClient.DK_HOST\n        elif tld == \"do\":\n            return NICClient.DO_HOST\n        elif tld == \"games\":\n            return NICClient.GAMES_HOST\n        elif tld == \"goog\" or tld == \"google\":\n            return NICClient.GOOGLE_HOST\n        elif tld == \"group\":\n            return NICClient.GROUP_HOST\n        elif tld == \"hk\":\n            return NICClient.HK_HOST\n        elif tld == \"hn\":\n            return NICClient.HN_HOST\n        elif tld == \"ist\":\n            return NICClient.IST_HOST\n        elif tld == \"jobs\":\n            return NICClient.JOBS_HOST\n        elif tld == \"jp\":\n            return NICClient.JP_HOST\n        elif tld == \"kz\":\n            return NICClient.KZ_HOST\n        elif tld == \"lat\":\n            return NICClient.LAT_HOST\n        elif tld == \"li\":\n            return NICClient.LI_HOST\n        elif tld == \"live\":\n            return NICClient.LIVE_HOST\n        elif tld == \"lt\":\n            return NICClient.LT_HOST\n        elif tld == \"market\":\n            return NICClient.MARKET_HOST\n        elif tld == \"money\":\n            return NICClient.MONEY_HOST\n        elif tld == \"mx\":\n            return NICClient.MX_HOST\n        elif tld == \"nl\":\n            return NICClient.NL_HOST\n        elif tld == \"online\":\n            return NICClient.ONLINE_HOST\n        elif tld == \"ooo\":\n            return NICClient.OOO_HOST\n        elif tld == \"page\":\n            return NICClient.PAGE_HOST\n        elif tld == \"pe\":\n            return NICClient.PE_HOST\n        elif tld == \"website\":\n            return NICClient.WEBSITE_HOST\n        elif tld == \"za\":\n            return NICClient.ZA_HOST\n        elif tld == \"ru\":\n            return NICClient.RU_HOST\n        elif tld == \"bz\":\n            return NICClient.RU_HOST\n        elif tld == \"city\":\n            return NICClient.RU_HOST\n        elif tld == \"design\":\n            return NICClient.DESIGN_HOST\n        elif tld == \"studio\":\n            return NICClient.STUDIO_HOST\n        elif tld == \"style\":\n            return NICClient.RU_HOST\n        elif tld == \"su\":\n            return NICClient.RU_HOST\n        elif tld == \"рус\" or tld == \"xn--p1acf\":\n            return NICClient.RU_HOST\n        elif tld == \"direct\":\n            return NICClient.IDS_HOST\n        elif tld == \"group\":\n            return NICClient.IDS_HOST\n        elif tld == \"immo\":\n            return NICClient.IDS_HOST\n        elif tld == \"life\":\n            return NICClient.IDS_HOST\n        elif tld == \"fashion\":\n            return NICClient.GDD_HOST\n        elif tld == \"vip\":\n            return NICClient.GDD_HOST\n        elif tld == \"shop\":\n            return NICClient.SHOP_HOST\n        elif tld == \"store\":\n            return NICClient.STORE_HOST\n        elif tld == \"дети\" or tld == \"xn--d1acj3b\":\n            return NICClient.DETI_HOST\n        elif tld == \"москва\" or tld == \"xn--80adxhks\":\n            return NICClient.MOSKVA_HOST\n        elif tld == \"рф\" or tld == \"xn--p1ai\":\n            return NICClient.RF_HOST\n        elif tld == \"орг\" or tld == \"xn--c1avg\":\n            return NICClient.PIR_HOST\n        elif tld == \"ng\":\n            return NICClient.NG_HOST\n        elif tld == \"укр\" or tld == \"xn--j1amh\":\n            return NICClient.UKR_HOST\n        elif tld == \"tn\":\n            return NICClient.TN_HOST\n        elif tld == \"sbs\":\n            return NICClient.SBS_HOST\n        elif tld == \"sg\":\n            return NICClient.SG_HOST\n        elif tld == \"site\":\n            return NICClient.SITE_HOST\n        elif tld == \"ga\":\n            return NICClient.GA_HOST\n        elif tld == \"xyz\":\n            return NICClient.XYZ_HOST\n        else:\n            return self.findwhois_iana(tld, timeout=timeout)\n            # server = tld + NICClient.QNICHOST_TAIL\n            # try:\n            #    socket.gethostbyname(server)\n            # except socket.gaierror:\n            #    server = NICClient.QNICHOST_HEAD + tld\n            # return server\n\n    def whois_lookup(\n        self, options: Optional[dict], query_arg: str, flags: int, quiet: bool = False, ignore_socket_errors: bool = True, timeout: int = 10\n    ) -> str:\n        \"\"\"Main entry point: Perform initial lookup on TLD whois server,\n        or other server to get region-specific whois server, then if quick\n        flag is false, perform a second lookup on the region-specific\n        server for contact records.  If `quiet` is `True`, no message\n        will be printed to STDOUT when a socket error is encountered.\n        If `ignore_socket_errors` is `False`, will raise an exception\n        instead of returning a string containing the error.\"\"\"\n        nichost = None\n        # whoud happen when this function is called by other than main\n        if options is None:\n            options = {}\n\n        if (\"whoishost\" not in options or options[\"whoishost\"] is None) and (\n            \"country\" not in options or options[\"country\"] is None\n        ):\n            self.use_qnichost = True\n            options[\"whoishost\"] = NICClient.NICHOST\n            if not (flags & NICClient.WHOIS_QUICK):\n                flags |= NICClient.WHOIS_RECURSE\n\n        if \"country\" in options and options[\"country\"] is not None:\n            result = self.whois(\n                query_arg,\n                options[\"country\"] + NICClient.QNICHOST_TAIL,\n                flags,\n                quiet=quiet,\n                ignore_socket_errors=ignore_socket_errors,\n                timeout=timeout\n            )\n        elif self.use_qnichost:\n            nichost = self.choose_server(query_arg, timeout=timeout)\n            if nichost is not None:\n                result = self.whois(query_arg, nichost, flags, quiet=quiet, ignore_socket_errors=ignore_socket_errors, timeout=timeout)\n            else:\n                result = \"\"\n        else:\n            result = self.whois(query_arg, options[\"whoishost\"], flags, quiet=quiet, ignore_socket_errors=ignore_socket_errors, timeout=timeout)\n        return result\n\n\ndef parse_command_line(argv: list[str]) -> tuple[optparse.Values, list[str]]:\n    \"\"\"Options handling mostly follows the UNIX whois(1) man page, except\n    long-form options can also be used.\n    \"\"\"\n    usage = \"usage: %prog [options] name\"\n\n    parser = optparse.OptionParser(add_help_option=False, usage=usage)\n    parser.add_option(\n        \"-a\",\n        \"--arin\",\n        action=\"store_const\",\n        const=NICClient.ANICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.ANICHOST,\n    )\n    parser.add_option(\n        \"-A\",\n        \"--apnic\",\n        action=\"store_const\",\n        const=NICClient.PNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.PNICHOST,\n    )\n    parser.add_option(\n        \"-b\",\n        \"--abuse\",\n        action=\"store_const\",\n        const=NICClient.ABUSEHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.ABUSEHOST,\n    )\n    parser.add_option(\n        \"-c\",\n        \"--country\",\n        action=\"store\",\n        type=\"string\",\n        dest=\"country\",\n        help=\"Lookup using country-specific NIC\",\n    )\n    parser.add_option(\n        \"-d\",\n        \"--mil\",\n        action=\"store_const\",\n        const=NICClient.DNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.DNICHOST,\n    )\n    parser.add_option(\n        \"-g\",\n        \"--gov\",\n        action=\"store_const\",\n        const=NICClient.GNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.GNICHOST,\n    )\n    parser.add_option(\n        \"-h\",\n        \"--host\",\n        action=\"store\",\n        type=\"string\",\n        dest=\"whoishost\",\n        help=\"Lookup using specified whois host\",\n    )\n    parser.add_option(\n        \"-i\",\n        \"--nws\",\n        action=\"store_const\",\n        const=NICClient.INICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.INICHOST,\n    )\n    parser.add_option(\n        \"-I\",\n        \"--iana\",\n        action=\"store_const\",\n        const=NICClient.IANAHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.IANAHOST,\n    )\n    parser.add_option(\n        \"-l\",\n        \"--lcanic\",\n        action=\"store_const\",\n        const=NICClient.LNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.LNICHOST,\n    )\n    parser.add_option(\n        \"-m\",\n        \"--ra\",\n        action=\"store_const\",\n        const=NICClient.MNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.MNICHOST,\n    )\n    parser.add_option(\n        \"-p\",\n        \"--port\",\n        action=\"store\",\n        type=\"int\",\n        dest=\"port\",\n        help=\"Lookup using specified tcp port\",\n    )\n    parser.add_option(\n        \"--prefer-ipv6\",\n        action=\"store_true\",\n        dest=\"prefer_ipv6\",\n        default=False,\n        help=\"Prioritize IPv6 resolution for WHOIS servers\",\n    )\n    parser.add_option(\n        \"-Q\",\n        \"--quick\",\n        action=\"store_true\",\n        dest=\"b_quicklookup\",\n        help=\"Perform quick lookup\",\n    )\n    parser.add_option(\n        \"-r\",\n        \"--ripe\",\n        action=\"store_const\",\n        const=NICClient.RNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.RNICHOST,\n    )\n    parser.add_option(\n        \"-R\",\n        \"--ru\",\n        action=\"store_const\",\n        const=\"ru\",\n        dest=\"country\",\n        help=\"Lookup Russian NIC\",\n    )\n    parser.add_option(\n        \"-6\",\n        \"--6bone\",\n        action=\"store_const\",\n        const=NICClient.SNICHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.SNICHOST,\n    )\n    parser.add_option(\n        \"-n\",\n        \"--ina\",\n        action=\"store_const\",\n        const=NICClient.PANDIHOST,\n        dest=\"whoishost\",\n        help=\"Lookup using host \" + NICClient.PANDIHOST,\n    )\n    parser.add_option(\n        \"-t\",\n        \"--timeout\",\n        action=\"store\",\n        type=\"int\",\n        dest=\"timeout\",\n        help=\"Set timeout for WHOIS request\",\n    )\n    parser.add_option(\"-?\", \"--help\", action=\"help\")\n\n    return parser.parse_args(argv)\n\n\nif __name__ == \"__main__\":\n    flags = 0\n    options, args = parse_command_line(sys.argv)\n    nic_client = NICClient(prefer_ipv6=options.prefer_ipv6)\n    if options.b_quicklookup:\n        flags = flags | NICClient.WHOIS_QUICK\n    logger.debug(nic_client.whois_lookup(options.__dict__, args[1], flags))\n"
  }
]