koztv-blog-tools 1.2.3 → 1.2.5
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/index.js +56 -31
- package/dist/index.mjs +56 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -497,37 +497,44 @@ async function exportTelegramChannel(options) {
|
|
|
497
497
|
const postMediaDir = path.join(mediaDir, paddedId);
|
|
498
498
|
const mediaFiles = [];
|
|
499
499
|
if (downloadMedia && message.media) {
|
|
500
|
-
fs.
|
|
501
|
-
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
500
|
+
const existingFiles = fs.existsSync(postMediaDir) ? fs.readdirSync(postMediaDir).filter((f) => f.startsWith("media.")) : [];
|
|
501
|
+
if (existingFiles.length > 0) {
|
|
502
|
+
for (const f of existingFiles) {
|
|
503
|
+
mediaFiles.push(`media/${paddedId}/${f}`);
|
|
504
|
+
}
|
|
505
|
+
} else {
|
|
506
|
+
fs.mkdirSync(postMediaDir, { recursive: true });
|
|
507
|
+
try {
|
|
508
|
+
const buffer = await client.downloadMedia(message.media, {});
|
|
509
|
+
if (buffer) {
|
|
510
|
+
let ext = ".bin";
|
|
511
|
+
if (message.media instanceof import_telegram.Api.MessageMediaPhoto) {
|
|
512
|
+
ext = ".jpg";
|
|
513
|
+
} else if (message.media instanceof import_telegram.Api.MessageMediaDocument) {
|
|
514
|
+
const doc = message.media.document;
|
|
515
|
+
if (doc instanceof import_telegram.Api.Document) {
|
|
516
|
+
const mimeExt = doc.mimeType?.split("/")[1];
|
|
517
|
+
if (mimeExt) {
|
|
518
|
+
ext = "." + mimeExt.replace("jpeg", "jpg");
|
|
517
519
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
+
for (const attr of doc.attributes) {
|
|
521
|
+
if (attr instanceof import_telegram.Api.DocumentAttributeVideo) {
|
|
522
|
+
ext = ".mp4";
|
|
523
|
+
}
|
|
524
|
+
if (attr instanceof import_telegram.Api.DocumentAttributeFilename) {
|
|
525
|
+
ext = path.extname(attr.fileName) || ext;
|
|
526
|
+
}
|
|
520
527
|
}
|
|
521
528
|
}
|
|
522
529
|
}
|
|
530
|
+
const mediaFileName = `media${ext}`;
|
|
531
|
+
const mediaPath = path.join(postMediaDir, mediaFileName);
|
|
532
|
+
fs.writeFileSync(mediaPath, buffer);
|
|
533
|
+
mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
|
|
523
534
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
fs.writeFileSync(mediaPath, buffer);
|
|
527
|
-
mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
|
|
535
|
+
} catch (e) {
|
|
536
|
+
console.error(`Error downloading media for message ${msgId}:`, e);
|
|
528
537
|
}
|
|
529
|
-
} catch (e) {
|
|
530
|
-
console.error(`Error downloading media for message ${msgId}:`, e);
|
|
531
538
|
}
|
|
532
539
|
}
|
|
533
540
|
const content = message.message || "";
|
|
@@ -664,9 +671,26 @@ async function processPost(post, options, exportDir) {
|
|
|
664
671
|
const { title: originalTitle, body: originalBody } = extractTitleAndBody(cleanedContent);
|
|
665
672
|
const date = post.date.toISOString().split("T")[0];
|
|
666
673
|
const languages = [];
|
|
674
|
+
const translationExists = (lang) => {
|
|
675
|
+
const langDir = path2.join(outputDir, lang);
|
|
676
|
+
if (!fs2.existsSync(langDir)) return false;
|
|
677
|
+
try {
|
|
678
|
+
for (const slug of fs2.readdirSync(langDir)) {
|
|
679
|
+
const indexPath = path2.join(langDir, slug, "index.md");
|
|
680
|
+
if (fs2.existsSync(indexPath)) {
|
|
681
|
+
const content = fs2.readFileSync(indexPath, "utf-8");
|
|
682
|
+
if (content.includes(`original_link: "${post.link}"`)) {
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
} catch {
|
|
688
|
+
}
|
|
689
|
+
return false;
|
|
690
|
+
};
|
|
667
691
|
if (translate && translate.targetLangs.length > 0) {
|
|
668
692
|
const sourceLang = translate.sourceLang || "ru";
|
|
669
|
-
if (translate.keepOriginal) {
|
|
693
|
+
if (translate.keepOriginal && !translationExists(sourceLang)) {
|
|
670
694
|
languages.push({
|
|
671
695
|
lang: sourceLang,
|
|
672
696
|
title: originalTitle,
|
|
@@ -676,6 +700,10 @@ async function processPost(post, options, exportDir) {
|
|
|
676
700
|
}
|
|
677
701
|
for (const targetLang of translate.targetLangs) {
|
|
678
702
|
if (targetLang === sourceLang) continue;
|
|
703
|
+
if (translationExists(targetLang)) {
|
|
704
|
+
onProgress?.(` ${targetLang}: already exists, skipping`);
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
679
707
|
onProgress?.(` Translating to ${targetLang}...`);
|
|
680
708
|
const translateOpts = {
|
|
681
709
|
apiKey: translate.apiKey,
|
|
@@ -804,10 +832,6 @@ async function exportAndTranslate(options) {
|
|
|
804
832
|
let skipped = 0;
|
|
805
833
|
for (const post of exportResult.posts) {
|
|
806
834
|
const postId = `${post.channelUsername}-${post.msgId}`;
|
|
807
|
-
if (processedLog[postId]) {
|
|
808
|
-
skipped++;
|
|
809
|
-
continue;
|
|
810
|
-
}
|
|
811
835
|
if (!post.content && !post.hasMedia) {
|
|
812
836
|
skipped++;
|
|
813
837
|
continue;
|
|
@@ -818,8 +842,9 @@ Processing: ${postId}`);
|
|
|
818
842
|
const created = await processPost(post, options, exportDir);
|
|
819
843
|
if (created.length > 0) {
|
|
820
844
|
processed++;
|
|
845
|
+
const existing = processedLog[postId]?.posts || [];
|
|
821
846
|
processedLog[postId] = {
|
|
822
|
-
posts: created,
|
|
847
|
+
posts: [.../* @__PURE__ */ new Set([...existing, ...created])],
|
|
823
848
|
date: post.date.toISOString(),
|
|
824
849
|
processedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
825
850
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -440,37 +440,44 @@ async function exportTelegramChannel(options) {
|
|
|
440
440
|
const postMediaDir = path.join(mediaDir, paddedId);
|
|
441
441
|
const mediaFiles = [];
|
|
442
442
|
if (downloadMedia && message.media) {
|
|
443
|
-
fs.
|
|
444
|
-
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
443
|
+
const existingFiles = fs.existsSync(postMediaDir) ? fs.readdirSync(postMediaDir).filter((f) => f.startsWith("media.")) : [];
|
|
444
|
+
if (existingFiles.length > 0) {
|
|
445
|
+
for (const f of existingFiles) {
|
|
446
|
+
mediaFiles.push(`media/${paddedId}/${f}`);
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
fs.mkdirSync(postMediaDir, { recursive: true });
|
|
450
|
+
try {
|
|
451
|
+
const buffer = await client.downloadMedia(message.media, {});
|
|
452
|
+
if (buffer) {
|
|
453
|
+
let ext = ".bin";
|
|
454
|
+
if (message.media instanceof Api.MessageMediaPhoto) {
|
|
455
|
+
ext = ".jpg";
|
|
456
|
+
} else if (message.media instanceof Api.MessageMediaDocument) {
|
|
457
|
+
const doc = message.media.document;
|
|
458
|
+
if (doc instanceof Api.Document) {
|
|
459
|
+
const mimeExt = doc.mimeType?.split("/")[1];
|
|
460
|
+
if (mimeExt) {
|
|
461
|
+
ext = "." + mimeExt.replace("jpeg", "jpg");
|
|
460
462
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
+
for (const attr of doc.attributes) {
|
|
464
|
+
if (attr instanceof Api.DocumentAttributeVideo) {
|
|
465
|
+
ext = ".mp4";
|
|
466
|
+
}
|
|
467
|
+
if (attr instanceof Api.DocumentAttributeFilename) {
|
|
468
|
+
ext = path.extname(attr.fileName) || ext;
|
|
469
|
+
}
|
|
463
470
|
}
|
|
464
471
|
}
|
|
465
472
|
}
|
|
473
|
+
const mediaFileName = `media${ext}`;
|
|
474
|
+
const mediaPath = path.join(postMediaDir, mediaFileName);
|
|
475
|
+
fs.writeFileSync(mediaPath, buffer);
|
|
476
|
+
mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
|
|
466
477
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
fs.writeFileSync(mediaPath, buffer);
|
|
470
|
-
mediaFiles.push(`media/${paddedId}/${mediaFileName}`);
|
|
478
|
+
} catch (e) {
|
|
479
|
+
console.error(`Error downloading media for message ${msgId}:`, e);
|
|
471
480
|
}
|
|
472
|
-
} catch (e) {
|
|
473
|
-
console.error(`Error downloading media for message ${msgId}:`, e);
|
|
474
481
|
}
|
|
475
482
|
}
|
|
476
483
|
const content = message.message || "";
|
|
@@ -607,9 +614,26 @@ async function processPost(post, options, exportDir) {
|
|
|
607
614
|
const { title: originalTitle, body: originalBody } = extractTitleAndBody(cleanedContent);
|
|
608
615
|
const date = post.date.toISOString().split("T")[0];
|
|
609
616
|
const languages = [];
|
|
617
|
+
const translationExists = (lang) => {
|
|
618
|
+
const langDir = path2.join(outputDir, lang);
|
|
619
|
+
if (!fs2.existsSync(langDir)) return false;
|
|
620
|
+
try {
|
|
621
|
+
for (const slug of fs2.readdirSync(langDir)) {
|
|
622
|
+
const indexPath = path2.join(langDir, slug, "index.md");
|
|
623
|
+
if (fs2.existsSync(indexPath)) {
|
|
624
|
+
const content = fs2.readFileSync(indexPath, "utf-8");
|
|
625
|
+
if (content.includes(`original_link: "${post.link}"`)) {
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
return false;
|
|
633
|
+
};
|
|
610
634
|
if (translate && translate.targetLangs.length > 0) {
|
|
611
635
|
const sourceLang = translate.sourceLang || "ru";
|
|
612
|
-
if (translate.keepOriginal) {
|
|
636
|
+
if (translate.keepOriginal && !translationExists(sourceLang)) {
|
|
613
637
|
languages.push({
|
|
614
638
|
lang: sourceLang,
|
|
615
639
|
title: originalTitle,
|
|
@@ -619,6 +643,10 @@ async function processPost(post, options, exportDir) {
|
|
|
619
643
|
}
|
|
620
644
|
for (const targetLang of translate.targetLangs) {
|
|
621
645
|
if (targetLang === sourceLang) continue;
|
|
646
|
+
if (translationExists(targetLang)) {
|
|
647
|
+
onProgress?.(` ${targetLang}: already exists, skipping`);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
622
650
|
onProgress?.(` Translating to ${targetLang}...`);
|
|
623
651
|
const translateOpts = {
|
|
624
652
|
apiKey: translate.apiKey,
|
|
@@ -747,10 +775,6 @@ async function exportAndTranslate(options) {
|
|
|
747
775
|
let skipped = 0;
|
|
748
776
|
for (const post of exportResult.posts) {
|
|
749
777
|
const postId = `${post.channelUsername}-${post.msgId}`;
|
|
750
|
-
if (processedLog[postId]) {
|
|
751
|
-
skipped++;
|
|
752
|
-
continue;
|
|
753
|
-
}
|
|
754
778
|
if (!post.content && !post.hasMedia) {
|
|
755
779
|
skipped++;
|
|
756
780
|
continue;
|
|
@@ -761,8 +785,9 @@ Processing: ${postId}`);
|
|
|
761
785
|
const created = await processPost(post, options, exportDir);
|
|
762
786
|
if (created.length > 0) {
|
|
763
787
|
processed++;
|
|
788
|
+
const existing = processedLog[postId]?.posts || [];
|
|
764
789
|
processedLog[postId] = {
|
|
765
|
-
posts: created,
|
|
790
|
+
posts: [.../* @__PURE__ */ new Set([...existing, ...created])],
|
|
766
791
|
date: post.date.toISOString(),
|
|
767
792
|
processedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
768
793
|
};
|