From e645e57f74792aabd5373b947135e94b5953b4f1 Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Thu, 13 Nov 2025 15:07:53 +0300 Subject: [PATCH] add system messages --- LichessClientTG_bot/admin_bot.py | 121 ++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/LichessClientTG_bot/admin_bot.py b/LichessClientTG_bot/admin_bot.py index 6fe69b9..f1ed6ac 100644 --- a/LichessClientTG_bot/admin_bot.py +++ b/LichessClientTG_bot/admin_bot.py @@ -4,12 +4,18 @@ Sends notifications about new users and new tracked players """ import logging +import sqlite3 +import aiohttp +import asyncio from typing import Optional from telegram import Update -from telegram.ext import Application, CommandHandler, ContextTypes +from telegram.ext import ( + Application, CommandHandler, ContextTypes, + ConversationHandler, MessageHandler, filters +) -from config import ADMINPANEL_TELEGRAM_BOT_TOKEN, DATABASE_PATH +from config import ADMINPANEL_TELEGRAM_BOT_TOKEN, DATABASE_PATH, TELEGRAM_BOT_TOKEN from database import Database from message_counters import MessageCounters @@ -20,6 +26,9 @@ logging.basicConfig( ) logger = logging.getLogger(__name__) +# Conversation states for system message +WAITING_FOR_SYSTEM_MESSAGE = range(1) + class AdminBot: def __init__(self): @@ -147,6 +156,97 @@ class AdminBot: logger.error(f"Error getting status: {e}") await update.message.reply_text(f"❌ Ошибка получения статистики: {e}") + async def system_mes_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Start system message command - ask for message text""" + await update.message.reply_text( + "📨 Введите текст сообщения для отправки всем пользователям:\n\n" + "Используйте /cancel для отмены." + ) + return WAITING_FOR_SYSTEM_MESSAGE + + async def handle_system_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Handle system message text input and send to all users""" + message_text = update.message.text + + if not message_text or not message_text.strip(): + await update.message.reply_text("❌ Сообщение не может быть пустым. Попробуйте снова или используйте /cancel для отмены.") + return WAITING_FOR_SYSTEM_MESSAGE + + # Get all users from database + try: + conn = sqlite3.connect(self.db.db_path) + cursor = conn.cursor() + cursor.execute("SELECT user_id FROM telegram_users") + users = cursor.fetchall() + conn.close() + + total_users = len(users) + if total_users == 0: + await update.message.reply_text("❌ В базе данных нет пользователей для отправки сообщения.") + return ConversationHandler.END + + # Send status message + status_msg = await update.message.reply_text( + f"📤 Отправка сообщения {total_users} пользователям...\n\n" + f"Сообщение:\n{message_text}" + ) + + # Send message to all users + success_count = 0 + failed_count = 0 + + # Format message with system message header + formatted_message = f"🔔 System Message\n\n{message_text}" + + for i, (user_id,) in enumerate(users): + try: + url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage" + async with aiohttp.ClientSession() as session: + async with session.post(url, json={ + "chat_id": user_id, + "text": formatted_message, + "parse_mode": "HTML" + }, timeout=aiohttp.ClientTimeout(total=5)) as response: + if response.status == 200: + success_count += 1 + else: + failed_count += 1 + error_text = await response.text() + logger.warning(f"Failed to send to user {user_id}: {error_text}") + except Exception as e: + failed_count += 1 + logger.error(f"Error sending to user {user_id}: {e}") + + # Add small delay to avoid rate limiting (except for the last user) + if i < len(users) - 1: + await asyncio.sleep(0.05) # 50ms delay between messages + + # Update status message + result_text = ( + f"✅ Рассылка завершена\n\n" + f"📊 Статистика:\n" + f"• Всего пользователей: {total_users}\n" + f"• Успешно отправлено: {success_count}\n" + f"• Ошибок: {failed_count}\n\n" + f"Отправленное сообщение:\n{message_text}" + ) + await status_msg.edit_text(result_text, parse_mode='HTML') + + logger.info(f"System message sent: {success_count} successful, {failed_count} failed out of {total_users} users") + + except Exception as e: + logger.error(f"Error in system message sending: {e}") + import traceback + logger.error(traceback.format_exc()) + await update.message.reply_text(f"❌ Ошибка при отправке сообщений: {e}") + + return ConversationHandler.END + + async def cancel_system_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Cancel system message command""" + await update.message.reply_text("❌ Отправка сообщения отменена.") + return ConversationHandler.END + async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): """Start command - register admin chat""" try: @@ -156,7 +256,8 @@ class AdminBot: await update.message.reply_text( "✅ Админ-панель активирована!\n\n" "Доступные команды:\n" - "/status - Показать статистику" + "/status - Показать статистику\n" + "/system_mes - Отправить сообщение всем пользователям" ) except Exception as e: logger.error(f"Error in start command: {e}") @@ -171,6 +272,20 @@ class AdminBot: """Setup all handlers""" self.application = application # Store application reference + # Conversation handler for system message + system_mes_conv = ConversationHandler( + entry_points=[CommandHandler("system_mes", self.system_mes_start)], + states={ + WAITING_FOR_SYSTEM_MESSAGE: [ + MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_system_message) + ], + }, + fallbacks=[CommandHandler("cancel", self.cancel_system_message)] + ) + + # Add conversation handler + application.add_handler(system_mes_conv) + # Add start command handler application.add_handler(CommandHandler("start", self.start))