UNUSUALxd commited on
Commit
e9958b0
Β·
verified Β·
1 Parent(s): 284d686

Update bot/handlers.py

Browse files
Files changed (1) hide show
  1. bot/handlers.py +68 -15
bot/handlers.py CHANGED
@@ -1,10 +1,10 @@
1
  import os
2
  import asyncio
3
  import random
4
- import re # ⚑ Added for error extraction
5
  import datetime
6
  from pyrogram import filters, enums
7
- from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
8
  from pyrogram.errors import MessageNotModified
9
  from bot.client import bot
10
  from bot.state import state
@@ -13,12 +13,12 @@ from bot.scheduler import scheduler, schedule_next, get_pkt_time
13
  from utils.logger import log, get_recent_logs
14
  from bot.sniper import fleet
15
  from bot.proxy_manager import proxy_mgr
16
- from pyrogram.types import LinkPreviewOptions
17
 
18
  from bot.ui.keyboards import (
19
  markup_cancel, markup_main, markup_settings,
20
  markup_claim_settings, markup_fragment_settings,
21
- markup_channel_accounts, markup_db_manager, markup_confirm
 
22
  )
23
  from bot.ui.text_views import (
24
  text_main, get_settings_text, text_dashboard,
@@ -61,7 +61,8 @@ def is_admin(_, __, update):
61
 
62
  admin_filter = filters.create(is_admin)
63
 
64
- def get_account_by_index(idx: int): return next((a for a in state["account_pool"] if a.index == idx), None)
 
65
 
66
  async def input_timeout(user_id: int, expected_state: str, msg):
67
  await asyncio.sleep(60)
@@ -209,7 +210,7 @@ async def cmd_addsnipe(client, message):
209
  try: await message.react("⚑")
210
  except Exception: pass
211
  else:
212
- await message.reply_text(f"⚠️ <b>@{target}</b> is already in the snipe queue.", parse_mode=enums.ParseMode.HTML)
213
 
214
  @bot.on_message(filters.command("rmsnipe") & admin_filter)
215
  async def cmd_rmsnipe(client, message):
@@ -311,10 +312,11 @@ async def cmd_fragcheck(client, message):
311
 
312
  @bot.on_message(filters.command("unfrag") & admin_filter)
313
  async def cmd_unfrag(client, message):
 
314
  if len(message.command) < 2:
315
  state["waiting_for_input"][user_id] = "unfrag_input"
316
  msg = await message.reply_text("Send the username to remove from Fragment Scraper:", reply_markup=markup_cancel(), parse_mode=enums.ParseMode.HTML)
317
- asyncio.create_task(input_timeout(message.from_user.id, "unfrag_input", msg))
318
  return
319
 
320
  target = message.command[1].replace("@", "").strip().lower()
@@ -338,7 +340,6 @@ async def cmd_proxy_mapping_dashboard(client, message):
338
  if not state.get("account_pool"):
339
  return await message.reply_text("❌ System error: Account pool is empty.")
340
 
341
- # ⚑ UI UPGRADE: Wrapped in Expandable Blockquote to save screen space
342
  dashboard_lines = [
343
  "<b>πŸ›‘οΈ Cluster Network Egress Mapping</b>\n",
344
  f"<b>Proxy Engine:</b> {'βœ… ACTIVE' if proxy_mgr.is_enabled else '❌ DISABLED'}",
@@ -523,7 +524,6 @@ async def handle_media_and_text_input(client, message):
523
  state["waiting_for_input"][user_id] = None
524
  return
525
 
526
- # ⚑ ENGINE UPGRADE: Fully Automated Secure Transfer Initiation
527
  if waiting_for and waiting_for.startswith("trans_target|"):
528
  _, idx_str, chat_id_str = waiting_for.split("|")
529
  target = message.text.strip()
@@ -551,7 +551,6 @@ async def handle_media_and_text_input(client, message):
551
  else:
552
  await msg.edit_text("⏳ <b>Telegram Security Lock:</b> Session must be active for 24 hours before transferring ownership.", parse_mode=enums.ParseMode.HTML)
553
  elif "PASSWORD_REQUIRED" in result or "PASSWORD_HASH_INVALID" in result:
554
- # Fallback to manual password input if the user changed the default 2FA password
555
  state["waiting_for_input"][user_id] = f"trans_2fa|{idx_str}|{chat_id_str}|{target}"
556
  await msg.edit_text(f"πŸ”’ <b>2FA Password Required</b>\n\nAccount #{idx_str} has a custom Two-Step Verification password.\nPlease send the password:", reply_markup=markup_cancel(), parse_mode=enums.ParseMode.HTML)
557
  asyncio.create_task(input_timeout(user_id, state["waiting_for_input"][user_id], msg))
@@ -576,7 +575,7 @@ async def handle_media_and_text_input(client, message):
576
  if success:
577
  await msg.edit_text(f"βœ… <b>Ownership transferred to {target}.</b>", parse_mode=enums.ParseMode.HTML)
578
  else:
579
- await msg.edit_text(f"❌ Transfer Failed: <b>{result}</b>", parse_mode=enums.ParseMode.HTML)
580
  return
581
 
582
  if waiting_for == "watchdog_add":
@@ -642,9 +641,64 @@ async def callback_router(client, callback_query):
642
  data = callback_query.data
643
  user_id = callback_query.from_user.id
644
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  if data == "toggle_proxy":
646
  if len(proxy_mgr.proxies) == 0:
647
- return await callback_query.answer("⚠️️ No proxies available! Check WEBSHARE_API_KEY.", show_alert=True)
648
 
649
  proxy_mgr.is_enabled = not proxy_mgr.is_enabled
650
  proxy_text = "🟒 Proxy: ON" if proxy_mgr.is_enabled else "πŸ”΄ Proxy: OFF"
@@ -701,7 +755,7 @@ async def callback_router(client, callback_query):
701
 
702
  text = f"πŸ” <b>@{target}</b>\n\n<blockquote>Snipe: {in_snipe}\nCheck: {in_check}\nWatchdog: {in_watchdog}\nFragment: {in_frag}\nUnavailable DB: {in_unavail}</blockquote>"
703
  buttons = []
704
- if target in state["snipe_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈ Remove from Snipe", callback_data=f"rm_q|s|{target}", style=enums.ButtonStyle.DANGER)])
705
  if target in state["watchdog_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈ Remove from Watchdog", callback_data=f"rm_q|w|{target}", style=enums.ButtonStyle.DANGER)])
