import { sleep } from '@fuman/utils' import { z } from 'zod' import { ffetch } from './fetch.ts' import { getEnv } from './misc.ts' // https://whois.whoisxmlapi.com/documentation/output // not all fields are present currently const WhoisResultSchema = z.object({ registrant: z.object({ organization: z.string(), name: z.string(), email: z.string(), }).partial().optional(), administrativeContact: z.object({ organization: z.string(), name: z.string(), email: z.string(), }).partial().optional(), technicalContact: z.object({ organization: z.string(), name: z.string(), email: z.string(), }).partial().optional(), registryData: z.object({ registrant: z.object({ organization: z.string(), name: z.string(), email: z.string(), }).partial().optional(), registrarName: z.string(), createdDate: z.string(), updatedDate: z.string(), expiresDate: z.string(), }).partial().optional(), registrarName: z.string().optional(), createdDate: z.string().optional(), updatedDate: z.string().optional(), expiresDate: z.string().optional(), }) export type WhoisResult = z.infer const WhoisWrapSchema = z.object({ domainName: z.string(), domainStatus: z.enum(['I', 'N']), whoisRecord: WhoisResultSchema.optional(), }) export async function bulkWhois(domains: string[]) { const res = await ffetch.post('https://www.whoisxmlapi.com/BulkWhoisLookup/bulkServices/bulkWhois', { json: { apiKey: getEnv('WHOISXMLAPI_TOKEN'), domains, outputFormat: 'JSON', }, }).parsedJson(z.object({ requestId: z.string(), })) while (true) { const res2 = await ffetch.post('https://www.whoisxmlapi.com/BulkWhoisLookup/bulkServices/getRecords', { json: { apiKey: getEnv('WHOISXMLAPI_KEY'), requestId: res.requestId, outputFormat: 'JSON', maxRecords: 1, }, }).parsedJson(z.object({ recordsLeft: z.number(), })) if (res2.recordsLeft !== 0) { await sleep(1000) continue } break } const result = new Map() const finalRes = await ffetch.post('https://www.whoisxmlapi.com/BulkWhoisLookup/bulkServices/getRecords', { json: { apiKey: getEnv('WHOISXMLAPI_KEY'), requestId: res.requestId, outputFormat: 'JSON', }, }).parsedJson(z.object({ whoisRecords: z.array(WhoisWrapSchema), })) for (const record of finalRes.whoisRecords) { result.set(record.domainName, record.domainStatus === 'I' ? record.whoisRecord ?? null : null) } return result } export async function whois(domain: string) { const res = await ffetch.post('https://www.whoisxmlapi.com/whoisserver/WhoisService', { json: { domainName: domain, outputFormat: 'JSON', apiKey: getEnv('WHOISXMLAPI_TOKEN'), }, }).parsedJson(z.object({ WhoisRecord: WhoisResultSchema.optional(), })) return res.WhoisRecord ?? null }