koishi-plugin-nitter 0.0.5 → 0.0.6

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/lib/index.d.ts CHANGED
@@ -19,3 +19,4 @@ export interface Config {
19
19
  }
20
20
  export declare const Config: Schema<Config, Dict>;
21
21
  export declare function apply(ctx: Context, config: Config): void;
22
+ export declare function downloadVideosToBase64(videoUrls: any): Promise<any[]>;
package/lib/index.js CHANGED
@@ -32,6 +32,7 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  Config: () => Config,
34
34
  apply: () => apply,
35
+ downloadVideosToBase64: () => downloadVideosToBase64,
35
36
  inject: () => inject,
36
37
  name: () => name
37
38
  });
@@ -154,13 +155,11 @@ __name(addTranslate, "addTranslate");
154
155
  var import_rettiwt_api = require("rettiwt-api");
155
156
  var import_node_cron = require("node-cron");
156
157
  var import_fluent_ffmpeg = __toESM(require("fluent-ffmpeg"));
157
- var import_ffmpeg_static = __toESM(require("ffmpeg-static"));
158
158
  var import_path = __toESM(require("path"));
159
159
  var import_promises = __toESM(require("fs/promises"));
160
- var import_url = require("url");
161
160
  var import_jsx_runtime = require("@satorijs/element/jsx-runtime");
162
- import_fluent_ffmpeg.default.setFfmpegPath(import_ffmpeg_static.default);
163
161
  var name = "nitter";
162
+ var logger = new import_koishi.Logger(name);
164
163
  var inject = ["puppeteer", "subscription"];
165
164
  var Config = import_koishi.Schema.intersect([
166
165
  import_koishi.Schema.object({
@@ -248,15 +247,14 @@ function apply(ctx, config) {
248
247
  const [screenshot, imageUrls, hlsUrls] = await renderTweetScreenshot(ctx, tweetId, config);
249
248
  let msg = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: "data:image/png;base64," + screenshot.toString("base64") });
250
249
  let forwardMsg = [];
251
- const videoUrls = await downloadAndConvertVideos(hlsUrls);
250
+ const videoUrls = await downloadVideosToBase64(hlsUrls);
252
251
  if (imageUrls.length > 0) {
253
252
  forwardMsg.push(...imageUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: url }) })));
254
253
  }
255
254
  if (videoUrls.length > 0) {
256
- forwardMsg.push(...videoUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("video", { src: (0, import_url.pathToFileURL)(url).href }) })));
255
+ forwardMsg.push(...videoUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("video", { src: url }) })));
257
256
  }
258
257
  await session.send(msg + /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { forward: true, children: forwardMsg }));
259
- await deleteFiles(videoUrls);
260
258
  } catch (error) {
261
259
  ctx.logger("nitter").error("获取推文失败:", error);
262
260
  return "获取推文失败";
@@ -273,18 +271,17 @@ function apply(ctx, config) {
273
271
  const [screenshot, imageUrls, hlsUrls] = await renderTweetScreenshot(ctx, tweetId, config);
274
272
  const screenshotMsg = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: "data:image/png;base64," + screenshot.toString("base64") });
275
273
  ctx.subscription.broadcast(config.app, account, screenshotMsg);
276
- let forwardMsg = ``;
277
- const videoUrls = await downloadAndConvertVideos(hlsUrls);
274
+ let forwardMsg = [];
275
+ const videoUrls = await downloadVideosToBase64(hlsUrls);
278
276
  if (imageUrls.length > 0) {
279
- forwardMsg += imageUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: url }) }));
277
+ forwardMsg.push(...imageUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: url }) })));
280
278
  }
281
279
  if (videoUrls.length > 0) {
282
- forwardMsg += videoUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("video", { src: (0, import_url.pathToFileURL)(url).href }) }));
280
+ forwardMsg.push(...videoUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("video", { src: url }) })));
283
281
  }
284
282
  if (forwardMsg.length > 0) {
285
283
  await ctx.subscription.broadcastForward(config.app, account, forwardMsg);
286
284
  }
