144 lines
4.6 KiB
Python
144 lines
4.6 KiB
Python
#!/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()) |