Обновить instruct/handlers.py

This commit is contained in:
2026-07-30 22:29:53 +07:00
parent a3b9796fe8
commit c5edcbdd06
+36 -20
View File
@@ -116,10 +116,33 @@ async def send_2fa_alert_email(cn: str, user_id: str, ticket_id: str):
</html>
"""
# Запускаем отправку в отдельном потоке, чтобы не блокировать event loop asyncio
await asyncio.to_thread(_send_email_sync, ALERTS_SUPPORT_EMAILS, subject, body_html)
# ВСПОМОГАТЕЛЬНАЯ ФУНКЦИЯ ПРОВЕРКИ ЗАКРЫТОГО СТАТУСА ЗАЯВКИ
def _is_ticket_closed(status_data) -> bool:
"""
Проверяет, является ли статус заявки закрытым / исполненным.
Использует поиск по основам слов для улавливания всех форматов и склонений.
"""
if not status_data:
return False
if isinstance(status_data, dict):
status_str = str(status_data.get("name", "")).strip().lower()
else:
status_str = str(status_data).strip().lower()
closed_keywords = [
"closed", "close", "resolved", "resolv", "solved", "solv",
"rejected", "reject", "canceled", "cancel", "completed", "complete",
"закрыт", "решен", "исполн", "выполн", "отмен", "отклон", "заверш"
]
return any(kw in status_str for kw in closed_keywords)
# ОСНОВНАЯ ЛОГИКА АКТИВНОСТИ
def get_user_cn(user_id: str) -> str | None:
@@ -241,13 +264,6 @@ async def _find_existing_trueconf_ticket(cn: str, requester_email: str = None) -
"""Находит открытую или находящуюся в работе заявку по Trueconf."""
subject_keyword = "запрос доступа к trueconf"
CLOSED_STATUSES = {
"resolved", "rejected", "closed", "solved", "canceled", "cancelled",
"решена", "закрыта", "отклонена", "выполнена", "отменена", "закрыто", "решено",
# ManageEngine Service Desk Plus statuses
"исполнен", "исполнена", "исполнено", "выполнен", "выполнена", "выполнено",
}
try:
url = f"{SD_URL.rstrip('/')}/api/v3/requests"
headers = {"TECHNICIAN_KEY": SD_TOKEN}
@@ -278,24 +294,28 @@ async def _find_existing_trueconf_ticket(cn: str, requester_email: str = None) -
if subject_keyword not in req_subject:
continue
req_status = req.get("status", {})
status_name = (
req_status.get("name", "") if isinstance(req_status, dict) else str(req_status)
).strip().lower()
req_id = req.get("id")
req_status = req.get("status")
if status_name in CLOSED_STATUSES:
logger.info(f"Skipping closed ticket #{req_id} (status: '{status_name}')")
# 1. Проверяем статус в общем списке
if _is_ticket_closed(req_status):
logger.info(f"Skipping closed ticket #{req_id} (list status: '{req_status}')")
continue
logger.info(f"Checking candidate open ticket #{req_id} (status: '{status_name}')")
logger.info(f"Checking candidate open ticket #{req_id}")
detail_url = f"{SD_URL.rstrip('/')}/api/v3/requests/{req_id}"
detail_resp = await client.get(detail_url, headers=headers, timeout=10.0)
if detail_resp.status_code == 200:
detail = detail_resp.json().get("request", {})
# 2. Повторно проверяем статус в деталях заявки
detail_status = detail.get("status")
if _is_ticket_closed(detail_status):
logger.info(f"Skipping closed ticket #{req_id} (detail status: '{detail_status}')")
continue
requester = detail.get("requester", {})
req_name = str(requester.get("name", "") or requester.get("display_name", "")).strip().lower()
req_email = str(requester.get("email", "") or requester.get("email_id", "")).strip().lower()
@@ -535,7 +555,3 @@ async def instruct_router_handler(msg: Message):
await msg.answer(INSTRUCT_MAIN_MENU_TEXT, parse_mode="html")
else:
await msg.answer(UNKNOWN_MAIN_CMD_TEXT, parse_mode="html")