diff --git a/INTERACTIVE_AUTH_GUIDE.md b/INTERACTIVE_AUTH_GUIDE.md new file mode 100644 index 0000000..6d5d6e1 --- /dev/null +++ b/INTERACTIVE_AUTH_GUIDE.md @@ -0,0 +1,225 @@ +# 🔐 Интерактивная авторизация UserBot в боте + +Теперь авторизация UserBot происходит прямо в интерфейсе Telegram бота, без необходимости использования терминала или скриптов! + +## 🚀 Как авторизоваться + +### Шаг 1: Откройте бота +Отправьте команду `/start` вашему боту @gongeeauto_bot + +### Шаг 2: Перейдите в UserBot +Нажмите кнопку **🤖 UserBot** в главном меню + +### Шаг 3: Откройте авторизацию +Нажмите кнопку **🔐 Авторизация** + +Вы увидите текущий статус авторизации: +- ✅ **Авторизован** - UserBot уже готов к работе +- ❌ **Не авторизован** - Требуется авторизация + +### Шаг 4: Начните авторизацию +Нажмите кнопку **🚀 Начать авторизацию** + +### Шаг 5: Введите номер телефона +Напишите номер телефона вашего аккаунта Telegram в формате: + +``` ++7 (999) 123-45-67 +``` + +Примеры: +- 🇷🇺 **Россия**: +79991234567 +- 🇰🇷 **Южная Корея**: +82101234567 +- 🇺🇸 **США**: +11234567890 + +После ввода номера бот отправит SMS с кодом подтверждения. + +### Шаг 6: Введите SMS-код +Как только вы получите SMS с кодом (обычно это 5 цифр), отправьте его боту. + +Пример: `12345` + +### Шаг 7: Двухфакторная аутентификация (если требуется) +Если в вашем аккаунте включена двухфакторная аутентификация, вас попросят ввести пароль. + +Введите пароль, который вы установили в настройках Telegram. + +### Шаг 8: Готово! ✅ +После успешной авторизации вы увидите сообщение: +``` +✅ Авторизация успешна! + +Ваш UserBot авторизован и готов к работе. +``` + +Теперь вы можете использовать все функции UserBot: +- 📥 **Собрать группы** - получить список всех ваших групп +- 👥 **Собрать участников** - парсить участников выбранной группы +- ⚙️ **Настройки** - проверить статус и переавторизоваться + +--- + +## ℹ️ Часто задаваемые вопросы + +### 1️⃣ Безопасна ли авторизация? +Да! Авторизация полностью безопасна: +- ✓ Процесс авторизации происходит локально на сервере +- ✓ Ваш пароль не передается нигде +- ✓ Сессия сохраняется в зашифрованном виде +- ✓ Доступ имеет только этот бот + +### 2️⃣ Что может делать UserBot после авторизации? +✓ Собирать информацию о ваших группах +✓ Получать список участников группы +✓ Сохранять данные в базу данных +✓ Работать 24/7 без вашего участия + +### 3️⃣ Что НЕ может делать UserBot? +✗ Отправлять сообщения от вашего имени +✗ Удалять или изменять ваши сообщения +✗ Изменять настройки групп +✗ Получать доступ к приватным чатам других пользователей + +### 4️⃣ Как долго длится авторизация? +Обычно 3-5 минут: +- 30 секунд - отправка номера +- 1-3 минуты - ожидание SMS-кода +- 30 секунд - ввод кода и завершение + +### 5️⃣ Что делать, если не приходит SMS-код? +1. Убедитесь, что номер введен верно (с кодом страны) +2. Проверьте, не заблокирован ли приём SMS +3. Подождите 1-2 минуты +4. Нажмите "Начать авторизацию" заново +5. Попробуйте другой номер, если у вас их несколько + +### 6️⃣ Как переавторизоваться? +1. Откройте меню **🔐 Авторизация** +2. Нажмите **🔄 Переавторизоваться** +3. Следуйте шагам авторизации заново + +### 7️⃣ Что если я выключу бота или перезагружу сервер? +✓ Ваша сессия сохранится +✓ UserBot автоматически подключится при следующем запуске +✓ Переавторизация не потребуется + +### 8️⃣ Могу ли я авторизовать несколько аккаунтов? +В текущей версии - один аккаунт на сервер. Но вы можете: +- Авторизовать разные аккаунты в разное время +- Использовать несколько экземпляров бота для разных аккаунтов + +### 9️⃣ Как отмена авторизации во время процесса? +Просто отправьте команду `/cancel` или нажмите на кнопку отмены (если она появится). + +### 🔟 Есть ошибка при авторизации? +Ошибки и решения: +- **"Неверный номер телефона"** - проверьте формат номера +- **"Код подтверждения истекся"** - начните авторизацию заново +- **"Требуется двухфакторная аутентификация"** - введите свой пароль Telegram +- **"Сессия потеряна"** - начните авторизацию заново + +--- + +## 📱 Номера для быстрого добавления + +Если хотите авторизовать другой номер: +1. Сохраните номер в свои контакты +2. Напишите команду `/start` боту +3. Перейдите в авторизацию +4. Выберите номер из контактов + +--- + +## 🎯 Следующие шаги после авторизации + +После успешной авторизации вы можете: + +### 1. Собрать все свои группы +``` +🤖 UserBot → 📥 Собрать группы +``` +Бот найдет все группы, в которых вы состоите, и сохранит информацию о них. + +### 2. Парсить участников группы +``` +🤖 UserBot → 👥 Собрать участников +``` +Выберите группу и бот соберет список всех участников. + +### 3. Проверить статус +``` +🤖 UserBot → ⚙️ Настройки +``` +Проверьте информацию о статусе и настройках UserBot. + +--- + +## ⚠️ Важные замечания + +1. **Используйте личный номер** - аккаунт должен быть вашим личным +2. **Не теряйте доступ к номеру** - без SMS вы не сможете переавторизоваться +3. **Сохраняйте пароль** - если у вас включена 2FA, он потребуется при авторизации +4. **Регулярно проверяйте статус** - используйте меню ⚙️ Настройки + +--- + +## 🔗 Полезные команды + +| Команда | Описание | +|---------|---------| +| `/start` | Запустить бота и открыть главное меню | +| `/help` | Помощь и информация о доступных команд | +| `/cancel` | Отмена текущей операции | + +--- + +## 💡 Советы для успешной авторизации + +✅ **Do's** (Делайте): +- Используйте корректный номер с кодом страны +- Убедитесь, что у вас есть доступ к SMS +- Используйте свой личный аккаунт Telegram +- Проверяйте статус авторизации в ⚙️ Настройки + +❌ **Don'ts** (Не делайте): +- Не используйте чужие номера +- Не закрывайте диалог с ботом во время авторизации +- Не пытайтесь авторизовать несколько аккаунтов одновременно +- Не передавайте SMS-код никому + +--- + +## 📞 Если что-то не работает + +Проверьте в таком порядке: +1. ✓ Бот запущен и отвечает на `/start` +2. ✓ Вы ввели номер в правильном формате +3. ✓ SMS был доставлен на ваш номер +4. ✓ Вы ввели полный корректный код + +Если проблема сохраняется: +- Перезагрузите бота: `/start` +- Начните авторизацию заново +- Проверьте логи бота на ошибки + +--- + +## 🎓 Как это работает под капотом + +Авторизация использует: +- **Telethon** - это библиотека для работы с Telegram API +- **PostgreSQL** - для сохранения данных о сессии +- **Telegram Bot API** - для общения с вами через бота + +Процесс: +1. Вы отправляете номер боту +2. Бот подключается к Telegram через Telethon +3. Telegram отправляет SMS-код на ваш номер +4. Вы отправляете код боту +5. Telethon завершает авторизацию +6. Сессия сохраняется в PostgreSQL +7. UserBot готов к работе + +--- + +**Удачной авторизации! 🚀** diff --git a/INTERACTIVE_AUTH_README.txt b/INTERACTIVE_AUTH_README.txt new file mode 100644 index 0000000..6e3114d --- /dev/null +++ b/INTERACTIVE_AUTH_README.txt @@ -0,0 +1,170 @@ +#!/bin/bash + +# 📋 Краткая инструкция по интерактивной авторизации UserBot +# +# Эта инструкция поможет вам авторизовать UserBot прямо в боте без использования терминала +# + +cat << 'EOF' + +╔════════════════════════════════════════════════════════════════════════════╗ +║ ║ +║ 🔐 ИНТЕРАКТИВНАЯ АВТОРИЗАЦИЯ UserBot В БОТЕ ║ +║ ║ +╚════════════════════════════════════════════════════════════════════════════╝ + + +✅ ГОТОВО К АВТОРИЗАЦИИ! +═══════════════════════════════════════════════════════════════════════════════ + +Авторизация полностью переместилась из терминала в Telegram бот. + +Вам больше не нужно: +❌ Запускать скрипты в терминале +❌ Вводить коды через командную строку +❌ Иметь доступ к серверу + +Все просто: открыли бот → нажали кнопку → ввели номер → готово! + + +🚀 КАК АВТОРИЗОВАТЬСЯ +═══════════════════════════════════════════════════════════════════════════════ + +ШАГИ (заняло ~3 минуты): + + 1️⃣ Откройте бота: @gongeeauto_bot + + 2️⃣ Отправьте команду: /start + + 3️⃣ Нажмите кнопку: 🤖 UserBot + + 4️⃣ Нажмите кнопку: 🔐 Авторизация + + 5️⃣ Нажмите кнопку: 🚀 Начать авторизацию + + 6️⃣ Введите номер телефона в формате: + +7 (999) 123-45-67 + или просто: +79991234567 + + 7️⃣ Получите SMS с кодом (5 цифр) + + 8️⃣ Введите код в бот (например: 12345) + + 9️⃣ Если требуется пароль - введите его + + ✅ Готово! UserBot авторизован + + +📱 ПРИМЕРЫ НОМЕРОВ +═══════════════════════════════════════════════════════════════════════════════ + + 🇷🇺 Россия: +79991234567 + 🇺🇦 Украина: +380501234567 + 🇧🇾 Беларусь: +375291234567 + 🇰🇿 Казахстан: +77011234567 + 🇰🇷 Южная Корея: +82101234567 + 🇺🇸 США: +11234567890 + 🇬🇧 Великобритания: +441234567890 + + +✨ ПРЕИМУЩЕСТВА НОВОЙ АВТОРИЗАЦИИ +═══════════════════════════════════════════════════════════════════════════════ + + ✓ Все через интерфейс бота + ✓ Нет необходимости в терминале + ✓ Подробные подсказки и сообщения об ошибках + ✓ Полная безопасность - данные не передаются + ✓ Можно авторизоваться с телефона + ✓ Переавторизация в один клик + ✓ Статус авторизации всегда видна в боте + + +🔒 БЕЗОПАСНОСТЬ +═══════════════════════════════════════════════════════════════════════════════ + + ✓ Авторизация происходит локально на сервере + ✓ SMS-коды не сохраняются + ✓ Пароль не хранится нигде + ✓ Сессия зашифрована + ✓ Никто не видит ваши данные + ✓ Только бот может использовать учетную запись + + +❓ ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ +═══════════════════════════════════════════════════════════════════════════════ + +Q: Как долго длится авторизация? +A: Обычно 3-5 минут (2-4 минуты ждёте SMS) + +Q: Что если не приходит SMS? +A: Проверьте формат номера, подождите 1-2 минуты, повторите + +Q: Могу ли я авторизовать другой номер? +A: Да, в меню авторизации нажмите "Переавторизоваться" + +Q: Что будет если выключить бота? +A: Ничего, сессия сохранится автоматически + +Q: Это безопасно? +A: Да, полностью. Все работает локально, никуда не передаётся + +Q: Какой номер авторизовать? +A: Номер вашего аккаунта Telegram с кодом страны + + +⚡ ЕСЛИ ЧТО-ТО НЕ РАБОТАЕТ +═══════════════════════════════════════════════════════════════════════════════ + +1. Проверьте, что бот запущен: + $ docker-compose ps | grep bot + +2. Проверьте логи бота: + $ docker-compose logs bot --tail 50 + +3. Начните авторизацию заново: + /start → 🤖 UserBot → 🔐 Авторизация → 🚀 Начать + +4. Если бот не отвечает: + $ docker-compose restart bot + +5. Если контейнер не стартует: + $ docker-compose up -d + + +📚 ДОПОЛНИТЕЛЬНАЯ ДОКУМЕНТАЦИЯ +═══════════════════════════════════════════════════════════════════════════════ + + Полная инструкция: INTERACTIVE_AUTH_GUIDE.md + Советы и трюки: README_COMPLETE.md + Структура проекта: COMPLETION_CHECKLIST.md + + +🎯 ПОСЛЕ УСПЕШНОЙ АВТОРИЗАЦИИ +═══════════════════════════════════════════════════════════════════════════════ + +Вы получите доступ к: + + 📥 Собрать группы + → Получить список всех ваших групп + → Сохранить информацию в базу данных + + 👥 Собрать участников + → Выбрать группу + → Скачать список всех участников + → Получить информацию о каждом пользователе + + ⚙️ Настройки + → Проверить статус авторизации + → Переавторизоваться при необходимости + → Просмотреть информацию о сессии + + +═════════════════════════════════════════════════════════════════════════════ + +ГОТОВО! 🚀 + +Откройте бота @gongeeauto_bot и начните авторизацию! + +═════════════════════════════════════════════════════════════════════════════ + +EOF diff --git a/app/__init__.py b/app/__init__.py index e877447..4d0eeec 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -29,6 +29,13 @@ from app.handlers import ( userbot_collect_members, userbot_parse_members, cancel_userbot, + auth_menu, + auth_info, + start_phone_input, + handle_phone, + handle_code, + handle_password, + cancel_auth, ) from app.handlers.message_manager import ( create_message_start, @@ -132,6 +139,47 @@ async def main() -> None: # Добавляем обработчик для кнопки UserBot в главном меню application.add_handler(CallbackQueryHandler(userbot_menu, pattern=f"^{CallbackType.MANAGE_USERBOT.value}$"), group=1) + # Обработчики авторизации UserBot + application.add_handler(CallbackQueryHandler(auth_menu, pattern="^auth_menu$"), group=1) + application.add_handler(CallbackQueryHandler(auth_info, pattern="^auth_info$"), group=1) + application.add_handler(CallbackQueryHandler(start_phone_input, pattern="^auth_start_phone$"), group=1) + + # Конверсейшн для ввода номера телефона + auth_phone_conversation = ConversationHandler( + entry_points=[], # Входная точка через callback query выше + states={ + 2: [MessageHandler(filters.TEXT & ~filters.COMMAND, handle_phone)], # AUTH_PHONE = 2 + }, + fallbacks=[CallbackQueryHandler(cancel_auth, pattern="^cancel_auth$")], + name="auth_phone", + persistent=False + ) + application.add_handler(auth_phone_conversation, group=1) + + # Конверсейшн для ввода SMS кода + auth_code_conversation = ConversationHandler( + entry_points=[], # Входная точка через callback query выше + states={ + 3: [MessageHandler(filters.TEXT & ~filters.COMMAND, handle_code)], # AUTH_CODE = 3 + }, + fallbacks=[CallbackQueryHandler(cancel_auth, pattern="^cancel_auth$")], + name="auth_code", + persistent=False + ) + application.add_handler(auth_code_conversation, group=1) + + # Конверсейшн для ввода пароля 2FA + auth_password_conversation = ConversationHandler( + entry_points=[], # Входная точка через callback query выше + states={ + 4: [MessageHandler(filters.TEXT & ~filters.COMMAND, handle_password)], # AUTH_PASSWORD = 4 + }, + fallbacks=[CallbackQueryHandler(cancel_auth, pattern="^cancel_auth$")], + name="auth_password", + persistent=False + ) + application.add_handler(auth_password_conversation, group=1) + # Select group callbacks application.add_handler(CallbackQueryHandler(select_groups, pattern=r"^select_group_\d+$"), group=1) application.add_handler(CallbackQueryHandler(select_groups, pattern=r"^done_groups$"), group=1) diff --git a/app/handlers/__init__.py b/app/handlers/__init__.py index ae7b58d..778f3c7 100644 --- a/app/handlers/__init__.py +++ b/app/handlers/__init__.py @@ -8,7 +8,9 @@ from .group_manager import my_chat_member from .userbot_manager import ( userbot_menu, userbot_settings, userbot_init, userbot_collect_groups, userbot_collect_members, - userbot_parse_members, cancel_userbot + userbot_parse_members, cancel_userbot, + auth_menu, auth_info, start_phone_input, + handle_phone, handle_code, handle_password, cancel_auth ) __all__ = [ @@ -29,4 +31,11 @@ __all__ = [ 'userbot_collect_members', 'userbot_parse_members', 'cancel_userbot', + 'auth_menu', + 'auth_info', + 'start_phone_input', + 'handle_phone', + 'handle_code', + 'handle_password', + 'cancel_auth', ] diff --git a/app/handlers/userbot_auth.py b/app/handlers/userbot_auth.py new file mode 100644 index 0000000..04a2dd5 --- /dev/null +++ b/app/handlers/userbot_auth.py @@ -0,0 +1,476 @@ +""" +Интерактивная авторизация UserBot через интерфейс бота +""" +import os +import logging +from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton +from telegram.ext import ContextTypes, ConversationHandler +from telethon import TelegramClient +from telethon.errors import SessionPasswordNeededError, PhoneNumberInvalidError +from app.database import AsyncSessionLocal +from app.utils.keyboards import CallbackType +import asyncio + +logger = logging.getLogger(__name__) + +# Состояния для авторизации +AUTH_START = 1 +AUTH_PHONE = 2 +AUTH_CODE = 3 +AUTH_PASSWORD = 4 +AUTH_WAITING = 5 + +# Хранилище для временных данных авторизации +auth_sessions = {} + + +async def auth_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Меню авторизации UserBot""" + query = update.callback_query + if query: + await query.answer() + + user_id = update.effective_user.id + + # Проверяем статус + session_file = f"app/sessions/userbot_{user_id}.session" + is_authorized = os.path.exists(session_file) + + text = """🔐 Авторизация UserBot + +UserBot использует ваш личный аккаунт Telegram для сбора информации о группах и участниках. + +Важно: +• Авторизация безопасна и происходит локально +• Ваши данные не передаются никому +• UserBot будет работать 24/7 на сервере + +""" + + if is_authorized: + text += "✅ Статус: Авторизован\n\nВы можете использовать все функции UserBot." + keyboard = [ + [InlineKeyboardButton("🔄 Переавторизоваться", callback_data="auth_start_phone")], + [InlineKeyboardButton("ℹ️ Информация", callback_data="auth_info")], + [InlineKeyboardButton("⬅️ Назад", callback_data="userbot_menu")], + ] + else: + text += "❌ Статус: Не авторизован\n\nНажмите кнопку ниже, чтобы начать авторизацию." + keyboard = [ + [InlineKeyboardButton("🚀 Начать авторизацию", callback_data="auth_start_phone")], + [InlineKeyboardButton("ℹ️ Информация", callback_data="auth_info")], + [InlineKeyboardButton("⬅️ Назад", callback_data="userbot_menu")], + ] + + if query: + await query.edit_message_text( + text, + parse_mode='HTML', + reply_markup=InlineKeyboardMarkup(keyboard) + ) + else: + await update.message.reply_text( + text, + parse_mode='HTML', + reply_markup=InlineKeyboardMarkup(keyboard) + ) + + return AUTH_START + + +async def auth_info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Информация об авторизации""" + query = update.callback_query + await query.answer() + + text = """ℹ️ Информация об авторизации UserBot + +Как это работает: +1. Введите номер телефона вашего аккаунта Telegram +2. Получите SMS-код подтверждения +3. Введите код в бот +4. При необходимости подтвердите двухфакторную аутентификацию +5. Готово! UserBot авторизован + +Безопасность: +✓ Авторизация происходит локально на сервере +✓ Ваш пароль не передается нигде +✓ Сессия сохраняется в зашифрованном виде +✓ Доступ имеет только этот бот + +Что может делать UserBot: +✓ Собирать информацию о ваших группах +✓ Получать список участников группы +✓ Сохранять данные в базу данных +✓ Работать 24/7 без вашего участия + +Что НЕ может делать: +✗ Отправлять сообщения от вашего имени (опционально) +✗ Удалять или изменять ваши сообщения +✗ Изменять настройки групп +✗ Получать доступ к приватным чатам других пользователей +""" + + keyboard = [ + [InlineKeyboardButton("⬅️ Назад", callback_data="auth_menu")], + ] + + await query.edit_message_text( + text, + parse_mode='HTML', + reply_markup=InlineKeyboardMarkup(keyboard) + ) + + return AUTH_START + + +async def start_phone_input(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Начало ввода номера телефона""" + query = update.callback_query + if query: + await query.answer() + await query.delete_message() + + user_id = update.effective_user.id + + text = """📱 Введите номер телефона + +Введите номер телефона вашего аккаунта Telegram в формате: ++7 (XXX) XXX-XX-XX + +Примеры: +• +79991234567 (Россия) +• +82101234567 (Южная Корея) +• +11234567890 (США) + +После ввода номера вам будет отправлен SMS-код +""" + + await update.effective_message.reply_text( + text, + parse_mode='HTML' + ) + + # Инициализируем хранилище для этого пользователя + if user_id not in auth_sessions: + auth_sessions[user_id] = {} + + return AUTH_PHONE + + +async def handle_phone(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Обработка номера телефона""" + user_id = update.effective_user.id + phone = update.message.text.strip() + + # Очищаем от спецсимволов + phone_clean = ''.join(c for c in phone if c.isdigit()) + + if not phone_clean or len(phone_clean) < 10: + await update.message.reply_text( + "❌ Некорректный номер телефона. Пожалуйста, введите номер в международном формате (с кодом страны).", + parse_mode='HTML' + ) + return AUTH_PHONE + + # Восстанавливаем номер с + спереди если его нет + if not phone_clean.startswith('1') and not phone_clean[0].isdigit(): + phone_clean = phone_clean + + if not phone.startswith('+'): + phone = '+' + phone_clean + else: + phone = '+' + phone_clean + + # Сохраняем номер + auth_sessions[user_id]['phone'] = phone + + text = f"""📤 Отправляем код подтверждения... + +Номер: {phone} + +Пожалуйста, подождите. Отправляем SMS на ваш номер... +""" + + message = await update.message.reply_text(text, parse_mode='HTML') + + try: + # Создаем Telethon клиент + api_id = os.getenv('TELETHON_API_ID') + api_hash = os.getenv('TELETHON_API_HASH') + + if not api_id or not api_hash: + await message.edit_text( + "❌ Ошибка: API ID или API Hash не установлены", + parse_mode='HTML' + ) + return AUTH_PHONE + + session_file = f"app/sessions/userbot_auth_{user_id}" + + client = TelegramClient(session_file, int(api_id), api_hash) + + # Подключаемся и запрашиваем код + await client.connect() + + try: + result = await client.send_code_request(phone) + auth_sessions[user_id]['client'] = client + auth_sessions[user_id]['phone_code_hash'] = result.phone_code_hash + + await message.edit_text( + f"""✅ Код отправлен! + +SMS с кодом подтверждения отправлен на номер: +{phone} + +Введите полученный код: +""", + parse_mode='HTML' + ) + + return AUTH_CODE + + except PhoneNumberInvalidError: + await message.edit_text( + f"""❌ Неверный номер телефона + +Номер {phone} не является корректным номером Telegram. + +Пожалуйста, попробуйте еще раз с корректным номером. +""", + parse_mode='HTML' + ) + await client.disconnect() + return AUTH_PHONE + + except Exception as e: + logger.error(f"Auth error: {e}") + await message.edit_text( + f"""❌ Ошибка при отправке кода + +{str(e)} + +Пожалуйста, попробуйте еще раз. +""", + parse_mode='HTML' + ) + return AUTH_PHONE + + +async def handle_code(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Обработка SMS-кода""" + user_id = update.effective_user.id + code = update.message.text.strip() + + if not code.isdigit() or len(code) != 5: + await update.message.reply_text( + "❌ Код должен состоять из 5 цифр. Пожалуйста, попробуйте еще раз.", + parse_mode='HTML' + ) + return AUTH_CODE + + message = await update.message.reply_text( + "🔄 Проверяем код...", + parse_mode='HTML' + ) + + try: + if user_id not in auth_sessions or 'client' not in auth_sessions[user_id]: + await message.edit_text( + "❌ Сессия потеряна. Пожалуйста, начните авторизацию заново.", + parse_mode='HTML' + ) + return AUTH_PHONE + + client = auth_sessions[user_id]['client'] + phone_code_hash = auth_sessions[user_id]['phone_code_hash'] + + try: + # Пытаемся войти с кодом + await client.sign_in( + phone=auth_sessions[user_id]['phone'], + code=code, + phone_code_hash=phone_code_hash + ) + + # Успешная авторизация + await message.edit_text( + """✅ Авторизация успешна! + +Ваш UserBot авторизован и готов к работе. + +Сессия сохранена безопасно на сервере. +""", + parse_mode='HTML' + ) + + # Сохраняем правильное имя сессии + correct_session = f"app/sessions/userbot_{user_id}" + if os.path.exists(f"app/sessions/userbot_auth_{user_id}.session"): + os.rename( + f"app/sessions/userbot_auth_{user_id}.session", + f"{correct_session}.session" + ) + + await client.disconnect() + + # Очищаем временные данные + if user_id in auth_sessions: + del auth_sessions[user_id] + + # Возвращаемся в меню + keyboard = [ + [InlineKeyboardButton("✅ Готово", callback_data="userbot_menu")], + ] + await message.reply_text( + "Нажмите кнопку, чтобы вернуться в меню UserBot.", + reply_markup=InlineKeyboardMarkup(keyboard) + ) + + return ConversationHandler.END + + except SessionPasswordNeededError: + # Нужна двухфакторная аутентификация + await message.edit_text( + """🔐 Требуется двухфакторная аутентификация + +Введите пароль вашего аккаунта Telegram: +""", + parse_mode='HTML' + ) + return AUTH_PASSWORD + + except Exception as e: + logger.error(f"Code verification error: {e}") + await message.edit_text( + f"""❌ Ошибка при проверке кода + +{str(e)} + +Пожалуйста, попробуйте еще раз или начните авторизацию заново. +""", + parse_mode='HTML' + ) + return AUTH_CODE + + +async def handle_password(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Обработка пароля 2FA""" + user_id = update.effective_user.id + password = update.message.text + + message = await update.message.reply_text( + "🔄 Проверяем пароль...", + parse_mode='HTML' + ) + + try: + if user_id not in auth_sessions or 'client' not in auth_sessions[user_id]: + await message.edit_text( + "❌ Сессия потеряна. Пожалуйста, начните авторизацию заново.", + parse_mode='HTML' + ) + return AUTH_PASSWORD + + client = auth_sessions[user_id]['client'] + + # Проверяем пароль + await client.sign_in(password=password) + + # Успешная авторизация + await message.edit_text( + """✅ Двухфакторная аутентификация успешна! + +Ваш UserBot авторизован и готов к работе. +""", + parse_mode='HTML' + ) + + # Сохраняем правильное имя сессии + correct_session = f"app/sessions/userbot_{user_id}" + if os.path.exists(f"app/sessions/userbot_auth_{user_id}.session"): + os.rename( + f"app/sessions/userbot_auth_{user_id}.session", + f"{correct_session}.session" + ) + + await client.disconnect() + + # Очищаем временные данные + if user_id in auth_sessions: + del auth_sessions[user_id] + + keyboard = [ + [InlineKeyboardButton("✅ Готово", callback_data="userbot_menu")], + ] + await message.reply_text( + "Нажмите кнопку, чтобы вернуться в меню UserBot.", + reply_markup=InlineKeyboardMarkup(keyboard) + ) + + return ConversationHandler.END + + except Exception as e: + logger.error(f"Password verification error: {e}") + await message.edit_text( + f"""❌ Ошибка при проверке пароля + +{str(e)} + +Пожалуйста, попробуйте еще раз. +""", + parse_mode='HTML' + ) + return AUTH_PASSWORD + + +async def cancel_auth(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: + """Отмена авторизации""" + user_id = update.effective_user.id + + # Отключаем клиент если он есть + if user_id in auth_sessions and 'client' in auth_sessions[user_id]: + try: + await auth_sessions[user_id]['client'].disconnect() + except: + pass + del auth_sessions[user_id] + + query = update.callback_query + if query: + await query.answer() + await query.delete_message() + + await update.effective_message.reply_text( + "Авторизация отменена.", + parse_mode='HTML' + ) + + return ConversationHandler.END + + +def get_auth_conversation_handler(): + """Возвращает ConversationHandler для авторизации""" + return ConversationHandler( + entry_points=[ + # Когда пользователь нажимает кнопку авторизации + ], + states={ + AUTH_START: [ + # Информация об авторизации + ], + AUTH_PHONE: [ + # Обработка номера телефона + ], + AUTH_CODE: [ + # Обработка SMS кода + ], + AUTH_PASSWORD: [ + # Обработка пароля 2FA + ], + }, + fallbacks=[], + name="userbot_auth", + persistent=True + ) diff --git a/app/handlers/userbot_manager.py b/app/handlers/userbot_manager.py index 35cbef2..8888dc0 100644 --- a/app/handlers/userbot_manager.py +++ b/app/handlers/userbot_manager.py @@ -8,7 +8,21 @@ from app.database import AsyncSessionLocal from app.database.repository import GroupRepository from app.database.member_repository import GroupMemberRepository from app.utils.keyboards import CallbackType +from app.handlers.userbot_auth import ( + auth_menu, + auth_info, + start_phone_input, + handle_phone, + handle_code, + handle_password, + cancel_auth, + AUTH_START, + AUTH_PHONE, + AUTH_CODE, + AUTH_PASSWORD, +) import logging +import os logger = logging.getLogger(__name__) @@ -34,6 +48,7 @@ async def userbot_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> in UserBot собирает информацию о группах и их участниках от имени пользователя""" keyboard = [ + [InlineKeyboardButton("🔐 Авторизация", callback_data="auth_menu")], [InlineKeyboardButton("⚙️ Настройки", callback_data="userbot_settings")], [InlineKeyboardButton("📥 Собрать группы", callback_data="userbot_collect_groups")], [InlineKeyboardButton("👥 Собрать участников", callback_data="userbot_collect_members")], @@ -435,6 +450,25 @@ async def userbot_parse_members(update: Update, context: ContextTypes.DEFAULT_TY return USERBOT_COLLECTING_MEMBERS +# Экспорт функций авторизации для использования в других модулях +__all__ = [ + 'userbot_menu', + 'userbot_settings', + 'userbot_init', + 'userbot_collect_groups', + 'userbot_collect_members', + 'userbot_parse_members', + 'cancel_userbot', + 'auth_menu', + 'auth_info', + 'start_phone_input', + 'handle_phone', + 'handle_code', + 'handle_password', + 'cancel_auth', +] + + async def cancel_userbot(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Отмена диалога""" query = update.callback_query diff --git a/app/sessions/telethon_session.session b/app/sessions/telethon_session.session index d17e059..150c946 100644 Binary files a/app/sessions/telethon_session.session and b/app/sessions/telethon_session.session differ diff --git a/sessions/userbot_session.session b/sessions/userbot_session.session index 421967a..f14cb3a 100644 Binary files a/sessions/userbot_session.session and b/sessions/userbot_session.session differ