diff --git a/.gitignore b/.gitignore index c48f48e..7d196de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env /.venv /logs/* -/__pycache__ \ No newline at end of file +/__pycache__/* +*.pyc \ No newline at end of file diff --git a/__pycache__/get_data.cpython-312.pyc b/__pycache__/get_data.cpython-312.pyc index 85bfb8a..fd6f266 100644 Binary files a/__pycache__/get_data.cpython-312.pyc and b/__pycache__/get_data.cpython-312.pyc differ diff --git a/__pycache__/smb_excel.cpython-312.pyc b/__pycache__/smb_excel.cpython-312.pyc deleted file mode 100644 index 82f5b7e..0000000 Binary files a/__pycache__/smb_excel.cpython-312.pyc and /dev/null differ diff --git a/function.py b/function.py deleted file mode 100644 index e705774..0000000 --- a/function.py +++ /dev/null @@ -1,41 +0,0 @@ -import os -from io import BytesIO -import pandas as pd -from dotenv import load_dotenv -from synology_drive_api.drive import SynologyDrive -from synology_drive_api.base import SynologyException - -load_dotenv() - -SYNO_HOST = os.getenv("SYNO_BASE_URL", "").strip() # без схемы! например: "nas.example.com" -SYNO_USERNAME = os.getenv("SYNO_USERNAME", "") -SYNO_PASSWORD = os.getenv("SYNO_PASSWORD", "") -SYNO_PORT = int(os.getenv("SYNO_PORT", "5001")) - -def load_osheet(file_path: str, sheet: str | int = 0) -> pd.DataFrame: - """ - Скачивает Synology Office .osheet через Drive API (делает экспорт в xlsx под капотом) - и возвращает pandas.DataFrame для указанного листа. - file_path: путь вида '/GFX/…/MATCH.osheet' (шара должна быть Team Folder в Drive). - """ - - drv = SynologyDrive(SYNO_USERNAME, SYNO_PASSWORD, SYNO_HOST, SYNO_PORT, https=True, dsm_version="7") - try: - # вернёт BytesIO c xlsx - bio = drv.download_synology_office_file(file_path) - df = pd.read_excel(bio, sheet_name=sheet) - return df - except SynologyException as e: - # Часто: {"code":1000,"message":"get file information failed"} — Drive не видит путь (нет Team Folder/прав) - raise RuntimeError( - "Не удалось экспортировать .osheet через Synology Drive. " - "Проверь, что шара включена в Drive Admin Console → Team Folder, " - "и у пользователя есть права. Исходная ошибка: " + str(e) - ) - finally: - try: - drv.logout() - except Exception: - pass - -load_osheet(file_path="/GFX/Hockey/KHL/Soft/MATCH.osheet", sheet="TEAMS") \ No newline at end of file diff --git a/get_data.py b/get_data.py index fa21e2b..cba2592 100644 --- a/get_data.py +++ b/get_data.py @@ -10,8 +10,8 @@ import uvicorn from threading import Thread, Event, Lock import time from contextlib import asynccontextmanager -#from smb_excel import read_excel_from_smb, fetch_smb_file import numpy as np +import nasio # --- Глобальные переменные --- @@ -36,13 +36,10 @@ api_user = os.getenv("API_USER") api_pass = os.getenv("API_PASS") league = os.getenv("LEAGUE") POLL_SEC = int(os.getenv("GAME_POLL_SECONDS")) -SERVER_NAME = os.getenv("SERVER_NAME") -SERVER_IP = os.getenv("SERVER_IP") -SHARE = os.getenv("SHARE") -PATH_IN_SHARE = os.getenv("PATH_IN_SHARE") -USER = os.getenv("USER") -PASSWORD = os.getenv("PASSWORD") -DOMAIN = os.getenv("DOMAIN") +SERVER_NAME = os.getenv("SYNO_URL") +USER = os.getenv("SYNO_USERNAME") +PASSWORD = os.getenv("SYNO_PASSWORD") +PATH = "/team-folders/GFX/Hockey/KHL/Soft/MATCH.xlsm" @@ -652,25 +649,6 @@ def _build_all_stats(payload: dict) -> dict: }) return result -def xl(): - df = read_excel_from_smb( - server_name=SERVER_NAME, - server_ip=SERVER_IP, - share_name=SHARE, - file_path_in_share=PATH_IN_SHARE, - username=USER, - password=PASSWORD, - domain=DOMAIN, - client_machine_name="KHL_SOFT", - sheet_name="TEAMS", # или None, или список листов - ) - df = df.replace([float("inf"), float("-inf")], pd.NA) - columns_to_keep = [ - "Team", "Logo", "Short", "HexPodl", # ← укажи свои - ] - df = df.loc[:, [c for c in columns_to_keep if c in df.columns]] - json_text = df.to_json(orient="records", force_ascii=False) # NaN/NA -> null - return Response(content=json_text, media_type="application/json; charset=utf-8") @app.get("/teams/stats") async def teams_stats( @@ -756,16 +734,13 @@ async def info(): away_name = str(row.get("visitorName_en", "")).strip() # 3) Подтягиваем справочник команд из Excel (лист TEAMS) - teams_df = read_excel_from_smb( - server_name=SERVER_NAME, - server_ip=SERVER_IP, - share_name=SHARE, - file_path_in_share=PATH_IN_SHARE, - username=USER, + teams_df = nasio.load_formatted( + user=USER, password=PASSWORD, - domain=DOMAIN, - client_machine_name="KHL_SOFT", - sheet_name="TEAMS", + nas_ip=SERVER_NAME, + nas_port="443", + path=PATH, + sheet="TEAMS" ) # Оставляем только полезные поля (подгони под свой файл) diff --git a/requirements.txt b/requirements.txt index f91e978..8d1f591 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,6 @@ requests>=2.31.0 python-telegram-handler python-dotenv>=1.1.0 lxml -python-dotenv \ No newline at end of file +python-dotenv +--extra-index-url https://git.tvstart.ru/api/packages/lexx/pypi/simple +nasio \ No newline at end of file diff --git a/smb_excel.py b/smb_excel.py deleted file mode 100644 index acb7b85..0000000 --- a/smb_excel.py +++ /dev/null @@ -1,154 +0,0 @@ -# smb_excel.py (обновлённый фрагмент) -from io import BytesIO -from typing import Optional, Union, Any, Dict -#from smb.SMBConnection import SMBConnection -import pandas as pd -import re - -class SMBDownloadError(Exception): - pass - -def _normalize_path(p: str) -> str: - """Убирает случайные r"..."/"...", лишние кавычки и ставит прямые слэши.""" - if p is None: - return p - # уберём обрамляющие кавычки/префикс r"..." - m = re.fullmatch(r"""r?["'](.*)["']""", p.strip()) - if m: - p = m.group(1) - # заменим \ на / - p = p.replace("\\", "/").lstrip("/") # путь внутри шары не должен начинаться с / - return p - -def _try_connect( - remote_name: str, - server_ip: str, - username: str, - password: str, - *, - client_machine_name: str, - domain: str, - port: int -) -> Optional[SMBConnection]: - conn = SMBConnection( - username, - password, - client_machine_name, - remote_name, # ВАЖНО: remote_name — имя сервера (или IP как fallback) - domain=domain, - use_ntlm_v2=True, - is_direct_tcp=True - ) - try: - if conn.connect(server_ip, port): - return conn - except Exception: - pass - return None - -def _connect_smb( - server_name: str, - server_ip: str, - username: str, - password: str, - *, - client_machine_name: str = "client", - domain: str = "", - port: int = 445, -) -> SMBConnection: - """ - Пробуем два варианта remote_name: (1) реальное имя сервера, (2) IP. - """ - for remote_name in (server_name, server_ip): - if not remote_name: - continue - conn = _try_connect( - remote_name=remote_name, - server_ip=server_ip, - username=username, - password=password, - client_machine_name=client_machine_name, - domain=domain, - port=port, - ) - if conn: - return conn - raise SMBDownloadError( - f"Не удалось подключиться к SMB {server_ip}:{port}. " - f"Проверь server_name (реальное имя хоста), домен/логин и доступность порта 445." - ) - -def fetch_smb_file( - *, - server_name: str, - server_ip: str, - share_name: str, - file_path_in_share: str, - username: str, - password: str, - client_machine_name: str = "client", - domain: str = "", - port: int = 445, -) -> BytesIO: - """ - Возвращает содержимое файла из SMB как BytesIO. - """ - file_path_in_share = _normalize_path(file_path_in_share) - conn: Optional[SMBConnection] = None - try: - conn = _connect_smb( - server_name=server_name, - server_ip=server_ip, - username=username, - password=password, - client_machine_name=client_machine_name, - domain=domain, - port=port, - ) - # Быстрая проверка существования каталога/файла - parent = "/".join(file_path_in_share.split("/")[:-1]) or "" - # listPath кидает исключение, если каталога/шары нет — получим понятную ошибку - if parent: - conn.listPath(share_name, parent) - - buf = BytesIO() - conn.retrieveFile(share_name, file_path_in_share, buf) - buf.seek(0) - return buf - except Exception as e: - raise SMBDownloadError( - f"Ошибка скачивания {share_name}/{file_path_in_share}: {e}" - ) from e - finally: - if conn: - try: - conn.close() - except Exception: - pass - -def read_excel_from_smb( - *, - server_name: str, - server_ip: str, - share_name: str, - file_path_in_share: str, - username: str, - password: str, - client_machine_name: str = "client", - domain: str = "", - port: int = 445, - sheet_name: Optional[Union[str, int, list]] = None, - **read_excel_kwargs: Dict[str, Any], -) -> pd.DataFrame: - file_obj = fetch_smb_file( - server_name=server_name, - server_ip=server_ip, - share_name=share_name, - file_path_in_share=file_path_in_share, - username=username, - password=password, - client_machine_name=client_machine_name, - domain=domain, - port=port, - ) - return pd.read_excel(file_obj, sheet_name=sheet_name, **read_excel_kwargs)