"""Autonomous action routes: V1, V2, per-server autonomous.""" from fastapi import APIRouter from fastapi.responses import JSONResponse import globals from server_manager import server_manager from routes.models import CustomPromptRequest from utils.logger import get_logger logger = get_logger('api') router = APIRouter() # ========== Autonomous V1 ========== @router.post("/autonomous/general") async def trigger_autonomous_general(guild_id: int = None): if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: from utils.autonomous import miku_say_something_general_for_server globals.client.loop.create_task(miku_say_something_general_for_server(guild_id)) return {"status": "ok", "message": f"Autonomous general message queued for server {guild_id}"} else: from utils.autonomous import miku_say_something_general globals.client.loop.create_task(miku_say_something_general()) return {"status": "ok", "message": "Autonomous general message queued for all servers"} else: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) @router.post("/autonomous/engage") async def trigger_autonomous_engage_user( guild_id: int = None, user_id: str = None, engagement_type: str = None, manual_trigger: str = "false" ): manual_trigger_bool = manual_trigger.lower() in ('true', '1', 'yes') if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: from utils.autonomous import miku_engage_random_user_for_server globals.client.loop.create_task(miku_engage_random_user_for_server(guild_id, user_id=user_id, engagement_type=engagement_type, manual_trigger=manual_trigger_bool)) msg_parts = [f"Autonomous user engagement queued for server {guild_id}"] if user_id: msg_parts.append(f"targeting user {user_id}") if engagement_type: msg_parts.append(f"with {engagement_type} engagement") if manual_trigger_bool: msg_parts.append("(manual trigger - bypassing cooldown)") return {"status": "ok", "message": " ".join(msg_parts)} else: from utils.autonomous import miku_engage_random_user globals.client.loop.create_task(miku_engage_random_user(user_id=user_id, engagement_type=engagement_type, manual_trigger=manual_trigger_bool)) msg_parts = ["Autonomous user engagement queued for all servers"] if user_id: msg_parts.append(f"targeting user {user_id}") if engagement_type: msg_parts.append(f"with {engagement_type} engagement") if manual_trigger_bool: msg_parts.append("(manual trigger - bypassing cooldown)") return {"status": "ok", "message": " ".join(msg_parts)} else: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) @router.post("/autonomous/tweet") async def trigger_autonomous_tweet(guild_id: int = None, tweet_url: str = None): if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: from utils.autonomous import share_miku_tweet_for_server globals.client.loop.create_task(share_miku_tweet_for_server(guild_id, tweet_url=tweet_url)) msg = f"Autonomous tweet sharing queued for server {guild_id}" if tweet_url: msg += f" with URL {tweet_url}" return {"status": "ok", "message": msg} else: from utils.autonomous import share_miku_tweet globals.client.loop.create_task(share_miku_tweet(tweet_url=tweet_url)) msg = "Autonomous tweet sharing queued for all servers" if tweet_url: msg += f" with URL {tweet_url}" return {"status": "ok", "message": msg} else: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) @router.post("/autonomous/custom") async def custom_autonomous_message(req: CustomPromptRequest, guild_id: int = None): if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: from utils.autonomous import handle_custom_prompt_for_server globals.client.loop.create_task(handle_custom_prompt_for_server(guild_id, req.prompt)) return {"status": "ok", "message": f"Custom autonomous message queued for server {guild_id}"} else: from utils.autonomous import handle_custom_prompt globals.client.loop.create_task(handle_custom_prompt(req.prompt)) return {"status": "ok", "message": "Custom autonomous message queued for all servers"} else: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) @router.post("/autonomous/reaction") async def trigger_autonomous_reaction(guild_id: int = None): if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: from utils.autonomous import miku_autonomous_reaction_for_server globals.client.loop.create_task(miku_autonomous_reaction_for_server(guild_id, force=True)) return {"status": "ok", "message": f"Autonomous reaction queued for server {guild_id}"} else: from utils.autonomous import miku_autonomous_reaction globals.client.loop.create_task(miku_autonomous_reaction(force=True)) return {"status": "ok", "message": "Autonomous reaction queued for all servers"} else: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) @router.post("/autonomous/join-conversation") async def trigger_detect_and_join_conversation(guild_id: int = None): logger.debug(f"Join conversation endpoint called with guild_id={guild_id}") if globals.client and globals.client.loop and globals.client.loop.is_running(): if guild_id is not None: logger.debug(f"Importing and calling miku_detect_and_join_conversation_for_server({guild_id}, force=True)") from utils.autonomous import miku_detect_and_join_conversation_for_server globals.client.loop.create_task(miku_detect_and_join_conversation_for_server(guild_id, force=True)) return {"status": "ok", "message": f"Detect and join conversation queued for server {guild_id}"} else: logger.debug(f"Importing and calling miku_detect_and_join_conversation() for all servers") from utils.autonomous import miku_detect_and_join_conversation globals.client.loop.create_task(miku_detect_and_join_conversation(force=True)) return {"status": "ok", "message": "Detect and join conversation queued for all servers"} else: logger.error(f"Bot not ready: client={globals.client}, loop={globals.client.loop if globals.client else None}") return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) # ========== Per-Server Autonomous ========== @router.post("/servers/{guild_id}/autonomous/general") async def trigger_autonomous_general_for_server(guild_id: int): """Trigger autonomous general message for a specific server""" from utils.autonomous import miku_say_something_general_for_server try: await miku_say_something_general_for_server(guild_id) return {"status": "ok", "message": f"Autonomous general message triggered for server {guild_id}"} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": f"Failed to trigger autonomous message: {e}"}) @router.post("/servers/{guild_id}/autonomous/engage") async def trigger_autonomous_engage_for_server( guild_id: int, user_id: str = None, engagement_type: str = None, manual_trigger: str = "false" ): """Trigger autonomous user engagement for a specific server""" manual_trigger_bool = manual_trigger.lower() in ('true', '1', 'yes') from utils.autonomous import miku_engage_random_user_for_server try: await miku_engage_random_user_for_server(guild_id, user_id=user_id, engagement_type=engagement_type, manual_trigger=manual_trigger_bool) msg_parts = [f"Autonomous user engagement triggered for server {guild_id}"] if user_id: msg_parts.append(f"targeting user {user_id}") if engagement_type: msg_parts.append(f"with {engagement_type} engagement") if manual_trigger_bool: msg_parts.append("(manual trigger - bypassing cooldown)") return {"status": "ok", "message": " ".join(msg_parts)} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": f"Failed to trigger user engagement: {e}"}) @router.post("/servers/{guild_id}/autonomous/custom") async def custom_autonomous_message_for_server(guild_id: int, req: CustomPromptRequest): """Send custom autonomous message to a specific server""" from utils.autonomous import handle_custom_prompt_for_server try: success = await handle_custom_prompt_for_server(guild_id, req.prompt) if success: return {"status": "ok", "message": f"Custom autonomous message sent to server {guild_id}"} else: return JSONResponse(status_code=500, content={"status": "error", "message": f"Failed to send custom message to server {guild_id}"}) except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": f"Error: {e}"}) @router.post("/servers/{guild_id}/autonomous/tweet") async def trigger_autonomous_tweet_for_server(guild_id: int): """Trigger autonomous tweet sharing for a specific server""" from utils.autonomous import share_miku_tweet_for_server try: await share_miku_tweet_for_server(guild_id) return {"status": "ok", "message": f"Autonomous tweet sharing triggered for server {guild_id}"} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": f"Failed to trigger tweet sharing: {e}"}) # ========== Autonomous V2 ========== @router.get("/autonomous/v2/stats/{guild_id}") async def get_v2_stats(guild_id: int): """Get current V2 social stats for a server""" try: from utils.autonomous_v2_integration import get_v2_stats_for_server stats = get_v2_stats_for_server(guild_id) return {"status": "ok", "guild_id": guild_id, "stats": stats} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) @router.get("/autonomous/v2/check/{guild_id}") async def manual_v2_check(guild_id: int): """Manually trigger a V2 context check""" try: from utils.autonomous_v2_integration import manual_trigger_v2_check if not globals.client: return JSONResponse(status_code=503, content={"status": "error", "message": "Bot not ready"}) result = await manual_trigger_v2_check(guild_id, globals.client) if isinstance(result, str): return JSONResponse(status_code=500, content={"status": "error", "message": result}) return {"status": "ok", "guild_id": guild_id, "analysis": result} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) @router.get("/autonomous/v2/status") async def get_v2_status(): """Get V2 system status for all servers""" try: from utils.autonomous_v2 import autonomous_system_v2 status = {} for guild_id in server_manager.servers: server_config = server_manager.get_server_config(guild_id) if server_config: stats = autonomous_system_v2.get_stats(guild_id) status[str(guild_id)] = { "server_name": server_config.guild_name, "loop_running": autonomous_system_v2.running_loops.get(guild_id, False), "action_urgency": f"{stats.get_action_urgency():.2f}", "loneliness": f"{stats.loneliness:.2f}", "boredom": f"{stats.boredom:.2f}", "excitement": f"{stats.excitement:.2f}", "chattiness": f"{stats.chattiness:.2f}", } return {"status": "ok", "servers": status} except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})