1
0
mirror of https://github.com/eternnoir/pyTelegramBotAPI.git synced 2023-08-10 21:12:57 +03:00

Webhook processing function using flask for sync

This commit is contained in:
_run 2022-07-06 21:31:03 +05:00
parent 01f9e3b710
commit eb4cd7aba0
2 changed files with 162 additions and 0 deletions

View File

@ -18,6 +18,13 @@ import telebot.types
from telebot.storage import StatePickleStorage, StateMemoryStorage from telebot.storage import StatePickleStorage, StateMemoryStorage
# random module to generate random string
import random
import string
# webhooks module
from telebot.extensions.webhooks import SyncWebhookListener
logger = logging.getLogger('TeleBot') logger = logging.getLogger('TeleBot')
@ -293,6 +300,74 @@ class TeleBot:
return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address, return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address,
drop_pending_updates, timeout, secret_token) drop_pending_updates, timeout, secret_token)
def run_webhooks(self,
listen: Optional[str]="127.0.0.1",
port: Optional[int]=443,
url_path: Optional[str]=None,
certificate: Optional[str]=None,
certificate_key: Optional[str]=None,
webhook_url: Optional[str]=None,
max_connections: Optional[int]=None,
allowed_updates: Optional[List]=None,
ip_address: Optional[str]=None,
drop_pending_updates: Optional[bool] = None,
timeout: Optional[int]=None,
secret_token: Optional[str]=None,
secret_token_length: Optional[int]=20,
debug: Optional[bool]=False):
"""
This class sets webhooks and listens to a given url and port.
:param listen: IP address to listen to. Defaults to
0.0.0.0
:param port: A port which will be used to listen to webhooks.
:param url_path: Path to the webhook. Defaults to /token
:param certificate: Path to the certificate file.
:param certificate_key: Path to the certificate key file.
:param webhook_url: Webhook URL.
:param max_connections: Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput.
:param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [message, edited_channel_post, callback_query] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used.
:param ip_address: The fixed IP address which will be used to send webhook requests instead of the IP address resolved through DNS
:param drop_pending_updates: Pass True to drop all pending updates
:param timeout: Integer. Request connection timeout
:param secret_token: Secret token to be used to verify the webhook request.
:return:
"""
# generate secret token if not set
if not secret_token:
secret_token = ''.join(random.choices(string.ascii_uppercase + string.digits, k=secret_token_length))
if not url_path:
url_path = self.token + '/'
if url_path[-1] != '/': url_path += '/'
protocol = "https" if certificate else "http"
if not webhook_url:
webhook_url = "{}://{}:{}/{}".format(protocol, listen, port, url_path)
self.set_webhook(
url=webhook_url,
certificate=certificate,
max_connections=max_connections,
allowed_updates=allowed_updates,
ip_address=ip_address,
drop_pending_updates=drop_pending_updates,
timeout=timeout,
secret_token=secret_token
)
ssl_context = (certificate, certificate_key) if certificate else None
self.webhook_listener = SyncWebhookListener(self, secret_token, listen, port, ssl_context, '/'+url_path, debug)
self.webhook_listener.run_app()
return self.webhook_listener
def delete_webhook(self, drop_pending_updates=None, timeout=None): def delete_webhook(self, drop_pending_updates=None, timeout=None):
""" """
Use this method to remove webhook integration if you decide to switch back to getUpdates. Use this method to remove webhook integration if you decide to switch back to getUpdates.

View File

@ -0,0 +1,87 @@
"""
This file is used by TeleBot.run_webhooks() &
AsyncTeleBot.run_webhooks() functions.
Flask/Aiohttp is required to run this script.
"""
flask_installed = True
try:
import flask
from werkzeug.serving import _TSSLContextArg
except ImportError:
flask_installed = False
from telebot.types import Update
from typing import Optional
class SyncWebhookListener:
def __init__(self, bot,
secret_token: str, host: Optional[str]="127.0.0.1",
port: Optional[int]=8000,
ssl_context: Optional[_TSSLContextArg]=None,
url_path: Optional[str]=None,
debug: Optional[bool]=False
) -> None:
"""
Synchronous implementation of webhook listener
for synchronous version of telebot.
:param bot: TeleBot instance
:param secret_token: Telegram secret token
:param host: Webhook host
:param port: Webhook port
:param ssl_context: SSL context
"""
if not flask_installed:
raise ImportError('Flask is not installed. Please install it via pip.')
self.app = flask.Flask(__name__)
self._secret_token = secret_token
self._bot = bot
self._port = port
self._host = host
self._ssl_context = ssl_context
self._url_path = url_path
self._debug = debug
self._prepare_endpoint_urls()
def _prepare_endpoint_urls(self):
self.app.add_url_rule(self._url_path, 'index', self.process_update, methods=['POST'])
def process_update(self):
"""
Processes updates.
"""
# header containsX-Telegram-Bot-Api-Secret-Token
if flask.request.headers.get('X-Telegram-Bot-Api-Secret-Token') != self._secret_token:
# secret token didn't match
flask.abort(403)
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
self._bot.process_new_updates([Update.de_json(json_string)])
return ''
flask.abort(403)
def run_app(self):
"""
Run app with the given parameters.
"""
self.app.run(
host=self._host,
port=self._port,
ssl_context=self._ssl_context,
debug=self._debug
)
return self