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
JavaScript
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