From 62922cf61345e807f29052bd06ba9b2c709052c8 Mon Sep 17 00:00:00 2001 From: Ivan Ashikhmin Date: Mon, 11 Mar 2024 01:56:43 +0400 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=BE=D0=B9=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=B8=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/handlers/events.py | 12 +++++++++ app/handlers/favorites.py | 0 app/handlers/multiply_commands.py | 39 +++++++++++++++++++++++++++ app/handlers/simple.py | 7 +++++ app/handlers/single_command.py | 12 +++++++++ app/handlers/user_command.py | 11 -------- app/utils/__init__.py | 0 app/utils/commands.py | 15 +++++++++++ app/utils/statesform.py | 5 ++++ app/views.py | 45 +++++++++++++++++++++++++++++++ main.py | 13 ++++++++- 11 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 app/handlers/events.py create mode 100644 app/handlers/favorites.py create mode 100644 app/handlers/multiply_commands.py create mode 100644 app/handlers/simple.py create mode 100644 app/handlers/single_command.py delete mode 100644 app/handlers/user_command.py create mode 100644 app/utils/__init__.py create mode 100644 app/utils/commands.py create mode 100644 app/utils/statesform.py create mode 100644 app/views.py 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: