Initial import: Discodrome codebase (ignore docker-compose.yml and data.env)
This commit is contained in:
16
util/env.py
Normal file
16
util/env.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
|
||||
from typing import Final
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(os.path.relpath("data.env"))
|
||||
|
||||
DISCORD_BOT_TOKEN: Final[str] = os.getenv("DISCORD_BOT_TOKEN")
|
||||
DISCORD_TEST_GUILD: Final[str] = os.getenv("DISCORD_TEST_GUILD")
|
||||
DISCORD_OWNER_ID: Final[int] = int(os.getenv("DISCORD_OWNER_ID"))
|
||||
|
||||
SUBSONIC_SERVER: Final[str] = os.getenv("SUBSONIC_SERVER")
|
||||
SUBSONIC_USER: Final[str] = os.getenv("SUBSONIC_USER")
|
||||
SUBSONIC_PASSWORD: Final[str] = os.getenv("SUBSONIC_PASSWORD")
|
||||
|
||||
BOT_STATUS: Final[str] = os.getenv("BOT_STATUS")
|
||||
89
util/logs.py
Normal file
89
util/logs.py
Normal file
@@ -0,0 +1,89 @@
|
||||
'''Collection of utility functions related to logging.'''
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
|
||||
from typing import TextIO
|
||||
|
||||
def is_docker() -> bool:
|
||||
'''Checks if the application is being run within a Docker container.'''
|
||||
|
||||
path = '/proc/self/cgroup'
|
||||
return os.path.exists('/.dockerenv') or (os.path.isfile(path) and any('docker' in line for line in open(path, encoding='utf-8')))
|
||||
|
||||
|
||||
def stream_supports_color(stream: TextIO) -> bool:
|
||||
'''Checks if the provided `TextIO` stream supports color.'''
|
||||
|
||||
is_a_tty = hasattr(stream, 'isatty') and stream.isatty()
|
||||
|
||||
if 'PYCHARM_HOSTED' in os.environ or os.environ.get('TERM_PROGRAM') == 'vscode':
|
||||
return is_a_tty
|
||||
|
||||
if sys.platform != 'win32':
|
||||
return is_a_tty or is_docker()
|
||||
|
||||
return is_a_tty and ('ANSICON' in os.environ or 'WT_SESSION' in os.environ)
|
||||
|
||||
|
||||
class ColorFormatter(logging.Formatter):
|
||||
'''A logging formatter that applies colored formatting to logs.'''
|
||||
|
||||
LEVEL_COLORS = [
|
||||
(logging.DEBUG, '\x1b[40;1m'),
|
||||
(logging.INFO, '\x1b[34;1m'),
|
||||
(logging.WARNING, '\x1b[33;1m'),
|
||||
(logging.ERROR, '\x1b[31m'),
|
||||
(logging.CRITICAL, '\x1b[41m'),
|
||||
]
|
||||
|
||||
FORMATS = {
|
||||
level: logging.Formatter(
|
||||
f'\x1b[30;1m%(asctime)s\x1b[0m {color}%(levelname)-8s\x1b[0m \x1b[35m%(name)s\x1b[0m %(message)s',
|
||||
'%Y-%m-%d %H:%M:%S',
|
||||
)
|
||||
for level, color in LEVEL_COLORS
|
||||
}
|
||||
|
||||
def format(self, record: logging.LogRecord) -> str:
|
||||
formatter = self.FORMATS.get(record.levelno)
|
||||
if formatter is None:
|
||||
formatter = self.FORMATS[logging.DEBUG]
|
||||
|
||||
if record.exc_info:
|
||||
text = formatter.formatException(record.exc_info)
|
||||
record.exc_text = f'\x1b[31m{text}\x1b[0m'
|
||||
|
||||
output = formatter.format(record)
|
||||
|
||||
record.exc_text = None
|
||||
return output
|
||||
|
||||
|
||||
def setup_logging(main_log_level: int=logging.INFO, file_log_level: int=logging.INFO, stream_log_level: int=logging.INFO) -> None:
|
||||
'''Sets up logging handlers for both console and file logging.'''
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(main_log_level)
|
||||
|
||||
dt_fmt = '%Y-%m-%d %H:%M:%S'
|
||||
formatter = logging.Formatter('[{asctime}] [{levelname:<8}] {name}: {message}', dt_fmt, style='{')
|
||||
|
||||
file_max_size = 10 * 1024 * 1024 # 10mb
|
||||
|
||||
file_handler = logging.handlers.RotatingFileHandler(filename='bot.log', encoding='utf-8', maxBytes=file_max_size, backupCount=1)
|
||||
file_handler.setLevel(file_log_level)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
stream_handler = logging.StreamHandler(stream=sys.stdout)
|
||||
stream_handler.setLevel(stream_log_level)
|
||||
|
||||
if stream_supports_color(stream_handler.stream):
|
||||
formatter = ColorFormatter()
|
||||
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(stream_handler)
|
||||
logger.addHandler(file_handler)
|
||||
Reference in New Issue
Block a user