diff --git a/collect_all_members.py b/collect_all_members.py new file mode 100644 index 0000000..d12073f --- /dev/null +++ b/collect_all_members.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +""" +Сбор всех участников группы в базу данных +Использование: python collect_all_members.py +""" +import asyncio +import logging +import aiohttp +from aiohttp_socks import ProxyConnector +from sqlalchemy import select, func +from database.db import AsyncSessionLocal, init_db +from database.models import User +from config import BOT_TOKEN, ADMIN_CHAT_ID, get_proxy_url + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +async def collect_all_members(): + """Собрать всех участников группы""" + + await init_db() + + proxy_url = get_proxy_url() + connector = ProxyConnector.from_url(proxy_url) + + async with aiohttp.ClientSession(connector=connector) as session: + # Получаем всех участников через getChatMembers + # Telegram API позволяет получать по 100 за раз + all_members = [] + offset = 0 + limit = 100 + + logger.info(f'🔄 Начинаем сбор участников...') + + while True: + try: + url = f"https://api.telegram.org/bot{BOT_TOKEN}/getChatMembers" + params = { + "chat_id": ADMIN_CHAT_ID, + "offset": offset, + "limit": limit + } + + async with session.get(url, params=params) as resp: + result = await resp.json() + + if not result.get('ok'): + logger.error(f'Ошибка API: {result}') + break + + members = result.get('result', []) + if not members: + break + + all_members.extend(members) + offset += limit + + logger.info(f'Загружено {len(all_members)} участников...') + + # Если загрузили меньше чем лимит — это конец + if len(members) < limit: + break + + except Exception as e: + logger.error(f'Ошибка при загрузке: {e}') + break + + logger.info(f'✅ Всего загружено: {len(all_members)}') + + # Добавляем в базу + async with AsyncSessionLocal() as db_session: + added = 0 + updated = 0 + + for member in all_members: + user_data = member.get('user', {}) + user_id = user_data.get('id') + + if not user_id: + continue + + user = await db_session.get(User, user_id) + + if not user: + # Новый пользователь + user = User( + user_id=user_id, + username=user_data.get('username'), + first_name=user_data.get('first_name'), + last_name=user_data.get('last_name'), + verified=False, # Пока не верифицирован + ) + db_session.add(user) + added += 1 + else: + # Обновляем данные + if user_data.get('username') and user.username != user_data.get('username'): + user.username = user_data.get('username') + updated += 1 + if user_data.get('first_name') and user.first_name != user_data.get('first_name'): + user.first_name = user_data.get('first_name') + updated += 1 + + await db_session.commit() + + # Статистика + total = (await db_session.execute(select(func.count(User.user_id)))).scalar() + + logger.info(f'✅ Сбор завершён!') + logger.info(f' Добавлено: {added}') + logger.info(f' Обновлено: {updated}') + logger.info(f' Всего в базе: {total}') + + +if __name__ == '__main__': + asyncio.run(collect_all_members()) diff --git a/data/service_images/police_2a8a48fc857d4cf78a10583d6820f1be.png b/data/service_images/police_2a8a48fc857d4cf78a10583d6820f1be.png new file mode 100644 index 0000000..c2da00a Binary files /dev/null and b/data/service_images/police_2a8a48fc857d4cf78a10583d6820f1be.png differ diff --git a/data/service_images/utility_508733a4ff614d18be9424936c45b57f.png b/data/service_images/utility_508733a4ff614d18be9424936c45b57f.png new file mode 100644 index 0000000..90a9a4f Binary files /dev/null and b/data/service_images/utility_508733a4ff614d18be9424936c45b57f.png differ diff --git a/handlers/users.py b/handlers/users.py index 8ac545a..cd6137e 100644 --- a/handlers/users.py +++ b/handlers/users.py @@ -24,15 +24,9 @@ router = Router() async def cmd_start(message: Message): """Команда /start (ТОЛЬКО В ЛИЧКЕ!)""" from utils.ui_styles import get_level_badge - from aiogram.types import ReplyKeyboardMarkup, KeyboardButton # Проверяем что это личка if message.chat.type != 'private': - await message.answer( - '💡 Бот работает только в личных сообщениях!\n\n' - 'Нажмите на имя бота сверху и напишите /start в личке', - parse_mode='HTML' - ) return user_id = message.from_user.id @@ -44,62 +38,14 @@ async def cmd_start(message: Message): user = result.scalar_one_or_none() if not user: - # Создаём нового пользователя - user = User( - user_id=user_id, - username=message.from_user.username, - first_name=message.from_user.first_name, - last_name=message.from_user.last_name, - ) - session.add(user) - await session.commit() - - # 🔴 НОВОЕ СООБЩЕНИЕ С КНОПКАМИ (БЕЗ !) - welcome_text = f'''🔴 ДОБРО ПОЖАЛОВАТЬ - -👋 Привет, {message.from_user.first_name}! - -Я — домовой бот нашего дома. - -🏠 Что я умею: -• 📞 Телефоны экстренных служб -• 👷 Проверенные мастера -• 📅 График отключений -• 💰 Напоминания о платежах -• 🏆 Рейтинг и достижения -• 📋 Опросы и голосования - -⚠️ ВАЖНО: -Для полного доступа пройдите верификацию! - -📝 Как пройти верификацию: - -Шаг 1: Отправьте номер квартиры -Примеры: 45, 12А, 100-1 - -Шаг 2: (опционально) Отправьте телефон -Пример: +79991234567 - -Шаг 3: Дождитесь подтверждения админа - -После верификации откроются все функции! 🎉''' - - # Кнопки для быстрого старта - kb = ReplyKeyboardMarkup( - keyboard=[ - [KeyboardButton(text='📞 Экстренные телефоны')], - [KeyboardButton(text='📜 Правила чата'), KeyboardButton(text='❓ Помощь')], - ], - resize_keyboard=True - ) - - await message.answer(welcome_text, parse_mode='HTML', reply_markup=kb) - - else: - # Обновляем имя - user.username = message.from_user.username - user.first_name = message.from_user.first_name - user.last_name = message.from_user.last_name + # Пользователя нет в базе - ИГНОР! + logger.info(f'Пользователь {user_id} не в базе - игнорируем /start') + return + + # Пользователь в базе - обновляем имя + user.username = message.from_user.username + user.first_name = message.from_user.first_name + user.last_name = message.from_user.last_name # Проверяем статус is_admin = user.is_admin or (user_id == config.ADMIN_USER_ID) @@ -182,15 +128,20 @@ async def cmd_start(message: Message): @router.message(Command('help')) async def cmd_help(message: Message): """Справка по командам (для жильцов)""" - from utils.ui_styles import get_colored_header, get_level_badge, get_user_level_with_ig + from utils.ui_styles import get_colored_header, get_level_badge from database.models import InitiativeGroup user_id = message.from_user.id async with AsyncSessionLocal() as session: user = await session.get(User, user_id) + # Проверяем есть ли в базе + if not user: + logger.info(f'Пользователь {user_id} не в базе - игнорируем /help') + return + # Определяем уровень - if user and user.verified: + if user.verified: ig_stmt = select(InitiativeGroup).where( InitiativeGroup.user_id == user_id, InitiativeGroup.is_active == True