93 lines
4.0 KiB
Python
93 lines
4.0 KiB
Python
# chat.py
|
||
import logging
|
||
from telegram import Update, InputMediaPhoto
|
||
from telegram.ext import ContextTypes
|
||
from asgiref.sync import sync_to_async
|
||
from bot.state import BINDING_PENDING
|
||
|
||
class ChatHandler:
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
self.logger = logging.getLogger(__name__)
|
||
|
||
@sync_to_async
|
||
def get_bot_settings(self):
|
||
from bot.models import BotConfig
|
||
settings = BotConfig.objects.first()
|
||
if settings is None:
|
||
settings = BotConfig.objects.create(chat_enabled=True)
|
||
return settings
|
||
|
||
@sync_to_async
|
||
def get_client_by_telegram_id(self, telegram_id: int):
|
||
from webapp.models import Client
|
||
try:
|
||
return Client.objects.get(telegram_id=str(telegram_id))
|
||
except Client.DoesNotExist:
|
||
return None
|
||
|
||
@sync_to_async
|
||
def get_all_clients(self):
|
||
from webapp.models import Client
|
||
return list(Client.objects.all())
|
||
|
||
async def broadcast_message(self, sender, message_text: str, photo_media: InputMediaPhoto = None):
|
||
clients = await self.get_all_clients()
|
||
for client in clients:
|
||
if client.telegram_id == sender.telegram_id:
|
||
continue
|
||
try:
|
||
if photo_media:
|
||
await self.bot.send_photo(
|
||
chat_id=client.telegram_id,
|
||
photo=photo_media.media,
|
||
caption=photo_media.caption,
|
||
parse_mode="Markdown"
|
||
)
|
||
else:
|
||
await self.bot.send_message(
|
||
chat_id=client.telegram_id,
|
||
text=message_text,
|
||
parse_mode="Markdown"
|
||
)
|
||
except Exception as e:
|
||
self.logger.error(f"Ошибка отправки сообщения пользователю {client.telegram_id}: {e}")
|
||
|
||
async def handle_chat_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||
if not update.message:
|
||
return
|
||
|
||
bot_settings = await self.get_bot_settings()
|
||
if not bot_settings.chat_enabled:
|
||
await update.message.reply_text("🚫 Чат временно отключён администрацией.")
|
||
return
|
||
|
||
chat_id = update.message.chat_id
|
||
sender = await self.get_client_by_telegram_id(chat_id)
|
||
# Если пользователь не привязан, но находится в pending, обрабатываем как ввод КК
|
||
if not sender and chat_id in BINDING_PENDING:
|
||
# Импортируем функцию process_binding_input из bot.handlers
|
||
from bot.handlers import process_binding_input
|
||
await process_binding_input(update, context)
|
||
return
|
||
# Если пользователь не привязан и не находится в pending, просим привязаться
|
||
if not sender:
|
||
await update.message.reply_text("🚫 Для участия в чате привяжите свою клиентскую карту с помощью /bind")
|
||
return
|
||
|
||
# Если у пользователя отключена возможность отправки сообщений
|
||
if getattr(sender, "chat_disabled", False):
|
||
await update.message.reply_text("🚫 Вы не можете отправлять сообщения. Обратитесь к администратору.")
|
||
return
|
||
|
||
sender_name = sender.name if sender else "Аноним"
|
||
broadcast_text = f"💬 *{sender_name} пишет:*\n{update.message.text or ''}"
|
||
|
||
photo_media = None
|
||
if update.message.photo:
|
||
photo = update.message.photo[-1]
|
||
caption = update.message.caption or broadcast_text
|
||
photo_media = InputMediaPhoto(photo.file_id, caption=caption)
|
||
|
||
await self.broadcast_message(sender, broadcast_text, photo_media)
|