Telegram bot webhook или long polling

Конечной целью любой интеграции API является эффективный обмен данными между приложениями, чтобы обеспечить большую ценность для ваших пользователей. Чтобы облегчить это, интеграция должна предоставить метод для обнаружения изменений, событий , которые происходят в приложении конечной точки. В настоящее время два самых популярных инструмента управления событиями — это опрос и веб-зацепки.

голосование

Концепция опроса очень проста: отправьте запрос на новые события (в частности, события Create, Retrieve и Delete, которые сигнализируют об изменении данных) с заранее определенной частотой и дождитесь ответа конечной точки. Если конечная точка не отвечает, новых событий нет.

Webhooks

Подобно опросу, веб-зацепки предоставляют вашему приложению способ получения новых данных о событиях из конечной точки. Однако вместо отправки повторных запросов о новых событиях вы предоставляете конечной точке URL-адрес, обычно внутри пользовательского интерфейса конечной точки, который отслеживает ваше приложение. Всякий раз, когда в приложении конечной точки происходит новое событие, оно публикует данные события по указанному вами URL-адресу, обновляя ваше приложение в режиме реального времени.

Polling Vs Webhooks

Будьте хороши… к вашим серверам

Хотя оба опроса и веб-хуки выполняют одну и ту же задачу, веб-хуки гораздо эффективнее. Zapier обнаружил, что более 98,5% опросов потрачены впустую. В отличие от этого , webhooks только передавать данные , когда есть новые данные для отправки, что делает их эффективными на 100%. Это означает, что опрос создает в среднем в 66 раз большую нагрузку на сервер, чем веб-хуки. Это много потерянного времени, а если вы платите за вызов API, то много потраченных денег.

Данные всегда старые (если вы не используете веб-хуки)

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

С помощью webhooks эта проблема устраняется. Поскольку события сразу же публикуются на отслеживаемом URL-адресе, ваши приложения будут автоматически обновляться новыми данными практически мгновенно.

Разработчики знают лучше

Когда было опрошено более 160 разработчиков, 82% ответили, что они предпочитают веб-крючки опросам. Почему? Помимо всех преимуществ, которые мы уже обсуждали, веб-хуки гораздо проще реализовать и поддерживать. Для большинства конечных точек существует инструмент пользовательского интерфейса для настройки веб-хуков, поэтому кодирование требуется только для определения того, какие данные события следует передавать.

В качестве примера давайте сравним код, необходимый для создания webhook, с кодом, необходимым для инфраструктуры опроса в Marketo:

Webhook и Long Polling! Чем отличаются? Что лучше использовать?


