bot prime refactor. Notification events & messages

This commit is contained in:
2025-08-03 21:42:07 +09:00
parent 842710fe5c
commit becf4f5c99
22 changed files with 431 additions and 139 deletions

View File

@@ -1,39 +1,99 @@
# bot/utils.py
from telegram import Bot
from telegram import Bot, InlineKeyboardMarkup, InlineKeyboardButton
from django.conf import settings
from telegram import Bot
from bot.models import BotConfig
from django.core.exceptions import ImproperlyConfigured
from urllib.parse import urljoin
from bot.models import BotConfig, BotEventMessageConfig
import logging
from asgiref.sync import sync_to_async
from telegram import InputFile
import os
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def create_bot_instance():
"""
Получает настройки бота из БД и создаёт экземпляр Telegram Bot.
"""
config = BotConfig.objects.first() # предполагается, что конфигурация одна
config = BotConfig.objects.first()
if not config:
raise ImproperlyConfigured("Настройки бота (BotConfig) не сконфигурированы в базе данных.")
raise ImproperlyConfigured("BotConfig не задан.")
# Можно дополнительно использовать config.channel_id и config.bot_name при необходимости.
bot = Bot(token=config.bot_token)
return bot
logger.debug("Создан экземпляр бота с токеном.")
return Bot(token=config.bot_token)
def notify_user(binding_request, approved=True):
bot_token = settings.BOT_CONFIG.bot_token # можно использовать модель BotConfig или настройку из settings
bot = Bot(token=bot_token)
message = "Ваша заявка на привязку успешно подтверждена!" if approved else "Ваша заявка на привязку отклонена."
def get_event_message_sync(event_key: str, context_vars: dict = None):
logger.debug(f"get_event_message_sync для события: {event_key}")
try:
bot.send_message(chat_id=binding_request.telegram_chat_id, text=message)
config = BotEventMessageConfig.objects.select_related("message").get(event=event_key, enabled=True)
msg = config.message
context_vars = context_vars or {}
text = msg.text.format(**context_vars) if msg.text else None
image_name = msg.image.name if msg.image else None # только имя файла
keyboard = None
if msg.buttons_json:
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton(btn["text"], url=btn["url"])]
for btn in msg.buttons_json
])
return {
"text": text,
"image": image_name,
"keyboard": keyboard
}
except Exception as e:
# Обработка ошибок отправки сообщения
print(f"Ошибка уведомления: {e}")
logger.error(f"Ошибка get_event_message_sync для события '{event_key}': {e}")
return None
# Пример использования в точке входа приложения:
if __name__ == '__main__':
# Предполагается, что Django уже настроен (например, через manage.py shell или management command)
bot = create_bot_instance()
# Теперь можно использовать объект bot для отправки сообщений, обработки обновлений и т.д.
print(f"Бот {bot.name} успешно создан!")
def send_event_message_sync(event: str, bot: Bot, chat_id: int, context_vars: dict = None):
msg = get_event_message_sync(event, context_vars)
if not msg:
logger.warning(f"Пропущена отправка: шаблон события '{event}' не найден.")
return
try:
if msg["image"]:
bot.send_photo(chat_id=chat_id, photo=msg["image"], caption=msg["text"], reply_markup=msg["keyboard"])
elif msg["text"]:
bot.send_message(chat_id=chat_id, text=msg["text"], reply_markup=msg["keyboard"])
logger.info(f"Сообщение '{event}' успешно отправлено пользователю {chat_id}")
except Exception as e:
logger.error(f"Ошибка при отправке сообщения '{event}' пользователю {chat_id}: {e}")
@sync_to_async
def get_event_message_async(event_key: str, context_vars: dict = None):
return get_event_message_sync(event_key, context_vars)
async def send_event_message_async(event: str, bot: Bot, chat_id: int, context_vars: dict = None):
msg = await get_event_message_async(event, context_vars)
if not msg:
logger.warning(f"[ASYNC] Пропущена отправка: шаблон события '{event}' не найден.")
return
try:
if msg["image"]:
# локальный путь к файлу
from django.conf import settings
file_path = os.path.join(settings.MEDIA_ROOT, msg["image"])
logger.debug(f"[ASYNC] Отправка фото из {file_path}")
with open(file_path, "rb") as photo:
await bot.send_photo(
chat_id=chat_id,
photo=InputFile(photo),
caption=msg["text"],
reply_markup=msg["keyboard"]
)
elif msg["text"]:
await bot.send_message(
chat_id=chat_id,
text=msg["text"],
reply_markup=msg["keyboard"]
)
logger.info(f"[ASYNC] Сообщение '{event}' отправлено пользователю {chat_id}")
except Exception as e:
logger.error(f"[ASYNC] Ошибка Telegram при отправке '{event}' пользователю {chat_id}: {e}")