cogs fuckery (i have zero clue how this is supposed to work you're on your own for this one glitch)
This commit is contained in:
parent
c3114639a2
commit
fbfa27c979
5 changed files with 296 additions and 15 deletions
173
bot/cogs/cog_manager.py
Normal file
173
bot/cogs/cog_manager.py
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
import os
|
||||
import sys
|
||||
import importlib
|
||||
import importlib.util
|
||||
import inspect
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
class BaseCog:
|
||||
"""Base cog class that all cogs should inherit from"""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.name = self.__class__.__name__
|
||||
|
||||
def cleanup(self):
|
||||
"""Called when cog is unloaded"""
|
||||
pass
|
||||
|
||||
class CogManager:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.cogs: Dict[str, BaseCog] = {}
|
||||
self.cogs_dir = os.path.join("bot", "cogs")
|
||||
os.makedirs(self.cogs_dir, exist_ok=True)
|
||||
|
||||
def load_cog(self, cog_name: str) -> bool:
|
||||
"""
|
||||
Load a cog by name
|
||||
|
||||
Args:
|
||||
cog_name: Name of the cog file (without .py)
|
||||
|
||||
Returns:
|
||||
bool: True if loaded successfully, False otherwise
|
||||
"""
|
||||
try:
|
||||
# If already loaded, unload first
|
||||
if cog_name in self.cogs:
|
||||
self.unload_cog(cog_name)
|
||||
|
||||
# Get full path to cog file
|
||||
cog_path = os.path.join(self.cogs_dir, f"{cog_name}.py")
|
||||
if not os.path.exists(cog_path):
|
||||
print(f"Cog file not found: {cog_path}")
|
||||
return False
|
||||
|
||||
# Create a unique module name to avoid conflicts
|
||||
module_name = f"bot.cogs.{cog_name}"
|
||||
|
||||
# Load the module
|
||||
spec = importlib.util.spec_from_file_location(module_name, cog_path)
|
||||
if not spec:
|
||||
print(f"Failed to create spec for {cog_path}")
|
||||
return False
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
# Find and instantiate the cog class
|
||||
# A cog class is a class that inherits from BaseCog
|
||||
cog_class = None
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if (inspect.isclass(obj) and
|
||||
issubclass(obj, BaseCog) and
|
||||
obj is not BaseCog):
|
||||
cog_class = obj
|
||||
break
|
||||
|
||||
if not cog_class:
|
||||
print(f"No cog class found in {cog_path}")
|
||||
return False
|
||||
|
||||
# Instantiate the cog
|
||||
cog = cog_class(self.bot)
|
||||
self.cogs[cog_name] = cog
|
||||
|
||||
# Register commands
|
||||
for name, method in inspect.getmembers(cog, inspect.ismethod):
|
||||
if name.startswith("cmd_"):
|
||||
cmd_name = name[4:] # Remove "cmd_" prefix
|
||||
self.bot.loaded_commands[cmd_name] = method
|
||||
|
||||
print(f"Loaded cog: {cog_name}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error loading cog {cog_name}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def unload_cog(self, cog_name: str) -> bool:
|
||||
"""
|
||||
Unload a cog by name
|
||||
|
||||
Args:
|
||||
cog_name: Name of the cog
|
||||
|
||||
Returns:
|
||||
bool: True if unloaded successfully, False otherwise
|
||||
"""
|
||||
try:
|
||||
if cog_name not in self.cogs:
|
||||
print(f"Cog not loaded: {cog_name}")
|
||||
return False
|
||||
|
||||
cog = self.cogs[cog_name]
|
||||
|
||||
# Call cleanup method
|
||||
cog.cleanup()
|
||||
|
||||
# Remove commands from loaded_commands
|
||||
for name, method in inspect.getmembers(cog, inspect.ismethod):
|
||||
if name.startswith("cmd_"):
|
||||
cmd_name = name[4:]
|
||||
if cmd_name in self.bot.loaded_commands:
|
||||
del self.bot.loaded_commands[cmd_name]
|
||||
|
||||
# Remove cog
|
||||
del self.cogs[cog_name]
|
||||
|
||||
# Remove module
|
||||
module_name = f"bot.cogs.{cog_name}"
|
||||
if module_name in sys.modules:
|
||||
del sys.modules[module_name]
|
||||
|
||||
print(f"Unloaded cog: {cog_name}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error unloading cog {cog_name}: {e}")
|
||||
return False
|
||||
|
||||
def reload_cog(self, cog_name: str) -> bool:
|
||||
"""
|
||||
Reload a cog by name
|
||||
|
||||
Args:
|
||||
cog_name: Name of the cog
|
||||
|
||||
Returns:
|
||||
bool: True if reloaded successfully, False otherwise
|
||||
"""
|
||||
return self.load_cog(cog_name)
|
||||
|
||||
def load_all_cogs(self) -> int:
|
||||
"""
|
||||
Load all cogs from the cogs directory
|
||||
|
||||
Returns:
|
||||
int: Number of cogs loaded successfully
|
||||
"""
|
||||
count = 0
|
||||
for filename in os.listdir(self.cogs_dir):
|
||||
if filename.endswith(".py") and not filename.startswith("_"):
|
||||
cog_name = filename[:-3]
|
||||
if self.load_cog(cog_name):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def unload_all_cogs(self) -> int:
|
||||
"""
|
||||
Unload all cogs
|
||||
|
||||
Returns:
|
||||
int: Number of cogs unloaded successfully
|
||||
"""
|
||||
cog_names = list(self.cogs.keys())
|
||||
count = 0
|
||||
for cog_name in cog_names:
|
||||
if self.unload_cog(cog_name):
|
||||
count += 1
|
||||
return count
|
||||
33
bot/cogs/example_cog.py
Normal file
33
bot/cogs/example_cog.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
from bot.cogs.cog_manager import BaseCog
|
||||
import discord
|
||||
import asyncio
|
||||
|
||||
class ExampleCog(BaseCog):
|
||||
def __init__(self, bot):
|
||||
super().__init__(bot)
|
||||
# Initialize any state for this cog
|
||||
self.counter = 0
|
||||
|
||||
def cleanup(self):
|
||||
# Clean up any resources when unloaded
|
||||
print("Example cog is being unloaded and cleaned up")
|
||||
|
||||
async def cmd_hello(self, message):
|
||||
"""
|
||||
A simple hello command
|
||||
Usage: .hello
|
||||
"""
|
||||
self.counter += 1
|
||||
await message.edit(content=f"👋 Hello! I've been greeted {self.counter} times.")
|
||||
|
||||
async def cmd_echo(self, message):
|
||||
"""
|
||||
Echo the user's message
|
||||
Usage: .echo <message>
|
||||
"""
|
||||
content = message.content
|
||||
if ' ' in content:
|
||||
text = content.split(' ', 1)[1]
|
||||
await message.edit(content=f"🔊 {text}")
|
||||
else:
|
||||
await message.edit(content="❌ Usage: `.echo <message>`")
|
||||
Loading…
Add table
Add a link
Reference in a new issue