diff --git a/config.py b/config.py index afb1940..e50f979 100644 --- a/config.py +++ b/config.py @@ -85,6 +85,11 @@ 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')) +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')) + + def get_proxy_url() -> str | None: """Получить URL прокси для aiohttp""" diff --git a/handlers/admin.py b/handlers/admin.py index 8d9aa3b..48ad006 100644 --- a/handlers/admin.py +++ b/handlers/admin.py @@ -100,8 +100,15 @@ async def process_jurist_question(message: Message, state: FSMContext): import asyncio import os + # Динамический поиск бинарника nlm + nlm_bin = "nlm" + for p in ["/app/bin/nlm", "/usr/local/bin/nlm", os.path.expanduser("~/.local/bin/nlm"), "/home/matrixhasyou/.local/bin/nlm"]: + if os.path.exists(p): + nlm_bin = p + break + cmd = [ - "/home/matrixhasyou/.local/bin/nlm", "query", "notebook", + nlm_bin, "query", "notebook", "00ed7d92-1ab2-4159-ac72-1d0c4be21377", message.text ] diff --git a/services/gis_harvester b/services/gis_harvester index 1d8871f..93a3d14 160000 --- a/services/gis_harvester +++ b/services/gis_harvester @@ -1 +1 @@ -Subproject commit 1d8871f348b4df9561aec957f2a7f07790862899 +Subproject commit 93a3d14d571832433bfcd3d1fe5a244d234fc020 diff --git a/services/gis_pdf_pipeline/gdrive_uploader.py b/services/gis_pdf_pipeline/gdrive_uploader.py index f847dc4..ef382a7 100644 --- a/services/gis_pdf_pipeline/gdrive_uploader.py +++ b/services/gis_pdf_pipeline/gdrive_uploader.py @@ -5,7 +5,7 @@ from googleapiclient.discovery import build from googleapiclient.http import MediaFileUpload SCOPES = ['https://www.googleapis.com/auth/drive'] -SERVICE_ACCOUNT_FILE = '/home/matrixhasyou/domovoy_google_creds.json' +SERVICE_ACCOUNT_FILE = os.getenv('GOOGLE_CREDS_FILE', '/app/config/google_creds.json' if os.path.exists('/app/config/google_creds.json') else '/home/matrixhasyou/domovoy_google_creds.json') PARENT_FOLDER_ID = '1lnHt9Os0L_SnBa8i2dHrI0lBepuVm0Om' GIS_FILE_NAME = "TOTAL_GIS_ARCHIVE.pdf" diff --git a/services/gis_pdf_pipeline/pipeline_main.py b/services/gis_pdf_pipeline/pipeline_main.py index 57afa5b..33b6856 100644 --- a/services/gis_pdf_pipeline/pipeline_main.py +++ b/services/gis_pdf_pipeline/pipeline_main.py @@ -6,15 +6,18 @@ from pdf_tagger import tag_image_to_pdf from gdrive_uploader import upload_gis_archive # --- CONFIG (LEGAL PATHS ONLY) --- -LOCAL_ARCHIVE = Path("/home/matrixhasyou/domovoy_bot/services/gis_harvester/archive") -TEMP_DIR = Path("/home/matrixhasyou/domovoy_bot/services/gis_pdf_pipeline/temp") -OUTPUT_FILE = Path("/home/matrixhasyou/domovoy_bot/services/gis_pdf_pipeline/TOTAL_GIS_ARCHIVE.pdf") +BASE_DIR = Path(__file__).resolve().parent.parent.parent +LOCAL_ARCHIVE = BASE_DIR / "services" / "gis_harvester" / "archive" +TEMP_DIR = BASE_DIR / "services" / "gis_pdf_pipeline" / "temp" +OUTPUT_FILE = BASE_DIR / "services" / "gis_pdf_pipeline" / "TOTAL_GIS_ARCHIVE.pdf" NAS_LEGAL_PATH = "/volume1/web/legal/gis/TOTAL_GIS_ARCHIVE.pdf" NAS_IP = "192.168.10.105" def send_tg(msg): - subprocess.run(["curl", "-s", "-X", "POST", f"https://api.telegram.org/bot8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M/sendMessage", - "-d", f"chat_id=197957361&text={msg}&parse_mode=markdown"]) + token = os.getenv("BOT_TOKEN", "8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M") + chat_id = os.getenv("ADMIN_USER_ID", "197957361") + subprocess.run(["curl", "-s", "-X", "POST", f"https://api.telegram.org/bot{token}/sendMessage", + "-d", f"chat_id={chat_id}&text={msg}&parse_mode=markdown"]) def run_pipeline(): send_tg("🧬 **PDF-КОНВЕЙЕР (LEGAL MODE)**\nНачинаю сборку из /services/gis_harvester/archive...") diff --git a/web/app.py b/web/app.py index 15a9864..ff74640 100644 --- a/web/app.py +++ b/web/app.py @@ -117,8 +117,8 @@ async def upload_to_tg(content, filename, content_type): @app.post("/api/emails/sync_ai") async def api_sync_emails_to_ai(username: str = Depends(get_current_admin)): - sync_script = "/home/matrixhasyou/domovoy_drive_sync.py" - python_path = "/home/matrixhasyou/domovoy_bot/venv-google/bin/python" + 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: # Запуск синхронизации @@ -667,7 +667,7 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi audit_data = (await session.execute(select(EmailAudit).order_by(EmailAudit.last_email_date.desc()))).scalars().all() last_log = (await session.execute(select(EmailExportLog).order_by(EmailExportLog.start_time.desc()).limit(1))).scalar_one_or_none() latest_emails = [] - all_folder = Path("/home/matrixhasyou/mutt/exported_emails/all") + all_folder = Path(config.MUTT_DIR) / "exported_emails" / "all" if all_folder.exists(): files = sorted(all_folder.glob("*.pdf"), key=lambda x: x.stat().st_mtime, reverse=True)[:10] for f in files: @@ -678,11 +678,11 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi else: latest_emails.append({"date": "-", "domain": "other", "subject": f.stem}) - master_pdf_path = Path("/home/matrixhasyou/mutt/ALL_EMAILS_CONSOLIDATED.pdf") + 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 # Drive sync status - sync_time_file = Path("/home/matrixhasyou/mutt/last_ai_sync.txt") + sync_time_file = Path(config.MUTT_DIR) / "last_ai_sync.txt" last_sync_time = None if sync_time_file.exists(): try: @@ -697,7 +697,7 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi total_emails = total_inbound + total_outbound total_attachments = 0 - export_log_path = Path("/home/matrixhasyou/mutt/export.log") + export_log_path = Path(config.MUTT_DIR) / "export.log" if export_log_path.exists(): try: content = export_log_path.read_text(errors='ignore') @@ -728,7 +728,7 @@ async def emails_page(request: Request, username: str = Depends(get_current_admi @app.post("/api/emails/run_full_sync") async def api_emails_run_full_sync(username: str = Depends(get_current_admin)): - master_script = "/home/matrixhasyou/mutt/master_ai_sync.py" + master_script = str(Path(config.MUTT_DIR) / "master_ai_sync.py") python_path = sys.executable if not os.path.exists(master_script): @@ -743,9 +743,9 @@ async def api_emails_run_full_sync(username: str = Depends(get_current_admin)): @app.post("/api/emails/sync_ai") async def api_emails_sync_ai(username: str = Depends(get_current_admin)): - sync_script = "/home/matrixhasyou/domovoy_drive_sync.py" + 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 - master_pdf = "/home/matrixhasyou/mutt/TOTAL_ARCHIVE_2025-2026.pdf" + master_pdf = str(Path(config.MUTT_DIR) / "TOTAL_ARCHIVE_2025-2026.pdf") if not os.path.exists(sync_script): return JSONResponse(status_code=404, content={"message": "Sync script not found"}) @@ -760,8 +760,8 @@ async def api_emails_sync_ai(username: str = Depends(get_current_admin)): @app.get("/api/emails/pipeline_status") async def api_emails_pipeline_status(username: str = Depends(get_current_admin)): import time - status_file = Path("/home/matrixhasyou/mutt/pipeline_status.json") - master_pdf_path = Path("/home/matrixhasyou/mutt/ALL_EMAILS_CONSOLIDATED.pdf") + status_file = Path(config.MUTT_DIR) / "pipeline_status.json" + master_pdf_path = Path(config.MUTT_DIR) / "ALL_EMAILS_CONSOLIDATED.pdf" # Calculate fallback values pdf_size_mb = 0.0 @@ -778,7 +778,7 @@ async def api_emails_pipeline_status(username: str = Depends(get_current_admin)) total_emails = total_inbound + total_outbound total_attachments = 0 - export_log_path = Path("/home/matrixhasyou/mutt/export.log") + export_log_path = Path(config.MUTT_DIR) / "export.log" if export_log_path.exists(): try: content = export_log_path.read_text(errors='ignore') @@ -787,7 +787,7 @@ async def api_emails_pipeline_status(username: str = Depends(get_current_admin)) except Exception as e: pass - sync_time_file = Path("/home/matrixhasyou/mutt/last_ai_sync.txt") + sync_time_file = Path(config.MUTT_DIR) / "last_ai_sync.txt" last_sync_time = "-" if sync_time_file.exists(): try: @@ -844,9 +844,9 @@ async def get_infra_page(request: Request, username: str = Depends(get_current_a @app.post("/api/infra/run_speedtest") async def api_run_speedtest(username: str = Depends(get_current_admin)): - script_path = "/home/matrixhasyou/infra/speedtest_monitor.py" + script_path = "/app/infra/speedtest_monitor.py" if os.path.exists("/app/infra/speedtest_monitor.py") else "/home/matrixhasyou/infra/speedtest_monitor.py" try: - subprocess.Popen(["python3", script_path], start_new_session=True) + subprocess.Popen([sys.executable if os.path.exists("/app/infra/speedtest_monitor.py") else "python3", script_path], start_new_session=True) return JSONResponse(content={"message": "Тест скорости запущен в фоне. Результаты появятся через минуту."}) except Exception as e: return JSONResponse(status_code=500, content={"message": str(e)}) @@ -859,8 +859,8 @@ async def api_run_gis_harvest(username: str = Depends(get_current_admin)): subprocess.Popen(["docker", "exec", "-d", "lkm37-gis-scraper", "python3", "/app/services/gis_harvester/harvester_v5.py"]) # 2. Запуск PDF-конвейера - pipeline_script = "/home/matrixhasyou/domovoy_bot/services/gis_pdf_pipeline/pipeline_main.py" - venv_python = "/home/matrixhasyou/domovoy_bot/services/gis_pdf_pipeline/venv/bin/python3" + pipeline_script = str(Path(__file__).resolve().parent.parent / "services" / "gis_pdf_pipeline" / "pipeline_main.py") + venv_python = sys.executable subprocess.Popen([venv_python, pipeline_script], start_new_session=True) return JSONResponse(content={"message": "Процесс ГИС ЖКХ запущен (Жатва + PDF). Следите за Telegram."})