JS Result EDIT ON package com.marketo; // minimal-json library (https://github.com/ralfstx/minimal-json) import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import com.eclipsesource.json.JsonValue; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import javax.net.ssl.HttpsURLConnection; public class LeadActivities // Number of lead records to read at a time private static final String READ_BATCH_SIZE = «200»; // Lookup lead records using lead id as primary key private static final String LEAD_FILTER_TYPE = «id»; // Lead record lookup returns these fields private static final String LEAD_FIELDS = «firstName,lastName,email»; // Lookup activity records for these activity types private static Map ACTIVITY_TYPES; static public static void main(String[] args) // Establish «since date» using current timestamp minus some number of days (default is 1 day) Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_MONTH, -lookBackNumDays); SimpleDateFormat sdf = new SimpleDateFormat(«yyyy-MM-dd’T’HH:mm:ssZ»); String sinceDateTime = sdf.format(cal.getTime()); // Compose base URL String baseUrl = String.format(«https://%s.mktorest.com», CUSTOM_SERVICE_DATA.get(«accountId»)); // Compose Identity URL String identityUrl = String.format(«%s/identity/oauth/token?grant_type=%sclient_secret=%s», baseUrl, «client_credentials», CUSTOM_SERVICE_DATA.get(«clientId»), CUSTOM_SERVICE_DATA.get(«clientSecret»)); // Call Identity API JsonObject identityObj = JsonObject.readFrom(getData(identityUrl)); String accessToken = identityObj.get(«access_token»).asString(); // Compose URLs for Get Lead Changes, and Get Paging Token String activityTypesUrl = String.format(«%s/rest/v1/activities/types.json?access_token=%s», baseUrl, accessToken); String pagingTokenUrl = String.format(«%s/rest/v1/activities/pagingtoken.json?access_token=%s, baseUrl, accessToken, sinceDateTime); // Use activity ids to create filter parameter String activityTypeIds = «»; for (Integer id : ACTIVITY_TYPES.keySet()) leadLst.add(leadObj); // Store unique lead ids for use as lead filter value below leadsSet.add(leadId); > > > > while (moreResult); > // Use unique lead id values to create filter parameter String filterValues = «»; for (Object object : leadsSet) 0) filterValues += String.format(«%s», object); > // Compose Get Multiple Leads by Filter Type URL // Only retrieve leads that match the list of lead ids that was accumulated during activity query String getMultipleLeadsUrl = String.format(«%s/rest/v1/leads.json?access_token=%sfields=%sbatchSize=%s», baseUrl, accessToken, LEAD_FILTER_TYPE, LEAD_FIELDS, filterValues, READ_BATCH_SIZE); String nextPageToken = «»; do 0) // Call Get Multiple Leads by Filter Type API to retrieve lead data JsonObject multipleLeadsObj = JsonObject.readFrom(getData(gmlUrl)); if (multipleLeadsObj.get(«success»).asBoolean()) > > > nextPageToken = «»; if (multipleLeadsObj.asObject().get(«nextPageToken») != null) > while (nextPageToken.length() > 0); // Now place activity data into an array of JSON objects JsonArray activitiesAry = new JsonArray(); for (Map.Entry activity : activitiesMap.entrySet()) > // Print out result objects JsonObject result = new JsonObject(); result.add(«result», activitiesAry); System.out.println(result); System.exit(0); > // Perform HTTP GET request private static String getData(String endpoint) else > catch (MalformedURLException e) catch (IOException e) return data; > private static String convertStreamToString(InputStream inputStream) catch (NoSuchElementException e) > >

Еще по теме:  Как сделать магик в Телеграмме

Это много кода! В рамках нашей структуры опросов мы делаем запросы GET к конечной точке в определенный интервал времени. Мы определяем, как далеко назад вовремя искать изменения, перебираем все наши данные о потенциальных клиентах и ​​выделяем потенциальных клиентов, связанных с действиями, которые произошли в течение нашего времени. Чем чаще мы проводим опрос, тем короче период времени, через который мы должны пройти.

Theoretically, the framework should work the same way for every poll, but it’s likely that it will need to be changed with future versioning of the endpoint.

Now let’s see what we need for a webhook:

JS Result EDIT ON URL: «https://hooks.slack.com/services/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» payload=> >, >» >

That’s it! Just provide a URL, specify a payload, and the rest is taken care of with a few clicks in the Marketo UI. In this example, Marketo posts an event to the URL anytime a lead visits a certain domain. The user’s instance of Slack monitors the domain and posts the lead’s name, company, and email address in one of its channels.

Because the process is handled by the endpoint API, it is less likely that the webhook will break in future versions, unless the existing object names are altered, which is unlikely.

As the proliferation of the API economy continues, expect to see many more APIs begin to support webhooks. To stay ahead of the curve, check out the State of API Integration Report which goes into greater depth on the advantages of webhooks as well as which APIs support them.

Источник: coderlessons.com

Что использовать Long Polling или Webhooks?

Пишу телеграм бота на Aiogram. Который должен будет выполнять операции с деньгами
Поискав информации, понял что на вебхуках будет работать надежней.
Но, информации по работе с вебхуками нашел небольшое количество и то, 5-ти летней давности.
Теперь состоит вопрос, если делать запрос серверу через long polling будет ли слетать скрипт?
При установке skip_updates = False, и циклом while со sleep(0.5)?
Или стоит сразу делать на вебхуках? Буду рад хорошему материалу на вебхуки телеграма с 0

  • Вопрос задан более года назад
  • 2828 просмотров
Еще по теме:  Глаз бога Телеграмм как удалить аккаунт

Комментировать
Решения вопроса 0
Ответы на вопрос 2

Dr_Elvis

В гугле забанен

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

Ответ написан более года назад
Нравится 3 2 комментария

Окей, а где можно найти материал для создания бота на вебхуках? Т.к все материалы 5-ти летней давности и для меня сложно подключить сервер с адресом куда телеграм будет слать запросы

Dr_Elvis

