Files
plain-ub-overfork/app/plugins/system/shell.py
overspend1 8fe355ed0c Update README and alive command for @overspend1 fork
- Updated README title to show OVERSPEND1 FORK
- Changed maintainer credit to @overspend1
- Updated alive command to show @overspend1 as creator instead of Meliodas
2025-07-25 20:27:05 +02:00

232 lines
8.4 KiB
Python

import asyncio
import os
import shlex
from datetime import datetime
from app import BOT, Config, Message
# Dangerous commands that should be blocked
DANGEROUS_COMMANDS = [
'rm', 'sudo rm', 'del', 'format', 'fdisk', 'mkfs',
'dd', 'sudo dd', 'chmod 000', 'sudo chmod',
':(){ :|:& };:', 'shutdown', 'reboot', 'halt',
'sudo shutdown', 'sudo reboot', 'sudo halt',
'passwd', 'sudo passwd', 'userdel', 'sudo userdel'
]
def is_dangerous_command(command: str) -> bool:
"""Check if command contains dangerous operations"""
command_lower = command.lower().strip()
for dangerous in DANGEROUS_COMMANDS:
if command_lower.startswith(dangerous):
return True
return False
@BOT.add_cmd(cmd="sh", allow_sudo=False)
async def shell_command(bot: BOT, message: Message):
"""
CMD: SH
INFO: Execute shell commands safely (Owner only).
FLAGS: -o for output only, -t for with timestamps
USAGE: .sh ls -la
"""
# Only allow owner to use shell commands
if message.from_user.id != Config.OWNER_ID:
await message.reply("❌ <b>Access Denied:</b> Only the bot owner can execute shell commands.")
return
command = message.filtered_input
if not command:
await message.reply("❌ <b>No command provided.</b>\nUsage: <code>.sh [command]</code>")
return
# Check for dangerous commands
if is_dangerous_command(command):
await message.reply("⚠️ <b>Dangerous command blocked for safety!</b>\n"
f"Command: <code>{command}</code>\n\n"
"This command could harm your system.")
return
response = await message.reply(f"🔄 <b>Executing:</b> <code>{command}</code>")
try:
start_time = datetime.now()
# Execute command with timeout
process = await asyncio.create_subprocess_shell(
command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
cwd=os.getcwd()
)
# Wait for completion with timeout
try:
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=30.0)
except asyncio.TimeoutError:
process.kill()
await response.edit("⏰ <b>Command timed out after 30 seconds!</b>")
return
end_time = datetime.now()
execution_time = (end_time - start_time).total_seconds()
# Decode output
stdout_text = stdout.decode('utf-8', errors='ignore').strip()
stderr_text = stderr.decode('utf-8', errors='ignore').strip()
# Prepare output
result_text = f"💻 <b>Shell Command Result</b>\n\n"
result_text += f"<b>Command:</b> <code>{command}</code>\n"
result_text += f"<b>Exit Code:</b> <code>{process.returncode}</code>\n"
result_text += f"<b>Execution Time:</b> <code>{execution_time:.2f}s</code>\n"
if "-t" in message.flags:
result_text += f"<b>Started:</b> <code>{start_time.strftime('%H:%M:%S')}</code>\n"
result_text += f"<b>Finished:</b> <code>{end_time.strftime('%H:%M:%S')}</code>\n"
result_text += "\n"
# Add stdout if present
if stdout_text:
if len(stdout_text) > 3000:
stdout_text = stdout_text[:3000] + "\n... (output truncated)"
result_text += f"<b>📤 Output:</b>\n<pre>{stdout_text}</pre>\n"
# Add stderr if present
if stderr_text:
if len(stderr_text) > 1000:
stderr_text = stderr_text[:1000] + "\n... (error truncated)"
result_text += f"<b>❌ Error:</b>\n<pre>{stderr_text}</pre>\n"
# If no output
if not stdout_text and not stderr_text:
result_text += "<i>No output produced.</i>\n"
# Success indicator
if process.returncode == 0:
result_text += "\n✅ <b>Command executed successfully!</b>"
else:
result_text += f"\n❌ <b>Command failed with exit code {process.returncode}</b>"
await response.edit(result_text)
except Exception as e:
await response.edit(f"❌ <b>Error executing command:</b>\n<code>{str(e)}</code>")
@BOT.add_cmd(cmd="exec", allow_sudo=False)
async def python_exec(bot: BOT, message: Message):
"""
CMD: EXEC
INFO: Execute Python code safely (Owner only).
USAGE: .exec print("Hello World")
"""
# Only allow owner
if message.from_user.id != Config.OWNER_ID:
await message.reply("❌ <b>Access Denied:</b> Only the bot owner can execute Python code.")
return
code = message.filtered_input
if not code:
await message.reply("❌ <b>No code provided.</b>\nUsage: <code>.exec [python_code]</code>")
return
response = await message.reply(f"🐍 <b>Executing Python code...</b>\n<pre>{code}</pre>")
try:
# Capture output
import io
import sys
from contextlib import redirect_stdout, redirect_stderr
stdout_capture = io.StringIO()
stderr_capture = io.StringIO()
start_time = datetime.now()
# Execute the code
with redirect_stdout(stdout_capture), redirect_stderr(stderr_capture):
exec(code)
end_time = datetime.now()
execution_time = (end_time - start_time).total_seconds()
# Get captured output
stdout_output = stdout_capture.getvalue()
stderr_output = stderr_capture.getvalue()
result_text = f"🐍 <b>Python Execution Result</b>\n\n"
result_text += f"<b>Execution Time:</b> <code>{execution_time:.3f}s</code>\n\n"
if stdout_output:
if len(stdout_output) > 3500:
stdout_output = stdout_output[:3500] + "\n... (output truncated)"
result_text += f"<b>📤 Output:</b>\n<pre>{stdout_output}</pre>\n"
if stderr_output:
if len(stderr_output) > 1000:
stderr_output = stderr_output[:1000] + "\n... (error truncated)"
result_text += f"<b>❌ Error:</b>\n<pre>{stderr_output}</pre>\n"
if not stdout_output and not stderr_output:
result_text += "<i>Code executed without output.</i>\n"
result_text += "\n✅ <b>Python code executed successfully!</b>"
await response.edit(result_text)
except Exception as e:
error_text = f"🐍 <b>Python Execution Error</b>\n\n"
error_text += f"<b>Error:</b> <code>{type(e).__name__}: {str(e)}</code>\n"
error_text += f"<b>Code:</b>\n<pre>{code}</pre>"
await response.edit(error_text)
@BOT.add_cmd(cmd="eval", allow_sudo=False)
async def python_eval(bot: BOT, message: Message):
"""
CMD: EVAL
INFO: Evaluate Python expressions safely (Owner only).
USAGE: .eval 2 + 2
"""
# Only allow owner
if message.from_user.id != Config.OWNER_ID:
await message.reply("❌ <b>Access Denied:</b> Only the bot owner can evaluate Python expressions.")
return
expression = message.filtered_input
if not expression:
await message.reply("❌ <b>No expression provided.</b>\nUsage: <code>.eval [expression]</code>")
return
response = await message.reply(f"🧮 <b>Evaluating:</b> <code>{expression}</code>")
try:
start_time = datetime.now()
# Evaluate the expression
result = eval(expression)
end_time = datetime.now()
execution_time = (end_time - start_time).total_seconds()
result_text = f"🧮 <b>Python Evaluation Result</b>\n\n"
result_text += f"<b>Expression:</b> <code>{expression}</code>\n"
result_text += f"<b>Result:</b> <code>{repr(result)}</code>\n"
result_text += f"<b>Type:</b> <code>{type(result).__name__}</code>\n"
result_text += f"<b>Execution Time:</b> <code>{execution_time:.3f}s</code>\n"
result_text += "\n✅ <b>Expression evaluated successfully!</b>"
await response.edit(result_text)
except Exception as e:
error_text = f"🧮 <b>Python Evaluation Error</b>\n\n"
error_text += f"<b>Expression:</b> <code>{expression}</code>\n"
error_text += f"<b>Error:</b> <code>{type(e).__name__}: {str(e)}</code>"
await response.edit(error_text)