diff --git a/LichessClientTG_bot/bot.py b/LichessClientTG_bot/bot.py index 694c193..88d1b93 100644 --- a/LichessClientTG_bot/bot.py +++ b/LichessClientTG_bot/bot.py @@ -1,8 +1,10 @@ import asyncio import logging import sqlite3 +import os from datetime import datetime, timedelta from typing import Dict, Any, Optional +from pathlib import Path from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import ( @@ -286,32 +288,153 @@ class LichessBot: pass async def addgamer_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): - """Start addgamer command - simple username only""" + """Start addgamer command - show menu with options""" user_id = update.effective_user.id logger.info(f"addgamer_start called for user {user_id}") - # Check if we're already awaiting a username (prevent duplicate messages) - if context and hasattr(context, "user_data") and context.user_data.get('awaiting_addgamer_username'): - logger.info(f"addgamer_start: Already awaiting username for user {user_id}, skipping duplicate call") - return - lang = self.get_user_language_from_update(update) try: - # Mark that we are awaiting a username reply - if context and hasattr(context, "user_data"): - context.user_data['awaiting_addgamer_username'] = True - await update.message.reply_text(t('addgamer_prompt', lang), parse_mode='HTML') - logger.info(f"Addgamer prompt sent to user {user_id}") - self.counters.increment('addgamer') + keyboard = [ + [ + InlineKeyboardButton( + text=t('addgamer_btn_add', lang), + callback_data="addgamer_add" + ) + ], + [ + InlineKeyboardButton( + text=t('addgamer_btn_how', lang), + callback_data="addgamer_how" + ) + ], + ] + reply_markup = InlineKeyboardMarkup(keyboard) + await update.message.reply_text( + t('addgamer_menu', lang), + reply_markup=reply_markup + ) + logger.info(f"Addgamer menu sent to user {user_id}") except Exception as e: - logger.error(f"Error sending addgamer prompt: {e}") + logger.error(f"Error sending addgamer menu: {e}") import traceback logger.error(traceback.format_exc()) - # Clear flag on error - if context and hasattr(context, "user_data"): - context.user_data['awaiting_addgamer_username'] = False # No conversation state returned; handler-based flow return + + async def addgamer_show_prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Callback: show username prompt after user presses 'Add player'""" + query = update.callback_query + await query.answer() + + user_id = query.from_user.id + logger.info(f"addgamer_show_prompt called for user {user_id}") + + # Clear previous state and mark that we're waiting for username + if context and hasattr(context, "user_data"): + context.user_data.clear() + context.user_data['awaiting_addgamer_username'] = True + + # Language from DB (for callbacks) + if update.effective_user: + self.db.add_or_get_telegram_user( + user_id=update.effective_user.id, + username=update.effective_user.username, + first_name=update.effective_user.first_name, + last_name=update.effective_user.last_name, + language_code=update.effective_user.language_code + ) + lang = self.db.get_user_language(user_id) + + await query.message.reply_text( + t('addgamer_prompt', lang), + parse_mode='HTML' + ) + logger.info(f"Addgamer prompt (from button) sent to user {user_id}") + # Count real start of username input flow + self.counters.increment('addgamer') + + async def addgamer_show_help(self, update: Update, context: ContextTypes.DEFAULT_TYPE): + """Callback: show how to find username on Lichess (with images)""" + query = update.callback_query + if not query or not query.message: + logger.error("addgamer_show_help: Invalid query or message") + return + + await query.answer() + + user_id = query.from_user.id + logger.info(f"addgamer_show_help called for user {user_id}") + + # Language from DB (for callbacks) + if update.effective_user: + self.db.add_or_get_telegram_user( + user_id=update.effective_user.id, + username=update.effective_user.username, + first_name=update.effective_user.first_name, + last_name=update.effective_user.last_name, + language_code=update.effective_user.language_code + ) + lang = self.db.get_user_language(user_id) + + # Определяем имя файла картинки в зависимости от языка + # Для русской локализации - helpRU.jpeg, для английской - helpEN.jpeg + image_filename = "helpRU.jpeg" if lang == 'ru' else "helpEN.jpeg" + + # Определяем путь к картинке (она находится в той же папке, что и bot.py) + bot_dir = Path(__file__).resolve().parent + image_path = bot_dir / image_filename + + # Пробуем альтернативные пути, если основной не найден + possible_paths = [ + image_path, # В папке бота + bot_dir.parent / image_filename, # В корне проекта + Path("/home/vrubel/PROJECTS/LichessStatTgWeb/LichessClientTG_bot") / image_filename, # Абсолютный путь + ] + + # Ищем существующий файл + found_path = None + for candidate in possible_paths: + if candidate and candidate.exists(): + found_path = candidate + logger.info(f"✅ Found {image_filename} at: {found_path}") + break + + if not found_path or not found_path.exists(): + error_msg = f"❌ Error: Could not find {image_filename}\n\nChecked paths:\n" + for path in possible_paths: + exists = path.exists() if path else False + error_msg += f" • {path} (exists: {exists})\n" + logger.error(error_msg) + await query.message.reply_text(f"❌ Error: Could not find image file. Please check bot logs.") + return + + try: + logger.info(f"Sending help image: {found_path} (language: {lang})") + with open(found_path, "rb") as img: + await query.message.reply_photo(photo=img) + + logger.info(f"Successfully sent help image to user {user_id}") + + # Устанавливаем флаг ожидания username, чтобы пользователь мог ввести его после просмотра картинки + if context and hasattr(context, "user_data"): + context.user_data['awaiting_addgamer_username'] = True + + # Отправляем текст с запросом username + await query.message.reply_text( + t('addgamer_prompt', lang), + parse_mode='HTML' + ) + + # Считаем это началом процесса добавления игрока + self.counters.increment('addgamer') + except Exception as e: + logger.error(f"Error sending lichess help images: {e}") + import traceback + logger.error(traceback.format_exc()) + try: + await query.message.reply_text(f"❌ Error sending images: {e}") + except Exception as e2: + logger.error(f"Failed to send error message: {e2}") async def addtoken_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): """Start addtoken command - token required""" @@ -1561,6 +1684,8 @@ class LichessBot: application.add_handler(CommandHandler("test_admin_notify", self.test_admin_notify)) # Callback handlers (order matters - more specific patterns first) + application.add_handler(CallbackQueryHandler(self.addgamer_show_prompt, pattern="^addgamer_add$")) + application.add_handler(CallbackQueryHandler(self.addgamer_show_help, pattern="^addgamer_how$")) application.add_handler(CallbackQueryHandler(self.handle_language_selection, pattern="^lang_")) application.add_handler(CallbackQueryHandler(self.handle_profile_selection, pattern="^profile_")) application.add_handler(CallbackQueryHandler(self.select_gamer_for_period, pattern="^select_gamer_period_")) diff --git a/LichessClientTG_bot/helpEN.jpeg b/LichessClientTG_bot/helpEN.jpeg new file mode 100644 index 0000000..5c44042 Binary files /dev/null and b/LichessClientTG_bot/helpEN.jpeg differ diff --git a/LichessClientTG_bot/helpRU.jpeg b/LichessClientTG_bot/helpRU.jpeg new file mode 100644 index 0000000..b6fe6fa Binary files /dev/null and b/LichessClientTG_bot/helpRU.jpeg differ diff --git a/LichessClientTG_bot/i18n.py b/LichessClientTG_bot/i18n.py index 3efa474..f71b96e 100644 --- a/LichessClientTG_bot/i18n.py +++ b/LichessClientTG_bot/i18n.py @@ -45,7 +45,18 @@ TRANSLATIONS = { ), # Add gamer commands + 'addgamer_menu': ( + "➕ Add a player to track.\n\n" + "Choose an option:" + ), + 'addgamer_btn_add': "➕ Add player", + 'addgamer_btn_how': "❓ How to add a player?", 'addgamer_prompt': "👤 Enter the Lichess username of the player to track:", + 'addgamer_after_help': ( + "Now send the Lichess username of the player you want to track.\n\n" + "Example: MagnusCarlsen\n\n" + "This is the name from the link: https://lichess.org/@/username" + ), 'addtoken_prompt': ( "🔑 Enter the Lichess API token to get puzzle data.\n" "The token is created in profile settings — give it only puzzle:read permission.\n" @@ -169,7 +180,18 @@ TRANSLATIONS = { ), # Add gamer commands + 'addgamer_menu': ( + "➕ Добавление игрока для отслеживания.\n\n" + "Выберите, что сделать:" + ), + 'addgamer_btn_add': "➕ Добавить игрока", + 'addgamer_btn_how': "❓ Как добавить игрока?", 'addgamer_prompt': "👤 Введите username игрока Lichess для отслеживания:", + 'addgamer_after_help': ( + "Теперь отправьте username игрока Lichess, которого хотите отслеживать.\n\n" + "Пример: MagnusCarlsen\n\n" + "Это имя из ссылки: https://lichess.org/@/username" + ), 'addtoken_prompt': ( "🔑 Введите токен API Lichess для получения данных по пазлам.\n" "Токен создается в настройках профиля — дайте ему только разрешение puzzle:read.\n"