v1.7.1: fix all P1-P4, C1-C6, H1-H6, M1-M7, L1-L3 from error.md — async migrations, CSS variables, SQL validation, event loop, prompt injection, VCF parsing, race conditions, unused imports, gitignore

This commit is contained in:
2026-05-29 03:46:41 +03:00
parent 72b6879f4b
commit 54af5892d5
21 changed files with 406 additions and 156 deletions
+1 -11
View File
@@ -20,7 +20,7 @@ async def handle_contact_received(user_id: int, conv_id: int, contact_text: str)
if PHONE_PATTERN.match(contact_text):
user.phone = contact_text
elif EMAIL_PATTERN.match(contact_text):
user.phone = contact_text
user.email = contact_text
result = await db.execute(
select(BotConversation).where(BotConversation.id == conv_id)
@@ -39,16 +39,6 @@ async def handle_contact_received(user_id: int, conv_id: int, contact_text: str)
async def handle_manual_contact(user_id: int, conv_id: int, text: str) -> None:
text = text.strip()
async with async_session() as db:
msg = BotMessage(
conversation_id=conv_id,
direction="incoming",
text=text,
created_at=datetime.datetime.utcnow(),
)
db.add(msg)
await db.commit()
if PHONE_PATTERN.match(text) or EMAIL_PATTERN.match(text):
await handle_contact_received(user_id, conv_id, text)
else:
+30 -13
View File
@@ -37,16 +37,35 @@ async def handle_greeting(
now = datetime.datetime.utcnow()
if not user:
user = BotUser(
id=user_id,
first_name=first_name,
last_name=last_name,
username=username,
last_interaction=now,
total_conversations=1,
created_at=now,
)
db.add(user)
try:
user = BotUser(
id=user_id,
first_name=first_name,
last_name=last_name,
username=username,
last_interaction=now,
total_conversations=1,
created_at=now,
)
db.add(user)
await db.commit()
await db.refresh(user)
except Exception:
await db.rollback()
existing = await db.execute(
select(BotUser).where(BotUser.id == user_id)
)
user = existing.scalar_one_or_none()
if user:
if first_name:
user.first_name = first_name
if last_name:
user.last_name = last_name
if username:
user.username = username
user.last_interaction = now
user.total_conversations = (user.total_conversations or 0) + 1
await db.commit()
else:
if first_name:
user.first_name = first_name
@@ -56,9 +75,7 @@ async def handle_greeting(
user.username = username
user.last_interaction = now
user.total_conversations = (user.total_conversations or 0) + 1
await db.commit()
await db.refresh(user)
await db.commit()
conv = BotConversation(
user_id=user_id,
+43 -47
View File
@@ -5,7 +5,6 @@ from app.database import async_session
from app.models import BotUser, BotConversation, BotMessage, BotTicket, BotTicketMessage, BotTicketStatus
from app.max_api import max_api
from app.settings_cache import settings_cache
from app.config_reader import config_reader
from app.email_sender import email_sender
logger = logging.getLogger(__name__)
@@ -22,66 +21,61 @@ async def handle_inquiry(user_id: int, conv_id: int, text: str) -> None:
user_result = await db.execute(select(BotUser).where(BotUser.id == user_id))
user = user_result.scalar_one_or_none()
if not user:
await max_api.send_message(
user_id,
"Произошла ошибка при обработке запроса. Пожалуйста, попробуйте ещё раз позже.",
)
return
conv.inquiry_text = text
conv.state = "escalated"
await _finalize_ticket_in_tx(db, user_id, conv, user, text)
await db.commit()
await _finalize_ticket(user_id, conv, user, text)
async def _finalize_ticket(
async def _finalize_ticket_in_tx(
db,
user_id: int,
conv: BotConversation,
user: BotUser,
inquiry_text: str,
) -> None:
async with async_session() as db:
user_name = user.first_name or user.last_name or ""
ticket_title = f"Обращение от {user_name or 'клиента'} ({user_id})"
if len(inquiry_text) > 100:
ticket_title = inquiry_text[:97] + "..."
user_name = user.first_name or user.last_name or ""
ticket_title = f"Обращение от {user_name or 'клиента'} ({user_id})"
if len(inquiry_text) > 100:
ticket_title = inquiry_text[:97] + "..."
ticket = BotTicket(
user_id=user_id,
title=ticket_title,
description=inquiry_text,
priority="normal",
status="Новая",
created_by="bot",
)
db.add(ticket)
await db.commit()
await db.refresh(ticket)
ticket = BotTicket(
user_id=user_id,
title=ticket_title,
description=inquiry_text,
priority="normal",
status="Новая",
created_by="bot",
)
db.add(ticket)
await db.flush()
msg = BotTicketMessage(
ticket_id=ticket.id,
direction="incoming",
text=inquiry_text,
)
db.add(msg)
msg = BotTicketMessage(
ticket_id=ticket.id,
direction="incoming",
text=inquiry_text,
)
db.add(msg)
status_log = BotTicketStatus(
ticket_id=ticket.id,
new_status="Новая",
changed_by="bot",
)
db.add(status_log)
status_log = BotTicketStatus(
ticket_id=ticket.id,
new_status="Новая",
changed_by="bot",
)
db.add(status_log)
conv_result = await db.execute(
select(BotConversation).where(BotConversation.id == conv.id)
)
conv_obj = conv_result.scalar_one_or_none()
if conv_obj:
conv_obj.state = "completed"
conv.state = "completed"
await db.commit()
async with async_session() as db2:
user_obj = await db2.get(BotUser, user_id)
if user_obj:
user_obj.total_tickets = (user_obj.total_tickets or 0) + 1
await db2.commit()
user.total_tickets = (user.total_tickets or 0) + 1
user_info = f"ID: {user_id}\nИмя: {user.first_name or 'не указано'} {user.last_name or ''}"
contact = user.phone or "не указан"
@@ -93,14 +87,16 @@ async def _finalize_ticket(
"Обращение через Виртуального помощника AegisOne Engineering",
)
email_sender.send_ticket_escalation(
import asyncio
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, lambda: email_sender.send_ticket_escalation(
to=support_email,
subject=email_subject,
user_info=user_info,
contact=contact,
inquiry=inquiry_text,
history=history,
)
))
await max_api.send_message(
user_id,