diff --git a/app/handlers/events.py b/app/handlers/events.py new file mode 100644 index 0000000..8d1ad70 --- /dev/null +++ b/app/handlers/events.py @@ -0,0 +1,12 @@ +from app.settings import bot, Secrets +from app.utils.commands import set_commands +from app import views + + +async def start_bot(): + await set_commands(bot) + await bot.send_message(Secrets.admin_id, views.start_bot_message()) + + +async def stop_bot(): + await bot.send_message(Secrets.admin_id, views.stop_bot_message()) diff --git a/app/handlers/favorites.py b/app/handlers/favorites.py new file mode 100644 index 0000000..e69de29 diff --git a/app/handlers/multiply_commands.py b/app/handlers/multiply_commands.py new file mode 100644 index 0000000..3a7d138 --- /dev/null +++ b/app/handlers/multiply_commands.py @@ -0,0 +1,39 @@ +import os +import subprocess + +from aiogram.fsm.context import FSMContext +from aiogram.types import Message + +from app import views +from app.utils.statesform import ExecuteCommandsSteps + + +async def multiply_commands(message: Message, state: FSMContext): + cwd = os.getcwd() + await message.answer(views.exec_command_message(cwd)) + await state.set_data({"cwd": cwd}) + await state.set_state(ExecuteCommandsSteps.EXECUTE) + + +async def execute_commands(message: Message, state: FSMContext): + if message.text.lower() == "cancel": + await message.answer(views.exec_canceled()) + await state.clear() + else: + data = await state.get_data() + + if message.text.lower().split()[0] == "cd": + new_cwd = os.path.join(data.get("cwd"), " ".join(message.text.split()[1:])) + os.chdir(new_cwd) + await state.set_data({"cwd": new_cwd}) + res = views.changed_dir(new_cwd) + else: + try: + sub = subprocess.check_output(message.text, shell=True, cwd=data.get("cwd")) + res = sub.decode().replace("&", "&").replace("<", "<").replace(">", ">") + except subprocess.CalledProcessError as e: + res = views.subprocess_error(e) + + await message.answer(views.user_command(res), parse_mode="HTML") + + await state.set_state(ExecuteCommandsSteps.EXECUTE) diff --git a/app/handlers/simple.py b/app/handlers/simple.py new file mode 100644 index 0000000..aae5fc3 --- /dev/null +++ b/app/handlers/simple.py @@ -0,0 +1,7 @@ +from aiogram.types import Message +from app import views + + +async def start_command(message: Message): + await message.answer(views.start_text()) + diff --git a/app/handlers/single_command.py b/app/handlers/single_command.py new file mode 100644 index 0000000..a134746 --- /dev/null +++ b/app/handlers/single_command.py @@ -0,0 +1,12 @@ +import subprocess + +from aiogram.types import Message + +from app import views + + +async def execute_command(message: Message): + user_command = message.text.split()[1:] + sub = subprocess.check_output(user_command, shell=True) + res = sub.decode().replace("&", "&").replace("<", "<").replace(">", ">") + await message.answer(views.user_command(res), parse_mode="HTML") diff --git a/app/handlers/user_command.py b/app/handlers/user_command.py deleted file mode 100644 index 8e6e67f..0000000 --- a/app/handlers/user_command.py +++ /dev/null @@ -1,11 +0,0 @@ -import subprocess - -from aiogram.types import Message - - -async def execute_command(message: Message): - user_command = message.text.split()[1:] - print(user_command) - sub = subprocess.check_output(user_command) - # print(sub) - await message.answer(f"
{sub.decode()}
", parse_mode="HTML")
diff --git a/app/utils/__init__.py b/app/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/app/utils/commands.py b/app/utils/commands.py
new file mode 100644
index 0000000..c135905
--- /dev/null
+++ b/app/utils/commands.py
@@ -0,0 +1,15 @@
+from aiogram import Bot
+from aiogram.types import BotCommand, BotCommandScopeDefault
+
+from app import views
+
+
+async def set_commands(bot: Bot):
+ commands = [
+ BotCommand(command="start", description=views.menu.get("start")),
+ BotCommand(command="command", description=views.menu.get("command")),
+ BotCommand(command="multiply_commands", description=views.menu.get("multiply_commands")),
+ BotCommand(command="docker_list", description=views.menu.get("docker_list"))
+ ]
+
+ await bot.set_my_commands(commands, BotCommandScopeDefault())
diff --git a/app/utils/statesform.py b/app/utils/statesform.py
new file mode 100644
index 0000000..0e6547f
--- /dev/null
+++ b/app/utils/statesform.py
@@ -0,0 +1,5 @@
+from aiogram.fsm.state import StatesGroup, State
+
+
+class ExecuteCommandsSteps(StatesGroup):
+ EXECUTE = State()
diff --git a/app/views.py b/app/views.py
new file mode 100644
index 0000000..8633e9e
--- /dev/null
+++ b/app/views.py
@@ -0,0 +1,45 @@
+menu = {
+ "start": "Начало работы",
+ "command": "Выполнение произвольной команды",
+ "multiply_commands": "Выполнение нескольких команд",
+ "docker_list": "Список Docker-контейнеров",
+}
+
+
+def start_bot_message():
+ return "Бот запущен"
+
+
+def stop_bot_message():
+ return "Бот остановлен"
+
+
+def user_command(result: str):
+ return f"{result or 'Done'}
"
+
+
+def exec_command_message(cwd: str):
+ return f"Режим выполнения команд.\nВы находитесь в директории:\n{cwd}\n\nИли введите cancel для остановки."
+
+
+def exec_canceled():
+ return "Процесс выполнения команд остановлен."
+
+
+def changed_dir(cwd: str):
+ return f"Перешли в директорию {cwd}"
+
+
+def subprocess_error(e: str):
+ return f"Неверная команда или произошла ошибка:\n{e}
"
+
+
+def start_text():
+ return """Бот для управления сервером.
+
+Доступные команды:
+/start - информация о доступных командах
+/command <команда> - выполнение произвольной команды
+/multiply_commands - выполнение нескольких команд с запоминанием пути
+/docker_list - отображение списка Docker-контейнеров и действий для них
+"""
diff --git a/main.py b/main.py
index fa8f2b0..72e5283 100644
--- a/main.py
+++ b/main.py
@@ -4,19 +4,30 @@ from aiogram import Dispatcher, F
from aiogram.filters import Command
from app.handlers.docker_commands import get_containers, container_actions, do_container_action
-from app.handlers.user_command import execute_command
+from app.handlers.events import start_bot, stop_bot
+from app.handlers.multiply_commands import multiply_commands, execute_commands
+from app.handlers.simple import start_command
+from app.handlers.single_command import execute_command
from app.settings import bot
+from app.utils.statesform import ExecuteCommandsSteps
async def start():
dp = Dispatcher()
+ dp.startup.register(start_bot)
+ dp.shutdown.register(stop_bot)
+
+ dp.message.register(start_command, Command(commands="start"))
dp.message.register(execute_command, Command(commands="command"))
+ dp.message.register(multiply_commands, Command(commands="multiply_commands"))
dp.message.register(get_containers, Command(commands="docker_list"))
dp.callback_query.register(container_actions, F.data.startswith("container"))
dp.callback_query.register(do_container_action, F.data.startswith("action"))
+ dp.message.register(execute_commands, ExecuteCommandsSteps.EXECUTE)
+
try:
await dp.start_polling(bot)
finally: