feat: Implement comprehensive non-hierarchical logging system
- Created new logging infrastructure with per-component filtering - Added 6 log levels: DEBUG, INFO, API, WARNING, ERROR, CRITICAL - Implemented non-hierarchical level control (any combination can be enabled) - Migrated 917 print() statements across 31 files to structured logging - Created web UI (system.html) for runtime configuration with dark theme - Added global level controls to enable/disable levels across all components - Added timestamp format control (off/time/date/datetime options) - Implemented log rotation (10MB per file, 5 backups) - Added API endpoints for dynamic log configuration - Configured HTTP request logging with filtering via api.requests component - Intercepted APScheduler logs with proper formatting - Fixed persistence paths to use /app/memory for Docker volume compatibility - Fixed checkbox display bug in web UI (enabled_levels now properly shown) - Changed System Settings button to open in same tab instead of new window Components: bot, api, api.requests, autonomous, persona, vision, llm, conversation, mood, dm, scheduled, gpu, media, server, commands, sentiment, core, apscheduler All settings persist across container restarts via JSON config.
This commit is contained in:
@@ -13,6 +13,9 @@ from apscheduler.triggers.cron import CronTrigger
|
||||
from apscheduler.triggers.date import DateTrigger
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger('server')
|
||||
|
||||
@dataclass
|
||||
class ServerConfig:
|
||||
@@ -58,7 +61,7 @@ class ServerConfig:
|
||||
features_list = [f.strip().strip("'\"") for f in features_str.split(',') if f.strip()]
|
||||
data['enabled_features'] = set(features_list)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to parse enabled_features string '{data['enabled_features']}': {e}")
|
||||
logger.warning(f"Failed to parse enabled_features string '{data['enabled_features']}': {e}")
|
||||
# Fallback to default features
|
||||
data['enabled_features'] = {"autonomous", "bedtime", "monday_video"}
|
||||
return cls(**data)
|
||||
@@ -83,12 +86,12 @@ class ServerManager:
|
||||
guild_id = int(guild_id_str)
|
||||
self.servers[guild_id] = ServerConfig.from_dict(server_data)
|
||||
self.server_memories[guild_id] = {}
|
||||
print(f"📋 Loaded config for server: {server_data['guild_name']} (ID: {guild_id})")
|
||||
logger.info(f"Loaded config for server: {server_data['guild_name']} (ID: {guild_id})")
|
||||
|
||||
# After loading, check if we need to repair the config
|
||||
self.repair_config()
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to load server config: {e}")
|
||||
logger.error(f"Failed to load server config: {e}")
|
||||
self._create_default_config()
|
||||
else:
|
||||
self._create_default_config()
|
||||
@@ -101,21 +104,21 @@ class ServerManager:
|
||||
# Check if enabled_features is a string (corrupted)
|
||||
if isinstance(server.enabled_features, str):
|
||||
needs_repair = True
|
||||
print(f"🔧 Repairing corrupted enabled_features for server: {server.guild_name}")
|
||||
logger.info(f"Repairing corrupted enabled_features for server: {server.guild_name}")
|
||||
# Re-parse the features
|
||||
try:
|
||||
features_str = server.enabled_features.strip('{}')
|
||||
features_list = [f.strip().strip("'\"") for f in features_str.split(',') if f.strip()]
|
||||
server.enabled_features = set(features_list)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to repair enabled_features for {server.guild_name}: {e}")
|
||||
logger.warning(f"Failed to repair enabled_features for {server.guild_name}: {e}")
|
||||
server.enabled_features = {"autonomous", "bedtime", "monday_video"}
|
||||
|
||||
if needs_repair:
|
||||
print("🔧 Saving repaired configuration...")
|
||||
logger.info("Saving repaired configuration...")
|
||||
self.save_config()
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to repair config: {e}")
|
||||
logger.error(f"Failed to repair config: {e}")
|
||||
|
||||
def _create_default_config(self):
|
||||
"""Create default configuration for backward compatibility"""
|
||||
@@ -132,7 +135,7 @@ class ServerManager:
|
||||
self.servers[default_server.guild_id] = default_server
|
||||
self.server_memories[default_server.guild_id] = {}
|
||||
self.save_config()
|
||||
print("📋 Created default server configuration")
|
||||
logger.info("Created default server configuration")
|
||||
|
||||
def save_config(self):
|
||||
"""Save server configurations to file"""
|
||||
@@ -150,14 +153,14 @@ class ServerManager:
|
||||
with open(self.config_file, "w", encoding="utf-8") as f:
|
||||
json.dump(config_data, f, indent=2)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to save server config: {e}")
|
||||
logger.error(f"Failed to save server config: {e}")
|
||||
|
||||
def add_server(self, guild_id: int, guild_name: str, autonomous_channel_id: int,
|
||||
autonomous_channel_name: str, bedtime_channel_ids: List[int] = None,
|
||||
enabled_features: Set[str] = None) -> bool:
|
||||
"""Add a new server configuration"""
|
||||
if guild_id in self.servers:
|
||||
print(f"⚠️ Server {guild_id} already exists")
|
||||
logger.info(f"Server {guild_id} already exists")
|
||||
return False
|
||||
|
||||
if bedtime_channel_ids is None:
|
||||
@@ -178,7 +181,7 @@ class ServerManager:
|
||||
self.servers[guild_id] = server
|
||||
self.server_memories[guild_id] = {}
|
||||
self.save_config()
|
||||
print(f"✅ Added new server: {guild_name} (ID: {guild_id})")
|
||||
logger.info(f"Added new server: {guild_name} (ID: {guild_id})")
|
||||
return True
|
||||
|
||||
def remove_server(self, guild_id: int) -> bool:
|
||||
@@ -199,7 +202,7 @@ class ServerManager:
|
||||
del self.server_memories[guild_id]
|
||||
|
||||
self.save_config()
|
||||
print(f"🗑️ Removed server: {server_name} (ID: {guild_id})")
|
||||
logger.info(f"Removed server: {server_name} (ID: {guild_id})")
|
||||
return True
|
||||
|
||||
def get_server_config(self, guild_id: int) -> Optional[ServerConfig]:
|
||||
@@ -221,7 +224,7 @@ class ServerManager:
|
||||
setattr(server, key, value)
|
||||
|
||||
self.save_config()
|
||||
print(f"✅ Updated config for server: {server.guild_name}")
|
||||
logger.info(f"Updated config for server: {server.guild_name}")
|
||||
return True
|
||||
|
||||
def get_server_memory(self, guild_id: int, key: str = None):
|
||||
@@ -267,12 +270,12 @@ class ServerManager:
|
||||
from utils.moods import load_mood_description
|
||||
server.current_mood_description = load_mood_description(mood_name)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to load mood description for {mood_name}: {e}")
|
||||
logger.error(f"Failed to load mood description for {mood_name}: {e}")
|
||||
server.current_mood_description = f"I'm feeling {mood_name} today."
|
||||
|
||||
self.save_config()
|
||||
print(f"😊 Server {server.guild_name} mood changed to: {mood_name}")
|
||||
print(f"😊 Mood description: {server.current_mood_description[:100]}{'...' if len(server.current_mood_description) > 100 else ''}")
|
||||
logger.info(f"Server {server.guild_name} mood changed to: {mood_name}")
|
||||
logger.debug(f"Mood description: {server.current_mood_description[:100]}{'...' if len(server.current_mood_description) > 100 else ''}")
|
||||
return True
|
||||
|
||||
def get_server_sleep_state(self, guild_id: int) -> bool:
|
||||
@@ -323,7 +326,7 @@ class ServerManager:
|
||||
def setup_server_scheduler(self, guild_id: int, client: discord.Client):
|
||||
"""Setup independent scheduler for a specific server"""
|
||||
if guild_id not in self.servers:
|
||||
print(f"⚠️ Cannot setup scheduler for unknown server: {guild_id}")
|
||||
logger.warning(f"Cannot setup scheduler for unknown server: {guild_id}")
|
||||
return
|
||||
|
||||
server_config = self.servers[guild_id]
|
||||
@@ -363,8 +366,8 @@ class ServerManager:
|
||||
|
||||
# Add bedtime reminder job
|
||||
if "bedtime" in server_config.enabled_features:
|
||||
print(f"⏰ Setting up bedtime scheduler for server {server_config.guild_name}")
|
||||
print(f" Random time range: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} - {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d}")
|
||||
logger.info(f"Setting up bedtime scheduler for server {server_config.guild_name}")
|
||||
logger.debug(f" Random time range: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} - {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d}")
|
||||
scheduler.add_job(
|
||||
self._schedule_random_bedtime_for_server,
|
||||
CronTrigger(hour=server_config.bedtime_hour, minute=server_config.bedtime_minute),
|
||||
@@ -382,11 +385,11 @@ class ServerManager:
|
||||
|
||||
self.schedulers[guild_id] = scheduler
|
||||
scheduler.start()
|
||||
print(f"⏰ Started scheduler for server: {server_config.guild_name}")
|
||||
logger.info(f"Started scheduler for server: {server_config.guild_name}")
|
||||
|
||||
def start_all_schedulers(self, client: discord.Client):
|
||||
"""Start schedulers for all servers"""
|
||||
print("🚀 Starting all server schedulers...")
|
||||
logger.info("Starting all server schedulers...")
|
||||
|
||||
for guild_id in self.servers:
|
||||
self.setup_server_scheduler(guild_id, client)
|
||||
@@ -396,42 +399,42 @@ class ServerManager:
|
||||
# Start Figurine DM scheduler
|
||||
self.setup_figurine_updates_scheduler(client)
|
||||
|
||||
print(f"✅ Started {len(self.servers)} server schedulers + DM mood scheduler")
|
||||
logger.info(f"Started {len(self.servers)} server schedulers + DM mood scheduler")
|
||||
|
||||
def update_server_bedtime_job(self, guild_id: int, client: discord.Client):
|
||||
"""Update just the bedtime job for a specific server without restarting all schedulers"""
|
||||
server_config = self.servers.get(guild_id)
|
||||
if not server_config:
|
||||
print(f"⚠️ No server config found for guild {guild_id}")
|
||||
logger.warning(f"No server config found for guild {guild_id}")
|
||||
return False
|
||||
|
||||
scheduler = self.schedulers.get(guild_id)
|
||||
if not scheduler:
|
||||
print(f"⚠️ No scheduler found for guild {guild_id}")
|
||||
logger.warning(f"No scheduler found for guild {guild_id}")
|
||||
return False
|
||||
|
||||
# Remove existing bedtime job if it exists
|
||||
bedtime_job_id = f"bedtime_schedule_{guild_id}"
|
||||
try:
|
||||
scheduler.remove_job(bedtime_job_id)
|
||||
print(f"🗑️ Removed old bedtime job for server {guild_id}")
|
||||
logger.info(f"Removed old bedtime job for server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"ℹ️ No existing bedtime job to remove for server {guild_id}: {e}")
|
||||
logger.debug(f"No existing bedtime job to remove for server {guild_id}: {e}")
|
||||
|
||||
# Add new bedtime job with updated configuration
|
||||
if "bedtime" in server_config.enabled_features:
|
||||
print(f"⏰ Updating bedtime scheduler for server {server_config.guild_name}")
|
||||
print(f" New random time range: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} - {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d}")
|
||||
logger.info(f"Updating bedtime scheduler for server {server_config.guild_name}")
|
||||
logger.debug(f" New random time range: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} - {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d}")
|
||||
scheduler.add_job(
|
||||
self._schedule_random_bedtime_for_server,
|
||||
CronTrigger(hour=server_config.bedtime_hour, minute=server_config.bedtime_minute),
|
||||
args=[guild_id, client],
|
||||
id=bedtime_job_id
|
||||
)
|
||||
print(f"✅ Updated bedtime job for server {server_config.guild_name}")
|
||||
logger.info(f"Updated bedtime job for server {server_config.guild_name}")
|
||||
return True
|
||||
else:
|
||||
print(f"ℹ️ Bedtime feature not enabled for server {guild_id}")
|
||||
logger.info(f"Bedtime feature not enabled for server {guild_id}")
|
||||
return True
|
||||
|
||||
def setup_dm_mood_scheduler(self, client: discord.Client):
|
||||
@@ -449,10 +452,10 @@ class ServerManager:
|
||||
|
||||
scheduler.start()
|
||||
self.schedulers["dm_mood"] = scheduler
|
||||
print("🔄 DM mood rotation scheduler started (every 2 hours)")
|
||||
logger.info("DM mood rotation scheduler started (every 2 hours)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to setup DM mood scheduler: {e}")
|
||||
logger.error(f"Failed to setup DM mood scheduler: {e}")
|
||||
|
||||
def _enqueue_figurine_send(self, client: discord.Client):
|
||||
"""Enqueue the figurine DM send task in the client's loop."""
|
||||
@@ -460,11 +463,11 @@ class ServerManager:
|
||||
from utils.figurine_notifier import send_figurine_dm_to_all_subscribers
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(send_figurine_dm_to_all_subscribers(client))
|
||||
print("✅ Figurine DM send task queued")
|
||||
logger.debug("Figurine DM send task queued")
|
||||
else:
|
||||
print("⚠️ Client loop not available for figurine DM send")
|
||||
logger.warning("Client loop not available for figurine DM send")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error enqueuing figurine DM: {e}")
|
||||
logger.error(f"Error enqueuing figurine DM: {e}")
|
||||
|
||||
def _schedule_one_figurine_send_today(self, scheduler: AsyncIOScheduler, client: discord.Client):
|
||||
"""Schedule one figurine DM send at a random non-evening time today (or tomorrow if time passed)."""
|
||||
@@ -475,7 +478,7 @@ class ServerManager:
|
||||
target_time = now.replace(hour=random_hour, minute=random_minute, second=0, microsecond=0)
|
||||
if target_time <= now:
|
||||
target_time = target_time + timedelta(days=1)
|
||||
print(f"🗓️ Scheduling figurine DM at {target_time.strftime('%Y-%m-%d %H:%M')} (random non-evening)")
|
||||
logger.info(f"Scheduling figurine DM at {target_time.strftime('%Y-%m-%d %H:%M')} (random non-evening)")
|
||||
scheduler.add_job(
|
||||
self._enqueue_figurine_send,
|
||||
DateTrigger(run_date=target_time),
|
||||
@@ -499,22 +502,22 @@ class ServerManager:
|
||||
self._schedule_one_figurine_send_today(scheduler, client)
|
||||
scheduler.start()
|
||||
self.schedulers["figurine_dm"] = scheduler
|
||||
print("🗓️ Figurine updates scheduler started")
|
||||
logger.info("Figurine updates scheduler started")
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to setup figurine updates scheduler: {e}")
|
||||
logger.error(f"Failed to setup figurine updates scheduler: {e}")
|
||||
|
||||
def stop_all_schedulers(self):
|
||||
"""Stop all schedulers"""
|
||||
print("🛑 Stopping all schedulers...")
|
||||
logger.info("Stopping all schedulers...")
|
||||
|
||||
for scheduler in self.schedulers.values():
|
||||
try:
|
||||
scheduler.shutdown()
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error stopping scheduler: {e}")
|
||||
logger.warning(f"Error stopping scheduler: {e}")
|
||||
|
||||
self.schedulers.clear()
|
||||
print("✅ All schedulers stopped")
|
||||
logger.info("All schedulers stopped")
|
||||
|
||||
# Implementation of autonomous functions - these integrate with the autonomous system
|
||||
def _run_autonomous_for_server(self, guild_id: int, client: discord.Client):
|
||||
@@ -525,11 +528,11 @@ class ServerManager:
|
||||
# Create an async task in the client's event loop
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(autonomous_tick(guild_id))
|
||||
print(f"✅ [V2] Autonomous tick queued for server {guild_id}")
|
||||
logger.debug(f"[V2] Autonomous tick queued for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for autonomous tick in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for autonomous tick in server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error in autonomous tick for server {guild_id}: {e}")
|
||||
logger.error(f"Error in autonomous tick for server {guild_id}: {e}")
|
||||
|
||||
def _run_autonomous_reaction_for_server(self, guild_id: int, client: discord.Client):
|
||||
"""Run autonomous reaction for a specific server - called by APScheduler"""
|
||||
@@ -539,11 +542,11 @@ class ServerManager:
|
||||
# Create an async task in the client's event loop
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(autonomous_reaction_tick(guild_id))
|
||||
print(f"✅ [V2] Autonomous reaction queued for server {guild_id}")
|
||||
logger.debug(f"[V2] Autonomous reaction queued for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for autonomous reaction in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for autonomous reaction in server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error in autonomous reaction for server {guild_id}: {e}")
|
||||
logger.error(f"Error in autonomous reaction for server {guild_id}: {e}")
|
||||
|
||||
def _run_conversation_detection_for_server(self, guild_id: int, client: discord.Client):
|
||||
"""Run conversation detection for a specific server - called by APScheduler"""
|
||||
@@ -552,11 +555,11 @@ class ServerManager:
|
||||
# Create an async task in the client's event loop
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(miku_detect_and_join_conversation_for_server(guild_id))
|
||||
print(f"✅ Conversation detection queued for server {guild_id}")
|
||||
logger.debug(f"Conversation detection queued for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for conversation detection in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for conversation detection in server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error in conversation detection for server {guild_id}: {e}")
|
||||
logger.error(f"Error in conversation detection for server {guild_id}: {e}")
|
||||
|
||||
def _send_monday_video_for_server(self, guild_id: int, client: discord.Client):
|
||||
"""Send Monday video for a specific server - called by APScheduler"""
|
||||
@@ -565,35 +568,35 @@ class ServerManager:
|
||||
# Create an async task in the client's event loop
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(send_monday_video_for_server(guild_id))
|
||||
print(f"✅ Monday video queued for server {guild_id}")
|
||||
logger.debug(f"Monday video queued for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for Monday video in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for Monday video in server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error in Monday video for server {guild_id}: {e}")
|
||||
logger.error(f"Error in Monday video for server {guild_id}: {e}")
|
||||
|
||||
def _schedule_random_bedtime_for_server(self, guild_id: int, client: discord.Client):
|
||||
"""Schedule bedtime reminder for a specific server at a random time within the configured range"""
|
||||
print(f"⏰ Bedtime scheduler triggered for server {guild_id} at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
logger.info(f"Bedtime scheduler triggered for server {guild_id} at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
# Get server config to determine the random time range
|
||||
server_config = self.servers.get(guild_id)
|
||||
if not server_config:
|
||||
print(f"⚠️ No server config found for guild {guild_id}")
|
||||
logger.warning(f"No server config found for guild {guild_id}")
|
||||
return
|
||||
|
||||
# Calculate random time within the bedtime range
|
||||
start_minutes = server_config.bedtime_hour * 60 + server_config.bedtime_minute
|
||||
end_minutes = server_config.bedtime_hour_end * 60 + server_config.bedtime_minute_end
|
||||
|
||||
print(f"🕐 Bedtime range calculation: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} ({start_minutes} min) to {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d} ({end_minutes} min)")
|
||||
logger.debug(f"Bedtime range calculation: {server_config.bedtime_hour:02d}:{server_config.bedtime_minute:02d} ({start_minutes} min) to {server_config.bedtime_hour_end:02d}:{server_config.bedtime_minute_end:02d} ({end_minutes} min)")
|
||||
|
||||
# Handle case where end time is next day (e.g., 23:30 to 00:30)
|
||||
if end_minutes <= start_minutes:
|
||||
end_minutes += 24 * 60 # Add 24 hours
|
||||
print(f"🌙 Cross-midnight range detected, adjusted end to {end_minutes} minutes")
|
||||
logger.debug(f"Cross-midnight range detected, adjusted end to {end_minutes} minutes")
|
||||
|
||||
random_minutes = random.randint(start_minutes, end_minutes)
|
||||
print(f"🎲 Random time selected: {random_minutes} minutes from midnight")
|
||||
logger.debug(f"Random time selected: {random_minutes} minutes from midnight")
|
||||
|
||||
# Convert back to hours and minutes
|
||||
random_hour = (random_minutes // 60) % 24
|
||||
@@ -609,7 +612,7 @@ class ServerManager:
|
||||
|
||||
delay_seconds = (target_time - now).total_seconds()
|
||||
|
||||
print(f"🎲 Random bedtime for server {server_config.guild_name}: {random_hour:02d}:{random_minute:02d} (in {delay_seconds/60:.1f} minutes)")
|
||||
logger.info(f"Random bedtime for server {server_config.guild_name}: {random_hour:02d}:{random_minute:02d} (in {delay_seconds/60:.1f} minutes)")
|
||||
|
||||
# Schedule the actual bedtime reminder
|
||||
try:
|
||||
@@ -618,9 +621,9 @@ class ServerManager:
|
||||
def send_bedtime_delayed():
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(send_bedtime_reminder_for_server(guild_id, client))
|
||||
print(f"✅ Random bedtime reminder sent for server {guild_id}")
|
||||
logger.info(f"Random bedtime reminder sent for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for bedtime reminder in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for bedtime reminder in server {guild_id}")
|
||||
|
||||
# Use the scheduler to schedule the delayed bedtime reminder
|
||||
scheduler = self.schedulers.get(guild_id)
|
||||
@@ -630,12 +633,12 @@ class ServerManager:
|
||||
DateTrigger(run_date=target_time),
|
||||
id=f"bedtime_reminder_{guild_id}_{int(target_time.timestamp())}"
|
||||
)
|
||||
print(f"✅ Bedtime reminder scheduled for server {guild_id} at {target_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
logger.info(f"Bedtime reminder scheduled for server {guild_id} at {target_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
else:
|
||||
print(f"⚠️ No scheduler found for server {guild_id}")
|
||||
logger.warning(f"No scheduler found for server {guild_id}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error scheduling bedtime reminder for server {guild_id}: {e}")
|
||||
logger.error(f"Error scheduling bedtime reminder for server {guild_id}: {e}")
|
||||
|
||||
def _rotate_server_mood(self, guild_id: int, client: discord.Client):
|
||||
"""Rotate mood for a specific server - called by APScheduler"""
|
||||
@@ -644,11 +647,11 @@ class ServerManager:
|
||||
# Create an async task in the client's event loop
|
||||
if client.loop and client.loop.is_running():
|
||||
client.loop.create_task(rotate_server_mood(guild_id))
|
||||
print(f"✅ Mood rotation queued for server {guild_id}")
|
||||
logger.debug(f"Mood rotation queued for server {guild_id}")
|
||||
else:
|
||||
print(f"⚠️ Client loop not available for mood rotation in server {guild_id}")
|
||||
logger.warning(f"Client loop not available for mood rotation in server {guild_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error in mood rotation for server {guild_id}: {e}")
|
||||
logger.error(f"Error in mood rotation for server {guild_id}: {e}")
|
||||
|
||||
# Global instance
|
||||
server_manager = ServerManager()
|
||||
|
||||
Reference in New Issue
Block a user