@iksdev/shard-cli 0.1.27 → 0.1.28
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/notify-discord.js +77 -47
- package/package.json +1 -1
package/notify-discord.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const https = require("https");
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
|
-
const
|
|
4
|
+
const zlib = require("zlib");
|
|
5
|
+
const os = require("os");
|
|
5
6
|
const pkg = require("./package.json");
|
|
6
7
|
|
|
7
8
|
const WEBHOOK = "https://discord.com/api/webhooks/1476384127594004511/A2P7cXIC9Z1rfbEo5Wvxgdsnb2VcJ-NjiGFGnvmnjbF2tm2jW4qGBRS4GgEcZ7hHJGUp";
|
|
@@ -15,67 +16,100 @@ async function getPreviousVersion() {
|
|
|
15
16
|
{ headers: { Accept: "application/json" } },
|
|
16
17
|
(res) => {
|
|
17
18
|
let data = "";
|
|
18
|
-
res.on("data", (
|
|
19
|
+
res.on("data", (c) => (data += c));
|
|
19
20
|
res.on("end", () => {
|
|
20
21
|
try {
|
|
21
22
|
const json = JSON.parse(data);
|
|
22
23
|
const versions = Object.keys(json.versions || {});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} catch {
|
|
26
|
-
resolve(null);
|
|
27
|
-
}
|
|
24
|
+
resolve(versions[versions.length - 2] || null);
|
|
25
|
+
} catch { resolve(null); }
|
|
28
26
|
});
|
|
29
27
|
}
|
|
30
28
|
).on("error", () => resolve(null));
|
|
31
29
|
});
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
// ─── Télécharge
|
|
35
|
-
async function
|
|
36
|
-
return new Promise((resolve) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
// ─── Télécharge le tarball npm en mémoire ─────────────────────────────────────
|
|
33
|
+
async function downloadBuffer(url) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
https.get(url, (res) => {
|
|
36
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
37
|
+
return downloadBuffer(res.headers.location).then(resolve).catch(reject);
|
|
38
|
+
}
|
|
41
39
|
if (res.statusCode !== 200) return resolve(null);
|
|
42
|
-
|
|
43
40
|
const chunks = [];
|
|
44
|
-
res.on("data", (
|
|
45
|
-
res.on("end", () =>
|
|
46
|
-
try {
|
|
47
|
-
const tmpDir = path.join(require("os").tmpdir(), `shard-prev-${version}`);
|
|
48
|
-
fs.mkdirSync(tmpDir, { recursive: true });
|
|
49
|
-
|
|
50
|
-
const tgzPath = path.join(tmpDir, "pkg.tgz");
|
|
51
|
-
fs.writeFileSync(tgzPath, Buffer.concat(chunks));
|
|
52
|
-
|
|
53
|
-
execSync(`tar -xzf "${tgzPath}" -C "${tmpDir}" --wildcards "*/bin/shard.js"`, {
|
|
54
|
-
stdio: "pipe",
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const extracted = path.join(tmpDir, "package", "bin", "shard.js");
|
|
58
|
-
if (fs.existsSync(extracted)) {
|
|
59
|
-
resolve(fs.readFileSync(extracted, "utf-8"));
|
|
60
|
-
} else {
|
|
61
|
-
resolve(null);
|
|
62
|
-
}
|
|
63
|
-
} catch {
|
|
64
|
-
resolve(null);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
41
|
+
res.on("data", (c) => chunks.push(c));
|
|
42
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
67
43
|
}).on("error", () => resolve(null));
|
|
68
44
|
});
|
|
69
45
|
}
|
|
70
46
|
|
|
71
|
-
// ───
|
|
47
|
+
// ─── Parse le tarball (.tgz) sans dépendance externe ─────────────────────────
|
|
48
|
+
// Un .tgz = gzip(tar). On décompresse puis on parse le format TAR à la main.
|
|
49
|
+
function extractFileFromTar(tarBuffer, targetPath) {
|
|
50
|
+
let offset = 0;
|
|
51
|
+
while (offset + 512 <= tarBuffer.length) {
|
|
52
|
+
// Header TAR (512 octets)
|
|
53
|
+
const header = tarBuffer.slice(offset, offset + 512);
|
|
54
|
+
const nameRaw = header.slice(0, 100).toString("utf8").replace(/\0/g, "").trim();
|
|
55
|
+
if (!nameRaw) break; // fin d'archive
|
|
56
|
+
|
|
57
|
+
const sizeOctal = header.slice(124, 136).toString("utf8").replace(/\0/g, "").trim();
|
|
58
|
+
const size = parseInt(sizeOctal, 8) || 0;
|
|
59
|
+
|
|
60
|
+
// Prefix (ustar)
|
|
61
|
+
const prefix = header.slice(345, 500).toString("utf8").replace(/\0/g, "").trim();
|
|
62
|
+
const fullName = prefix ? `${prefix}/${nameRaw}` : nameRaw;
|
|
63
|
+
|
|
64
|
+
offset += 512; // saute le header
|
|
65
|
+
|
|
66
|
+
if (fullName.endsWith(targetPath) || fullName === targetPath) {
|
|
67
|
+
return tarBuffer.slice(offset, offset + size).toString("utf8");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Saute le contenu (arrondi à 512)
|
|
71
|
+
offset += Math.ceil(size / 512) * 512;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function fetchShardJsFromNpm(version) {
|
|
77
|
+
const pkgShort = pkg.name.replace("@iksdev/", "");
|
|
78
|
+
const url = `https://registry.npmjs.org/${pkg.name}/-/${pkgShort}-${version}.tgz`;
|
|
79
|
+
|
|
80
|
+
console.log(` URL: ${url}`);
|
|
81
|
+
const tgzBuffer = await downloadBuffer(url);
|
|
82
|
+
if (!tgzBuffer) {
|
|
83
|
+
console.log(" ❌ Téléchargement échoué");
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
console.log(` ✅ Téléchargé (${(tgzBuffer.length / 1024).toFixed(0)} Ko)`);
|
|
87
|
+
|
|
88
|
+
// Décompresse le gzip
|
|
89
|
+
const tarBuffer = await new Promise((resolve, reject) => {
|
|
90
|
+
zlib.gunzip(tgzBuffer, (err, result) => {
|
|
91
|
+
if (err) reject(err);
|
|
92
|
+
else resolve(result);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Extrait bin/shard.js
|
|
97
|
+
const content = extractFileFromTar(tarBuffer, "bin/shard.js");
|
|
98
|
+
if (!content) {
|
|
99
|
+
console.log(" ❌ bin/shard.js introuvable dans le tarball");
|
|
100
|
+
} else {
|
|
101
|
+
console.log(` ✅ bin/shard.js extrait (${content.length} chars)`);
|
|
102
|
+
}
|
|
103
|
+
return content;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ─── Gemini ───────────────────────────────────────────────────────────────────
|
|
72
107
|
function geminiRequest(prompt) {
|
|
73
108
|
return new Promise((resolve, reject) => {
|
|
74
109
|
const body = JSON.stringify({
|
|
75
110
|
contents: [{ parts: [{ text: prompt }] }],
|
|
76
111
|
generationConfig: { maxOutputTokens: 500, temperature: 0.3 },
|
|
77
112
|
});
|
|
78
|
-
|
|
79
113
|
const req = https.request(
|
|
80
114
|
{
|
|
81
115
|
hostname: "generativelanguage.googleapis.com",
|
|
@@ -88,14 +122,12 @@ function geminiRequest(prompt) {
|
|
|
88
122
|
},
|
|
89
123
|
(res) => {
|
|
90
124
|
let data = "";
|
|
91
|
-
res.on("data", (
|
|
125
|
+
res.on("data", (c) => (data += c));
|
|
92
126
|
res.on("end", () => {
|
|
93
127
|
try {
|
|
94
128
|
const json = JSON.parse(data);
|
|
95
129
|
resolve(json.candidates?.[0]?.content?.parts?.[0]?.text || null);
|
|
96
|
-
} catch {
|
|
97
|
-
resolve(null);
|
|
98
|
-
}
|
|
130
|
+
} catch { resolve(null); }
|
|
99
131
|
});
|
|
100
132
|
}
|
|
101
133
|
);
|
|
@@ -124,11 +156,10 @@ Génère un changelog clair en français (max 6 points) basé uniquement sur les
|
|
|
124
156
|
return await geminiRequest(prompt);
|
|
125
157
|
}
|
|
126
158
|
|
|
127
|
-
// ───
|
|
159
|
+
// ─── Discord ──────────────────────────────────────────────────────────────────
|
|
128
160
|
function sendDiscord(changelog, prevVersion) {
|
|
129
161
|
return new Promise((resolve) => {
|
|
130
162
|
const fields = [];
|
|
131
|
-
|
|
132
163
|
if (changelog) {
|
|
133
164
|
fields.push({
|
|
134
165
|
name: `📋 Changements depuis v${prevVersion}`,
|
|
@@ -136,7 +167,6 @@ function sendDiscord(changelog, prevVersion) {
|
|
|
136
167
|
inline: false,
|
|
137
168
|
});
|
|
138
169
|
}
|
|
139
|
-
|
|
140
170
|
fields.push({
|
|
141
171
|
name: "📦 Mise à jour",
|
|
142
172
|
value: `\`\`\`bash\nnpm i -g ${pkg.name}@latest\n\`\`\``,
|