userbot.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. """
  2. CREDITS:
  3. MOST OF THE CODE IN THIS FILE IS WRITTEN BY @Pokurt.
  4. SOURCE:
  5. https://github.com/pokurt/Nana-Remix/blob/master/nana/plugins/devs.py
  6. """
  7. import os
  8. import re
  9. import subprocess
  10. import sys
  11. import traceback
  12. from asyncio import Lock, create_task
  13. from html import escape
  14. from inspect import getfullargspec
  15. from io import StringIO
  16. from pyrogram import filters
  17. from pyrogram.errors import MessageNotModified
  18. from pyrogram.types import Message, ReplyKeyboardMarkup
  19. from wbb import app # don't remove
  20. from wbb import SUDOERS, USERBOT_PREFIX, app2, arq
  21. # Eval and Sh module from nana-remix
  22. m = None
  23. p = print
  24. r = None
  25. arq = arq
  26. arrow = lambda x: x.text + "\n`→`"
  27. TASKS_LOCK = Lock()
  28. tasks = {}
  29. async def aexec(code, client, message):
  30. exec(
  31. "async def __aexec(client, message): "
  32. + "".join(f"\n {a}" for a in code.split("\n"))
  33. )
  34. return await locals()["__aexec"](client, message)
  35. async def eor(msg: Message, **kwargs):
  36. func = msg.edit_text if msg.from_user.is_self else msg.reply
  37. spec = getfullargspec(func.__wrapped__).args
  38. return await func(
  39. **{k: v for k, v in kwargs.items() if k in spec}
  40. )
  41. async def add_task(taskFunc, task_id, *args, **kwargs):
  42. global tasks
  43. task = create_task(taskFunc(*args, **kwargs))
  44. tasks[task_id] = task
  45. return task
  46. async def rm_task(task_id=None):
  47. global tasks
  48. async with TASKS_LOCK:
  49. for key, value in list(tasks.items()):
  50. if value.done() or value.cancelled():
  51. del tasks[key]
  52. if task_id:
  53. if task_id in tasks:
  54. if not tasks[task_id].done():
  55. tasks[task_id].cancel()
  56. del tasks[task_id]
  57. @app2.on_message(
  58. filters.user(SUDOERS)
  59. & ~filters.forwarded
  60. & ~filters.via_bot
  61. & filters.command("cancelTask", prefixes=USERBOT_PREFIX)
  62. )
  63. async def task_cancel(_, message: Message):
  64. global tasks
  65. m = message
  66. r = m.reply_to_message
  67. if len(m.text.split()) == 2:
  68. mid = int(m.text.split(None, 1)[1])
  69. else:
  70. mid = r.message_id if r else None
  71. if not mid or not tasks:
  72. return await m.delete()
  73. if mid not in tasks:
  74. return await m.delete()
  75. await rm_task(mid)
  76. await eor(message, text=f"{arrow(m)} Task cancelled")
  77. @app2.on_message(
  78. filters.user(SUDOERS)
  79. & ~filters.forwarded
  80. & ~filters.via_bot
  81. & filters.command("lsTasks", prefixes=USERBOT_PREFIX)
  82. )
  83. async def task_list(_, message: Message):
  84. await rm_task()
  85. if not tasks:
  86. return await eor(
  87. message,
  88. text=f"{arrow(message)} No tasks pending",
  89. )
  90. ls = "\n ".join([str(i) for i in tasks.keys()])
  91. await eor(message, text=f"{arrow(message)} {ls}")
  92. @app2.on_message(
  93. filters.user(SUDOERS)
  94. & ~filters.forwarded
  95. & ~filters.via_bot
  96. & filters.command("eval", prefixes=USERBOT_PREFIX)
  97. )
  98. async def executor(client, message: Message):
  99. global m, p, r, tasks
  100. try:
  101. cmd = message.text.split(" ", maxsplit=1)[1]
  102. except IndexError:
  103. return await message.delete()
  104. if message.chat.type == "channel":
  105. return
  106. m = message
  107. p = print
  108. # To prevent keyboard input attacks
  109. if m.reply_to_message:
  110. r = m.reply_to_message
  111. if r.reply_markup:
  112. if isinstance(r.reply_markup, ReplyKeyboardMarkup):
  113. return await eor(m, text="INSECURE!")
  114. old_stderr = sys.stderr
  115. old_stdout = sys.stdout
  116. redirected_output = sys.stdout = StringIO()
  117. redirected_error = sys.stderr = StringIO()
  118. stdout, stderr, exc = None, None, None
  119. try:
  120. task = await add_task(
  121. aexec,
  122. m.message_id,
  123. cmd,
  124. client,
  125. message,
  126. )
  127. await task
  128. except Exception as e:
  129. exc = str(e)
  130. await rm_task()
  131. stdout = redirected_output.getvalue()
  132. stderr = redirected_error.getvalue()
  133. sys.stdout = old_stdout
  134. sys.stderr = old_stderr
  135. evaluation = ""
  136. if exc:
  137. evaluation = exc
  138. elif stderr:
  139. evaluation = stderr
  140. elif stdout:
  141. evaluation = stdout
  142. # Save the last stdout in globals,
  143. # Can use the it in next calls
  144. globals()["lstdout"] = stdout
  145. else:
  146. evaluation = "Success"
  147. final_output = f"**→**\n`{escape(evaluation.strip())}`"
  148. if len(final_output) > 4096:
  149. filename = "output.txt"
  150. with open(filename, "w+", encoding="utf8") as out_file:
  151. out_file.write(str(evaluation.strip()))
  152. await message.reply_document(
  153. document=filename,
  154. caption="`→`\n **Attached Document**",
  155. quote=False,
  156. )
  157. os.remove(filename)
  158. else:
  159. mid = message.message_id
  160. # Edit the output if input is edited
  161. if message.edit_date:
  162. async for m in app2.iter_history(message.chat.id):
  163. # If no replies found, reply
  164. if m.message_id == mid:
  165. break
  166. if (
  167. not m.from_user
  168. or not m.text
  169. or not m.reply_to_message
  170. ):
  171. continue
  172. if m.reply_to_message.message_id == mid:
  173. if m.from_user.id == message.from_user.id:
  174. if "→" in m.text:
  175. try:
  176. return await m.edit(final_output)
  177. except MessageNotModified:
  178. return
  179. await message.reply(final_output, quote=True)
  180. @app2.on_message(
  181. filters.user(SUDOERS)
  182. & ~filters.forwarded
  183. & ~filters.via_bot
  184. & ~filters.edited
  185. & filters.command("sh", prefixes=USERBOT_PREFIX),
  186. )
  187. async def shellrunner(client, message: Message):
  188. if len(message.command) < 2:
  189. return await eor(message, text="**Usage:**\n/sh git pull")
  190. if message.reply_to_message:
  191. r = message.reply_to_message
  192. if r.reply_markup:
  193. if isinstance(r.reply_markup, ReplyKeyboardMarkup):
  194. return await eor(message, text="INSECURE!")
  195. text = message.text.split(None, 1)[1]
  196. if "\n" in text:
  197. code = text.split("\n")
  198. output = ""
  199. for x in code:
  200. shell = re.split(
  201. """ (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x
  202. )
  203. try:
  204. process = subprocess.Popen(
  205. shell,
  206. stdout=subprocess.PIPE,
  207. stderr=subprocess.PIPE,
  208. )
  209. except Exception as err:
  210. print(err)
  211. await eor(
  212. message,
  213. text=f"**INPUT:**\n```{escape(text)}```\n\n**ERROR:**\n```{escape(err)}```",
  214. )
  215. output += f"**{code}**\n"
  216. output += process.stdout.read()[:-1].decode("utf-8")
  217. output += "\n"
  218. else:
  219. shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text)
  220. for a in range(len(shell)):
  221. shell[a] = shell[a].replace('"', "")
  222. try:
  223. process = subprocess.Popen(
  224. shell,
  225. stdout=subprocess.PIPE,
  226. stderr=subprocess.PIPE,
  227. )
  228. except Exception as err:
  229. print(err)
  230. exc_type, exc_obj, exc_tb = sys.exc_info()
  231. errors = traceback.format_exception(
  232. etype=exc_type,
  233. value=exc_obj,
  234. tb=exc_tb,
  235. )
  236. return await eor(
  237. message,
  238. text=f"**INPUT:**\n```{escape(text)}```\n\n**ERROR:**\n```{''.join(errors)}```",
  239. )
  240. output = process.stdout.read()[:-1].decode("utf-8")
  241. if str(output) == "\n":
  242. output = None
  243. if output:
  244. if len(output) > 4096:
  245. with open("output.txt", "w+") as file:
  246. file.write(output)
  247. await app2.send_document(
  248. message.chat.id,
  249. "output.txt",
  250. reply_to_message_id=message.message_id,
  251. caption=escape(text),
  252. )
  253. return os.remove("output.txt")
  254. await eor(
  255. message,
  256. text=f"**INPUT:**\n```{escape(text)}```\n\n**OUTPUT:**\n```{escape(output)}```",
  257. )
  258. else:
  259. await eor(
  260. message,
  261. text=f"**INPUT:**\n```{escape(text)}```\n\n**OUTPUT: **\n`No output`",
  262. )