706
  if target in state["fragcheck_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈ Remove from Fragment", callback_data=f"rm_q|f|{target}", style=enums.ButtonStyle.DANGER)])
707
  buttons.append([InlineKeyboardButton("❌ Dismiss", callback_data="cancel_input", style=enums.ButtonStyle.DEFAULT)])
@@ -786,7 +840,6 @@ async def callback_router(client, callback_query):
786
  markup = InlineKeyboardMarkup([[InlineKeyboardButton("πŸ“Š Live Dashboard", callback_data="start_live_dash", style=enums.ButtonStyle.PRIMARY)], [InlineKeyboardButton("⬅️ Back", callback_data="main_panel", style=enums.ButtonStyle.PRIMARY)]])
787
  await callback_query.message.edit_text(text_dashboard(), reply_markup=markup, parse_mode=enums.ParseMode.HTML)
788
 
789
- # ⚑ UI UPGRADE: Expandable Blockquote
790
  elif data in ["view_logs", "refresh_logs"]:
791
  logs = get_recent_logs(20)
792
  log_text = "\n".join(logs) if logs else "No logs yet."
@@ -1370,7 +1423,7 @@ async def callback_router(client, callback_query):
1370
  state["unavailable_set"].discard(username)
1371
  if hasattr(db, "remove_unavailable"): await db.remove_unavailable(username)
1372
  await purge_target_from_queues(username)
1373
- await callback_query.message.edit_text(f"πŸ—‘οΈοΈ Channel deleted. <b>@{username}</b> released and purged from active queues.", parse_mode=enums.ParseMode.HTML)
1374
  except Exception as e:
1375
  if "FROZEN" in str(e).upper(): account.status = "frozen"
1376
  await callback_query.message.edit_text(f"❌ Undo Failed: <b>{e}</b>", parse_mode=enums.ParseMode.HTML)
 
1
  import os
2
  import asyncio
3
  import random
4
+ import re
5
  import datetime
6
  from pyrogram import filters, enums
7
+ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, LinkPreviewOptions
8
  from pyrogram.errors import MessageNotModified
9
  from bot.client import bot
10
  from bot.state import state
 
13
  from utils.logger import log, get_recent_logs
14
  from bot.sniper import fleet
15
  from bot.proxy_manager import proxy_mgr
 
16
 
17
  from bot.ui.keyboards import (
18
  markup_cancel, markup_main, markup_settings,
19
  markup_claim_settings, markup_fragment_settings,
20
+ markup_channel_accounts, markup_db_manager, markup_confirm,
21
+ markup_bot_query
22
  )