287
- await deleteFiles(videoUrls);
288
285
  } catch (error) {
289
286
  ctx.logger("nitter").error("获取推文失败:", error);
290
287
  }
@@ -316,33 +313,47 @@ function apply(ctx, config) {
316
313
  }
317
314
  __name(apply, "apply");
318
315
  var tempDir = import_path.default.join(process.cwd(), "tmp");
319
- async function downloadAndConvertVideos(videoUrls) {
316
+ async function downloadVideosToBase64(videoUrls) {
320
317
  await import_promises.default.mkdir(tempDir, { recursive: true });
321
- const promises = videoUrls.map(async (url, index) => {
318
+ const results = [];
319
+ for (const url of videoUrls) {
320
+ let outputPath = null;
322
321
  try {
323
- const outputPath = import_path.default.join(tempDir, `video_${index}_${Date.now()}.mp4`);
322
+ outputPath = import_path.default.join(tempDir, `video_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.mp4`);
324
323
  await new Promise((resolve, reject) => {
325
- (0, import_fluent_ffmpeg.default)(url).output(outputPath).on("end", () => {
326
- resolve(outputPath);
327
- }).on("error", reject).run();
324
+ (0, import_fluent_ffmpeg.default)(url).inputOptions([
325
+ "-protocol_whitelist",
326
+ "file,http,https,tcp,tls,crypto"
327
+ ]).outputOptions([
328
+ "-c",
329
+ "copy"
330
+ ]).output(outputPath).on("end", () => resolve(outputPath)).on("error", reject).run();
328
331
  });
329
- return outputPath;
332
+ const stats = await import_promises.default.stat(outputPath);
333
+ const fileSizeInMB = stats.size / (1024 * 1024);
334
+ if (fileSizeInMB > 10) {
335
+ logger.info(`视频大小 ${fileSizeInMB.toFixed(2)}MB 超过10MB限制,跳过转换`);
336
+ } else {
337
+ const fileBuffer = await import_promises.default.readFile(outputPath);
338
+ const base64String = fileBuffer.toString("base64");
339
+ const dataUrl = `data:video/mp4;base64,${base64String}`;
340
+ results.push(dataUrl);
341
+ }
330
342
  } catch (error) {
331
343
  console.error(`处理失败 (${url}):`, error.message);
332
- return null;
344
+ results.push(null);
345
+ } finally {
346
+ if (outputPath) {
347
+ try {
348
+ await import_promises.default.unlink(outputPath);
349
+ } catch (deleteError) {
350
+ }
351
+ }
333
352
  }
334
- });
335
- const results = await Promise.all(promises);
336
- return results.filter((path2) => path2 !== null);
337
- }
338
- __name(downloadAndConvertVideos, "downloadAndConvertVideos");
339
- async function deleteFiles(filePaths) {
340
- await Promise.allSettled(
341
- filePaths.map((filePath) => import_promises.default.unlink(filePath).catch(() => {
342
- }))
343
- );
353
+ }
354
+ return results;
344
355
  }
345
- __name(deleteFiles, "deleteFiles");
356
+ __name(downloadVideosToBase64, "downloadVideosToBase64");
346
357
  async function renderTweetScreenshot(ctx, tweetId, config) {
347
358
  const puppeteer = ctx.puppeteer;
348
359
  if (!puppeteer) {
@@ -399,6 +410,7 @@ __name(renderTweetScreenshot, "renderTweetScreenshot");
399
410
  0 && (module.exports = {
400
411
  Config,
401
412
  apply,
413
+ downloadVideosToBase64,
402
414
  inject,
403
415
  name
404
416
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-nitter",
3
3
  "description": "使用Rettiwt-API订阅推文,并使用nitter渲染",
4
- "version": "0.0.5",
4
+ "version": "0.0.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -24,7 +24,6 @@
24
24
  "dependencies": {
25
25
  "node-cron": "^4.2.1",
26
26
  "rettiwt-api": "^6.0.6",
27
- "ffmpeg-static": "^5.2.0",
28
27
  "fluent-ffmpeg": "^2.1.3"
29
28
  }
30
29
  }