koztv-blog-tools 1.3.0 → 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.d.mts +2 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.js +65 -1
- package/dist/node.mjs +65 -1
- package/package.json +1 -1
package/dist/node.d.mts
CHANGED
|
@@ -25,6 +25,8 @@ interface TelegramExportOptions {
|
|
|
25
25
|
until?: Date;
|
|
26
26
|
/** Download media files */
|
|
27
27
|
downloadMedia?: boolean;
|
|
28
|
+
/** Skip posts that already have markdown files */
|
|
29
|
+
skipExisting?: boolean;
|
|
28
30
|
/** Number of concurrent media downloads */
|
|
29
31
|
mediaWorkers?: number;
|
|
30
32
|
/** Callback for progress updates */
|
package/dist/node.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ interface TelegramExportOptions {
|
|
|
25
25
|
until?: Date;
|
|
26
26
|
/** Download media files */
|
|
27
27
|
downloadMedia?: boolean;
|
|
28
|
+
/** Skip posts that already have markdown files */
|
|
29
|
+
skipExisting?: boolean;
|
|
28
30
|
/** Number of concurrent media downloads */
|
|
29
31
|
mediaWorkers?: number;
|
|
30
32
|
/** Callback for progress updates */
|
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 = [];
|
|
@@ -514,6 +538,7 @@ async function exportTelegramChannel(options) {
|
|
|
514
538
|
since,
|
|
515
539
|
until,
|
|
516
540
|
downloadMedia = true,
|
|
541
|
+
skipExisting = false,
|
|
517
542
|
mediaWorkers = 3,
|
|
518
543
|
onProgress,
|
|
519
544
|
onPhoneNumber = () => defaultReadline("Phone number: "),
|
|
@@ -611,7 +636,14 @@ async function exportTelegramChannel(options) {
|
|
|
611
636
|
}
|
|
612
637
|
const msgId = message.id;
|
|
613
638
|
const paddedId = String(msgId).padStart(6, "0");
|
|
639
|
+
const postPath = path.join(postsDir, `${paddedId}.md`);
|
|
614
640
|
const postMediaDir = path.join(mediaDir, paddedId);
|
|
641
|
+
if (skipExisting && fs.existsSync(postPath)) {
|
|
642
|
+
if (onProgress) {
|
|
643
|
+
onProgress(processedCount, totalMessages, `Skipping ${paddedId} (exists)`);
|
|
644
|
+
}
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
615
647
|
const mediaFiles = [];
|
|
616
648
|
if (downloadMedia && message.media) {
|
|
617
649
|
const existingFiles = fs.existsSync(postMediaDir) ? fs.readdirSync(postMediaDir).filter((f) => f.startsWith("media.")) : [];
|
|
@@ -647,7 +679,39 @@ async function exportTelegramChannel(options) {
|
|
|
647
679
|
const mediaFileName = `media${ext}`;
|
|
648
680
|
const mediaPath = path.join(postMediaDir, mediaFileName);
|
|
649
681
|
fs.writeFileSync(mediaPath, buffer);
|
|
650
|
-
|
|
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
|
+
}
|
|
651
715
|
}
|
|
652
716
|
} catch (e) {
|
|
653
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 = [];
|
|
@@ -164,6 +188,7 @@ async function exportTelegramChannel(options) {
|
|
|
164
188
|
since,
|
|
165
189
|
until,
|
|
166
190
|
downloadMedia = true,
|
|
191
|
+
skipExisting = false,
|
|
167
192
|
mediaWorkers = 3,
|
|
168
193
|
onProgress,
|
|
169
194
|
onPhoneNumber = () => defaultReadline("Phone number: "),
|
|
@@ -261,7 +286,14 @@ async function exportTelegramChannel(options) {
|
|
|
261
286
|
}
|
|
262
287
|
const msgId = message.id;
|
|
263
288
|
const paddedId = String(msgId).padStart(6, "0");
|
|
289
|
+
const postPath = path.join(postsDir, `${paddedId}.md`);
|
|
264
290
|
const postMediaDir = path.join(mediaDir, paddedId);
|
|
291
|
+
if (skipExisting && fs.existsSync(postPath)) {
|
|
292
|
+
if (onProgress) {
|
|
293
|
+
onProgress(processedCount, totalMessages, `Skipping ${paddedId} (exists)`);
|
|
294
|
+
}
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
265
297
|
const mediaFiles = [];
|
|
266
298
|
if (downloadMedia && message.media) {
|
|
267
299
|
const existingFiles = fs.existsSync(postMediaDir) ? fs.readdirSync(postMediaDir).filter((f) => f.startsWith("media.")) : [];
|
|
@@ -297,7 +329,39 @@ async function exportTelegramChannel(options) {
|
|
|
297
329
|
const mediaFileName = `media${ext}`;
|
|
298
330
|
const mediaPath = path.join(postMediaDir, mediaFileName);
|
|
299
331
|
fs.writeFileSync(mediaPath, buffer);
|
|
300
|
-
|
|
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
|
+
}
|
|
301
365
|
}
|
|
302
366
|
} catch (e) {
|
|
303
367
|
console.error(`Error downloading media for message ${msgId}:`, e);
|