Урок 10. Запросы и интеграция

Основная информация о запросах

Запросы можно делать к любому стороннему серверу, который их поддерживает. Если вы не можете найти документацию к API в публичном доступе, свяжитесь с поддержкой или разработчиками системы.

Ботмама умеет отправлять запросы и принимать ответы только в формате JSON. Если нужная вам система не поддерживает json, нужно искать сервис, который изменяет формат запроса, или писать скрипт обработки на сервере.

Существует множество типов запросов, мы используем только самые распространённые: GET, POST, PUT, DELETE.

GET чаще всего используется как запрос получения информации. В отдельных случаях он может использоваться равнозначно с другими типами. Например, в Telegram можно использовать и GET, и POST для одинаковых запросов.

POST используется для отправки информации и создания объектов. Этим методом чаще всего создаются заявки, формируются заказы и т.д.

PUT обновляет информацию об объекте.

DELETE удаляет созданный объект.

Тело в GET запросе можно передавать в строке URL, для остальных запросов — только в специальном поле компонента.

Основная информация об ответах

Ответом на запрос может быть информация об ошибке или об удачном запросе с дополнительными данными или без них.

Коды ответов
Об ответах на запросы можно подробно узнать в Википедии.

Чаще всего приходят ответы успеха и ошибок.

Если запрос прошёл успешно, код будет иметь значение, начинающееся на 2:

  • 200 OK — успешный запрос.
  • 201 Created — в результате успешного выполнения запроса был создан новый ресурс.
  • 202 Accepted — запрос был принят на обработку, но она не завершена.

Если запрос не прошёл из-за ошибки параметров запроса, Ботмама считает его успешным, но в объекте {{last_request}} будет лежать ошибка, начинающаяся на 4:

  • 400 Bad Request — сервер обнаружил в запросе клиента синтаксическую ошибку. Этот код используется для любых ошибок такого типа, если разработчик сервиса не вложил другие значения.
  • 401 Unauthorized — для доступа к запрашиваемому ресурсу требуется авторизация.
  • 403 Forbidden — сервер понял запрос, но он отказывается его выполнять из-за ограничений в доступе для клиента к указанному ресурсу.
  • 404 Not Found — запрашиваемый ресурс не был найдет или не существует.

Если запрос не прошёл из-за ошибки сервера, Ботмама исполняет Экран при ошибке запроса. Ошибки сервера начинаются на 5:

  • 500 Internal Server Error — любая внутренняя ошибка сервера. Этот код используется, если разработчик не добавил код для описания данной ошибки.
  • 501 Not Implemented — сервер не может обработать запрос. Например, вы используете несуществующий метод.
  • 502 Bad Gateway — когда сервер, к которому вы делаете запрос, фактически является буфером между вами и другим сервером, получает некорректный ответ от другого сервера.
  • 503 Service Unavailable — сервер временно не может обрабатывать запросы. Такие ошибки возникают, когда сервер выключен, не имеет доступа к Сети или ограничен в доступе.
  • 504 Gateway Timeout — когда сервер, к которому вы делаете запрос, фактически является буфером между вами и другим сервером, не получает ответ от другого сервера.

Запросы к Telegram bot API GET и POST

Для понимания материала открывайте предложенные ссылки в соседних вкладках.

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

Все запросы в телеграм создаются по шаблону:

https://api.telegram.org/bot<token>/НАЗВАНИЕ_МЕТОДА

Метод запроса — действие, которое должна совершить система в заданном боте. Рассмотрим методы запросов в Telegram. Для этого откройте документацию по ссылке.

С одним из методов мы уже сталкивались в оповещении. Там мы используем sendMessage, отправку сообщения. Обязательными параметрами являются chat_id и text.

chat_id уникальный идентификатор пользователя в боте. Его мы получаем как основную переменную {{this_user.platform_id}}. Чтобы отправить сообщение определённому пользователю, нужно вставить значение его переменной.
text текст сообщения, которое мы отправляем.

Для передачи пробелов в запросе нужно заменять их знаком + . Если отправить текст без замены, он оборвётся на первом пробеле.
Сформируем запрос GET

