bug today

This commit is contained in:
vrubelroman 2025-11-20 03:14:06 +03:00
parent faf6ec0c35
commit 4dc5539da2
5 changed files with 189 additions and 38 deletions

View file

@ -732,8 +732,11 @@ class LichessBot:
"""Get statistics for a period - shows stats for all players with activity""" """Get statistics for a period - shows stats for all players with activity"""
user_id = update.effective_user.id user_id = update.effective_user.id
logger.info(f"🔍 get_stats called: user_id={user_id}, period={period}")
# Get all gamers for this user # Get all gamers for this user
gamers = self.db.get_user_gamers(user_id) gamers = self.db.get_user_gamers(user_id)
logger.info(f"🔍 Found {len(gamers)} gamers for user {user_id}: {[g['username'] for g in gamers]}")
lang = self.get_user_language_from_update(update) lang = self.get_user_language_from_update(update)
if not gamers: if not gamers:
@ -752,6 +755,7 @@ class LichessBot:
has_any_activity = False has_any_activity = False
for i, gamer in enumerate(gamers): for i, gamer in enumerate(gamers):
username = gamer['username'] username = gamer['username']
logger.info(f"🔍 Processing gamer {i+1}/{len(gamers)}: {username} for period {period}")
# Send message about processing this player # Send message about processing this player
processing_msg = None processing_msg = None
@ -761,6 +765,8 @@ class LichessBot:
pass pass
# Get stats based on period # Get stats based on period
try:
logger.info(f"🔍 Making API request for {username}, period={period}")
if period == "today": if period == "today":
data = await self.lichess_api.get_today_stats(username) data = await self.lichess_api.get_today_stats(username)
elif period == "yesterday": elif period == "yesterday":
@ -771,6 +777,17 @@ class LichessBot:
await update.message.reply_text(t('unknown_period', lang)) await update.message.reply_text(t('unknown_period', lang))
return return
logger.info(f"🔍 API response for {username}: data={data is not None}, type={type(data)}")
if data:
logger.info(f"🔍 API response keys: {data.keys() if isinstance(data, dict) else 'not a dict'}")
if isinstance(data, dict) and 'message' in data:
logger.info(f"🔍 API message: {data.get('message')}")
except Exception as e:
logger.error(f"❌ Error getting stats for {username}: {e}")
import traceback
logger.error(traceback.format_exc())
data = None
# Delete processing message # Delete processing message
if processing_msg: if processing_msg:
try: try:
@ -780,27 +797,40 @@ class LichessBot:
# Check if there's activity # Check if there's activity
has_activity = False has_activity = False
if data and data.get('data'): if data:
if data.get('data'):
api_data = data.get('data', {}) api_data = data.get('data', {})
tasks = api_data.get('tasks', {}) tasks = api_data.get('tasks', {})
games = api_data.get('games', {}) games = api_data.get('games', {})
logger.info(f"🔍 Activity check for {username}: tasks={tasks}, games={games}")
# Check for puzzles activity # Check for puzzles activity
if tasks and tasks.get('total', 0) > 0: if tasks and tasks.get('total', 0) > 0:
has_activity = True has_activity = True
logger.info(f"{username} has puzzles activity: {tasks.get('total')}")
# Check for games activity # Check for games activity
if games: if games:
for game_type, game_data in games.items(): for game_type, game_data in games.items():
if game_data and game_data.get('games_played', 0) > 0: if game_data and game_data.get('games_played', 0) > 0:
has_activity = True has_activity = True
logger.info(f"{username} has {game_type} activity: {game_data.get('games_played')} games")
break break
else:
# API вернул ответ, но без данных (нет активности)
message = data.get('message', 'No message')
logger.info(f" API response for {username}: {message} (no activity data)")
else:
logger.warning(f"⚠️ No response data for {username}: data is None")
# Only send response if there's activity # Only send response if there's activity
if has_activity: if has_activity:
formatted_response = StatsFormatter.format_stats_response(data, username, period, lang) formatted_response = StatsFormatter.format_stats_response(data, username, period, lang)
await update.message.reply_text(formatted_response) await update.message.reply_text(formatted_response)
has_any_activity = True has_any_activity = True
else:
logger.info(f" No activity found for {username}, skipping response")
# Add delay between requests to avoid rate limiting # Add delay between requests to avoid rate limiting
if i < len(gamers) - 1: if i < len(gamers) - 1:

View file

