114 lines
4.3 KiB
Python
Executable file
114 lines
4.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
||
"""
|
||
Consolidates all individual email PDFs into one giant PDF for NotebookLM.
|
||
Sorted by date (prefix in filename). Supports auto-splitting into parts if size > 180MB.
|
||
"""
|
||
import os
|
||
import sys
|
||
import fitz # PyMuPDF
|
||
from pathlib import Path
|
||
import logging
|
||
import requests
|
||
from datetime import datetime
|
||
|
||
# === CONFIG ===
|
||
BASE_DIR = Path(__file__).parent
|
||
SOURCE_DIR = BASE_DIR / "exported_emails" / "all"
|
||
OUTPUT_FILE = BASE_DIR / "ALL_EMAILS_CONSOLIDATED.pdf"
|
||
BOT_TOKEN = "8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M"
|
||
CHAT_ID = "197957361"
|
||
PROXY = "socks5h://127.0.0.1:10808"
|
||
|
||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||
log = logging.getLogger("Consolidator")
|
||
|
||
def send_tg_alert(count, size_mb, parts_count):
|
||
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
|
||
parts_text = f"📦 <b>Частей архива:</b> {parts_count}\n" if parts_count > 1 else ""
|
||
text = f"""
|
||
🔥 <b>СВОДНЫЙ АРХИВ ПОЧТЫ ОБНОВЛЕН!</b> 🔥
|
||
|
||
📑 <b>Файлы:</b> <code>ALL_EMAILS_CONSOLIDATED.pdf</code> (или части _partX.pdf)
|
||
📧 <b>Всего писем в архиве:</b> {count}
|
||
{parts_text}🐘 <b>Общий размер:</b> {size_mb:.2f} МБ
|
||
📅 <b>Обновлено:</b> {datetime.now().strftime('%Y-%m-%d %H:%M')}
|
||
|
||
🚀 Данные успешно отправлены в Google Drive (Domovoy_AI).
|
||
"""
|
||
try:
|
||
requests.post(url, json={"chat_id": CHAT_ID, "text": text, "parse_mode": "HTML"},
|
||
proxies={"https": PROXY}, timeout=20)
|
||
log.info("✅ Telegram alert sent.")
|
||
except Exception as e:
|
||
log.error(f"❌ TG Alert failed: {e}")
|
||
|
||
def consolidate():
|
||
log.info("Starting consolidation...")
|
||
|
||
if not SOURCE_DIR.exists():
|
||
log.error(f"Source directory {SOURCE_DIR} not found!")
|
||
return
|
||
|
||
pdf_files = list(SOURCE_DIR.glob("*.pdf"))
|
||
if not pdf_files:
|
||
log.warning("No PDF files found to consolidate.")
|
||
return
|
||
|
||
# Sort by filename (which starts with date YYYY-MM-DD or contains it)
|
||
pdf_files.sort(key=lambda x: x.name)
|
||
|
||
log.info(f"Found {len(pdf_files)} PDFs. Merging with part splitting (max 180MB)...")
|
||
|
||
# Clean old parts
|
||
for p in BASE_DIR.glob("ALL_EMAILS_CONSOLIDATED_part*.pdf"):
|
||
try: os.unlink(p)
|
||
except Exception as e: log.warning(f"Failed to delete old part {p}: {e}")
|
||
if OUTPUT_FILE.exists():
|
||
try: os.unlink(OUTPUT_FILE)
|
||
except Exception as e: log.warning(f"Failed to delete old output: {e}")
|
||
|
||
parts = []
|
||
current_merger = fitz.open()
|
||
current_size = 0
|
||
part_num = 1
|
||
|
||
for pdf_path in pdf_files:
|
||
file_size = pdf_path.stat().st_size
|
||
# Limit to 195 MB to guarantee fitting in NotebookLM 195MB
|
||
if current_size + file_size > 195 * 1024 * 1024 and len(current_merger) > 0:
|
||
part_file = BASE_DIR / f"ALL_EMAILS_CONSOLIDATED_part{part_num}.pdf"
|
||
current_merger.save(part_file, garbage=3, deflate=True)
|
||
log.info(f"Saved part {part_num}: {part_file} ({part_file.stat().st_size / (1024*1024):.2f} MB)")
|
||
parts.append(part_file)
|
||
current_merger.close()
|
||
|
||
current_merger = fitz.open()
|
||
current_size = 0
|
||
part_num += 1
|
||
|
||
try:
|
||
doc = fitz.open(pdf_path)
|
||
current_merger.insert_pdf(doc)
|
||
doc.close()
|
||
current_size += file_size
|
||
except Exception as e:
|
||
log.warning(f"Failed to add {pdf_path.name}: {e}")
|
||
|
||
# Save last part
|
||
if len(current_merger) > 0:
|
||
if part_num == 1:
|
||
current_merger.save(OUTPUT_FILE, garbage=3, deflate=True)
|
||
log.info(f"✅ Consolidated single PDF saved: {OUTPUT_FILE} ({OUTPUT_FILE.stat().st_size / (1024*1024):.2f} MB)")
|
||
parts.append(OUTPUT_FILE)
|
||
else:
|
||
part_file = BASE_DIR / f"ALL_EMAILS_CONSOLIDATED_part{part_num}.pdf"
|
||
current_merger.save(part_file, garbage=3, deflate=True)
|
||
log.info(f"Saved part {part_num}: {part_file} ({part_file.stat().st_size / (1024*1024):.2f} MB)")
|
||
parts.append(part_file)
|
||
current_merger.close()
|
||
|
||
total_size_mb = sum(p.stat().st_size for p in parts) / (1024 * 1024)
|
||
send_tg_alert(len(pdf_files), total_size_mb, len(parts))
|
||
|
||
if __name__ == "__main__":
|
||
consolidate()
|