From 1e0817819c68a6d425d330f6e72a27e8b1f9431a Mon Sep 17 00:00:00 2001 From: Joe Obarzanek Date: Thu, 12 Oct 2023 10:23:00 -0400 Subject: [PATCH 1/5] Add key conversion function --- asyncwhois/parse.py | 64 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/asyncwhois/parse.py b/asyncwhois/parse.py index c06dc71..b5d2d5f 100644 --- a/asyncwhois/parse.py +++ b/asyncwhois/parse.py @@ -122,7 +122,6 @@ def __str__(self): class IPBaseKeys(str, Enum): - NET_RANGE = "net_range" CIDR = "cidr" NET_NAME = "net_name" @@ -173,8 +172,69 @@ def __str__(self): return self.value -class BaseParser: +def convert_whodap_keys(parser_output: dict) -> dict: + # keys in both, but with mismatched names + conversions = [ + (TLDBaseKeys.EXPIRES, "expires_date", False), + (TLDBaseKeys.UPDATED, "updated_date", False), + (TLDBaseKeys.CREATED, "created_date", False), + (TLDBaseKeys.NAME_SERVERS, "nameservers", False), + (TLDBaseKeys.REGISTRAR_ABUSE_EMAIL, "abuse_email", False), + (TLDBaseKeys.REGISTRAR_ABUSE_PHONE, "abuse_phone", False), + (TLDBaseKeys.TECH_EMAIL, "technical_email", False), + (TLDBaseKeys.TECH_ADDRESS, "technical_address", False), + (TLDBaseKeys.TECH_ORGANIZATION, "technical_organization", False), + (TLDBaseKeys.TECH_NAME, "technical_name", False), + (TLDBaseKeys.TECH_PHONE, "technical_phone", False), + (TLDBaseKeys.TECH_FAX, "technical_fax", False), + (TLDBaseKeys.REGISTRAR, "registrar_name", False), + ] + for asyncwhois_key, whodap_key, keep in conversions: + if keep: + parser_output[asyncwhois_key] = parser_output.get(whodap_key) + else: + parser_output[asyncwhois_key] = parser_output.pop(whodap_key) + # asyncwhois keys not in whodap + non_whodap_keys = [ + TLDBaseKeys.ADMIN_ID, + TLDBaseKeys.ADMIN_CITY, + TLDBaseKeys.ADMIN_STATE, + TLDBaseKeys.ADMIN_COUNTRY, + TLDBaseKeys.ADMIN_ZIPCODE, + TLDBaseKeys.BILLING_ID, + TLDBaseKeys.BILLING_CITY, + TLDBaseKeys.BILLING_STATE, + TLDBaseKeys.BILLING_COUNTRY, + TLDBaseKeys.BILLING_ZIPCODE, + TLDBaseKeys.TECH_ID, + TLDBaseKeys.TECH_CITY, + TLDBaseKeys.TECH_STATE, + TLDBaseKeys.TECH_COUNTRY, + TLDBaseKeys.TECH_ZIPCODE, + TLDBaseKeys.REGISTRANT_CITY, + TLDBaseKeys.REGISTRANT_STATE, + TLDBaseKeys.REGISTRANT_COUNTRY, + TLDBaseKeys.REGISTRANT_ZIPCODE, + TLDBaseKeys.REGISTRAR, + TLDBaseKeys.REGISTRAR_IANA_ID, + TLDBaseKeys.REGISTRAR_URL, + TLDBaseKeys.DNSSEC, + ] + for key in non_whodap_keys: + parser_output[key] = None + # whodap keys not in asyncwhois + non_asyncwhois_keys = [ + "registrar_email", + "registrar_phone", + "registrar_address", + "registrar_fax", + ] + for key in non_asyncwhois_keys: + parser_output.pop(key) + return parser_output + +class BaseParser: reg_expressions = {} date_keys = () From b91378100bbb81490ee0c6ce61268c9b339b3cd0 Mon Sep 17 00:00:00 2001 From: Joe Obarzanek Date: Thu, 12 Oct 2023 10:24:07 -0400 Subject: [PATCH 2/5] Add registrant phone and email --- asyncwhois/parse_tld.py | 226 ++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 79 deletions(-) diff --git a/asyncwhois/parse_tld.py b/asyncwhois/parse_tld.py index 6527ada..c2e1a3f 100644 --- a/asyncwhois/parse_tld.py +++ b/asyncwhois/parse_tld.py @@ -7,7 +7,6 @@ class TLDParser(BaseParser): - base_expressions = { TLDBaseKeys.DOMAIN_NAME: r"Domain Name: *(.+)", TLDBaseKeys.CREATED: r"Creation Date: *(.+)", @@ -26,6 +25,8 @@ class TLDParser(BaseParser): TLDBaseKeys.REGISTRANT_ZIPCODE: r"Registrant Postal Code: *(.+)", TLDBaseKeys.REGISTRANT_COUNTRY: r"Registrant Country: *(.+)", TLDBaseKeys.REGISTRANT_EMAIL: r"Registrant Email: *(.+)", + TLDBaseKeys.REGISTRANT_PHONE: r"Registrant Phone: *(.+)", + TLDBaseKeys.REGISTRANT_FAX: r"Registrant Fax: *(.+)", TLDBaseKeys.DNSSEC: r"DNSSEC: *([\S]+)", TLDBaseKeys.STATUS: r"Status: *(.+)", TLDBaseKeys.NAME_SERVERS: r"Name server: *(.+)", @@ -72,7 +73,6 @@ def __init__(self): class DomainParser: - _no_match_checks = [ "no match", "not found", @@ -105,81 +105,149 @@ def _init_parser(tld: str) -> TLDParser: key/value pairs from the whois server output for the given `tld`. :param tld: the top level domain - :return: instance of TLDParser or a TLDParser sub-class + :return: instance of TLDParser or a TLDParser subclass """ - tld_parsers = { - "ae": RegexAE(), - "ar": RegexAR(), - "at": RegexAT(), - "au": RegexAU(), - "aw": RegexAW(), - "ax": RegexAX(), - "be": RegexBE(), - "br": RegexBR(), - "by": RegexBY(), - "cc": RegexCC(), - "ch": RegexCH(), - "cl": RegexCL(), - "cn": RegexCN(), - "cr": RegexCR(), - "cz": RegexCZ(), - "de": RegexDE(), - "dk": RegexDK(), - "edu": RegexEDU(), - "ee": RegexEE(), - "eu": RegexEU(), - "fi": RegexFI(), - "fr": RegexFR(), - "ga": RegexGA(), - "ge": RegexGE(), - "gg": RegexGG(), - "gq": RegexGQ(), - "hk": RegexHK(), - "hr": RegexHR(), - "id": RegexID(), - "ie": RegexIE(), - "il": RegexIL(), - "ir": RegexIR(), - "is": RegexIS(), - "it": RegexIT(), - "jp": RegexJP(), - "kg": RegexKG(), - "kr": RegexKR(), - "kz": RegexKZ(), - "li": RegexLI(), - "lu": RegexLU(), - "lv": RegexLV(), - "ma": RegexMA(), - "ml": RegexML(), - "mx": RegexMX(), - "nl": RegexNL(), - "no": RegexNO(), - "nu": RegexNU(), - "nz": RegexNZ(), - "om": RegexOM(), - "pe": RegexPE(), - "pl": RegexPL(), - "pt": RegexPT(), - "rf": RegexRF(), - "ro": RegexRO(), - "ru": RegexRU(), - "sa": RegexSA(), - "se": RegexSE(), - "si": RegexSI(), - "sk": RegexSK(), - "su": RegexSU(), - "tk": RegexTK(), - "tr": RegexTR(), - "tw": RegexTW(), - "ua": RegexUA(), - "uk": RegexUK(), - "uz": RegexUZ(), - "ve": RegexVE(), - } + if tld == "ae": + return RegexAE() + elif tld == "ar": + return RegexAR() + elif tld == "at": + return RegexAT() + elif tld == "au": + return RegexAU() + elif tld == "aw": + return RegexAW() + elif tld == "ax": + return RegexAX() + elif tld == "be": + return RegexBE() + elif tld == "br": + return RegexBR() + elif tld == "by": + return RegexBY() + elif tld == "cc": + return RegexCC() + elif tld == "ch": + return RegexCH() + elif tld == "cl": + return RegexCL() + elif tld == "cn": + return RegexCN() + elif tld == "cr": + return RegexCR() + elif tld == "cz": + return RegexCZ() + elif tld == "de": + return RegexDE() + elif tld == "dk": + return RegexDK() + elif tld == "edu": + return RegexEDU() + elif tld == "ee": + return RegexEE() + elif tld == "eu": + return RegexEU() + elif tld == "fi": + return RegexFI() + elif tld == "fr": + return RegexFR() + elif tld == "ga": + return RegexGA() + elif tld == "ge": + return RegexGE() + elif tld == "gg": + return RegexGG() + elif tld == "gq": + return RegexGQ() + elif tld == "hk": + return RegexHK() + elif tld == "hr": + return RegexHR() + elif tld == "id": + return RegexID() + elif tld == "ie": + return RegexIE() + elif tld == "il": + return RegexIL() + elif tld == "ir": + return RegexIR() + elif tld == "is": + return RegexIS() + elif tld == "it": + return RegexIT() + elif tld == "jp": + return RegexJP() + elif tld == "kg": + return RegexKG() + elif tld == "kr": + return RegexKR() + elif tld == "kz": + return RegexKZ() + elif tld == "li": + return RegexLI() + elif tld == "lu": + return RegexLU() + elif tld == "lv": + return RegexLV() + elif tld == "ma": + return RegexMA() + elif tld == "ml": + return RegexML() + elif tld == "mx": + return RegexMX() + elif tld == "nl": + return RegexNL() + elif tld == "no": + return RegexNO() + elif tld == "ar": + return RegexAR() + elif tld == "nu": + return RegexNU() + elif tld == "nz": + return RegexNZ() + elif tld == "om": + return RegexOM() + elif tld == "pe": + return RegexPE() + elif tld == "pl": + return RegexPL() + elif tld == "pt": + return RegexPT() + elif tld == "rf": + return RegexRF() + elif tld == "ro": + return RegexRO() + elif tld == "ru": + return RegexRU() + elif tld == "sa": + return RegexSA() + elif tld == "se": + return RegexSE() + elif tld == "si": + return RegexSI() + elif tld == "sk": + return RegexSK() + elif tld == "su": + return RegexSU() + elif tld == "tk": + return RegexTK() + elif tld == "tr": + return RegexTR() + elif tld == "tw": + return RegexTW() + elif tld == "ua": + return RegexUA() + elif tld == "uk": + return RegexUK() + elif tld == "uz": + return RegexUZ() + elif tld == "ve": + return RegexVE() + # The TLDParser can handle all "Generic" and some "Country-Code" TLDs. # If the parsed output of lookup is not what you expect or even incorrect, - # check for and then modify the existing Regex subclass or create a new one. - return tld_parsers.get(tld, TLDParser()) + # check and modify the existing Regex subclass or create a new one. + return TLDParser() # ============================== @@ -195,7 +263,7 @@ class RegexRU(TLDParser): TLDBaseKeys.REGISTRANT_ORGANIZATION: r"org: *(.+)", TLDBaseKeys.STATUS: r"state: *(.+)", TLDBaseKeys.NAME_SERVERS: r"nserver: *(.+)", - TLDBaseKeys.ADMIN_EMAIL: r"admin-contact: *(.+)" + TLDBaseKeys.ADMIN_EMAIL: r"admin-contact: *(.+)", } def __init__(self): @@ -251,7 +319,7 @@ class RegexRO(TLDParser): TLDBaseKeys.CREATED: r"Registered On: *(.+)", TLDBaseKeys.EXPIRES: r"Expires On: *(.+)", TLDBaseKeys.NAME_SERVERS: r"Nameserver: *(.+)", - TLDBaseKeys.REGISTRAR_URL: r"Referral URL: *(.+)" + TLDBaseKeys.REGISTRAR_URL: r"Referral URL: *(.+)", } def __init__(self): @@ -300,7 +368,7 @@ class RegexFR(TLDParser): TLDBaseKeys.UPDATED: r"last-update: (\d{4}-\d{2}-\d{2})", TLDBaseKeys.EXPIRES: r"Expiry Date: (\d{4}-\d{2}-\d{2})", TLDBaseKeys.NAME_SERVERS: r"nserver: *(.+)", - TLDBaseKeys.REGISTRAR: r"registrar: *(.+)" + TLDBaseKeys.REGISTRAR: r"registrar: *(.+)", } def __init__(self): @@ -1420,7 +1488,7 @@ def parse(self, blob: str) -> Dict[str, Any]: class RegexNL(TLDParser): _nl_expressions = { TLDBaseKeys.REGISTRAR: r"Registrar:\n(.+)", - TLDBaseKeys.REGISTRAR_ABUSE_EMAIL: r"Abuse Contact:\n(.+)" + TLDBaseKeys.REGISTRAR_ABUSE_EMAIL: r"Abuse Contact:\n(.+)", } def __init__(self): @@ -1492,7 +1560,7 @@ def parse(self, blob: str) -> Dict[str, Any]: class RegexAW(TLDParser): _aw_expressions = { TLDBaseKeys.REGISTRAR: r"Registrar:\n*(.+)", - TLDBaseKeys.REGISTRAR_ABUSE_EMAIL: r"Abuse Contact:\n*(.+)" + TLDBaseKeys.REGISTRAR_ABUSE_EMAIL: r"Abuse Contact:\n*(.+)", } def __init__(self): From ecffe33b7451e3745dd5bc5e880c0d5e42ad72f2 Mon Sep 17 00:00:00 2001 From: Joe Obarzanek Date: Thu, 12 Oct 2023 13:00:42 -0400 Subject: [PATCH 3/5] Handle mismatched keys for rdap --- asyncwhois/parse_tld.py | 2 -- asyncwhois/pywhois.py | 29 ++++------------------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/asyncwhois/parse_tld.py b/asyncwhois/parse_tld.py index c2e1a3f..aa59bed 100644 --- a/asyncwhois/parse_tld.py +++ b/asyncwhois/parse_tld.py @@ -199,8 +199,6 @@ def _init_parser(tld: str) -> TLDParser: return RegexNL() elif tld == "no": return RegexNO() - elif tld == "ar": - return RegexAR() elif tld == "nu": return RegexNU() elif tld == "nz": diff --git a/asyncwhois/pywhois.py b/asyncwhois/pywhois.py index b546f12..b22e108 100644 --- a/asyncwhois/pywhois.py +++ b/asyncwhois/pywhois.py @@ -4,8 +4,9 @@ import tldextract import whodap +from .parse import convert_whodap_keys from .parse_rir import NumberParser -from .parse_tld import DomainParser, TLDBaseKeys +from .parse_tld import DomainParser from .query import DomainQuery, NumberQuery from .servers import CountryCodeTLD, GenericTLD, SponsoredTLD, IPv4Allocations @@ -123,19 +124,8 @@ def rdap_domain(cls, domain: str, httpx_client: Any = None): httpx_client=httpx_client, ) _self._query = response.to_dict() - # date keys are mismatched between projects; change these keys to the asyncwhois set. whois_dict = response.to_whois_dict() - for a_key, b_key in [ - (TLDBaseKeys.EXPIRES, "expires_date"), - (TLDBaseKeys.UPDATED, "updated_date"), - (TLDBaseKeys.CREATED, "created_date") - ]: - whois_dict[a_key] = whois_dict.pop(b_key) - # reconcile abuse keys, but don't remove existing key as to not cause issues - # with apps currently depending on them. todo: re-standardize keys in next major release - whois_dict[TLDBaseKeys.REGISTRAR_ABUSE_EMAIL] = whois_dict["abuse_email"] - whois_dict[TLDBaseKeys.REGISTRAR_ABUSE_PHONE] = whois_dict["abuse_phone"] - _self._parser = whois_dict + _self._parser = convert_whodap_keys(whois_dict) return _self @classmethod @@ -158,18 +148,7 @@ async def aio_rdap_domain(cls, domain: str, httpx_client: Any = None): ) _self._query = response.to_dict() whois_dict = response.to_whois_dict() - # date keys are mismatched between projects; change these keys to the asyncwhois set. - for a_key, b_key in [ - (TLDBaseKeys.EXPIRES, "expires_date"), - (TLDBaseKeys.UPDATED, "updated_date"), - (TLDBaseKeys.CREATED, "created_date"), - ]: - whois_dict[a_key] = whois_dict.pop(b_key) - # reconcile abuse keys, but don't remove existing key as to not cause issues - # with apps currently depending on them. todo: re-standardize keys in next major release - whois_dict[TLDBaseKeys.REGISTRAR_ABUSE_EMAIL] = whois_dict["abuse_email"] - whois_dict[TLDBaseKeys.REGISTRAR_ABUSE_PHONE] = whois_dict["abuse_phone"] - _self._parser = whois_dict + _self._parser = convert_whodap_keys(whois_dict) return _self From 6c37f5a63c7cd224b565a97094080dafb4136d11 Mon Sep 17 00:00:00 2001 From: Joe Obarzanek Date: Thu, 12 Oct 2023 13:00:57 -0400 Subject: [PATCH 4/5] Run black formatter --- asyncwhois/parse_rir.py | 5 ----- asyncwhois/query.py | 4 +++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/asyncwhois/parse_rir.py b/asyncwhois/parse_rir.py index 4b282bb..7b5a10b 100644 --- a/asyncwhois/parse_rir.py +++ b/asyncwhois/parse_rir.py @@ -5,7 +5,6 @@ class RIRParser(BaseParser): - date_keys = ( IPBaseKeys.ORG_REG_DATE, IPBaseKeys.ORG_UPDATED, @@ -86,7 +85,6 @@ def __init__(self): class AFRINICParser(RIRParser): - _afrinic = { IPBaseKeys.NET_RANGE: r"inetnum: *(.+)", IPBaseKeys.NET_NAME: r"netname: *(.+)", @@ -150,7 +148,6 @@ def parse(self, blob: str) -> Dict[IPBaseKeys, Any]: class APNICParser(RIRParser): - _apnic = { IPBaseKeys.NET_RANGE: r"inetnum: *(.+)", IPBaseKeys.NET_NAME: r"netname: *(.+)", @@ -221,7 +218,6 @@ def parse(self, blob: str) -> Dict[IPBaseKeys, Any]: class LACNICParser(RIRParser): - _lacnic = { IPBaseKeys.NET_RANGE: r"inetnum: *(.+)", IPBaseKeys.CIDR: r"inetrev: *(.+)", @@ -291,7 +287,6 @@ def parse(self, blob: str) -> Dict[IPBaseKeys, Any]: class RIPEParser(RIRParser): - _ripe = { IPBaseKeys.NET_RANGE: r"inetnum: *(.+)", IPBaseKeys.NET_NAME: r"netname: *(.+)", diff --git a/asyncwhois/query.py b/asyncwhois/query.py index 2c7e16d..9bdb67b 100644 --- a/asyncwhois/query.py +++ b/asyncwhois/query.py @@ -162,7 +162,9 @@ async def _aio_do_query(self, server: str, data: str, regex: str): # socket reader and writer reader, writer = r_and_w # submit domain and receive raw query output - query_output = await asyncio.wait_for(self._aio_send_and_recv(reader, writer, data), self.timeout) + query_output = await asyncio.wait_for( + self._aio_send_and_recv(reader, writer, data), self.timeout + ) if not self.authoritative_only: # concatenate query outputs self.query_chain += query_output From 7b3260d2c89eab557f5317d316c45412316ea098 Mon Sep 17 00:00:00 2001 From: Joe Obarzanek Date: Thu, 12 Oct 2023 13:01:14 -0400 Subject: [PATCH 5/5] Add test for mismatched keys --- tests/samples/com_dict_asyncwhois.json | 69 ++++++++++++++++++++++++++ tests/samples/com_dict_whodap.json | 52 +++++++++++++++++++ tests/test_parser_methods.py | 64 ++++++++++++++++++------ 3 files changed, 170 insertions(+), 15 deletions(-) create mode 100644 tests/samples/com_dict_asyncwhois.json create mode 100644 tests/samples/com_dict_whodap.json diff --git a/tests/samples/com_dict_asyncwhois.json b/tests/samples/com_dict_asyncwhois.json new file mode 100644 index 0000000..4e72997 --- /dev/null +++ b/tests/samples/com_dict_asyncwhois.json @@ -0,0 +1,69 @@ +{ + "domain_name": "google.com", + "created": "1997-09-15T07:00:00+00:00", + "updated": "2019-09-09T15:39:04+00:00", + "expires": "2028-09-13T07:00:00+00:00", + "registrar": "MarkMonitor, Inc.", + "registrar_iana_id": "292", + "registrar_url": "http://www.markmonitor.com", + "registrar_abuse_email": "abusecomplaints@markmonitor.com", + "registrar_abuse_phone": "+1.2086851750", + "registrant_name": null, + "registrant_organization": "Google LLC", + "registrant_address": null, + "registrant_city": null, + "registrant_state": "CA", + "registrant_zipcode": null, + "registrant_country": "US", + "registrant_email": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com", + "registrant_phone": null, + "registrant_fax": null, + "dnssec": "unsigned", + "status": [ + "clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)", + "clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)", + "clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)", + "serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)", + "serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)", + "serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)" + ], + "name_servers": [ + "ns2.google.com", + "ns1.google.com", + "ns4.google.com", + "ns3.google.com" + ], + "admin_name": null, + "admin_id": null, + "admin_organization": "Google LLC", + "admin_city": null, + "admin_address": null, + "admin_state": "CA", + "admin_zipcode": null, + "admin_country": "US", + "admin_phone": null, + "admin_fax": null, + "admin_email": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com", + "billing_name": null, + "billing_id": null, + "billing_organization": null, + "billing_city": null, + "billing_address": null, + "billing_state": null, + "billing_zipcode": null, + "billing_country": null, + "billing_phone": null, + "billing_fax": null, + "billing_email": null, + "tech_name": null, + "tech_id": null, + "tech_organization": "Google LLC", + "tech_city": null, + "tech_address": null, + "tech_state": "CA", + "tech_zipcode": null, + "tech_country": "US", + "tech_phone": null, + "tech_fax": null, + "tech_email": "Select Request Email Form at https://domains.markmonitor.com/whois/google.com" +} \ No newline at end of file diff --git a/tests/samples/com_dict_whodap.json b/tests/samples/com_dict_whodap.json new file mode 100644 index 0000000..6694853 --- /dev/null +++ b/tests/samples/com_dict_whodap.json @@ -0,0 +1,52 @@ +{ + "abuse_email": "abusecomplaints@markmonitor.com", + "abuse_phone": "+1.2086851750", + "admin_name": "REDACTED FOR PRIVACY", + "admin_organization": "REDACTED FOR PRIVACY", + "admin_email": "REDACTED FOR PRIVACY", + "admin_address": "CA, US", + "admin_phone": "REDACTED FOR PRIVACY", + "admin_fax": "REDACTED FOR PRIVACY", + "billing_name": null, + "billing_organization": null, + "billing_email": null, + "billing_address": null, + "billing_phone": null, + "billing_fax": null, + "registrant_name": "REDACTED FOR PRIVACY", + "registrant_organization": null, + "registrant_email": "REDACTED FOR PRIVACY", + "registrant_address": "CA, US", + "registrant_phone": "REDACTED FOR PRIVACY", + "registrant_fax": "REDACTED FOR PRIVACY", + "registrar_name": null, + "registrar_email": null, + "registrar_address": "3540 E Longwing Ln, Meridian, ID, 83646, US", + "registrar_phone": null, + "registrar_fax": null, + "technical_name": "REDACTED FOR PRIVACY", + "technical_organization": "REDACTED FOR PRIVACY", + "technical_email": "REDACTED FOR PRIVACY", + "technical_address": "CA, US", + "technical_phone": "REDACTED FOR PRIVACY", + "technical_fax": "REDACTED FOR PRIVACY", + "created_date": "1997-09-15T07:00:00+00:00", + "updated_date": "2019-09-09T15:39:04+00:00", + "expires_date": "2028-09-13T07:00:00+00:00", + "status": [ + "client update prohibited", + "client transfer prohibited", + "client delete prohibited", + "server update prohibited", + "server transfer prohibited", + "server delete prohibited" + ], + "nameservers": [ + "ns1.google.com", + "ns2.google.com", + "ns3.google.com", + "ns4.google.com" + ], + "domain_name": "google.com", + "dnssec": "unsigned" +} \ No newline at end of file diff --git a/tests/test_parser_methods.py b/tests/test_parser_methods.py index 1f45b9a..172a52e 100644 --- a/tests/test_parser_methods.py +++ b/tests/test_parser_methods.py @@ -1,23 +1,53 @@ import unittest import datetime +import json +import os -from asyncwhois.parse import BaseParser +from asyncwhois.parse import BaseParser, convert_whodap_keys class TestWhoIsParserMethods(unittest.TestCase): + def test_convert_whodap_keys(self): + with open( + os.path.join( + os.path.abspath(os.path.dirname(__file__)), + "samples/com_dict_asyncwhois.json", + ) + ) as o: + asyncwhois_dict = json.loads(o.read()) + + with open( + os.path.join( + os.path.abspath(os.path.dirname(__file__)), + "samples/com_dict_whodap.json", + ) + ) as o: + whodap_dict = json.loads(o.read()) + + whodap_keys_after = convert_whodap_keys(whodap_dict).keys() + asyncwhois_keys = asyncwhois_dict.keys() + for whodap_key in whodap_keys_after: + assert ( + whodap_key in asyncwhois_keys + ), f"{whodap_key} not in {asyncwhois_keys}" + + for asyncwhois_key in asyncwhois_dict.keys(): + assert ( + asyncwhois_key in whodap_keys_after + ), f"{asyncwhois_key} not in {whodap_keys_after}" def test_parse_dates(self): date_strings = [ - '11-aug-2020', - '11-August-2020', - '11-09-2020', - '2020-09-20', - '2020.09.20', - '2020/09/20', - '2020. 09. 20.', - '2020.09.20 11:11:11', - 'August 11 2020', - '20200920' + "11-aug-2020", + "11-August-2020", + "11-09-2020", + "2020-09-20", + "2020.09.20", + "2020/09/20", + "2020. 09. 20.", + "2020.09.20 11:11:11", + "August 11 2020", + "20200920", ] for date_string in date_strings: @@ -31,11 +61,13 @@ def test_find_match(self): Name server: ns2.google.com Status: ok """ - domain = BaseParser().find_match(r'domain name: *(.+)', test_blob) + domain = BaseParser().find_match(r"domain name: *(.+)", test_blob) self.assertEqual(domain, "google.com") - name_servers = BaseParser().find_match(r'name server: *(.+)', test_blob, many=True) + name_servers = BaseParser().find_match( + r"name server: *(.+)", test_blob, many=True + ) self.assertEqual(len(name_servers), 2) - status = BaseParser().find_match(r'status: *(.+)', test_blob, many=True) + status = BaseParser().find_match(r"status: *(.+)", test_blob, many=True) self.assertEqual(len(status), 1) def test_find_multiline_match(self): @@ -50,5 +82,7 @@ def test_find_multiline_match(self): Registrar: someone """ - name_servers = BaseParser().find_multiline_match(r'Domain nameservers:\n', test_blob) + name_servers = BaseParser().find_multiline_match( + r"Domain nameservers:\n", test_blob + ) self.assertEqual(len(name_servers), 4)