argorant 0.1.0 → 0.3.0
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/bin/argorant.js +86 -9
- package/package.json +3 -3
package/bin/argorant.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
4
|
// Argorant CLI — a thin, dependency-free wrapper over the Argorant REST API.
|
|
5
|
-
// Search, count, reveal, and
|
|
5
|
+
// Search, count, reveal, export, and verify B2B contacts from the terminal.
|
|
6
6
|
// Auth: an Argorant API key (ag_live_*) via `argorant login`, or ARGORANT_API_KEY.
|
|
7
7
|
|
|
8
8
|
const https = require("https");
|
|
@@ -52,16 +52,20 @@ function resolveKey() {
|
|
|
52
52
|
// Flags that map to API filter params. Value flags take the next token.
|
|
53
53
|
const VALUE_FLAGS = {
|
|
54
54
|
"--title": "title",
|
|
55
|
+
"--exclude-title": "exclude_title",
|
|
55
56
|
"--seniority": "seniority",
|
|
56
57
|
"--department": "departments",
|
|
57
58
|
"--departments": "departments",
|
|
58
59
|
"--industry": "industry",
|
|
59
60
|
"--country": "country",
|
|
61
|
+
// --geography is an alias for --country; the API expands regions like
|
|
62
|
+
// "Europe", "EMEA", "DACH", "APAC" into their member countries.
|
|
63
|
+
"--geography": "country",
|
|
64
|
+
"--region": "country",
|
|
60
65
|
"--state": "state",
|
|
61
66
|
"--city": "city",
|
|
62
67
|
"--company": "company_name",
|
|
63
68
|
"--domain": "company_domain",
|
|
64
|
-
"--verify-status": "verify_status",
|
|
65
69
|
};
|
|
66
70
|
// Boolean filter flags (presence => "true").
|
|
67
71
|
const BOOL_FLAGS = {
|
|
@@ -71,13 +75,15 @@ const BOOL_FLAGS = {
|
|
|
71
75
|
};
|
|
72
76
|
|
|
73
77
|
function parseArgs(argv) {
|
|
74
|
-
const out = { _: [], filters: {}, limit: null, output: null, json: false, yes: false, base: DEFAULT_BASE };
|
|
78
|
+
const out = { _: [], filters: {}, limit: null, output: null, file: null, column: null, json: false, yes: false, base: DEFAULT_BASE };
|
|
75
79
|
for (let i = 0; i < argv.length; i++) {
|
|
76
80
|
const a = argv[i];
|
|
77
81
|
if (a === "--json") out.json = true;
|
|
78
82
|
else if (a === "--yes" || a === "-y") out.yes = true;
|
|
79
83
|
else if (a === "-n" || a === "--limit") out.limit = parseInt(argv[++i], 10);
|
|
80
84
|
else if (a === "-o" || a === "--output") out.output = argv[++i];
|
|
85
|
+
else if (a === "-f" || a === "--file") out.file = argv[++i];
|
|
86
|
+
else if (a === "--column") out.column = argv[++i];
|
|
81
87
|
else if (a === "--base") out.base = argv[++i];
|
|
82
88
|
else if (a in VALUE_FLAGS) out.filters[VALUE_FLAGS[a]] = argv[++i];
|
|
83
89
|
else if (a in BOOL_FLAGS) out.filters[BOOL_FLAGS[a]] = "true";
|
|
@@ -339,6 +345,70 @@ async function cmdExport(args) {
|
|
|
339
345
|
console.log(green("✓") + ` Saved ${rows != null ? bold(rows.toLocaleString()) + " rows → " : ""}${bold(dest)}`);
|
|
340
346
|
}
|
|
341
347
|
|
|
348
|
+
// ---- verify: external email verification (own lists) — the verification pool,
|
|
349
|
+
// separate from contact credits. 60-day re-checks are free. ----
|
|
350
|
+
const EMAIL_RE = /[^\s,;"']+@[^\s,;"']+\.[^\s,;"']+/;
|
|
351
|
+
|
|
352
|
+
async function cmdVerify(args) {
|
|
353
|
+
const key = requireKey();
|
|
354
|
+
if (args.file) return cmdVerifyFile(args, key);
|
|
355
|
+
const email = (args._[0] || args.filters.q || "").trim().toLowerCase();
|
|
356
|
+
if (!email || !email.includes("@")) {
|
|
357
|
+
die('usage: argorant verify <email> | argorant verify --file emails.csv [-o out.csv]');
|
|
358
|
+
}
|
|
359
|
+
const res = await request("POST", args.base, "/api/mcp/email/verify", { key, body: { email } });
|
|
360
|
+
const r = need(res, "verify");
|
|
361
|
+
if (args.json) return console.log(JSON.stringify(r, null, 2));
|
|
362
|
+
const tag = r.deliverable ? green(r.status) : dim(r.status);
|
|
363
|
+
console.log(` ${bold(email)} → ${tag}${r.deliverable ? " " + green("✓ deliverable") : ""}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async function cmdVerifyFile(args, key) {
|
|
367
|
+
let text;
|
|
368
|
+
try { text = fs.readFileSync(args.file, "utf8"); } catch { die(`cannot read file: ${args.file}`); }
|
|
369
|
+
const lines = text.split(/\r?\n/).filter((l) => l.trim());
|
|
370
|
+
if (!lines.length) die("file is empty");
|
|
371
|
+
// Use the named/auto-detected email column if the file looks like a CSV with a
|
|
372
|
+
// header; otherwise scan every line for an address.
|
|
373
|
+
const header = lines[0].split(",").map((h) => h.trim().toLowerCase().replace(/^["']|["']$/g, ""));
|
|
374
|
+
const colIdx = args.column
|
|
375
|
+
? header.indexOf(args.column.toLowerCase())
|
|
376
|
+
: header.findIndex((h) => h === "email" || h.includes("email"));
|
|
377
|
+
let emails = [];
|
|
378
|
+
if (colIdx >= 0) {
|
|
379
|
+
for (let i = 1; i < lines.length; i++) {
|
|
380
|
+
const m = (lines[i].split(",")[colIdx] || "").match(EMAIL_RE);
|
|
381
|
+
if (m) emails.push(m[0].toLowerCase());
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
for (const l of lines) { const m = l.match(EMAIL_RE); if (m) emails.push(m[0].toLowerCase()); }
|
|
385
|
+
}
|
|
386
|
+
emails = [...new Set(emails)];
|
|
387
|
+
if (!emails.length) die("no email addresses found in file (try --column <name>)");
|
|
388
|
+
const out = args.output || "argorant-verified.csv";
|
|
389
|
+
if (!args.yes && !args.json && process.stdin.isTTY) {
|
|
390
|
+
const ans = await prompt(`Verify ${bold(emails.length.toLocaleString())} emails? Fresh checks use your verification-check pool; addresses checked in the last 60 days are free. [y/N] `);
|
|
391
|
+
if (!/^y(es)?$/i.test(ans)) return console.log(dim("aborted."));
|
|
392
|
+
}
|
|
393
|
+
const all = [];
|
|
394
|
+
let charged = 0, cached = 0;
|
|
395
|
+
for (let i = 0; i < emails.length; i += 500) {
|
|
396
|
+
const chunk = emails.slice(i, i + 500);
|
|
397
|
+
const res = await request("POST", args.base, "/api/mcp/email/verify/batch", { key, body: { emails: chunk } });
|
|
398
|
+
const r = need(res, "verify");
|
|
399
|
+
charged += r.checks_charged || 0;
|
|
400
|
+
cached += r.cached || 0;
|
|
401
|
+
for (const row of r.results || []) all.push(row);
|
|
402
|
+
if (!args.json) process.stdout.write(`\r${dim(`verified ${Math.min(i + 500, emails.length).toLocaleString()}/${emails.length.toLocaleString()}`)}`);
|
|
403
|
+
}
|
|
404
|
+
if (!args.json) process.stdout.write("\n");
|
|
405
|
+
if (args.json) return console.log(JSON.stringify({ ok: true, total: all.length, checks_charged: charged, cached, results: all }, null, 2));
|
|
406
|
+
const csv = ["email,status,deliverable", ...all.map((r) => `${r.email},${r.status},${r.deliverable}`)].join("\n") + "\n";
|
|
407
|
+
fs.writeFileSync(out, csv);
|
|
408
|
+
const deliverable = all.filter((r) => r.deliverable).length;
|
|
409
|
+
console.log(green("✓") + ` ${bold(all.length.toLocaleString())} verified → ${bold(out)} ${dim(`(${deliverable.toLocaleString()} deliverable · ${charged.toLocaleString()} checks billed · ${cached.toLocaleString()} free cache hits)`)}`);
|
|
410
|
+
}
|
|
411
|
+
|
|
342
412
|
function help() {
|
|
343
413
|
const p = bold("argorant");
|
|
344
414
|
console.log(`
|
|
@@ -352,14 +422,18 @@ ${bold("COMMANDS")}
|
|
|
352
422
|
${cyan("whoami")} Account, scopes, and daily quota
|
|
353
423
|
${cyan("count")} "<query>" Count matching contacts ${dim("(free)")}
|
|
354
424
|
${cyan("search")} "<query>" -n 10 Preview matches, details redacted ${dim("(free)")}
|
|
355
|
-
${cyan("reveal")} "<query>" -n 25 Reveal full contact details ${dim("(uses
|
|
356
|
-
${cyan("export")} "<query>" -n 1000 -o leads.csv Verified CSV export ${dim("(uses
|
|
425
|
+
${cyan("reveal")} "<query>" -n 25 Reveal full contact details ${dim("(uses credits; live-verified, pay only for deliverable)")}
|
|
426
|
+
${cyan("export")} "<query>" -n 1000 -o leads.csv Verified CSV export ${dim("(uses credits)")}
|
|
427
|
+
${cyan("verify")} <email> Verify one of your own emails ${dim("(verification pool)")}
|
|
428
|
+
${cyan("verify")} --file emails.csv -o out.csv Bulk-verify your own list ${dim("(60-day re-checks free)")}
|
|
357
429
|
|
|
358
430
|
${bold("FILTERS")}
|
|
359
|
-
--title <t> --seniority <s>
|
|
360
|
-
--industry <i> --country <c>
|
|
361
|
-
--company <name>
|
|
362
|
-
--has-phone --has-linkedin
|
|
431
|
+
--title <t> --exclude-title <t> --seniority <s> --department <d>
|
|
432
|
+
--industry <i> --country <c> --geography <r> --state <s>
|
|
433
|
+
--city <c> --company <name> --domain <domain>
|
|
434
|
+
--has-phone --has-linkedin --has-email
|
|
435
|
+
${dim("--title is abbreviation-aware (CFO ↔ Chief Financial Officer).")}
|
|
436
|
+
${dim("--country / --geography accept regions: Europe, EMEA, DACH, Nordics, APAC, LATAM, GCC…")}
|
|
363
437
|
|
|
364
438
|
${bold("OPTIONS")}
|
|
365
439
|
-n, --limit <n> Max rows -o, --output <file> CSV path (export)
|
|
@@ -370,6 +444,8 @@ ${bold("EXAMPLES")}
|
|
|
370
444
|
${p} count "fintech CFOs in germany"
|
|
371
445
|
${p} search "heads of procurement" --country Germany -n 10
|
|
372
446
|
${p} export --industry fintech --title CFO --country Germany -n 500 -o cfos.csv
|
|
447
|
+
${p} verify ceo@stripe.com
|
|
448
|
+
${p} verify --file my-list.csv -o verified.csv
|
|
373
449
|
|
|
374
450
|
Docs: ${cyan("https://argorant.com/docs/cli")}
|
|
375
451
|
`);
|
|
@@ -393,6 +469,7 @@ async function main() {
|
|
|
393
469
|
search: cmdSearch,
|
|
394
470
|
reveal: cmdReveal,
|
|
395
471
|
export: cmdExport,
|
|
472
|
+
verify: cmdVerify,
|
|
396
473
|
};
|
|
397
474
|
const fn = table[cmd];
|
|
398
475
|
if (!fn) die(`unknown command: ${cmd}\nRun \`argorant help\` for usage.`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argorant",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Search, count, reveal, and
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Search, count, reveal, export, and verify B2B contacts from the Argorant database \u2014 from your terminal, scripts, or coding agent.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"argorant": "bin/argorant.js"
|
|
7
7
|
},
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
"url": "https://argorant.com/docs/cli"
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT"
|
|
32
|
-
}
|
|
32
|
+
}
|