В этом руководстве мы напишем простой Python-скрипт, предназначенный для отправки WhatsApp-сообщений. В ходе работы будем пользоваться Python-пакетом Twilio. Для организации ежедневного запуска скрипта в заданное время разместим код в облаке.

Одним из подходов к решению этой задачи является использование Python-пакета Selenium и веб-версии WhatsApp вместо сервиса Twilio, на который, после исчерпания возможностей бесплатного предложения, нужно оформлять платную подписку. Но так как работа с веб-версией WhatsApp требует периодического сканирования QR-кода с помощью мобильного телефона, автоматизировать отправку сообщений при таком подходе не получится.
Работа над проектом будет состоять из трёх шагов:
- Настройка Twilio.
- Изучение и модификация кода.
- Развёртывание проекта в облаке и настройка триггера.
Шаг 1. Настройка Twilio
Создадим бесплатную учётную запись на сайте Twilio, подтвердим адрес электронной почты и номер телефона.

Регистрация учётной записи Twilio
Кроме того, в рамках бесплатного предложения Twilio необходимо использовать WhatsApp-песочницу (WhatsApp Sandbox). Это означает, что вы не сможете пользоваться собственным номером телефона, и то, что вам придётся пройти через процедуру выдачи разрешения на получение WhatsApp-сообщений.
Собственным номером для работы с сообщениями можно пользоваться после того, как WhatsApp разрешит Twilio использовать ваш номер. Для того чтобы получить разрешение, нужно заполнить форму. Из материалов техподдержки Twilio можно узнать о том, что, хотя Twilio и работает напрямую с WhatsApp, на получение разрешения может понадобиться некоторое время. К тому же, там говорится об ограниченных масштабах выдачи разрешений. В результате многим приходится пользоваться WhatsApp-песочницей Twilio.
Всё это особой радости не вызывает, но то, что доступно нам в рамках бесплатного предложения Twilio, позволяет решить нашу задачу. Кроме того, получается, что WhatsApp-песочница — это пока единственный широкодоступный вариант.
Теперь нужно подключить телефон получателя сообщений к песочнице, после чего на этот телефон можно будет отправлять сообщения. Для того чтобы узнать о том, как это сделать, вам нужно перейти в раздел консоли Twilio, который посвящён WhatsApp. В частности, тут предлагается отправить WhatsApp-сообщение с указанным текстом на определённый номер.

Страница консоли Twilio с инструкциями по подключению телефона, на который можно будет отправлять сообщения

Запрос на подключение, отправленный с телефона
Сохраните выданный вам WhatsApp-номер в контактах. Ему можно назначить любое имя. Я, чтобы не усложнять себе жизнь, назвал этот контакт Twilio Sandbox, а потом отправил на него сообщение с телефона отца (это можно видеть на предыдущем рисунке). Эта процедура выполняется лишь один раз.
Теперь нужно перейти в консоль Twilio и получить SID и токен аутентификации для своей учётной записи. Эти данные помогут Twilio узнать вас при программной работе с сервисом.
Шаг 2. Изучение и модификация кода
Загрузите этот GitHub-репозиторий и распакуйте архив.

Содержимое zip-файла
Здесь вы найдёте файл с исходным кодом (
whatsapp_messaging.py
) и пакет для развёртывания проекта (aws_lambda_deploy.zip
).Вот код скрипта:
from twilio.rest import Client
def msg_mom_and_dad(event=None, context=None):
# тут нужно использовать SID и токен аутентификации, которые вы получили на Twilio
twilio_sid = 'AC84c9f1602d7fb6af4eda5b0c39a03b37'
auth_token = '4a2021b28f1aa606d9c6945d3c248ebd'
whatsapp_client = Client(twilio_sid, auth_token)
# в этот словарь можно добавлять контактные сведения тех,
# кому вы хотите отправлять сообщения
contact_directory = {'daddy':'+919624666836'}
for key, value in contact_directory.items():
msg_loved_ones = whatsapp_client.messages.create(
body = 'good morning {} !'.format(key),
from_= 'whatsapp:+14155238886',
to='whatsapp:' + value,
)
print(msg_loved_ones.sid)
Сейчас мы разберём этот код. Вот, для удобства, скриншот с пронумерованными строками.

