@iksdev/shard-cli 0.1.27 → 0.1.29
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 +92 -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,101 @@ 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
|
+
function extractFileFromTar(tarBuffer, targetPath) {
|
|
49
|
+
let offset = 0;
|
|
50
|
+
const found = [];
|
|
51
|
+
|
|
52
|
+
while (offset + 512 <= tarBuffer.length) {
|
|
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;
|
|
56
|
+
|
|
57
|
+
const sizeOctal = header.slice(124, 136).toString("utf8").replace(/\0/g, "").trim();
|
|
58
|
+
const size = parseInt(sizeOctal, 8) || 0;
|
|
59
|
+
|
|
60
|
+
const prefix = header.slice(345, 500).toString("utf8").replace(/\0/g, "").trim();
|
|
61
|
+
const fullName = prefix ? `${prefix}/${nameRaw}` : nameRaw;
|
|
62
|
+
|
|
63
|
+
offset += 512;
|
|
64
|
+
|
|
65
|
+
// Log tous les fichiers trouvés pour debug
|
|
66
|
+
if (size > 0) found.push(fullName);
|
|
67
|
+
|
|
68
|
+
if (fullName.endsWith(targetPath) || fullName === targetPath) {
|
|
69
|
+
console.log(` ✅ Trouvé: ${fullName}`);
|
|
70
|
+
return tarBuffer.slice(offset, offset + size).toString("utf8");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
offset += Math.ceil(size / 512) * 512;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Si pas trouvé, affiche tous les fichiers du tarball
|
|
77
|
+
console.log(` ❌ "${targetPath}" introuvable. Fichiers dans le tarball:`);
|
|
78
|
+
found.forEach((f) => console.log(` - ${f}`));
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function fetchShardJsFromNpm(version) {
|
|
83
|
+
const pkgShort = pkg.name.replace("@iksdev/", "");
|
|
84
|
+
const url = `https://registry.npmjs.org/${pkg.name}/-/${pkgShort}-${version}.tgz`;
|
|
85
|
+
|
|
86
|
+
console.log(` URL: ${url}`);
|
|
87
|
+
const tgzBuffer = await downloadBuffer(url);
|
|
88
|
+
if (!tgzBuffer) {
|
|
89
|
+
console.log(" ❌ Téléchargement échoué");
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
console.log(` ✅ Téléchargé (${(tgzBuffer.length / 1024).toFixed(0)} Ko)`);
|
|
93
|
+
|
|
94
|
+
const tarBuffer = await new Promise((resolve, reject) => {
|
|
95
|
+
zlib.gunzip(tgzBuffer, (err, result) => {
|
|
96
|
+
if (err) { console.log(" ❌ Erreur gunzip:", err.message); reject(err); }
|
|
97
|
+
else resolve(result);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
console.log(` ✅ Décompressé (${(tarBuffer.length / 1024).toFixed(0)} Ko)`);
|
|
102
|
+
const content = extractFileFromTar(tarBuffer, "bin/shard.js");
|
|
103
|
+
if (content) console.log(` ✅ bin/shard.js extrait (${content.length} chars)`);
|
|
104
|
+
return content;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ─── Gemini ───────────────────────────────────────────────────────────────────
|
|
72
108
|
function geminiRequest(prompt) {
|
|
73
109
|
return new Promise((resolve, reject) => {
|
|
74
110
|
const body = JSON.stringify({
|
|
75
111
|
contents: [{ parts: [{ text: prompt }] }],
|
|
76
112
|
generationConfig: { maxOutputTokens: 500, temperature: 0.3 },
|
|
77
113
|
});
|
|
78
|
-
|
|
79
114
|
const req = https.request(
|
|
80
115
|
{
|
|
81
116
|
hostname: "generativelanguage.googleapis.com",
|
|
@@ -88,18 +123,27 @@ function geminiRequest(prompt) {
|
|
|
88
123
|
},
|
|
89
124
|
(res) => {
|
|
90
125
|
let data = "";
|
|
91
|
-
|
|
126
|
+
console.log(` Gemini HTTP status: ${res.statusCode}`);
|
|
127
|
+
res.on("data", (c) => (data += c));
|
|
92
128
|
res.on("end", () => {
|
|
93
129
|
try {
|
|
94
130
|
const json = JSON.parse(data);
|
|
95
|
-
|
|
96
|
-
|
|
131
|
+
// Log la réponse complète si erreur
|
|
132
|
+
if (res.statusCode !== 200) {
|
|
133
|
+
console.log(" ❌ Réponse Gemini:", JSON.stringify(json, null, 2));
|
|
134
|
+
}
|
|
135
|
+
const text = json.candidates?.[0]?.content?.parts?.[0]?.text || null;
|
|
136
|
+
console.log(text ? ` ✅ Changelog généré (${text.length} chars)` : " ❌ Gemini a retourné null");
|
|
137
|
+
resolve(text);
|
|
138
|
+
} catch (e) {
|
|
139
|
+
console.log(" ❌ Parse JSON échoué:", e.message);
|
|
140
|
+
console.log(" Raw response:", data.slice(0, 500));
|
|
97
141
|
resolve(null);
|
|
98
142
|
}
|
|
99
143
|
});
|
|
100
144
|
}
|
|
101
145
|
);
|
|
102
|
-
req.on("error", reject);
|
|
146
|
+
req.on("error", (e) => { console.log(" ❌ Erreur réseau Gemini:", e.message); reject(e); });
|
|
103
147
|
req.write(body);
|
|
104
148
|
req.end();
|
|
105
149
|
});
|
|
@@ -124,11 +168,10 @@ Génère un changelog clair en français (max 6 points) basé uniquement sur les
|
|
|
124
168
|
return await geminiRequest(prompt);
|
|
125
169
|
}
|
|
126
170
|
|
|
127
|
-
// ───
|
|
171
|
+
// ─── Discord ──────────────────────────────────────────────────────────────────
|
|
128
172
|
function sendDiscord(changelog, prevVersion) {
|
|
129
173
|
return new Promise((resolve) => {
|
|
130
174
|
const fields = [];
|
|
131
|
-
|
|
132
175
|
if (changelog) {
|
|
133
176
|
fields.push({
|
|
134
177
|
name: `📋 Changements depuis v${prevVersion}`,
|
|
@@ -136,7 +179,6 @@ function sendDiscord(changelog, prevVersion) {
|
|
|
136
179
|
inline: false,
|
|
137
180
|
});
|
|
138
181
|
}
|
|
139
|
-
|
|
140
182
|
fields.push({
|
|
141
183
|
name: "📦 Mise à jour",
|
|
142
184
|
value: `\`\`\`bash\nnpm i -g ${pkg.name}@latest\n\`\`\``,
|
|
@@ -190,6 +232,7 @@ function sendDiscord(changelog, prevVersion) {
|
|
|
190
232
|
(async () => {
|
|
191
233
|
console.log("🔍 Récupération de la version précédente sur npm...");
|
|
192
234
|
const prevVersion = await getPreviousVersion();
|
|
235
|
+
console.log(` Version précédente: ${prevVersion}`);
|
|
193
236
|
|
|
194
237
|
if (!prevVersion) {
|
|
195
238
|
console.log("⚠️ Pas de version précédente, envoi sans changelog.");
|
|
@@ -200,9 +243,11 @@ function sendDiscord(changelog, prevVersion) {
|
|
|
200
243
|
console.log(`📥 Téléchargement de shard.js v${prevVersion} depuis npm...`);
|
|
201
244
|
const oldCode = await fetchShardJsFromNpm(prevVersion);
|
|
202
245
|
|
|
246
|
+
console.log("📂 Lecture de bin/shard.js local...");
|
|
203
247
|
const newCode = fs.existsSync("./bin/shard.js")
|
|
204
248
|
? fs.readFileSync("./bin/shard.js", "utf-8")
|
|
205
249
|
: null;
|
|
250
|
+
console.log(newCode ? ` ✅ Lu (${newCode.length} chars)` : " ❌ ./bin/shard.js introuvable");
|
|
206
251
|
|
|
207
252
|
if (!oldCode || !newCode) {
|
|
208
253
|
console.log("⚠️ Fichiers introuvables, envoi sans changelog.");
|