userbot.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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 html import escape
  13. from io import StringIO
  14. from pyrogram import filters
  15. from pyrogram.enums import ChatType
  16. from pyrogram.errors import MessageNotModified
  17. from pyrogram.types import Message, ReplyKeyboardMarkup
  18. from wbb import app2 # don't remove
  19. from wbb import SUDOERS, USERBOT_PREFIX, eor
  20. from wbb.core.tasks import add_task, rm_task
  21. # Eval and Sh module from nana-remix
  22. m = None
  23. p = print
  24. r = None
  25. arrow = lambda x: (x.text if isinstance(x, Message) else "") + "\n`→`"
  26. async def aexec(code, client, message):
  27. exec(
  28. "async def __aexec(client, message): "
  29. + "".join(f"\n {a}" for a in code.split("\n"))
  30. )
  31. return await locals()["__aexec"](client, message)
  32. async def iter_edit(message: Message, text: str):
  33. async for m in app2.get_chat_history(message.chat.id):
  34. # If no replies found, reply
  35. if m.id == message.id:
  36. return 0
  37. if not m.from_user or not m.text or not m.reply_to_message:
  38. continue
  39. if (
  40. (m.reply_to_message.id == message.id)
  41. and (m.from_user.id == message.from_user.id)
  42. and ("→" in m.text)
  43. ):
  44. try:
  45. return await m.edit(text)
  46. except MessageNotModified:
  47. return
  48. @app2.on_message(
  49. SUDOERS
  50. & ~filters.forwarded
  51. & ~filters.via_bot
  52. & filters.command("eval", prefixes=USERBOT_PREFIX)
  53. )
  54. async def executor(client, message: Message):
  55. global m, p, r
  56. if not message.from_user or message.from_user.id not in SUDOERS:
  57. return
  58. try:
  59. cmd = message.text.split(" ", maxsplit=1)[1]
  60. except IndexError:
  61. return await message.delete()
  62. if message.chat.type == ChatType.CHANNEL:
  63. return
  64. m = message
  65. p = print
  66. # To prevent keyboard input attacks
  67. if m.reply_to_message:
  68. r = m.reply_to_message
  69. if r.reply_markup and isinstance(r.reply_markup, ReplyKeyboardMarkup):
  70. return await eor(m, text="INSECURE!")
  71. status = None
  72. old_stderr = sys.stderr
  73. old_stdout = sys.stdout
  74. redirected_output = sys.stdout = StringIO()
  75. redirected_error = sys.stderr = StringIO()
  76. stdout, stderr, exc = None, None, None
  77. try:
  78. task, task_id = await add_task(
  79. aexec,
  80. "Eval",
  81. cmd,
  82. client,
  83. m,
  84. )
  85. text = f"{arrow('')} Pending Task `{task_id}`"
  86. if not message.edit_date:
  87. status = await m.reply(text, quote=True)
  88. await task
  89. except Exception as e:
  90. e = traceback.format_exc()
  91. print(e)
  92. exc = e.splitlines()[-1]
  93. await rm_task()
  94. stdout = redirected_output.getvalue()
  95. stderr = redirected_error.getvalue()
  96. sys.stdout = old_stdout
  97. sys.stderr = old_stderr
  98. evaluation = ""
  99. if exc:
  100. evaluation = exc
  101. elif stderr:
  102. evaluation = stderr
  103. elif stdout:
  104. evaluation = stdout
  105. else:
  106. evaluation = "Success"
  107. final_output = f"**→**\n`{escape(evaluation.strip())}`"
  108. if len(final_output) > 4096:
  109. filename = "output.txt"
  110. with open(filename, "w+", encoding="utf8") as out_file:
  111. out_file.write(str(evaluation.strip()))
  112. await message.reply_document(
  113. document=filename,
  114. caption="`→`\n **Attached Document**",
  115. quote=False,
  116. )
  117. os.remove(filename)
  118. if status:
  119. await status.delete()
  120. return
  121. # Edit the output if input is edited
  122. if message.edit_date:
  123. status_ = await iter_edit(message, final_output)
  124. if status_ == 0:
  125. return await message.reply(final_output, quote=True)
  126. return
  127. if not status.from_user:
  128. status = await app2.get_messages(status.chat.id, status.id)
  129. await eor(status, text=final_output, quote=True)
  130. @app2.on_message(
  131. SUDOERS
  132. & ~filters.forwarded
  133. & ~filters.via_bot
  134. & filters.command("sh", prefixes=USERBOT_PREFIX),
  135. )
  136. async def shellrunner(_, message: Message):
  137. if not message.from_user or message.from_user.id not in SUDOERS:
  138. return
  139. if len(message.command) < 2:
  140. return await eor(message, text="**Usage:**\n/sh git pull")
  141. if message.reply_to_message:
  142. r = message.reply_to_message
  143. if r.reply_markup and isinstance(
  144. r.reply_markup,
  145. ReplyKeyboardMarkup,
  146. ):
  147. return await eor(message, text="INSECURE!")
  148. text = message.text.split(None, 1)[1]
  149. if "\n" in text:
  150. code = text.split("\n")
  151. output = ""
  152. for x in code:
  153. shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x)
  154. try:
  155. process = subprocess.Popen(
  156. shell,
  157. stdout=subprocess.PIPE,
  158. stderr=subprocess.PIPE,
  159. )
  160. except Exception as err:
  161. print(err)
  162. await eor(
  163. message,
  164. text=f"**INPUT:**\n```{escape(text)}```\n\n**ERROR:**\n```{escape(err)}```",
  165. )
  166. output += f"**{code}**\n"
  167. output += process.stdout.read()[:-1].decode("utf-8")
  168. output += "\n"
  169. else:
  170. shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text)
  171. for a, _ in enumerate(shell):
  172. shell[a] = shell[a].replace('"', "")
  173. try:
  174. process = subprocess.Popen(
  175. shell,
  176. stdout=subprocess.PIPE,
  177. stderr=subprocess.PIPE,
  178. )
  179. except Exception as err:
  180. print(err)
  181. errors = traceback.format_exc()
  182. return await eor(
  183. message,
  184. text=f"**INPUT:**\n```{escape(text)}```\n\n**ERROR:**\n```{''.join(errors)}```",
  185. )
  186. output = process.stdout.read()[:-1].decode("utf-8")
  187. if str(output) == "\n":
  188. output = None
  189. if output:
  190. if len(output) > 4096:
  191. with open("output.txt", "w+") as file:
  192. file.write(output)
  193. await app2.send_document(
  194. message.chat.id,
  195. "output.txt",
  196. reply_to_message_id=message.id,
  197. caption=escape(text),
  198. )
  199. return os.remove("output.txt")
  200. await eor(
  201. message,
  202. text=f"**INPUT:**\n```{escape(text)}```\n\n**OUTPUT:**\n```{escape(output)}```",
  203. )
  204. else:
  205. await eor(
  206. message,
  207. text=f"**INPUT:**\n```{escape(text)}```\n\n**OUTPUT: **\n`No output`",
  208. )
  209. @app2.on_message(
  210. filters.command("reserve", prefixes=USERBOT_PREFIX)
  211. & ~filters.forwarded
  212. & ~filters.via_bot
  213. & SUDOERS
  214. )
  215. async def reserve_channel_handler(_, message: Message):
  216. if len(message.text.split()) != 2:
  217. return await eor(message, text="Pass a username as argument!!")
  218. username = message.text.split(None, 1)[1].strip().replace("@", "")
  219. m = await eor(message, text="Reserving...")
  220. chat = await app2.create_channel(username, "Created by .reserve command")
  221. try:
  222. await app2.set_chat_username(chat.id, username)
  223. except Exception as e:
  224. await m.edit(f"Couldn't Reserve, Error: `{str(e)}`")
  225. return await app2.delete_channel(chat.id)
  226. await m.edit(f"Reserved @{username} Successfully")