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:
parent
01f9e3b710
commit
eb4cd7aba0
@ -18,6 +18,13 @@ import telebot.types
|
||||
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')
|
||||
|
||||
@ -293,6 +300,74 @@ class TeleBot:
|
||||
return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address,
|
||||
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):
|
||||
"""
|
||||
Use this method to remove webhook integration if you decide to switch back to getUpdates.
|
||||
|
87
telebot/extensions/webhooks.py
Normal file
87
telebot/extensions/webhooks.py
Normal 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
|
Loading…
Reference in New Issue
Block a user