forked from FOSS/ASF-Control-Bot
237 lines
8.0 KiB
Python
237 lines
8.0 KiB
Python
import aiohttp
|
|
import requests
|
|
|
|
from bot.config import ASF_PASSWORD, ASF_URL
|
|
from bot.logging_utils import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def _headers() -> dict[str, str | None]:
|
|
return {"Authentication": ASF_PASSWORD}
|
|
|
|
|
|
def asf_get(path: str) -> requests.Response:
|
|
logger.info("Отправка GET-запроса в ASF: path=%s", path)
|
|
response = requests.get(f"{ASF_URL}{path}", headers=_headers())
|
|
|
|
logger.info(
|
|
"Получен ответ ASF на GET-запрос: path=%s status=%s", path, response.status_code
|
|
)
|
|
|
|
return response
|
|
|
|
|
|
def asf_post(path: str, payload: dict | None = None) -> requests.Response:
|
|
logger.info(
|
|
"Отправка POST-запроса в ASF: path=%s payload_keys=%s",
|
|
path,
|
|
sorted((payload or {}).keys()),
|
|
)
|
|
|
|
response = requests.post(f"{ASF_URL}{path}", headers=_headers(), json=payload)
|
|
logger.info(
|
|
"Получен ответ ASF на POST-запрос: path=%s status=%s",
|
|
path,
|
|
response.status_code,
|
|
)
|
|
|
|
return response
|
|
|
|
|
|
def get_asf_status() -> requests.Response:
|
|
logger.info("Запрос статуса ASF")
|
|
response = requests.get(f"{ASF_URL}/Api/ASF", headers=_headers()) # type: ignore[arg-type]
|
|
logger.info("Получен статус ASF: status=%s", response.status_code)
|
|
|
|
return response
|
|
|
|
|
|
def get_all_bots() -> requests.Response:
|
|
return asf_get("/Api/Bot/ASF")
|
|
|
|
|
|
def get_bot(bot_name: str) -> requests.Response:
|
|
return asf_get(f"/Api/Bot/{bot_name}")
|
|
|
|
|
|
def get_plugins() -> requests.Response:
|
|
return asf_get("/Api/Plugins")
|
|
|
|
|
|
def send_command(command: str) -> requests.Response:
|
|
return asf_post("/Api/Command", {"Command": command})
|
|
|
|
|
|
def restart_asf() -> requests.Response:
|
|
return send_command("!restart")
|
|
|
|
|
|
async def get_bot_inventory(bot_name: str, appid: int, contextid: int) -> dict | None:
|
|
logger.info(
|
|
"Запрос инвентаря бота: bot=%s appid=%s contextid=%s",
|
|
bot_name,
|
|
appid,
|
|
contextid,
|
|
)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(
|
|
f"{ASF_URL}/Api/Bot/{bot_name}/Inventory/{appid}/{contextid}",
|
|
headers=_headers(),
|
|
) as response:
|
|
if response.status != 200:
|
|
logger.warning(
|
|
"Не удалось получить инвентарь бота: bot=%s appid=%s contextid=%s status=%s",
|
|
bot_name,
|
|
appid,
|
|
contextid,
|
|
response.status,
|
|
)
|
|
return None
|
|
|
|
data = await response.json()
|
|
if not data.get("Success"):
|
|
logger.warning(
|
|
"ASF вернул ошибку при получении инвентаря: bot=%s appid=%s contextid=%s",
|
|
bot_name,
|
|
appid,
|
|
contextid,
|
|
)
|
|
return None
|
|
|
|
logger.info(
|
|
"Инвентарь бота получен: bot=%s appid=%s contextid=%s",
|
|
bot_name,
|
|
appid,
|
|
contextid,
|
|
)
|
|
|
|
return data.get("Result")
|
|
|
|
|
|
async def get_2fa_token(bot_name: str) -> str:
|
|
logger.info("Запрос 2FA-кода: bot=%s", bot_name)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(
|
|
f"{ASF_URL}/Api/Bot/{bot_name}/TwoFactorAuthentication/Token",
|
|
headers=_headers(),
|
|
) as response:
|
|
if response.status != 200:
|
|
logger.warning(
|
|
"Не удалось получить 2FA-код: bot=%s status=%s",
|
|
bot_name,
|
|
response.status,
|
|
)
|
|
return f"Ошибка HTTP {response.status}"
|
|
|
|
data = await response.json()
|
|
if not data.get("Success"):
|
|
logger.warning(
|
|
"ASF вернул ошибку при запросе 2FA-кода: bot=%s", bot_name
|
|
)
|
|
return "Ошибка ASF"
|
|
|
|
try:
|
|
logger.info("2FA-код успешно получен: bot=%s", bot_name)
|
|
return data["Result"][bot_name]["Result"]
|
|
|
|
except Exception:
|
|
logger.exception(
|
|
"Не удалось извлечь 2FA-код из ответа ASF: bot=%s", bot_name
|
|
)
|
|
|
|
return "Не удалось получить код"
|
|
|
|
|
|
async def get_confirmations(bot_name: str) -> list:
|
|
logger.info("Запрос подтверждений 2FA: bot=%s", bot_name)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(
|
|
f"{ASF_URL}/Api/Bot/{bot_name}/TwoFactorAuthentication/Confirmations",
|
|
headers=_headers(),
|
|
) as response:
|
|
if response.status != 200:
|
|
logger.warning(
|
|
"Не удалось получить подтверждения 2FA: bot=%s status=%s",
|
|
bot_name,
|
|
response.status,
|
|
)
|
|
return []
|
|
|
|
data = await response.json()
|
|
if not data.get("Success"):
|
|
logger.warning(
|
|
"ASF вернул ошибку при запросе подтверждений 2FA: bot=%s",
|
|
bot_name,
|
|
)
|
|
return []
|
|
|
|
try:
|
|
result = data["Result"][bot_name]["Result"]
|
|
logger.info(
|
|
"Подтверждения 2FA получены: bot=%s count=%s",
|
|
bot_name,
|
|
len(result),
|
|
)
|
|
return result
|
|
|
|
except Exception:
|
|
logger.exception(
|
|
"Не удалось извлечь подтверждения 2FA из ответа ASF: bot=%s",
|
|
bot_name,
|
|
)
|
|
return []
|
|
|
|
|
|
async def accept_confirmations(bot_name: str) -> int:
|
|
logger.info("Отправка запроса на подтверждение всех 2FA-операций: bot=%s", bot_name)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(
|
|
f"{ASF_URL}/Api/Bot/{bot_name}/TwoFactorAuthentication/Confirmations/Accept",
|
|
headers=_headers(),
|
|
) as response:
|
|
logger.info(
|
|
"Получен ответ на подтверждение 2FA-операций: bot=%s status=%s",
|
|
bot_name,
|
|
response.status,
|
|
)
|
|
|
|
return response.status
|
|
|
|
|
|
def save_bot_config(bot_name: str, config: dict) -> requests.Response:
|
|
logger.info("Сохранение конфигурации бота: bot=%s", bot_name)
|
|
return asf_post(f"/Api/Bot/{bot_name}", {"BotConfig": config})
|
|
|
|
|
|
async def redeem_key(bot_name: str, key: str) -> tuple[bool, str]:
|
|
logger.info("Запрос активации ключа: bot=%s", bot_name)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(
|
|
f"{ASF_URL}/Api/Command",
|
|
headers=_headers(),
|
|
json={"Command": f"!redeem {bot_name} {key}"},
|
|
) as response:
|
|
if response.status != 200:
|
|
logger.warning(
|
|
"Не удалось активировать ключ: bot=%s status=%s",
|
|
bot_name,
|
|
response.status,
|
|
)
|
|
return False, f"HTTP_ERROR_{response.status}"
|
|
|
|
data = await response.json()
|
|
if not data.get("Success"):
|
|
logger.warning(
|
|
"ASF вернул ошибку при активации ключа: bot=%s", bot_name
|
|
)
|
|
return False, "ASF_ERROR"
|
|
|
|
logger.info("ASF вернул результат активации ключа: bot=%s", bot_name)
|
|
return True, str(data.get("Result", ""))
|