From 6cb5a9b99f735cccfdf971c95678003062b23b18 Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Tue, 28 Oct 2025 21:34:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B2=D0=BE=D0=B9=D0=BD=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B0=20=D0=B8=20?= =?UTF-8?q?=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Исправлен баг с двойным ответом в /getgamers (добавлена обработка ошибок) - Добавлена автоматическая миграция токенов при инициализации БД - Исправлен веб-интерфейс - теперь берет токены из user_gamers - Улучшен start.sh - создает бэкап базы перед перезапуском - Добавлен export_db.sh для экспорта базы данных - start.sh безопасно обновляет проект и сохраняет все данные --- .gitignore | 3 ++ LichessClientTG_bot/bot.py | 23 ++++++++-- LichessClientTG_bot/database.py | 41 +++++++++++++++++ LichessClientTG_bot/migrate_tokens.py | 66 +++++++++++++++++++++++++++ LichessWebView/.gitignore | 3 ++ LichessWebView/app.py | 7 ++- LichessWebView/docker-compose.yml | 3 ++ LichessWebView/requirements.txt | 3 ++ LichessWebView/templates/index.html | 3 ++ README.md | 3 ++ docker-compose.yml | 9 ++-- export_db.sh | 20 ++++++++ start.sh | 13 +++++- 13 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 LichessClientTG_bot/migrate_tokens.py create mode 100644 export_db.sh diff --git a/.gitignore b/.gitignore index 5fa9852..535b3a0 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ npm-debug.log # Файлы кеша .cache/ + + + diff --git a/LichessClientTG_bot/bot.py b/LichessClientTG_bot/bot.py index 40f84b6..92be2d5 100644 --- a/LichessClientTG_bot/bot.py +++ b/LichessClientTG_bot/bot.py @@ -229,11 +229,24 @@ class LichessBot: reply_markup = InlineKeyboardMarkup(keyboard) # Edit the loading message with the results - await loading_msg.edit_text( - gamers_text, - parse_mode='HTML', - reply_markup=reply_markup - ) + try: + await loading_msg.edit_text( + gamers_text, + parse_mode='HTML', + reply_markup=reply_markup + ) + except Exception as e: + logger.error(f"Error editing message: {e}") + # If edit fails, delete the loading message and send a new one + try: + await loading_msg.delete() + except: + pass + await update.message.reply_text( + gamers_text, + parse_mode='HTML', + reply_markup=reply_markup + ) async def select_gamer(self, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle gamer selection""" diff --git a/LichessClientTG_bot/database.py b/LichessClientTG_bot/database.py index 32dc12a..d279ad8 100644 --- a/LichessClientTG_bot/database.py +++ b/LichessClientTG_bot/database.py @@ -60,8 +60,49 @@ class Database: pass conn.commit() + + # Migrate tokens from gamers to user_gamers if needed + self._migrate_tokens_from_gamers() + logger.info("Database initialized successfully") + def _migrate_tokens_from_gamers(self): + """Migrate tokens from old gamers table to user_gamers table if needed""" + with sqlite3.connect(self.db_path) as conn: + cursor = conn.cursor() + + # Check if there are tokens in gamers table that need migration + cursor.execute("SELECT COUNT(*) FROM gamers WHERE token IS NOT NULL") + gamers_with_tokens = cursor.fetchone()[0] + + if gamers_with_tokens == 0: + return # No tokens to migrate + + # Check if user_gamers already has tokens + cursor.execute("SELECT COUNT(*) FROM user_gamers WHERE token IS NOT NULL") + user_gamers_with_tokens = cursor.fetchone()[0] + + if user_gamers_with_tokens > 0: + return # Migration already done + + # Migrate tokens from gamers to user_gamers + cursor.execute("SELECT id, token FROM gamers WHERE token IS NOT NULL") + gamers_tokens = cursor.fetchall() + + migrated = 0 + for gamer_id, token in gamers_tokens: + # Update all user-gamer relationships for this gamer + cursor.execute( + "UPDATE user_gamers SET token = ? WHERE gamer_id = ? AND token IS NULL", + (token, gamer_id) + ) + migrated += cursor.rowcount + + conn.commit() + + if migrated > 0: + logger.info(f"Migrated {migrated} tokens from gamers to user_gamers") + def add_or_get_telegram_user(self, user_id: int, username: Optional[str] = None, first_name: Optional[str] = None, last_name: Optional[str] = None) -> bool: """Add or update Telegram user""" diff --git a/LichessClientTG_bot/migrate_tokens.py b/LichessClientTG_bot/migrate_tokens.py new file mode 100644 index 0000000..4f3a130 --- /dev/null +++ b/LichessClientTG_bot/migrate_tokens.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +""" +Миграция токенов из старой таблицы gamers в новую таблицу user_gamers +""" +import sqlite3 +import sys + +def migrate_tokens(): + """Migrate tokens from gamers table to user_gamers table""" + db_path = "/app/data/lichess_bot.db" + + try: + with sqlite3.connect(db_path) as conn: + cursor = conn.cursor() + + # Проверяем есть ли токены в gamers + cursor.execute("SELECT id, username, token FROM gamers WHERE token IS NOT NULL") + gamers_with_tokens = cursor.fetchall() + + if not gamers_with_tokens: + print("В базе нет токенов для миграции") + return + + print(f"Найдено {len(gamers_with_tokens)} игроков с токенами") + + migrated = 0 + for gamer_id, gamer_username, token in gamers_with_tokens: + # Находим всех пользователей, отслеживающих этого игрока + cursor.execute("SELECT user_id FROM user_gamers WHERE gamer_id = ?", (gamer_id,)) + users = cursor.fetchall() + + for (user_id,) in users: + # Проверяем есть ли уже токен у этого пользователя для этого игрока + cursor.execute( + "SELECT token FROM user_gamers WHERE user_id = ? AND gamer_id = ?", + (user_id, gamer_id) + ) + existing_token = cursor.fetchone() + + if existing_token and existing_token[0]: + # Токен уже есть, пропускаем + continue + + # Переносим токен + cursor.execute( + "UPDATE user_gamers SET token = ? WHERE user_id = ? AND gamer_id = ?", + (token, user_id, gamer_id) + ) + + cursor.execute("SELECT username FROM telegram_users WHERE user_id = ?", (user_id,)) + user_data = cursor.fetchone() + user_name = user_data[0] if user_data else f"ID:{user_id}" + + print(f" - Перенесен токен для {gamer_username} -> пользователю @{user_name}") + migrated += 1 + + conn.commit() + print(f"\n✅ Миграция завершена. Перенесено {migrated} токенов") + + except Exception as e: + print(f"❌ Ошибка при миграции: {e}") + sys.exit(1) + +if __name__ == "__main__": + migrate_tokens() + diff --git a/LichessWebView/.gitignore b/LichessWebView/.gitignore index feb6dc1..c38dc80 100644 --- a/LichessWebView/.gitignore +++ b/LichessWebView/.gitignore @@ -23,3 +23,6 @@ wheels/ *.egg .DS_Store + + + diff --git a/LichessWebView/app.py b/LichessWebView/app.py index 53c5b65..aa1e84d 100644 --- a/LichessWebView/app.py +++ b/LichessWebView/app.py @@ -77,7 +77,7 @@ def get_user_gamers(user_id): SELECT g.id, g.username, - g.token, + ug.token, ug.is_active, ug.period_minutes, ug.created_at @@ -94,7 +94,7 @@ def get_user_gamers(user_id): gamers.append({ 'id': row[0], 'username': row[1], - 'has_token': bool(row[2]), + 'has_token': bool(row[2]), # Token from user_gamers, not gamers 'is_active': bool(row[3]), 'period_minutes': row[4], 'created_at': row[5] @@ -114,3 +114,6 @@ def get_user_gamers(user_id): if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True) + + + diff --git a/LichessWebView/docker-compose.yml b/LichessWebView/docker-compose.yml index 6bd2503..7788539 100644 --- a/LichessWebView/docker-compose.yml +++ b/LichessWebView/docker-compose.yml @@ -10,3 +10,6 @@ services: environment: - FLASK_ENV=production + + + diff --git a/LichessWebView/requirements.txt b/LichessWebView/requirements.txt index 8c7ee03..f1fcb6f 100644 --- a/LichessWebView/requirements.txt +++ b/LichessWebView/requirements.txt @@ -1,3 +1,6 @@ Flask==3.0.0 flask-cors==4.0.0 + + + diff --git a/LichessWebView/templates/index.html b/LichessWebView/templates/index.html index 34a6d0e..030845b 100644 --- a/LichessWebView/templates/index.html +++ b/LichessWebView/templates/index.html @@ -438,3 +438,6 @@ + + + diff --git a/README.md b/README.md index 5964d50..c6aa972 100644 --- a/README.md +++ b/README.md @@ -238,3 +238,6 @@ Roman Vrubel - [Telegram Bot API](https://core.telegram.org/bots/api) - [FastAPI Documentation](https://fastapi.tiangolo.com/) + + + diff --git a/docker-compose.yml b/docker-compose.yml index a69c1ca..f2705cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: - PYTHONUNBUFFERED=1 volumes: - ./LichessWebServices:/app - restart: unless-stopped + restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s @@ -26,7 +26,7 @@ services: - PYTHONPATH=/app - PYTHONUNBUFFERED=1 network_mode: "host" - restart: unless-stopped + restart: always depends_on: - lichess-api healthcheck: @@ -44,7 +44,7 @@ services: - "5000:5000" volumes: - ./LichessClientTG_bot/data:/app/data:ro - restart: unless-stopped + restart: always depends_on: - lichess-bot @@ -52,3 +52,6 @@ networks: default: name: lichess-network + + + diff --git a/export_db.sh b/export_db.sh new file mode 100644 index 0000000..5dd0da7 --- /dev/null +++ b/export_db.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +echo "📤 Экспорт базы данных..." + +if [ ! -f "LichessClientTG_bot/data/lichess_bot.db" ]; then + echo "❌ База данных не найдена!" + exit 1 +fi + +mkdir -p backups +timestamp=$(date +%Y%m%d_%H%M%S) + +# Экспортируем базу +cp LichessClientTG_bot/data/lichess_bot.db "backups/export_lichess_bot_${timestamp}.db" + +echo "✅ База данных экспортирована: backups/export_lichess_bot_${timestamp}.db" +echo "" +echo "Для импорта на другом компьютере используйте:" +echo " cp backups/export_lichess_bot_${timestamp}.db LichessClientTG_bot/data/lichess_bot.db" + diff --git a/start.sh b/start.sh index c69db42..f7257c8 100755 --- a/start.sh +++ b/start.sh @@ -14,10 +14,18 @@ if ! command -v docker-compose &> /dev/null; then exit 1 fi -# Останавливаем существующие контейнеры +# Останавливаем существующие контейнеры (без удаления volumes для сохранения данных) echo "🛑 Остановка существующих контейнеров..." docker-compose down +# Бэкап базы данных (на всякий случай) +echo "💾 Создание резервной копии базы данных..." +if [ -d "LichessClientTG_bot/data" ]; then + mkdir -p backups + cp -f LichessClientTG_bot/data/lichess_bot.db backups/lichess_bot_$(date +%Y%m%d_%H%M%S).db 2>/dev/null || true + echo "✅ Бэкап создан" +fi + # Пересобираем образы echo "🔨 Пересборка Docker образов..." docker-compose build @@ -48,3 +56,6 @@ echo "" echo "🛑 Для остановки используйте:" echo " docker-compose down" + + +