@iksdev/shard-cli 0.1.33 → 0.1.35
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/shard.js +2 -2
- package/notify-discord.js +33 -240
- package/package.json +1 -1
package/bin/shard.js
CHANGED
|
@@ -17,9 +17,9 @@ const DEFAULT_SERVER = 'https://shard-0ow4.onrender.com';
|
|
|
17
17
|
const IGNORED_DIRS = new Set(['.git', 'node_modules']);
|
|
18
18
|
|
|
19
19
|
function printHelp() {
|
|
20
|
-
console.log(`
|
|
20
|
+
console.log(`
|
|
21
21
|
╔══════════════════════════════════════════════════╗
|
|
22
|
-
║
|
|
22
|
+
║ Shard ║
|
|
23
23
|
╚══════════════════════════════════════════════════╝
|
|
24
24
|
|
|
25
25
|
Commandes disponibles:
|
package/notify-discord.js
CHANGED
|
@@ -1,247 +1,40 @@
|
|
|
1
1
|
const https = require("https");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const zlib = require("zlib");
|
|
5
|
-
const os = require("os");
|
|
6
2
|
const pkg = require("./package.json");
|
|
7
3
|
|
|
8
4
|
const WEBHOOK = "https://discord.com/api/webhooks/1476384127594004511/A2P7cXIC9Z1rfbEo5Wvxgdsnb2VcJ-NjiGFGnvmnjbF2tm2jW4qGBRS4GgEcZ7hHJGUp";
|
|
9
|
-
const GEMINI_KEY = "AIzaSyBXSnhnYSI6A1cgYAQzmE7pWmmOZi3H334"; // https://aistudio.google.com/apikey
|
|
10
5
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
if (res.statusCode !== 200) return resolve(null);
|
|
40
|
-
const chunks = [];
|
|
41
|
-
res.on("data", (c) => chunks.push(c));
|
|
42
|
-
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
43
|
-
}).on("error", () => resolve(null));
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
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");
|
|
6
|
+
const body = JSON.stringify({
|
|
7
|
+
embeds: [{
|
|
8
|
+
author: {
|
|
9
|
+
name: "npm • nouvelle version disponible",
|
|
10
|
+
icon_url: "https://static-production.npmjs.com/b0f1a8318363185cc2ea6a40ac23eeb2.png",
|
|
11
|
+
},
|
|
12
|
+
title: `🚀 ${pkg.name} — v${pkg.version}`,
|
|
13
|
+
url: `https://www.npmjs.com/package/${pkg.name}/v/${pkg.version}`,
|
|
14
|
+
color: 0x5865f2,
|
|
15
|
+
fields: [{
|
|
16
|
+
name: "📦 Mettre à jour",
|
|
17
|
+
value: `\`\`\`\nnpm i -g ${pkg.name}@latest\n\`\`\``,
|
|
18
|
+
}],
|
|
19
|
+
footer: { text: "Publié le" },
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
}],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const url = new URL(WEBHOOK);
|
|
25
|
+
const req = https.request({
|
|
26
|
+
hostname: url.hostname,
|
|
27
|
+
path: url.pathname + url.search,
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) },
|
|
30
|
+
}, (res) => {
|
|
31
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
32
|
+
console.log(`✅ Notification Discord envoyée (v${pkg.version})`);
|
|
100
33
|
} else {
|
|
101
|
-
|
|
34
|
+
res.setEncoding("utf-8");
|
|
35
|
+
res.on("data", (d) => console.error("❌ Erreur Discord :", d));
|
|
102
36
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
function geminiRequest(prompt) {
|
|
108
|
-
return new Promise((resolve, reject) => {
|
|
109
|
-
const body = JSON.stringify({
|
|
110
|
-
contents: [{ parts: [{ text: prompt }] }],
|
|
111
|
-
generationConfig: { maxOutputTokens: 500, temperature: 0.3 },
|
|
112
|
-
});
|
|
113
|
-
const req = https.request(
|
|
114
|
-
{
|
|
115
|
-
hostname: "generativelanguage.googleapis.com",
|
|
116
|
-
path: `/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`,
|
|
117
|
-
method: "POST",
|
|
118
|
-
headers: {
|
|
119
|
-
"Content-Type": "application/json",
|
|
120
|
-
"Content-Length": Buffer.byteLength(body),
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
(res) => {
|
|
124
|
-
let data = "";
|
|
125
|
-
res.on("data", (c) => (data += c));
|
|
126
|
-
res.on("end", () => {
|
|
127
|
-
try {
|
|
128
|
-
const json = JSON.parse(data);
|
|
129
|
-
resolve(json.candidates?.[0]?.content?.parts?.[0]?.text || null);
|
|
130
|
-
} catch { resolve(null); }
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
req.on("error", reject);
|
|
135
|
-
req.write(body);
|
|
136
|
-
req.end();
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async function generateChangelog(oldCode, newCode, prevVersion) {
|
|
141
|
-
const maxLen = 6000;
|
|
142
|
-
const prompt = `Tu es un expert Node.js. Compare ces deux versions du CLI "${pkg.name}".
|
|
143
|
-
|
|
144
|
-
=== VERSION PRÉCÉDENTE (v${prevVersion}) ===
|
|
145
|
-
${oldCode.slice(0, maxLen)}
|
|
146
|
-
|
|
147
|
-
=== NOUVELLE VERSION (v${pkg.version}) ===
|
|
148
|
-
${newCode.slice(0, maxLen)}
|
|
149
|
-
|
|
150
|
-
Génère un changelog clair en français (max 6 points) basé uniquement sur les vraies différences de code. Utilise des emojis. Pas d'introduction, juste les bullet points :
|
|
151
|
-
✨ Ajout de X
|
|
152
|
-
🐛 Correction de Y
|
|
153
|
-
⚡ Amélioration de Z
|
|
154
|
-
🗑️ Suppression de W`;
|
|
155
|
-
|
|
156
|
-
return await geminiRequest(prompt);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ─── Discord ──────────────────────────────────────────────────────────────────
|
|
160
|
-
function sendDiscord(changelog, prevVersion) {
|
|
161
|
-
return new Promise((resolve) => {
|
|
162
|
-
const fields = [];
|
|
163
|
-
if (changelog) {
|
|
164
|
-
fields.push({
|
|
165
|
-
name: `📋 Changements depuis v${prevVersion}`,
|
|
166
|
-
value: changelog.slice(0, 1024),
|
|
167
|
-
inline: false,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
fields.push({
|
|
171
|
-
name: "📦 Mise à jour",
|
|
172
|
-
value: `\`\`\`bash\nnpm i -g ${pkg.name}@latest\n\`\`\``,
|
|
173
|
-
inline: false,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const body = JSON.stringify({
|
|
177
|
-
embeds: [{
|
|
178
|
-
author: {
|
|
179
|
-
name: "npm • nouvelle version disponible",
|
|
180
|
-
icon_url: "https://static-production.npmjs.com/b0f1a8318363185cc2ea6a40ac23eeb2.png",
|
|
181
|
-
},
|
|
182
|
-
title: `🚀 ${pkg.name} — v${pkg.version}`,
|
|
183
|
-
url: `https://www.npmjs.com/package/${pkg.name}/v/${pkg.version}`,
|
|
184
|
-
description: `> ${pkg.description}`,
|
|
185
|
-
color: 0x5865f2,
|
|
186
|
-
fields,
|
|
187
|
-
footer: { text: `v${prevVersion} → v${pkg.version}` },
|
|
188
|
-
timestamp: new Date().toISOString(),
|
|
189
|
-
}],
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const url = new URL(WEBHOOK);
|
|
193
|
-
const req = https.request(
|
|
194
|
-
{
|
|
195
|
-
hostname: url.hostname,
|
|
196
|
-
path: url.pathname + url.search,
|
|
197
|
-
method: "POST",
|
|
198
|
-
headers: {
|
|
199
|
-
"Content-Type": "application/json",
|
|
200
|
-
"Content-Length": Buffer.byteLength(body),
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
(res) => {
|
|
204
|
-
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
205
|
-
console.log(`✅ Notification Discord envoyée (v${pkg.version})`);
|
|
206
|
-
} else {
|
|
207
|
-
res.setEncoding("utf-8");
|
|
208
|
-
res.on("data", (d) => console.error("❌ Erreur Discord :", d));
|
|
209
|
-
}
|
|
210
|
-
resolve();
|
|
211
|
-
}
|
|
212
|
-
);
|
|
213
|
-
req.on("error", (e) => { console.error("❌ Réseau :", e.message); resolve(); });
|
|
214
|
-
req.write(body);
|
|
215
|
-
req.end();
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
220
|
-
(async () => {
|
|
221
|
-
console.log("🔍 Récupération de la version précédente sur npm...");
|
|
222
|
-
const prevVersion = await getPreviousVersion();
|
|
223
|
-
|
|
224
|
-
if (!prevVersion) {
|
|
225
|
-
console.log("⚠️ Pas de version précédente, envoi sans changelog.");
|
|
226
|
-
await sendDiscord(null, "?");
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
console.log(`📥 Téléchargement de shard.js v${prevVersion} depuis npm...`);
|
|
231
|
-
const oldCode = await fetchShardJsFromNpm(prevVersion);
|
|
232
|
-
|
|
233
|
-
const newCode = fs.existsSync("./bin/shard.js")
|
|
234
|
-
? fs.readFileSync("./bin/shard.js", "utf-8")
|
|
235
|
-
: null;
|
|
236
|
-
|
|
237
|
-
if (!oldCode || !newCode) {
|
|
238
|
-
console.log("⚠️ Fichiers introuvables, envoi sans changelog.");
|
|
239
|
-
await sendDiscord(null, prevVersion);
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
console.log("🤖 Analyse des différences avec Gemini...");
|
|
244
|
-
const changelog = await generateChangelog(oldCode, newCode, prevVersion);
|
|
245
|
-
|
|
246
|
-
await sendDiscord(changelog, prevVersion);
|
|
247
|
-
})();
|
|
37
|
+
});
|
|
38
|
+
req.on("error", (e) => console.error("❌ Réseau :", e.message));
|
|
39
|
+
req.write(body);
|
|
40
|
+
req.end();
|