koztv-blog-tools 1.3.1 → 1.3.2

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/dist/node.js CHANGED
@@ -375,6 +375,30 @@ var import_sessions = require("telegram/sessions/index.js");
375
375
  var fs = __toESM(require("fs"));
376
376
  var path = __toESM(require("path"));
377
377
  var readline = __toESM(require("readline"));
378
+ var import_child_process = require("child_process");
379
+ var MAX_FILE_SIZE = 95 * 1024 * 1024;
380
+ var COMPRESS_THRESHOLD = 50 * 1024 * 1024;
381
+ function hasFFmpeg() {
382
+ try {
383
+ (0, import_child_process.execSync)("ffmpeg -version", { stdio: "ignore" });
384
+ return true;
385
+ } catch {
386
+ return false;
387
+ }
388
+ }
389
+ function compressVideo(inputPath, outputPath) {
390
+ try {
391
+ (0, import_child_process.execSync)(
392
+ `ffmpeg -i "${inputPath}" -vf "scale='min(1280,iw)':'-2'" -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k -y "${outputPath}"`,
393
+ { stdio: "ignore", timeout: 3e5 }
394
+ // 5 min timeout
395
+ );
396
+ const stats = fs.statSync(outputPath);
397
+ return stats.size <= MAX_FILE_SIZE;
398
+ } catch {
399
+ return false;
400
+ }
401
+ }
378
402
  function entitiesToMarkdown(text, entities) {
379
403
  if (!entities || entities.length === 0) return text;
380
404
  const mergedEntities = [];
@@ -655,7 +679,39 @@ async function exportTelegramChannel(options) {
655
679
  const mediaFileName = `media${ext}`;
656
680
  const mediaPath = path.join(postMediaDir, mediaFileName);
657
681
  fs.writeFileSync(mediaPath, buffer);
658
- mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
682
+ const stats = fs.statSync(mediaPath);
683
+ const isVideo = [".mp4", ".mov", ".avi", ".webm", ".m4v"].includes(ext.toLowerCase());
684
+ if (stats.size > MAX_FILE_SIZE) {
685
+ if (isVideo && hasFFmpeg()) {
686
+ const compressedPath = path.join(postMediaDir, `media_compressed${ext}`);
687
+ if (compressVideo(mediaPath, compressedPath)) {
688
+ fs.unlinkSync(mediaPath);
689
+ fs.renameSync(compressedPath, mediaPath);
690
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
691
+ } else {
692
+ fs.unlinkSync(mediaPath);
693
+ if (fs.existsSync(compressedPath)) fs.unlinkSync(compressedPath);
694
+ console.warn(`Skipping large media for message ${msgId} (>${MAX_FILE_SIZE / 1024 / 1024}MB)`);
695
+ }
696
+ } else {
697
+ fs.unlinkSync(mediaPath);
698
+ console.warn(`Skipping large media for message ${msgId} (>${MAX_FILE_SIZE / 1024 / 1024}MB)`);
699
+ }
700
+ } else if (stats.size > COMPRESS_THRESHOLD && isVideo && hasFFmpeg()) {
701
+ const compressedPath = path.join(postMediaDir, `media_compressed${ext}`);
702
+ if (compressVideo(mediaPath, compressedPath)) {
703
+ const compressedStats = fs.statSync(compressedPath);
704
+ if (compressedStats.size < stats.size) {
705
+ fs.unlinkSync(mediaPath);
706
+ fs.renameSync(compressedPath, mediaPath);
707
+ } else {
708
+ fs.unlinkSync(compressedPath);
709
+ }
710
+ }
711
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
712
+ } else {
713
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
714
+ }
659
715
  }
660
716
  } catch (e) {
661
717
  console.error(`Error downloading media for message ${msgId}:`, e);
package/dist/node.mjs CHANGED
@@ -25,6 +25,30 @@ import { StringSession } from "telegram/sessions/index.js";
25
25
  import * as fs from "fs";
26
26
  import * as path from "path";
27
27
  import * as readline from "readline";
28
+ import { execSync } from "child_process";
29
+ var MAX_FILE_SIZE = 95 * 1024 * 1024;
30
+ var COMPRESS_THRESHOLD = 50 * 1024 * 1024;
31
+ function hasFFmpeg() {
32
+ try {
33
+ execSync("ffmpeg -version", { stdio: "ignore" });
34
+ return true;
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+ function compressVideo(inputPath, outputPath) {
40
+ try {
41
+ execSync(
42
+ `ffmpeg -i "${inputPath}" -vf "scale='min(1280,iw)':'-2'" -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k -y "${outputPath}"`,
43
+ { stdio: "ignore", timeout: 3e5 }
44
+ // 5 min timeout
45
+ );
46
+ const stats = fs.statSync(outputPath);
47
+ return stats.size <= MAX_FILE_SIZE;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
28
52
  function entitiesToMarkdown(text, entities) {
29
53
  if (!entities || entities.length === 0) return text;
30
54
  const mergedEntities = [];
@@ -305,7 +329,39 @@ async function exportTelegramChannel(options) {
305
329
  const mediaFileName = `media${ext}`;
306
330
  const mediaPath = path.join(postMediaDir, mediaFileName);
307
331
  fs.writeFileSync(mediaPath, buffer);
308
- mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
332
+ const stats = fs.statSync(mediaPath);
333
+ const isVideo = [".mp4", ".mov", ".avi", ".webm", ".m4v"].includes(ext.toLowerCase());
334
+ if (stats.size > MAX_FILE_SIZE) {
335
+ if (isVideo && hasFFmpeg()) {
336
+ const compressedPath = path.join(postMediaDir, `media_compressed${ext}`);
337
+ if (compressVideo(mediaPath, compressedPath)) {
338
+ fs.unlinkSync(mediaPath);
339
+ fs.renameSync(compressedPath, mediaPath);
340
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
341
+ } else {
342
+ fs.unlinkSync(mediaPath);
343
+ if (fs.existsSync(compressedPath)) fs.unlinkSync(compressedPath);
344
+ console.warn(`Skipping large media for message ${msgId} (>${MAX_FILE_SIZE / 1024 / 1024}MB)`);
345
+ }
346
+ } else {
347
+ fs.unlinkSync(mediaPath);
348
+ console.warn(`Skipping large media for message ${msgId} (>${MAX_FILE_SIZE / 1024 / 1024}MB)`);
349
+ }
350
+ } else if (stats.size > COMPRESS_THRESHOLD && isVideo && hasFFmpeg()) {
351
+ const compressedPath = path.join(postMediaDir, `media_compressed${ext}`);
352
+ if (compressVideo(mediaPath, compressedPath)) {
353
+ const compressedStats = fs.statSync(compressedPath);
354
+ if (compressedStats.size < stats.size) {
355
+ fs.unlinkSync(mediaPath);
356
+ fs.renameSync(compressedPath, mediaPath);
357
+ } else {
358
+ fs.unlinkSync(compressedPath);
359
+ }
360
+ }
361
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
362
+ } else {
363
+ mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
364
+ }
309
365
  }
310
366
  } catch (e) {
311
367
  console.error(`Error downloading media for message ${msgId}:`, e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koztv-blog-tools",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Shared utilities for Telegram-based blog sites",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",