Загрузка данных
import asyncio
from datetime import datetime, timezone, timedelta
from telethon import TelegramClient
from telethon.errors import (
FloodWaitError,
UsernameInvalidError,
UsernameNotOccupiedError,
ChannelPrivateError,
)
# Твои личные ключи
API_ID = 35901392
API_HASH = "08ab29c9da01a4f3eaf10f3baa7200f2"
INPUT_FILE = "usernames.txt"
# Файлы для категорий
CAT_1 = "cat_1_bec_o365.txt"
CAT_2A = "cat_2a_active_hacking.txt"
CAT_2B = "cat_2b_ads_hacking.txt"
CAT_3 = "cat_3_unrelated_russian_inactive.txt"
CAT_4 = "cat_4_dead_groups.txt"
# Ключевые слова
KW_O365 = [
"o365",
"office 365",
"microsoft 365",
"outlook",
"smtp",
"imap",
"exchange",
"mail access",
"logs",
"imap logs",
"mail pass",
"mailbase",
"azure",
"entra id",
"office365",
]
KW_HACKING = [
"hacking",
"exploit",
"fraud",
"carding",
"stealer",
"cves",
"pentest",
"ddos",
"botnet",
"phishing",
"malware",
"credentials",
"combolists",
]
KW_ADS = [
"selling",
"buying",
"price",
"pm",
"escrow",
"vcc",
"for sale",
"shop",
"store",
]
async def write_file(filename, text):
with open(filename, "a", encoding="utf-8") as f:
f.write(text + "\n")
def is_russian(text):
return any("\u0400" <= char <= "\u04ff" for char in text.lower())
async def check_activity(client, entity):
"""Проверяет активность: мин. 3-5 сообщений за последние 24 часа от >= 2 разных людей"""
try:
now = datetime.now(timezone.utc)
one_day_ago = now - timedelta(days=1)
messages = []
async for message in client.iter_messages(entity, limit=20):
if message.date and message.date >= one_day_ago:
messages.append(message)
else:
break # Сообщения идут от новых к старым, если вышли за сутки — прекращаем
if len(messages) < 3:
return False # Слишком мало сообщений за сутки
# Считаем уникальных отправителей
senders = set()
for msg in messages:
# Учитываем реальных пользователей (sender_id или from_id)
sender = msg.sender_id or msg.from_id
if sender:
senders.add(sender)
# Требуется минимум 2 разных человека
if len(senders) < 2:
return False
return True
except Exception:
return False
async def main():
for filename in [CAT_1, CAT_2A, CAT_2B, CAT_3, CAT_4]:
open(filename, "w", encoding="utf-8").close()
try:
with open(INPUT_FILE, "r", encoding="utf-8") as f:
usernames = [line.strip().lstrip("@") for line in f if line.strip()]
except FileNotFoundError:
print(f"Ошибка: Не найден файл {INPUT_FILE}!")
return
print(f"Загружено {len(usernames)} групп. Запуск проверки с фильтром активности...\n")
async with TelegramClient("session_checker", API_ID, API_HASH) as client:
for idx, username in enumerate(usernames, 1):
while True:
try:
entity = await client.get_entity(username)
title = getattr(entity, "title", "") or ""
about = ""
try:
full_info = await client.get_full_info(entity)
about = getattr(full_info.full_chat, "about", "") or ""
except Exception:
pass
text_to_check = f"{title} {about}"
text_lower = text_to_check.lower()
# Проверка темы (название/описание должно быть английским и содержать ключевые слова)
is_valid_topic = False
target_category = None
if not is_russian(text_to_check):
if any(kw in text_lower for kw in KW_O365):
is_valid_topic = True
target_category = 1
elif any(kw in text_lower for kw in KW_HACKING):
is_valid_topic = True
if any(ad in text_lower for ad in KW_ADS):
target_category = "2b"
else:
target_category = "2a"
# Если тема подходит, проверяем активность (минумум 3-5 сообщений за сутки от 2+ человек)
if is_valid_topic:
active = await check_activity(client, entity)
if not active:
# Если тема подходит, но группа мертвая/неактивная — отправляем в Категорию 3
await write_file(CAT_3, f"@{username} | {title} (Неактивна)")
print(f"[{idx}/{len(usernames)}] [Категория 3 (Подходящая, но НEАКТИВНАЯ)]: @{username}")
break
# Если активна — раскидываем по целевым категориям
if target_category == 1:
await write_file(CAT_1, f"@{username} | {title}")
print(f"[{idx}/{len(usernames)}] [Категория 1 (O365 + Актив)]: @{username}")
elif target_category == "2a":
await write_file(CAT_2A, f"@{username} | {title}")
print(f"[{idx}/{len(usernames)}] [Категория 2a (Актив хакинг)]: @{username}")
elif target_category == "2b":
await write_file(CAT_2B, f"@{username} | {title}")
print(f"[{idx}/{len(usernames)}] [Категория 2b (Реклама хакинг)]: @{username}")
break
# Всё остальное (русские, не подошедшие по темам, неактивные) идет в Категорию 3
await write_file(CAT_3, f"@{username} | {title}")
print(f"[{idx}/{len(usernames)}] [Категория 3 (Рус/Неподходящая/Мусор)]: @{username}")
break
except (UsernameInvalidError, UsernameNotOccupiedError, ValueError, ChannelPrivateError):
# Мертвые группы (Категория 4)
await write_file(CAT_4, f"@{username}")
print(f"[{idx}/{len(usernames)}] [Категория 4 (Мертвая)]: @{username}")
break
except FloodWaitError as e:
print(f"\n[!] Лимит Telegram. Ждем {e.seconds} сек...")
await asyncio.sleep(e.seconds + 2)
except Exception:
await write_file(CAT_4, f"@{username}")
print(f"[{idx}/{len(usernames)}] [Категория 4 (Ошибка/Мертвая)]: @{username}")
break
await asyncio.sleep(1.5)
print("\n" + "=" * 40)
print("Сортировка с проверкой активности завершена!")
print(f"Результаты сохранены в файлы: {CAT_1}, {CAT_2A}, {CAT_2B}, {CAT_3}, {CAT_4}")
print("=" * 40)
if __name__ == "__main__":
asyncio.run(main())