lark-agent-bot 0.3.11 → 0.3.13
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/README.md +6 -0
- package/install.js +112 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,12 @@ npm install -g lark-agent-bot
|
|
|
12
12
|
The postinstall step downloads the prebuilt binary for your platform from
|
|
13
13
|
[GitHub Releases](https://github.com/ClaymanTwinkle/lark-agent-bot/releases).
|
|
14
14
|
|
|
15
|
+
If `ffmpeg` is not on your `PATH`, it also downloads a static ffmpeg build
|
|
16
|
+
([ffmpeg-static](https://github.com/eugeneware/ffmpeg-static), checksum-verified)
|
|
17
|
+
to `~/.lark-agent-bot/bin`, outside the package so upgrades keep it; voice
|
|
18
|
+
messages and video covers need it. Set `LARK_AGENT_BOT_SKIP_FFMPEG=1` to skip
|
|
19
|
+
this step.
|
|
20
|
+
|
|
15
21
|
## Usage
|
|
16
22
|
|
|
17
23
|
```bash
|
package/install.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { execSync } = require("child_process");
|
|
5
|
+
const { execFileSync, execSync } = require("child_process");
|
|
6
|
+
const crypto = require("crypto");
|
|
6
7
|
const fs = require("fs");
|
|
8
|
+
const os = require("os");
|
|
7
9
|
const path = require("path");
|
|
8
10
|
const https = require("https");
|
|
9
11
|
const http = require("http");
|
|
@@ -15,6 +17,22 @@ const NAME = "lark-agent-bot";
|
|
|
15
17
|
|
|
16
18
|
const GITHUB_REPO = "ClaymanTwinkle/lark-agent-bot";
|
|
17
19
|
|
|
20
|
+
// Voice messages and video covers need ffmpeg. When it isn't on PATH, a
|
|
21
|
+
// static build from ffmpeg-static goes to ~/.lark-agent-bot/bin, where
|
|
22
|
+
// lark-agent-bot also looks. That directory is outside the npm package, so
|
|
23
|
+
// upgrades (which replace the package directory) keep it. Set
|
|
24
|
+
// LARK_AGENT_BOT_SKIP_FFMPEG=1 to skip.
|
|
25
|
+
const FFMPEG_REPO = "eugeneware/ffmpeg-static";
|
|
26
|
+
const FFMPEG_RELEASE = "b6.1.1";
|
|
27
|
+
// SHA-256 of each ffmpeg-<platform>-<arch>.gz asset in FFMPEG_RELEASE.
|
|
28
|
+
const FFMPEG_SHA256 = {
|
|
29
|
+
"darwin-arm64": "8923876afa8db5585022d7860ec7e589af192f441c56793971276d450ed3bbfa",
|
|
30
|
+
"darwin-x64": "929b375c1182d956c51f7ac25e0b2b0411fb01f6f407aa15c9758efeb4242106",
|
|
31
|
+
"linux-arm64": "754a678672298bc68156adff58aa7385a592c2b30b1d0ae8750c45c915c4bac0",
|
|
32
|
+
"linux-x64": "bfe8a8fc511530457b528c48d77b5737527b504a3797a9bc4866aeca69c2dffa",
|
|
33
|
+
"win32-x64": "8883a3dffbd0a16cf4ef95206ea05283f78908dbfb118f73c83f4951dcc06d77",
|
|
34
|
+
};
|
|
35
|
+
|
|
18
36
|
const PLATFORM_MAP = {
|
|
19
37
|
darwin: "darwin",
|
|
20
38
|
linux: "linux",
|
|
@@ -149,11 +167,91 @@ function isNewerOrEqual(installed, expected) {
|
|
|
149
167
|
return a.preNum >= b.preNum;
|
|
150
168
|
}
|
|
151
169
|
|
|
170
|
+
function hasFFmpegOnPath() {
|
|
171
|
+
try {
|
|
172
|
+
execFileSync("ffmpeg", ["-version"], { stdio: "ignore", timeout: 10000 });
|
|
173
|
+
return true;
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function ffmpegToolDir() {
|
|
180
|
+
return path.join(os.homedir(), ".lark-agent-bot", "bin");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function ffmpegHint(toolDir) {
|
|
184
|
+
return (
|
|
185
|
+
"[lark-agent-bot] Voice messages and video covers need ffmpeg. Install it yourself:\n" +
|
|
186
|
+
" Windows: winget install Gyan.FFmpeg\n" +
|
|
187
|
+
" macOS: brew install ffmpeg\n" +
|
|
188
|
+
" Linux: sudo apt install ffmpeg (or your distro's package manager)\n" +
|
|
189
|
+
` or put an ffmpeg executable in ${toolDir}`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// installFFmpeg never fails the install: without ffmpeg lark-agent-bot still
|
|
194
|
+
// works, it only loses voice conversion and video covers.
|
|
195
|
+
async function installFFmpeg(toolDir) {
|
|
196
|
+
if (process.env.LARK_AGENT_BOT_SKIP_FFMPEG) {
|
|
197
|
+
console.log("[lark-agent-bot] LARK_AGENT_BOT_SKIP_FFMPEG is set, skipping ffmpeg.");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const ffmpegPath = path.join(toolDir, process.platform === "win32" ? "ffmpeg.exe" : "ffmpeg");
|
|
201
|
+
if (fs.existsSync(ffmpegPath)) {
|
|
202
|
+
console.log(`[lark-agent-bot] ffmpeg already at ${ffmpegPath}, skipping.`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (hasFFmpegOnPath()) {
|
|
206
|
+
console.log("[lark-agent-bot] ffmpeg found on PATH, skipping.");
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const key = `${process.platform}-${process.arch}`;
|
|
211
|
+
const sha256 = FFMPEG_SHA256[key];
|
|
212
|
+
if (!sha256) {
|
|
213
|
+
console.warn(`[lark-agent-bot] No prebuilt ffmpeg for ${key}.`);
|
|
214
|
+
console.warn(ffmpegHint(toolDir));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const url = `https://github.com/${FFMPEG_REPO}/releases/download/${FFMPEG_RELEASE}/ffmpeg-${key}.gz`;
|
|
219
|
+
const tmpPath = `${ffmpegPath}.download`;
|
|
220
|
+
try {
|
|
221
|
+
console.log(`[lark-agent-bot] ffmpeg not found, downloading from ${url}`);
|
|
222
|
+
const gz = await fetch(url);
|
|
223
|
+
fs.mkdirSync(toolDir, { recursive: true });
|
|
224
|
+
const actual = crypto.createHash("sha256").update(gz).digest("hex");
|
|
225
|
+
if (actual !== sha256) {
|
|
226
|
+
throw new Error(`checksum mismatch: got ${actual}, want ${sha256}`);
|
|
227
|
+
}
|
|
228
|
+
fs.writeFileSync(tmpPath, zlib.gunzipSync(gz), { mode: 0o755 });
|
|
229
|
+
fs.renameSync(tmpPath, ffmpegPath);
|
|
230
|
+
if (process.platform === "darwin") {
|
|
231
|
+
try {
|
|
232
|
+
execSync(`xattr -d com.apple.quarantine "${ffmpegPath}"`, { stdio: "pipe" });
|
|
233
|
+
} catch {
|
|
234
|
+
// xattr fails if the attribute doesn't exist, which is fine
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
console.log(`[lark-agent-bot] Installed ffmpeg to ${ffmpegPath}`);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
try { fs.unlinkSync(tmpPath); } catch {}
|
|
240
|
+
console.warn(`[lark-agent-bot] Could not install ffmpeg: ${err.message}`);
|
|
241
|
+
console.warn(ffmpegHint(toolDir));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
152
245
|
async function main() {
|
|
246
|
+
const binDir = path.join(__dirname, "bin");
|
|
247
|
+
await installBinary(binDir);
|
|
248
|
+
await installFFmpeg(ffmpegToolDir());
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async function installBinary(binDir) {
|
|
153
252
|
const { platform, arch, ext, filename } = getPlatformInfo();
|
|
154
253
|
console.log(`[lark-agent-bot] Platform: ${platform}/${arch}`);
|
|
155
254
|
|
|
156
|
-
const binDir = path.join(__dirname, "bin");
|
|
157
255
|
fs.mkdirSync(binDir, { recursive: true });
|
|
158
256
|
|
|
159
257
|
const binaryName = platform === "windows" ? `${NAME}.exe` : NAME;
|
|
@@ -206,11 +304,15 @@ async function main() {
|
|
|
206
304
|
console.log(`[lark-agent-bot] Installed to ${binaryPath}`);
|
|
207
305
|
}
|
|
208
306
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
307
|
+
if (require.main === module) {
|
|
308
|
+
main().catch((err) => {
|
|
309
|
+
console.error(err.message);
|
|
310
|
+
console.error(
|
|
311
|
+
"[lark-agent-bot] Installation failed. You can install manually:\n" +
|
|
312
|
+
` https://github.com/${GITHUB_REPO}/releases/tag/${VERSION}`
|
|
313
|
+
);
|
|
314
|
+
process.exit(1);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
module.exports = { installFFmpeg };
|