"""API Wrapper Tools for Slack

DO NOT EDIT THIS MODULE DIRECTLY.

THIS MODULE WAS AUTO-GENERATED BY TRANSPILING THE API WRAPPER TOOL JSON DEFINITIONS
IN THE ../wrapper_tools DIRECTORY INTO PYTHON CODE. ANY CHANGES TO THIS MODULE WILL
BE OVERWRITTEN BY THE TRANSPILER.
"""

from typing import Annotated, Any

import httpx
from arcade_tdk import ToolContext, tool
from arcade_tdk.auth import OAuth2


def remove_none_values(data: dict[str, Any]) -> dict[str, Any]:
    return {k: v for k, v in data.items() if v is not None}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:write"]))
async def add_slack_emoji_alias(
    context: ToolContext,
    emoji_alias_name: Annotated[
        str,
        "The new alias for the specified emoji. Whitespace or colons will be automatically trimmed.",  # noqa: E501
    ],
    target_emoji_name: Annotated[
        str,
        "The name of the existing emoji to which the new alias is being added. Remove any surrounding whitespace or colons.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.emoji.addAlias'."]:
    """Add an emoji alias in a Slack Enterprise organization.

    This tool calls the Slack API to add an alias for an emoji within a Slack Enterprise organization. It should be used when a user wants to create a new shortcut or name for an existing emoji. Requires appropriate admin permissions."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.emoji.addAlias",
            params=remove_none_values({"name": emoji_alias_name, "alias_for": target_emoji_name}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:read"]))
async def list_slack_enterprise_emojis(
    context: ToolContext,
    pagination_cursor: Annotated[
        str | None,
        "Cursor for fetching the next page of emojis. Use 'next_cursor' from the previous response.",  # noqa: E501
    ] = None,
    max_items_to_return: Annotated[
        int | None,
        "The maximum number of emojis to return, between 1 and 1000 inclusive. (default: '100')",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.emoji.list'."]:
    """Retrieve emojis for a Slack Enterprise organization.

    This tool uses the Slack Admin API to fetch a list of emojis available in a Slack Enterprise organization. It requires the appropriate OAuth scope to access team information."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.emoji.list",
            params=remove_none_values({"cursor": pagination_cursor, "limit": max_items_to_return}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:write"]))
async def rename_slack_emoji(
    context: ToolContext,
    current_emoji_name: Annotated[
        str,
        "The current name of the emoji to be renamed. Colons (:myemoji:) around the value are optional.",  # noqa: E501
    ],
    new_emoji_name: Annotated[
        str, "The new name to assign to the emoji in the Slack Enterprise organization."
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.emoji.rename'."]:
    """Rename an emoji in a Slack Enterprise organization.

    Use this tool to rename a custom emoji within a Slack Enterprise organization. It requires appropriate OAuth scope for team operations."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.emoji.rename",
            params=remove_none_values({"name": current_emoji_name, "new_name": new_emoji_name}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.invites:read"]))
async def list_approved_workspace_invite_requests(
    context: ToolContext,
    workspace_id: Annotated[
        str | None,
        "ID for the Slack workspace where the invite requests were made. Required if the Enterprise org has more than one workspace.",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "Value of the `next_cursor` from the previous API response for paginating results.",
    ] = None,
    result_limit: Annotated[
        int | None,
        "Specify the number of results to return, between 1 and 1000 inclusive. (default: '100')",
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'admin.inviteRequests.approved.list'."
]:
    """Retrieve all approved workspace invite requests from Slack.

    This tool retrieves a list of all approved invite requests for a Slack workspace. It should be called when there is a need to review or manage approved invitations. The response will include details of each invitation request."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.inviteRequests.approved.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_id,
                "cursor": pagination_cursor,
                "limit": result_limit,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.invites:read"]))
async def list_denied_slack_invite_requests(
    context: ToolContext,
    workspace_team_id: Annotated[
        str | None,
        "ID of the workspace where the invite requests were made. Required if the Enterprise org has multiple workspaces.",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "The cursor value from the previous API response to fetch the next set of results. Use this for pagination.",  # noqa: E501
    ] = None,
    result_limit: Annotated[
        int | None,
        "Specify the number of denied invite request results to return, between 1 and 1000 inclusive. (default: '100')",  # noqa: E501
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'admin.inviteRequests.denied.list'."
]:
    """Retrieve denied Slack workspace invite requests.

    This tool retrieves a list of all denied workspace invite requests on Slack. It should be called when there is a need to review or analyze denied invitations to a Slack workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.inviteRequests.denied.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_team_id,
                "cursor": pagination_cursor,
                "limit": result_limit,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.invites:read"]))
async def list_pending_workspace_invites(
    context: ToolContext,
    workspace_id: Annotated[
        str | None,
        "The ID of the workspace to list pending invite requests from. Required for multi-workspace enterprises.",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "The cursor value for fetching the next set of invite requests. Use the `next_cursor` from the previous response if available.",  # noqa: E501
    ] = None,
    result_limit: Annotated[
        int | None,
        "The number of invite requests to return per call, must be between 1 and 1000. (default: '100')",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.inviteRequests.list'."]:
    """Retrieve all pending workspace invite requests from Slack.

    Use this tool to list all pending workspace invite requests in a Slack workspace. This can be useful for administrators managing team invitations. Requires 'admin.invites:read' OAuth scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.inviteRequests.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_id,
                "cursor": pagination_cursor,
                "limit": result_limit,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:read"]))
async def list_teams_in_enterprise(
    context: ToolContext,
    maximum_items_to_return: Annotated[
        int | None,
        "Specify the maximum number of teams to retrieve. Must be a positive integer, up to 1000. (default: '100')",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "Use this to retrieve the next page of results by setting it to the `next_cursor` from the previous response.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.teams.list'."]:
    """Retrieve all teams in an Enterprise organization on Slack.

    This tool retrieves a list of all teams within an Enterprise organization on Slack, utilizing the admin.teams.list endpoint. It should be called when information about the teams in an Enterprise organization is needed."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.teams.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "limit": maximum_items_to_return,
                "cursor": pagination_cursor,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:read"]))
async def list_slack_workspace_owners(
    context: ToolContext,
    workspace_id: Annotated[
        str, "The unique identifier of the Slack workspace for which to list the owners."
    ],
    maximum_items_to_return: Annotated[
        int | None,
        "Specifies the maximum number of owners to return, ranging from 1 to 1000. (default: '100')",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "The cursor from the previous response used to fetch the next page of owners. Leave empty for the first page.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.teams.owners.list'."]:
    """Retrieve all owners in a Slack workspace.

    This tool retrieves a list of all the owners in a specified Slack workspace, using the admin.teams.owners.list API endpoint. It is useful for managing or viewing the user roles within a Slack workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.teams.owners.list",
            params=remove_none_values({
                "team_id": workspace_id,
                "limit": maximum_items_to_return,
                "cursor": pagination_cursor,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:read"]))
async def fetch_workspace_settings_info(
    context: ToolContext,
    slack_team_id: Annotated[
        str,
        "The unique identifier of the Slack workspace (team) for which to fetch the settings information.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.teams.settings.info'."]:
    """Retrieve settings information for a Slack workspace.

    This tool calls the Slack API to fetch detailed information about settings in a specific workspace. It is useful for administrators who need to manage team settings. The tool requires appropriate OAuth scopes for access."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.teams.settings.info",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"team_id": slack_team_id}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:write"]))
async def set_workspace_description(
    context: ToolContext,
    workspace_id: Annotated[
        str, "The unique identifier for the Slack workspace where the description will be updated."
    ],
    workspace_description: Annotated[
        str, "The new description to set for the Slack workspace. Provide a clear and concise text."
    ],
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'admin.teams.settings.setDescription'."
]:
    """Update the description of a Slack workspace.

    This tool updates the description of a specified workspace in Slack. It requires admin permissions with the 'admin.teams:write' scope. It should be called when there is a need to change or set a new description for a Slack team."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.teams.settings.setDescription",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_id,
                "description": workspace_description,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.teams:write"]))
async def set_slack_workspace_name(
    context: ToolContext,
    workspace_id: Annotated[
        str, "Unique identifier for the Slack workspace whose name you want to update."
    ],
    new_workspace_name: Annotated[
        str, "The desired new name for the Slack workspace. This replaces the existing name."
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.teams.settings.setName'."]:
    """Update the name of a Slack workspace.

    Use this tool to update the name of a specified Slack workspace. This tool should be called when there's a need to change the workspace name. It requires appropriate permissions."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.teams.settings.setName",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"team_id": workspace_id, "name": new_workspace_name}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.usergroups:read"]))
async def list_channels_for_usergroup(
    context: ToolContext,
    usergroup_id: Annotated[
        str,
        "The ID of the IDP group to list channels for. It identifies which organizational group to retrieve the default channels from.",  # noqa: E501
    ],
    workspace_id: Annotated[str | None, "The unique identifier for the Slack workspace."] = None,
    include_member_count_in_channels: Annotated[
        bool | None,
        "Set to true to include the count of members for each channel, otherwise set to false.",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.usergroups.listChannels'."]:
    """Retrieve channels linked to an org-level user group in Slack.

    Fetches a list of channels associated with a specified organizational IDP group in Slack. This tool is useful for admins managing user groups and their related channels."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.usergroups.listChannels",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "usergroup_id": usergroup_id,
                "team_id": workspace_id,
                "include_num_members": include_member_count_in_channels,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin.users:read"]))
async def list_workspace_users(
    context: ToolContext,
    workspace_team_id: Annotated[
        str | None,
        "The ID of the Slack workspace (e.g., T1234) to filter users from. Only users from this workspace will be listed.",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "Use this to navigate through paginated results by setting it to the `next_cursor` from a previous response.",  # noqa: E501
    ] = None,
    user_retrieval_limit: Annotated[
        int | None,
        "Maximum number of users to retrieve per page from the Slack workspace. (default: '100')",
    ] = None,
    return_only_active_users: Annotated[
        bool | None,
        "Return only active users if true; return only deactivated users if false. Default is true.",  # noqa: E501
    ] = None,
    include_deactivated_user_workspaces: Annotated[
        bool | None,
        "Include workspaces for users even if they are deactivated. Only applies with org token and no team_id. Default is false.",  # noqa: E501
    ] = None,
    return_only_guest_users: Annotated[
        bool | None,
        "If true, returns only guests and their expiration dates that belong to the specified team_id.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'admin.users.list'."]:
    """Retrieve a list of users from a Slack workspace.

    Use this tool to get a list of users in a specific Slack workspace. It's helpful for administrators who need to manage or view user information within the workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/admin.users.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_team_id,
                "cursor": pagination_cursor,
                "is_active": return_only_active_users,
                "include_deactivated_user_workspaces": include_deactivated_user_workspaces,
                "only_guests": return_only_guest_users,
                "limit": user_retrieval_limit,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack"))
async def check_api_calling_code(
    context: ToolContext,
    simulate_error_response: Annotated[
        str | None,
        "Specify an error code to simulate an error response for testing API calls. Useful for testing error handling.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'api.test'."]:
    """Verify the correctness of API calling code for Slack.

    This tool verifies the accuracy and functionality of an API calling code by calling Slack's API testing endpoint. It's useful for developers who want to check if their code successfully interacts with Slack's API."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/api.test",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"error": simulate_error_response}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack"))
async def revoke_slack_token(
    context: ToolContext,
    trigger_testing_mode: Annotated[
        bool | None,
        "Set to true to trigger testing mode where the token will not be revoked. Useful for testing.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'auth.revoke'."]:
    """Revoke a Slack authentication token.

    This tool is used to revoke a Slack authentication token via a GET request to the Slack API endpoint. It should be called when it is necessary to invalidate a token to ensure it is no longer usable."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/auth.revoke",
            params=remove_none_values({"test": trigger_testing_mode}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["bookmarks:write"]))
async def edit_slack_bookmark(
    context: ToolContext,
    slack_channel_id: Annotated[
        str, "The ID of the Slack channel where the bookmark will be updated."
    ],
    target_bookmark_id: Annotated[str, "The unique identifier of the bookmark you want to update."],
    bookmark_title: Annotated[str | None, "The new title for the bookmark to update."] = None,
    bookmark_link: Annotated[
        str | None,
        "URL of the bookmark to be edited. Ensure it is a valid format starting with http or https.",  # noqa: E501
    ] = None,
    emoji_tag: Annotated[
        str | None,
        "The emoji tag to apply to the bookmark link. It should be a valid emoji code (e.g., :smile:).",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'bookmarks.edit'."]:
    """Edit an existing bookmark in a Slack channel.

    This tool is used to edit an existing bookmark in a specified Slack channel. It requires appropriate permissions and should be called when you need to update the details of a bookmark in any channel you have access to."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/bookmarks.edit",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel_id": slack_channel_id,
                "bookmark_id": target_bookmark_id,
                "title": bookmark_title,
                "link": bookmark_link,
                "emoji": emoji_tag,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["bookmarks:write"]))
async def remove_slack_bookmark(
    context: ToolContext,
    slack_channel_id_to_remove_bookmark: Annotated[
        str,
        "The ID of the Slack channel from which the bookmark should be removed. This ID specifies the target channel and is required to locate and delete the bookmark.",  # noqa: E501
    ],
    bookmark_id_to_remove: Annotated[
        str,
        "The ID of the bookmark to be removed from a Slack channel. Ensure it is specified correctly to delete the correct bookmark.",  # noqa: E501
    ],
    quip_section_id: Annotated[
        str | None,
        "The ID of the Quip section to unbookmark. This is required to specify which section's bookmark should be removed.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'bookmarks.remove'."]:
    """Remove a bookmark from a Slack channel.

    This tool removes a specified bookmark from a Slack channel. It should be called when a user wants to delete a bookmark that is no longer needed or relevant. Requires appropriate permissions to execute."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/bookmarks.remove",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel_id": slack_channel_id_to_remove_bookmark,
                "bookmark_id": bookmark_id_to_remove,
                "quip_section_id": quip_section_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users:read"]))
async def get_slack_bot_info(
    context: ToolContext,
    target_bot_id: Annotated[
        str | None,
        "The unique bot ID for which information is requested. This ID is specific to each workspace the bot is in.",  # noqa: E501
    ] = None,
    team_id_for_org_token_use: Annotated[
        str | None,
        "Encoded team or enterprise ID where the bot exists. Required if using an organization token. Ignored if using a workspace-level token.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'bots.info'."]:
    """Retrieve details about a Slack bot user.

    This tool fetches information about a bot user in Slack. It should be called when details about a specific Slack bot are needed, such as its name, ID, or other metadata."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/bots.info",
            params=remove_none_values({"bot": target_bot_id, "team_id": team_id_for_org_token_use}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["calls:write"]))
async def register_slack_call(
    context: ToolContext,
    unique_call_id: Annotated[
        str,
        "A unique ID for the Call, provided by the 3rd-party Call provider. Ensure it is unique across all calls from your service.",  # noqa: E501
    ],
    call_join_url: Annotated[str, "The URL required for a client to join the Call on Slack."],
    optional_human_readable_display_id: Annotated[
        str | None,
        "An optional, human-readable ID for the call, supplied by the third-party provider. This ID will be displayed in the Call object if given.",  # noqa: E501
    ] = None,
    desktop_app_join_url: Annotated[
        str | None,
        "The URL used to directly launch the 3rd-party Call from Slack clients, if provided.",
    ] = None,
    call_start_timestamp: Annotated[
        int | None, "Unix timestamp indicating when the call is scheduled to start."
    ] = None,
    call_title: Annotated[
        str | None,
        "The name of the Call to be registered on Slack. This title will be used to identify the Call within Slack.",  # noqa: E501
    ] = None,
    call_creator_user_id: Annotated[
        str | None,
        "The valid Slack user ID of the creator of this call. Optional if using a user token, which defaults to the authed user.",  # noqa: E501
    ] = None,
    participants_info: Annotated[
        list[str] | None,
        "A list of participants to register for the call, including 'slack_id', 'external_id', 'display_name', and 'avatar_url' for each user.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'calls.add'."]:
    """Registers a new call on Slack.

    This tool registers a new call on Slack using the Slack API. It should be called when you want to create and log a new call event in a Slack workspace. The tool requires appropriate permissions (calls:write scope)."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/calls.add",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "external_unique_id": unique_call_id,
                "join_url": call_join_url,
                "external_display_id": optional_human_readable_display_id,
                "desktop_app_join_url": desktop_app_join_url,
                "date_start": call_start_timestamp,
                "title": call_title,
                "created_by": call_creator_user_id,
                "users": participants_info,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["calls:read"]))
async def get_call_information(
    context: ToolContext,
    call_id: Annotated[
        str,
        "The unique identifier of the call as returned by the `calls.add` method. This ID is necessary to retrieve detailed call information.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'calls.info'."]:
    """Retrieve detailed information about a specific call in Slack.

    Use this tool to access detailed information about a call within Slack by providing the call ID. Useful for obtaining call metadata such as participants, start time, and more."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/calls.info",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"id": call_id}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["calls:write"]))
async def add_call_participants(
    context: ToolContext,
    call_id: Annotated[
        str,
        "The unique identifier for the call, as returned by the `calls.add` method. This ID specifies which call the participants will be added to.",  # noqa: E501
    ],
    participant_users: Annotated[
        list[str],
        "List of users to add, specified by `slack_id` or `external_id`. Include optional `display_name` and `avatar_url` for each user.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'calls.participants.add'."]:
    """Add new participants to a Slack call.

    This tool registers new participants to an existing call in Slack. It should be used when you want to add people to a call that is already in progress or scheduled. The tool ensures participants are correctly added using the appropriate Slack API scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/calls.participants.add",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"id": call_id, "users": participant_users}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["calls:write"]))
async def remove_call_participants(
    context: ToolContext,
    call_id: Annotated[
        str,
        "The unique identifier for the call from which participants are to be removed. This `id` is obtained from the `calls.add` method.",  # noqa: E501
    ],
    users_to_remove: Annotated[
        list[str],
        "A list of user IDs to remove as participants from the call. Refer to Slack's documentation for specifying user IDs.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'calls.participants.remove'."]:
    """Remove participants from a Slack call.

    This tool removes specified participants from a call in Slack by registering their removal. Useful when a user needs to manage call attendees."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/calls.participants.remove",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"id": call_id, "users": users_to_remove}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["chat:write"]))
async def delete_scheduled_slack_message(
    context: ToolContext,
    channel_id: Annotated[
        str,
        "The ID of the channel where the scheduled message is set to post. Required to identify the correct message to delete.",  # noqa: E501
    ],
    scheduled_message_id: Annotated[
        str,
        "The ID of the scheduled message to be deleted. This ID is obtained from the `chat.scheduleMessage` response.",  # noqa: E501
    ],
    delete_as_authenticated_user: Annotated[
        bool | None,
        "Set to true to delete the message as the authenticated user with `chat:write:user` scope. Bot users are considered authenticated users. If false, the message will be deleted with `chat:write:bot` scope.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.deleteScheduledMessage'."]:
    """Delete a pending scheduled message from Slack queue.

    Use this tool to remove a scheduled message from the Slack queue. It requires \"chat:write\" OAuth scope, allowing you to manage messages as an authenticated user or bot."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.deleteScheduledMessage",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": channel_id,
                "scheduled_message_id": scheduled_message_id,
                "as_user": delete_as_authenticated_user,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack"))
async def get_slack_message_permalink(
    context: ToolContext,
    channel_id: Annotated[
        str, "The unique identifier of the Slack conversation or channel containing the message."
    ],
    message_timestamp: Annotated[
        str,
        "The unique timestamp of the message to retrieve the permalink for. It identifies the message within the Slack channel.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.getPermalink'."]:
    """Retrieve a permalink URL for a specific Slack message.

    This tool retrieves a permalink URL for an existing message in Slack. Use it when you need the direct link to a particular message in a Slack channel."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.getPermalink",
            params=remove_none_values({"channel": channel_id, "message_ts": message_timestamp}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["chat:write"]))
async def send_ephemeral_message_slack(
    context: ToolContext,
    target_channel: Annotated[
        str,
        "The channel, private group, or IM channel where the ephemeral message will be sent. Accepts an encoded ID or the channel's name.",  # noqa: E501
    ],
    recipient_user_id: Annotated[
        str,
        "The ID of the user who will receive the ephemeral message. Must be in the specified channel.",  # noqa: E501
    ],
    structured_attachments: Annotated[
        list[str] | None,
        "A JSON-encoded array of structured attachments for the message. Presented as a URL-encoded string.",  # noqa: E501
    ] = None,
    structured_blocks: Annotated[
        list[str] | None,
        "A URL-encoded JSON array of structured Slack block elements. Use for rich message formatting.",  # noqa: E501
    ] = None,
    message_icon_emoji: Annotated[
        str | None,
        "Emoji to display as the message icon, overriding icon_url. Specify using the emoji name like :smile:.",  # noqa: E501
    ] = None,
    message_icon_url: Annotated[
        str | None,
        "URL for the image to be used as the icon for the message. It overrides the icon_emoji if provided.",  # noqa: E501
    ] = None,
    message_markdown_text: Annotated[
        str | None,
        "The main text formatted in markdown to be sent as an ephemeral message. Do not use with `blocks` or `text`. Character limit: 12,000.",  # noqa: E501
    ] = None,
    message_parse_mode: Annotated[
        str | None,
        "Specifies how the message text is interpreted. Options are: 'none', 'full', 'mrkdwn', or 'false'. Defaults to 'none'. (default: 'none')",  # noqa: E501
    ] = None,
    ephemeral_message_text: Annotated[
        str | None,
        "The main text of the ephemeral message for Slack. It acts as a fallback when using blocks; can be formatted as plain text or markdown. Limit to a few thousand bytes.",  # noqa: E501
    ] = None,
    parent_message_timestamp: Annotated[
        str | None,
        "The timestamp of the parent message to post this ephemeral message in its thread. Ensure there is already an active thread.",  # noqa: E501
    ] = None,
    bot_username: Annotated[
        str | None,
        "The username for the bot sending the ephemeral message. This sets the display name in the Slack message.",  # noqa: E501
    ] = None,
    link_names_auto_link: Annotated[
        bool | None, "Set to true to automatically find and link channel names and usernames."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.postEphemeral'."]:
    """Send an ephemeral message to a user in a Slack channel.

    This tool sends an ephemeral message to a user within a specified Slack channel. It's useful for sending temporary messages or notifications that only the specified user can see. Requires the 'chat:write' scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.postEphemeral",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": target_channel,
                "user": recipient_user_id,
                "attachments": structured_attachments,
                "blocks": structured_blocks,
                "icon_emoji": message_icon_emoji,
                "icon_url": message_icon_url,
                "link_names": link_names_auto_link,
                "markdown_text": message_markdown_text,
                "parse": message_parse_mode,
                "text": ephemeral_message_text,
                "thread_ts": parent_message_timestamp,
                "username": bot_username,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["chat:write"]))
async def send_slack_message(
    context: ToolContext,
    target_channel_id_or_name: Annotated[
        str,
        "The encoded ID or name of the channel, private group, or IM where the message will be sent. Retrieve using Slack's conversations.list API.",  # noqa: E501
    ],
    message_attachments: Annotated[
        list[str] | None,
        'A JSON array of structured attachment objects for the message, provided as a URL-encoded string. Example: `[{"pretext": "pre-hello", "text": "text-world"}]`.',  # noqa: E501
    ] = None,
    structured_blocks: Annotated[
        list[str] | None,
        "A JSON-based array of structured blocks for constructing messages using Block Kit. Provide as a URL-encoded string. Include fallback text if necessary.",  # noqa: E501
    ] = None,
    emoji_icon_for_message: Annotated[
        str | None,
        "Emoji to display as the icon for the Slack message. Overrides any image URL icon.",
    ] = None,
    message_icon_url: Annotated[
        str | None,
        "URL to an image to use as the icon for the message. Overrides any specified icon emoji.",
    ] = None,
    message_markdown: Annotated[
        str | None,
        "The message text formatted using markdown, up to 12,000 characters. Cannot be used with `blocks` or `text`.",  # noqa: E501
    ] = None,
    message_metadata: Annotated[
        str | None,
        "A JSON object with 'event_type' and 'event_payload' fields, URL-encoded, providing additional metadata for the message.",  # noqa: E501
    ] = None,
    parse_mode: Annotated[
        str | None,
        "Specifies how the message content should be treated. Options are 'none' to remove hyperlinks or 'full' to ignore markdown formatting.",  # noqa: E501
    ] = None,
    message_text: Annotated[
        str | None,
        "The main text of the message. Acts as the primary message or a fallback for notifications when using blocks. Supports plain text or markdown.",  # noqa: E501
    ] = None,
    thread_timestamp: Annotated[
        str | None,
        "Timestamp of the parent message to which this message will be a reply. Use the parent's `ts` value, not a reply's.",  # noqa: E501
    ] = None,
    bot_username: Annotated[
        str | None, "The display name to use for the bot when sending the message to Slack."
    ] = None,
    post_as_authenticated_user: Annotated[
        bool | None,
        "Set to true to post the message as the authenticated user instead of as a bot. Only applicable for classic apps.",  # noqa: E501
    ] = None,
    link_user_groups: Annotated[
        bool | None,
        "Enable linking of user groups in the message. Individual user linking is not supported.",
    ] = None,
    enable_slack_markup_parsing: Annotated[
        bool | None,
        "Set to true to enable Slack markup parsing in the message. Default is enabled.",
    ] = None,
    broadcast_reply_to_channel: Annotated[
        bool | None,
        "Set to true to make the reply visible to everyone in the channel when responding to a thread. Use with 'thread_ts'. Default is false.",  # noqa: E501
    ] = None,
    enable_unfurling_text_content: Annotated[
        bool | None,
        "Set to true to enable unfurling of primarily text-based content in Slack messages.",
    ] = None,
    disable_media_unfurling: Annotated[
        bool | None,
        "Set to false to enable media unfurling and true to disable it. (default: 'false')",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.postMessage'."]:
    """Sends a message to a Slack channel.

    This tool allows you to send messages to a Slack channel or direct message on behalf of an authenticated user. It is useful for automating communications within Slack workspaces."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.postMessage",
            method="POST",
            headers=remove_none_values({
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                )
            }),
            data=remove_none_values({
                "channel": target_channel_id_or_name,
                "as_user": post_as_authenticated_user,
                "attachments": message_attachments,
                "blocks": structured_blocks,
                "icon_emoji": emoji_icon_for_message,
                "icon_url": message_icon_url,
                "link_names": link_user_groups,
                "markdown_text": message_markdown,
                "metadata": message_metadata,
                "mrkdwn": enable_slack_markup_parsing,
                "parse": parse_mode,
                "reply_broadcast": broadcast_reply_to_channel,
                "text": message_text,
                "thread_ts": thread_timestamp,
                "unfurl_links": enable_unfurling_text_content,
                "unfurl_media": disable_media_unfurling,
                "username": bot_username,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack"))
async def list_scheduled_messages(
    context: ToolContext,
    channel_id: Annotated[
        str | None, "The ID of the Slack channel from which to retrieve scheduled messages."
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "Cursor value for pagination to specify the starting point of the list from a previous call.",  # noqa: E501
    ] = None,
    latest_timestamp: Annotated[
        str | None,
        "A Unix timestamp marking the latest point in the time range for fetching scheduled messages. Ensure it is greater than the `oldest` timestamp if both are set.",  # noqa: E501
    ] = None,
    max_number_of_entries: Annotated[
        int | None, "Specify the maximum number of scheduled messages to return from Slack."
    ] = None,
    oldest_timestamp: Annotated[
        str | None,
        "A Unix timestamp representing the start of the time range for scheduled messages. It must be less than the `latest_timestamp` if both are specified.",  # noqa: E501
    ] = None,
    team_id: Annotated[
        str | None,
        "Encoded team ID to specify which team's channels to list. Required if using an org-level token; ignore for workspace-level tokens.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.scheduledMessages.list'."]:
    """Retrieve scheduled messages from Slack.

    Use this tool to obtain a list of messages that are scheduled to be sent in a Slack workspace. It is useful for managing future communications and staying informed of pending messages."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.scheduledMessages.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": channel_id,
                "cursor": pagination_cursor,
                "latest": latest_timestamp,
                "limit": max_number_of_entries,
                "oldest": oldest_timestamp,
                "team_id": team_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["chat:write"]))
async def schedule_slack_message(
    context: ToolContext,
    slack_channel_id_or_name: Annotated[
        str,
        "Specify the target Slack channel, private group, or DM. Use an encoded ID or the channel name. Retrieve channel ID via `conversations.list`.",  # noqa: E501
    ],
    schedule_time_unix_timestamp: Annotated[
        int,
        "Unix timestamp for when the message should be posted to Slack. Must be within 120 days and not exceed 30 messages per 5-minute window.",  # noqa: E501
    ],
    attachments_json: Annotated[
        str | None,
        "A JSON array of structured attachments as a URL-encoded string for the Slack message.",
    ] = None,
    structured_blocks_json: Annotated[
        str | None,
        "A URL-encoded string of a JSON-based array containing structured blocks for message formatting.",  # noqa: E501
    ] = None,
    message_markdown: Annotated[
        str | None,
        "Message text in markdown format. Avoid using with 'blocks' or 'text'. Maximum 12,000 characters.",  # noqa: E501
    ] = None,
    message_parsing_mode: Annotated[
        str | None,
        "Specifies how the message content should be parsed and interpreted when sending to Slack. For more details, refer to chat.postMessage documentation.",  # noqa: E501
    ] = None,
    message_text: Annotated[
        str | None,
        "The main body of the Slack message or a fallback text when using blocks. Can be plain text or formatted with mrkdwn.",  # noqa: E501
    ] = None,
    parent_message_timestamp: Annotated[
        str | None,
        "Timestamp of the parent message to which this message is a reply. Use the original message's timestamp, not a reply's timestamp.",  # noqa: E501
    ] = None,
    metadata_json: Annotated[
        str | None,
        "JSON object containing 'event_type' and 'event_payload' fields. Must be URL-encoded. Note: using this will prevent scheduled messages from posting.",  # noqa: E501
    ] = None,
    enable_group_linking: Annotated[
        bool | None,
        "Set to true to link user groups in the message. Linking individual users is not supported; use mention syntax instead.",  # noqa: E501
    ] = None,
    make_reply_visible_to_everyone: Annotated[
        bool | None,
        "Set to true to make the reply visible to everyone in the channel or conversation. Use with `thread_ts`. Defaults to false.",  # noqa: E501
    ] = None,
    enable_link_unfurling: Annotated[
        bool | None, "Pass true to enable unfurling of primarily text-based content."
    ] = None,
    disable_unfurling_of_media_content: Annotated[
        bool | None, "Set to true to disable unfurling of media content. Defaults to false."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.scheduleMessage'."]:
    """Schedule a message to be sent later in Slack.

    This tool schedules a message to be sent to a specific Slack channel at a designated future time. It utilizes the Slack API endpoint 'chat.scheduleMessage' and requires the 'chat:write' OAuth scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.scheduleMessage",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": slack_channel_id_or_name,
                "post_at": schedule_time_unix_timestamp,
                "attachments": attachments_json,
                "blocks": structured_blocks_json,
                "link_names": enable_group_linking,
                "markdown_text": message_markdown,
                "parse": message_parsing_mode,
                "reply_broadcast": make_reply_visible_to_everyone,
                "text": message_text,
                "thread_ts": parent_message_timestamp,
                "unfurl_links": enable_link_unfurling,
                "unfurl_media": disable_unfurling_of_media_content,
                "metadata": metadata_json,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["links:write"]))
async def custom_unfurl_slack_urls(
    context: ToolContext,
    channel_id: Annotated[
        str,
        "ID of the Slack channel where the message is posted. Required with 'ts' for custom unfurl or with 'unfurl_id' and 'source'.",  # noqa: E501
    ],
    message_timestamp: Annotated[
        str,
        "Timestamp of the message to which unfurl behavior will be added. Ensure it corresponds to a message in the specified channel containing a fully-qualified URL registered with your Slack app.",  # noqa: E501
    ],
    unfurl_url_map: Annotated[
        str,
        "A URL-encoded JSON map with URLs as keys and their corresponding unfurl data as values. Each URL should point to a single attachment, like message buttons.",  # noqa: E501
    ],
    authentication_invitation_message: Annotated[
        str | None,
        "A simple formatted string sent as an ephemeral message inviting the user to authenticate for full unfurl behavior. Supports Slack's *bold*, _italics_, and linking formatting. If provided, this takes precedence over `authentication_invitation_url`.",  # noqa: E501
    ] = None,
    custom_authentication_url: Annotated[
        str | None,
        "A URL to redirect users for app authentication to enable full URL unfurling, requires URL encoding.",  # noqa: E501
    ] = None,
    user_authentication_blocks: Annotated[
        list[str] | None,
        "A URL-encoded JSON array of structured blocks to send as an ephemeral message for user authentication invitation.",  # noqa: E501
    ] = None,
    unfurl_link_id: Annotated[
        str | None, "The ID of the link to unfurl. Must be used with 'source'."
    ] = None,
    link_source: Annotated[
        str | None,
        "Specify the source of the link to unfurl as either 'composer' for links inside the message composer or 'conversations_history' for links posted to a conversation. Must be used with 'unfurl_id', or alternatively with 'channel' and 'ts'.",  # noqa: E501
    ] = None,
    require_user_authentication: Annotated[
        bool | None,
        "Set to true if the user must install your Slack app to trigger unfurls for this domain.",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'chat.unfurl'."]:
    """Provide custom unfurl behavior for user-posted URLs on Slack.

    This tool should be called to customize how URLs posted by users are displayed in Slack by providing a custom unfurl behavior."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/chat.unfurl",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": channel_id,
                "ts": message_timestamp,
                "unfurls": unfurl_url_map,
                "user_auth_message": authentication_invitation_message,
                "user_auth_required": require_user_authentication,
                "user_auth_url": custom_authentication_url,
                "user_auth_blocks": user_authentication_blocks,
                "unfurl_id": unfurl_link_id,
                "source": link_source,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations.connect:write"]))
async def accept_slack_invite(
    context: ToolContext,
    channel_name: Annotated[
        str,
        "Provide the desired name for the Slack Connect channel. If the channel doesn't exist in your workspace, this name will be assigned to it.",  # noqa: E501
    ],
    invite_id: Annotated[
        str | None,
        "ID of the invitation you want to accept. Must provide either this or channel_id.",
    ] = None,
    slack_channel_id_to_accept: Annotated[
        str | None,
        "The ID of the channel you would like to accept the invitation for. Either this or `invite_id` is required.",  # noqa: E501
    ] = None,
    workspace_id: Annotated[
        str | None,
        "The ID of the workspace where the channel should be accepted. Required if using an org-level token.",  # noqa: E501
    ] = None,
    is_channel_private: Annotated[
        bool | None, "True to make the channel private; false to make it public."
    ] = None,
    use_free_trial: Annotated[
        bool | None,
        "Set to 'True' to use your workspace's free trial to start using Slack Connect.",
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'conversations.acceptSharedInvite'."
]:
    """Accept invitations to a Slack Connect channel.

    Use this tool to accept an invitation to a Slack Connect channel, facilitating seamless collaboration across different Slack workspaces."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.acceptSharedInvite",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel_name": channel_name,
                "is_private": is_channel_private,
                "free_trial_accepted": use_free_trial,
                "invite_id": invite_id,
                "channel_id": slack_channel_id_to_accept,
                "team_id": workspace_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations.connect:manage"]))
async def approve_slack_channel_invitation(
    context: ToolContext,
    shared_channel_invite_id: Annotated[
        str,
        "The ID of the shared channel invitation you want to approve. It is required to specifically identify which invitation is being approved for the Slack Connect channel.",  # noqa: E501
    ],
    other_party_team_id: Annotated[
        str | None,
        "The team or enterprise ID of the other party involved in the Slack Connect invitation you are approving.",  # noqa: E501
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'conversations.approveSharedInvite'."
]:
    """Approve an invitation to a Slack Connect channel.

    This tool is used to approve invitations sent to a Slack Connect channel, allowing collaboration between different Slack workspaces. It should be called when a user wants to manage and approve channel access invitations."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.approveSharedInvite",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "invite_id": shared_channel_invite_id,
                "target_team": other_party_team_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack",
        scopes=["channels:manage", "channels:write", "groups:write", "im:write", "mpim:write"],
    )
)
async def create_slack_conversation(
    context: ToolContext,
    channel_name: Annotated[
        str,
        "The name of the new Slack channel to create. It must contain only lowercase letters, numbers, hyphens, and underscores, and be 80 characters or less.",  # noqa: E501
    ],
    encoded_team_id: Annotated[
        str | None,
        "The encoded team ID where the channel will be created. Required when using an organization-level token. Ignored if using a workspace-level token.",  # noqa: E501
    ] = None,
    create_private_channel: Annotated[
        bool | None, "Set to true to create a private channel instead of a public one."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.create'."]:
    """Create a new public or private Slack conversation.

    This tool is used to initiate a new conversation channel in Slack, allowing for the creation of either public or private channels. It is useful when setting up new communication threads within a team or project."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.create",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "name": channel_name,
                "is_private": create_private_channel,
                "team_id": encoded_team_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack", scopes=["channels:read", "groups:read", "im:read", "mpim:read"]
    )
)
async def get_conversation_info(
    context: ToolContext,
    conversation_id: Annotated[
        str, "The unique ID of the Slack conversation to retrieve information for."
    ],
    include_locale: Annotated[
        bool | None,
        "Set to `true` to receive the locale for this conversation. Defaults to `false`.",
    ] = None,
    include_member_count: Annotated[
        bool | None,
        "Set to true to include the member count for the specified conversation. Defaults to false.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.info'."]:
    """Fetches information about a Slack conversation.

    This tool retrieves details about a specific conversation in Slack, such as its name, members, and other relevant data. It should be used when information about a Slack conversation is needed, and requires appropriate read permissions."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.info",
            params=remove_none_values({
                "channel": conversation_id,
                "include_locale": include_locale,
                "include_num_members": include_member_count,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations:write.invites"]))
async def invite_user_to_slack_channel(
    context: ToolContext,
    slack_channel_id: Annotated[
        str,
        "The ID of the Slack channel to invite users to. It can be a public or private channel ID.",
    ],
    user_ids_list: Annotated[str, "A list of up to 100 user IDs to invite, separated by commas."],
    continue_with_valid_users: Annotated[
        bool | None,
        "Set to true to invite valid users while ignoring invalid IDs when multiple user IDs are provided. Default is false.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.invite'."]:
    """Invite users to a Slack channel.

    This tool sends an invitation to specified users to join a Slack channel. It should be called when you want to add new members to a channel via an invite."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.invite",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": slack_channel_id,
                "users": user_ids_list,
                "force": continue_with_valid_users,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["channels:join", "channels:write"]))
async def join_slack_conversation(
    context: ToolContext,
    conversation_id: Annotated[
        str, "The ID of the conversation or channel you want to join in Slack."
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.join'."]:
    """Join an existing conversation in Slack.

    This tool is used to join a specified conversation within Slack. It requires appropriate user permissions and should be called when there's a need to participate in an existing Slack channel."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.join",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"channel": conversation_id}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack", scopes=["channels:read", "groups:read", "im:read", "mpim:read"]
    )
)
async def list_slack_channels(
    context: ToolContext,
    pagination_cursor: Annotated[
        str | None,
        "The cursor used to paginate through data collections. Use the `next_cursor` from a previous response to continue; omit for the first page.",  # noqa: E501
    ] = None,
    maximum_number_of_channels: Annotated[
        int | None,
        "Specify the maximum number of channels to return. Must be an integer under 1000. Note that fewer channels than requested may be returned. (default: '100')",  # noqa: E501
    ] = None,
    team_id_for_org_app: Annotated[
        str | None,
        "Encoded team ID to list channels. Required for org-level tokens; ignored for workspace-level tokens.",  # noqa: E501
    ] = None,
    channel_types: Annotated[
        str | None,
        "Comma-separated list of channel types to include, e.g., 'public_channel', 'private_channel', 'mpim', 'im'. (default: 'public_channel')",  # noqa: E501
    ] = None,
    exclude_archived_channels: Annotated[
        bool | None,
        "Set to true to exclude archived channels from the list of Slack channels. Default is false.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.list'."]:
    """Retrieve a list of all channels in a Slack team.

    This tool retrieves a list of all public and private channels that the user has access to within a Slack team. It can also view direct and multiparty direct messages, depending on the user's permissions."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.list",
            params=remove_none_values({
                "cursor": pagination_cursor,
                "exclude_archived": exclude_archived_channels,
                "limit": maximum_number_of_channels,
                "team_id": team_id_for_org_app,
                "types": channel_types,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations.connect:manage"]))
async def list_shared_channel_invites(
    context: ToolContext,
    workspace_team_id: Annotated[
        str | None,
        "The encoded team ID for the workspace to retrieve invites from. Required when using an organization token.",  # noqa: E501
    ] = None,
    maximum_invites_to_return: Annotated[
        int | None,
        "Specify the maximum number of unapproved shared channel invites to retrieve. (default: '100')",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "The cursor for paginating through results, obtained from a previous call's next_cursor.",
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'conversations.listConnectInvites'."
]:
    """Retrieve unapproved shared channel invites from Slack.

    This tool retrieves a list of shared channel invites that have been generated or received but are not yet approved by all parties on Slack. It should be called when you need to manage or view pending shared channel invites."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.listConnectInvites",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "team_id": workspace_team_id,
                "count": maximum_invites_to_return,
                "cursor": pagination_cursor,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack",
        scopes=["channels:manage", "channels:write", "groups:write", "im:write", "mpim:write"],
    )
)
async def set_slack_channel_read_cursor(
    context: ToolContext,
    channel_id: Annotated[
        str,
        "The ID of the Slack channel or conversation where you want to set the read cursor. This should be a valid Slack channel ID.",  # noqa: E501
    ],
    timestamp_of_message_to_mark_as_read: Annotated[
        str,
        "The unique identifier (timestamp) of the message you want to mark as most recently seen in the conversation.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.mark'."]:
    """Update the read cursor in a Slack channel.

    Use this tool to mark a specific point in a Slack channel as read. This is useful for keeping track of the latest read messages in channels, groups, or direct messages. Requires appropriate Slack OAuth scopes."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.mark",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": channel_id,
                "ts": timestamp_of_message_to_mark_as_read,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack", scopes=["channels:read", "groups:read", "im:read", "mpim:read"]
    )
)
async def get_slack_conversation_members(
    context: ToolContext,
    conversation_id: Annotated[
        str,
        "The ID of the Slack conversation to retrieve members from. This can be a channel, group, or direct message.",  # noqa: E501
    ],
    pagination_cursor: Annotated[
        str | None,
        "Cursor for pagination, set to the `next_cursor` value from a previous response to continue retrieving members from a conversation.",  # noqa: E501
    ] = None,
    max_items_to_return: Annotated[
        int | None,
        "The maximum number of conversation members to return. Recommended to specify a value under 1000, with no more than 200 results at a time for optimal pagination. (default: '100')",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.members'."]:
    """Retrieve members from a specified Slack conversation.

    Use this tool to get a list of members in a specific Slack conversation. This can apply to public and private channels, as well as direct and multi-party direct message conversations. Appropriate OAuth scopes are required to access different types of conversations."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.members",
            params=remove_none_values({
                "channel": conversation_id,
                "cursor": pagination_cursor,
                "limit": max_items_to_return,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack",
        scopes=["channels:manage", "channels:write", "groups:write", "im:write", "mpim:write"],
    )
)
async def open_or_resume_slack_conversation(
    context: ToolContext,
    conversation_channel_id: Annotated[
        str | None,
        "The ID of an existing direct or multi-person message channel to resume. Alternatively, provide the `users` field to start a new conversation.",  # noqa: E501
    ] = None,
    target_user_ids: Annotated[
        str | None,
        "A comma-separated list of user IDs to open or resume a conversation. Provide 1 to 8 IDs. Supplying 1 ID opens a 1:1 DM, while more than 1 ID opens a multi-person DM. Do not include the caller's ID.",  # noqa: E501
    ] = None,
    return_full_im_channel_definition: Annotated[
        bool | None,
        "Set to true to receive the entire IM channel definition; false returns only the conversation ID.",  # noqa: E501
    ] = None,
    prevent_creation: Annotated[
        bool | None,
        "If true, does not create a new conversation and instead checks for an existing DM or MPDM.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.open'."]:
    """Open or resume a direct or multi-person message in Slack.

    This tool calls the Slack API to open a new conversation or resume an existing direct message or multi-person direct message. It should be used when there's a need to start or continue a conversation within Slack."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.open",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": conversation_channel_id,
                "return_im": return_full_im_channel_definition,
                "users": target_user_ids,
                "prevent_creation": prevent_creation,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack",
        scopes=["channels:history", "groups:history", "im:history", "mpim:history"],
    )
)
async def get_slack_thread_messages(
    context: ToolContext,
    conversation_id: Annotated[
        str, "The ID of the Slack conversation from which to fetch the message thread."
    ],
    thread_message_timestamp: Annotated[
        str,
        "Unique identifier of a parent message or a thread message (timestamp). Fetches the thread or the single message.",  # noqa: E501
    ],
    pagination_cursor: Annotated[
        str | None,
        "Cursor for pagination. Use the `next_cursor` from a previous response to fetch the next page of data.",  # noqa: E501
    ] = None,
    latest_message_timestamp: Annotated[
        str | None,
        "Only include messages posted before this Unix timestamp in the results. (default: 'now')",
    ] = None,
    maximum_items_to_return: Annotated[
        int | None,
        "Specify the maximum number of messages to fetch. The default and maximum are 15 for certain apps, with possible rate limits. (default: '1000')",  # noqa: E501
    ] = None,
    start_time_unix_timestamp: Annotated[
        str | None, "Only include messages after this Unix timestamp in results. (default: '0')"
    ] = None,
    include_all_message_metadata: Annotated[
        bool | None, "Set to true to return all metadata associated with this message."
    ] = None,
    include_boundary_timestamps: Annotated[
        bool | None,
        "Include messages with 'oldest' or 'latest' timestamps. Ignored unless either timestamp is specified.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'conversations.replies'."]:
    """Retrieve messages from a Slack conversation thread.

    This tool fetches a thread of messages posted to a specific conversation in Slack. It should be called when there is a need to review or analyze the message history of a public or private channel, a direct message, or a multi-party direct message. The tool requires appropriate OAuth scopes to access the message history."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.replies",
            params=remove_none_values({
                "channel": conversation_id,
                "ts": thread_message_timestamp,
                "cursor": pagination_cursor,
                "include_all_metadata": include_all_message_metadata,
                "inclusive": include_boundary_timestamps,
                "latest": latest_message_timestamp,
                "limit": maximum_items_to_return,
                "oldest": start_time_unix_timestamp,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations.connect:manage"]))
async def deny_shared_invite_request(
    context: ToolContext,
    shared_channel_invite_id: Annotated[
        str,
        "The ID for the shared channel invite request that you intend to deny. This is required for specifying which invite to decline.",  # noqa: E501
    ],
    deny_invite_message: Annotated[
        str | None,
        "An optional message explaining why the invitation was denied. This message will be sent to the requester.",  # noqa: E501
    ] = None,
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'conversations.requestSharedInvite.deny'."
]:
    """Denies an external user invitation to a Slack channel.

    Use this tool to deny a request that invites an external user to join a Slack channel. It should be called when such an invite needs to be rejected."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/conversations.requestSharedInvite.deny",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "invite_id": shared_channel_invite_id,
                "message": deny_invite_message,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["emoji:read"]))
async def list_custom_emoji_for_team(
    context: ToolContext,
    include_emoji_categories: Annotated[
        bool | None, "Set to true to include categories for Unicode emojis in the response."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'emoji.list'."]:
    """Retrieve a list of custom emojis for a specific team.

    Use this tool to get a list of custom emojis available for a team on Slack. It should be called when you need to display or manage team-specific emojis."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/emoji.list",
            params=remove_none_values({"include_categories": include_emoji_categories}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["files:write"]))
async def get_external_file_upload_url(
    context: ToolContext,
    file_size_in_bytes: Annotated[
        int,
        "Specify the size of the file to be uploaded, measured in bytes. Ensure this value accurately reflects the file size.",  # noqa: E501
    ],
    file_name: Annotated[str, "The name of the file to be uploaded to Slack."],
    snippet_syntax_type: Annotated[
        str | None,
        "Specify the syntax highlighting type for the snippet being uploaded, such as 'javascript', 'python', etc.",  # noqa: E501
    ] = None,
    alt_text_description: Annotated[
        str | None, "A description of the image for screen-readers, limited to 1000 characters."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'files.getUploadURLExternal'."]:
    """Retrieve a URL to upload an external file to Slack.

    This tool is used to obtain a URL for uploading files externally to Slack, requiring the 'files:write' OAuth scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/files.getUploadURLExternal",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "length": file_size_in_bytes,
                "filename": file_name,
                "snippet_type": snippet_syntax_type,
                "alt_txt": alt_text_description,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["remote_files:read"]))
async def get_remote_file_info_slack(
    context: ToolContext,
    file_external_identifier: Annotated[
        str | None,
        "The GUID defined by the creator for the remote file to retrieve its information.",
    ] = None,
    file_id: Annotated[
        str | None,
        "The unique identifier of the file to retrieve information about. Use this to specify the file in Slack.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'files.remote.info'."]:
    """Retrieve details about a remote file from Slack.

    Use this tool to get information about a remote file that has been added to Slack. It is useful when you need details regarding the file, such as its metadata or status within Slack."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/files.remote.info",
            params=remove_none_values({"external_id": file_external_identifier, "file": file_id}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["remote_files:read"]))
async def get_slack_remote_files_info(
    context: ToolContext,
    filter_by_channel_id: Annotated[
        str | None,
        "Filter remote files to only include those appearing in the specified Slack channel, indicated by its channel ID.",  # noqa: E501
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "A cursor for paginating through data. Use the `next_cursor` from a prior request to fetch the next set of results. Defaults to the first page if not set.",  # noqa: E501
    ] = None,
    maximum_items_to_return: Annotated[
        int | None, "Specify the maximum number of remote file records to retrieve from Slack."
    ] = None,
    filter_files_from_timestamp: Annotated[
        str | None,
        "Filter files created after this inclusive timestamp. Use a Unix timestamp format. (default: '0')",  # noqa: E501
    ] = None,
    timestamp_filter_end: Annotated[
        str | None,
        "Filter files created before this timestamp (inclusive) in Unix epoch time format. (default: 'now')",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'files.remote.list'."]:
    """Retrieve information about remote files added to Slack.

    This tool fetches details about remote files stored in Slack. It is useful when you need to access metadata for files that have been added to Slack from external sources."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/files.remote.list",
            params=remove_none_values({
                "channel": filter_by_channel_id,
                "cursor": pagination_cursor,
                "limit": maximum_items_to_return,
                "ts_from": filter_files_from_timestamp,
                "ts_to": timestamp_filter_end,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["remote_files:share"]))
async def share_remote_file_in_channel(
    context: ToolContext,
    target_channel_ids: Annotated[
        str,
        "Comma-separated list of Slack channel IDs where the remote file will be shared. Ensure IDs are valid and the user has permission to share files in these channels.",  # noqa: E501
    ],
    file_external_identifier: Annotated[
        str | None,
        "The globally unique identifier (GUID) for the file set by the app when registering with Slack. Required if 'file' is not provided.",  # noqa: E501
    ] = None,
    file_id: Annotated[
        str | None,
        "The ID of a file registered with Slack to be shared. Required if `external_id` is not provided.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'files.remote.share'."]:
    """Share a remote file into a Slack channel.

    This tool shares a specified remote file into a selected Slack channel. It utilizes Slack's API to facilitate file sharing across channels."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/files.remote.share",
            params=remove_none_values({
                "channels": target_channel_ids,
                "external_id": file_external_identifier,
                "file": file_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["files:write"]))
async def enable_slack_file_sharing(
    context: ToolContext,
    file_id_to_share: Annotated[
        str, "The ID of the file on Slack that you want to enable for public sharing."
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'files.sharedPublicURL'."]:
    """Enable a Slack file for public sharing.

    This tool enables a file for public or external sharing on Slack using the Slack API. It should be called when a user wants to share a file publicly outside their Slack workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/files.sharedPublicURL",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"file": file_id_to_share}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["pins:write"]))
async def pin_item_to_slack_channel(
    context: ToolContext,
    channel_id: Annotated[
        str,
        "The ID of the Slack channel where the message will be pinned. A `timestamp` must also be provided.",  # noqa: E501
    ],
    message_timestamp: Annotated[
        str | None,
        "The timestamp (`ts`) of the message to pin in the Slack channel. Ensure the channel is also specified.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'pins.add'."]:
    """Pin an item to a Slack channel.

    Use this tool to pin an item to a specific channel in Slack, enhancing visibility for important content."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/pins.add",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"channel": channel_id, "timestamp": message_timestamp}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["pins:read"]))
async def list_pinned_items(
    context: ToolContext,
    channel_id: Annotated[
        str,
        "The ID of the Slack channel to retrieve pinned items from. This is required to specify which channel's pinned items will be listed.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'pins.list'."]:
    """Retrieve items pinned to a Slack channel.

    This tool calls the Slack API to list all items pinned to a specific channel. It should be used when there is a need to display or manage pinned items in a Slack channel."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/pins.list",
            params=remove_none_values({"channel": channel_id}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["reactions:write"]))
async def add_slack_reaction(
    context: ToolContext,
    slack_channel_id: Annotated[
        str,
        "ID of the channel where the message is posted. Use to specify the location for adding a reaction.",  # noqa: E501
    ],
    reaction_emoji_name: Annotated[
        str,
        "The name of the emoji to be used as a reaction. Include skin tone modifiers if applicable (e.g., 'thumbsup::skin-tone-2').",  # noqa: E501
    ],
    message_timestamp: Annotated[
        str,
        "The timestamp of the message to which the reaction will be added. Ensure the format matches the Slack API requirements.",  # noqa: E501
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'reactions.add'."]:
    """Add a reaction to a Slack item.

    Use this tool to add an emoji reaction to a message or item within Slack. This can be useful for acknowledging messages or express sentiments quickly."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/reactions.add",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "channel": slack_channel_id,
                "name": reaction_emoji_name,
                "timestamp": message_timestamp,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["reactions:write"]))
async def remove_reaction_from_item(
    context: ToolContext,
    reaction_emoji_name: Annotated[
        str, "The name of the emoji reaction to be removed, such as 'smile' or 'thumbsup'."
    ],
    target_file_id: Annotated[
        str | None,
        "The identifier of the file from which to remove the reaction. Specify either this, `target_file_comment_id`, or both `target_channel_id` and `target_message_timestamp`.",  # noqa: E501
    ] = None,
    file_comment_id: Annotated[
        str | None,
        "The ID of the file comment from which you want to remove the reaction. Provide this if the reaction is on a file comment.",  # noqa: E501
    ] = None,
    message_channel_id: Annotated[
        str | None,
        "Channel ID where the message to remove the reaction from was posted. Required if removing a reaction from a message. Use in combination with 'message_timestamp'.",  # noqa: E501
    ] = None,
    message_timestamp: Annotated[
        str | None,
        "The exact timestamp of the message from which to remove the reaction. Specify when targeting a message.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'reactions.remove'."]:
    """Remove a reaction from a Slack item.

    Use this tool to remove a reaction (emoji) from a message, file, or file comment in Slack. This tool is intended for situations where a reaction needs to be revoked. It requires the 'reactions:write' scope, which allows the app to manage reactions on behalf of the user."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/reactions.remove",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "name": reaction_emoji_name,
                "file": target_file_id,
                "file_comment": file_comment_id,
                "channel": message_channel_id,
                "timestamp": message_timestamp,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["search:read"]))
async def search_files_in_slack(
    context: ToolContext,
    search_query: Annotated[
        str,
        "The text string to search for in Slack files. Use keywords or phrases to narrow down results.",  # noqa: E501
    ],
    items_per_page: Annotated[
        int | None,
        "The number of file results to return per page. Maximum allowed value is 100. (default: '20')",  # noqa: E501
    ] = None,
    results_page_number: Annotated[
        int | None,
        "The specific page number of results to retrieve, with a maximum value of 100. (default: '1')",  # noqa: E501
    ] = None,
    sort_files_by: Annotated[
        str | None,
        "Specify how to sort the search results: either by 'score' or 'timestamp'. (default: 'score')",  # noqa: E501
    ] = None,
    sort_direction: Annotated[
        str | None,
        "Change the sort direction for search results to ascending ('asc') or descending ('desc'). (default: 'desc')",  # noqa: E501
    ] = None,
    encoded_team_id: Annotated[
        str | None,
        "Encoded team ID to specify the search domain when using an org-level token. Ignored with a workspace-level token.",  # noqa: E501
    ] = None,
    enable_query_highlight: Annotated[
        bool | None,
        "Set to true to enable highlight markers for matching query terms in the search results.",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'search.files'."]:
    """Search for files in Slack using a query.

    This tool searches for files in Slack that match a given query. It is useful when a user needs to locate specific files shared in Slack channels or direct messages. The tool returns a list of files that meet the search criteria."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/search.files",
            params=remove_none_values({
                "query": search_query,
                "count": items_per_page,
                "highlight": enable_query_highlight,
                "page": results_page_number,
                "sort": sort_files_by,
                "sort_dir": sort_direction,
                "team_id": encoded_team_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["search:read"]))
async def search_slack_messages(
    context: ToolContext,
    search_query: Annotated[
        str,
        "The text to search for in Slack messages. Use keywords or phrases to narrow down results.",
    ],
    results_per_page: Annotated[
        int | None,
        "The number of search results to return per page, with a maximum limit of 100. (default: '20')",  # noqa: E501
    ] = None,
    page_number: Annotated[
        int | None,
        "The page number of search results to retrieve, maximum value of 100. (default: '1')",
    ] = None,
    pagination_cursor: Annotated[
        str | None,
        "Use '*' for the first call to start pagination or provide the 'next_cursor' value from previous results to continue.",  # noqa: E501
    ] = None,
    sort_results_by: Annotated[
        str | None,
        "Specify the criterion for sorting the search results, either by 'score' for relevance or 'timestamp' for chronological order. (default: 'score')",  # noqa: E501
    ] = None,
    sort_direction: Annotated[
        str | None,
        "Specify the order for sorting results: use 'asc' for ascending or 'desc' for descending. (default: 'desc')",  # noqa: E501
    ] = None,
    team_id: Annotated[
        str | None,
        "The encoded team ID to search within. Required only if an organization-level token is used. Ignored for workspace-level tokens.",  # noqa: E501
    ] = None,
    enable_query_highlighting: Annotated[
        bool | None,
        "Set to true to enable query highlight markers, marking matching terms in the results.",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'search.messages'."]:
    """Search Slack messages based on a query.

    This tool searches for messages in a Slack workspace that match a specified query. It should be called when users want to find specific messages or discussions within their Slack channels."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/search.messages",
            params=remove_none_values({
                "query": search_query,
                "count": results_per_page,
                "highlight": enable_query_highlighting,
                "page": page_number,
                "cursor": pagination_cursor,
                "sort": sort_results_by,
                "sort_dir": sort_direction,
                "team_id": team_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin"]))
async def get_team_billable_users_info(
    context: ToolContext,
    pagination_cursor: Annotated[
        str | None,
        "Cursor for pagination. Use the `next_cursor` from the previous response to fetch the next page of users. (default: 'fetches the first page')",  # noqa: E501
    ] = None,
    maximum_items_to_return: Annotated[
        int | None, "Specifies the maximum number of billable user entries to be retrieved."
    ] = None,
    specific_user_id: Annotated[
        str | None,
        "The ID of a specific user to retrieve billable information for. Leave empty to retrieve info for all users.",  # noqa: E501
    ] = None,
    encoded_team_id: Annotated[
        str | None,
        "Encoded team ID for retrieving billable info, required if using an org token. Ignored with workspace-level tokens.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'team.billableInfo'."]:
    """Retrieves billable users info for the current Slack team.

    Use this tool to obtain information about billable users in your Slack team. It requires administrative privileges with the 'admin' scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/team.billableInfo",
            params=remove_none_values({
                "cursor": pagination_cursor,
                "limit": maximum_items_to_return,
                "user": specific_user_id,
                "team_id": encoded_team_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["team:read"]))
async def get_current_slack_team_info(
    context: ToolContext,
    query_by_domain: Annotated[
        str | None,
        "Comma-separated domains to query instead of a team, used when the team is not specified. This only works for domains in the same enterprise as the querying team token.",  # noqa: E501
    ] = None,
    specific_team_id: Annotated[
        str | None,
        "The ID of the Slack team to retrieve information about. If omitted, information about the current team will be returned.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'team.info'."]:
    """Retrieve information about the current Slack team.

    This tool is used to get information about the current Slack team, including settings and general details. It is called when there's a need to access team information in a Slack workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/team.info",
            params=remove_none_values({"domain": query_by_domain, "team": specific_team_id}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["admin"]))
async def get_integration_logs(
    context: ToolContext,
    filter_by_app_id: Annotated[
        str | None,
        "Filter integration logs to a specific Slack app. If not provided, logs for all apps are retrieved.",  # noqa: E501
    ] = None,
    filter_by_change_type: Annotated[
        str | None,
        "Specify the change type to filter logs. Options: 'added', 'removed', 'enabled', 'disabled', 'updated'. Defaults to all logs.",  # noqa: E501
    ] = None,
    result_count: Annotated[
        str | None,
        "The number of log entries to retrieve. Specify the maximum number of logs to return in a single request. (default: '100')",  # noqa: E501
    ] = None,
    result_page_number: Annotated[
        str | None,
        "The specific page number of the integration logs to retrieve. Used for pagination. (default: '1')",  # noqa: E501
    ] = None,
    filter_by_service_id: Annotated[
        str | None,
        "Specify the service ID to filter integration logs related to a specific service. If not provided, logs for all services will be retrieved.",  # noqa: E501
    ] = None,
    encoded_team_id: Annotated[
        str | None,
        "The encoded team ID to get logs from, required if using an org-level token. Ignored if using a workspace-level token.",  # noqa: E501
    ] = None,
    filter_by_user: Annotated[
        str | None,
        "Filter logs generated by a specific user's actions. Defaults to all logs if not specified.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'team.integrationLogs'."]:
    """Retrieve integration logs for the current Slack team.

    This tool retrieves the integration logs for the current Slack team, providing insights into the team's integration history and activities. It requires admin OAuth scope to access the logs."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/team.integrationLogs",
            params=remove_none_values({
                "app_id": filter_by_app_id,
                "change_type": filter_by_change_type,
                "count": result_count,
                "page": result_page_number,
                "service_id": filter_by_service_id,
                "team_id": encoded_team_id,
                "user": filter_by_user,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["team.preferences:read"]))
async def get_slack_team_preferences(
    context: ToolContext,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'team.preferences.list'."]:
    """Retrieve a list of a workspace's team preferences.

    This tool fetches team preferences from a Slack workspace. It should be called when there's a need to access or review team settings. Requires appropriate OAuth scope for access."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/team.preferences.list",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users.profile:read"]))
async def get_team_profile(
    context: ToolContext,
    visibility_filter: Annotated[
        str | None,
        "Filter the profile fields based on visibility. Options: 'all', 'visible', 'hidden'. Default is 'all'.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'team.profile.get'."]:
    """Retrieve a team's profile information from Slack.

    This tool retrieves a team's profile from Slack. It should be called when there's a need to access team information such as members, roles, or other relevant details. The tool uses the Slack API and requires the 'users.profile:read' OAuth scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/team.profile.get",
            params=remove_none_values({"visibility": visibility_filter}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:write"]))
async def create_slack_user_group(
    context: ToolContext,
    user_group_name: Annotated[
        str,
        "A unique name for the user group to be created, distinguishing it from other user groups.",
    ],
    default_channel_ids: Annotated[
        list[str] | None,
        "A list of channel IDs to set as default for the User Group. Use comma-separated values.",
    ] = None,
    custom_additional_channels: Annotated[
        list[str] | None,
        "Comma-separated encoded channel IDs where the User Group can add members.",
    ] = None,
    user_group_description: Annotated[
        str | None, "A brief text describing the purpose or role of the user group in Slack."
    ] = None,
    unique_mention_handle: Annotated[
        str | None,
        "A unique mention handle for the user group. It must not duplicate existing handles of channels, users, or other user groups.",  # noqa: E501
    ] = None,
    team_id_for_user_group_creation: Annotated[
        str | None,
        "Encoded team ID for the user group creation, required if using an org-level token.",
    ] = None,
    include_user_count: Annotated[
        bool | None, "Set to true to include the number of users in each User Group."
    ] = None,
    enable_display_as_sidebar_section: Annotated[
        bool | None,
        "Set to true to display the user group as a sidebar section for all group members if the group has one or more default channels.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.create'."]:
    """Creates a new user group in Slack.

    This tool allows the creation of a new user group in Slack using the Slack API. It should be called when you need to organize users into groups for easier management or communication. Requires 'usergroups:write' scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.create",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "name": user_group_name,
                "channels": default_channel_ids,
                "additional_channels": custom_additional_channels,
                "description": user_group_description,
                "handle": unique_mention_handle,
                "include_count": include_user_count,
                "team_id": team_id_for_user_group_creation,
                "enable_section": enable_display_as_sidebar_section,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:write"]))
async def disable_user_group(
    context: ToolContext,
    user_group_id: Annotated[str, "The encoded ID of the User Group to be disabled."],
    team_id: Annotated[
        str | None,
        "Encoded target team ID where the user group exists. Required only if using an org-level token; ignored for workspace-level tokens.",  # noqa: E501
    ] = None,
    include_user_count: Annotated[
        bool | None,
        "Include the number of users in the User Group. Set to true to include the count.",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.disable'."]:
    """Disable an existing Slack User Group.

    This tool should be called to disable an existing User Group in Slack. It requires appropriate OAuth scopes and sends a POST request to the Slack API. Use this tool when you need to deactivate a User Group to prevent users from being able to reference or use it."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.disable",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "usergroup": user_group_id,
                "include_count": include_user_count,
                "team_id": team_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:write"]))
async def enable_slack_user_group(
    context: ToolContext,
    user_group_id: Annotated[str, "The encoded ID of the User Group to be enabled in Slack."],
    team_id: Annotated[
        str | None,
        "Provide the encoded team ID where the user group is located. Only required if using an org-level token. Ignored with workspace-level tokens.",  # noqa: E501
    ] = None,
    include_user_count: Annotated[
        bool | None, "Set to true to include the number of users in the User Group."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.enable'."]:
    """Enable a user group in Slack.

    This tool activates a specified user group in Slack. It should be called when an action is needed to enable a user group so that it can be used within Slack for communication or organizational purposes. This tool is particularly useful for managing Slack user groups efficiently."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.enable",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "usergroup": user_group_id,
                "include_count": include_user_count,
                "team_id": team_id,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:read"]))
async def list_slack_user_groups(
    context: ToolContext,
    team_id_for_org_token: Annotated[
        str | None,
        "Encoded team ID required when using an org-level token. Ignored if using a workspace-level token.",  # noqa: E501
    ] = None,
    include_user_count: Annotated[
        bool | None, "Set to true to include the number of users in each User Group."
    ] = None,
    include_disabled_groups: Annotated[
        bool | None, "Set to true to include disabled user groups in the results."
    ] = None,
    include_users_in_group: Annotated[
        bool | None, "Include the list of users for each User Group in the response."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.list'."]:
    """Retrieve all user groups for a Slack team.

    This tool retrieves a list of all user groups available in a Slack team. It should be called when there's a need to access or display user group information within a Slack workspace."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.list",
            params=remove_none_values({
                "include_count": include_user_count,
                "include_disabled": include_disabled_groups,
                "include_users": include_users_in_group,
                "team_id": team_id_for_org_token,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:write"]))
async def update_slack_user_group(
    context: ToolContext,
    user_group_id: Annotated[str, "The encoded ID of the User Group to update in Slack."],
    default_channel_ids: Annotated[
        list[str] | None,
        "A comma-separated list of channel IDs where the User Group is set as default. Use encoded channel IDs.",  # noqa: E501
    ] = None,
    additional_channel_ids: Annotated[
        list[str] | None,
        "Comma separated encoded channel IDs for custom additions to user group members.",
    ] = None,
    user_group_description: Annotated[
        str | None,
        "A short description of the User Group to update in Slack. This should clearly define the group's purpose or role.",  # noqa: E501
    ] = None,
    user_group_handle: Annotated[
        str | None,
        "Unique mention handle for the User Group, distinct from all channels, users, and other User Groups.",  # noqa: E501
    ] = None,
    user_group_name: Annotated[
        str | None,
        "A unique name for the User Group to update. Ensure it does not duplicate any existing User Group names.",  # noqa: E501
    ] = None,
    team_id_for_org_token: Annotated[
        str | None,
        "Encoded team ID where the user group exists, required for org-level tokens. Ignored if using a workspace-level token.",  # noqa: E501
    ] = None,
    include_user_count: Annotated[
        bool | None, "Set to true to include the number of users in the User Group."
    ] = None,
    enable_sidebar_section: Annotated[
        bool | None,
        "Set to true to configure the user group to appear as a sidebar section for all group members. Only relevant if the group has 1 or more default channels.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.update'."]:
    """Update an existing User Group in Slack.

    This tool updates an existing User Group in Slack. It should be called when you need to modify the details of a user group, such as its name or permissions. Ensure the appropriate permissions are granted with the 'usergroups:write' scope."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.update",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "usergroup": user_group_id,
                "channels": default_channel_ids,
                "additional_channels": additional_channel_ids,
                "description": user_group_description,
                "handle": user_group_handle,
                "include_count": include_user_count,
                "name": user_group_name,
                "team_id": team_id_for_org_token,
                "enable_section": enable_sidebar_section,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["usergroups:write"]))
async def update_slack_usergroup_users(
    context: ToolContext,
    user_group_id: Annotated[str, "The encoded ID of the Slack user group to update."],
    user_ids_list: Annotated[
        list[str],
        "A comma separated string of encoded Slack user IDs representing the complete user list for the group. This replaces all current members.",  # noqa: E501
    ],
    team_id_for_org_token: Annotated[
        str | None,
        "Encoded team ID where the user group exists. Required if using an organization token; ignored with workspace-level token.",  # noqa: E501
    ] = None,
    update_additional_channels: Annotated[
        list[str] | None,
        "Encoded channel IDs to add user group members to, separated by commas. These represent additional channels for custom user group member additions.",  # noqa: E501
    ] = None,
    include_user_count: Annotated[
        bool | None, "Set to true to include the number of users in the user group in the response."
    ] = None,
    is_shared_section: Annotated[
        bool | None,
        "Indicates if the API call involves a shared section. Set to true if it does, otherwise false.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'usergroups.users.update'."]:
    """Update the list of users in a Slack user group.

    This tool updates the list of users for a specified Slack user group. It should be called when changes to the membership of a Slack user group are required."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/usergroups.users.update",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "usergroup": user_group_id,
                "users": user_ids_list,
                "include_count": include_user_count,
                "team_id": team_id_for_org_token,
                "additional_channels": update_additional_channels,
                "is_shared": is_shared_section,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(
    requires_auth=OAuth2(
        id="arcade-slack", scopes=["channels:read", "groups:read", "im:read", "mpim:read"]
    )
)
async def list_accessible_slack_conversations(
    context: ToolContext,
    pagination_cursor: Annotated[
        str | None,
        "A cursor for pagination to continue listing conversations from a specific point. Use the 'next_cursor' from a previous response. Default is the first page.",  # noqa: E501
    ] = None,
    maximum_items_to_return: Annotated[
        int | None,
        "The maximum number of conversations to return in the response. Must be an integer with a maximum value of 999. It is recommended to request no more than 200 results at a time for optimal performance. (default: '100')",  # noqa: E501
    ] = None,
    slack_team_id: Annotated[
        str | None,
        "The encoded ID of the Slack team to list conversations for. Required if using an organization-level token. Ignored if a workspace-level token is used.",  # noqa: E501
    ] = None,
    channel_types: Annotated[
        str | None,
        "Comma-separated list of channel types to filter conversations. Options: public_channel, private_channel, mpim, im. (default: 'public_channel')",  # noqa: E501
    ] = None,
    specific_user_id: Annotated[
        str | None,
        "Filter conversations by a specific user ID's membership. Only includes conversations shared with the calling user.",  # noqa: E501
    ] = None,
    exclude_archived_channels: Annotated[
        bool | None,
        "Set to true to exclude archived channels from the retrieved list of Slack conversations. (default: false)",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.conversations'."]:
    """Retrieve a list of conversations the user can access on Slack.

    This tool calls the Slack API to list all conversations (public channels, private channels, direct messages) that a user has access to. It can be used to view information about different types of conversations including public channels, private channels, and direct or group messages."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.conversations",
            params=remove_none_values({
                "cursor": pagination_cursor,
                "exclude_archived": exclude_archived_channels,
                "limit": maximum_items_to_return,
                "team_id": slack_team_id,
                "types": channel_types,
                "user": specific_user_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["conversations.connect:manage", "team:read"]))
async def check_slack_discoverability(
    context: ToolContext,
    email_to_check: Annotated[
        str, "The email address to verify if it is associated with a discoverable Slack user."
    ],
) -> Annotated[
    dict[str, Any], "Response from the API endpoint 'users.discoverableContacts.lookup'."
]:
    """Check if an email is discoverable on Slack.

    Use this tool to determine if an email address is associated with a discoverable Slack user. It should be called when needing to verify Slack user discoverability by email."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.discoverableContacts.lookup",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({"email": email_to_check}),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users:read"]))
async def get_slack_user_presence(
    context: ToolContext,
    target_user_id: Annotated[
        str | None,
        "The Slack user ID for which you want to retrieve presence information. (default: 'authed user')",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.getPresence'."]:
    """Retrieve user presence information from Slack.

    Use this tool to get the presence status of a user on Slack, indicating whether they are active or away."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.getPresence",
            params=remove_none_values({"user": target_user_id}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["identity.read", "identity.basic"]))
async def get_user_identity(
    context: ToolContext,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.identity'."]:
    """Retrieve a user's identity information from Slack.

    This tool is used to get detailed information about a user's identity on Slack. It should be called when user identity details are required, such as for authentication purposes or to display user information within an application leveraging Slack's API."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.identity",
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users:read", "users:read.email"]))
async def list_slack_team_users(
    context: ToolContext,
    pagination_cursor: Annotated[
        str | None,
        "Cursor for paginating through data. Use the `next_cursor` from a previous response to continue.",  # noqa: E501
    ] = None,
    maximum_items_to_return: Annotated[
        int | None, "Maximum number of users to return (recommended max is 200 for pagination)."
    ] = None,
    slack_team_id: Annotated[
        str | None,
        "The encoded team ID to list users from, necessary if an organization-level token is used. Ignored if a workspace-level token is provided.",  # noqa: E501
    ] = None,
    include_user_locale: Annotated[
        bool | None, "Set to true to receive locale information for each user. Default is false."
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.list'."]:
    """Fetches a list of all users in a Slack team.

    This tool retrieves a comprehensive list of all users within a specified Slack team. It includes user details and can access email information if the appropriate OAuth scopes are provided."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.list",
            params=remove_none_values({
                "cursor": pagination_cursor,
                "include_locale": include_user_locale,
                "limit": maximum_items_to_return,
                "team_id": slack_team_id,
            }),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users:read.email"]))
async def find_slack_user_by_email(
    context: ToolContext,
    user_email_address: Annotated[
        str, "The email address of the user in the Slack workspace to search for."
    ],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.lookupByEmail'."]:
    """Find a Slack user using their email address.

    This tool allows you to search for a Slack user by their email address. It should be called when you need to retrieve user information based on email within Slack."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.lookupByEmail",
            params=remove_none_values({"email": user_email_address}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users.profile:read", "users:read.email"]))
async def get_slack_user_profile(
    context: ToolContext,
    target_user_id: Annotated[
        str | None,
        "The unique identifier of the Slack user whose profile information is to be retrieved.",
    ] = None,
    include_labels: Annotated[
        bool | None,
        "Include labels for each ID in custom profile fields. This option can heavily rate-limit requests and is not recommended. Default is false.",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.profile.get'."]:
    """Retrieve Slack user profile information and custom status.

    This tool fetches the profile information of a Slack user, including their custom status and email (if authorized). It requires appropriate read scopes (users.profile:read or users:read.email)."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.profile.get",
            params=remove_none_values({"include_labels": include_labels, "user": target_user_id}),
            method="GET",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}


@tool(requires_auth=OAuth2(id="arcade-slack", scopes=["users.profile:write"]))
async def set_slack_profile_photo(
    context: ToolContext,
    crop_box_size: Annotated[
        str | None,
        "The size of the square crop box for the profile photo in pixels. Specify the width and height, which are the same value for a square.",  # noqa: E501
    ] = None,
    crop_box_x_coordinate: Annotated[
        str | None, "X coordinate of the top-left corner of the crop box for the profile photo."
    ] = None,
    crop_y_coordinate: Annotated[
        str | None,
        "Y coordinate of the top-left corner of the crop box for the user's profile photo on Slack. This determines where the cropping of the image will start on the vertical axis.",  # noqa: E501
    ] = None,
    profile_photo_image: Annotated[
        str | None,
        "The image file to set as the Slack profile photo. Provide image data directly with the correct content type (e.g., image/jpeg, image/png).",  # noqa: E501
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users.setPhoto'."]:
    """Set the user's profile photo on Slack.

    Use this tool to update a user's profile photo on Slack. This requires the 'users.profile:write' OAuth scope, allowing changes to profile information including the profile photo."""  # noqa: E501
    async with httpx.AsyncClient() as client:
        response = await client.request(
            url="https://slack.com/api/users.setPhoto",
            method="POST",
            headers=remove_none_values({
                "Content-Type": "application/x-www-form-urlencoded",
                "Authorization": "Bearer {authorization}".format(  # noqa: UP032
                    authorization=context.get_auth_token_or_empty()
                ),
            }),
            data=remove_none_values({
                "crop_w": crop_box_size,
                "crop_x": crop_box_x_coordinate,
                "crop_y": crop_y_coordinate,
                "image": profile_photo_image,
            }),
        )
        response.raise_for_status()
        try:
            return {"response_json": response.json()}
        except Exception:
            return {"response_text": response.text}