Параметры от метода отделяем знаком вопроса. Значение параметра отправляем после знака равенства. Между собой параметры отделяются знаком &. В итоге получаем конструкцию:

https://api.telegram.org/bot<token>/НАЗВАНИЕ_МЕТОДА?параметр1=значение1&параметр2=значение2

Для метода sendMessage запрос выглядит так:

https://api.telegram.org/bot<token>/sendMessage?chat_id=значение1&text=значение2

Запрос с тестовыми параметрами выглядит следующим образом:

https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/sendMessage?chat_id=123456&text=Привет+из+бота!
Сформируем тот же запрос POST

Параметры запроса и их значения составляют тело запроса. Поэтому в строке URL мы оставляем только

https://api.telegram.org/bot<token>/НАЗВАНИЕ_МЕТОДА

Далее формируем тело запроса. В json оно будет выглядеть таким образом:

{
"параметр1": "значение1",
"параметр2": "значение2"
}

Подставляем параметры.

URL запроса с тестовыми параметрами:

https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/sendMessage

Тело запроса с тестовыми параметрами:

{
"chat_id": "123456",
"text": "Привет из бота!"
}
Важно следить за синтаксисом. Если вы забудете поставить хотя бы один символ, запрос не сработает. Это самая распространённая ошибка при отправке запросов.

Для тестирования можете попробовать удалить предыдущее сообщение методом deleteMessage.
Обязательные параметры:

chat_id уникальный идентификатор пользователя в боте. Его мы получаем как основную переменную {{this_user.platform_id}}.
message_id уникальный идентификатор сообщения, находится в переменной {{last_telegram_message_id}}


Получение информации методом GET

Для примера мы будем использовать ресурс https://www.cbr-xml-daily.ru/

В нём мы выбираем запрос в формате JSON:

https://www.cbr-xml-daily.ru/daily_json.js

Открываем его как обычную ссылку в браузере и получаем ответ в json формате.

Чтобы ответ был удобным для чтения, поставьте расширение на браузер. Для Google Chrome это JSON Formatter.

Например, мы хотим получить стоимость 1 доллара США. Находим часть, где выводится значение USD:

"USD": {
    "ID": "R01235",
    "NumCode": "840",
    "CharCode": "USD",
    "Nominal": 1,
    "Name": "Р"оллар РЎРЁРђ",
    "Value": 56.5918,
    "Previous": 57.5899
}

Составляем переменную.

Ответ на запрос находится в объекте {{last_request}}. Но мы хотим вывести только часть объекта, поэтому смотрим, частью какой переменной является курс валют:

