Source code for camel.toolkits.whatsapp_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. =========
import os
from typing import Any, Dict, List, Optional, Union
import requests
from camel.toolkits import FunctionTool
from camel.toolkits.base import BaseToolkit
from camel.utils import MCPServer, retry_on_error
[docs]
@MCPServer()
class WhatsAppToolkit(BaseToolkit):
r"""A class representing a toolkit for WhatsApp operations.
This toolkit provides methods to interact with the WhatsApp Business API,
allowing users to send messages, retrieve message templates, and get
business profile information.
Attributes:
retries (int): Number of retries for API requests in case of failure.
delay (int): Delay between retries in seconds.
base_url (str): Base URL for the WhatsApp Business API.
version (str): API version.
"""
def __init__(self, timeout: Optional[float] = None):
r"""Initializes the WhatsAppToolkit."""
super().__init__(timeout=timeout)
self.base_url = "https://graph.facebook.com"
self.version = "v17.0"
self.access_token = os.environ.get("WHATSAPP_ACCESS_TOKEN", "")
self.phone_number_id = os.environ.get("WHATSAPP_PHONE_NUMBER_ID", "")
if not all([self.access_token, self.phone_number_id]):
raise ValueError(
"WhatsApp API credentials are not set. "
"Please set the WHATSAPP_ACCESS_TOKEN and "
"WHATSAPP_PHONE_NUMBER_ID environment variables."
)
[docs]
@retry_on_error()
def send_message(
self, to: str, message: str
) -> Union[Dict[str, Any], str]:
r"""Sends a text message to a specified WhatsApp number.
Args:
to (str): The recipient's WhatsApp number in international format.
message (str): The text message to send.
Returns:
Union[Dict[str, Any], str]: A dictionary containing
the API response if successful, or an error message string if
failed.
"""
url = f"{self.base_url}/{self.version}/{self.phone_number_id}/messages"
headers = {
"Authorization": f"Bearer {self.access_token}",
"Content-Type": "application/json",
}
data = {
"messaging_product": "whatsapp",
"to": to,
"type": "text",
"text": {"body": message},
}
try:
response = requests.post(url=url, headers=headers, json=data)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
raise e
except Exception as e:
return f"Failed to send message: {e!s}"
[docs]
@retry_on_error()
def get_message_templates(self) -> Union[List[Dict[str, Any]], str]:
r"""Retrieves all message templates for the WhatsApp Business account.
Returns:
Union[List[Dict[str, Any]], str]: A list of dictionaries containing
template information if successful, or an error message string
if failed.
"""
url = (
f"{self.base_url}/{self.version}/{self.phone_number_id}"
"/message_templates"
)
headers = {"Authorization": f"Bearer {self.access_token}"}
try:
response = requests.get(url=url, headers=headers)
response.raise_for_status()
return response.json().get("data", [])
except Exception as e:
return f"Failed to retrieve message templates: {e!s}"
[docs]
@retry_on_error()
def get_business_profile(self) -> Union[Dict[str, Any], str]:
r"""Retrieves the WhatsApp Business profile information.
Returns:
Union[Dict[str, Any], str]: A dictionary containing the business
profile information if successful, or an error message string
if failed.
"""
url = (
f"{self.base_url}/{self.version}/{self.phone_number_id}"
"/whatsapp_business_profile"
)
headers = {"Authorization": f"Bearer {self.access_token}"}
params = {
"fields": (
"about,address,description,email,profile_picture_url,"
"websites,vertical"
)
}
try:
response = requests.get(
url=url,
headers=headers,
params=params,
)
response.raise_for_status()
return response.json()
except Exception as e:
return f"Failed to retrieve business profile: {e!s}"
[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 for the
toolkit methods.
"""
return [
FunctionTool(self.send_message),
FunctionTool(self.get_message_templates),
FunctionTool(self.get_business_profile),
]