rdapper 0.10.1 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +134 -52
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -316,10 +316,33 @@ const PRIVACY_NAME_KEYWORDS = [
|
|
|
316
316
|
"withheld",
|
|
317
317
|
"not disclosed",
|
|
318
318
|
"protected",
|
|
319
|
-
"protection"
|
|
319
|
+
"protection",
|
|
320
|
+
"privado",
|
|
321
|
+
"datos privados",
|
|
322
|
+
"data protected",
|
|
323
|
+
"data redacted",
|
|
324
|
+
"gdpr redacted",
|
|
325
|
+
"gdpr masked",
|
|
326
|
+
"non-public data",
|
|
327
|
+
"statutory masking",
|
|
328
|
+
"redacted.forprivacy",
|
|
329
|
+
"registration private",
|
|
330
|
+
"hidden upon user request",
|
|
331
|
+
"not available from registry"
|
|
332
|
+
];
|
|
333
|
+
const NO_DATA_VALUES = [
|
|
334
|
+
"-",
|
|
335
|
+
".",
|
|
336
|
+
"n/a",
|
|
337
|
+
"na",
|
|
338
|
+
"no data",
|
|
339
|
+
"not available",
|
|
340
|
+
"not applicable",
|
|
341
|
+
"none"
|
|
320
342
|
];
|
|
321
343
|
function isPrivacyName(value) {
|
|
322
|
-
const v = value.toLowerCase();
|
|
344
|
+
const v = value.toLowerCase().trim();
|
|
345
|
+
if (NO_DATA_VALUES.includes(v)) return true;
|
|
323
346
|
return PRIVACY_NAME_KEYWORDS.some((k) => v.includes(k));
|
|
324
347
|
}
|
|
325
348
|
|
|
@@ -547,14 +570,25 @@ function parseVcard(vcardArray) {
|
|
|
547
570
|
//#endregion
|
|
548
571
|
//#region src/whois/client.ts
|
|
549
572
|
/**
|
|
573
|
+
* Some WHOIS servers default to non-English responses. This mapping allows automatic
|
|
574
|
+
* query transformation to request English-only output for easier parsing.
|
|
575
|
+
*
|
|
576
|
+
* To add new servers: Add an entry with the hostname and transformation function:
|
|
577
|
+
* "whois.example.org": (query) => `${query}/english`,
|
|
578
|
+
*/
|
|
579
|
+
const WHOIS_QUERY_TRANSFORMERS = { "whois.jprs.jp": (query) => `${query}/e` };
|
|
580
|
+
/**
|
|
550
581
|
* Perform a WHOIS query against an RFC 3912 server over TCP 43.
|
|
551
582
|
* Returns the raw text and the server used.
|
|
552
583
|
*/
|
|
553
584
|
async function whoisQuery(server, query, options) {
|
|
554
585
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
586
|
+
const port = 43;
|
|
587
|
+
const host = server.replace(/^whois:\/\//i, "");
|
|
588
|
+
const transformer = WHOIS_QUERY_TRANSFORMERS[host];
|
|
555
589
|
return {
|
|
556
590
|
serverQueried: server,
|
|
557
|
-
text: await withTimeout(queryTcp(
|
|
591
|
+
text: await withTimeout(queryTcp(host, port, transformer ? transformer(query) : query, options), timeoutMs, "WHOIS timeout")
|
|
558
592
|
};
|
|
559
593
|
}
|
|
560
594
|
async function queryTcp(host, port, query, options) {
|
|
@@ -834,6 +868,8 @@ const WHOIS_AVAILABLE_PATTERNS = [
|
|
|
834
868
|
/\bdomain status[:\s]+available\b/i,
|
|
835
869
|
/\bobject does not exist\b/i,
|
|
836
870
|
/\bthe queried object does not exist\b/i,
|
|
871
|
+
/\bqueried object does not exist\b/i,
|
|
872
|
+
/\breturned 0 objects\b/i,
|
|
837
873
|
/\bstatus:\s*free\b/i,
|
|
838
874
|
/\bstatus:\s*available\b/i,
|
|
839
875
|
/\bno object found\b/i,
|
|
@@ -856,52 +892,73 @@ function normalizeWhois(domain, tld, whoisText, whoisServer, includeRaw = false)
|
|
|
856
892
|
const creationDate = anyValue(map, [
|
|
857
893
|
"creation date",
|
|
858
894
|
"created on",
|
|
895
|
+
"created",
|
|
859
896
|
"registered on",
|
|
897
|
+
"registered",
|
|
898
|
+
"registration date",
|
|
860
899
|
"domain registration date",
|
|
861
900
|
"domain create date",
|
|
862
|
-
"created",
|
|
863
|
-
"registered",
|
|
864
901
|
"domain name commencement date",
|
|
865
902
|
"registration time",
|
|
866
903
|
"domain record activated",
|
|
904
|
+
"domain registered",
|
|
905
|
+
"registered date",
|
|
867
906
|
"assigned"
|
|
868
907
|
]);
|
|
869
908
|
const updatedDate = anyValue(map, [
|
|
870
909
|
"updated date",
|
|
910
|
+
"updated",
|
|
871
911
|
"last updated",
|
|
912
|
+
"last updated on",
|
|
872
913
|
"last update",
|
|
914
|
+
"last-update",
|
|
873
915
|
"last modified",
|
|
874
916
|
"modified",
|
|
917
|
+
"changed",
|
|
918
|
+
"modification date",
|
|
875
919
|
"domain record last updated"
|
|
876
920
|
]);
|
|
877
921
|
const expirationDate = anyValue(map, [
|
|
878
922
|
"registry expiry date",
|
|
879
923
|
"registry expiration date",
|
|
880
|
-
"expiry date",
|
|
881
|
-
"expiration date",
|
|
882
|
-
"expire date",
|
|
883
|
-
"expiration time",
|
|
884
924
|
"registrar registration expiration date",
|
|
885
925
|
"registrar registration expiry date",
|
|
886
926
|
"registrar expiration date",
|
|
887
927
|
"registrar expiry date",
|
|
888
|
-
"
|
|
889
|
-
"
|
|
928
|
+
"expiry date",
|
|
929
|
+
"expiration date",
|
|
930
|
+
"expiry",
|
|
931
|
+
"expire date",
|
|
932
|
+
"expire",
|
|
933
|
+
"expired",
|
|
890
934
|
"expires on",
|
|
891
935
|
"expires",
|
|
892
|
-
"
|
|
936
|
+
"expiration time",
|
|
937
|
+
"domain expires",
|
|
938
|
+
"paid-till",
|
|
893
939
|
"renewal date",
|
|
894
|
-
"validity"
|
|
940
|
+
"validity",
|
|
941
|
+
"record will expire on"
|
|
895
942
|
]);
|
|
896
943
|
const registrar = (() => {
|
|
897
944
|
const name = anyValue(map, [
|
|
898
945
|
"registrar",
|
|
946
|
+
"registrar name",
|
|
947
|
+
"registrar organization",
|
|
948
|
+
"registrar organization name",
|
|
899
949
|
"sponsoring registrar",
|
|
900
|
-
"
|
|
950
|
+
"organisation",
|
|
951
|
+
"record maintained by"
|
|
952
|
+
]);
|
|
953
|
+
const ianaId = anyValue(map, [
|
|
954
|
+
"registrar iana id",
|
|
955
|
+
"sponsoring registrar iana id",
|
|
956
|
+
"iana id"
|
|
901
957
|
]);
|
|
902
|
-
const ianaId = anyValue(map, ["registrar iana id", "iana id"]);
|
|
903
958
|
const url = anyValue(map, [
|
|
904
959
|
"registrar url",
|
|
960
|
+
"registrar website",
|
|
961
|
+
"registrar web",
|
|
905
962
|
"url of the registrar",
|
|
906
963
|
"referrer"
|
|
907
964
|
]);
|
|
@@ -916,7 +973,7 @@ function normalizeWhois(domain, tld, whoisText, whoisServer, includeRaw = false)
|
|
|
916
973
|
phone: abusePhone || void 0
|
|
917
974
|
};
|
|
918
975
|
})();
|
|
919
|
-
const statusLines = map["domain status"] || map.status || [];
|
|
976
|
+
const statusLines = map["domain status"] || map.status || map.flags || map.state || map["registration status"] || map.eppstatus || [];
|
|
920
977
|
const statuses = statusLines.length ? statusLines.map((line) => ({
|
|
921
978
|
status: line.split(/\s+/)[0],
|
|
922
979
|
raw: line
|
|
@@ -925,7 +982,18 @@ function normalizeWhois(domain, tld, whoisText, whoisServer, includeRaw = false)
|
|
|
925
982
|
...map["name server"] || [],
|
|
926
983
|
...map.nameserver || [],
|
|
927
984
|
...map["name servers"] || [],
|
|
928
|
-
...map.nserver || []
|
|
985
|
+
...map.nserver || [],
|
|
986
|
+
...map["name server information"] || [],
|
|
987
|
+
...map.dns || [],
|
|
988
|
+
...map.hostname || [],
|
|
989
|
+
...map["domain nameservers"] || [],
|
|
990
|
+
...map["domain servers in listed order"] || [],
|
|
991
|
+
...map["domain servers"] || [],
|
|
992
|
+
...map["name servers dns"] || [],
|
|
993
|
+
...map["ns 1"] || [],
|
|
994
|
+
...map["ns 2"] || [],
|
|
995
|
+
...map["ns 3"] || [],
|
|
996
|
+
...map["ns 4"] || []
|
|
929
997
|
];
|
|
930
998
|
const nameservers = nsLines.length ? uniq(nsLines.map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
931
999
|
const parts = line.split(/\s+/);
|
|
@@ -984,57 +1052,71 @@ function collectContacts(map) {
|
|
|
984
1052
|
const roles = [
|
|
985
1053
|
{
|
|
986
1054
|
role: "registrant",
|
|
987
|
-
|
|
1055
|
+
prefixes: [
|
|
1056
|
+
"registrant",
|
|
1057
|
+
"owner",
|
|
1058
|
+
"holder"
|
|
1059
|
+
]
|
|
988
1060
|
},
|
|
989
1061
|
{
|
|
990
1062
|
role: "admin",
|
|
991
|
-
|
|
1063
|
+
prefixes: ["admin", "administrative"]
|
|
992
1064
|
},
|
|
993
1065
|
{
|
|
994
1066
|
role: "tech",
|
|
995
|
-
|
|
1067
|
+
prefixes: ["tech", "technical"]
|
|
996
1068
|
},
|
|
997
1069
|
{
|
|
998
1070
|
role: "billing",
|
|
999
|
-
|
|
1071
|
+
prefixes: ["billing"]
|
|
1000
1072
|
},
|
|
1001
1073
|
{
|
|
1002
1074
|
role: "abuse",
|
|
1003
|
-
|
|
1075
|
+
prefixes: ["abuse"]
|
|
1004
1076
|
}
|
|
1005
1077
|
];
|
|
1006
1078
|
const contacts = [];
|
|
1007
1079
|
for (const r of roles) {
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
]
|
|
1013
|
-
const
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
`${
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
`${
|
|
1029
|
-
`${
|
|
1030
|
-
`${
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
`${
|
|
1034
|
-
`${
|
|
1035
|
-
`${
|
|
1036
|
-
|
|
1037
|
-
|
|
1080
|
+
const nameKeys = [];
|
|
1081
|
+
const orgKeys = [];
|
|
1082
|
+
const emailKeys = [];
|
|
1083
|
+
const phoneKeys = [];
|
|
1084
|
+
const faxKeys = [];
|
|
1085
|
+
const streetKeys = [];
|
|
1086
|
+
const cityKeys = [];
|
|
1087
|
+
const stateKeys = [];
|
|
1088
|
+
const postalCodeKeys = [];
|
|
1089
|
+
const countryKeys = [];
|
|
1090
|
+
for (const prefix of r.prefixes) {
|
|
1091
|
+
nameKeys.push(`${prefix} name`, `${prefix} contact name`, `${prefix}`);
|
|
1092
|
+
if (prefix === "registrant") nameKeys.push("registrant person");
|
|
1093
|
+
if (prefix === "owner") nameKeys.push("owner name");
|
|
1094
|
+
orgKeys.push(`${prefix} organization`, `${prefix} organisation`, `${prefix} org`);
|
|
1095
|
+
if (prefix === "registrant") {
|
|
1096
|
+
orgKeys.push("trading as");
|
|
1097
|
+
orgKeys.push("org");
|
|
1098
|
+
}
|
|
1099
|
+
if (prefix === "owner") orgKeys.push("owner orgname");
|
|
1100
|
+
emailKeys.push(`${prefix} email`, `${prefix} contact email`, `${prefix} e-mail`);
|
|
1101
|
+
phoneKeys.push(`${prefix} phone`, `${prefix} contact phone`, `${prefix} telephone`);
|
|
1102
|
+
faxKeys.push(`${prefix} fax`, `${prefix} facsimile`);
|
|
1103
|
+
streetKeys.push(`${prefix} street`, `${prefix} address`, `${prefix}'s address`);
|
|
1104
|
+
if (prefix === "owner") streetKeys.push("owner addr");
|
|
1105
|
+
cityKeys.push(`${prefix} city`);
|
|
1106
|
+
stateKeys.push(`${prefix} state`, `${prefix} province`, `${prefix} state/province`);
|
|
1107
|
+
postalCodeKeys.push(`${prefix} postal code`, `${prefix} postcode`, `${prefix} zip`);
|
|
1108
|
+
countryKeys.push(`${prefix} country`);
|
|
1109
|
+
}
|
|
1110
|
+
const name = anyValue(map, nameKeys);
|
|
1111
|
+
const org = anyValue(map, orgKeys);
|
|
1112
|
+
const email = anyValue(map, emailKeys);
|
|
1113
|
+
const phone = anyValue(map, phoneKeys);
|
|
1114
|
+
const fax = anyValue(map, faxKeys);
|
|
1115
|
+
const street = multi(map, streetKeys);
|
|
1116
|
+
const city = anyValue(map, cityKeys);
|
|
1117
|
+
const state = anyValue(map, stateKeys);
|
|
1118
|
+
const postalCode = anyValue(map, postalCodeKeys);
|
|
1119
|
+
const country = anyValue(map, countryKeys);
|
|
1038
1120
|
if (name || org || email || phone || street?.length) contacts.push({
|
|
1039
1121
|
type: r.role,
|
|
1040
1122
|
name: name || void 0,
|