refactor(bot): bot utilities into separate modules

Moved logging, signal handling, and uptime calculation logic from bot.py into dedicated utils modules for better organization and reusability. Updated imports and usage in bot.py and utils/__init__.py accordingly.
This commit is contained in:
neoarz
2025-09-28 16:20:28 -04:00
parent 0a262c522e
commit 4948d2edf7
5 changed files with 96 additions and 73 deletions

76
bot.py
View File

@@ -15,7 +15,7 @@ from discord.ext.commands import Context
from dotenv import load_dotenv
from database import DatabaseManager
from utils.ascii_art import ascii
from utils import ascii, setup_logger, get_uptime, setup_signal_handlers
load_dotenv()
@@ -50,54 +50,7 @@ intents.messages = True
class LoggingFormatter(logging.Formatter):
# Colors
black = "\x1b[30m"
red = "\x1b[31m"
green = "\x1b[32m"
yellow = "\x1b[33m"
blue = "\x1b[34m"
gray = "\x1b[38m"
# Styles
reset = "\x1b[0m"
bold = "\x1b[1m"
COLORS = {
logging.DEBUG: gray + bold,
logging.INFO: blue + bold,
logging.WARNING: yellow + bold,
logging.ERROR: red,
logging.CRITICAL: red + bold,
}
def format(self, record):
log_color = self.COLORS[record.levelno]
format = "(black){asctime}(reset) (levelcolor){levelname:<8}(reset) (green){name}(reset) {message}"
format = format.replace("(black)", self.black + self.bold)
format = format.replace("(reset)", self.reset)
format = format.replace("(levelcolor)", log_color)
format = format.replace("(green)", self.green + self.bold)
formatter = logging.Formatter(format, "%Y-%m-%d %H:%M:%S", style="{")
return formatter.format(record)
logger = logging.getLogger("discord_bot")
logger.setLevel(logging.INFO)
console_handler = logging.StreamHandler()
console_handler.setFormatter(LoggingFormatter())
log_file_path = os.getenv("LOG_FILE", "logs/discord.log")
log_dir = os.path.dirname(log_file_path)
if log_dir:
os.makedirs(log_dir, exist_ok=True)
file_handler = logging.FileHandler(filename=log_file_path, encoding="utf-8", mode="w")
file_handler_formatter = logging.Formatter(
"[{asctime}] [{levelname:<8}] {name}: {message}", "%Y-%m-%d %H:%M:%S", style="{"
)
file_handler.setFormatter(file_handler_formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
logger = setup_logger()
class DiscordBot(commands.Bot):
@@ -223,20 +176,7 @@ class DiscordBot(commands.Bot):
)
def get_uptime(self) -> str:
uptime_seconds = int(time.time() - self.start_time)
days = uptime_seconds // 86400
hours = (uptime_seconds % 86400) // 3600
minutes = (uptime_seconds % 3600) // 60
seconds = uptime_seconds % 60
if days > 0:
return f"{days}d {hours}h {minutes}m {seconds}s"
elif hours > 0:
return f"{hours}h {minutes}m {seconds}s"
elif minutes > 0:
return f"{minutes}m {seconds}s"
else:
return f"{seconds}s"
return get_uptime(self.start_time)
async def close(self) -> None:
if self._shutdown:
@@ -374,13 +314,6 @@ class DiscordBot(commands.Bot):
raise error
def signal_handler(signum, frame):
logger.info("Shutdown requested. Closing bot...")
if bot.loop and not bot.loop.is_closed():
asyncio.create_task(bot.close())
bot.loop.call_soon_threadsafe(bot.loop.stop)
bot = DiscordBot()
if __name__ == "__main__":
@@ -388,8 +321,7 @@ if __name__ == "__main__":
print(ascii)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
setup_signal_handlers(bot)
try:
bot.run(os.getenv("TOKEN"))