mirror of
https://github.com/xx254/linkedin_skills.git
synced 2026-06-10 07:24:56 +03:00
123 lines
4.3 KiB
JavaScript
123 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const readline = require("readline");
|
|
const { readJson, writeJson, ensureDir } = require("./lib/io");
|
|
|
|
const ROOT = path.resolve(__dirname, "..");
|
|
const settingsPath = path.join(ROOT, "state", "linkedin-settings.json");
|
|
const statePath = path.join(ROOT, "state", "linkedin-system-state.json");
|
|
const defaultSettingsPath = path.join(ROOT, "config", "default-settings.json");
|
|
const contextDir = path.join(ROOT, "context");
|
|
const aboutMePath = path.join(contextDir, "about-me.md");
|
|
const brandVoicePath = path.join(contextDir, "brand-voice.md");
|
|
|
|
const defaultSettings = readJson(defaultSettingsPath, {});
|
|
const currentSettings = readJson(settingsPath, null);
|
|
const currentState = readJson(statePath, null);
|
|
|
|
if (!currentSettings) {
|
|
writeJson(settingsPath, defaultSettings);
|
|
}
|
|
|
|
if (!currentState) {
|
|
writeJson(statePath, {
|
|
version: "1.0.0",
|
|
firstRunCompleted: false,
|
|
lastSuccessfulRunAt: null,
|
|
lastLeadFilterRunAt: null,
|
|
lastDraftRunAt: null,
|
|
lastReplyRunAt: null,
|
|
leadRegistry: {},
|
|
outreachRegistry: {},
|
|
weeklyMetrics: {
|
|
weekKey: null,
|
|
leads_processed: 0,
|
|
qualified_count: 0,
|
|
drafted_count: 0,
|
|
reply_drafts_count: 0,
|
|
replied_count: 0,
|
|
rejected_count: 0,
|
|
score3_conversion_count: 0
|
|
}
|
|
});
|
|
}
|
|
|
|
ensureDir(path.join(ROOT, "output"));
|
|
ensureDir(path.join(ROOT, "reports"));
|
|
ensureDir(contextDir);
|
|
|
|
if (!fs.existsSync(aboutMePath)) {
|
|
fs.writeFileSync(
|
|
aboutMePath,
|
|
"# ICP Profile\n\n## Target Industries\n- Software Development\n- Marketing Services\n\n## Target Seniority\n- Manager\n- Director\n\n## Target Geographies\n- United States\n\n## Offer Summary\nDescribe your offer here.\n",
|
|
"utf8"
|
|
);
|
|
}
|
|
|
|
if (!fs.existsSync(brandVoicePath)) {
|
|
fs.writeFileSync(
|
|
brandVoicePath,
|
|
"# Brand Voice Profile\n\n## Language\nDefault: English\n\n## Outreach Goal\nStart relevant conversations with qualified leads.\n\n## Formatting Rules\n- Keep first-touch message concise.\n- Max one question.\n- No generic opener.\n",
|
|
"utf8"
|
|
);
|
|
}
|
|
|
|
const result = {
|
|
ok: true,
|
|
settingsInitialized: !currentSettings,
|
|
stateInitialized: !currentState,
|
|
root: ROOT
|
|
};
|
|
|
|
// Telemetry opt-in — ask once on first setup
|
|
const freshState = readJson(statePath, {});
|
|
if (!freshState.telemetryPrompted) {
|
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
|
|
const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
|
|
(async () => {
|
|
console.log("\n──────────────────────────────────────────");
|
|
console.log("Help us improve these skills for your industry.");
|
|
console.log("Community mode shares anonymous usage data — which skills you run,");
|
|
console.log("how many leads processed, signal types that worked.");
|
|
console.log("No names, no message content, no file paths. Ever.");
|
|
console.log("Change anytime: set \"telemetry\": \"off\" in state/linkedin-settings.json");
|
|
console.log("──────────────────────────────────────────");
|
|
|
|
const a1 = await ask("\nA) Sure, happy to help improve this\nB) No thanks\n> ");
|
|
|
|
let telemetryLevel;
|
|
|
|
if (a1.trim().toUpperCase() === "A") {
|
|
telemetryLevel = "community";
|
|
} else {
|
|
const a2 = await ask(
|
|
"\nHow about anonymous mode? We just learn that someone ran the pipeline —\n" +
|
|
"no ID, no details. Just a counter that helps us know the tool is useful.\n\n" +
|
|
"A) Anonymous is fine\nB) No thanks, fully off\n> "
|
|
);
|
|
telemetryLevel = a2.trim().toUpperCase() === "A" ? "anonymous" : "off";
|
|
}
|
|
|
|
rl.close();
|
|
|
|
// Save telemetry choice to settings
|
|
const settings = readJson(settingsPath, {});
|
|
if (!settings.settings) settings.settings = {};
|
|
settings.settings.telemetry = telemetryLevel;
|
|
writeJson(settingsPath, settings);
|
|
|
|
// Mark telemetry as prompted in state
|
|
const state = readJson(statePath, {});
|
|
state.telemetryPrompted = true;
|
|
writeJson(statePath, state);
|
|
|
|
result.telemetry = telemetryLevel;
|
|
console.log("\n" + JSON.stringify(result, null, 2));
|
|
})();
|
|
} else {
|
|
console.log(JSON.stringify(result, null, 2));
|
|
}
|