From 2649b9136a29d1f86436f9458d7f562df37b53ab Mon Sep 17 00:00:00 2001 From: Ivan Ashikhmin Date: Sun, 3 Mar 2024 20:29:44 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D1=8B=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 --- .env.example | 2 ++ .gitignore | 6 ++++ app/__init__.py | 0 app/handlers/__init__.py | 0 app/handlers/docker_commands.py | 48 +++++++++++++++++++++++++++++++ app/handlers/user_command.py | 11 +++++++ app/keyboards/__init__.py | 0 app/keyboards/docker_keyboards.py | 42 +++++++++++++++++++++++++++ app/settings.py | 16 +++++++++++ main.py | 27 +++++++++++++++++ 10 files changed, 152 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 app/__init__.py create mode 100644 app/handlers/__init__.py create mode 100644 app/handlers/docker_commands.py create mode 100644 app/handlers/user_command.py create mode 100644 app/keyboards/__init__.py create mode 100644 app/keyboards/docker_keyboards.py create mode 100644 app/settings.py create mode 100644 main.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4cf16a5 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +TOKEN= +ADMIN_ID= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d4a7d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.env +.idea +venv +__pycache__/ +*.py[cod] +*$py.class \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/handlers/__init__.py b/app/handlers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/handlers/docker_commands.py b/app/handlers/docker_commands.py new file mode 100644 index 0000000..340a88c --- /dev/null +++ b/app/handlers/docker_commands.py @@ -0,0 +1,48 @@ +import subprocess + +from aiogram.types import Message, CallbackQuery + +from app.keyboards.docker_keyboards import container_names_keyboard, container_actions_keyboard + + +async def get_containers(message: Message): + sub = subprocess.check_output("docker ps -a").decode() + keyboard = container_names_keyboard(sub) + await message.answer( + text=f"
{sub}
", + parse_mode="HTML", + reply_markup=keyboard.as_markup() + ) + + +async def container_actions(call: CallbackQuery): + name = call.data.split("_")[-1] + keyboard = container_actions_keyboard(name) + await call.message.answer( + text=f"Выберите действие для контейнера {name}", + parse_mode="HTML", + reply_markup=keyboard.as_markup() + ) + + +async def do_container_action(call: CallbackQuery): + _, action, name = call.data.split("_") + match action: + case "start": + subprocess.run(f"docker start {name}") + message = f"Контейнер {name} успешно запущен" + case "stop": + subprocess.run(f"docker stop {name}") + message = f"Контейнер {name} успешно остановлен" + case "restart": + subprocess.run(f"docker restart {name}") + message = f"Контейнер {name} успешно перезапущен" + case "delete": + subprocess.run(f"docker rm -f {name}") + message = f"Контейнер {name} успешно удалён" + case _: + message = f"Произошла необъяснимая ошибка" + + await call.message.answer( + text=message, + ) diff --git a/app/handlers/user_command.py b/app/handlers/user_command.py new file mode 100644 index 0000000..8e6e67f --- /dev/null +++ b/app/handlers/user_command.py @@ -0,0 +1,11 @@ +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/keyboards/__init__.py b/app/keyboards/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/keyboards/docker_keyboards.py b/app/keyboards/docker_keyboards.py new file mode 100644 index 0000000..224a9ff --- /dev/null +++ b/app/keyboards/docker_keyboards.py @@ -0,0 +1,42 @@ +from aiogram.types import InlineKeyboardButton +from aiogram.utils.keyboard import InlineKeyboardBuilder + + +def container_names_keyboard(stdout: str): + container_names = [line.split(" ")[-1].strip() for line in stdout.splitlines()[1:]] + builder = InlineKeyboardBuilder() + for name in container_names: + data = f"container_{name}" + builder.add( + InlineKeyboardButton( + text=name, + callback_data=data, + ) + ) + builder.adjust(1) + + return builder + + +def container_actions_keyboard(name: str): + builder = InlineKeyboardBuilder() + + builder.add(InlineKeyboardButton( + text="Запустить контейнер", + callback_data=f"action_start_{name}", + )) + builder.add(InlineKeyboardButton( + text="Остановить контейнер", + callback_data=f"action_stop_{name}", + )) + builder.add(InlineKeyboardButton( + text="Перезапустить контейнер", + callback_data=f"action_restart_{name}", + )) + builder.add(InlineKeyboardButton( + text="Удалить контейнер", + callback_data=f"action_delete_{name}", + )) + builder.adjust(1) + + return builder diff --git a/app/settings.py b/app/settings.py new file mode 100644 index 0000000..cb96309 --- /dev/null +++ b/app/settings.py @@ -0,0 +1,16 @@ +import os +from dataclasses import dataclass + +from aiogram import Bot +from dotenv import load_dotenv + +load_dotenv() + + +@dataclass +class Secrets: + token: str = os.environ.get("TOKEN") + admin_id: int = os.environ.get("ADMIN_ID") + + +bot = Bot(token=Secrets.token) diff --git a/main.py b/main.py new file mode 100644 index 0000000..fa8f2b0 --- /dev/null +++ b/main.py @@ -0,0 +1,27 @@ +import asyncio + +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.settings import bot + + +async def start(): + dp = Dispatcher() + + dp.message.register(execute_command, Command(commands="command")) + 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")) + + try: + await dp.start_polling(bot) + finally: + await bot.session.close() + + +if __name__ == "__main__": + asyncio.run(start())