mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Merge pull request #1380 from coder2020official/master
2 new examples and behaviour change
This commit is contained in:
commit
4347dd3dd9
87
examples/asynchronous_telebot/CallbackData_example.py
Normal file
87
examples/asynchronous_telebot/CallbackData_example.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
This Example will show you how to use CallbackData
|
||||||
|
"""
|
||||||
|
|
||||||
|
from telebot.callback_data import CallbackData, CallbackDataFilter
|
||||||
|
from telebot import types
|
||||||
|
from telebot.async_telebot import AsyncTeleBot
|
||||||
|
from telebot.asyncio_filters import AdvancedCustomFilter
|
||||||
|
|
||||||
|
API_TOKEN = 'TOKEN'
|
||||||
|
PRODUCTS = [
|
||||||
|
{'id': '0', 'name': 'xiaomi mi 10', 'price': 400},
|
||||||
|
{'id': '1', 'name': 'samsung s20', 'price': 800},
|
||||||
|
{'id': '2', 'name': 'iphone 13', 'price': 1300}
|
||||||
|
]
|
||||||
|
|
||||||
|
bot = AsyncTeleBot(API_TOKEN)
|
||||||
|
products_factory = CallbackData('product_id', prefix='products')
|
||||||
|
|
||||||
|
|
||||||
|
def products_keyboard():
|
||||||
|
return types.InlineKeyboardMarkup(
|
||||||
|
keyboard=[
|
||||||
|
[
|
||||||
|
types.InlineKeyboardButton(
|
||||||
|
text=product['name'],
|
||||||
|
callback_data=products_factory.new(product_id=product["id"])
|
||||||
|
)
|
||||||
|
]
|
||||||
|
for product in PRODUCTS
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def back_keyboard():
|
||||||
|
return types.InlineKeyboardMarkup(
|
||||||
|
keyboard=[
|
||||||
|
[
|
||||||
|
types.InlineKeyboardButton(
|
||||||
|
text='⬅',
|
||||||
|
callback_data='back'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductsCallbackFilter(AdvancedCustomFilter):
|
||||||
|
key = 'config'
|
||||||
|
|
||||||
|
async def check(self, call: types.CallbackQuery, config: CallbackDataFilter):
|
||||||
|
return config.check(query=call)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['products'])
|
||||||
|
async def products_command_handler(message: types.Message):
|
||||||
|
await bot.send_message(message.chat.id, 'Products:', reply_markup=products_keyboard())
|
||||||
|
|
||||||
|
|
||||||
|
# Only product with field - product_id = 2
|
||||||
|
@bot.callback_query_handler(func=None, config=products_factory.filter(product_id='2'))
|
||||||
|
async def product_one_callback(call: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query_id=call.id, text='Not available :(', show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Any other products
|
||||||
|
@bot.callback_query_handler(func=None, config=products_factory.filter())
|
||||||
|
async def products_callback(call: types.CallbackQuery):
|
||||||
|
callback_data: dict = products_factory.parse(callback_data=call.data)
|
||||||
|
product_id = int(callback_data['product_id'])
|
||||||
|
product = PRODUCTS[product_id]
|
||||||
|
|
||||||
|
text = f"Product name: {product['name']}\n" \
|
||||||
|
f"Product price: {product['price']}"
|
||||||
|
await bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||||
|
text=text, reply_markup=back_keyboard())
|
||||||
|
|
||||||
|
|
||||||
|
@bot.callback_query_handler(func=lambda c: c.data == 'back')
|
||||||
|
async def back_callback(call: types.CallbackQuery):
|
||||||
|
await bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
|
||||||
|
text='Products:', reply_markup=products_keyboard())
|
||||||
|
|
||||||
|
|
||||||
|
bot.add_custom_filter(ProductsCallbackFilter())
|
||||||
|
bot.polling()
|
14
examples/asynchronous_telebot/update_listener.py
Normal file
14
examples/asynchronous_telebot/update_listener.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from telebot.async_telebot import AsyncTeleBot
|
||||||
|
|
||||||
|
# Update listeners are functions that are called when any update is received.
|
||||||
|
|
||||||
|
bot = AsyncTeleBot(token='TOKEN')
|
||||||
|
|
||||||
|
async def update_listener(messages):
|
||||||
|
for message in messages:
|
||||||
|
if message.text == '/start':
|
||||||
|
await bot.send_message(message.chat.id, 'Hello!')
|
||||||
|
|
||||||
|
bot.set_update_listener(update_listener)
|
||||||
|
|
||||||
|
bot.polling()
|
@ -97,16 +97,15 @@ class AsyncTeleBot:
|
|||||||
|
|
||||||
|
|
||||||
def __init__(self, token: str, parse_mode: Optional[str]=None, offset=None,
|
def __init__(self, token: str, parse_mode: Optional[str]=None, offset=None,
|
||||||
exception_handler=None,suppress_middleware_excepions=False) -> None: # TODO: ADD TYPEHINTS
|
exception_handler=None) -> None: # TODO: ADD TYPEHINTS
|
||||||
self.token = token
|
self.token = token
|
||||||
|
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
self.token = token
|
self.token = token
|
||||||
self.parse_mode = parse_mode
|
self.parse_mode = parse_mode
|
||||||
self.update_listener = []
|
self.update_listener = []
|
||||||
self.suppress_middleware_excepions = suppress_middleware_excepions
|
|
||||||
|
|
||||||
self.exc_info = None
|
|
||||||
|
|
||||||
self.exception_handler = exception_handler
|
self.exception_handler = exception_handler
|
||||||
|
|
||||||
@ -234,13 +233,23 @@ class AsyncTeleBot:
|
|||||||
try:
|
try:
|
||||||
|
|
||||||
updates = await self.get_updates(offset=self.offset, allowed_updates=allowed_updates, timeout=timeout, request_timeout=request_timeout)
|
updates = await self.get_updates(offset=self.offset, allowed_updates=allowed_updates, timeout=timeout, request_timeout=request_timeout)
|
||||||
|
if updates:
|
||||||
|
self.offset = updates[-1].update_id + 1
|
||||||
|
self._loop_create_task(self.process_new_updates(updates)) # Seperate task for processing updates
|
||||||
|
if interval: await asyncio.sleep(interval)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
return
|
return
|
||||||
|
|
||||||
except asyncio_helper.ApiTelegramException as e:
|
except asyncio_helper.ApiTelegramException as e:
|
||||||
logger.error(str(e))
|
logger.error(str(e))
|
||||||
|
|
||||||
|
if non_stop:
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Cause exception while getting updates.')
|
logger.error('Cause exception while getting updates.')
|
||||||
if non_stop:
|
if non_stop:
|
||||||
@ -249,10 +258,6 @@ class AsyncTeleBot:
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
if updates:
|
|
||||||
self.offset = updates[-1].update_id + 1
|
|
||||||
self._loop_create_task(self.process_new_updates(updates)) # Seperate task for processing updates
|
|
||||||
if interval: await asyncio.sleep(interval)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self._polling = False
|
self._polling = False
|
||||||
@ -297,7 +302,12 @@ class AsyncTeleBot:
|
|||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handler_error = e
|
handler_error = e
|
||||||
logger.info(str(e))
|
|
||||||
|
if not middleware:
|
||||||
|
if self.exception_handler:
|
||||||
|
return self.exception_handler.handle(e)
|
||||||
|
logging.error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
if middleware:
|
if middleware:
|
||||||
await middleware.post_process(message, data, handler_error)
|
await middleware.post_process(message, data, handler_error)
|
||||||
@ -448,7 +458,7 @@ class AsyncTeleBot:
|
|||||||
if len(self.update_listener) == 0:
|
if len(self.update_listener) == 0:
|
||||||
return
|
return
|
||||||
for listener in self.update_listener:
|
for listener in self.update_listener:
|
||||||
self._loop_create_task(listener, new_messages)
|
self._loop_create_task(listener(new_messages))
|
||||||
|
|
||||||
async def _test_message_handler(self, message_handler, message):
|
async def _test_message_handler(self, message_handler, message):
|
||||||
"""
|
"""
|
||||||
@ -466,6 +476,9 @@ class AsyncTeleBot:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def set_update_listener(self, func):
|
||||||
|
self.update_listener.append(func)
|
||||||
|
|
||||||
def add_custom_filter(self, custom_filter):
|
def add_custom_filter(self, custom_filter):
|
||||||
"""
|
"""
|
||||||
Create custom filter.
|
Create custom filter.
|
||||||
|
@ -8,7 +8,7 @@ try:
|
|||||||
import ujson as json
|
import ujson as json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
API_URL = 'https://api.telegram.org/bot{0}/{1}'
|
API_URL = 'https://api.telegram.org/bot{0}/{1}'
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -42,14 +42,55 @@ RETRY_TIMEOUT = 2
|
|||||||
MAX_RETRIES = 15
|
MAX_RETRIES = 15
|
||||||
|
|
||||||
async def _process_request(token, url, method='get', params=None, files=None, request_timeout=None):
|
async def _process_request(token, url, method='get', params=None, files=None, request_timeout=None):
|
||||||
|
params = compose_data(params, files)
|
||||||
async with await session_manager._get_new_session() as session:
|
async with await session_manager._get_new_session() as session:
|
||||||
async with session.get(API_URL.format(token, url), params=params, data=files, timeout=request_timeout) as response:
|
async with session.request(method=method, url=API_URL.format(token, url), data=params, timeout=request_timeout) as response:
|
||||||
logger.debug("Request: method={0} url={1} params={2} files={3} request_timeout={4}".format(method, url, params, files, request_timeout).replace(token, token.split(':')[0] + ":{TOKEN}"))
|
logger.debug("Request: method={0} url={1} params={2} files={3} request_timeout={4}".format(method, url, params, files, request_timeout).replace(token, token.split(':')[0] + ":{TOKEN}"))
|
||||||
json_result = await _check_result(url, response)
|
json_result = await _check_result(url, response)
|
||||||
if json_result:
|
if json_result:
|
||||||
return json_result['result']
|
return json_result['result']
|
||||||
|
|
||||||
|
|
||||||
|
def guess_filename(obj):
|
||||||
|
"""
|
||||||
|
Get file name from object
|
||||||
|
|
||||||
|
:param obj:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
name = getattr(obj, 'name', None)
|
||||||
|
if name and isinstance(name, str) and name[0] != '<' and name[-1] != '>':
|
||||||
|
return os.path.basename(name)
|
||||||
|
|
||||||
|
|
||||||
|
def compose_data(params=None, files=None):
|
||||||
|
"""
|
||||||
|
Prepare request data
|
||||||
|
|
||||||
|
:param params:
|
||||||
|
:param files:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
data = aiohttp.formdata.FormData(quote_fields=False)
|
||||||
|
|
||||||
|
if params:
|
||||||
|
for key, value in params.items():
|
||||||
|
data.add_field(key, str(value))
|
||||||
|
|
||||||
|
if files:
|
||||||
|
for key, f in files.items():
|
||||||
|
if isinstance(f, tuple):
|
||||||
|
if len(f) == 2:
|
||||||
|
filename, fileobj = f
|
||||||
|
else:
|
||||||
|
raise ValueError('Tuple must have exactly 2 elements: filename, fileobj')
|
||||||
|
else:
|
||||||
|
filename, fileobj = guess_filename(f) or key, f
|
||||||
|
|
||||||
|
data.add_field(key, fileobj, filename=filename)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
async def _convert_markup(markup):
|
async def _convert_markup(markup):
|
||||||
if isinstance(markup, types.JsonSerializable):
|
if isinstance(markup, types.JsonSerializable):
|
||||||
return markup.to_json()
|
return markup.to_json()
|
||||||
@ -731,7 +772,7 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform
|
|||||||
async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None,
|
async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None,
|
||||||
disable_notification=None, timeout=None, caption=None, thumb=None, caption_entities=None,
|
disable_notification=None, timeout=None, caption=None, thumb=None, caption_entities=None,
|
||||||
allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None):
|
allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None):
|
||||||
method_url = get_method_by_type(data_type)
|
method_url = await get_method_by_type(data_type)
|
||||||
payload = {'chat_id': chat_id}
|
payload = {'chat_id': chat_id}
|
||||||
files = None
|
files = None
|
||||||
if not util.is_string(data):
|
if not util.is_string(data):
|
||||||
|
Loading…
Reference in New Issue
Block a user