← back to Domain Sniper
inspect.js
63 lines
#!/usr/bin/env node
// inspect.js — pretty-prints the snipe-timing curve from data/honeypot-spotcheck.jsonl.
//
// Handles two record shapes:
// 1) legacy per-row : {ts, phase, domain, status}
// 2) per-batch tally: {spotcheckAt, batchTs, elapsedHours, sampleSize, sampleSlice, tally, items}
//
// Usage: node inspect.js
const fs = require('fs');
const path = require('path');
const FILE = path.join(__dirname, 'data', 'honeypot-spotcheck.jsonl');
const lines = fs.readFileSync(FILE, 'utf8').split('\n').filter(Boolean);
const summaryOnly = process.argv.includes('--summary') || process.argv.includes('-s');
const rows = []; // {elapsedH, snipes, total, label}
// Bucket legacy per-row entries by phase
const legacy = {};
for (const ln of lines) {
let r; try { r = JSON.parse(ln); } catch { continue; }
if (r.phase) {
const b = (legacy[r.phase] = legacy[r.phase] || { total: 0, snipes: 0, ts: r.ts });
b.total++;
if (r.status && /SNIP|TAKEN/i.test(r.status)) b.snipes++;
} else if (r.elapsedHours != null && r.tally) {
const snipes = Object.values(r.tally).reduce((a, b) => a + (b.sniped || 0), 0);
const total = Object.values(r.tally).reduce((a, b) => a + (b.total || 0), 0);
rows.push({ elapsedH: r.elapsedHours, snipes, total, label: `slice ${r.sampleSlice || '?'}` });
}
}
for (const [phase, b] of Object.entries(legacy)) {
rows.push({ elapsedH: phase.match(/(\d+(\.\d+)?)h/) ? +RegExp.$1 : 0, snipes: b.snipes, total: b.total, label: phase });
}
rows.sort((a, b) => a.elapsedH - b.elapsedH);
let cumSniped = 0, cumTotal = 0;
for (const r of rows) { cumSniped += r.snipes; cumTotal += r.total; }
const last = rows[rows.length - 1];
if (summaryOnly) {
const tag = cumSniped > 0 ? '\x1b[31m' : '\x1b[32m';
const end = '\x1b[0m';
console.log(` ${tag}${cumSniped}/${cumTotal}${end} sniped across ${rows.length} datapoints | last ${last ? `${last.elapsedH.toFixed(2)}h ${last.snipes}/${last.total} (${last.label})` : 'n/a'}`);
process.exit(0);
}
console.log(`\n honeypot snipe-timing curve (${rows.length} datapoints, ${lines.length} raw rows)`);
console.log(` ` + '-'.repeat(78));
console.log(` elapsed snipes/total rate label chart`);
console.log(` ` + '-'.repeat(78));
for (const r of rows) {
const rate = r.total ? `${Math.round((100 * r.snipes) / r.total)}%` : 'n/a';
const bar = '█'.repeat(r.snipes) + '·'.repeat(Math.max(0, r.total - r.snipes));
const tag = r.snipes > 0 ? '\x1b[31m' : '';
const end = r.snipes > 0 ? '\x1b[0m' : '';
console.log(` ${r.elapsedH.toFixed(2).padStart(5)}h ${tag}${String(r.snipes).padStart(2)}/${String(r.total).padEnd(3)}${end} ${rate.padStart(4)} ${r.label.padEnd(28)} ${bar}`);
}
console.log(` ` + '-'.repeat(78));
console.log(` cumulative: ${cumSniped} sniped of ${cumTotal} checks (${cumTotal ? Math.round((100 * cumSniped) / cumTotal) : 0}%)`);
console.log(`\n source: ${FILE}\n`);