Source code for camel.toolkits.slack_toolkit
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
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__)
[docs]
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
[docs]
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']}"
[docs]
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']}"
[docs]
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']}"
[docs]
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"]
# Filtering conversations and extracting required information
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']}"
[docs]
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']}"
[docs]
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']}"
[docs]
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']}"
[docs]
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),
]