"Date": "2018-02-16T11:30:00+03:00",
"PreviousDate": "2018-02-15T11:30:00+03:00",
"PreviousURL": "//www.cbr-xml-daily.ru/archive/2018/02/15/daily_json.js",
"Timestamp": "2018-02-15T15:00:00+03:00",
"Valute": {

Разделяем точкой название объекта и переменной в нём: {{last_request.Valute}}
Теперь нам нужно уточнить, какую именно валюту мы выводим на экран. Разделяем точкой переменную и вложенную в неё переменную доллара: {{last_request.Valute.USD}}.
Чтобы уточнить, что нас интересует именно текущий курс, добавляем через точку уточнение значения: {{last_request.Valute.USD.Value}}.

Полученную переменную вставляем в компонент Текст после компонента Запрос, при исполнении экрана нам придёт актуальный курс валют.

Массив

В примере с курсом валют мы получали простую переменную. Иногда мы получаем переменную с массивом внутри. Массив находится внутри квадратных скобок, например:

"forecastday": [
        {
          "date": "2018-02-15",
          "date_epoch": 1518652800,
          "day": {
            "maxtemp_c": 11.5,
            "maxtemp_f": 52.7,
            "mintemp_c": 5.1,
            "mintemp_f": 41.2,
            "avgtemp_c": 8.1,
            "avgtemp_f": 46.6,
            "maxwind_mph": 12.1,
            "maxwind_kph": 19.4,
            "totalprecip_mm": 10.5,
            "totalprecip_in": 0.41,
            "avgvis_km": 11,
            "avgvis_miles": 6,
            "avghumidity": 85,
            "condition": {
              "text": "Light drizzle",
              "icon": "//cdn.apixu.com/weather/64x64/day/266.png",
              "code": 1153
            },
            "uv": 1
          },
          "astro": {
            "sunrise": "07:59 AM",
            "sunset": "06:11 PM",
            "moonrise": "07:53 AM",
            "moonset": "05:51 PM"
          }
        }
      ]

Для примера будем использовать сервис https://www.apixu.com. Чтобы использовать их API, нужно зарегистрироваться. После регистрации вам выдаются токен и примеры запроса.

Пример выглядит так:

http://api.apixu.com/v1/forecast.json?key=<token>&q=Paris

Изменим название города, к примеру, на Воронеж. Название пишем латиницей. В состоянии пользователя смотрим на объект {{last_request}}:

"last_request": {
    "location": {
      "name": "Voronezh",
      "region": "Voronezh",
      "country": "Russia",
      "lat": 51.67,
      "lon": 39.17,
      "tz_id": "Europe/Moscow",
      "localtime_epoch": 1518704930,
      "localtime": "2018-02-15 17:28"
    },
    "current": {
      "last_updated_epoch": 1518704129,
      "last_updated": "2018-02-15 17:15",
      "temp_c": -6,
      "temp_f": 21.2,
      "is_day": 1,
      "condition": {
        "text": "Light snow",
        "icon": "//cdn.apixu.com/weather/64x64/day/326.png",
        "code": 1213
      },
      "wind_mph": 9.4,
      "wind_kph": 15.1,
      "wind_degree": 110,
      "wind_dir": "ESE",
      "pressure_mb": 1033,
      "pressure_in": 31,
      "precip_mm": 0.1,
      "precip_in": 0,
      "humidity": 93,
      "cloud": 100,
      "feelslike_c": -11.8,
      "feelslike_f": 10.7,
      "vis_km": 4.3,
      "vis_miles": 2
    },
    "forecast": {
      "forecastday": [
        {
          "date": "2018-02-15",
          "date_epoch": 1518652800,
          "day": {
            "maxtemp_c": -4.6,
            "maxtemp_f": 23.7,
            "mintemp_c": -10.5,
            "mintemp_f": 13.1,
            "avgtemp_c": -6.9,
            "avgtemp_f": 19.7,
            "maxwind_mph": 7.8,
            "maxwind_kph": 12.6,
            "totalprecip_mm": 0.6,
            "totalprecip_in": 0.02,
            "avgvis_km": 12.7,
            "avgvis_miles": 7,
            "avghumidity": 95,
            "condition": {
              "text": "Light snow",
              "icon": "//cdn.apixu.com/weather/64x64/day/326.png",
              "code": 1213
            },
            "uv": 1.2
          },
          "astro": {
            "sunrise": "07:38 AM",
            "sunset": "05:38 PM",
            "moonrise": "07:31 AM",
            "moonset": "05:09 PM"
          }
        }
      ]
    }

И составляем текст прогноза погоды, исходя из полученных данных. Объект {{last_request}}, переменная с прогнозом — {{forecast}}. Внутри переменной с прогнозом есть переменная {{forecastday}}, в которой находится массив. Пока что мы получили {{last_request.forecast.forecastday}}.

В одной переменной может быть несколько массивов. Нумерация массивов начинается с нуля, сверху вниз. Чтобы обозначить массив, из которого мы берём переменную, ставим его номер в квадратных скобках, а после него обозначаем название переменной.

Например, мы хотим вывести максимальную температуру по Цельсию maxtemp_c. Она находится в переменной day массива, применяем те же правила, что и для переменных вне массива: {{last_request.forecast.forecastday.[0].day.maxtemp_c}}.

Итак, прогноз погоды для Воронежа будет выглядеть:

Прогноз на {{last_request.forecast.forecastday.[0].date}}:
Максимальная температура воздуха {{last_request.forecast.forecastday.[0].day.maxtemp_c}} С°. Минимальная температура воздуха {{last_request.forecast.forecastday.[0].day.
mintemp_c}} С°.
Средняя температура воздуха {{last_request.forecast.forecastday.[0].day.
avgtemp_c}} С°.

Прогноз в сообщении:



Для перехода к следующему уроку нажмите на категорию (слева).