userbot.py 8.1 KB

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