Sanzhar Bazarbek, к примеру официальная документация которая была взята с github проекта. там же можно найти русское комьюнити, думаю там много будет ответов на ваши вопросы. И если статья 5-ти летней давности — это не значит что она устарела. Да, возможно уже реализованы методы более современные или улучшенные, но основной принцип остается тот же.

Источник: qna.habr.com

Telegram-бот, webhook и 50 строк кода

Как, опять? Ещё один туториал, пережёвывающий официальную документацию от Telegram, подумали вы? Да, но нет! Это скорее рассуждения на тему того, как построить функциональный бот-сервис используя Python3.5+, asyncio и aiohttp. Тем интереснее, что заголовок на самом деле лукавит…

Так в чём же лукавство заголовка? Во-первых, кода не 50 строк, а всего 39, а во-вторых, и бот не такой сложный, просто эхо-бот. Но, как мне кажется, этого достаточно, чтобы поверить в то, что сделать свой собственный бот-сервис не столь сложно, как может показаться.

Telegram-bot в 39 строк кода

import asyncio import aiohttp from aiohttp import web import json TOKEN = ‘111111111:AAHKeYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA’ API_URL = ‘https://api.telegram.org/bot%s/sendMessage’ % TOKEN async def handler(request): data = await request.json() headers = < ‘Content-Type’: ‘application/json’ >message = < ‘chat_id’: data[‘message’][‘chat’][‘id’], ‘text’: data[‘message’][‘text’] >async with aiohttp.ClientSession(loop=loop) as session: async with session.post(API_URL, data=json.dumps(message), headers=headers) as resp: try: assert resp.status == 200 except: return web.Response(status=500) return web.Response(status=200) async def init_app(loop): app = web.Application(loop=loop, middlewares=[]) app.router.add_post(‘/api/v1’, handler) return app if __name__ == ‘__main__’: loop = asyncio.get_event_loop() try: app = loop.run_until_complete(init_app(loop)) web.run_app(app, host=’0.0.0.0′, port=23456) except Exception as e: print(‘Error create server: %r’ % e) finally: pass loop.close()

Далее, в нескольких словах, что для чего и как сделать лучше из того, что уже есть.

1. Что используем

  • во-первых, Python 3.5+. Почему именно 3.5+, потому что asyncio [2] и потому что сахарные async, await etc;
  • во-вторых, aiohttp. Так как сервис на вебхуках, то он одновременно и HTTP-сервер и HTTP-клиент, а что для этого использовать, как не aiohttp [3];
  • в-третьих, почему webhook, а не long polling? Если не планируется изначально бот-рассыльщик, то интерактивность является его основной функцией. Выскажу своё мнение, что для этой задачи, бот в роли HTTP-сервера подходит лучше, чем в роли клиента. Да, и отдадим часть работы (доставку сообщений) сервисам Telegram.

2. Как используем

Сервер

Состояние библиотеки aiohttp на текущий момент таково, что с её использованием можно построить полноценный web-сервер в Джанго-стиле [4].

Для standalone-сервиса вся мощь не пригодится, поэтому создание сервера ограничивается несколькими строками.

async def init_app(loop): app = web.Application(loop=loop, middlewares=[]) app.router.add_post(‘/api/v1’, handler) return app

N.B. Обратите внимание, что здесь мы определяем роутинг и задаём обработчик входящих сообщений handler.

Еще по теме:  Как востановить пороль в Телеграме двойной аунтефткации

И стартуем веб-сервер:

app = loop.run_until_complete(init_app(loop)) web.run_app(app, host=’0.0.0.0′, port=23456)

Клиент

Для отправки сообщения используем метод sendMessage из Telegram API, для этого необходимо отправить на оформленный должным образом URL POST-запрос с параметрами в виде JSON-объекта. И это мы делаем с помощью aiohttp:

TOKEN = ‘111111111:AAHKeYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA’ API_URL = ‘https://api.telegram.org/bot%s/sendMessage’ % TOKEN . async def handler(request): data = await request.json() headers = < ‘Content-Type’: ‘application/json’ >message = < ‘chat_id’: data[‘message’][‘chat’][‘id’], ‘text’: data[‘message’][‘text’] >async with aiohttp.ClientSession(loop=loop) as session: async with session.post(API_URL, data=json.dumps(message), headers=headers) as resp: try: assert resp.status == 200 except: return web.Response(status=500) return web.Response(status=200)

