#!/usr/bin/env python3 """SPAM LIVE — все аккаунты с live-чатами, авто-пропуск флуда. TEMPLATE: copy to project, fill in API_ID, API_HASH, MESSAGES, BASE path.""" import asyncio, json, random, time from pathlib import Path from datetime import datetime from telethon import TelegramClient from telethon.errors import FloodWaitError BASE = Path(r"C:\Users\User\Desktop\_PROJECTS\рассылка") API_ID = 2040 API_HASH = "[REDACTED-KEY]" MESSAGES = [ "🚀 Заработок на трафике — без вложений!\n\nИщу партнёров...", # Add 4-5 variants ] PROGRESS = BASE / "spam_live_progress.json" if PROGRESS.exists(): p = json.loads(PROGRESS.read_text()) else: p = {"sent": {}, "failed": {}, "flood_until": {}, "stats": {"total_sent": 0, "total_failed": 0}} def save(): PROGRESS.write_text(json.dumps(p, indent=2)) def log(msg): ts = datetime.now().strftime("%H:%M:%S") print(f"[{ts}] {msg}") def find_sessions(): sessions = {} for folder in ["sessions5", "sessions_clean"]: sd = BASE / folder if sd.exists(): for f in sd.glob("*.session"): if f.stem not in sessions: sessions[f.stem] = f return sessions async def spam(aid, chats, session_path): done = set(p["sent"].get(aid, []) + p["failed"].get(aid, [])) remaining = [c for c in chats if c["username"] not in done] if not remaining: return 0, 0 client = None try: client = TelegramClient(str(session_path), API_ID, API_HASH) await client.connect() except Exception as e: log(f"❌ {aid} BAD SESSION: {e}") p["flood_until"][aid] = int(time.time()) + 3600 save() if client: await client.disconnect() return 0, 0 me = await client.get_me() log(f"✅ {aid} (@{me.username or me.first_name}): {len(remaining)} chats") sent = 0 msg = random.choice(MESSAGES) for i, c in enumerate(remaining): u = c["username"] t = c.get("title", u) try: entity = await client.get_entity(f"@{u}") await client.send_message(entity, msg) p["sent"].setdefault(aid, []).append(u) p["stats"]["total_sent"] += 1 sent += 1 log(f" [{i+1}/{len(remaining)}] SENT: {t}") save() await asyncio.sleep(random.uniform(4, 10)) except FloodWaitError as e: p["flood_until"][aid] = int(time.time()) + e.seconds save() log(f" FLOOD {e.seconds}s — DONE with {aid}") break except Exception as e: p["failed"].setdefault(aid, []).append(u) p["stats"]["total_failed"] += 1 save() log(f" [{i+1}/{len(remaining)}] {type(e).__name__}: {t}") await client.disconnect() return sent, 0 async def main(): # Load live chats from generated/account_live_chats_v2.json live_path = BASE / "generated" / "account_live_chats_v2.json" if not live_path.exists(): log("No live chats file found!") return all_chats = {} src = json.loads(live_path.read_text()) for aid, chats in src.items(): if not isinstance(chats, list): continue all_chats[aid] = {} for c in chats: all_chats[aid][c["username"]] = c sessions = find_sessions() now = time.time() working = [] skipped = 0 for aid, sp in sorted(sessions.items(), key=lambda x: len(all_chats.get(x[0], {})), reverse=True): if aid not in all_chats: continue fu = p["flood_until"].get(aid, 0) if fu > now: skipped += 1 continue chats = list(all_chats[aid].values()) done = len(p["sent"].get(aid, [])) + len(p["failed"].get(aid, [])) remaining = len(chats) - done if remaining > 0: working.append((aid, chats, sp, remaining)) working.sort(key=lambda x: x[3], reverse=True) total = sum(w[3] for w in working) log(f"=== SPAM LIVE ===") log(f"Accounts ready: {len(working)}, flooded: {skipped}") log(f"Total chats remaining: {total}") log(f"Already sent: {p['stats']['total_sent']}, failed: {p['stats']['total_failed']}\n") for aid, chats, sp, rem in working: log(f"▶ {aid}: {rem} chats") s, f = await spam(aid, chats, sp) if s > 0: delay = random.uniform(30, 60) log(f"💤 Cooldown {delay:.0f}s\n") await asyncio.sleep(delay) log(f"\n=== DONE ===") log(f"Sent: {p['stats']['total_sent']}, Failed: {p['stats']['total_failed']}") asyncio.run(main())