23
  from bot.ui.text_views import (
24
  text_main, get_settings_text, text_dashboard,
 
61
 
62
  admin_filter = filters.create(is_admin)
63
 
64
+ def get_account_by_index(idx: int):
65
+ return next((a for a in state["account_pool"] if a.index == idx), None)
66
 
67
  async def input_timeout(user_id: int, expected_state: str, msg):
68
  await asyncio.sleep(60)
 
210
  try: await message.react("⚑")
211
  except Exception: pass
212
  else:
213
+ await message.reply_text(f"⚠️️ <b>@{target}</b> is already in the snipe queue.", parse_mode=enums.ParseMode.HTML)
214
 
215
  @bot.on_message(filters.command("rmsnipe") & admin_filter)
216
  async def cmd_rmsnipe(client, message):
 
312
 
313
  @bot.on_message(filters.command("unfrag") & admin_filter)
314
  async def cmd_unfrag(client, message):
315
+ user_id = message.from_user.id
316
  if len(message.command) < 2:
317
  state["waiting_for_input"][user_id] = "unfrag_input"
318
  msg = await message.reply_text("Send the username to remove from Fragment Scraper:", reply_markup=markup_cancel(), parse_mode=enums.ParseMode.HTML)
319
+ asyncio.create_task(input_timeout(user_id, "unfrag_input", msg))
320
  return
321
 
322
  target = message.command[1].replace("@", "").strip().lower()
 
340
  if not state.get("account_pool"):
341
  return await message.reply_text("❌ System error: Account pool is empty.")
342
 
 
343
  dashboard_lines = [
344
  "<b>πŸ›‘οΈ Cluster Network Egress Mapping</b>\n",
345
  f"<b>Proxy Engine:</b> {'βœ… ACTIVE' if proxy_mgr.is_enabled else '❌ DISABLED'}",
 
524
  state["waiting_for_input"][user_id] = None
525
  return
526
 
 
527
  if waiting_for and waiting_for.startswith("trans_target|"):
528
  _, idx_str, chat_id_str = waiting_for.split("|")
529
  target = message.text.strip()
 
551
  else:
552
  await msg.edit_text("⏳ <b>Telegram Security Lock:</b> Session must be active for 24 hours before transferring ownership.", parse_mode=enums.ParseMode.HTML)
553
  elif "PASSWORD_REQUIRED" in result or "PASSWORD_HASH_INVALID" in result:
 
554
  state["waiting_for_input"][user_id] = f"trans_2fa|{idx_str}|{chat_id_str}|{target}"
555
  await msg.edit_text(f"πŸ”’ <b>2FA Password Required</b>\n\nAccount #{idx_str} has a custom Two-Step Verification password.\nPlease send the password:", reply_markup=markup_cancel(), parse_mode=enums.ParseMode.HTML)
556
  asyncio.create_task(input_timeout(user_id, state["waiting_for_input"][user_id], msg))
 
575
  if success:
576
  await msg.edit_text(f"βœ… <b>Ownership transferred to {target}.</b>", parse_mode=enums.ParseMode.HTML)
577
  else:
578
+ await msg.edit_text(f"❌ Transfer Failed: <b>{result}</b>", parse_mode=enums.ParseMode.HTML)
579
  return
580
 
581
  if waiting_for == "watchdog_add":
 
641
  data = callback_query.data
642
  user_id = callback_query.from_user.id
643
  try:
644
+ if data == "ignore":
645
+ return await callback_query.answer()
646
+
647
+ if data == "menu_bot_query":
648
+ await callback_query.message.edit_text(
649
+ "<b>πŸͺ™ Account Bot Query Menu</b>\nSelect an account to send <code>/coins</code> and fetch its balance:",
650
+ reply_markup=markup_bot_query(),
651
+ parse_mode=enums.ParseMode.HTML
652
+ )
653
+ return
654
+
655
+ if data.startswith("query_coins|"):
656
+ acc_idx = int(data.split("|")[1])
657
+ acc = get_account_by_index(acc_idx)
658
+ if not acc:
659
+ return await callback_query.answer("Account unavailable.", show_alert=True)
660
+
661
+ await callback_query.message.edit_text(f"⏳ Sending <code>/coins</code> from Account #{acc_idx}...", parse_mode=enums.ParseMode.HTML)
662
+
663
+ from bot.checker import send_and_await_reply
664
+ target_bot = "@info_id_bot"
665
+ reply = await send_and_await_reply(acc, target_bot, "/coins", timeout=8)
666
+
667
+ text = (
668
+ f"<b>πŸͺ™ Balance Report (Acc #{acc_idx})</b>\n"
669
+ f"Target Bot: <code>{target_bot}</code>\n\n"
670
+ f"<blockquote expandable>{reply}</blockquote>"
671
+ )
672
+ buttons = [
673
+ [InlineKeyboardButton("πŸ”„ Re-check", callback_data=f"query_coins|{acc_idx}", style=enums.ButtonStyle.PRIMARY)],
674
+ [InlineKeyboardButton("⬅️ Back", callback_data="menu_bot_query", style=enums.ButtonStyle.PRIMARY)]
675
+ ]
676
+ await callback_query.message.edit_text(text, reply_markup=InlineKeyboardMarkup(buttons), parse_mode=enums.ParseMode.HTML)
677
+ return
678
+
679
+ if data == "query_coins_all":
680
+ await callback_query.message.edit_text("⏳ Querying <code>/coins</code> across all active accounts...", parse_mode=enums.ParseMode.HTML)
681
+
682
+ from bot.checker import send_and_await_reply
683
+ target_bot = "@info_id_bot"
684
+ active_accounts = [a for a in state["account_pool"] if a.status in ["active", "paused"] and a.client]
685
+
686
+ results = []
687
+ for acc in active_accounts:
688
+ masked = f"****{acc.phone[-4:]}" if len(acc.phone) >= 4 else acc.phone
689
+ res = await send_and_await_reply(acc, target_bot, "/coins", timeout=6)
690
+ first_line = res.split("\n")[0] if res else "No response"
691
+ results.append(f"<b>Acc #{acc.index} ({masked}):</b>\n{first_line}")
692
+
693
+ summary = "\n\n".join(results) if results else "No active accounts found."
694
+ text = f"<b>πŸͺ™ Fleet Balance Summary</b>\n\n<blockquote expandable>{summary}</blockquote>"
695
+ buttons = [[InlineKeyboardButton("⬅️ Back", callback_data="menu_bot_query", style=enums.ButtonStyle.PRIMARY)]]
696
+ await callback_query.message.edit_text(text, reply_markup=InlineKeyboardMarkup(buttons), parse_mode=enums.ParseMode.HTML)
697
+ return
698
+
699
  if data == "toggle_proxy":
700
  if len(proxy_mgr.proxies) == 0:
701
+ return await callback_query.answer("⚠️ No proxies available! Check WEBSHARE_API_KEY.", show_alert=True)
702
 
703
  proxy_mgr.is_enabled = not proxy_mgr.is_enabled
704
  proxy_text = "🟒 Proxy: ON" if proxy_mgr.is_enabled else "πŸ”΄ Proxy: OFF"
 
755
 
756
  text = f"πŸ” <b>@{target}</b>\n\n<blockquote>Snipe: {in_snipe}\nCheck: {in_check}\nWatchdog: {in_watchdog}\nFragment: {in_frag}\nUnavailable DB: {in_unavail}</blockquote>"
757
  buttons = []
758
+ if target in state["snipe_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈοΈ Remove from Snipe", callback_data=f"rm_q|s|{target}", style=enums.ButtonStyle.DANGER)])
759
  if target in state["watchdog_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈ Remove from Watchdog", callback_data=f"rm_q|w|{target}", style=enums.ButtonStyle.DANGER)])
