autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
147
skills/telegram-automation/templates/lead_funnel_template.py
Normal file
147
skills/telegram-automation/templates/lead_funnel_template.py
Normal file
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
Lead funnel auto-reply bot — human-like DM responder.
|
||||
Shows typing indicator, realistic delays, 3-4 messages → redirect to target.
|
||||
|
||||
Copy to project, fill in SESSION_PATH, MY_USERNAME, TARGET_LINK, run.
|
||||
"""
|
||||
|
||||
import asyncio, json, random, time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from telethon import TelegramClient, events
|
||||
from telethon.tl.functions.messages import SetTypingRequest
|
||||
from telethon.tl.types import SendMessageTypingAction
|
||||
from telethon.errors import FloodWaitError
|
||||
|
||||
# ── Config ──────────────────────────────────────────────
|
||||
API_ID = 2040
|
||||
API_HASH = "[REDACTED-KEY]"
|
||||
SESSION_PATH = "session_file.session"
|
||||
MY_USERNAME = "my_username"
|
||||
TARGET_LINK = "https://t.me/target"
|
||||
|
||||
STATE_FILE = Path("lead_funnel_state.json")
|
||||
LOG_FILE = Path("lead_funnel_log.txt")
|
||||
|
||||
FUNNEL = [
|
||||
("Привет! Да, всё актуально. Что именно интересует?", (3, 7)),
|
||||
("Понял, есть в наличии. Цены адекватные. Что планируешь брать?", (5, 10)),
|
||||
("Я сейчас редко тут сижу. Напиши партнёру — он всегда в сети: {target}", (4, 8)),
|
||||
("Скажи что от @{me}, он подберёт под бюджет. Давай 🤝", (3, 6)),
|
||||
]
|
||||
|
||||
REPLY_DELAY_MIN = 15
|
||||
REPLY_DELAY_MAX = 60
|
||||
|
||||
BUY_KEYWORDS = [
|
||||
"купить", "продаёшь", "цена", "сколько", "стоит", "прайс",
|
||||
"хочу", "интересует", "нужен", "заказ", "готов", "возьму",
|
||||
"беру", "покупаю", "приобрести", "каталог", "в наличии",
|
||||
"есть", "почём", "расценки", "отзывы", "тема", "подробнее",
|
||||
]
|
||||
|
||||
def load_state():
|
||||
if STATE_FILE.exists():
|
||||
return json.loads(STATE_FILE.read_text(encoding="utf-8"))
|
||||
return {}
|
||||
|
||||
def save_state(state):
|
||||
STATE_FILE.write_text(json.dumps(state, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||
|
||||
def log(msg):
|
||||
line = f"[{datetime.now().strftime('%H:%M:%S')}] {msg}"
|
||||
print(line)
|
||||
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
||||
f.write(line + "\n")
|
||||
|
||||
def is_buy_intent(text):
|
||||
if not text:
|
||||
return False
|
||||
t = text.lower().strip()
|
||||
skip = ["привет", "здравствуй", "хай", "hello", "hi", "как дела", "салам", "ку", "здарова"]
|
||||
if t in skip:
|
||||
return False
|
||||
return any(kw in t for kw in BUY_KEYWORDS)
|
||||
|
||||
async def type_and_send(client, user_id, message, typing_range):
|
||||
secs = random.uniform(*typing_range)
|
||||
try:
|
||||
await client(SetTypingRequest(peer=user_id, action=SendMessageTypingAction()))
|
||||
except Exception:
|
||||
pass
|
||||
await asyncio.sleep(secs)
|
||||
await client.send_message(user_id, message)
|
||||
log(f"SENT: {message[:60]}...")
|
||||
|
||||
async def process_user(client, user_id, state):
|
||||
user_key = str(user_id)
|
||||
ud = state.get(user_key, {})
|
||||
step = ud.get("step", 0)
|
||||
if ud.get("done") or step >= len(FUNNEL):
|
||||
state[user_key]["done"] = True
|
||||
save_state(state)
|
||||
return
|
||||
|
||||
if step == 0:
|
||||
await asyncio.sleep(random.uniform(REPLY_DELAY_MIN, REPLY_DELAY_MAX))
|
||||
|
||||
msg, trange = FUNNEL[step]
|
||||
msg = msg.format(target=TARGET_LINK, me=MY_USERNAME)
|
||||
await type_and_send(client, user_id, msg, trange)
|
||||
|
||||
state[user_key]["step"] = step + 1
|
||||
state[user_key]["last_msg_time"] = time.time()
|
||||
save_state(state)
|
||||
|
||||
async def funnel_timer(client):
|
||||
while True:
|
||||
await asyncio.sleep(30)
|
||||
state = load_state()
|
||||
for user_key, ud in list(state.items()):
|
||||
if ud.get("done") or ud.get("step", 0) == 0:
|
||||
continue
|
||||
if ud.get("step", 0) >= len(FUNNEL):
|
||||
state[user_key]["done"] = True
|
||||
save_state(state)
|
||||
continue
|
||||
if time.time() - ud.get("last_msg_time", 0) < random.uniform(120, 240):
|
||||
continue
|
||||
try:
|
||||
await process_user(client, int(user_key), state)
|
||||
except FloodWaitError:
|
||||
pass
|
||||
except Exception as e:
|
||||
log(f"Timer error: {e}")
|
||||
|
||||
async def main():
|
||||
client = TelegramClient(SESSION_PATH, API_ID, API_HASH)
|
||||
await client.start()
|
||||
me = await client.get_me()
|
||||
log(f"STARTED: @{me.username} ({me.first_name})")
|
||||
|
||||
state = load_state()
|
||||
|
||||
@client.on(events.NewMessage(incoming=True))
|
||||
async def handler(event):
|
||||
if not event.is_private or event.out:
|
||||
return
|
||||
sender = await event.get_sender()
|
||||
uid, text = event.sender_id, event.raw_text or ""
|
||||
uk = str(uid)
|
||||
ud = state.get(uk, {})
|
||||
|
||||
if is_buy_intent(text) or ud.get("step", 0) > 0:
|
||||
if uk not in state:
|
||||
state[uk] = {"step": 0, "last_msg_time": 0, "first_seen": time.time()}
|
||||
save_state(state)
|
||||
try:
|
||||
await process_user(client, uid, state)
|
||||
except FloodWaitError:
|
||||
pass
|
||||
|
||||
asyncio.create_task(funnel_timer(client))
|
||||
log("Listening...")
|
||||
await client.run_until_disconnected()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
144
skills/telegram-automation/templates/spam_live_template.py
Normal file
144
skills/telegram-automation/templates/spam_live_template.py
Normal file
@@ -0,0 +1,144 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user