modularized the program; oops

This commit is contained in:
2025-08-23 13:01:30 +05:30
parent 9dfcbe37b6
commit 00c7c9f455
10 changed files with 801 additions and 727 deletions

View File

@@ -0,0 +1,87 @@
"""This module provides utility functions for logging, file handling, and string generation."""
import logging
import os
import sys
import random
import string
from datetime import datetime, timezone
from colorama import Fore, Style, init
from . import config
class ColoredFormatter(logging.Formatter):
"""A logging formatter that adds color to console output for different log levels."""
LOG_COLORS = {
logging.DEBUG: Fore.CYAN,
logging.INFO: Fore.GREEN,
logging.WARNING: Fore.YELLOW,
logging.ERROR: Fore.RED,
logging.CRITICAL: Fore.RED + Style.BRIGHT,
}
def format(self, record):
"""Applies color to the formatted log message."""
color = self.LOG_COLORS.get(record.levelno)
message = super().format(record)
if color:
# For better readability, only color the message part of the log string.
parts = message.split(" - ", 2)
if len(parts) > 2:
parts[2] = color + parts[2] + Style.RESET_ALL
message = " - ".join(parts)
else:
message = color + message + Style.RESET_ALL
return message
def setup_logging():
"""
Configures the root logger to output to both a timestamped file and the console.
Console output is colorized for readability.
"""
init(autoreset=True) # Required for colorama on Windows
if not os.path.exists(config.LOG_DIR):
os.makedirs(config.LOG_DIR)
log_filename = f"gemini_key_management_{datetime.now(timezone.utc).strftime('%Y-%m-%dT%H-%M-%S')}.log"
log_filepath = os.path.join(config.LOG_DIR, log_filename)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Avoids duplicate log messages if the function is called multiple times.
if logger.hasHandlers():
logger.handlers.clear()
# The file handler logs detailed, non-colored messages.
file_handler = logging.FileHandler(log_filepath, encoding='utf-8')
file_formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - [%(name)s:%(module)s:%(lineno)d] - %(message)s"
)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
# The console handler logs concise, colored messages.
console_handler = logging.StreamHandler(sys.stdout)
console_formatter = ColoredFormatter("%(asctime)s - %(levelname)s - %(message)s")
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
logging.info(f"Logging initialized. Log file: {log_filepath}")
def load_emails_from_file(filename):
"""
Reads a list of email addresses from a text file.
It ignores empty lines and lines that start with a '#' comment character.
"""
if not os.path.exists(filename):
logging.error(f"Email file not found at '{filename}'")
logging.info("Please create it and add one email address per line.")
return []
with open(filename, "r") as f:
return [line.strip() for line in f if line.strip() and not line.startswith("#")]
def generate_random_string(length=10):
"""Generates a random alphanumeric string for creating unique project IDs."""
letters_and_digits = string.ascii_lowercase + string.digits
return ''.join(random.choice(letters_and_digits) for i in range(length))