Files
miku-discord/bot/routes/autonomous.py

263 lines
12 KiB
Python
Raw Permalink Normal View History

"""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)})