"""Leave a Discord server."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from tool_context import ToolContext
logger = logging.getLogger(__name__)
TOOL_NAME = "discord_leave_server"
TOOL_DESCRIPTION = (
"Make the bot leave a specified Discord server. "
"Requires admin permissions from the requesting user."
)
TOOL_PARAMETERS = {
"type": "object",
"properties": {
"server_id": {
"type": "string",
"description": "The Discord server (guild) ID to leave.",
},
},
"required": ["server_id"],
}
[docs]
async def run(
server_id: str,
ctx: ToolContext | None = None,
) -> str:
"""Execute this tool and return the result.
Args:
server_id (str): The server id value.
ctx (ToolContext | None): Tool execution context providing access to bot internals.
Returns:
str: Result string.
"""
from tools._discord_helpers import (
require_discord_client,
check_admin_permission,
)
client = require_discord_client(ctx)
if isinstance(client, str):
return client
user_id = ctx.user_id if ctx else ""
# Check bot admin first — bot admins can always leave any server
is_bot_admin = False
if ctx:
config = getattr(ctx, "config", None)
admin_ids = getattr(config, "admin_user_ids", None) or []
is_bot_admin = str(user_id) in admin_ids
if not is_bot_admin:
# Fall back to Discord guild permissions
ok, err = await check_admin_permission(
client, user_id, server_id,
)
if not ok:
return err
try:
server = client.get_guild(int(server_id))
except ValueError:
return f"Error: Invalid server ID: '{server_id}'."
if not server:
return f"Error: Server '{server_id}' not found."
sname = server.name
try:
await server.leave()
return f"Successfully left server '{sname}'."
except Exception as exc:
return f"Error leaving server: {exc}"