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


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"

# Имя сессии (меняй имя под новый аккаунт, если нужно: session_acc1, session_acc2...)
SESSION_NAME = "session_checker"
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", "office365", "outlook", "smtp",
    "imap", "exchange", "mail access", "imap logs", "mail pass", "mailbase",
    "azure", "entra id", "webmail", "cpanel", "corporate leads", "business email",
    "inbox fwd", "fwd rule", "bec", "tdata", "business lead", "corp mail"
]

KW_HACKING = [
    "hacking", "exploit", "fraud", "carding", "stealer", "cves", "pentest",
    "ddos", "botnet", "phishing", "malware", "credentials", "combolists",
    "redline", "vidar", "raccoon", "lumma", "source code", "0day", "rat",
    "sqli", "bypass", "dump", "cracked", "cookies", "rdp", "checker", "combo"
]

KW_ADS = [
    "selling", "buying", "price", "pm me", "escrow", "vcc", "for sale",
    "shop", "store", "deal", "discount", "bulk", "wts", "wtb", "$", "usd",
    "crypto accepted", "order now"
]

async def append_to_file(filename, text):
    with open(filename, "a", encoding="utf-8") as f:
        f.write(text + "\n")

def has_cyrillic(text):
    return any("\u0400" <= char <= "\u04ff" for char in text.lower())

async def analyze_chat(client, entity):
    """
    Вытягивает текст постов и проверяет активность:
    Возвращает: (is_active, full_text_corpus)
    """
    now = datetime.now(timezone.utc)
    one_day_ago = now - timedelta(days=1)
    
    messages_24h = []
    text_corpus = []
    senders = set()

    try:
        async for msg in client.iter_messages(entity, limit=20):
            if msg.text:
                text_corpus.append(msg.text)
            
            # Считаем суточную активность
            if msg.date and msg.date >= one_day_ago:
                messages_24h.append(msg)
                sender = msg.sender_id or msg.from_id
                if sender:
                    senders.add(sender)
    except Exception:
        pass

    # Живой чат: минимум 3 сообщения за 24 часа минимум от 2 людей
    is_active = (len(messages_24h) >= 3 and len(senders) >= 2)
    return is_active, " ".join(text_corpus)

async def main():
    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)} строк. Запуск глубокого анализа...")

    async with TelegramClient(SESSION_NAME, 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 ""

                    # Вытягиваем текст из чата и статус активности
                    is_active, chat_body_text = await analyze_chat(client, entity)
                    full_content = f"{title} {chat_body_text}"
                    full_content_lower = full_content.lower()

                    # 1. Кириллица -> сразу в Категорию 3
                    if has_cyrillic(full_content):
                        await append_to_file(CAT_3, f"@{username} | {title} (RU content)")
                        print(f"[{idx}/{len(usernames)}] [Cat 3 - RU]: @{username}")
                        break

                    # 2. Поиск совпадений по темам
                    is_o365 = any(kw in full_content_lower for kw in KW_O365)
                    is_hack = any(kw in full_content_lower for kw in KW_HACKING)

                    # Не подошло под целевые темы
                    if not is_o365 and not is_hack:
                        await append_to_file(CAT_3, f"@{username} | {title} (Unrelated topic)")
                        print(f"[{idx}/{len(usernames)}] [Cat 3 - Не по теме]: @{username}")
                        break

                    # Тема подошла, но чат мертв/неактивен
                    if not is_active:
                        await append_to_file(CAT_3, f"@{username} | {title} (Inactive chat)")
                        print(f"[{idx}/{len(usernames)}] [Cat 3 - Мертвый чат]: @{username}")
                        break

                    # 3. Распределение активных целевых групп
                    if is_o365:
                        await append_to_file(CAT_1, f"@{username} | {title}")
                        print(f"[{idx}/{len(usernames)}] [Cat 1 - O365/BEC]: @{username}")
                    elif is_hack:
                        # Разделяем на рекламу (2b) и живое общение (2a)
                        if any(ad in full_content_lower for ad in KW_ADS):
                            await append_to_file(CAT_2B, f"@{username} | {title}")
                            print(f"[{idx}/{len(usernames)}] [Cat 2b - Ads]: @{username}")
                        else:
                            await append_to_file(CAT_2A, f"@{username} | {title}")
                            print(f"[{idx}/{len(usernames)}] [Cat 2a - Active]: @{username}")
                    break

                except (UsernameInvalidError, UsernameNotOccupiedError, ValueError, ChannelPrivateError):
                    await append_to_file(CAT_4, f"@{username}")
                    print(f"[{idx}/{len(usernames)}] [Cat 4 - Dead/Private]: @{username}")
                    break

                except FloodWaitError as e:
                    print(f"\nЛимит Telegram! Ожидание {e.seconds} секунд...")
                    await asyncio.sleep(e.seconds + 2)

                except Exception:
                    await append_to_file(CAT_4, f"@{username}")
                    print(f"[{idx}/{len(usernames)}] [Cat 4 - Inaccessible]: @{username}")
                    break

            await asyncio.sleep(1.8)

    print("\nПакет обработан! Данные сохранены.")

if __name__ == "__main__":
    asyncio.run(main())