Автоматизация WhatsApp на Python
В этом руководстве мы покажем, как создать безопасного для продакшена чат-бота для WhatsApp на Python с использованием Flask и ChatGPT. В то время как Meta* требует сложной верификации компании, Whapi.Cloud обеспечивает мгновенное подключение номера по QR-коду. Вы узнаете, как обрабатывать вебхуки, автоматизировать группы до 1024 участников, отправлять рассылки в каналы, предотвращать бесконечные циклы и настроить дедупликацию сообщений для контроля расходов на API.
- Как работать с WhatsApp API с использованием Python;
- Интеграцию с Whapi.Cloud для автоматизации различных задач;
- Использование вебхуков для обработки и автоответа на сообщения;
- Подключение вашего WhatsApp-бота к ChatGPT для диалогов на базе ИИ;
А чтобы упростить работу, вы можете воспользоваться нашими готовыми скриптами Python ботов, которые мы опубликовали на GitHub. В этих проектах подробно описан процесс настройки и тестирования, а внутри кода вы найдете полезные комментарии. Это отличный старт для начинающих разработчиков.
Почему разработчики избегают официального Meta* Cloud API для ботов WhatsApp
Подготовка к разработке бота
- Python. Установите Python, если он ещё не установлен. Скачайте последнюю версию (рекомендуется 3.6 или выше) с официального сайта и следуйте инструкциям.
- Flask. Flask — это лёгкий веб-фреймворк на Python, который мы будем использовать для настройки сервера и обработки вебхуков. Вы всегда сможете установить Flask следующей командой: pip install Flask
- API Токен. Зарегистрируйтесь в Whapi.Cloud, чтобы получить API токен. Этот токен позволит вашему боту взаимодействовать с WhatsApp через API. После регистрации вам предоставят бесплатный канал с некоторыми лимитами. Этого хватит для тестирования вашей разработки. Whapi.Cloud - провайдер, который выделяется своей стабильностью, низкой стоимостью и большим количеством функций. Инструкции по получению токена мы приведем ниже.
- Настроенный вебхук. Чтобы бот мог обрабатывать входящие сообщения и события из WhatsApp, вам потребуется URL вашего сервера (локального или внешнего) для обработки уведомлений от WhatsApp. В статье мы подробно разберем, как это сделать и где взять такую ссылку.
Получение токена для WhatsApp API
Регистрация и подключение номера
- 1. Перейдите в дашборд и откройте страницу канала Default Channel, который уже создан для вас.
- 2. На первом шаге вы увидите QR-код с инструкцией.
- 3. Откройте WhatsApp на вашем устройстве, перейдите в Настройки → Связанные устройства → Подключить устройство → Сканировать QR-код.
- 4. После успешного подключения задайте имя каналу (например, "Мой Чат-бот"), чтобы удобнее работать в дальнейшем.
Получение API-токена
Your API Key
Инструменты для работы с API
- Удобный Хаб для разработчика: Специализированная платформа с документацией и примерами, позволит получить на все эндпоинты фрагменты кода на разных языках программирования.
- Postman-коллекция: Готовые запросы для тестирования API через Постман.
- Swagger-файл: Подробное описание всех методов API, с возможностью тестирования прямо на странице канала.
-
WhatsApp MCP Сервер: Интегрируйте вашего WhatsApp-бота с ИИ-агентами и инструментами разработки (например, Cursor) с помощью нашего официального WhatsApp MCP Сервера.
Что такое Webhook и как его настроить?
Что такое вебхук?
- Мгновенные уведомления. Все события обрабатываются практически в реальном времени.
- Высокая пропускная способность. Скорость получения уведомлений ограничена только производительностью вашего сервера.
- Гибкость. Вы можете получать только те события, которые вам действительно нужны, например: Личные сообщения; Сообщения в группах; Изменения статусов сообщений; Изменения участников групп; Уведомления о пропущенных вызовах; Статусы каналов и многое другое.
Как и где получить URL для вебхука?
- 1) Скачайте Ngrok с официального сайта и распакуйте его. Теперь откройте терминал и перейдите в папку, где хранится Ngrok.
- 2) Запустите ./ngrok http НОМЕР_ПОРТА, заменяя НОМЕР_ПОРТА на порт, на котором ваш Flask сервер работает локально (например 80).
- 3) Теперь у вас должен быть публичный URL, который вы можете использовать как URL для вебхука. Именно его и нужно скопировать для дальнейшей работы.
Установка вебхука на канал
- Перейдите в настройки канала. На странице канала нажмите кнопку настроек (в правом верхнем углу).
- Настройте вебхук. Укажите ваш URL в разделе вебхуков, используя предвыбранные настройки. Вы можете настроить несколько вебхуков для разных событий, если это необходимо. Так же, вы сможете менять эти настройки через API.
- Сохраните изменения. После этого все уведомления о событиях в WhatsApp будут отправляться на указанный вами сервер.
Создание основы бота WhatsApp на Python
Flask==3.0.0
requests==2.27.1
requests-toolbelt==0.9.1
python-dotenv==0.20.0
pip install -r requirements.txt
API_TOKEN=8FjpwmyFUulh7emXOprrET3xKrwJ984O # API token from your channel
API_URL=https://gate.whapi.cloud # API endpoint URL
PORT=80 # example, 80 or 443
#URL_LINK= The Webhook link to your server {link to server}/hook.
from dotenv import load_dotenv
import os
load_dotenv()
api_token = os.getenv("API_TOKEN")
Отправка текстового сообщения
import requests
# URL for sending text messages. Can be pulled from .env
url = "https://gate.whapi.cloud/messages/text"
# Data for sending a message
payload = {
"to": "919984351847", # Enter the recipient's number in international format
"body": "Hello! This is a test message." # Text of message
}
# Headers, including authorization token
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": f"Bearer {api_token}" # Use the token from the .env file
}
# Sending a POST request
response = requests.post(url, json=payload, headers=headers)
# Output server response
print(response.status_code)
print(response.text)
Получение сообщений через Flask Webhook
from flask import Flask, request, jsonify
app = Flask(__name__)
# Route for processing incoming messages
@app.route('/hook', methods=['POST'])
def webhook():
# Retrieving data from a request
data = request.json
# Logging an incoming message
print("Received message:", data)
# Example of incoming message processing
if "messages" in data:
for message in data["messages"]:
sender = message["from"] # Sender's number
text = message.get("body", "") # Text of message
print(f"Message from {sender}: {text}")
# Logic for replying to a message
# Check out our examples on GitHub, where we use more branching on commands for the bot
if text.lower() == "hello":
send_response(sender, "Hi there! How can I help you?")
elif text.lower() == "bye":
send_response(sender, "Goodbye!")
return jsonify({"status": "success"}), 200
# Function for sending a reply
def send_response(to, body):
import requests
url = "https://gate.whapi.cloud/messages/text"
payload = {
"to": to,
"body": body
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": f"Bearer {api_token}" # Use the token from the .env file
}
response = requests.post(url, json=payload, headers=headers)
print(f"Response to {to}: {response.status_code}, {response.text}")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
Расширенные возможности
Отправка изображения
import requests
url = "https://gate.whapi.cloud/messages/image"
payload = {
"to": "919984351847",
"media": "https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg",
"caption": "An example image"
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": "Bearer Your_Token"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
Отправка файла
import requests
url = "https://gate.whapi.cloud/messages/document"
payload = {
"to": "919984351847",
"media": "data:application/pdf;base64,JVBERi0xLjQKJdPr6eEKMSAwIG9iago8PC9UaXRsZSAoVGVybXMgb2YgU2VydmljZSBXaGFwaS5DbG91ZCkKL0NyZWF0b3IgKE1vemlsbGEvNS4wIFwoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0XCkgQXBwbGVXZWJLaXQvNTM3LjM2IFwoS0h............",
"filename": "Terms of Service Whapi.Cloud.pdf",
"caption": "Hello, I am attaching an important file to my message"
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": "Bearer Your_Token"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
Создание WhatsApp Группы на Python
import requests
url = "https://gate.whapi.cloud/groups"
payload = {
"participants": ["919984351847", "919984351848", "919984351849"],
"subject": "Group Subject 3"
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": "Bearer Your_Token"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
Программная автоматизация групп и каналов в WhatsApp
Интеграция с ChatGPT: ИИ для вашего бота в WhatsApp
Шаг 1: Добавьте зависимости для ChatGPT
openai>=1.91.0,<2.0.0
httpx>=0.28.1,<1.0.0
httpcore>=1.0.9,<2.0.0
- openai — официальный SDK для отправки запросов в OpenAI и получения ответов от ChatGPT.
- httpx — современная асинхронная HTTP-библиотека, которую OpenAI использует для вызовов API.
- httpcore — низкоуровневая библиотека сетевого транспорта, используемая httpx. Её необходимо явно закрепить по версии, чтобы избежать конфликтов.
pip install -r requirements.txt
Шаг 2: Получите свой OpenAI API-ключ
OPENAI_API_KEY=your_api_key_here
Шаг 3: Добавьте AI-логику в вашего бота
- - получает входящие webhook-события от Whapi.Cloud,
- - проверяет, начинается ли сообщение с /ai,
- - отправляет запрос пользователя в ChatGPT через OpenAI API,
- - возвращает сгенерированный AI-ответ пользователю в WhatsApp.
Как предотвратить бесконечные циклы и обеспечить безопасность в продакшене
from_me во входящем JSON-пакете и немедленный пропуск таких событий полностью устраняют этот риск. Дополнительные советы по сохранению репутации отправителя читайте в нашей статье как избежать банов в WhatsApp.
from flask import Flask, request, jsonify
import requests
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
API_TOKEN = os.getenv("API_TOKEN")
API_URL = os.getenv("API_URL")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
BACKUP_ADMIN_NUMBER = os.getenv("BACKUP_ADMIN_NUMBER")
if not API_TOKEN or not API_URL or not OPENAI_API_KEY:
raise RuntimeError("Missing required environment variables in .env")
openai_client = OpenAI(api_key=OPENAI_API_KEY)
# Simple in-memory message deduplication to prevent duplicate processing
processed_messages = set()
MAX_DEDUPLICATION_SIZE = 1000
def send_message(to, body):
"""Sends a text message using the Whapi.Cloud HTTP REST API."""
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
payload = {"to": to, "body": body}
response = requests.post(f"{API_URL}/messages/text", json=payload, headers=headers)
print("Whapi response:", response.status_code, response.text)
def send_backup_alert(error_message):
"""Sends an alert to the backup admin when a critical failure occurs."""
if BACKUP_ADMIN_NUMBER:
send_message(BACKUP_ADMIN_NUMBER, f"⚠ CRITICAL BOT ALERT: {error_message}")
def ask_openai(prompt):
"""Sends the user prompt to ChatGPT and returns the text response."""
response = openai_client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content.strip()
@app.route("/hook/messages", methods=["POST"])
def webhook():
data = request.json
print("Incoming webhook:", data)
for msg in data.get("messages", []):
# 1. The loop prevention filter: ignore messages sent by the bot itself
if msg.get("from_me"):
continue
msg_id = msg.get("id")
# 2. Webhook message deduplication
if msg_id in processed_messages:
print(f"Duplicate message ignored: {msg_id}")
continue
processed_messages.add(msg_id)
if len(processed_messages) > MAX_DEDUPLICATION_SIZE:
processed_messages.pop() # Keep memory footprint bounded
sender = msg.get("chat_id")
text = (msg.get("text") or {}).get("body", "").strip()
if text.lower().startswith("/ai "):
prompt = text[4:].strip()
if not prompt:
send_message(sender, "Please provide a prompt after /ai.")
else:
try:
reply = ask_openai(prompt)
send_message(sender, reply)
except Exception as e:
error_msg = f"Failed to process ChatGPT request: {e}"
print(error_msg)
send_message(sender, "Sorry, I encountered an error processing your request.")
send_backup_alert(error_msg)
else:
send_message(sender, "Hi! To ask me something, type:\n/ai your question")
return jsonify({"status": "received"}), 200
def register_webhook():
"""Registers the webhook URL with Whapi.Cloud on startup."""
bot_url = os.getenv("BOT_URL")
if bot_url:
headers = {"Authorization": f"Bearer {API_TOKEN}"}
payload = {
"webhooks": [
{
"url": bot_url,
"events": [{"type": "messages", "method": "post"}],
"mode": "method"
}
]
}
response = requests.patch(f"{API_URL}/settings", json=payload, headers=headers)
print("Webhook registration:", response.status_code, response.text)
if __name__ == "__main__":
register_webhook()
port = int(os.getenv("PORT", 8080))
app.run(host="0.0.0.0", port=port)
Запуск вашего Python-бота в продакшене
gunicorn --workers 3 --bind 0.0.0.0:8080 index:app
Dockerfile и docker-compose.yml. Такая конфигурация монтирует локальную папку, автоматически загружает переменные окружения и перезапускает контейнер при перезагрузке сервера.
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["gunicorn", "--workers", "3", "--bind", "0.0.0.0:8080", "index:app"]
version: '3.8'
services:
whatsapp-bot:
build: .
ports:
- "8080:8080"
env_file:
- .env
restart: always
docker-compose up -d --build. Готовые шаблоны контейнеров и примеры развертывания вы можете найти в официальных примерах Python-ботов на GitHub, которые содержат стандартизированные скрипты развертывания и конфигурационные шаблоны.