Source code for tools.discord_message_reactions

"""Read reactions on a specific Discord message."""

from __future__ import annotations

import json
import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from tool_context import ToolContext

logger = logging.getLogger(__name__)

_REACTION_USERS_PREVIEW_LIMIT = 50

TOOL_NAME = "get_message_reactions"
TOOL_DESCRIPTION = (
    "Retrieve reactions on a specific Discord message, including sample "
    "users per emoji (up to a cap—see users_truncated). "
    "Pass channel_id when known for instant lookup; omitting it tries the "
    "current channel, then guild, then a full scan (slow)."
)
TOOL_PARAMETERS = {
    "type": "object",
    "properties": {
        "message_id": {
            "type": "string",
            "description": "The ID of the message to check reactions on.",
        },
        "channel_id": {
            "type": "string",
            "description": (
                "Channel containing the message. Strongly recommended for "
                "fast lookup; if omitted, context channel → same guild → "
                "global search."
            ),
        },
    },
    "required": ["message_id"],
}


[docs] async def run( message_id: str, channel_id: str | None = None, ctx: ToolContext | None = None, ) -> str: """Fetch reactions on a message and return them as JSON. Args: message_id: The Discord message ID. channel_id: Optional channel ID to narrow the search. ctx: Tool execution context. Returns: JSON string mapping emoji → list of user display names. """ from tools._discord_helpers import ( require_discord_client, resolve_discord_message, ) client = require_discord_client(ctx) if isinstance(client, str): return client try: msg_id = int(message_id) except ValueError: return f"Error: Invalid message ID: '{message_id}'." msg = await resolve_discord_message( client, msg_id, message_id_display=message_id, channel_id=channel_id, ctx=ctx, ) if isinstance(msg, str): return msg if not msg.reactions: return json.dumps({ "message_id": message_id, "reactions": [], "summary": "No reactions on this message.", }) reactions_data = [] for reaction in msg.reactions: emoji_str = str(reaction.emoji) users: list[str] = [] truncated = False try: async for user in reaction.users( limit=_REACTION_USERS_PREVIEW_LIMIT, ): users.append(user.display_name) truncated = reaction.count > len(users) except Exception: users = [f"({reaction.count} users – could not fetch names)"] truncated = False reactions_data.append({ "emoji": emoji_str, "count": reaction.count, "users": users, "users_truncated": truncated, }) return json.dumps({ "message_id": message_id, "channel_id": str(msg.channel.id), "total_reactions": sum(r["count"] for r in reactions_data), "reactions": reactions_data, "users_preview_limit": _REACTION_USERS_PREVIEW_LIMIT, }, indent=2)