Refactor: Decouple paths and tokens from codebase for hosting portability

This commit is contained in:
Admin 2026-06-27 15:54:10 +04:00
parent ed565c54c3
commit 1c342fd3c1
6 changed files with 40 additions and 25 deletions

View file

@ -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"""

View file

@ -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
]

@ -1 +1 @@
Subproject commit 1d8871f348b4df9561aec957f2a7f07790862899
Subproject commit 93a3d14d571832433bfcd3d1fe5a244d234fc020

View file

@ -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"

View file

@ -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...")

View file

@ -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."})