taslim19 commited on
Commit
abc89fd
·
1 Parent(s): 27bdbc9

Update devtools.py: add case-insensitive and flexible command triggers for userbot devtools

Browse files
DragMusic/plugins/kuri/check_username.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Plugin to check Telegram username availability using the userbot.
3
+ Command: /checkusername <username>
4
+ """
5
+
6
+ from pyrogram import Client, filters
7
+ from pyrogram.types import Message
8
+
9
+ @Client.on_message(filters.command(["checkusername", "checkuser", "username"], prefixes=["/", "!"]) & filters.me)
10
+ async def check_username_handler(client: Client, message: Message):
11
+ if len(message.command) < 2:
12
+ await message.reply_text("Please provide a username to check. Usage: /checkusername <username>")
13
+ return
14
+ username = message.command[1].strip().lower().replace("@", "")
15
+ try:
16
+ available = await client.check_username(username)
17
+ if available:
18
+ await message.reply_text(f"✅ The username '@{username}' is available!")
19
+ else:
20
+ await message.reply_text(f"❌ The username '@{username}' is already taken.")
21
+ except Exception as e:
22
+ await message.reply_text(f"⚠️ Error checking username: {e}")
DragMusic/plugins/kuri/devtools.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Devtools plugin for userbot-only (filters.me) development and admin commands.
3
+ Provides /sh, /xsh for shell commands and /eval, /e for Python code evaluation.
4
+ Also triggers if the message starts with 'sh', 'xsh', 'e', or 'eval' (with or without a slash or exclamation mark, and with any capitalization).
5
+ Restricted to OWNER_ID only.
6
+ """
7
+
8
+ import asyncio
9
+ import re
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+ from DragMusic import userbot
13
+ from config import OWNER_ID
14
+
15
+ # Helper to check if the message is from OWNER_ID
16
+ async def is_owner(message: Message):
17
+ return message.from_user and message.from_user.id == OWNER_ID
18
+
19
+ # Regex filters for command matching (case-insensitive)
20
+ sh_filter = filters.me & filters.regex(r"^[!/]*x?sh( |$)", re.IGNORECASE)
21
+ eval_filter = filters.me & filters.regex(r"^[!/]*(e|eval)( |$)", re.IGNORECASE)
22
+
23
+ @userbot.on_message(sh_filter)
24
+ async def shell_command_handler(client, message: Message):
25
+ if not await is_owner(message):
26
+ return
27
+ parts = message.text.split(None, 1)
28
+ if len(parts) < 2:
29
+ await message.reply_text("Usage: sh <command>")
30
+ return
31
+ cmd = parts[1]
32
+ try:
33
+ process = await asyncio.create_subprocess_shell(
34
+ cmd,
35
+ stdout=asyncio.subprocess.PIPE,
36
+ stderr=asyncio.subprocess.PIPE,
37
+ )
38
+ stdout, stderr = await process.communicate()
39
+ output = (stdout + stderr).decode().strip()
40
+ if not output:
41
+ output = "No output."
42
+ # Telegram message limit
43
+ if len(output) > 4096:
44
+ for i in range(0, len(output), 4096):
45
+ await message.reply_text(f"<code>{output[i:i+4096]}</code>")
46
+ else:
47
+ await message.reply_text(f"<code>{output}</code>")
48
+ except Exception as e:
49
+ await message.reply_text(f"Error: <code>{e}</code>")
50
+
51
+ @userbot.on_message(eval_filter)
52
+ async def eval_handler(client, message: Message):
53
+ if not await is_owner(message):
54
+ return
55
+ parts = message.text.split(None, 1)
56
+ if len(parts) < 2:
57
+ await message.reply_text("Usage: eval <python code>")
58
+ return
59
+ code = parts[1]
60
+ try:
61
+ env = {
62
+ "client": client,
63
+ "message": message,
64
+ "userbot": userbot,
65
+ "asyncio": asyncio,
66
+ }
67
+ exec(
68
+ f"async def __aexec(client, message):\n"
69
+ + "\n".join(f" {l}" for l in code.split("\n")),
70
+ env,
71
+ )
72
+ result = await env["__aexec"](client, message)
73
+ if result is not None:
74
+ await message.reply_text(f"<code>{result}</code>")
75
+ except Exception as e:
76
+ await message.reply_text(f"Error: <code>{e}</code>")
77
+
78
+ # Add more dev/admin commands below as needed
DragMusic/plugins/tools/afk.py CHANGED
@@ -9,7 +9,9 @@ from DragMusic.Mongo.afkdb import add_afk, is_afk, remove_afk
9
 
10
 
11
 
12
- @app.on_message(filters.command(["afk", "brb"], prefixes=["/", "!"]) | filters.regex(r"^(afk|brb)(?:\s+(.+))?$"))
 
 
13
  async def active_afk(_, message: Message):
14
  if message.sender_chat:
15
  return
@@ -63,6 +65,7 @@ async def active_afk(_, message: Message):
63
  return
64
 
65
  # Handle both command format and plain text format
 
66
  if message.command:
67
  # Command format: /afk or /afk reason
68
  if len(message.command) == 1 and not message.reply_to_message:
@@ -99,6 +102,15 @@ async def active_afk(_, message: Message):
99
  "reason": _reason,
100
  }
101
 
 
 
 
 
 
 
 
 
 
102
  # Handle reply to media (works for both command and plain text)
103
  if message.reply_to_message:
104
  if message.reply_to_message.animation:
 
9
 
10
 
11
 
12
+ @app.on_message(
13
+ filters.command(["afk", "brb", "Afk", "Brb"], prefixes=["/", "!","."]) |
14
+ filters.regex(r"^(afk|brb|Afk|Brb)(?:\s+(.+))?$"))
15
  async def active_afk(_, message: Message):
16
  if message.sender_chat:
17
  return
 
65
  return
66
 
67
  # Handle both command format and plain text format
68
+ details = None # Ensure details is always defined
69
  if message.command:
70
  # Command format: /afk or /afk reason
71
  if len(message.command) == 1 and not message.reply_to_message:
 
102
  "reason": _reason,
103
  }
104
 
105
+ # Fallback if details is still None (shouldn't happen, but just in case)
106
+ if details is None:
107
+ details = {
108
+ "type": "text",
109
+ "time": time.time(),
110
+ "data": None,
111
+ "reason": None,
112
+ }
113
+
114
  # Handle reply to media (works for both command and plain text)
115
  if message.reply_to_message:
116
  if message.reply_to_message.animation: