🔒 БЕЗОПАСНОСТЬ: • Бот работает ТОЛЬКО с пользователями из базы • /start - игнор если нет в базе • /help - игнор если нет в базе • Верифицированные - полный доступ • Неверифицированные - стимул пройти верификацию 📁 ФАЙЛЫ: • handlers/users.py: проверка базы • collect_all_members.py: скрипт сбора 🎯 СТИМУЛ: • Хочешь бота? → Пройди верификацию! • Админы, ИГ, верифицированные - работают • Остальные - игнор Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
#!/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())
|