Files
miku-discord/bot/routes/servers.py
koko210Serve 979217e7cc refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:

  core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
  bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
  profile_picture.py (26), manual_send.py (3), servers.py (6),
  figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
  config.py (7), logging_config.py (9), voice.py (3), memory.py (10)

All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00

138 lines
5.4 KiB
Python

"""Server management routes: CRUD, bedtime, repair."""
import os
import json
from fastapi import APIRouter
import globals
from server_manager import server_manager
from routes.models import ServerConfigRequest
from utils.logger import get_logger
logger = get_logger('api')
router = APIRouter()
@router.get("/servers")
def get_servers():
"""Get all configured servers"""
logger.debug("/servers endpoint called")
logger.debug(f"server_manager.servers keys: {list(server_manager.servers.keys())}")
logger.debug(f"server_manager.servers count: {len(server_manager.servers)}")
config_file = server_manager.config_file
logger.debug(f"Config file path: {config_file}")
if os.path.exists(config_file):
try:
with open(config_file, "r", encoding="utf-8") as f:
config_data = json.load(f)
logger.debug(f"Config file contains: {list(config_data.keys())}")
except Exception as e:
logger.error(f"Failed to read config file: {e}")
else:
logger.warning("Config file does not exist")
servers = []
for server in server_manager.get_all_servers():
server_data = server.to_dict()
server_data['enabled_features'] = list(server_data['enabled_features'])
server_data['guild_id'] = str(server_data['guild_id'])
servers.append(server_data)
logger.debug(f"Adding server to response: {server_data['guild_id']} - {server_data['guild_name']}")
logger.debug(f"Server data type check - guild_id: {type(server_data['guild_id'])}, value: {server_data['guild_id']}")
logger.debug(f"Returning {len(servers)} servers")
return {"servers": servers}
@router.post("/servers")
def add_server(data: ServerConfigRequest):
"""Add a new server configuration"""
enabled_features = set(data.enabled_features) if data.enabled_features else None
success = server_manager.add_server(
guild_id=data.guild_id,
guild_name=data.guild_name,
autonomous_channel_id=data.autonomous_channel_id,
autonomous_channel_name=data.autonomous_channel_name,
bedtime_channel_ids=data.bedtime_channel_ids,
enabled_features=enabled_features
)
if success:
server_manager.stop_all_schedulers()
server_manager.start_all_schedulers(globals.client)
return {"status": "ok", "message": f"Server {data.guild_name} added successfully"}
else:
return {"status": "error", "message": "Failed to add server"}
@router.delete("/servers/{guild_id}")
def remove_server(guild_id: int):
"""Remove a server configuration"""
success = server_manager.remove_server(guild_id)
if success:
return {"status": "ok", "message": "Server removed successfully"}
else:
return {"status": "error", "message": "Failed to remove server"}
@router.put("/servers/{guild_id}")
def update_server(guild_id: int, data: dict):
"""Update server configuration"""
success = server_manager.update_server_config(guild_id, **data)
if success:
server_manager.stop_all_schedulers()
server_manager.start_all_schedulers(globals.client)
return {"status": "ok", "message": "Server configuration updated"}
else:
return {"status": "error", "message": "Failed to update server configuration"}
@router.post("/servers/{guild_id}/bedtime-range")
def update_server_bedtime_range(guild_id: int, data: dict):
"""Update server bedtime range configuration"""
logger.debug(f"Updating bedtime range for server {guild_id}: {data}")
required_fields = ['bedtime_hour', 'bedtime_minute', 'bedtime_hour_end', 'bedtime_minute_end']
for field in required_fields:
if field not in data:
return {"status": "error", "message": f"Missing required field: {field}"}
try:
bedtime_hour = int(data['bedtime_hour'])
bedtime_minute = int(data['bedtime_minute'])
bedtime_hour_end = int(data['bedtime_hour_end'])
bedtime_minute_end = int(data['bedtime_minute_end'])
if not (0 <= bedtime_hour <= 23) or not (0 <= bedtime_hour_end <= 23):
return {"status": "error", "message": "Hours must be between 0 and 23"}
if not (0 <= bedtime_minute <= 59) or not (0 <= bedtime_minute_end <= 59):
return {"status": "error", "message": "Minutes must be between 0 and 59"}
except (ValueError, TypeError):
return {"status": "error", "message": "Invalid time values provided"}
success = server_manager.update_server_config(guild_id, **data)
if success:
job_success = server_manager.update_server_bedtime_job(guild_id, globals.client)
if job_success:
logger.info(f"Bedtime range updated for server {guild_id}")
return {
"status": "ok",
"message": f"Bedtime range updated: {bedtime_hour:02d}:{bedtime_minute:02d} - {bedtime_hour_end:02d}:{bedtime_minute_end:02d}"
}
else:
return {"status": "error", "message": "Updated config but failed to update scheduler"}
else:
return {"status": "error", "message": "Failed to update bedtime range"}
@router.post("/servers/repair")
def repair_server_config():
"""Repair corrupted server configuration"""
try:
server_manager.repair_config()
return {"status": "ok", "message": "Server configuration repaired and saved"}
except Exception as e:
return {"status": "error", "message": f"Failed to repair configuration: {e}"}