760
  if target in state["fragcheck_queue"]: buttons.append([InlineKeyboardButton("πŸ—‘οΈ Remove from Fragment", callback_data=f"rm_q|f|{target}", style=enums.ButtonStyle.DANGER)])
761
  buttons.append([InlineKeyboardButton("❌ Dismiss", callback_data="cancel_input", style=enums.ButtonStyle.DEFAULT)])
 
840
  markup = InlineKeyboardMarkup([[InlineKeyboardButton("πŸ“Š Live Dashboard", callback_data="start_live_dash", style=enums.ButtonStyle.PRIMARY)], [InlineKeyboardButton("⬅️ Back", callback_data="main_panel", style=enums.ButtonStyle.PRIMARY)]])
841
  await callback_query.message.edit_text(text_dashboard(), reply_markup=markup, parse_mode=enums.ParseMode.HTML)
842
 
 
843
  elif data in ["view_logs", "refresh_logs"]:
844
  logs = get_recent_logs(20)
845
  log_text = "\n".join(logs) if logs else "No logs yet."
 
1423
  state["unavailable_set"].discard(username)
1424
  if hasattr(db, "remove_unavailable"): await db.remove_unavailable(username)
1425
  await purge_target_from_queues(username)
1426
+ await callback_query.message.edit_text(f"πŸ—‘οΈ Channel deleted. <b>@{username}</b> released and purged from active queues.", parse_mode=enums.ParseMode.HTML)
1427
  except Exception as e:
1428
  if "FROZEN" in str(e).upper(): account.status = "frozen"
1429
  await callback_query.message.edit_text(f"❌ Undo Failed: <b>{e}</b>", parse_mode=enums.ParseMode.HTML)