Помните ли вы о своих новогодних обещаниях? С помощью C#, Azure Functions и Twilio мы создадим сервис, который будет отправлять ежедневные SMS-напоминания, чтобы помочь вам не забывать о новых целях.
Вот список того, что нам понадобится для создания сервиса напоминаний:
— Бесплатный аккаунт Twilio – зарегистрируйтесь здесь
— Номер телефона с поддержкой SMS – вы можете подобрать подходящий здесь
— Аккаунт Microsoft Azure
— Visual Studio 2015 (хотя работать с Azure Functions можно и напрямую в веб-портале, в VS2015 опыт разработки лучше)
— Microsoft Azure SDK для VS 2015
— Visual Studio Tools для Azure Functions
— Microsoft Azure Storage Explorer
Настройте свои аккаунты и установите необходимое программное обеспечение, прежде чем продолжить.
Azure Functions позволяют легко и быстро создать сервис, который мы разрабатываем. Это «бессерверная» технология, то есть нам не нужно беспокоиться об архитектуре веб-сервера. Вместо этого мы можем сосредоточиться на небольших фрагментах кода или «функциях», которые обеспечивают работу нашего сервиса.
Мы создадим одну функцию, которая будет обрабатывать входящие SMS-сообщения от Twilio. Когда она получит запрос от Twilio, она создаст запись в таблице Azure, если текст сообщения содержит слово «subscribe». Вторая функция будет запускаться раз в день, чтобы отправлять SMS-напоминания каждому номеру из таблицы Azure.
Достаточно просто? Давайте начнем.
Создайте новый проект в Visual Studio 2015 и найдите среди установленных шаблонов «Azure Functions»:
Назовите проект
`DailySmsReminders`
и нажмите `OK`.
Прежде чем добавлять функции, настроим параметры приложения. Откройте `appsettings.json`
и замените его содержимое следующим:
Настройка `UseDevelopmentStorage=true`
на строке 4 позволяет использовать Azure Storage Emulator при каждом обращении к хранилищу Azure. Не забудьте заменить учетные данные Twilio на свои.
Далее щелкните правой кнопкой мыши на проекте `DailySmsReminders`
и выберите `Добавить->Новая функция Azure…`:
Появившееся диалоговое окно содержит множество опций. Они представляют различные способы запуска функции Azure. Например, функция может запускаться, когда что-то добавляется в очередь, с помощью `QueueTrigger`. Узнайте больше о доступных типах триггеров здесь. Нашей первой функции нужно запускаться при поступлении HTTP-запроса. Опция `HTTPTrigger — C#`
идеально подходит для этого. Выберите эту опцию, назовите функцию `InboundSmsTrigger`
и нажмите `Создать`.
Отредактируйте `InboundSmsTrigger.project.json`
чтобы добавить зависимость от `Twilio.Twiml`, которую мы будем использовать для возврата TwiML Twilio при получении SMS:
Файл `InboundSmsTrigger.function.json`
используется для настройки привязок нашей функции. Две существующие привязки в файле соответствуют входящему HTTP-запросу и возвращаемому значению функции. Нам нужно добавить привязку для таблицы Azure, которую мы будем использовать для хранения записей. Отредактируйте `function.json`
так, чтобы он выглядел следующим образом:
В выделенных строках мы добавили привязку таблицы с `tableName`
`Reminder`
и установили соединение для таблицы с Azure Storage Emulator.
Код функции находится в `InboundSmsTrigger.run.csx`. Удалите его содержимое и замените следующим кодом:
В строках 1-2 мы подключаем ссылки на `Microsoft.WindowsAzure.Storage`
и `System.Runtime`. Это особые внешние сборки, которые можно подключать таким образом. Полный список доступен в документации.
Строка 10 добавляет параметр `CloudTable table`
в функцию, который соответствует привязке таблицы, добавленной в `function.json`. Это дает нам доступ к таблице `Reminder`
в хранилище Azure.
Класс `Reminder`
в конце является подклассом `TableEntity`, который мы будем использовать для хранения записей в таблице Azure. Класс содержит `PartitionKey`, который мы всегда будем устанавливать как `Reminders`, и `RowKey`, который мы будем использовать для хранения номера телефона пользователя для отправки напоминаний позже.
HTTP-запрос от Twilio будет содержать данные формы в теле запроса, включая такие параметры, как `Body`
и номера телефонов `To`/`From`. Добавим код для их разбора в `Dictionary`
и сохранения текста сообщения и номера телефона, с которого было отправлено сообщение:
Мы также создали объект `TwilioResponse`, который будет использоваться для возврата TwiML Twilio.
Если пользователь отправит сообщение, не содержащее слово `subscribe`,
мы отправим ответное сообщение с информацией о ключевом слове. Настроим это, добавив следующий код:
Когда мы разбирали значение `Body`
с помощью `System.Uri.UnescapeDataString`, пробелы в строке остаются как знаки `+`. Выделенная строка удаляет все знаки `+`
в начале и конце значения `body`, приводит его к нижнему регистру и сравнивает с `subscribe`.
Основная работа функции выполняется, когда текст сообщения содержит `subscribe`. Добавьте этот код в соответствующий блок:
Строки 1 и 2 ищут в таблице `Reminder`
запись, соответствующую `PartitionKey` `Reminders`
и `RowKey` `phoneNumber`. Если результат существует, то в строке 6 устанавливается ответное сообщение, чтобы уведомить пользователя о том, что он уже подписан. Если пользователь еще не подписан, то в строке 10 сообщается, что он подписан, и остальная часть кода в этом блоке выполняет операцию вставки для добавления его номера телефона в таблицу.
Осталось только вернуть `HttpResponse`
из функции. Мы вернем TwiML `response`
как `application/xml`
с кодировкой `UTF8` с помощью следующего кода:
Теперь пришло время протестировать эту функцию. Сначала нужно запустить Azure Storage Emulator. Найдите его в меню «Пуск» и запустите. Откроется окно командной строки, в котором будет выполнена команда для его запуска:
После запуска можно собрать и запустить решение Azure Functions. При первом запуске будет предложено установить инструменты Azure CLI. Установите их и снова запустите проект:
Чуть ниже крутого ASCII-арта Azure Functions вы увидите URL `localhost`
с номером порта. Вам понадобится что-то вроде ngrok, чтобы перенаправить этот локальный порт в Интернет, чтобы Twilio мог отправить HTTP-запрос. Если вы не знаете, как это настроить, воспользуйтесь этим руководством. Быстрый и простой способ запустить ngrok из Visual Studio – это очень удобное расширение ngrok.
Перейдите к своему номеру телефона Twilio и настройте вебхук `A Message comes in`
так, чтобы он указывал на `https://[ваш ngrok url]/api/InboundSmsTrigger`
и нажмите `Save`.
Протестируйте входящий триггер, отправив SMS-сообщения. Попробуйте отправить что-то, не содержащее `subscribe`, затем отправьте `subscribe`
и попробуйте подписаться снова. Теперь, когда у нас есть подписки, давайте отправим напоминания.
Добавьте еще одну функцию Azure в проект. На этот раз выберите `TimerTrigger — C#`
и назовите функцию `SendSmsReminders`. Триггер по таймеру будет запускаться по расписанию, заданному выражением `cron`
в файле `function.json`. Выражение cron имеет шесть полей: `{секунда} {минута} {час} {день} {месяц} {день недели}`. Например, выражение cron, которое будет запускать функцию в 10:00:00 по восточному времени США каждый день, выглядит так: `0 0 15 * * *`.
Измените `SendSmsReminders.function.json`
так, чтобы он содержал это выражение cron, а также добавьте привязку таблицы, как мы делали в предыдущей функции:
Далее добавьте зависимость от `Twilio`
в `SendSmsReminders.project.json`:
Теперь мы готовы отправлять напоминания. Откройте `SendSmsReminders.run.csx`
и замените его содержимое следующим кодом, который подключает сборки Twilio и Azure Storage и добавляет привязку CloudTable в список параметров:
Внутри функции `Run`
начнем с настройки `TwilioRestClient`:
Затем создадим запрос к таблице `Reminder`,
который соответствует `PartitionKey` `Reminders`. Это вернет всех пользователей, которые подписались:
Теперь, когда у нас есть все записи, пройдемся по каждой из них и отправим SMS-напоминание с помощью `TwilioRestClient`:
Чтобы протестировать это, измените выражение cron в `function.json`
на время через несколько минут в будущем и запустите проект. Вы должны получить SMS с `ReminderMessage`
в установленное время. Теперь вы не забудете о своих обещаниях!
Теперь, когда вы знаете, как использовать C#, Azure Functions и Twilio для отправки ежедневных SMS-напоминаний, попробуйте сделать следующее:
— Попробуйте развернуть проект в Azure. Процесс описан в этом пошаговом руководстве.
— Измените сервис так, чтобы пользователь мог задавать собственное напоминание.
— Узнайте, как настроить напоминания о встречах, в этом уроке.
Мне очень интересно увидеть, что вы создадите с помощью этих технологий. Дайте знать, что у вас получилось, написав мне в Twitter @brentschooley.