@ -37,19 +37,31 @@ class LichessAPI:
async def get_today_stats(self, username: str) -> Optional[Dict[str, Any]]: async def get_today_stats(self, username: str) -> Optional[Dict[str, Any]]:
"""Get today's statistics from our stats API""" """Get today's statistics from our stats API"""
logger.info(f"🔍 LichessAPI.get_today_stats: username={username}, stats_base_url={self.stats_base_url}")
await self.rate_limiter.wait_if_needed() await self.rate_limiter.wait_if_needed()
url = f"{self.stats_base_url}/stats/{username}/today"
logger.info(f"🔍 Making request to: {url}")
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.get( async with session.get(url) as response:
f"{self.stats_base_url}/stats/{username}/today" logger.info(f"🔍 Response status: {response.status} for {username}")
) as response:
if response.status == 200: if response.status == 200:
return await response.json() result = await response.json()
logger.info(f"🔍 Successfully got stats for {username}: {result.get('message', 'no message')}")
return result
else: else:
logger.error(f"Failed to get today stats: {response.status}") error_text = await response.text()
logger.error(f"❌ Failed to get today stats for {username}: status={response.status}, error={error_text[:200]}")
return None
except aiohttp.ClientError as e:
logger.error(f"❌ Client error getting today stats for {username}: {e}")
import traceback
logger.error(traceback.format_exc())
return None return None
except Exception as e: except Exception as e:
logger.error(f"Error getting today stats: {e}") logger.error(f"❌ Error getting today stats for {username}: {e}")
import traceback
logger.error(traceback.format_exc())
return None return None
async def get_yesterday_stats(self, username: str) -> Optional[Dict[str, Any]]: async def get_yesterday_stats(self, username: str) -> Optional[Dict[str, Any]]:

View file

@ -59,33 +59,39 @@ class LichessClient:
httpx.HTTPStatusError: При ошибках HTTP (кроме 404) httpx.HTTPStatusError: При ошибках HTTP (кроме 404)
Exception: При других ошибках Exception: При других ошибках
""" """
logger.info(f"🔍 LichessClient.get_user_activity: username={username}")
try: try:
# Rate limiting: ждем если нужно # Rate limiting: ждем если нужно
await self.rate_limiter.wait_if_needed() await self.rate_limiter.wait_if_needed()
# Формируем URL для получения активности пользователя # Формируем URL для получения активности пользователя
url = f"{self.base_url}/user/{username}/activity" url = f"{self.base_url}/user/{username}/activity"
logger.info(f"Запрос активности пользователя {username}") logger.info(f"🔍 Making request to Lichess API: {url}")
# Выполняем HTTP GET запрос # Выполняем HTTP GET запрос
response = await self.client.get(url) response = await self.client.get(url)
logger.info(f"🔍 Lichess API response status: {response.status_code} for {username}")
response.raise_for_status() # Проверяем статус ответа response.raise_for_status() # Проверяем статус ответа
# Возвращаем JSON данные # Возвращаем JSON данные
return response.json() result = response.json()
logger.info(f"🔍 Received activity data for {username}: {len(result) if isinstance(result, list) else 'not a list'} items")
return result
except httpx.HTTPStatusError as e: except httpx.HTTPStatusError as e:
if e.response.status_code == 404: if e.response.status_code == 404:
# Пользователь не найден - это нормальная ситуация # Пользователь не найден - это нормальная ситуация
logger.warning(f"Пользователь {username} не найден") logger.warning(f"⚠️ Пользователь {username} не найден (404)")
return None return None
else: else:
# Другие HTTP ошибки - логируем и пробрасываем # Другие HTTP ошибки - логируем и пробрасываем
logger.error(f"HTTP ошибка при получении активности пользователя {username}: {e}") logger.error(f"HTTP ошибка при получении активности пользователя {username}: status={e.response.status_code}, error={e}")
raise raise
except Exception as e: except Exception as e:
# Обрабатываем все остальные ошибки # Обрабатываем все остальные ошибки
logger.error(f"Ошибка при получении активности пользователя {username}: {e}") logger.error(f"❌ Ошибка при получении активности пользователя {username}: {e}")
import traceback
logger.error(traceback.format_exc())
raise raise
async def get_games_of_period(self, username: str, since_ms: int, until_ms: int, rated_only: bool = True) -> Optional[List[Dict[str, Any]]]: async def get_games_of_period(self, username: str, since_ms: int, until_ms: int, rated_only: bool = True) -> Optional[List[Dict[str, Any]]]:

View file

