userbot.py 8.5 KB

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