kooni-bot 0.3.0 → 0.3.2
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/kooni.js +38 -11
- package/package.json +1 -1
package/bin/kooni.js
CHANGED
|
@@ -16,13 +16,24 @@ import { emitKeypressEvents } from "node:readline";
|
|
|
16
16
|
import { stdin as input, stdout as output } from "node:process";
|
|
17
17
|
import { mkdirSync, writeFileSync, readFileSync, existsSync, rmSync, readdirSync, statSync, cpSync } from "node:fs";
|
|
18
18
|
import { realpathSync } from "node:fs";
|
|
19
|
-
import { join, basename } from "node:path";
|
|
19
|
+
import { join, basename, dirname } from "node:path";
|
|
20
20
|
import { homedir } from "node:os";
|
|
21
21
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
22
22
|
import { randomUUID, createPublicKey, verify as edVerify } from "node:crypto";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
// Leída del package.json publicado junto a este archivo — nunca hardcodeada,
|
|
26
|
+
// para que --version y la telemetría (cliVersion) no se desincronicen del
|
|
27
|
+
// número real publicado en npm (bug encontrado: quedó fija en "0.2.17" tras
|
|
28
|
+
// el bump a 0.3.0).
|
|
29
|
+
const CLI_VERSION = (() => {
|
|
30
|
+
try {
|
|
31
|
+
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
32
|
+
return JSON.parse(readFileSync(pkgPath, "utf8")).version || "0.0.0";
|
|
33
|
+
} catch {
|
|
34
|
+
return "0.0.0";
|
|
35
|
+
}
|
|
36
|
+
})();
|
|
26
37
|
|
|
27
38
|
const REPO = process.env.KOONI_REPO || "iamnocodeveloper/kooni-bot";
|
|
28
39
|
const BRANCH = process.env.KOONI_BRANCH || "main";
|
|
@@ -443,12 +454,27 @@ async function downloadTemplate(dest) {
|
|
|
443
454
|
writeFileSync(dest, Buffer.from(await res.arrayBuffer()));
|
|
444
455
|
}
|
|
445
456
|
|
|
446
|
-
// ── extracción
|
|
457
|
+
// ── extracción ───────────────────────────────────────────────────────────────
|
|
458
|
+
// Compat de tar entre shells: el bsdtar de Windows (System32\tar.exe) entiende
|
|
459
|
+
// rutas "C:\…", pero el GNU tar de Git-Bash/MSYS cree que "C:" es un host remoto
|
|
460
|
+
// y falla ("tar: Cannot connect to C: resolve failed"). Solución portátil:
|
|
461
|
+
// correr tar con cwd fijado y pasarle SOLO nombres relativos (sin dos puntos).
|
|
462
|
+
function relTo(base, p) {
|
|
463
|
+
const b = String(base).replace(/[\\/]+$/, "");
|
|
464
|
+
if (p === b) return ".";
|
|
465
|
+
if (p.startsWith(b + "\\") || p.startsWith(b + "/")) return p.slice(b.length + 1) || ".";
|
|
466
|
+
return p; // fuera de base: último recurso
|
|
467
|
+
}
|
|
468
|
+
function tarExtract(tgz, outDir) {
|
|
469
|
+
mkdirSync(outDir, { recursive: true });
|
|
470
|
+
const cwd = dirname(tgz);
|
|
471
|
+
execFileSync("tar", ["-xzf", basename(tgz), "-C", relTo(cwd, outDir)], { cwd });
|
|
472
|
+
}
|
|
473
|
+
|
|
447
474
|
function extractFresh(tgz, dir) {
|
|
448
475
|
mkdirSync(dir, { recursive: true });
|
|
449
476
|
const tmp = join(dir, ".kooni-extract");
|
|
450
|
-
|
|
451
|
-
execFileSync("tar", ["-xzf", tgz, "-C", tmp]);
|
|
477
|
+
tarExtract(tgz, tmp);
|
|
452
478
|
const root = readdirSync(tmp)[0];
|
|
453
479
|
const src = join(tmp, root);
|
|
454
480
|
for (const e of readdirSync(src)) {
|
|
@@ -462,8 +488,7 @@ function extractFresh(tgz, dir) {
|
|
|
462
488
|
|
|
463
489
|
// Extrae a un dir TEMP (sin pisar nada) para leer la versión y archivos del template.
|
|
464
490
|
function extractToTemp(tgz, outDir) {
|
|
465
|
-
|
|
466
|
-
execFileSync("tar", ["-xzf", tgz, "-C", outDir]);
|
|
491
|
+
tarExtract(tgz, outDir);
|
|
467
492
|
const root = readdirSync(outDir)[0];
|
|
468
493
|
return join(outDir, root);
|
|
469
494
|
}
|
|
@@ -494,10 +519,11 @@ function backupBeforeUpdate(dir, version) {
|
|
|
494
519
|
const dest = join(backDir, `${stamp}_v${version}.tgz`);
|
|
495
520
|
try {
|
|
496
521
|
mkdirSync(backDir, { recursive: true });
|
|
497
|
-
|
|
522
|
+
// cwd = dir + ruta relativa del archivo → tar portátil (ver relTo/tarExtract).
|
|
523
|
+
execFileSync("tar", ["-czf", relTo(dir, dest), "-C", ".",
|
|
498
524
|
"--exclude=./node_modules", "--exclude=./.kooni-backups", "--exclude=./.kooni-extract",
|
|
499
525
|
"--exclude=./.git", "--exclude=./.wrangler", "--exclude=./.dev.vars", "--exclude=./.dev.vars.*",
|
|
500
|
-
"--exclude=./.env", "--exclude=./.env.*", "."]);
|
|
526
|
+
"--exclude=./.env", "--exclude=./.env.*", "."], { cwd: dir });
|
|
501
527
|
const olds = readdirSync(backDir).filter((f) => f.endsWith(".tgz")).sort();
|
|
502
528
|
for (const f of olds.slice(0, -5)) rmSync(join(backDir, f), { force: true });
|
|
503
529
|
return dest;
|
|
@@ -896,8 +922,9 @@ async function onboarding(rl, answers, defaultDir) {
|
|
|
896
922
|
}
|
|
897
923
|
|
|
898
924
|
// Licencia Pro: si el usuario dice que es Pro, pide el código y lo valida
|
|
899
|
-
// localmente (
|
|
900
|
-
//
|
|
925
|
+
// localmente (Ed25519 con la clave PÚBLICA embebida — solo verifica, no firma).
|
|
926
|
+
// Si es válido se guarda tras el deploy (settings pro_license → límites
|
|
927
|
+
// quitados). Si es inválido, se avisa y sigue gratis.
|
|
901
928
|
const wantsPro = interactive()
|
|
902
929
|
? await confirm(rl, m("¿Tu bot será Pro (tienes una licencia)?", "Will your bot be Pro (do you have a license)?"))
|
|
903
930
|
: !!(flags.license || answers.licenseCode);
|
package/package.json
CHANGED