|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations |
|
|
|
import json |
|
import logging |
|
import os |
|
from typing import TYPE_CHECKING, List, Optional |
|
|
|
from camel.toolkits.base import BaseToolkit |
|
|
|
if TYPE_CHECKING: |
|
from ssl import SSLContext |
|
|
|
from slack_sdk import WebClient |
|
|
|
from camel.toolkits import FunctionTool |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
class SlackToolkit(BaseToolkit): |
|
r"""A class representing a toolkit for Slack operations. |
|
|
|
This class provides methods for Slack operations such as creating a new |
|
channel, joining an existing channel, leaving a channel. |
|
""" |
|
|
|
def _login_slack( |
|
self, |
|
slack_token: Optional[str] = None, |
|
ssl: Optional[SSLContext] = None, |
|
) -> WebClient: |
|
r"""Authenticate using the Slack API. |
|
|
|
Args: |
|
slack_token (str, optional): The Slack API token. |
|
If not provided, it attempts to retrieve the token from |
|
the environment variable SLACK_BOT_TOKEN or SLACK_USER_TOKEN. |
|
ssl (SSLContext, optional): SSL context for secure connections. |
|
Defaults to `None`. |
|
|
|
Returns: |
|
WebClient: A WebClient object for interacting with Slack API. |
|
|
|
Raises: |
|
ImportError: If slack_sdk package is not installed. |
|
KeyError: If SLACK_BOT_TOKEN or SLACK_USER_TOKEN |
|
environment variables are not set. |
|
""" |
|
try: |
|
from slack_sdk import WebClient |
|
except ImportError as e: |
|
raise ImportError( |
|
"Cannot import slack_sdk. Please install the package with \ |
|
`pip install slack_sdk`." |
|
) from e |
|
if not slack_token: |
|
slack_token = os.environ.get("SLACK_BOT_TOKEN") or os.environ.get( |
|
"SLACK_USER_TOKEN" |
|
) |
|
if not slack_token: |
|
raise KeyError( |
|
"SLACK_BOT_TOKEN or SLACK_USER_TOKEN environment " |
|
"variable not set." |
|
) |
|
|
|
client = WebClient(token=slack_token, ssl=ssl) |
|
logger.info("Slack login successful.") |
|
return client |
|
|
|
def create_slack_channel( |
|
self, name: str, is_private: Optional[bool] = True |
|
) -> str: |
|
r"""Creates a new slack channel, either public or private. |
|
|
|
Args: |
|
name (str): Name of the public or private channel to create. |
|
is_private (bool, optional): Whether to create a private channel |
|
instead of a public one. Defaults to `True`. |
|
|
|
Returns: |
|
str: JSON string containing information about Slack |
|
channel created. |
|
|
|
Raises: |
|
SlackApiError: If there is an error during get slack channel |
|
information. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
response = slack_client.conversations_create( |
|
name=name, is_private=is_private |
|
) |
|
channel_id = response["channel"]["id"] |
|
response = slack_client.conversations_archive(channel=channel_id) |
|
return str(response) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def join_slack_channel(self, channel_id: str) -> str: |
|
r"""Joins an existing Slack channel. |
|
|
|
Args: |
|
channel_id (str): The ID of the Slack channel to join. |
|
|
|
Returns: |
|
str: A confirmation message indicating whether join successfully |
|
or an error message. |
|
|
|
Raises: |
|
SlackApiError: If there is an error during get slack channel |
|
information. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
response = slack_client.conversations_join(channel=channel_id) |
|
return str(response) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def leave_slack_channel(self, channel_id: str) -> str: |
|
r"""Leaves an existing Slack channel. |
|
|
|
Args: |
|
channel_id (str): The ID of the Slack channel to leave. |
|
|
|
Returns: |
|
str: A confirmation message indicating whether leave successfully |
|
or an error message. |
|
|
|
Raises: |
|
SlackApiError: If there is an error during get slack channel |
|
information. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
response = slack_client.conversations_leave(channel=channel_id) |
|
return str(response) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def get_slack_channel_information(self) -> str: |
|
r"""Retrieve Slack channels and return relevant information in JSON |
|
format. |
|
|
|
Returns: |
|
str: JSON string containing information about Slack channels. |
|
|
|
Raises: |
|
SlackApiError: If there is an error during get slack channel |
|
information. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
response = slack_client.conversations_list() |
|
conversations = response["channels"] |
|
|
|
filtered_result = [ |
|
{ |
|
key: conversation[key] |
|
for key in ("id", "name", "created", "num_members") |
|
} |
|
for conversation in conversations |
|
if all( |
|
key in conversation |
|
for key in ("id", "name", "created", "num_members") |
|
) |
|
] |
|
return json.dumps(filtered_result, ensure_ascii=False) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def get_slack_channel_message(self, channel_id: str) -> str: |
|
r"""Retrieve messages from a Slack channel. |
|
|
|
Args: |
|
channel_id (str): The ID of the Slack channel to retrieve messages |
|
from. |
|
|
|
Returns: |
|
str: JSON string containing filtered message data. |
|
|
|
Raises: |
|
SlackApiError: If there is an error during get |
|
slack channel message. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
result = slack_client.conversations_history(channel=channel_id) |
|
messages = result["messages"] |
|
filtered_messages = [ |
|
{key: message[key] for key in ("user", "text", "ts")} |
|
for message in messages |
|
if all(key in message for key in ("user", "text", "ts")) |
|
] |
|
return json.dumps(filtered_messages, ensure_ascii=False) |
|
except SlackApiError as e: |
|
return f"Error retrieving messages: {e.response['error']}" |
|
|
|
def send_slack_message( |
|
self, |
|
message: str, |
|
channel_id: str, |
|
user: Optional[str] = None, |
|
) -> str: |
|
r"""Send a message to a Slack channel. |
|
|
|
Args: |
|
message (str): The message to send. |
|
channel_id (str): The ID of the Slack channel to send message. |
|
user (Optional[str]): The user ID of the recipient. |
|
Defaults to `None`. |
|
|
|
Returns: |
|
str: A confirmation message indicating whether the message was sent |
|
successfully or an error message. |
|
|
|
Raises: |
|
SlackApiError: If an error occurs while sending the message. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
if user: |
|
response = slack_client.chat_postEphemeral( |
|
channel=channel_id, text=message, user=user |
|
) |
|
else: |
|
response = slack_client.chat_postMessage( |
|
channel=channel_id, text=message |
|
) |
|
return str(response) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def delete_slack_message( |
|
self, |
|
time_stamp: str, |
|
channel_id: str, |
|
) -> str: |
|
r"""Delete a message to a Slack channel. |
|
|
|
Args: |
|
time_stamp (str): Timestamp of the message to be deleted. |
|
channel_id (str): The ID of the Slack channel to delete message. |
|
|
|
Returns: |
|
str: A confirmation message indicating whether the message |
|
was delete successfully or an error message. |
|
|
|
Raises: |
|
SlackApiError: If an error occurs while sending the message. |
|
""" |
|
from slack_sdk.errors import SlackApiError |
|
|
|
try: |
|
slack_client = self._login_slack() |
|
response = slack_client.chat_delete( |
|
channel=channel_id, ts=time_stamp |
|
) |
|
return str(response) |
|
except SlackApiError as e: |
|
return f"Error creating conversation: {e.response['error']}" |
|
|
|
def get_tools(self) -> List[FunctionTool]: |
|
r"""Returns a list of FunctionTool objects representing the |
|
functions in the toolkit. |
|
|
|
Returns: |
|
List[FunctionTool]: A list of FunctionTool objects |
|
representing the functions in the toolkit. |
|
""" |
|
return [ |
|
FunctionTool(self.create_slack_channel), |
|
FunctionTool(self.join_slack_channel), |
|
FunctionTool(self.leave_slack_channel), |
|
FunctionTool(self.get_slack_channel_information), |
|
FunctionTool(self.get_slack_channel_message), |
|
FunctionTool(self.send_slack_message), |
|
FunctionTool(self.delete_slack_message), |
|
] |
|
|