diff --git a/bot.py b/bot.py index fb0dbd7..61c8847 100644 --- a/bot.py +++ b/bot.py @@ -23,6 +23,9 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +# Время запуска бота (на уровне модуля, чтобы не хранить на объекте discord.py Bot) +START_TIME: float = time.time() + class TextHelpCommand(commands.HelpCommand): """Выводит справку по командам простым текстом вместо embed.""" @@ -104,7 +107,7 @@ class BotRunner: intents=intents, help_command=TextHelpCommand(), ) - self.bot._start_time = time.time() + self.stop_event = threading.Event() self.bot_ready = threading.Event() self.scheduler: SchedulerType | None = None @@ -142,7 +145,6 @@ class BotRunner: morning_time = os.getenv("MORNING_TIME", "07:00") self.scheduler = Scheduler(self.bot, morning_time) - self.bot._scheduler = self.scheduler await self.scheduler.start() logger.info( "Планировщик запущен (время: %s, сервер: %s)", morning_time, guild.name diff --git a/commands/status.py b/commands/status.py index f283862..3037489 100644 --- a/commands/status.py +++ b/commands/status.py @@ -13,9 +13,11 @@ class Status(commands.Cog): @commands.command(name="status") async def status(self, ctx: commands.Context) -> None: """Статус бота: пинг к Discord gateway и время работы""" + # Lazy import чтобы избежать циклического импорта (bot -> commands -> bot) + from bot import START_TIME # noqa: F401 + latency_ms = round(ctx.bot.latency * 1000, 1) - start_time = getattr(ctx.bot, "_start_time", time.time()) - uptime_seconds = time.time() - start_time + uptime_seconds = time.time() - START_TIME uptime_str = self._format_uptime(uptime_seconds) embed = discord.Embed( diff --git a/tests/test_commands_status.py b/tests/test_commands_status.py index 725b9c9..f675628 100644 --- a/tests/test_commands_status.py +++ b/tests/test_commands_status.py @@ -2,7 +2,7 @@ import time -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import AsyncMock, MagicMock, patch from commands.status import Status @@ -14,11 +14,11 @@ class TestStatusCommand: """Команда status отправляет embed-сообщение.""" mock_ctx = MagicMock() mock_ctx.bot.latency = 0.042 - mock_ctx.bot._start_time = time.time() mock_ctx.send = AsyncMock(return_value=None) - cog = Status() - await cog.status(cog, mock_ctx) + with patch("bot.START_TIME", time.time()): + cog = Status() + await cog.status(cog, mock_ctx) mock_ctx.send.assert_awaited_once() call_args = mock_ctx.send.call_args @@ -30,11 +30,11 @@ class TestStatusCommand: """Uptime форматируется корректно.""" mock_ctx = MagicMock() mock_ctx.bot.latency = 0.050 - mock_ctx.bot._start_time = time.time() - 90061 # 1д 1ч 1м 1с mock_ctx.send = AsyncMock(return_value=None) - cog = Status() - await cog.status(cog, mock_ctx) + with patch("bot.START_TIME", time.time() - 90061): # 1д 1ч 1м 1с + cog = Status() + await cog.status(cog, mock_ctx) call_args = mock_ctx.send.call_args embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]