Код файла whatsapp_messaging.py с пронумерованными строками
- Строка 1. Импорт клиента для работы с REST-API Twilio.
- Строка 3. Создание функции
msg_mom_and_dad
. Эту функцию мы передадим AWS. Она будет вызываться ежедневно в заданное время. - Строки 6-7. Здесь вам нужно заменить существующие в коде
sid
иauth_token
на собственные (об их получении мы говорили в конце предыдущего раздела). - Строка 9. Создание объекта клиента Twilio с использованием учётных данных.
- Строка 13. Создание словаря. В качестве ключа тут используется имя получателя сообщений, в качестве значения — номер его телефона. В этот словарь можно добавить и дополнительные контактные сведения.
- Строка 15. Цикл
for
, в котором осуществляется обход словаря (в нём пока имеется лишь одна запись). Вbody
нужно указать текст сообщения. Я создал простое сообщение с текстом «good morning», за которым следует значение, взятое из ключа текущего элемента словаря. В моём случае это приводит к формированию сообщения «good morning daddy !». Воfrom_
указывается тот WhatsApp-номер, который мы получили ранее. Вto
записывают номер получателя сообщения — тот, с которого ранее отправляли запрос на подключение к WhatsApp-песочнице Twilio. - Строка 23. Тут мы, в целях проверки состояния сообщения, выводим его SID. Мы этими сведениями пользоваться не будем.
Вам, чтобы воспользоваться этим кодом для отправки сообщений, нужно изменить в нём следующее:
twilio_sid
auth_token
contact_directory
from_
body (это необязательно)
После того, как вы внесёте в код изменения, сохраните файл. Затем распакуйте архив
aws_lambda_deploy.zip
, замените файл whatsapp_messaging.py
на ваш файл с тем же именем, после чего снова упакуйте всё в .zip-архив. Смысл этих действий сводится к тому, чтобы внести в код ваши учётные данные и сведения о тех, кому вы хотите отправлять сообщения. Всё остальное в пакете, предназначенном для развёртывания на AWS, осталось неизменным. Теперь займёмся работой с AWS.Шаг 3. Развёртывание проекта на AWS и настройка триггера
Код готов к запуску и к тому, чтобы отправлять WhatsApp-сообщения. Если вы интересуетесь тем, какую роль в проекте играют другие файлы из архива
aws_lambda_deploy.zip
, то знайте, что среди этих файлов находятся пакет Twilio и все остальные зависимости проекта. Всё это нам нужно из-за того, что мы планируем использовать функции AWS Lambda в Python-окружении, в котором нет пакета Twilio. А почему бы нам это не исправить, просто выполнив для установки нужного пакета команду pip install twilio
? Дело в том, что тут у нас нет сервера.Для этого мы используем AWS Lambda — это бессерверная вычислительная среда, в которой можно размещать фрагменты кода, вызов которых, в соответствии с нуждами пользователя, инициируют различные события и триггеры. Наш код планируется запускать всего раз в день, поэтому использование чего-то вроде EC2-сервера на AWS, работающего круглосуточно, окажется пустой тратой вычислительных ресурсов и денег. Наша Lambda-функция будет вызываться ежедневно в определённое время по запросу из триггера, а её выполнение будет занимать совсем немного времени.
Начало создания Lambda-функции
Войдите в свою учётную запись AWS. После этого пройдите по пути
Services > Compute > Lambda > Create a function
.
Экран создания Lambda-функции
Дадим функции имя.
В качестве окружения, в котором будет выполняться функция, выберем Python 3.6. Нам не нужно подключаться к другим сервисам AWS. Поэтому нас устроит уровень разрешений, задаваемый вариантом
Create a new role with basic Lambda permissions
.После выполнения настроек достаточно нажать на кнопку
Create function
. Теперь мы окажемся на главной панели управления.
Панель управления
Здесь, в разделе
Function code
, нужно указать обработчик (Handler
), с помощью которого система сможет запускать наш код. В нашем случае в поле Handler
нужно записать строку whatsapp_messaging. msg_mom_and_dad
, указав имя файла с кодом и функцию, которую мы хотим вызывать.В поле
Function package
нужно загрузить наш .zip-файл, то есть — тот файл, который мы создали на предыдущем шаге.Теперь код готов к запуску. Проверить — работает ли функция и отправляет ли она сообщения, можно, нажав на кнопку
Test
.Финальным шагом нашей работы станет настройка триггера, который будет вызывать функцию ежедневно в заданное время. Пройдите по пути
Add trigger > CloudWatch Events
.
Настройка триггера
Нам нужно создать новое правило (
Rule
). Ему необходимо назначить имя (Rule name
). При желании можно добавить к нему описание (Rule description
).Укажем тип правила (
Rule type
) как Schedule expression
.Время вызова функции задаётся с помощью конструкции
cron(30 1 * * ? *)
. Разберём эту конструкцию:30 1
означает UTC-время 1:30 утра. Это — 7 утра по моему IST-времени.- Следующие два символа,
* *
, служат для указания дня месяца и месяца. - Следующие два символа,
? *
, позволяют указать день недели и год. Эта конструкция означает, что функция будет вызываться ежедневно, без ограничений по годам и месяцам.
Здесь вы можете узнать о том, как настраивать собственные задания cron.
После того, как настройка триггера завершена, проверьте — установлен ли флажок
Enable trigger
, включающий триггер. Теперь осталось лишь нажать на кнопку Add
и триггер будет создан.
Сведения о триггере

