Автор материала, перевод которого мы сегодня публикуем, говорит, что современные люди, жизнь которых переполнена работой, часто забывают писать сообщения своим родным и близким. Он, глядя на то, как его родители каждое утро шлют ему в WhatsApp вдохновляющие цитаты и полезные советы о здоровье, решил, что пришло время ответить им взаимностью.

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



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

Работа над проектом будет состоять из трёх шагов:

  1. Настройка Twilio.
  2. Изучение и модификация кода.
  3. Развёртывание проекта в облаке и настройка триггера.

Шаг 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)


  1. Cheater
    23.08.2019 12:40
    +4

    Wat? Вы уверены, что автоматизированные пожелания доброго утра от бездушного скрипта являются решением проблемы недостатка общения с родителями?


    1. yarkov
      23.08.2019 12:46

      Вопрос немного не по адресу, ибо это перевод.


    1. eumorozov
      23.08.2019 14:29
      +2

      Пришел написать то же самое. Какая-то статья абсурд. Еще автору не хватало написать такой же скрипт родителям, чтобы они не напрягались по утрам, отправляя ему сообщения. Написать по боту на каждой стороне — пускай друг-друга поздравляют с добрым утром! Какая трогательная и нежная забота!


    1. Nurked
      23.08.2019 19:06

      Да это понятное дело статья о том, как посылать сообщения через ватсап автоматически. Оно как козе баян для многих хабрачеловеков, но есть те кто держит колл-центры и всякие телемаркетинги — такие люди возьмут на заметку.


    1. Aracon
      23.08.2019 23:29

      Поначалу подумал, что речь идёт об отправке сообщений в чаты родителей (чат класса или группы детсада). В таком контексте смотрелось бы более-менее органично.


  1. yarkov
    23.08.2019 12:45

    Он, глядя на то, как его родители каждое утро шлют ему в WhatsApp вдохновляющие цитаты и полезные советы о здоровье, решил, что пришло время ответить им взаимностью.

    Какой хороший человек. Я таких сразу в ЧС кидаю.


  1. KirillGerasimov
    23.08.2019 13:23

    Статья должна была называться «Как настроить спам-рассылку для своих родителей».

    Предпосылки, может, неплохи, но обманывать родителей, заставляя их думать, что им пишет их ребенок — немного низко.


  1. vilgeforce
    23.08.2019 13:28
    +1

    Лучше ничего не писать, но самому, чем что-то писать через скрипт


  1. char16t
    23.08.2019 13:51

    Очень тупая идея


    1. Minifets
      24.08.2019 07:50

      Почему тупая?
      Таким образом можно написать whatsapp бота. А это уже полезнее.


  1. maximw
    23.08.2019 14:32
    -1

    Безотносительно технической ценности статьи, удивлен первым нескольким комментаторам. Такое впечатление, что у людей полностью отсутствует абстрактное мышление. Да, задача выбрана не очень удачно, но статья же не про это. Придираться к этической стороне такого общения с родителями — это как придираться к землекопам в арифметической задачке.


  1. algotrader2013
    23.08.2019 14:35
    +3

    Читаю комментарии, и умиляюсь) Как говорится, сытый голодного не понимает. Понятно, что надо быть конченым моральным уродом, чтобы использовать подобное в наших краях, или в странах западной цивилизации.

    Но есть один нюанс — речь то идет об индусах, и автор изначальной статьи (не перевода) тоже индус. И для них тема очень актуальна. Подозреваю, что менталитет и промыть мозги престарелым родственникам не позволяет. Поэтому, это не хорошей жизни человек придумал, и решил свою острую проблему. Единственно, пмсм в таких переводах стоит сразу указывать контекст, чтобы была понятна ценность решения.


  1. Ryav
    23.08.2019 14:41
    +1

    Но так как работа с веб-версией WhatsApp требует периодического сканирования QR-кода с помощью мобильного телефона…
    …мы бросаем это дерьморешение и используем более современный мессенджер.


    1. Coriolis
      23.08.2019 15:00

      А у более современного разве нет проблемы с блокировкой на территории РФ?
      Всю думаю чем email заменить для нотификации с серверов.


      1. alexesDev
        23.08.2019 15:35

        slack поддерживают почти все уведомлялки


      1. Zibx
        23.08.2019 15:36
        +1

        На территории РФ столько интернета заблокировано, что без VPN уже давно невозможно работать. От каких-то статей по геймдеву, 3д, разработке, матиматике до целых репозиториев и официальных документаций. Потому абсолютно все кого я знаю уже взяли себе где-нибудь vds и развернули на нём VPN и mtproto туннель для тг.
        Своими действиями власти добились обратного результата — теперь у них нет возможности что-либо заблокировать без введения белых списков.


      1. Revertis
        23.08.2019 15:47

        Прокси для Телеги есть уже даже в сети Medium. И его не заблокируют.


      1. Ryav
        23.08.2019 19:10

        Не могу вам ответить, зависит от того, какой нормальный мессенджер вы имеете ввиду, но у меня даже тележка, которую «блокируют», работает без проблем.


  1. smarthomeblog
    23.08.2019 19:50

    Можно пойти дальше. Прикрутить туда ML, чтобы поддержать разговор, если родители ответят. Пообсуждать с ними в чате политику, погоду. Потом можно вообще все свои контакты на этого супер бота перевести. Как пелось в советском детском фильме «Вкалывают роботы, а не человек» :)


    1. algotrader2013
      23.08.2019 21:49

      Учитывая специфику применения (см. мой коммент выше), ML, а то и AI можно прикрутить, но для нагугливания поздравительных открыток, проверки, что это именно открытка, а не троллинг, и персонализации (кому какую отправить, учитывая то, какие в ответ от этого человека приходят)


  1. blackstrip
    23.08.2019 22:47

    это прямо как авто-поздравлялка с получением ачивок в World of Warcraft, она ждет когда в чате гильдии кто-то получил ачивку и тут же отправляет туда ответ «грац, username». В итоге сидят в гильдии 10 человек, один получает ачивку — и, опа, 9 мгновенных поздравлений от согильдейцев!


  1. sergey-b
    24.08.2019 00:02
    +1

    Если хотите проявить заботу о родителях, покажите им, как отправлять таких "поздравляторов" в блок.


  1. Neveil
    24.08.2019 07:51

    Прочёл как техническую статью, было очень интересно как решили автоматическую отправку сообщений в отсутствии API. Возьму на заметку как один из каналов алертов для заббикса.


    1. maximw
      24.08.2019 16:59

      Мне тоже была интересна статья именно автоматизацией в отстутствии API (по крайней мере, для широких масс).
      Я делал это «костыльно», через веб-версию в безголовом браузере (SlimerJS). К сожалению, получить доступ к веб-сокету у меня тогда не получилось, поэтому сделал тупо анализом DOM и кликами.


      1. Minifets
        26.08.2019 08:48

        И быстро такое решение работает, с DOM и кликами?


  1. Tresor
    24.08.2019 07:51
    +1

    This 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”


    }


    с Медиума :)


  1. 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

    Невероятно много времени экономит.


    1. Senpos
      24.08.2019 20:57

      Из приятностей еще можно отметить, что если вам понадобится удалить приложение — не придется ходить по каждому сервису и чистить все руками.


      chalice delete и все что оно породило — само и удалит.


  1. PaulAtreides
    26.08.2019 15:50
    +1

    Особенно криповой эта история станет, когда автор случайно попадёт под автобус (в Индии такое часто случается), а пожелания родителям продолжат приходить, пока не кончится оплата Амазона.