add system messages

This commit is contained in:
vrubelroman 2025-11-13 15:07:53 +03:00
parent ceb62b408a
commit e645e57f74

View file

@ -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"🔔 <b>System Message</b>\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"✅ <b>Рассылка завершена</b>\n\n"
f"📊 Статистика:\n"
f"Всего пользователей: {total_users}\n"
f"• Успешно отправлено: {success_count}\n"
f"• Ошибок: {failed_count}\n\n"
f"<b>Отправленное сообщение:</b>\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))