@cleandns/whois-rdap 1.0.26 → 1.0.28

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 CHANGED
@@ -66,8 +66,8 @@ export async function whois(origDomain, options = { fetch: fetch, thinOnly: fals
66
66
  }
67
67
  const registrars = [];
68
68
  const resellers = [];
69
- async function extractRegistrarsAndResellers(response, url) {
70
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
69
+ async function extractRegistrarsAndResellers(response, url, isThick) {
70
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
71
71
  for (const ent of [
72
72
  ...(response.entities || []),
73
73
  response.entity ? { events: response.events, ...response.entity } : null,
@@ -84,13 +84,14 @@ export async function whois(origDomain, options = { fetch: fetch, thinOnly: fals
84
84
  ? ent.publicIDs
85
85
  : [[ent.publicIDs]]));
86
86
  }
87
- const reg = ((_b = pubIds.find((id) => id.type === "PANDI Registrar ID")) === null || _b === void 0 ? void 0 : _b.Identifier) ||
88
- ((_c = pubIds.find((id) => id.type === "PANDI Registrar ID")) === null || _c === void 0 ? void 0 : _c.identifier) ||
89
- ((_d = pubIds.find((id) => id.type === "IANA Registrar ID")) === null || _d === void 0 ? void 0 : _d.Identifier) ||
90
- ((_e = pubIds.find((id) => id.type === "IANA Registrar ID")) === null || _e === void 0 ? void 0 : _e.identifier);
87
+ const reg = ((_b = pubIds.find((id) => id.type === "PANDI Registrar ID")) === null || _b === void 0 ? void 0 : _b.Identifier)
88
+ || ((_c = pubIds.find((id) => id.type === "PANDI Registrar ID")) === null || _c === void 0 ? void 0 : _c.identifier)
89
+ || ((_d = pubIds.find((id) => id.type === "IANA Registrar ID")) === null || _d === void 0 ? void 0 : _d.Identifier)
90
+ || ((_e = pubIds.find((id) => id.type === "IANA Registrar ID")) === null || _e === void 0 ? void 0 : _e.identifier)
91
+ || pubIds.find((id) => id.type === "IANA Registrar ID");
91
92
  if (reg) {
92
93
  // console.log(ent.vcardArray);
93
- const id = reg;
94
+ const id = typeof reg === 'object' ? 0 : reg;
94
95
  const name = (parseInt(id) == id
95
96
  && ((_f = (await ianaIdToRegistrar(parseInt(id)))) === null || _f === void 0 ? void 0 : _f.name))
96
97
  || findInObject(ent.vcardArray, (el) => Array.isArray(el) && (el[0] === "fn" || el[0] === "org"), (el) => el[3], reg);
@@ -101,21 +102,50 @@ export async function whois(origDomain, options = { fetch: fetch, thinOnly: fals
101
102
  const events = ent.events || response.events || ent.enents || response.enents;
102
103
  registrars.push({ id, name, email, events });
103
104
  }
105
+ // handles .ca
106
+ else if (((_k = (_j = (_h = ent.vcardArray) === null || _h === void 0 ? void 0 : _h[1]) === null || _j === void 0 ? void 0 : _j[3]) === null || _k === void 0 ? void 0 : _k[3]) === 'registrar') {
107
+ const email = ((_l = [ent, ...(ent.entities || [])]
108
+ .filter((e) => e === null || e === void 0 ? void 0 : e.vcardArray)
109
+ .map((e) => findInObject(e.vcardArray, (el) => Array.isArray(el) && el[0] === "email", (el) => el[3], ""))
110
+ .filter(Boolean)) === null || _l === void 0 ? void 0 : _l[0]) || "";
111
+ registrars.push({ id: 0, name: ent.vcardArray[1][1][3], email, events: ent.events || response.events || ent.enents || response.enents });
112
+ }
113
+ // handles .si
114
+ else if ((_m = ent.vcardArray) === null || _m === void 0 ? void 0 : _m[1].find((el) => el[0] === 'fn')) {
115
+ const email = ((_o = [ent, ...(ent.entities || [])]
116
+ .filter((e) => e === null || e === void 0 ? void 0 : e.vcardArray)
117
+ .map((e) => findInObject(e.vcardArray, (el) => Array.isArray(el) && el[0] === "email", (el) => el[3], ""))
118
+ .filter(Boolean)) === null || _o === void 0 ? void 0 : _o[0]) || "";
119
+ if (ent.handle && ent.handle.toString().match(/^\d+$/)) {
120
+ const id = ent.handle;
121
+ const name = (parseInt(id) == id
122
+ && ((_p = (await ianaIdToRegistrar(parseInt(id)))) === null || _p === void 0 ? void 0 : _p.name))
123
+ || findInObject(ent.vcardArray, (el) => Array.isArray(el) && (el[0] === "fn" || el[0] === "org"), (el) => el[3], id);
124
+ registrars.push({ id, name, email, events: ent.events || response.events || ent.enents || response.enents });
125
+ }
126
+ else {
127
+ registrars.push({ id: ent.handle || 0, name: ent.vcardArray[1].find((el) => el[0] === 'fn')[3], email, events: ent.events || response.events || ent.enents || response.enents });
128
+ }
129
+ }
130
+ // handles .ar
131
+ else if (ent.handle) {
132
+ registrars.push({ id: 0, name: ent.handle, email: '', events: ent.events || response.events || ent.enents || response.enents });
133
+ }
104
134
  }
105
135
  if (domain.endsWith(".is") &&
106
- (((_h = ent.roles) === null || _h === void 0 ? void 0 : _h.includes("technical")) || ent.role === "technical")) {
136
+ (((_q = ent.roles) === null || _q === void 0 ? void 0 : _q.includes("technical")) || ent.role === "technical")) {
107
137
  const id = ent.handle;
108
138
  const name = (parseInt(id) == id
109
- && ((_j = (await ianaIdToRegistrar(parseInt(id)))) === null || _j === void 0 ? void 0 : _j.name))
139
+ && ((_r = (await ianaIdToRegistrar(parseInt(id)))) === null || _r === void 0 ? void 0 : _r.name))
110
140
  || findInObject(ent.vcardArray, (el) => Array.isArray(el) && (el[0] === "fn" || el[0] === "org"), (el) => el[3], id);
111
- const email = ((_k = [ent, ...(ent.entities || [])]
141
+ const email = ((_s = [ent, ...(ent.entities || [])]
112
142
  .filter((e) => e === null || e === void 0 ? void 0 : e.vcardArray)
113
143
  .map((e) => findInObject(e.vcardArray, (el) => Array.isArray(el) && el[0] === "email", (el) => el[3], ""))
114
- .filter(Boolean)) === null || _k === void 0 ? void 0 : _k[0]) || "";
144
+ .filter(Boolean)) === null || _s === void 0 ? void 0 : _s[0]) || "";
115
145
  const events = ent.events || response.events || ent.enents || response.enents;
116
146
  registrars.push({ id, name, email, events });
117
147
  }
118
- if ((((_l = ent.roles) === null || _l === void 0 ? void 0 : _l.includes("reseller")) || ent.role === "reseller") &&
148
+ if ((((_t = ent.roles) === null || _t === void 0 ? void 0 : _t.includes("reseller")) || ent.role === "reseller") &&
119
149
  ent.vcardArray) {
120
150
  // vcard objects can be unexpectedly and arbitrarily nested
121
151
  const name = findInObject(ent.vcardArray, (el) => Array.isArray(el) && (el[0] === "fn" || el[0] === "org"), (el) => el[3], "");
@@ -124,10 +154,10 @@ export async function whois(origDomain, options = { fetch: fetch, thinOnly: fals
124
154
  }
125
155
  }
126
156
  if (thickResponse && !thickResponse.errorCode) {
127
- await extractRegistrarsAndResellers(thickResponse, thickRdap);
157
+ await extractRegistrarsAndResellers(thickResponse, thickRdap, true);
128
158
  }
129
159
  if (thinResponse && !thinResponse.errorCode) {
130
- await extractRegistrarsAndResellers(thinResponse, thinRdap);
160
+ await extractRegistrarsAndResellers(thinResponse, thinRdap, false);
131
161
  }
132
162
  response.found = true;
133
163
  // registrar
package/dist/port43.js CHANGED
@@ -21,7 +21,7 @@ export function determinePort43Domain(actor) {
21
21
  return [actor, "", null];
22
22
  }
23
23
  export async function port43(actor) {
24
- var _a, _b, _c, _d;
24
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
25
25
  const [domain, tld, whoisServer] = determinePort43Domain(actor);
26
26
  const opts = whoisServer;
27
27
  const isWwww = opts === null || opts === void 0 ? void 0 : opts.url;
@@ -56,16 +56,19 @@ export async function port43(actor) {
56
56
  await promiseSocket.write(query);
57
57
  port43response = (await promiseSocket.readAll())
58
58
  .toString()
59
+ .replace(/\r/g, "")
59
60
  .replace(/^[ \t]+/gm, "");
60
61
  await promiseSocket.end();
61
62
  }
62
63
  }
63
64
  catch (error) {
65
+ console.warn(port, server, query);
64
66
  response.found = false;
65
67
  }
66
68
  if (!response.found) {
67
69
  return response;
68
70
  }
71
+ console.log(port43response);
69
72
  if (port43response.match(/^%*\s+(NOT FOUND|No match|NO OBJECT FOUND|No entries found|No Data Found|Domain is available for registration|No information available|Status: free)\b/im)) {
70
73
  response.found = false;
71
74
  return response;
@@ -76,33 +79,70 @@ export async function port43(actor) {
76
79
  await parser(port43response, response);
77
80
  }
78
81
  !response.registrar.name &&
79
- (m = port43response.match(/^(?:(?:Sponsoring )?Registrar(?: Name)?|registrar_name|registrar):[ \t]*(\S.+)/m)) &&
80
- (response.registrar.name = m[1]);
81
- !response.reseller &&
82
- (m = port43response.match(/^(?:Reseller(?: Name)?|reseller_name|reseller):[ \t]*(\S.+)/m)) &&
83
- (response.reseller = m[1]);
82
+ (m = port43response.match(/^registrar(?:-name)?\.*:[ \t]*(\S.+)\s*\(\s*http.*/m)) &&
83
+ (response.registrar.name = m[1].trim());
84
+ !response.registrar.name &&
85
+ (m = port43response.match(/^(?:(?:Sponsoring )?Registrar(?: Name)?|registrar\Wname|registrar|Registration service provider)\.*:[ \t]*(\S.+)/im)) &&
86
+ (response.registrar.name = m[1].trim());
87
+ !response.registrar.name &&
88
+ (m = port43response.match(/^REGISTRAR:[ \t]*\n(\S.+)/m)) &&
89
+ (response.registrar.name = m[1].trim());
90
+ !response.registrar.name &&
91
+ (m = port43response.match(/^\[Registrar\]\s*(?:[^\n:]+:.*\n)*Name:[ \t]*(\S.+)/m)) &&
92
+ (response.registrar.name = m[1].trim());
84
93
  !response.registrar.id &&
85
- (m = port43response.match(/^Registrar IANA ID:[ \t]*(\d+)/m)) &&
94
+ (m = port43response.match(/^Registrar IANA ID:[ \t]*(\d+)/im)) &&
86
95
  (response.registrar.id = parseInt(m[1] || "0"));
96
+ !response.reseller &&
97
+ (m = port43response.match(/^(?:Reseller(?: Name)?|reseller_name|reseller):[ \t]*(\S.+)/im)) &&
98
+ (response.reseller = m[1].trim());
87
99
  !response.ts.updated &&
88
- (m = port43response.match(/^(?:Last Modified|Updated Date|domain_datelastmodified|last-update):[ \t]*(\S.+)/m)) &&
89
- (response.ts.updated = new Date(m[1]) || null);
100
+ (m = port43response.match(/^(?:Last Modified|Updated Date|Last updated on|domain_datelastmodified|last-update|modified|last modified)\.*:[ \t]*(\S.+)/im)) &&
101
+ (response.ts.updated = new Date(reformatDate(m[1])) || null);
102
+ !response.ts.updated &&
103
+ (m = port43response.match(/^\[Last Updated?\][ \t]+(\S.+)/im)) &&
104
+ (response.ts.updated = new Date(reformatDate(m[1])) || null);
105
+ !response.ts.created &&
106
+ (m = port43response.match(/^(?:Creation Date|domain_dateregistered|Registered|created|Created date|Domain created)\.*:[ \t]*(\S.+)/im)) &&
107
+ (response.ts.created = new Date(reformatDate(m[1])) || null);
90
108
  !response.ts.created &&
91
- (m = port43response.match(/^(?:Creation Date|domain_dateregistered|created):[ \t]*(\S.+)/m)) &&
92
- (response.ts.created = new Date(m[1]) || null);
109
+ (m = port43response.match(/^(?:Record created on |\[(?:Created on|Registered Date)\][ \t]+)(\S.+)/im)) &&
110
+ (response.ts.created = new Date(reformatDate(m[1])) || null);
93
111
  !response.ts.expires &&
94
- (m = port43response.match(/^(?:(?:Registry )?Expiry Date):[ \t]*(\S.+)/m)) &&
95
- (response.ts.expires = new Date(m[1]) || null);
96
- !((_c = response.status) === null || _c === void 0 ? void 0 : _c.length) && (m = port43response.match(/^(?:Status|Domain Status|status):.*/gm)) &&
112
+ (m = port43response.match(/^(?:(?:Registry )?Expiry Date|Expiration date|expires?|Exp date|paid-till|free-date|renewal date)\.*:[ \t]*(\S.+)/im)) &&
113
+ (response.ts.expires = new Date(reformatDate(m[1])) || null);
114
+ !response.ts.expires &&
115
+ (m = port43response.match(/^(?:Record expires on |\[Expires on\][ \t]+)(\S.+)/im)) &&
116
+ (response.ts.expires = new Date(reformatDate(m[1])) || null);
117
+ !((_c = response.status) === null || _c === void 0 ? void 0 : _c.length) && (m = port43response.match(/^(?:Status|Domain [Ss]tatus|status)\.*:.*/gm)) &&
118
+ m.forEach((s) => {
119
+ let m;
120
+ (m = s.match(/^(?:Status|Domain [Ss]tatus|status)\.*:[ \t]*(?:<a[^>]*>)?(\S+)/m)) && m[1].split(/\s*,\s*/).map((status) => response.status.push(normalizeWhoisStatus(status)));
121
+ });
122
+ !((_d = response.status) === null || _d === void 0 ? void 0 : _d.length) && (m = port43response.match(/^Domain status : ((?:\S+ -\s*)+)/m)) &&
123
+ ((_e = m[1].match(/\w+/g)) === null || _e === void 0 ? void 0 : _e.map((status) => response.status.push(normalizeWhoisStatus(status))));
124
+ !((_f = response.nameservers) === null || _f === void 0 ? void 0 : _f.length) && (m = port43response.match(/^(?:Hostname|DNS|Name Server|ns_name_\d+|name?server|nserver|(?:primary|secondary) server)\.*:.*/gmi)) &&
97
125
  m.forEach((s) => {
98
126
  let m;
99
- (m = s.match(/^(?:Status|Domain Status|status):[ \t]*(?:<a[^>]*>)?(\S+)/m)) && response.status.push(normalizeWhoisStatus(m[1]));
127
+ (m = s.match(/^(?:Hostname|DNS|Name Server|ns_name_\d+|name?server|nserver|(?:primary|secondary) server)\.*:[ \t]*(\S+)/mi)) && response.nameservers.push(m[1].toLowerCase());
100
128
  });
101
- !((_d = response.nameservers) === null || _d === void 0 ? void 0 : _d.length) && (m = port43response.match(/^(?:Name Server|ns_name_\d+|namserver|nserver):.*/gm)) &&
129
+ !((_g = response.nameservers) === null || _g === void 0 ? void 0 : _g.length) && (m = port43response.match(/^(?:\w. )?\[Name Server\][ \t]*\S+/gmi)) &&
102
130
  m.forEach((s) => {
103
131
  let m;
104
- (m = s.match(/^(?:Name Server|ns_name_\d+|namserver|nserver):[ \t]*(\S+)/m)) && response.nameservers.push(m[1].toLowerCase());
132
+ (m = s.match(/\[Name Server\][ \t]*(\S+)/mi)) && response.nameservers.push(m[1].toLowerCase());
133
+ });
134
+ !((_h = response.nameservers) === null || _h === void 0 ? void 0 : _h.length) && (m = port43response.match(/^DNS servers\s*((?:Name\.+:.+\n)+)/mi)) &&
135
+ ((_j = m[1].match(/[^.\s]+(?:\.[^.\s]+)+/g)) === null || _j === void 0 ? void 0 : _j.forEach((s) => {
136
+ response.nameservers.push(s.toLowerCase());
137
+ }));
138
+ !((_k = response.nameservers) === null || _k === void 0 ? void 0 : _k.length) && (m = port43response.match(/^Domain servers in listed order:\s*((?:\S+[ \t]*\n)+)/mi)) &&
139
+ m[1].trim().split(/\s+/).forEach((s) => {
140
+ response.nameservers.push(s.toLowerCase());
105
141
  });
142
+ !((_l = response.nameservers) === null || _l === void 0 ? void 0 : _l.length) && (m = port43response.match(/^nameservers:[ \t]*(\S+(?:[ \t]*\n\S+)+)/m)) &&
143
+ ((_m = m[1].match(/[^.\s]+(?:\.[^.\s]+)+/g)) === null || _m === void 0 ? void 0 : _m.forEach((s) => {
144
+ response.nameservers.push(s.toLowerCase());
145
+ }));
106
146
  if (response.ts.created && !response.ts.created.valueOf())
107
147
  response.ts.created = null;
108
148
  if (response.ts.updated && !response.ts.updated.valueOf())
@@ -135,3 +175,23 @@ export async function port43(actor) {
135
175
  }
136
176
  return response;
137
177
  }
178
+ function reformatDate(date) {
179
+ if (date.match(/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d \(UTC[+-]\d+\)$/)) {
180
+ return date;
181
+ }
182
+ if (date.match(/CLST$/)) {
183
+ return date.replace(/CLST$/, "-0400");
184
+ }
185
+ if (date.match(/CLT$/)) {
186
+ return date.replace(/CLT$/, "-0300");
187
+ }
188
+ const dmy = date.match(/^(\d\d)\W(\d\d)\W(\d\d\d\d)(\b.*)$/);
189
+ if (dmy) {
190
+ return `${dmy[3]}-${dmy[2]}-${dmy[1]}${dmy[4]}`;
191
+ }
192
+ const ymd = date.match(/^(\d\d\d\d)(\d\d)(\d\d)\b/);
193
+ if (ymd) {
194
+ return `${ymd[1]}-${ymd[2]}-${ymd[3]}`;
195
+ }
196
+ return date;
197
+ }
@@ -21,6 +21,9 @@ export const port43parsers = {
21
21
  record.nameservers.push(m[1].toLowerCase());
22
22
  });
23
23
  },
24
+ gg(response, record) {
25
+ // TODO: ebio.gg
26
+ },
24
27
  nl(response, record) {
25
28
  let m;
26
29
  (m = response.match(/^Registrar:\s+(\S[^\n]*)/m)) &&
@@ -607,6 +610,7 @@ export const port43servers = {
607
610
  as: "whois.nic.as",
608
611
  "priv.at": "whois.nic.priv.at",
609
612
  at: "whois.nic.at",
613
+ "*.at": "whois.nic.at",
610
614
  "*.au": "whois.auda.org.au",
611
615
  au: "whois.auda.org.au",
612
616
  aw: "whois.nic.aw",
@@ -669,6 +673,7 @@ export const port43servers = {
669
673
  },
670
674
  dm: "whois.nic.dm",
671
675
  do: "whois.nic.do",
676
+ "*.do": "whois.nic.do",
672
677
  dz: "whois.nic.dz",
673
678
  ec: "whois.nic.ec",
674
679
  ee: "whois.tld.ee",
@@ -708,17 +713,21 @@ export const port43servers = {
708
713
  hn: "whois.nic.hn",
709
714
  hr: "whois.dns.hr",
710
715
  ht: "whois.nic.ht",
716
+ "*.ht": "whois.nic.ht",
711
717
  hu: "whois.nic.hu",
712
718
  id: "whois.pandi.or.id",
713
719
  ie: "whois.domainregistry.ie",
714
720
  il: "whois.isoc.org.il",
721
+ "*.il": "whois.isoc.org.il",
715
722
  im: "whois.nic.im",
716
723
  in: "whois.registry.in",
724
+ "*.in": "whois.registry.in",
717
725
  io: "whois.nic.io",
718
726
  iq: "whois.cmc.iq",
719
727
  ir: "whois.nic.ir",
720
728
  is: "whois.isnic.is",
721
729
  it: "whois.nic.it",
730
+ "*.it": "whois.nic.it",
722
731
  je: "whois.je",
723
732
  jm: null,
724
733
  jo: null,
@@ -726,7 +735,12 @@ export const port43servers = {
726
735
  host: "whois.jprs.jp",
727
736
  query: "$addr/e\r\n",
728
737
  },
738
+ "*.jp": {
739
+ host: "whois.jprs.jp",
740
+ query: "$addr/e\r\n",
741
+ },
729
742
  ke: "whois.kenic.or.ke",
743
+ "*.ke": "whois.kenic.or.ke",
730
744
  kg: "whois.domain.kg",
731
745
  kh: null,
732
746
  ki: "whois.nic.ki",
@@ -734,6 +748,7 @@ export const port43servers = {
734
748
  kn: "whois.nic.kn",
735
749
  kp: null,
736
750
  kr: "whois.kr",
751
+ "*.kr": "whois.kr",
737
752
  kw: null,
738
753
  ky: "whois.kyregistry.ky",
739
754
  kz: "whois.nic.kz",
@@ -746,6 +761,7 @@ export const port43servers = {
746
761
  lt: "whois.domreg.lt",
747
762
  lu: "whois.dns.lu",
748
763
  lv: "whois.nic.lv",
764
+ "*.lv": "whois.nic.lv",
749
765
  ly: "whois.nic.ly",
750
766
  ma: "whois.iam.net.ma",
751
767
  mc: null,
@@ -768,13 +784,16 @@ export const port43servers = {
768
784
  mv: null,
769
785
  mw: "whois.nic.mw",
770
786
  mx: "whois.mx",
787
+ "*.mx": "whois.mx",
771
788
  my: "whois.mynic.my",
789
+ "*.my": "whois.mynic.my",
772
790
  mz: "whois.nic.mz",
773
791
  na: "whois.na-nic.com.na",
774
792
  nc: "whois.nc",
775
793
  ne: null,
776
794
  nf: "whois.nic.nf",
777
795
  ng: "whois.nic.net.ng",
796
+ "*.ng": "whois.nic.net.ng",
778
797
  ni: null,
779
798
  nl: "whois.domain-registry.nl",
780
799
  no: {
@@ -785,9 +804,11 @@ export const port43servers = {
785
804
  nr: null,
786
805
  nu: "whois.iis.nu",
787
806
  nz: "whois.srs.net.nz",
807
+ "*.nz": "whois.srs.net.nz",
788
808
  om: "whois.registry.om",
789
809
  pa: null,
790
810
  pe: "kero.yachay.pe",
811
+ "*.pe": "kero.yachay.pe",
791
812
  pf: "whois.registry.pf",
792
813
  pg: null,
793
814
  ph: null,
@@ -799,6 +820,7 @@ export const port43servers = {
799
820
  pr: "whois.nic.pr",
800
821
  ps: "whois.pnina.ps",
801
822
  pt: "whois.dns.pt",
823
+ "*.pt": "whois.dns.pt",
802
824
  pw: "whois.nic.pw",
803
825
  py: null,
804
826
  qa: "whois.registry.qa",
@@ -809,6 +831,7 @@ export const port43servers = {
809
831
  ru: "whois.tcinet.ru",
810
832
  rw: "whois.ricta.org.rw",
811
833
  sa: "whois.nic.net.sa",
834
+ "*.sa": "whois.nic.net.sa",
812
835
  sb: "whois.nic.sb",
813
836
  sc: "whois.afilias-grs.info",
814
837
  sd: null,
@@ -835,17 +858,21 @@ export const port43servers = {
835
858
  tf: "whois.nic.tf",
836
859
  tg: "whois.nic.tg",
837
860
  th: "whois.thnic.co.th",
861
+ "*.th": "whois.thnic.co.th",
838
862
  tj: null,
839
863
  tk: "whois.dot.tk",
840
864
  tl: "whois.nic.tl",
841
865
  tm: "whois.nic.tm",
842
866
  tn: "whois.ati.tn",
867
+ "*.tn": "whois.ati.tn",
843
868
  to: "whois.tonic.to",
844
869
  tp: null,
845
870
  tr: "whois.nic.tr",
871
+ "*.tr": "whois.nic.tr",
846
872
  tt: null,
847
873
  tv: "tvwhois.verisign-grs.com",
848
874
  tw: "whois.twnic.net.tw",
875
+ "*.tw": "whois.twnic.net.tw",
849
876
  tz: "whois.tznic.or.tz",
850
877
  "biz.ua": "whois.biz.ua",
851
878
  "co.ua": "whois.co.ua",
@@ -873,6 +900,7 @@ export const port43servers = {
873
900
  va: null,
874
901
  vc: "whois.afilias-grs.info",
875
902
  ve: "whois.nic.ve",
903
+ "*.ve": "whois.nic.ve",
876
904
  vg: "whois.nic.vg",
877
905
  vi: null,
878
906
  vn: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleandns/whois-rdap",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -87,7 +87,7 @@ export async function whois(
87
87
  const registrars: any[] = [];
88
88
  const resellers: any[] = [];
89
89
 
90
- async function extractRegistrarsAndResellers(response: any, url: string) {
90
+ async function extractRegistrarsAndResellers(response: any, url: string, isThick?: boolean) {
91
91
  for (const ent of [
92
92
  ...(response.entities || []),
93
93
  response.entity ? { events: response.events, ...response.entity } : null,
@@ -109,27 +109,26 @@ export async function whois(
109
109
  );
110
110
  }
111
111
  const reg =
112
- pubIds.find((id: any) => id.type === "PANDI Registrar ID")
113
- ?.Identifier ||
114
- pubIds.find((id: any) => id.type === "PANDI Registrar ID")
115
- ?.identifier ||
116
- pubIds.find((id: any) => id.type === "IANA Registrar ID")
117
- ?.Identifier ||
118
- pubIds.find((id: any) => id.type === "IANA Registrar ID")?.identifier;
112
+ pubIds.find((id: any) => id.type === "PANDI Registrar ID")?.Identifier
113
+ || pubIds.find((id: any) => id.type === "PANDI Registrar ID")?.identifier
114
+ || pubIds.find((id: any) => id.type === "IANA Registrar ID")?.Identifier
115
+ || pubIds.find((id: any) => id.type === "IANA Registrar ID")?.identifier
116
+ || pubIds.find((id: any) => id.type === "IANA Registrar ID")
117
+ ;
119
118
 
120
119
  if (reg) {
121
120
  // console.log(ent.vcardArray);
122
- const id = reg;
121
+ const id = typeof reg === 'object' ? 0 : reg;
123
122
  const name =
124
123
  (parseInt(id) == id
125
124
  && (await ianaIdToRegistrar(parseInt(id)))?.name)
126
- || findInObject(
127
- ent.vcardArray,
128
- (el: any) =>
129
- Array.isArray(el) && (el[0] === "fn" || el[0] === "org"),
130
- (el: any[]) => el[3],
131
- reg
132
- );
125
+ || findInObject(
126
+ ent.vcardArray,
127
+ (el: any) =>
128
+ Array.isArray(el) && (el[0] === "fn" || el[0] === "org"),
129
+ (el: any[]) => el[3],
130
+ reg
131
+ );
133
132
  const email =
134
133
  [ent, ...(ent.entities || [])]
135
134
  .filter((e) => e?.vcardArray)
@@ -147,6 +146,61 @@ export async function whois(
147
146
  ent.events || response.events || ent.enents || response.enents;
148
147
  registrars.push({ id, name, email, events });
149
148
  }
149
+ // handles .ca
150
+ else if (ent.vcardArray?.[1]?.[3]?.[3] === 'registrar') {
151
+ const email =
152
+ [ent, ...(ent.entities || [])]
153
+ .filter((e) => e?.vcardArray)
154
+ .map((e) =>
155
+ findInObject(
156
+ e.vcardArray,
157
+ (el: any) => Array.isArray(el) && el[0] === "email",
158
+ (el: any[]) => el[3],
159
+ ""
160
+ )
161
+ )
162
+ .filter(Boolean)?.[0] || "";
163
+
164
+ registrars.push({ id: 0, name: ent.vcardArray[1][1][3], email, events: ent.events || response.events || ent.enents || response.enents });
165
+ }
166
+ // handles .si
167
+ else if (ent.vcardArray?.[1].find((el: string[]) => el[0] === 'fn')) {
168
+ const email =
169
+ [ent, ...(ent.entities || [])]
170
+ .filter((e) => e?.vcardArray)
171
+ .map((e) =>
172
+ findInObject(
173
+ e.vcardArray,
174
+ (el: any) => Array.isArray(el) && el[0] === "email",
175
+ (el: any[]) => el[3],
176
+ ""
177
+ )
178
+ )
179
+ .filter(Boolean)?.[0] || "";
180
+
181
+ if (ent.handle && ent.handle.toString().match(/^\d+$/)) {
182
+ const id = ent.handle;
183
+ const name =
184
+ (parseInt(id) == id
185
+ && (await ianaIdToRegistrar(parseInt(id)))?.name)
186
+ || findInObject(
187
+ ent.vcardArray,
188
+ (el: any) =>
189
+ Array.isArray(el) && (el[0] === "fn" || el[0] === "org"),
190
+ (el: any[]) => el[3],
191
+ id
192
+ );
193
+ registrars.push({ id, name, email, events: ent.events || response.events || ent.enents || response.enents });
194
+ }
195
+ else {
196
+ registrars.push({ id: ent.handle || 0, name: ent.vcardArray[1].find((el: string[]) => el[0] === 'fn')[3], email, events: ent.events || response.events || ent.enents || response.enents });
197
+ }
198
+ }
199
+ // handles .ar
200
+ else if (ent.handle) {
201
+ registrars.push({ id: 0, name: ent.handle, email: '', events: ent.events || response.events || ent.enents || response.enents });
202
+ }
203
+
150
204
  }
151
205
 
152
206
  if (
@@ -157,13 +211,13 @@ export async function whois(
157
211
  const name =
158
212
  (parseInt(id) == id
159
213
  && (await ianaIdToRegistrar(parseInt(id)))?.name)
160
- || findInObject(
161
- ent.vcardArray,
162
- (el: any) =>
163
- Array.isArray(el) && (el[0] === "fn" || el[0] === "org"),
164
- (el: any[]) => el[3],
165
- id
166
- );
214
+ || findInObject(
215
+ ent.vcardArray,
216
+ (el: any) =>
217
+ Array.isArray(el) && (el[0] === "fn" || el[0] === "org"),
218
+ (el: any[]) => el[3],
219
+ id
220
+ );
167
221
  const email =
168
222
  [ent, ...(ent.entities || [])]
169
223
  .filter((e) => e?.vcardArray)
@@ -199,10 +253,10 @@ export async function whois(
199
253
  }
200
254
 
201
255
  if (thickResponse && !thickResponse.errorCode) {
202
- await extractRegistrarsAndResellers(thickResponse, thickRdap);
256
+ await extractRegistrarsAndResellers(thickResponse, thickRdap, true);
203
257
  }
204
258
  if (thinResponse && !thinResponse.errorCode) {
205
- await extractRegistrarsAndResellers(thinResponse, thinRdap);
259
+ await extractRegistrarsAndResellers(thinResponse, thinRdap, false);
206
260
  }
207
261
 
208
262
  response.found = true;
@@ -232,7 +286,7 @@ export async function whois(
232
286
  // status
233
287
  const statusThin = findStatus(thinResponse?.status || [], domain);
234
288
  const statusThick = findStatus(thickResponse?.status || [], domain);
235
- response.status = [...new Set ([...statusThin, ...statusThick])];
289
+ response.status = [...new Set([...statusThin, ...statusThick])];
236
290
 
237
291
  response.statusDelta = [];
238
292
  for (const status of response.status) {
@@ -263,8 +317,8 @@ function findStatus(statuses: string | string[], domain: string): string[] {
263
317
  return (Array.isArray(statuses)
264
318
  ? statuses
265
319
  : statuses && typeof statuses === "object"
266
- ? Object.keys(statuses)
267
- : (statuses || "").trim().split(/\s*,\s*/)
320
+ ? Object.keys(statuses)
321
+ : (statuses || "").trim().split(/\s*,\s*/)
268
322
  ).map((status) => normalizeWhoisStatus(status));
269
323
  }
270
324
 
package/src/port43.ts CHANGED
@@ -66,10 +66,12 @@ export async function port43(actor: string): Promise<WhoisResponse> {
66
66
  await promiseSocket.write(query);
67
67
  port43response = (await promiseSocket.readAll())!
68
68
  .toString()
69
+ .replace(/\r/g, "")
69
70
  .replace(/^[ \t]+/gm, "");
70
71
  await promiseSocket.end();
71
72
  }
72
- } catch (error) {
73
+ } catch (error: any) {
74
+ console.warn(port, server, query);
73
75
  response.found = false;
74
76
  }
75
77
 
@@ -77,6 +79,8 @@ export async function port43(actor: string): Promise<WhoisResponse> {
77
79
  return response;
78
80
  }
79
81
 
82
+ console.log(port43response);
83
+
80
84
  if (
81
85
  port43response.match(
82
86
  /^%*\s+(NOT FOUND|No match|NO OBJECT FOUND|No entries found|No Data Found|Domain is available for registration|No information available|Status: free)\b/im
@@ -91,53 +95,119 @@ export async function port43(actor: string): Promise<WhoisResponse> {
91
95
  const parser = port43parsers[tld] || Object.entries(port43parsers).find(([t]) => tld.endsWith('.' + t))?.[1];
92
96
 
93
97
  if (parser) {
94
- await parser(port43response, response);
98
+ await parser(port43response, response);
95
99
  }
96
100
 
97
101
  !response.registrar.name &&
98
102
  (m = port43response.match(
99
- /^(?:(?:Sponsoring )?Registrar(?: Name)?|registrar_name|registrar):[ \t]*(\S.+)/m
103
+ /^registrar(?:-name)?\.*:[ \t]*(\S.+)\s*\(\s*http.*/m
100
104
  )) &&
101
- (response.registrar.name = m[1]);
102
- !response.reseller &&
105
+ (response.registrar.name = m[1].trim());
106
+ !response.registrar.name &&
107
+ (m = port43response.match(
108
+ /^(?:(?:Sponsoring )?Registrar(?: Name)?|registrar\Wname|registrar|Registration service provider)\.*:[ \t]*(\S.+)/im
109
+ )) &&
110
+ (response.registrar.name = m[1].trim());
111
+ !response.registrar.name &&
112
+ (m = port43response.match(
113
+ /^REGISTRAR:[ \t]*\n(\S.+)/m
114
+ )) &&
115
+ (response.registrar.name = m[1].trim());
116
+ !response.registrar.name &&
103
117
  (m = port43response.match(
104
- /^(?:Reseller(?: Name)?|reseller_name|reseller):[ \t]*(\S.+)/m
118
+ /^\[Registrar\]\s*(?:[^\n:]+:.*\n)*Name:[ \t]*(\S.+)/m
105
119
  )) &&
106
- (response.reseller = m[1]);
120
+ (response.registrar.name = m[1].trim());
121
+
107
122
  !response.registrar.id &&
108
- (m = port43response.match(/^Registrar IANA ID:[ \t]*(\d+)/m)) &&
123
+ (m = port43response.match(/^Registrar IANA ID:[ \t]*(\d+)/im)) &&
109
124
  (response.registrar.id = parseInt(m[1] || "0"));
125
+
126
+ !response.reseller &&
127
+ (m = port43response.match(
128
+ /^(?:Reseller(?: Name)?|reseller_name|reseller):[ \t]*(\S.+)/im
129
+ )) &&
130
+ (response.reseller = m[1].trim());
131
+
132
+ !response.ts.updated &&
133
+ (m = port43response.match(
134
+ /^(?:Last Modified|Updated Date|Last updated on|domain_datelastmodified|last-update|modified|last modified)\.*:[ \t]*(\S.+)/im
135
+ )) &&
136
+ (response.ts.updated = new Date(reformatDate(m[1])) || null);
110
137
  !response.ts.updated &&
111
138
  (m = port43response.match(
112
- /^(?:Last Modified|Updated Date|domain_datelastmodified|last-update):[ \t]*(\S.+)/m
139
+ /^\[Last Updated?\][ \t]+(\S.+)/im
113
140
  )) &&
114
- (response.ts.updated = new Date(m[1]) || null);
141
+ (response.ts.updated = new Date(reformatDate(m[1])) || null);
142
+
115
143
  !response.ts.created &&
116
144
  (m = port43response.match(
117
- /^(?:Creation Date|domain_dateregistered|created):[ \t]*(\S.+)/m
145
+ /^(?:Creation Date|domain_dateregistered|Registered|created|Created date|Domain created)\.*:[ \t]*(\S.+)/im
118
146
  )) &&
119
- (response.ts.created = new Date(m[1]) || null);
147
+ (response.ts.created = new Date(reformatDate(m[1])) || null);
148
+ !response.ts.created &&
149
+ (m = port43response.match(
150
+ /^(?:Record created on |\[(?:Created on|Registered Date)\][ \t]+)(\S.+)/im
151
+ )) &&
152
+ (response.ts.created = new Date(reformatDate(m[1])) || null);
153
+
154
+ !response.ts.expires &&
155
+ (m = port43response.match(
156
+ /^(?:(?:Registry )?Expiry Date|Expiration date|expires?|Exp date|paid-till|free-date|renewal date)\.*:[ \t]*(\S.+)/im
157
+ )) &&
158
+ (response.ts.expires = new Date(reformatDate(m[1])) || null);
120
159
  !response.ts.expires &&
121
160
  (m = port43response.match(
122
- /^(?:(?:Registry )?Expiry Date):[ \t]*(\S.+)/m
161
+ /^(?:Record expires on |\[Expires on\][ \t]+)(\S.+)/im
123
162
  )) &&
124
- (response.ts.expires = new Date(m[1]) || null);
125
- !response.status?.length && (m = port43response.match(/^(?:Status|Domain Status|status):.*/gm)) &&
163
+ (response.ts.expires = new Date(reformatDate(m[1])) || null);
164
+
165
+ !response.status?.length && (m = port43response.match(/^(?:Status|Domain [Ss]tatus|status)\.*:.*/gm)) &&
126
166
  m.forEach((s) => {
127
167
  let m;
128
168
  (m = s.match(
129
- /^(?:Status|Domain Status|status):[ \t]*(?:<a[^>]*>)?(\S+)/m
130
- )) && response.status.push(normalizeWhoisStatus(m[1]));
169
+ /^(?:Status|Domain [Ss]tatus|status)\.*:[ \t]*(?:<a[^>]*>)?(\S+)/m
170
+ )) && m[1].split(/\s*,\s*/).map((status) => response.status.push(normalizeWhoisStatus(status)));
171
+ });
172
+ !response.status?.length && (m = port43response.match(/^Domain status : ((?:\S+ -\s*)+)/m)) &&
173
+ m[1].match(/\w+/g)?.map((status) => response.status.push(normalizeWhoisStatus(status)));
174
+
175
+ !response.nameservers?.length && (m = port43response.match(
176
+ /^(?:Hostname|DNS|Name Server|ns_name_\d+|name?server|nserver|(?:primary|secondary) server)\.*:.*/gmi
177
+ )) &&
178
+ m.forEach((s) => {
179
+ let m;
180
+ (m = s.match(
181
+ /^(?:Hostname|DNS|Name Server|ns_name_\d+|name?server|nserver|(?:primary|secondary) server)\.*:[ \t]*(\S+)/mi
182
+ )) && response.nameservers.push(m[1].toLowerCase());
131
183
  });
132
184
  !response.nameservers?.length && (m = port43response.match(
133
- /^(?:Name Server|ns_name_\d+|namserver|nserver):.*/gm
185
+ /^(?:\w. )?\[Name Server\][ \t]*\S+/gmi
134
186
  )) &&
135
187
  m.forEach((s) => {
136
188
  let m;
137
189
  (m = s.match(
138
- /^(?:Name Server|ns_name_\d+|namserver|nserver):[ \t]*(\S+)/m
190
+ /\[Name Server\][ \t]*(\S+)/mi
139
191
  )) && response.nameservers.push(m[1].toLowerCase());
140
192
  });
193
+ !response.nameservers?.length && (m = port43response.match(
194
+ /^DNS servers\s*((?:Name\.+:.+\n)+)/mi
195
+ )) &&
196
+ m[1].match(/[^.\s]+(?:\.[^.\s]+)+/g)?.forEach((s) => {
197
+ response.nameservers.push(s.toLowerCase());
198
+ });
199
+ !response.nameservers?.length && (m = port43response.match(
200
+ /^Domain servers in listed order:\s*((?:\S+[ \t]*\n)+)/mi
201
+ )) &&
202
+ m[1].trim().split(/\s+/).forEach((s) => {
203
+ response.nameservers.push(s.toLowerCase());
204
+ });
205
+ !response.nameservers?.length && (m = port43response.match(
206
+ /^nameservers:[ \t]*(\S+(?:[ \t]*\n\S+)+)/m
207
+ )) &&
208
+ m[1].match(/[^.\s]+(?:\.[^.\s]+)+/g)?.forEach((s) => {
209
+ response.nameservers.push(s.toLowerCase());
210
+ });
141
211
 
142
212
  if (response.ts.created && !response.ts.created.valueOf()) response.ts.created = null;
143
213
  if (response.ts.updated && !response.ts.updated.valueOf()) response.ts.updated = null;
@@ -176,3 +246,28 @@ export async function port43(actor: string): Promise<WhoisResponse> {
176
246
 
177
247
  return response;
178
248
  }
249
+
250
+
251
+ function reformatDate(date: string) {
252
+ if (date.match(/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d \(UTC[+-]\d+\)$/)) {
253
+ return date;
254
+ }
255
+ if (date.match(/CLST$/)) {
256
+ return date.replace(/CLST$/, "-0400");
257
+ }
258
+ if (date.match(/CLT$/)) {
259
+ return date.replace(/CLT$/, "-0300");
260
+ }
261
+
262
+ const dmy = date.match(/^(\d\d)\W(\d\d)\W(\d\d\d\d)(\b.*)$/);
263
+ if (dmy) {
264
+ return `${dmy[3]}-${dmy[2]}-${dmy[1]}${dmy[4]}`;
265
+ }
266
+
267
+ const ymd = date.match(/^(\d\d\d\d)(\d\d)(\d\d)\b/);
268
+ if (ymd) {
269
+ return `${ymd[1]}-${ymd[2]}-${ymd[3]}`;
270
+ }
271
+
272
+ return date;
273
+ }
@@ -40,6 +40,10 @@ export const port43parsers: Record<
40
40
  });
41
41
  },
42
42
 
43
+ gg(response, record) {
44
+ // TODO: ebio.gg
45
+ },
46
+
43
47
  nl(response, record) {
44
48
  let m;
45
49
 
@@ -658,6 +662,7 @@ export const port43servers: Record<string, any> = {
658
662
  as: "whois.nic.as",
659
663
  "priv.at": "whois.nic.priv.at",
660
664
  at: "whois.nic.at",
665
+ "*.at": "whois.nic.at",
661
666
  "*.au": "whois.auda.org.au",
662
667
  au: "whois.auda.org.au",
663
668
  aw: "whois.nic.aw",
@@ -720,6 +725,7 @@ export const port43servers: Record<string, any> = {
720
725
  },
721
726
  dm: "whois.nic.dm",
722
727
  do: "whois.nic.do",
728
+ "*.do": "whois.nic.do",
723
729
  dz: "whois.nic.dz",
724
730
  ec: "whois.nic.ec",
725
731
  ee: "whois.tld.ee",
@@ -759,17 +765,21 @@ export const port43servers: Record<string, any> = {
759
765
  hn: "whois.nic.hn",
760
766
  hr: "whois.dns.hr",
761
767
  ht: "whois.nic.ht",
768
+ "*.ht": "whois.nic.ht",
762
769
  hu: "whois.nic.hu",
763
770
  id: "whois.pandi.or.id",
764
771
  ie: "whois.domainregistry.ie",
765
772
  il: "whois.isoc.org.il",
773
+ "*.il": "whois.isoc.org.il",
766
774
  im: "whois.nic.im",
767
775
  in: "whois.registry.in",
776
+ "*.in": "whois.registry.in",
768
777
  io: "whois.nic.io",
769
778
  iq: "whois.cmc.iq",
770
779
  ir: "whois.nic.ir",
771
780
  is: "whois.isnic.is",
772
781
  it: "whois.nic.it",
782
+ "*.it": "whois.nic.it",
773
783
  je: "whois.je",
774
784
  jm: null,
775
785
  jo: null,
@@ -777,7 +787,12 @@ export const port43servers: Record<string, any> = {
777
787
  host: "whois.jprs.jp",
778
788
  query: "$addr/e\r\n",
779
789
  },
790
+ "*.jp": {
791
+ host: "whois.jprs.jp",
792
+ query: "$addr/e\r\n",
793
+ },
780
794
  ke: "whois.kenic.or.ke",
795
+ "*.ke": "whois.kenic.or.ke",
781
796
  kg: "whois.domain.kg",
782
797
  kh: null,
783
798
  ki: "whois.nic.ki",
@@ -785,6 +800,7 @@ export const port43servers: Record<string, any> = {
785
800
  kn: "whois.nic.kn",
786
801
  kp: null,
787
802
  kr: "whois.kr",
803
+ "*.kr": "whois.kr",
788
804
  kw: null,
789
805
  ky: "whois.kyregistry.ky",
790
806
  kz: "whois.nic.kz",
@@ -797,6 +813,7 @@ export const port43servers: Record<string, any> = {
797
813
  lt: "whois.domreg.lt",
798
814
  lu: "whois.dns.lu",
799
815
  lv: "whois.nic.lv",
816
+ "*.lv": "whois.nic.lv",
800
817
  ly: "whois.nic.ly",
801
818
  ma: "whois.iam.net.ma",
802
819
  mc: null,
@@ -819,13 +836,16 @@ export const port43servers: Record<string, any> = {
819
836
  mv: null,
820
837
  mw: "whois.nic.mw",
821
838
  mx: "whois.mx",
839
+ "*.mx": "whois.mx",
822
840
  my: "whois.mynic.my",
841
+ "*.my": "whois.mynic.my",
823
842
  mz: "whois.nic.mz",
824
843
  na: "whois.na-nic.com.na",
825
844
  nc: "whois.nc",
826
845
  ne: null,
827
846
  nf: "whois.nic.nf",
828
847
  ng: "whois.nic.net.ng",
848
+ "*.ng": "whois.nic.net.ng",
829
849
  ni: null,
830
850
  nl: "whois.domain-registry.nl",
831
851
  no: {
@@ -836,9 +856,11 @@ export const port43servers: Record<string, any> = {
836
856
  nr: null,
837
857
  nu: "whois.iis.nu",
838
858
  nz: "whois.srs.net.nz",
859
+ "*.nz": "whois.srs.net.nz",
839
860
  om: "whois.registry.om",
840
861
  pa: null,
841
862
  pe: "kero.yachay.pe",
863
+ "*.pe": "kero.yachay.pe",
842
864
  pf: "whois.registry.pf",
843
865
  pg: null,
844
866
  ph: null,
@@ -850,6 +872,7 @@ export const port43servers: Record<string, any> = {
850
872
  pr: "whois.nic.pr",
851
873
  ps: "whois.pnina.ps",
852
874
  pt: "whois.dns.pt",
875
+ "*.pt": "whois.dns.pt",
853
876
  pw: "whois.nic.pw",
854
877
  py: null,
855
878
  qa: "whois.registry.qa",
@@ -860,6 +883,7 @@ export const port43servers: Record<string, any> = {
860
883
  ru: "whois.tcinet.ru",
861
884
  rw: "whois.ricta.org.rw",
862
885
  sa: "whois.nic.net.sa",
886
+ "*.sa": "whois.nic.net.sa",
863
887
  sb: "whois.nic.sb",
864
888
  sc: "whois.afilias-grs.info",
865
889
  sd: null,
@@ -886,17 +910,21 @@ export const port43servers: Record<string, any> = {
886
910
  tf: "whois.nic.tf",
887
911
  tg: "whois.nic.tg",
888
912
  th: "whois.thnic.co.th",
913
+ "*.th": "whois.thnic.co.th",
889
914
  tj: null,
890
915
  tk: "whois.dot.tk",
891
916
  tl: "whois.nic.tl",
892
917
  tm: "whois.nic.tm",
893
918
  tn: "whois.ati.tn",
919
+ "*.tn": "whois.ati.tn",
894
920
  to: "whois.tonic.to",
895
921
  tp: null,
896
922
  tr: "whois.nic.tr",
923
+ "*.tr": "whois.nic.tr",
897
924
  tt: null,
898
925
  tv: "tvwhois.verisign-grs.com",
899
926
  tw: "whois.twnic.net.tw",
927
+ "*.tw": "whois.twnic.net.tw",
900
928
  tz: "whois.tznic.or.tz",
901
929
  "biz.ua": "whois.biz.ua",
902
930
  "co.ua": "whois.co.ua",
@@ -924,6 +952,7 @@ export const port43servers: Record<string, any> = {
924
952
  va: null,
925
953
  vc: "whois.afilias-grs.info",
926
954
  ve: "whois.nic.ve",
955
+ "*.ve": "whois.nic.ve",
927
956
  vg: "whois.nic.vg",
928
957
  vi: null,
929
958
  vn: null,