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"