init commit

This commit is contained in:
2025-08-30 10:33:46 +09:00
commit 49b3cea942
304 changed files with 116485 additions and 0 deletions

293
direct_api_test.py Normal file
View File

@@ -0,0 +1,293 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Тестовый скрипт для прямого доступа к API Synology для получения информации о системе.
Используется для отладки и определения совместимых API.
"""
import requests
import logging
import json
import sys
import os
import urllib3
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
# Добавляем корневой каталог в путь для импорта
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.config.config import (
SYNOLOGY_HOST,
SYNOLOGY_PORT,
SYNOLOGY_USERNAME,
SYNOLOGY_PASSWORD,
SYNOLOGY_SECURE
)
# Отключение предупреждений о небезопасных SSL-соединениях
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Настройка логирования
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def direct_api_test():
"""Прямой тест API без использования классов для определения проблемы"""
# Создаем базовую сессию
session = requests.Session()
session.verify = False # Отключаем проверку SSL
# Добавляем повторные попытки для HTTP-запросов
retry_strategy = Retry(
total=3,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST"],
backoff_factor=1.0
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
# Формируем базовый URL
protocol = "https" if SYNOLOGY_SECURE else "http"
base_url = f"{protocol}://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi"
logger.info(f"Тестирование прямого API доступа к {base_url}")
# Шаг 1: Авторизация
logger.info("Шаг 1: Попытка авторизации...")
# Сначала получаем информацию об API авторизации
api_info_url = f"{base_url}/entry.cgi"
api_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "SYNO.API.Auth"
}
try:
auth_info_response = session.get(api_info_url, params=api_info_params, timeout=10)
auth_info_data = auth_info_response.json()
if auth_info_data.get("success"):
auth_info = auth_info_data.get("data", {}).get("SYNO.API.Auth", {})
auth_path = auth_info.get("path", "auth.cgi")
auth_max_version = auth_info.get("maxVersion", 6)
logger.info(f"API авторизации: путь={auth_path}, макс. версия={auth_max_version}")
# Пробуем версию 6 или максимальную доступную
auth_version = min(6, auth_max_version)
# Выполняем авторизацию
auth_url = f"{base_url}/{auth_path}"
auth_params = {
"api": "SYNO.API.Auth",
"version": str(auth_version),
"method": "login",
"account": SYNOLOGY_USERNAME,
"passwd": SYNOLOGY_PASSWORD,
"session": "DirectApiTest",
"format": "cookie"
}
# Для версии 6+ используем немного другой формат
if auth_version >= 6:
auth_params["enable_syno_token"] = "yes"
logger.info(f"Авторизация с использованием SYNO.API.Auth v{auth_version}")
auth_response = session.get(auth_url, params=auth_params, timeout=10)
auth_data = auth_response.json()
if auth_data.get("success"):
sid = auth_data.get("data", {}).get("sid")
logger.info(f"Авторизация успешна! SID: {sid[:10]}...")
# Шаг 2: Тестирование различных API для получения информации о системе
logger.info("Шаг 2: Тестирование различных API для получения информации о системе")
# Создаем список API для тестирования
api_to_test = [
{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 1},
{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 2},
{"name": "SYNO.Core.System", "method": "info", "version": 1},
{"name": "SYNO.Core.System", "method": "info", "version": 2},
{"name": "SYNO.Core.System.Status", "method": "get", "version": 1},
{"name": "SYNO.Core.System.Status", "method": "get", "version": 2},
{"name": "SYNO.Core.System.Utilization", "method": "get", "version": 1},
{"name": "SYNO.Core.CurrentConnection", "method": "list", "version": 1}
]
# Перебираем все API и тестируем их
for api in api_to_test:
# Сначала получаем информацию о конкретном API
try:
api_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": api["name"]
}
api_info_resp = session.get(api_info_url, params=api_info_params, timeout=10)
api_info_data = api_info_resp.json()
if api_info_data.get("success") and api["name"] in api_info_data.get("data", {}):
api_details = api_info_data["data"][api["name"]]
api_path = api_details.get("path", "entry.cgi")
api_min_version = api_details.get("minVersion", 1)
api_max_version = api_details.get("maxVersion", 1)
# Проверяем, поддерживается ли указанная версия
if api["version"] < api_min_version:
logger.warning(f"{api['name']} v{api['version']} ниже минимальной {api_min_version}, используем {api_min_version}")
test_version = api_min_version
elif api["version"] > api_max_version:
logger.warning(f"{api['name']} v{api['version']} выше максимальной {api_max_version}, используем {api_max_version}")
test_version = api_max_version
else:
test_version = api["version"]
# Выполняем запрос API
test_url = f"{base_url}/{api_path}"
test_params = {
"api": api["name"],
"version": str(test_version),
"method": api["method"],
"_sid": sid # Используем sid для аутентификации
}
logger.info(f"Тестирование {api['name']}.{api['method']} v{test_version}")
test_response = session.get(test_url, params=test_params, timeout=10)
test_data = test_response.json()
if test_data.get("success"):
logger.info(f"API {api['name']}.{api['method']} v{test_version} РАБОТАЕТ!")
logger.info(f"Результат: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
else:
error_code = test_data.get("error", {}).get("code", -1)
logger.error(f"API {api['name']}.{api['method']} v{test_version} ОШИБКА: {error_code}")
# Если ошибка связана с сессией, попробуем еще раз авторизоваться
if error_code == 119: # Session timeout
logger.info("Повторная авторизация из-за ошибки 119...")
# Создаем новую сессию
new_session = requests.Session()
new_session.verify = False
auth_response = new_session.get(auth_url, params=auth_params, timeout=10)
auth_data = auth_response.json()
if auth_data.get("success"):
new_sid = auth_data.get("data", {}).get("sid")
logger.info(f"Повторная авторизация успешна! Новый SID: {new_sid[:10]}...")
# Пробуем запрос с новым SID
test_params["_sid"] = new_sid
logger.info(f"Повторное тестирование {api['name']}.{api['method']} v{test_version}")
test_response = new_session.get(test_url, params=test_params, timeout=10)
test_data = test_response.json()
if test_data.get("success"):
logger.info(f"API {api['name']}.{api['method']} v{test_version} теперь РАБОТАЕТ!")
logger.info(f"Результат с новой сессией: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
else:
error_code = test_data.get("error", {}).get("code", -1)
logger.error(f"API {api['name']}.{api['method']} v{test_version} ВСЕ ЕЩЕ С ОШИБКОЙ: {error_code}")
else:
logger.warning(f"API {api['name']} не найден в информации API")
except Exception as e:
logger.error(f"Ошибка при тестировании {api['name']}.{api['method']} v{api['version']}: {str(e)}")
# Шаг 3: Тестирование комбинации запросов для решения проблемы
logger.info("Шаг 3: Тестирование комбинации запросов для решения проблемы")
# Создаем новую сессию для каждого запроса
for api in [{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 1}]:
try:
fresh_session = requests.Session()
fresh_session.verify = False
# Авторизуемся
auth_response = fresh_session.get(auth_url, params=auth_params, timeout=10)
auth_data = auth_response.json()
if auth_data.get("success"):
fresh_sid = auth_data.get("data", {}).get("sid")
logger.info(f"Авторизация в новой сессии успешна! SID: {fresh_sid[:10]}...")
# Сразу же делаем запрос для получения информации в той же сессии
test_params = {
"api": api["name"],
"version": str(api["version"]),
"method": api["method"],
"_sid": fresh_sid
}
test_url = f"{base_url}/entry.cgi" # Используем entry.cgi по умолчанию
logger.info(f"Тест в свежей сессии: {api['name']}.{api['method']} v{api['version']}")
test_response = fresh_session.get(test_url, params=test_params, timeout=10)
test_data = test_response.json()
if test_data.get("success"):
logger.info(f"API в свежей сессии РАБОТАЕТ!")
logger.info(f"Результат: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
else:
error_code = test_data.get("error", {}).get("code", -1)
logger.error(f"API в свежей сессии ОШИБКА: {error_code}")
except Exception as e:
logger.error(f"Ошибка при тестировании свежей сессии: {str(e)}")
# Шаг 4: Получаем информацию об остальных API
logger.info("Шаг 4: Получаем информацию о доступных API для уточнения проблемы")
# Запрашиваем все API из SYNO.API.Info
try:
all_api_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "all"
}
all_api_response = session.get(api_info_url, params=all_api_params, timeout=15) # Больший таймаут для большого ответа
all_api_data = all_api_response.json()
if all_api_data.get("success"):
api_list = all_api_data.get("data", {})
logger.info(f"Получен список всех API. Найдено {len(api_list)} API.")
# Ищем интересующие нас API для отладки
interested_in = ["SYNO.DSM.Info", "SYNO.Core.System", "SYNO.Core.Hardware",
"SYNO.Core.System.Status", "SYNO.API.Auth"]
logger.info("Информация о важных API:")
for api_name in interested_in:
if api_name in api_list:
logger.info(f"{api_name}: {api_list[api_name]}")
else:
logger.warning(f"API {api_name} не найден")
else:
logger.error("Не удалось получить список всех API")
except Exception as e:
logger.error(f"Ошибка при получении списка API: {str(e)}")
else:
error_code = auth_data.get("error", {}).get("code", -1)
logger.error(f"Авторизация не удалась! Код ошибки: {error_code}")
else:
logger.error("Не удалось получить информацию об API авторизации")
except Exception as e:
logger.error(f"Произошла ошибка при выполнении теста: {str(e)}")
if __name__ == "__main__":
logger.info("Запуск прямого теста API Synology")
direct_api_test()