mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Merge remote-tracking branch 'refs/remotes/eternnoir/master'
This commit is contained in:
commit
ed88939110
@ -1,6 +1,6 @@
|
||||
# <p align="center">pyTelegramBotAPI
|
||||
|
||||
<p align="center">A simple, but extensible Python implementation for the [Telegram Bot API](https://core.telegram.org/bots/api).
|
||||
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.
|
||||
|
||||
[![Download Month](https://img.shields.io/pypi/v/pyTelegramBotAPI.svg)](https://pypi.python.org/pypi/pyTelegramBotAPI)
|
||||
[![Build Status](https://travis-ci.org/eternnoir/pyTelegramBotAPI.svg?branch=master)](https://travis-ci.org/eternnoir/pyTelegramBotAPI)
|
||||
|
@ -73,6 +73,11 @@ bot.remove_webhook()
|
||||
bot.set_webhook(url=WEBHOOK_URL_BASE+WEBHOOK_URL_PATH,
|
||||
certificate=open(WEBHOOK_SSL_CERT, 'r'))
|
||||
|
||||
# Disable CherryPy requests log
|
||||
access_log = cherrypy.log.access_log
|
||||
for handler in tuple(access_log.handlers):
|
||||
access_log.removeHandler(handler)
|
||||
|
||||
# Start cherrypy server
|
||||
cherrypy.config.update({
|
||||
'server.socket_host': WEBHOOK_LISTEN,
|
||||
|
2
setup.py
2
setup.py
@ -7,7 +7,7 @@ def readme():
|
||||
return f.read()
|
||||
|
||||
setup(name='pyTelegramBotAPI',
|
||||
version='2.3.2',
|
||||
version='3.0.1',
|
||||
description='Python Telegram bot api. ',
|
||||
long_description=readme(),
|
||||
author='eternnoir',
|
||||
|
@ -74,6 +74,8 @@ class TeleBot:
|
||||
self.inline_handlers = []
|
||||
self.chosen_inline_handlers = []
|
||||
self.callback_query_handlers = []
|
||||
self.shipping_query_handlers = []
|
||||
self.pre_checkout_query_handlers = []
|
||||
|
||||
self.threaded = threaded
|
||||
if self.threaded:
|
||||
@ -146,6 +148,9 @@ class TeleBot:
|
||||
new_inline_querys = []
|
||||
new_chosen_inline_results = []
|
||||
new_callback_querys = []
|
||||
new_shipping_querys = []
|
||||
new_pre_checkout_querys = []
|
||||
|
||||
for update in updates:
|
||||
if update.update_id > self.last_update_id:
|
||||
self.last_update_id = update.update_id
|
||||
@ -163,6 +168,11 @@ class TeleBot:
|
||||
new_chosen_inline_results.append(update.chosen_inline_result)
|
||||
if update.callback_query:
|
||||
new_callback_querys.append(update.callback_query)
|
||||
if update.shipping_query:
|
||||
new_shipping_querys.append(update.shipping_query)
|
||||
if update.pre_checkout_query:
|
||||
new_pre_checkout_querys.append(update.pre_checkout_query)
|
||||
|
||||
logger.debug('Received {0} new updates'.format(len(updates)))
|
||||
if len(new_messages) > 0:
|
||||
self.process_new_messages(new_messages)
|
||||
@ -178,6 +188,10 @@ class TeleBot:
|
||||
self.process_new_chosen_inline_query(new_chosen_inline_results)
|
||||
if len(new_callback_querys) > 0:
|
||||
self.process_new_callback_query(new_callback_querys)
|
||||
if len(new_pre_checkout_querys) > 0:
|
||||
self.process_new_pre_checkout_query(new_pre_checkout_querys)
|
||||
if len(new_shipping_querys) > 0:
|
||||
self.process_new_shipping_query(new_shipping_querys)
|
||||
|
||||
def process_new_messages(self, new_messages):
|
||||
self._append_pre_next_step_handler()
|
||||
@ -204,6 +218,12 @@ class TeleBot:
|
||||
def process_new_callback_query(self, new_callback_querys):
|
||||
self._notify_command_handlers(self.callback_query_handlers, new_callback_querys)
|
||||
|
||||
def process_new_shipping_query(self, new_shipping_querys):
|
||||
self._notify_command_handlers(self.shipping_query_handlers, new_shipping_querys)
|
||||
|
||||
def process_new_pre_checkout_query(self, pre_checkout_querys):
|
||||
self._notify_command_handlers(self.pre_checkout_query_handlers, pre_checkout_querys)
|
||||
|
||||
def __notify_update(self, new_messages):
|
||||
for listener in self.update_listener:
|
||||
self._exec_task(listener, new_messages)
|
||||
@ -512,7 +532,7 @@ class TeleBot:
|
||||
disable_notification, timeout))
|
||||
|
||||
def send_video_note(self, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None,
|
||||
disable_notification=None, timeout=None):
|
||||
disable_notification=None, timeout=None):
|
||||
"""
|
||||
Use this method to send video files, Telegram clients support mp4 videos.
|
||||
:param chat_id: Integer : Unique identifier for the message recipient — User or GroupChat id
|
||||
@ -525,7 +545,7 @@ class TeleBot:
|
||||
"""
|
||||
return types.Message.de_json(
|
||||
apihelper.send_video_note(self.token, chat_id, data, duration, length, reply_to_message_id, reply_markup,
|
||||
disable_notification, timeout))
|
||||
disable_notification, timeout))
|
||||
|
||||
def send_location(self, chat_id, latitude, longitude, reply_to_message_id=None, reply_markup=None,
|
||||
disable_notification=None):
|
||||
@ -613,7 +633,8 @@ class TeleBot:
|
||||
reply_markup)
|
||||
return types.Message.de_json(result)
|
||||
|
||||
def set_game_score(self, user_id, score, force=None,chat_id=None, message_id=None, inline_message_id=None, edit_message=None):
|
||||
def set_game_score(self, user_id, score, force=None, chat_id=None, message_id=None, inline_message_id=None,
|
||||
edit_message=None):
|
||||
result = apihelper.set_game_score(self.token, user_id, score, force, chat_id, message_id, inline_message_id,
|
||||
edit_message)
|
||||
if type(result) == bool:
|
||||
@ -627,6 +648,24 @@ class TeleBot:
|
||||
ret.append(types.GameHighScore.de_json(r))
|
||||
return ret
|
||||
|
||||
def send_invoice(self, chat_id, title, description, invoice_payload, provider_token, currency, prices,
|
||||
start_parameter, photo_url=None, photo_size=None, photo_width=None, photo_height=None,
|
||||
need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None,
|
||||
is_flexible=None,
|
||||
disable_notification=None, reply_to_message_id=None, reply_markup=None):
|
||||
result = apihelper.send_invoice(self.token, chat_id, title, description, invoice_payload, provider_token,
|
||||
currency, prices, start_parameter, photo_url, photo_size, photo_width,
|
||||
photo_height,
|
||||
need_name, need_phone_number, need_email, need_shipping_address, is_flexible,
|
||||
disable_notification, reply_to_message_id, reply_markup)
|
||||
return types.Message.de_json(result)
|
||||
|
||||
def answer_shipping_query(self, shipping_query_id, ok, shipping_options=None, error_message=None):
|
||||
return apihelper.answer_shipping_query(self.token, shipping_query_id, ok, shipping_options, error_message)
|
||||
|
||||
def answer_pre_checkout_query(self, pre_checkout_query_id, ok, error_message=None):
|
||||
return apihelper.answer_pre_checkout_query(self.token, pre_checkout_query_id, ok, error_message)
|
||||
|
||||
def edit_message_caption(self, caption, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None):
|
||||
result = apihelper.edit_message_caption(self.token, caption, chat_id, message_id, inline_message_id,
|
||||
reply_markup)
|
||||
@ -866,6 +905,28 @@ class TeleBot:
|
||||
def add_callback_query_handler(self, handler_dict):
|
||||
self.callback_query_handlers.append(handler_dict)
|
||||
|
||||
def shipping_query_handler(self, func, **kwargs):
|
||||
def decorator(handler):
|
||||
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
|
||||
self.add_shipping_query_handler(handler_dict)
|
||||
return handler
|
||||
|
||||
return decorator
|
||||
|
||||
def add_shipping_query_handler(self, handler_dict):
|
||||
self.shipping_query_handlers.append(handler_dict)
|
||||
|
||||
def pre_checkout_query_handler(self, func, **kwargs):
|
||||
def decorator(handler):
|
||||
handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
|
||||
self.add_pre_checkout_query_handler(handler_dict)
|
||||
return handler
|
||||
|
||||
return decorator
|
||||
|
||||
def add_pre_checkout_query_handler(self, handler_dict):
|
||||
self.pre_checkout_query_handlers.append(handler_dict)
|
||||
|
||||
def _test_message_handler(self, message_handler, message):
|
||||
for filter, filter_value in six.iteritems(message_handler['filters']):
|
||||
if filter_value is None:
|
||||
@ -1018,6 +1079,18 @@ class AsyncTeleBot(TeleBot):
|
||||
def get_game_high_scores(self, *args, **kwargs):
|
||||
return TeleBot.get_game_high_scores(self, *args, **kwargs)
|
||||
|
||||
@util.async()
|
||||
def send_invoice(self, *args, **kwargs):
|
||||
return TeleBot.send_invoice(self, *args, **kwargs)
|
||||
|
||||
@util.async()
|
||||
def answer_shipping_query(self, *args, **kwargs):
|
||||
return TeleBot.answer_shipping_query(self, *args, **kwargs)
|
||||
|
||||
@util.async()
|
||||
def answer_pre_checkout_query(self, *args, **kwargs):
|
||||
return TeleBot.answer_pre_checkout_query(self, *args, **kwargs)
|
||||
|
||||
@util.async()
|
||||
def edit_message_caption(self, *args, **kwargs):
|
||||
return TeleBot.edit_message_caption(self, *args, **kwargs)
|
||||
|
@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import requests
|
||||
|
||||
try:
|
||||
from requests.packages.urllib3 import fields
|
||||
|
||||
format_header_param = fields.format_header_param
|
||||
except ImportError:
|
||||
format_header_param = None
|
||||
@ -39,7 +41,8 @@ def _make_request(token, method_name, method='get', params=None, files=None, bas
|
||||
if params:
|
||||
if 'timeout' in params: read_timeout = params['timeout'] + 10
|
||||
if 'connect-timeout' in params: connect_timeout = params['connect-timeout'] + 10
|
||||
result = req_session.request(method, request_url, params=params, files=files, timeout=(connect_timeout, read_timeout))
|
||||
result = req_session.request(method, request_url, params=params, files=files,
|
||||
timeout=(connect_timeout, read_timeout))
|
||||
logger.debug("The server returned: '{0}'".format(result.text.encode('utf8')))
|
||||
return _check_result(method_name, result)['result']
|
||||
|
||||
@ -544,11 +547,12 @@ def get_game_high_scores(token, user_id, chat_id=None, message_id=None, inline_m
|
||||
payload['inline_message_id'] = inline_message_id
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
# Payments (https://core.telegram.org/bots/api#payments)
|
||||
|
||||
def send_invoice(token, chat_id, title, description, invoice_payload, provider_token, currency, prices, start_parameter=None,
|
||||
photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None,
|
||||
need_phone_number=None, need_email=None, need_shipping_address=None, is_flexible=None,
|
||||
def send_invoice(token, chat_id, title, description, invoice_payload, provider_token, currency, prices,
|
||||
start_parameter, photo_url=None, photo_size=None, photo_width=None, photo_height=None,
|
||||
need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, is_flexible=None,
|
||||
disable_notification=None, reply_to_message_id=None, reply_markup=None):
|
||||
"""
|
||||
Use this method to send invoices. On success, the sent Message is returned.
|
||||
@ -556,7 +560,7 @@ def send_invoice(token, chat_id, title, description, invoice_payload, provider_t
|
||||
:param chat_id: Unique identifier for the target private chat
|
||||
:param title: Product name
|
||||
:param description: Product description
|
||||
:param payload: Bot-defined invoice payload, 1-128 bytes. This will not be displayed to the user, use for your internal processes.
|
||||
:param invoice_payload: Bot-defined invoice payload, 1-128 bytes. This will not be displayed to the user, use for your internal processes.
|
||||
:param provider_token: Payments provider token, obtained via @Botfather
|
||||
:param currency: Three-letter ISO 4217 currency code, see https://core.telegram.org/bots/payments#supported-currencies
|
||||
:param prices: Price breakdown, a list of components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.)
|
||||
@ -576,9 +580,9 @@ def send_invoice(token, chat_id, title, description, invoice_payload, provider_t
|
||||
:return:
|
||||
"""
|
||||
method_url = r'sendInvoice'
|
||||
payload = {'chat_id': chat_id, 'title': title, 'description': description, 'payload': invoice_payload, 'provider_token': provider_token, 'currency': currency, 'prices': prices}
|
||||
if start_parameter:
|
||||
payload['start_parameter'] = start_parameter
|
||||
payload = {'chat_id': chat_id, 'title': title, 'description': description, 'payload': invoice_payload,
|
||||
'provider_token': provider_token, 'start_parameter': start_parameter, 'currency': currency,
|
||||
'prices': _convert_list_json_serializable(prices)}
|
||||
if photo_url:
|
||||
payload['photo_url'] = photo_url
|
||||
if photo_size:
|
||||
@ -602,11 +606,11 @@ def send_invoice(token, chat_id, title, description, invoice_payload, provider_t
|
||||
if reply_to_message_id:
|
||||
payload['reply_to_message_id'] = reply_to_message_id
|
||||
if reply_markup:
|
||||
payload['reply_markup'] = reply_markup
|
||||
payload['reply_markup'] = _convert_markup(reply_markup)
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def answer_shippingQuery(token, shipping_query_id, ok, shipping_options=None, error_message=None):
|
||||
def answer_shipping_query(token, shipping_query_id, ok, shipping_options=None, error_message=None):
|
||||
"""
|
||||
If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success, True is returned.
|
||||
:param token: Bot's token (you don't need to fill this)
|
||||
@ -619,9 +623,9 @@ def answer_shippingQuery(token, shipping_query_id, ok, shipping_options=None, er
|
||||
method_url = 'answerShippingQuery'
|
||||
payload = {'shipping_query_id': shipping_query_id, 'ok': ok}
|
||||
if shipping_options:
|
||||
payload['reply_markup'] = shipping_options
|
||||
payload['reply_markup'] = _convert_list_json_serializable(shipping_options)
|
||||
if error_message:
|
||||
payload['reply_markup'] = error_message
|
||||
payload['error_message'] = error_message
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
@ -672,7 +676,7 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None,
|
||||
def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
|
||||
switch_pm_text=None, switch_pm_parameter=None):
|
||||
method_url = 'answerInlineQuery'
|
||||
payload = {'inline_query_id': inline_query_id, 'results': _convert_inline_results(results)}
|
||||
payload = {'inline_query_id': inline_query_id, 'results': _convert_list_json_serializable(results)}
|
||||
if cache_time:
|
||||
payload['cache_time'] = cache_time
|
||||
if is_personal:
|
||||
@ -686,7 +690,7 @@ def answer_inline_query(token, inline_query_id, results, cache_time=None, is_per
|
||||
return _make_request(token, method_url, params=payload, method='post')
|
||||
|
||||
|
||||
def _convert_inline_results(results):
|
||||
def _convert_list_json_serializable(results):
|
||||
ret = ''
|
||||
for r in results:
|
||||
if isinstance(r, types.JsonSerializable):
|
||||
@ -708,6 +712,7 @@ def _no_encode(func):
|
||||
return '{0}={1}'.format(key, val)
|
||||
else:
|
||||
return func(key, val)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
@ -148,6 +148,8 @@ class WebhookInfo(JsonDeserializable):
|
||||
pending_update_count = obj['pending_update_count']
|
||||
last_error_date = None
|
||||
last_error_message = None
|
||||
max_connections = None
|
||||
allowed_updates = None
|
||||
if 'last_error_message' in obj:
|
||||
last_error_date = obj['last_error_date']
|
||||
if 'last_error_message' in obj:
|
||||
@ -794,13 +796,14 @@ class InlineKeyboardMarkup(Dictionaryable, JsonSerializable):
|
||||
|
||||
class InlineKeyboardButton(JsonSerializable):
|
||||
def __init__(self, text, url=None, callback_data=None, switch_inline_query=None,
|
||||
switch_inline_query_current_chat=None, callback_game=None):
|
||||
switch_inline_query_current_chat=None, callback_game=None, pay=None):
|
||||
self.text = text
|
||||
self.url = url
|
||||
self.callback_data = callback_data
|
||||
self.switch_inline_query = switch_inline_query
|
||||
self.switch_inline_query_current_chat = switch_inline_query_current_chat
|
||||
self.callback_game = callback_game
|
||||
self.pay = pay
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.to_dic())
|
||||
@ -817,6 +820,8 @@ class InlineKeyboardButton(JsonSerializable):
|
||||
json_dic['switch_inline_query_current_chat'] = self.switch_inline_query_current_chat
|
||||
if self.callback_game is not None:
|
||||
json_dic['callback_game'] = self.callback_game
|
||||
if self.pay is not None:
|
||||
json_dic['pay'] = self.pay
|
||||
return json_dic
|
||||
|
||||
|
||||
@ -1074,7 +1079,7 @@ class InlineQueryResultPhoto(JsonSerializable):
|
||||
|
||||
class InlineQueryResultGif(JsonSerializable):
|
||||
def __init__(self, id, gif_url, thumb_url, gif_width=None, gif_height=None, title=None, caption=None,
|
||||
reply_markup=None, input_message_content=None):
|
||||
reply_markup=None, input_message_content=None, gif_duration=None):
|
||||
"""
|
||||
Represents a link to an animated GIF file.
|
||||
:param id: Unique identifier for this result, 1-64 bytes.
|
||||
@ -1098,6 +1103,7 @@ class InlineQueryResultGif(JsonSerializable):
|
||||
self.caption = caption
|
||||
self.reply_markup = reply_markup
|
||||
self.input_message_content = input_message_content
|
||||
self.gif_duration = gif_duration
|
||||
|
||||
def to_json(self):
|
||||
json_dict = {'type': self.type, 'id': self.id, 'gif_url': self.gif_url, 'thumb_url': self.thumb_url}
|
||||
@ -1113,12 +1119,14 @@ class InlineQueryResultGif(JsonSerializable):
|
||||
json_dict['reply_markup'] = self.reply_markup.to_dic()
|
||||
if self.input_message_content:
|
||||
json_dict['input_message_content'] = self.input_message_content.to_dic()
|
||||
if self.gif_duration:
|
||||
json_dict['gif_duration'] = self.gif_duration
|
||||
return json.dumps(json_dict)
|
||||
|
||||
|
||||
class InlineQueryResultMpeg4Gif(JsonSerializable):
|
||||
def __init__(self, id, mpeg4_url, thumb_url, mpeg4_width=None, mpeg4_height=None, title=None, caption=None,
|
||||
reply_markup=None, input_message_content=None):
|
||||
reply_markup=None, input_message_content=None, mpeg4_duration=None):
|
||||
"""
|
||||
Represents a link to a video animation (H.264/MPEG-4 AVC video without sound).
|
||||
:param id: Unique identifier for this result, 1-64 bytes
|
||||
@ -1142,6 +1150,7 @@ class InlineQueryResultMpeg4Gif(JsonSerializable):
|
||||
self.caption = caption
|
||||
self.reply_markup = reply_markup
|
||||
self.input_message_content = input_message_content
|
||||
self.mpeg4_duration = mpeg4_duration
|
||||
|
||||
def to_json(self):
|
||||
json_dict = {'type': self.type, 'id': self.id, 'mpeg4_url': self.mpeg4_url, 'thumb_url': self.thumb_url}
|
||||
@ -1157,6 +1166,8 @@ class InlineQueryResultMpeg4Gif(JsonSerializable):
|
||||
json_dict['reply_markup'] = self.reply_markup.to_dic()
|
||||
if self.input_message_content:
|
||||
json_dict['input_message_content'] = self.input_message_content.to_dic()
|
||||
if self.mpeg4_duration:
|
||||
json_dict['mpeg4_duration '] = self.mpeg4_duration
|
||||
return json.dumps(json_dict)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user