- Add TIP Proxy Network (packages/proxy-agent): SOCKS5 proxy agent for residential IP bypass of CloudFront WAF blocks - Add /api/proxy/* routes: node registration, heartbeat, load balancing - Add image extraction to Flexoptix catalog scraper (GraphQL small_image) - Add image extraction to Optcore scraper (Playwright gallery img) - Fix Fluxlight price scraping (BigCommerce HTML structure: data-product-price-without-tax) - Add SmartOptics scraper (8 DWDM/coherent products, og:image extraction) - Fix findOrCreateScrapedTransceiver to update image_url for existing records - Add image backfill script (backfill-images.ts): 178 Flexoptix images added - Fix DB connection pool: max 5, idleTimeoutMillis 10s (was unlimited, caused >100 connections) - Add proxy.ts utility for scraper proxy rotation
168 lines
4.0 KiB
JavaScript
168 lines
4.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* TIP Proxy Agent CLI
|
|
*
|
|
* Usage:
|
|
* tip-agent start --token TOKEN [--port 1080] [--max-gb 10] [--name "My Node"]
|
|
* tip-agent status
|
|
* tip-agent stop
|
|
*/
|
|
import { startAgent } from "./agent";
|
|
import { loadConfig, saveConfig, loadPid, clearPid } from "./config";
|
|
|
|
const AGENT_VERSION = "1.0.0";
|
|
|
|
function parseArgs(argv: string[]): Record<string, string> {
|
|
const args: Record<string, string> = {};
|
|
for (let i = 0; i < argv.length; i++) {
|
|
const arg = argv[i];
|
|
if (arg && arg.startsWith("--")) {
|
|
const key = arg.slice(2);
|
|
const next = argv[i + 1];
|
|
if (next && !next.startsWith("--")) {
|
|
args[key] = next;
|
|
i++;
|
|
} else {
|
|
args[key] = "true";
|
|
}
|
|
}
|
|
}
|
|
return args;
|
|
}
|
|
|
|
function isProcessRunning(pid: number): boolean {
|
|
try {
|
|
process.kill(pid, 0);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function cmdStart(rawArgs: string[]): void {
|
|
const args = parseArgs(rawArgs);
|
|
|
|
const token = args["token"];
|
|
if (!token) {
|
|
console.error("Error: --token is required");
|
|
console.error(" tip-agent start --token YOUR_TOKEN [--port 1080] [--max-gb 10] [--name 'My Node']");
|
|
process.exit(1);
|
|
}
|
|
|
|
const cfg = saveConfig({
|
|
token,
|
|
port: args["port"] ? parseInt(args["port"], 10) : 1080,
|
|
maxGb: args["max-gb"] ? parseFloat(args["max-gb"]) : 10,
|
|
name: args["name"] ?? undefined,
|
|
serverUrl: args["server"] ?? "https://transceiver-db.context-x.org",
|
|
});
|
|
|
|
console.log(`\nTIP Proxy Agent v${AGENT_VERSION}`);
|
|
console.log("==========================================");
|
|
console.log(` Token: ${cfg.token.slice(0, 8)}...`);
|
|
console.log(` Port: ${cfg.port}`);
|
|
console.log(` Max GB: ${cfg.maxGb}`);
|
|
console.log(` Name: ${cfg.name}`);
|
|
console.log(` Server: ${cfg.serverUrl}`);
|
|
console.log("==========================================\n");
|
|
|
|
startAgent(cfg).catch((err) => {
|
|
console.error("[agent] Fatal error:", err.message);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|
|
function cmdStatus(): void {
|
|
const cfg = loadConfig();
|
|
const pid = loadPid();
|
|
|
|
if (!cfg || !pid) {
|
|
console.log("TIP Agent: not running");
|
|
process.exit(0);
|
|
}
|
|
|
|
const running = isProcessRunning(pid);
|
|
console.log(`TIP Agent: ${running ? "RUNNING" : "STOPPED (stale PID)"}`);
|
|
console.log(` PID: ${pid}`);
|
|
console.log(` Port: ${cfg.port}`);
|
|
console.log(` Token: ${cfg.token.slice(0, 8)}...`);
|
|
console.log(` Max GB: ${cfg.maxGb}`);
|
|
if (cfg.startedAt) {
|
|
console.log(` Started: ${cfg.startedAt}`);
|
|
}
|
|
|
|
if (!running) {
|
|
clearPid();
|
|
}
|
|
}
|
|
|
|
function cmdStop(): void {
|
|
const pid = loadPid();
|
|
|
|
if (!pid) {
|
|
console.log("TIP Agent: not running");
|
|
process.exit(0);
|
|
}
|
|
|
|
try {
|
|
process.kill(pid, "SIGTERM");
|
|
console.log(`TIP Agent (PID ${pid}) stopped.`);
|
|
clearPid();
|
|
} catch {
|
|
console.log(`TIP Agent: process ${pid} not found (already stopped)`);
|
|
clearPid();
|
|
}
|
|
}
|
|
|
|
function printHelp(): void {
|
|
console.log(`
|
|
TIP Proxy Agent v${AGENT_VERSION}
|
|
Contribute bandwidth to the TIP network, get free API access.
|
|
|
|
Usage:
|
|
tip-agent start --token TOKEN [options]
|
|
tip-agent status
|
|
tip-agent stop
|
|
|
|
Commands:
|
|
start Start the proxy agent
|
|
status Show agent status
|
|
stop Stop the agent
|
|
|
|
Options:
|
|
--token TOKEN Your TIP node token (required for start)
|
|
--port N SOCKS5 listen port (default: 1080)
|
|
--max-gb N Max bandwidth to donate in GB (default: 10)
|
|
--name NAME Node name (default: hostname)
|
|
--server URL TIP server URL (default: https://transceiver-db.context-x.org)
|
|
|
|
Example:
|
|
tip-agent start --token abc123 --port 1080 --max-gb 10 --name "Home Node"
|
|
`);
|
|
}
|
|
|
|
const [, , command, ...rest] = process.argv;
|
|
|
|
switch (command) {
|
|
case "start":
|
|
cmdStart(rest);
|
|
break;
|
|
case "status":
|
|
cmdStatus();
|
|
break;
|
|
case "stop":
|
|
cmdStop();
|
|
break;
|
|
case "--help":
|
|
case "-h":
|
|
case "help":
|
|
printHelp();
|
|
break;
|
|
default:
|
|
if (command) {
|
|
console.error(`Unknown command: ${command}`);
|
|
}
|
|
printHelp();
|
|
process.exit(command ? 1 : 0);
|
|
}
|