N.B. Обратите внимание, что в случае успешной обработки входящего сообщения и удачной отправки «эха», обработчик возвращает пустой ответ со статусом HTTP 200. Если этого не сделать, сервисы Telegram продолжат в течение какого-то времени «дёргать» запросами хук, либо пока не получат в ответ 200, либо пока не истечёт определённое для сообщения время.

3. Что можно улучшить

Совершенству нет предела, пара идей, как сделать сервис функциональней.

Используем middleware

Допустим, возникла необходимость фильтровать входящие сообщения. Препроцессинг сообщений можно сделать на специальных веб-обработчиках, в терминах aiohtttp — это middlewares [5].

Пример, определяем мидлварь для игнора сообщений от пользователей из черного списка:

async def middleware_factory(app, handler): async def middleware_handler(request): data = await request.json() if data[‘message’][‘from’][‘id’] in black_list: return web.Response(status=200) return await handler(request) return middleware_handler

И добавляем обработчик при инициализации web-приложения:

async def init_app(loop): app = web.Application(loop=loop, middlewares=[]) app.router.add_post(‘/api/v1’, handler) app.middlewares.append(middleware_factory) return app

Мысли по поводу обработки входящих сообщений

Если бот будет сложнее, чем репитер-попугай, то можно предложить следующую иерархию объектов Api → Conversation → CustomConversation.

class Api(object): URL = ‘https://api.telegram.org/bot%s/%s’ def __init__(self, token, loop): self._token = token self._loop = loop async def _request(self, method, message): headers = < ‘Content-Type’: ‘application/json’ >async with aiohttp.ClientSession(loop=self._loop) as session: async with session.post(self.URL % (self._token, method), data=json.dumps(message), headers=headers) as resp: try: assert resp.status == 200 except: pass async def sendMessage(self, chatId, text): message = < ‘chat_id’: chatId, ‘text’: text >await self._request(‘sendMessage’, message) class Conversation(Api): def __init__(self, token, loop): super().__init__(token, loop) async def _handler(self, message): pass async def handler(self, request): message = await request.json() asyncio.ensure_future(self._handler(message[‘message’])) return aiohttp.web.Response(status=200) class EchoConversation(Conversation): def __init__(self, token, loop): super().__init__(token, loop) async def _handler(self, message): await self.sendMessage(message[‘chat’][‘id’], message[‘text’])

Наследуя от Conversation и переопределяя _handler получаем кастомные обработчики, в зависимости от функциональности бота — погодный, финансовый etc.

И наш сервис превращается в ферму:

echobot = EchoConversation(TOKEN1, loop) weatherbot = WeatherConversation(TOKEN2, loop) finbot = FinanceConversation(TOKEN3, loop) . app.router.add_post(‘/api/v1/echo’, echobot.handler) app.router.add_post(‘/api/v1/weather’, weatherbot.handler) app.router.add_post(‘/api/v1/finance’, finbot.handler)

4. Реальный мир

Регистрация webhook

Создаём data.json:

И вызываем соответствующий метод API любым доступным способом, например:

N.B. Ваш домен, хук на который вы устанавливаете, должен резолвится, иначе метод setWebhook не отработает.

Используем прокси-сервер

Как говорит документация: ports currently supported for Webhooks: 443, 80, 88, 8443.

Как же быть в случае self-hosted, когда необходимые порты уже скорее всего заняты веб-сервером, да и соединение по HTTPS мы в нашем сервисе не настроили?

Ответ простой, запуск сервиса на любом доступном локальном интерфейсе и использование реверс-прокси, и лучше nginx здесь сложно найти что-то другое, пусть он возьмёт на себя задачу организации HTTPS-соединения и переадресацию запросов нашему сервису.

Заключение

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

Пусть ваши идеи находят достойный инструмент для реализации.

Полезное:

  1. Telegram Bot API
  2. 18.5. asyncio — Asynchronous I/O, event loop, coroutines and tasks
  3. aiohttp: Asynchronous HTTP Client/Server
  4. aiohttp: Server Tutorial
  5. aiohttp: Server Usage — Middlewares

Источник: h.amazingsoftworks.com

Рейтинг
( Пока оценок нет )
Загрузка ...