@ -213,29 +213,49 @@ class StatsService:
Returns: Returns:
ActivityResponse с данными статистики или сообщением об ошибке ActivityResponse с данными статистики или сообщением об ошибке
""" """
logger.info(f"🔍 StatsService.get_today_stats: username={username}")
try: try:
logger.info(f"🔍 Calling lichess_client.get_user_activity for {username}")
activity_data = await self.lichess_client.get_user_activity(username) activity_data = await self.lichess_client.get_user_activity(username)
logger.info(f"🔍 Activity data received: {activity_data is not None}, type={type(activity_data)}")
if not activity_data: if not activity_data:
logger.warning(f"⚠️ No activity data for {username}")
return ActivityResponse( return ActivityResponse(
message=f"Пользователь {username} не найден или неактивен" message=f"Пользователь {username} не найден или неактивен"
) )
logger.info(f"🔍 Activity data length: {len(activity_data) if isinstance(activity_data, list) else 'not a list'}")
today = date.today() today = date.today()
logger.info(f"🔍 Looking for activity for today: {today}")
# Ищем активность за сегодня # Ищем активность за сегодня
# Lichess возвращает интервалы, которые могут начинаться вчера, но включать активность сегодня
today_activity = None today_activity = None
for activity in activity_data: for activity in activity_data:
activity_date = self._parse_lichess_interval(activity['interval']) interval = activity['interval']
if activity_date == today: # Парсим начало и конец интервала
start_timestamp = interval['start'] / 1000
end_timestamp = interval['end'] / 1000
start_date = datetime.fromtimestamp(start_timestamp).date()
end_date = datetime.fromtimestamp(end_timestamp).date()
logger.debug(f"🔍 Checking activity interval: {start_date} to {end_date} vs today: {today}")
# Проверяем, попадает ли сегодняшняя дата в интервал
if start_date <= today <= end_date:
today_activity = activity today_activity = activity
logger.info(f"✅ Found today activity for {username} (interval: {start_date} to {end_date})")
break break
if not today_activity: if not today_activity:
logger.info(f" No activity found for today ({today}) for {username}")
return ActivityResponse( return ActivityResponse(
message=f"Активности за сегодняшний день ({today}) не было" message=f"Активности за сегодняшний день ({today}) не было"
) )
# Обрабатываем данные # Обрабатываем данные
logger.info(f"🔍 Processing activity data for {username}")
games_stats = self._process_games_by_mode(today_activity.get('games', {})) games_stats = self._process_games_by_mode(today_activity.get('games', {}))
tasks_stats = self._process_tasks(today_activity.get('puzzles', {})) tasks_stats = self._process_tasks(today_activity.get('puzzles', {}))
@ -245,13 +265,16 @@ class StatsService:
games=GamesStats(**games_stats) games=GamesStats(**games_stats)
) )
logger.info(f"✅ Successfully processed stats for {username}")
return ActivityResponse( return ActivityResponse(
message="Статистика за сегодняшний день", message="Статистика за сегодняшний день",
data=user_stats data=user_stats
) )
except Exception as e: except Exception as e:
logger.error(f"Ошибка при получении статистики за сегодня: {e}") logger.error(f"❌ Ошибка при получении статистики за сегодня для {username}: {e}")
import traceback
logger.error(traceback.format_exc())
return ActivityResponse( return ActivityResponse(
message=f"Ошибка при получении статистики: {str(e)}" message=f"Ошибка при получении статистики: {str(e)}"
) )

80
test_kostik2811.py Executable file
View file

@ -0,0 +1,80 @@
#!/usr/bin/env python3
"""
Скрипт для тестирования запросов к Lichess API для пользователя kostik2811
"""
import asyncio
import sys
import os
# Добавляем пути к модулям
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'LichessWebServices'))
from lichess_client import LichessClient
from stats_service import StatsService
import logging
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
async def test_kostik2811():
"""Тестирование запросов для kostik2811"""
username = "kostik2811"
logger.info(f"🔍 Тестирование запросов для пользователя: {username}")
# Тест 1: Прямой запрос к Lichess API
logger.info("\n" + "="*50)
logger.info("ТЕСТ 1: Прямой запрос к Lichess API")
logger.info("="*50)
lichess_client = LichessClient()
try:
activity_data = await lichess_client.get_user_activity(username)
if activity_data:
logger.info(f"✅ Получены данные активности: {len(activity_data)} записей")
for i, activity in enumerate(activity_data[:3]): # Показываем первые 3
logger.info(f" Активность {i+1}: {activity.get('interval', 'N/A')}")
else:
logger.warning(f"⚠️ Данные активности не получены (None или пусто)")
except Exception as e:
logger.error(f"❌ Ошибка при запросе к Lichess API: {e}")
import traceback
logger.error(traceback.format_exc())
finally:
await lichess_client.close()
# Тест 2: Запрос через StatsService
logger.info("\n" + "="*50)
logger.info("ТЕСТ 2: Запрос через StatsService.get_today_stats")
logger.info("="*50)
lichess_client2 = LichessClient()
stats_service = StatsService(lichess_client2)
try:
result = await stats_service.get_today_stats(username)
logger.info(f"✅ Результат StatsService: message={result.message}")
if result.data:
logger.info(f" Данные: username={result.data.username}")
logger.info(f" Задачи: {result.data.tasks}")
logger.info(f" Игры: {result.data.games}")
else:
logger.warning(f"⚠️ Нет данных в результате")
except Exception as e:
logger.error(f"❌ Ошибка в StatsService: {e}")
import traceback
logger.error(traceback.format_exc())
finally:
await lichess_client2.close()
logger.info("\n" + "="*50)
logger.info("Тестирование завершено")
logger.info("="*50)
if __name__ == "__main__":
asyncio.run(test_kostik2811())