1
0
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:
Kylmakalle 2017-07-07 00:25:13 +03:00
commit ed88939110
6 changed files with 116 additions and 22 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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',

View File

@ -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)

View File

@ -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

View File

@ -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)