Загрузка данных


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())