@floomhq/signaldash 0.7.0 → 0.8.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/sd.mjs +34 -22
- package/package.json +1 -1
package/bin/sd.mjs
CHANGED
|
@@ -276,36 +276,48 @@ export async function cmdStatus(dependencies = {}) {
|
|
|
276
276
|
|
|
277
277
|
export async function cmdConnections(outPath, dependencies = {}) {
|
|
278
278
|
const log = dependencies.log || console.log;
|
|
279
|
-
const error = dependencies.error || console.error;
|
|
280
279
|
const request = dependencies.request || api;
|
|
281
280
|
const { chalk, ora } = await ui();
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
281
|
+
const { writeFileSync: wf, readFileSync: rf, existsSync: ex } = await import("node:fs");
|
|
282
|
+
const file = outPath || "linkedin-connections.csv";
|
|
283
|
+
|
|
284
|
+
// Resume support: keep the cursor next to the CSV so a large network is
|
|
285
|
+
// fetched over several paced passes instead of one burst (LinkedIn detection
|
|
286
|
+
// is behavioural; bursts are what get accounts flagged).
|
|
287
|
+
const stateFile = file + ".state.json";
|
|
288
|
+
let cursor = null, rows = [];
|
|
289
|
+
if (ex(stateFile)) {
|
|
290
|
+
try {
|
|
291
|
+
const prev = JSON.parse(rf(stateFile, "utf8"));
|
|
292
|
+
cursor = prev.cursor || null; rows = prev.rows || [];
|
|
293
|
+
if (cursor) log(" " + chalk.dim(`resuming from previous run (${rows.length} already fetched)`));
|
|
294
|
+
} catch {}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const spin = ora({ text: "Fetching connections (paced, this is deliberate)...", indent: 2 }).start();
|
|
298
|
+
for (;;) {
|
|
299
|
+
const r = await request("/li/connections", { cursor, max_pages: 10 });
|
|
300
|
+
if (r.status >= 300) {
|
|
301
|
+
spin.fail(r.json.error || "failed");
|
|
302
|
+
if (rows.length) { wf(stateFile, JSON.stringify({ cursor, rows })); log(" " + chalk.dim("progress saved; run again to resume")); }
|
|
303
|
+
process.exitCode = 1; return;
|
|
304
|
+
}
|
|
305
|
+
rows = rows.concat(r.json.connections || []);
|
|
306
|
+
cursor = r.json.next_cursor;
|
|
307
|
+
spin.text = `Fetched ${rows.length} connections...`;
|
|
308
|
+
if (!cursor) break;
|
|
309
|
+
wf(stateFile, JSON.stringify({ cursor, rows }));
|
|
310
|
+
}
|
|
286
311
|
spin.succeed(`${rows.length} connections`);
|
|
287
|
-
|
|
312
|
+
|
|
288
313
|
const esc = v => `"${String(v ?? "").replace(/"/g, '""')}"`;
|
|
289
314
|
const csv = ["name,headline,public_id,profile_url,connected_at",
|
|
290
315
|
...rows.map(c => [c.name, c.headline, c.public_id, c.profile_url, c.connected_at].map(esc).join(","))].join("\n");
|
|
291
|
-
const file = outPath || "linkedin-connections.csv";
|
|
292
316
|
wf(file, csv);
|
|
317
|
+
try { const { unlinkSync } = await import("node:fs"); if (ex(stateFile)) unlinkSync(stateFile); } catch {}
|
|
293
318
|
log(" " + chalk.green("+") + " saved " + chalk.cyan(file));
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
function printHelp(log = console.log) {
|
|
298
|
-
log(`SignalDash — secure LinkedIn + WhatsApp access for your agent.
|
|
299
|
-
|
|
300
|
-
signaldash <invite-code> set up everything in one go
|
|
301
|
-
signaldash status show what is connected
|
|
302
|
-
signaldash connect linkedin|whatsapp connect a channel
|
|
303
|
-
signaldash connections [file.csv] export your LinkedIn connections
|
|
304
|
-
signaldash skill install the agent skill
|
|
305
|
-
signaldash mcp run the MCP server (used by your agent)
|
|
306
|
-
signaldash logout revoke this device
|
|
307
|
-
|
|
308
|
-
The agent reaches your channels only through SignalDash. No keys on your machine.`);
|
|
319
|
+
log(" " + chalk.dim("Tip: LinkedIn's own export (Settings > Get a copy of your data) is zero-risk"));
|
|
320
|
+
log(" " + chalk.dim("and includes emails. Both work; that one never touches the API."));
|
|
309
321
|
}
|
|
310
322
|
|
|
311
323
|
export async function main(argv = process.argv.slice(2), dependencies = {}) {
|