diff --git a/config.py b/config.py
index 7cff5fe..7131ae3 100644
--- a/config.py
+++ b/config.py
@@ -90,7 +90,7 @@ if not ADMIN_USER_ID:
SAFETY_MODE = os.getenv('SAFETY_MODE', 'production').lower() # 'production' или 'safe'
# ===== ДИНАМИЧЕСКИЕ ПУТИ (ПЕРЕНОСИМОСТЬ) =====
-MUTT_DIR = os.getenv('MUTT_DIR', '/app/mutt' if os.path.exists('/app/mutt') else str(BASE_DIR.parent.parent / 'mutt'))
+MUTT_DIR = os.getenv('MUTT_DIR', '/home/matrixhasyou/mutt' if os.path.exists('/home/matrixhasyou/mutt') else ('/app/mutt' if os.path.exists('/app/mutt') else str(BASE_DIR.parent.parent / 'mutt')))
GOOGLE_CREDS_FILE = os.getenv('GOOGLE_CREDS_FILE', '/app/config/google_creds.json' if os.path.exists('/app/config/google_creds.json') else str(BASE_DIR.parent.parent / 'domovoy_google_creds.json'))
diff --git a/docker-compose.yml b/docker-compose.yml
index f84617a..0c4ba3c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -13,6 +13,7 @@ services:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./.env:/app/.env:ro
+ - ./config.py:/app/config.py:ro
- ./main.py:/app/main.py
- ./logs:/app/logs
- ./exports:/app/exports
@@ -39,10 +40,12 @@ services:
- PYTHONPATH=/app:/app/services
- GOOGLE_CREDS_FILE=/home/matrixhasyou/domovoy_google_creds.json
- GOOGLE_API_KEY=AIzaSyAJMfQ_mRZ1picRXVFNaeFJ7fpAkZxUKyk
+ - MUTT_DIR=/home/matrixhasyou/mutt
- TZ=Europe/Ulyanovsk
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./.env:/app/.env:ro
+ - ./config.py:/app/config.py:ro
- ./web:/app/web
- ./podcasts:/app/podcasts
- ./logs:/app/logs
@@ -50,7 +53,8 @@ services:
- ./data:/app/data
- ./handlers:/app/handlers
- ./services:/app/services
- - /home/matrixhasyou/mutt:/home/matrixhasyou/mutt:ro
+ - /home/matrixhasyou/mutt:/home/matrixhasyou/mutt:rw
+ - /home/matrixhasyou/domovoy_drive_sync.py:/home/matrixhasyou/domovoy_drive_sync.py:ro
- ../libs/swarmlib:/app/swarmlib:ro
- /home/matrixhasyou/domovoy_google_creds.json:/home/matrixhasyou/domovoy_google_creds.json:ro
- /home/matrixhasyou/.notebooklm:/root/.notebooklm:rw
diff --git a/web/app.py b/web/app.py
index c5c771d..df4c04e 100644
--- a/web/app.py
+++ b/web/app.py
@@ -115,40 +115,7 @@ async def upload_to_tg(content, filename, content_type):
file_id = msg["photo"][-1]["file_id"] if file_type == "photo" else msg["document"]["file_id"]
return file_id, file_type
-@app.post("/api/emails/sync_ai")
-async def api_sync_emails_to_ai(username: str = Depends(get_current_admin)):
- sync_script = "/app/domovoy_drive_sync.py" if os.path.exists("/app/domovoy_drive_sync.py") else str(Path(config.MUTT_DIR).parent / "domovoy_drive_sync.py")
- python_path = sys.executable
- try:
- # Запуск синхронизации
- process = subprocess.run(
- [python_path, sync_script],
- capture_output=True, text=True, timeout=300
- )
-
- if process.returncode == 0:
- # Уведомляем админа в ТГ
- msg = "🤖 AI Синхронизация Успешна!\n\n📄 Архив почты обновлен на Google Drive.\n👉 Не забудь нажать 'Sync' в NotebookLM!"
-
- # Отправка через API Telegram (упрощенно)
- async with aiohttp.ClientSession() as session:
- url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/sendMessage"
- params = {
- "chat_id": config.ADMIN_USER_ID,
- "text": msg,
- "parse_mode": "HTML"
- }
- # Используем прокси если нужно
- proxy = f"http://{config.PROXY_HOST}:{config.PROXY_PORT}" if config.USE_PROXY else None
- await session.get(url, params=params, proxy=proxy)
-
- return {"success": True, "message": "Синхронизация завершена, уведомление отправлено."}
- else:
- return {"success": False, "error": process.stderr or process.stdout}
-
- except Exception as e:
- return JSONResponse(status_code=500, content={"success": False, "error": str(e)})
# ============================================================================
# ГЛАВНАЯ ПАНЕЛЬ (DASHBOARD)
@@ -679,7 +646,16 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi
latest_emails.append({"date": "-", "domain": "other", "subject": f.stem})
master_pdf_path = Path(config.MUTT_DIR) / "ALL_EMAILS_CONSOLIDATED.pdf"
- last_update = datetime.fromtimestamp(master_pdf_path.stat().st_mtime, tz=timezone.utc) if master_pdf_path.exists() else None
+ parts = list(Path(config.MUTT_DIR).glob("ALL_EMAILS_CONSOLIDATED_part*.pdf"))
+ has_master_pdf = master_pdf_path.exists() or bool(parts)
+ pdf_size_mb = 0.0
+ last_update = None
+ if master_pdf_path.exists():
+ pdf_size_mb = round(master_pdf_path.stat().st_size / (1024 * 1024), 2)
+ last_update = datetime.fromtimestamp(master_pdf_path.stat().st_mtime, tz=timezone.utc)
+ elif parts:
+ pdf_size_mb = round(sum(p.stat().st_size for p in parts) / (1024 * 1024), 2)
+ last_update = datetime.fromtimestamp(max(p.stat().st_mtime for p in parts), tz=timezone.utc)
# Drive sync status
sync_time_file = Path(config.MUTT_DIR) / "last_ai_sync.txt"
@@ -705,10 +681,6 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi
total_attachments = sum(int(m) for m in matches)
except Exception as e:
pass
-
- pdf_size_mb = 0.0
- if master_pdf_path.exists():
- pdf_size_mb = round(master_pdf_path.stat().st_size / (1024 * 1024), 2)
last_email_date = None
if audit_data:
@@ -735,15 +707,17 @@ async def api_emails_run_full_sync(username: str = Depends(get_current_admin)):
return JSONResponse(status_code=404, content={"message": "Master sync script not found"})
try:
- # Run master sync script in background
- subprocess.Popen([python_path, master_script], start_new_session=True)
+ # Run master sync script in background with logging
+ log_path = Path(config.MUTT_DIR) / "master_sync.log"
+ log_file = open(log_path, "a")
+ subprocess.Popen([python_path, master_script], stdout=log_file, stderr=log_file, start_new_session=True)
return JSONResponse(content={"message": "Полная синхронизация (Сбор -> PDF -> G-Drive) запущена в фоне. Следите за уведомлениями в Telegram."})
except Exception as e:
return JSONResponse(status_code=500, content={"message": str(e)})
@app.post("/api/emails/sync_ai")
async def api_emails_sync_ai(username: str = Depends(get_current_admin)):
- sync_script = "/app/domovoy_drive_sync.py" if os.path.exists("/app/domovoy_drive_sync.py") else str(Path(config.MUTT_DIR).parent / "domovoy_drive_sync.py")
+ sync_script = "/home/matrixhasyou/domovoy_drive_sync.py" if os.path.exists("/home/matrixhasyou/domovoy_drive_sync.py") else "/app/domovoy_drive_sync.py"
python_path = sys.executable
master_pdf = str(Path(config.MUTT_DIR) / "TOTAL_ARCHIVE_2025-2026.pdf")
@@ -751,8 +725,10 @@ async def api_emails_sync_ai(username: str = Depends(get_current_admin)):
return JSONResponse(status_code=404, content={"message": "Sync script not found"})
try:
- # Run sync script in background
- subprocess.Popen([python_path, sync_script, master_pdf], start_new_session=True)
+ # Run sync script in background with logging
+ log_path = Path(config.MUTT_DIR) / "master_sync.log"
+ log_file = open(log_path, "a")
+ subprocess.Popen([python_path, sync_script, master_pdf], stdout=log_file, stderr=log_file, start_new_session=True)
return JSONResponse(content={"message": "Синхронизация с Google Drive запущена в фоне. Это займет около минуты."})
except Exception as e:
return JSONResponse(status_code=500, content={"message": str(e)})
@@ -762,11 +738,14 @@ async def api_emails_pipeline_status(username: str = Depends(get_current_admin))
import time
status_file = Path(config.MUTT_DIR) / "pipeline_status.json"
master_pdf_path = Path(config.MUTT_DIR) / "ALL_EMAILS_CONSOLIDATED.pdf"
+ parts = list(Path(config.MUTT_DIR).glob("ALL_EMAILS_CONSOLIDATED_part*.pdf"))
# Calculate fallback values
pdf_size_mb = 0.0
if master_pdf_path.exists():
pdf_size_mb = round(master_pdf_path.stat().st_size / (1024 * 1024), 2)
+ elif parts:
+ pdf_size_mb = round(sum(p.stat().st_size for p in parts) / (1024 * 1024), 2)
total_emails = 0
total_inbound = 0
diff --git a/web/templates/base.html b/web/templates/base.html
index 0618c36..dd3aae8 100644
--- a/web/templates/base.html
+++ b/web/templates/base.html
@@ -208,7 +208,6 @@