Сведения о Lambda-функции
На панели управления Lambda-функции можно видеть, что к функции прикреплена сущность
CloudWatch Events
, и то, что функция может вызываться по срабатыванию соответствующего триггера.Итоги

Сообщение, отправленное Python-скриптом
Мы завершили работу над проектом. Теперь можно, в телефоне получателя сообщений, в контактах WhatsApp, поменять имя контакта Twilio Sandbox на собственное (я поменял его на Son). Наша система, кроме того, позволяет общаться с получателем сообщений из панели управления Twilio.
Уважаемые читатели! Используете ли вы Twilio в своих проектах?

Комментарии (29)
yarkov
23.08.2019 12:45Он, глядя на то, как его родители каждое утро шлют ему в WhatsApp вдохновляющие цитаты и полезные советы о здоровье, решил, что пришло время ответить им взаимностью.
Какой хороший человек. Я таких сразу в ЧС кидаю.
KirillGerasimov
23.08.2019 13:23Статья должна была называться «Как настроить спам-рассылку для своих родителей».
Предпосылки, может, неплохи, но обманывать родителей, заставляя их думать, что им пишет их ребенок — немного низко.
maximw
23.08.2019 14:32-1Безотносительно технической ценности статьи, удивлен первым нескольким комментаторам. Такое впечатление, что у людей полностью отсутствует абстрактное мышление. Да, задача выбрана не очень удачно, но статья же не про это. Придираться к этической стороне такого общения с родителями — это как придираться к землекопам в арифметической задачке.
algotrader2013
23.08.2019 14:35+3Читаю комментарии, и умиляюсь) Как говорится, сытый голодного не понимает. Понятно, что надо быть конченым моральным уродом, чтобы использовать подобное в наших краях, или в странах западной цивилизации.
Но есть один нюанс — речь то идет об индусах, и автор изначальной статьи (не перевода) тоже индус. И для них тема очень актуальна. Подозреваю, что менталитет и промыть мозги престарелым родственникам не позволяет. Поэтому, это не хорошей жизни человек придумал, и решил свою острую проблему. Единственно, пмсм в таких переводах стоит сразу указывать контекст, чтобы была понятна ценность решения.
Ryav
23.08.2019 14:41+1Но так как работа с веб-версией WhatsApp требует периодического сканирования QR-кода с помощью мобильного телефона…
…мы бросаем этодерьморешение и используем более современный мессенджер.Coriolis
23.08.2019 15:00А у более современного разве нет проблемы с блокировкой на территории РФ?
Всю думаю чем email заменить для нотификации с серверов.Zibx
23.08.2019 15:36+1На территории РФ столько интернета заблокировано, что без VPN уже давно невозможно работать. От каких-то статей по геймдеву, 3д, разработке, матиматике до целых репозиториев и официальных документаций. Потому абсолютно все кого я знаю уже взяли себе где-нибудь vds и развернули на нём VPN и mtproto туннель для тг.
Своими действиями власти добились обратного результата — теперь у них нет возможности что-либо заблокировать без введения белых списков.
Ryav
23.08.2019 19:10Не могу вам ответить, зависит от того, какой нормальный мессенджер вы имеете ввиду, но у меня даже тележка, которую «блокируют», работает без проблем.
smarthomeblog
23.08.2019 19:50Можно пойти дальше. Прикрутить туда ML, чтобы поддержать разговор, если родители ответят. Пообсуждать с ними в чате политику, погоду. Потом можно вообще все свои контакты на этого супер бота перевести. Как пелось в советском детском фильме «Вкалывают роботы, а не человек» :)
algotrader2013
23.08.2019 21:49Учитывая специфику применения (см. мой коммент выше), ML, а то и AI можно прикрутить, но для нагугливания поздравительных открыток, проверки, что это именно открытка, а не троллинг, и персонализации (кому какую отправить, учитывая то, какие в ответ от этого человека приходят)
blackstrip
23.08.2019 22:47это прямо как авто-поздравлялка с получением ачивок в World of Warcraft, она ждет когда в чате гильдии кто-то получил ачивку и тут же отправляет туда ответ «грац, username». В итоге сидят в гильдии 10 человек, один получает ачивку — и, опа, 9 мгновенных поздравлений от согильдейцев!
sergey-b
24.08.2019 00:02+1Если хотите проявить заботу о родителях, покажите им, как отправлять таких "поздравляторов" в блок.
Neveil
24.08.2019 07:51Прочёл как техническую статью, было очень интересно как решили автоматическую отправку сообщений в отсутствии API. Возьму на заметку как один из каналов алертов для заббикса.
maximw
24.08.2019 16:59Мне тоже была интересна статья именно автоматизацией в отстутствии API (по крайней мере, для широких масс).
Я делал это «костыльно», через веб-версию в безголовом браузере (SlimerJS). К сожалению, получить доступ к веб-сокету у меня тогда не получилось, поэтому сделал тупо анализом DOM и кликами.
Tresor
24.08.2019 07:51+1This is exactly what I was looking for! I followed your guide but I got this error:
{
“UnethicalActionException”: “You should not use a bot to message your parents, you should talk to them yourself”
}
с Медиума :)
Senpos
24.08.2019 20:42Весь третий шаг можно опустить, если воспользоваться официальной библиотекой под названием Chalice.
Всё приложение можно уместить в 20 строк кода (у меня не Twilio, но суть та же):
from os import environ from chalice import Chalice, Cron from httpx import Client from httpx.exceptions import HTTPError app = Chalice(app_name="app") http = Client() @app.schedule(Cron(30, 1, "*", "*", "?", "*")) def send_greetings_periodic(event): try: http.post( environ["DISCORD_WEBHOOK"], json={"content": "Hello!"} ).raise_for_status() except HTTPError as ex: app.log(ex)
А сборкой приложения, настройкой AWS и отправкой туда всего нужного займется CLI, который идет в комплекте.
Зависимости складываем в
<app_root>/requirements.txt
.
Самое главное — добавить креды AWS в
~/.aws
, добавитьтокен Twilio(в моем случае) URL для Discord, куда будет отправляться приветствие, вenvironment_variables
из файла<app_root>/.chalice/config.json
:
{ ... "environment_variables": { "DISCORD_WEBHOOK": "definitely_secret" }, ... }
И сделать
chalice deploy
.
Если всё сделали правильно — вы восхитительны. :)
(venv) D:\Projects\Python\discord-auto-greeter>chalice deploy Creating deployment package. Updating policy for IAM role: discord-auto-greeter-dev Updating lambda function: discord-auto-greeter-dev-send_greetings_periodic Resources deployed: - Lambda ARN: arn:aws:lambda:probably_not_secret:discord-auto-greeter-dev-send_greetings_periodic
Невероятно много времени экономит.
Senpos
24.08.2019 20:57Из приятностей еще можно отметить, что если вам понадобится удалить приложение — не придется ходить по каждому сервису и чистить все руками.
chalice delete
и все что оно породило — само и удалит.
PaulAtreides
26.08.2019 15:50+1Особенно криповой эта история станет, когда автор случайно попадёт под автобус (в Индии такое часто случается), а пожелания родителям продолжат приходить, пока не кончится оплата Амазона.
Cheater
Wat? Вы уверены, что автоматизированные пожелания доброго утра от бездушного скрипта являются решением проблемы недостатка общения с родителями?
yarkov
Вопрос немного не по адресу, ибо это перевод.
eumorozov
Пришел написать то же самое. Какая-то статья абсурд. Еще автору не хватало написать такой же скрипт родителям, чтобы они не напрягались по утрам, отправляя ему сообщения. Написать по боту на каждой стороне — пускай друг-друга поздравляют с добрым утром! Какая трогательная и нежная забота!
Nurked
Да это понятное дело статья о том, как посылать сообщения через ватсап автоматически. Оно как козе баян для многих хабрачеловеков, но есть те кто держит колл-центры и всякие телемаркетинги — такие люди возьмут на заметку.
Aracon
Поначалу подумал, что речь идёт об отправке сообщений в чаты родителей (чат класса или группы детсада). В таком контексте смотрелось бы более-менее органично.