From f58bf8b6a74c3d778d6ed62d5d95bff82ed19c35 Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Fri, 28 Nov 2025 18:28:51 +0300 Subject: [PATCH] add /sendusers0 --- LichessClientTG_bot/admin_bot.py | 111 ++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/LichessClientTG_bot/admin_bot.py b/LichessClientTG_bot/admin_bot.py index 66e9931..b12ab7c 100644 --- a/LichessClientTG_bot/admin_bot.py +++ b/LichessClientTG_bot/admin_bot.py @@ -28,6 +28,7 @@ logger = logging.getLogger(__name__) # Conversation states for system message WAITING_FOR_SYSTEM_MESSAGE = range(1) +WAITING_FOR_USERS0_MESSAGE = range(1, 2) class AdminBot: @@ -316,6 +317,102 @@ class AdminBot: await update.message.reply_text("❌ Отправка сообщения отменена.") return ConversationHandler.END + async def sendusers0_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Start sendusers0 command - ask for message text""" + await update.message.reply_text( + "📨 Введите текст сообщения для отправки пользователям без добавленных игроков:\n\n" + "Используйте /cancel для отмены." + ) + return WAITING_FOR_USERS0_MESSAGE + + async def handle_users0_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Handle message text input and send to users without gamers""" + message_text = update.message.text + + if not message_text or not message_text.strip(): + await update.message.reply_text("❌ Сообщение не может быть пустым. Попробуйте снова или используйте /cancel для отмены.") + return WAITING_FOR_USERS0_MESSAGE + + # Get users without gamers from database + try: + conn = sqlite3.connect(self.db.db_path) + cursor = conn.cursor() + cursor.execute(""" + SELECT DISTINCT tu.user_id + FROM telegram_users tu + LEFT JOIN user_gamers ug ON tu.user_id = ug.user_id + WHERE ug.id IS NULL + """) + 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 users without gamers + 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"Users0 message sent: {success_count} successful, {failed_count} failed out of {total_users} users") + + except Exception as e: + logger.error(f"Error in users0 message sending: {e}") + import traceback + logger.error(traceback.format_exc()) + await update.message.reply_text(f"❌ Ошибка при отправке сообщений: {e}") + + return ConversationHandler.END + + async def cancel_users0_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Cancel users0 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: @@ -352,8 +449,20 @@ class AdminBot: fallbacks=[CommandHandler("cancel", self.cancel_system_message)] ) - # Add conversation handler + # Conversation handler for sendusers0 message + sendusers0_conv = ConversationHandler( + entry_points=[CommandHandler("sendusers0", self.sendusers0_start)], + states={ + WAITING_FOR_USERS0_MESSAGE: [ + MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_users0_message) + ], + }, + fallbacks=[CommandHandler("cancel", self.cancel_users0_message)] + ) + + # Add conversation handlers application.add_handler(system_mes_conv) + application.add_handler(sendusers0_conv) # Add start command handler application.add_handler(CommandHandler("start", self.start))