UNPKG

domainlooker

Version:

šŸ•µļø Mission-critical domain intelligence gathering tool with spy-themed interface. Comprehensive WHOIS, DNS, SSL, network analysis, subdomain discovery, and API-ready JSON exports.

139 lines • 5.48 kB
import * as fs from 'fs'; import * as path from 'path'; export class CSVExportService { constructor() { this.csvData = []; // CSV Header this.csvData.push([ 'Domain', 'Registrar', 'Registration Date', 'Expiration Date', 'Registrant Country', 'Status', 'Name Servers', 'IPv4 Addresses', 'IPv6 Addresses', 'MX Records', 'TXT Records', 'SSL Issuer', 'SSL Subject', 'SSL Valid From', 'SSL Valid To', 'SSL Days Until Expiry', 'SSL Valid', 'Open Ports', 'Services', 'Subdomains Found', 'Sample Subdomains', 'Threat Level', 'Threats' ].join(',')); } addDomain(domainInfo) { const { domain, whois, dns, ssl, network, subdomains } = domainInfo; // Process arrays and objects for CSV format const nameServers = whois?.nameServers?.join('; ') || ''; const ipv4Addresses = dns?.a?.join('; ') || ''; const ipv6Addresses = dns?.aaaa?.join('; ') || ''; const mxRecords = dns?.mx?.map(mx => `${mx.priority} ${mx.exchange}`).join('; ') || ''; const txtRecords = dns?.txt?.slice(0, 3).join('; ') || ''; // Limit TXT records const openPorts = network?.openPorts?.join('; ') || ''; const services = network?.services?.map(s => `${s.port}:${s.service}`).join('; ') || ''; const status = whois?.status?.join('; ') || ''; const subdomainCount = subdomains?.totalFound?.toString() || '0'; const sampleSubdomains = subdomains?.subdomains?.slice(0, 5).join('; ') || ''; // Threat assessment const threats = this.assessThreats(domainInfo); const threatLevel = this.getThreatLevel(threats); // Escape CSV values const csvRow = [ this.escapeCSV(domain), this.escapeCSV(whois?.registrar || ''), this.escapeCSV(whois?.registrationDate || ''), this.escapeCSV(whois?.expirationDate || ''), this.escapeCSV(whois?.registrantCountry || ''), this.escapeCSV(status), this.escapeCSV(nameServers), this.escapeCSV(ipv4Addresses), this.escapeCSV(ipv6Addresses), this.escapeCSV(mxRecords), this.escapeCSV(txtRecords), this.escapeCSV(ssl?.issuer || ''), this.escapeCSV(ssl?.subject || ''), this.escapeCSV(ssl?.validFrom || ''), this.escapeCSV(ssl?.validTo || ''), this.escapeCSV(ssl?.daysUntilExpiry?.toString() || ''), this.escapeCSV(ssl?.isValid?.toString() || ''), this.escapeCSV(openPorts), this.escapeCSV(services), this.escapeCSV(subdomainCount), this.escapeCSV(sampleSubdomains), this.escapeCSV(threatLevel), this.escapeCSV(threats.join('; ')) ].join(','); this.csvData.push(csvRow); } assessThreats(info) { const threats = []; // SSL certificate expiry if (info.ssl?.daysUntilExpiry !== undefined && info.ssl.daysUntilExpiry < 30) { threats.push(`SSL expires in ${info.ssl.daysUntilExpiry} days`); } // Missing SSL if (!info.ssl) { threats.push('No SSL certificate detected'); } // Recently registered domains if (info.whois?.registrationDate) { const regDate = new Date(info.whois.registrationDate); const daysSinceReg = (Date.now() - regDate.getTime()) / (1000 * 60 * 60 * 24); if (daysSinceReg < 30) { threats.push('Domain registered recently'); } } // Invalid SSL if (info.ssl && info.ssl.isValid === false) { threats.push('Invalid SSL certificate'); } return threats; } getThreatLevel(threats) { if (threats.length === 0) return 'LOW'; if (threats.some(t => t.includes('Invalid SSL') || t.includes('No SSL'))) return 'HIGH'; if (threats.some(t => t.includes('expires'))) return 'MEDIUM'; return 'LOW'; } escapeCSV(value) { if (!value) return ''; // Escape quotes and wrap in quotes if contains comma, quote, or newline if (value.includes(',') || value.includes('"') || value.includes('\n')) { return `"${value.replace(/"/g, '""')}"`; } return value; } async exportToFile(filename) { const csvContent = this.csvData.join('\n'); // Ensure the filename has .csv extension const csvFilename = filename.endsWith('.csv') ? filename : `${filename}.csv`; // Get absolute path const fullPath = path.resolve(csvFilename); try { await fs.promises.writeFile(fullPath, csvContent, 'utf8'); console.log(`\nšŸ“Š CSV Export Complete: ${fullPath}`); console.log(`šŸ“ˆ Exported ${this.csvData.length - 1} domains with complete intelligence data`); } catch (error) { console.error(`āŒ Failed to export CSV: ${error}`); throw error; } } getRowCount() { return this.csvData.length - 1; // Subtract header row } } //# sourceMappingURL=csv-export.js.map