mirror of
https://github.com/neoarz/Syntrel.git
synced 2025-12-25 11:40:12 +01:00
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:
76
bot.py
76
bot.py
@@ -15,7 +15,7 @@ from discord.ext.commands import Context
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from database import DatabaseManager
|
from database import DatabaseManager
|
||||||
from utils.ascii_art import ascii
|
from utils import ascii, setup_logger, get_uptime, setup_signal_handlers
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
@@ -50,54 +50,7 @@ intents.messages = True
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LoggingFormatter(logging.Formatter):
|
logger = setup_logger()
|
||||||
# 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)
|
|
||||||
|
|
||||||
|
|
||||||
class DiscordBot(commands.Bot):
|
class DiscordBot(commands.Bot):
|
||||||
@@ -223,20 +176,7 @@ class DiscordBot(commands.Bot):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_uptime(self) -> str:
|
def get_uptime(self) -> str:
|
||||||
uptime_seconds = int(time.time() - self.start_time)
|
return get_uptime(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"
|
|
||||||
|
|
||||||
async def close(self) -> None:
|
async def close(self) -> None:
|
||||||
if self._shutdown:
|
if self._shutdown:
|
||||||
@@ -374,13 +314,6 @@ class DiscordBot(commands.Bot):
|
|||||||
raise error
|
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()
|
bot = DiscordBot()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -388,8 +321,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
print(ascii)
|
print(ascii)
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
setup_signal_handlers(bot)
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bot.run(os.getenv("TOKEN"))
|
bot.run(os.getenv("TOKEN"))
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
from .ascii_art import ascii, ascii_plain, gradient_text, gradient_text_selective
|
from .ascii_art import ascii, ascii_plain, gradient_text, gradient_text_selective
|
||||||
|
from .logging import LoggingFormatter, setup_logger
|
||||||
|
from .time import get_uptime
|
||||||
|
from .signal import setup_signal_handlers
|
||||||
|
|
||||||
__all__ = ['ascii', 'ascii_plain', 'gradient_text', 'gradient_text_selective']
|
__all__ = [
|
||||||
|
'ascii', 'ascii_plain', 'gradient_text', 'gradient_text_selective',
|
||||||
|
'LoggingFormatter', 'setup_logger', 'get_uptime', 'setup_signal_handlers'
|
||||||
|
]
|
||||||
54
utils/logging.py
Normal file
54
utils/logging.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class LoggingFormatter(logging.Formatter):
|
||||||
|
black = "\x1b[30m"
|
||||||
|
red = "\x1b[31m"
|
||||||
|
green = "\x1b[32m"
|
||||||
|
yellow = "\x1b[33m"
|
||||||
|
blue = "\x1b[34m"
|
||||||
|
gray = "\x1b[38m"
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logger():
|
||||||
|
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)
|
||||||
|
|
||||||
|
return logger
|
||||||
13
utils/signal.py
Normal file
13
utils/signal.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import asyncio
|
||||||
|
import signal
|
||||||
|
|
||||||
|
|
||||||
|
def setup_signal_handlers(bot):
|
||||||
|
def signal_handler(signum, frame):
|
||||||
|
bot.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)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
18
utils/time.py
Normal file
18
utils/time.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def get_uptime(start_time: float) -> str:
|
||||||
|
uptime_seconds = int(time.time() - 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"
|
||||||
Reference in New Issue
Block a user