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))