# bots.py import os import json import asyncio import sys import time import traceback import globals from discord.ext import commands from dotenv import load_dotenv from bot_discord import DiscordBot from bot_twitch import TwitchBot from modules.db import init_db_connection, run_db_operation # Load environment variables load_dotenv() # Load bot configuration CONFIG_PATH = "config.json" try: with open(CONFIG_PATH, "r") as f: config_data = json.load(f) except FileNotFoundError: print("Error: config.json not found.") sys.exit(1) except json.JSONDecodeError as e: print(f"Error parsing config.json: {e}") sys.exit(1) ############################### # Simple Logging System ############################### def log(message, level="INFO"): """ A simple logging function with adjustable log levels. Logs messages in a structured format. Available levels: DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL See 'config.json' for disabling/enabling logging levels """ from modules import utility log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "FATAL"] if level not in log_levels: level = "INFO" # Default to INFO if an invalid level is provided if level in config_data["log_levels"]: elapsed = time.time() - globals.get_bot_start_time() uptime_str, _ = utility.format_uptime(elapsed) timestamp = time.strftime('%Y-%m-%d %H:%M:%S') log_message = f"[{timestamp} - {uptime_str}] [{level}] {message}" try: print(log_message) # Print to terminal if level == "FATAL": print(f"!!! FATAL ERROR LOGGED, SHUTTING DOWN !!!") sys.exit(1) except Exception: pass # Prevent logging failures from crashing the bot # Placeholder for future expansions (e.g., file logging, Discord alerts, etc.) ############################### # Main Event Loop ############################### async def main(): global discord_bot, twitch_bot, db_conn # Before creating your DiscordBot/TwitchBot, initialize DB db_conn = init_db_connection(config_data, log) if not db_conn: # If we get None, it means FATAL. We might sys.exit(1) or handle it differently. log("Terminating bot due to no DB connection.", "FATAL") sys.exit(1) log("Initializing bots...", "INFO") # Create both bots discord_bot = DiscordBot(config_data, log) twitch_bot = TwitchBot(config_data, log) # Provide DB connection to both bots try: discord_bot.set_db_connection(db_conn) twitch_bot.set_db_connection(db_conn) log(f"Initialized database connection to both bots", "INFO") except Exception as e: log(f"Unable to initialize database connection to one or both bots: {e}", "FATAL") log("Starting Discord and Twitch bots...", "INFO") discord_task = asyncio.create_task(discord_bot.run(os.getenv("DISCORD_BOT_TOKEN"))) twitch_task = asyncio.create_task(twitch_bot.run()) await asyncio.gather(discord_task, twitch_task) if __name__ == "__main__": try: asyncio.run(main()) except Exception as e: error_trace = traceback.format_exc() log(f"Fatal Error: {e}\n{error_trace}", "FATAL")