Skip to content

Commit da8a3ce

Browse files
authored
Merge pull request python-telegram-bot#631 from jeffffc/paymenthandlers
Add both handlers for queries from new Payment API
2 parents bc3669f + 4247dc0 commit da8a3ce

File tree

10 files changed

+279
-11
lines changed

10 files changed

+279
-11
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ The following wonderful people contributed directly or indirectly to this projec
3030
- `Hugo Damer <https://github.com/HakimusGIT>`_
3131
- `Jacob Bom <https://github.com/bomjacob>`_
3232
- `JASON0916 <https://github.com/JASON0916>`_
33+
- `jeffffc <https://github.com/jeffffc>`_
3334
- `jh0ker <https://github.com/jh0ker>`_
3435
- `John Yong <https://github.com/whipermr5>`_
3536
- `jossalgon <https://github.com/jossalgon>`_

telegram/bot.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,7 @@ def send_invoice(self,
18351835
photo_height=None,
18361836
need_name=None,
18371837
need_phone_number=None,
1838+
need_email=None,
18381839
need_shipping_address=None,
18391840
is_flexible=None,
18401841
disable_notification=False,
@@ -1867,6 +1868,8 @@ def send_invoice(self,
18671868
the order
18681869
need_phone_number (Optional[bool]): Pass True, if you require the user's phone number
18691870
to complete the order
1871+
need_email (Optional[bool]): Pass True, if you require the user's email to
1872+
complete the order
18701873
need_shipping_address (Optional[bool]): Pass True, if you require the user's shipping
18711874
address to complete the order
18721875
is_flexible (Optional[bool]): Pass True, if the final price depends on the shipping
@@ -1915,6 +1918,8 @@ def send_invoice(self,
19151918
data['need_name'] = need_name
19161919
if need_phone_number is not None:
19171920
data['need_phone_number'] = need_phone_number
1921+
if need_email is not None:
1922+
data['need_email'] = need_email
19181923
if need_shipping_address is not None:
19191924
data['need_shipping_address'] = need_shipping_address
19201925
if is_flexible is not None:
@@ -1926,7 +1931,9 @@ def answer_shipping_query(self,
19261931
shipping_query_id,
19271932
ok,
19281933
shipping_options=None,
1929-
error_message=None):
1934+
error_message=None,
1935+
timeout=None,
1936+
**kwargs):
19301937
"""
19311938
If you sent an invoice requesting a shipping address and the parameter is_flexible was
19321939
specified, the Bot API will send an Update with a shipping_query field to the bot. Use
@@ -1943,6 +1950,7 @@ def answer_shipping_query(self,
19431950
form that explains why it is impossible to complete the order (e.g. "Sorry,
19441951
delivery to your desired address is unavailable'). Telegram will display this
19451952
message to the user.
1953+
**kwargs (dict): Arbitrary keyword arguments.
19461954
19471955
Returns:
19481956
bool: On success, `True` is returned.
@@ -1951,18 +1959,32 @@ def answer_shipping_query(self,
19511959
:class:`telegram.TelegramError`
19521960
19531961
"""
1954-
url = '{0]/answerShippingQuery'.format(self.base_url)
1962+
1963+
if ok is True and (shipping_options is None or error_message is not None):
1964+
raise TelegramError(
1965+
'answerShippingQuery: If ok is True, shipping_options '
1966+
'should not be empty and there should not be error_message')
1967+
1968+
if ok is False and (shipping_options is not None or error_message is None):
1969+
raise TelegramError(
1970+
'answerShippingQuery: If ok is False, error_message '
1971+
'should not be empty and there should not be shipping_options')
1972+
1973+
url_ = '{0}/answerShippingQuery'.format(self.base_url)
19551974

19561975
data = {'shipping_query_id': shipping_query_id, 'ok': ok}
19571976

1958-
if shipping_options is not None:
1977+
if ok is True:
19591978
data['shipping_options'] = shipping_options
19601979
if error_message is not None:
19611980
data['error_message'] = error_message
19621981

1963-
return url, data
1982+
result = self._request.post(url_, data, timeout=timeout)
19641983

1965-
def answer_pre_checkout_query(self, pre_checkout_query_id, ok, error_message=None):
1984+
return result
1985+
1986+
def answer_pre_checkout_query(self, pre_checkout_query_id, ok,
1987+
error_message=None, timeout=None, **kwargs):
19661988
"""
19671989
If you sent an invoice requesting a shipping address and the parameter is_flexible was
19681990
specified, the Bot API will send an Update with a shipping_query field to the bot.
@@ -1977,6 +1999,7 @@ def answer_pre_checkout_query(self, pre_checkout_query_id, ok, error_message=Non
19771999
"Sorry, somebody just bought the last of our amazing black T-shirts while you were
19782000
busy filling out your payment details. Please choose a different color or
19792001
garment!"). Telegram will display this message to the user.
2002+
**kwargs (dict): Arbitrary keyword arguments.
19802003
19812004
Returns:
19822005
bool: On success, `True` is returned.
@@ -1985,14 +2008,23 @@ def answer_pre_checkout_query(self, pre_checkout_query_id, ok, error_message=Non
19852008
:class:`telegram.TelegramError`
19862009
19872010
"""
1988-
url = '{0]/answerPreCheckoutQuery'.format(self.base_url)
2011+
2012+
if not (ok ^ (error_message is None)):
2013+
raise TelegramError(
2014+
'answerPreCheckoutQuery: If ok is True, there should '
2015+
'not be error_message; if ok is False, error_message '
2016+
'should not be empty')
2017+
2018+
url_ = '{0}/answerPreCheckoutQuery'.format(self.base_url)
19892019

19902020
data = {'pre_checkout_query_id': pre_checkout_query_id, 'ok': ok}
19912021

19922022
if error_message is not None:
19932023
data['error_message'] = error_message
19942024

1995-
return url, data
2025+
result = self._request.post(url_, data, timeout=timeout)
2026+
2027+
return result
19962028

19972029
@staticmethod
19982030
def de_json(data, bot):

telegram/ext/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@
3333
from .stringregexhandler import StringRegexHandler
3434
from .typehandler import TypeHandler
3535
from .conversationhandler import ConversationHandler
36+
from .precheckoutqueryhandler import PreCheckoutQueryHandler
37+
from .shippingqueryhandler import ShippingQueryHandler
3638

3739
__all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
3840
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
3941
'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler',
40-
'StringRegexHandler', 'TypeHandler', 'ConversationHandler')
42+
'StringRegexHandler', 'TypeHandler', 'ConversationHandler',
43+
'PreCheckoutQueryHandler', 'ShippingQueryHandler')
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
#
3+
# A library that provides a Python interface to the Telegram Bot API
4+
# Copyright (C) 2015-2017
5+
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser Public License
18+
# along with this program. If not, see [http://www.gnu.org/licenses/].
19+
""" This module contains the PreCheckoutQueryHandler class """
20+
21+
from telegram import Update
22+
from .handler import Handler
23+
24+
25+
class PreCheckoutQueryHandler(Handler):
26+
"""
27+
Handler class to handle Telegram PreCheckout callback queries.
28+
29+
Args:
30+
callback (function): A function that takes ``bot, update`` as
31+
positional arguments. It will be called when the ``check_update``
32+
has determined that an update should be processed by this handler.
33+
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
34+
``update_queue`` will be passed to the callback function. It will be the ``Queue``
35+
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
36+
be used to insert updates. Default is ``False``.
37+
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
38+
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
39+
instance created by the ``Updater`` which can be used to schedule new jobs.
40+
Default is ``False``.
41+
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
42+
``user_data`` will be passed to the callback function. It will be a ``dict`` you
43+
can use to keep any data related to the user that sent the update. For each update of
44+
the same user, it will be the same ``dict``. Default is ``False``.
45+
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
46+
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
47+
can use to keep any data related to the chat that the update was sent in.
48+
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
49+
"""
50+
51+
def __init__(self,
52+
callback,
53+
pass_update_queue=False,
54+
pass_job_queue=False,
55+
pass_user_data=False,
56+
pass_chat_data=False):
57+
super(PreCheckoutQueryHandler, self).__init__(
58+
callback,
59+
pass_update_queue=pass_update_queue,
60+
pass_job_queue=pass_job_queue,
61+
pass_user_data=pass_user_data,
62+
pass_chat_data=pass_chat_data)
63+
64+
def check_update(self, update):
65+
return isinstance(update, Update) and update.pre_checkout_query
66+
67+
def handle_update(self, update, dispatcher):
68+
optional_args = self.collect_optional_args(dispatcher, update)
69+
return self.callback(dispatcher.bot, update, **optional_args)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
#
3+
# A library that provides a Python interface to the Telegram Bot API
4+
# Copyright (C) 2015-2017
5+
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser Public License
18+
# along with this program. If not, see [http://www.gnu.org/licenses/].
19+
""" This module contains the ShippingQueryHandler class """
20+
21+
from telegram import Update
22+
from .handler import Handler
23+
24+
25+
class ShippingQueryHandler(Handler):
26+
"""
27+
Handler class to handle Telegram shipping callback queries.
28+
29+
Args:
30+
callback (function): A function that takes ``bot, update`` as
31+
positional arguments. It will be called when the ``check_update``
32+
has determined that an update should be processed by this handler.
33+
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
34+
``update_queue`` will be passed to the callback function. It will be the ``Queue``
35+
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
36+
be used to insert updates. Default is ``False``.
37+
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
38+
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
39+
instance created by the ``Updater`` which can be used to schedule new jobs.
40+
Default is ``False``.
41+
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
42+
``user_data`` will be passed to the callback function. It will be a ``dict`` you
43+
can use to keep any data related to the user that sent the update. For each update of
44+
the same user, it will be the same ``dict``. Default is ``False``.
45+
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
46+
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
47+
can use to keep any data related to the chat that the update was sent in.
48+
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
49+
"""
50+
51+
def __init__(self,
52+
callback,
53+
pass_update_queue=False,
54+
pass_job_queue=False,
55+
pass_user_data=False,
56+
pass_chat_data=False):
57+
super(ShippingQueryHandler, self).__init__(
58+
callback,
59+
pass_update_queue=pass_update_queue,
60+
pass_job_queue=pass_job_queue,
61+
pass_user_data=pass_user_data,
62+
pass_chat_data=pass_chat_data)
63+
64+
def check_update(self, update):
65+
return isinstance(update, Update) and update.shipping_query
66+
67+
def handle_update(self, update, dispatcher):
68+
optional_args = self.collect_optional_args(dispatcher, update)
69+
return self.callback(dispatcher.bot, update, **optional_args)

telegram/precheckoutquery.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class PreCheckoutQuery(TelegramObject):
3535
invoice_payload (str): Bot specified invoice payload
3636
shipping_option_id (Optional[str]): Identifier of the shipping option chosen by the user
3737
order_info (Optional[:class:`telegram.OrderInfo`]): Order info provided by the user
38+
bot (Optional[Bot]): The Bot to use for instance methods
3839
**kwargs (dict): Arbitrary keyword arguments.
3940
4041
"""
@@ -47,6 +48,7 @@ def __init__(self,
4748
invoice_payload,
4849
shipping_option_id=None,
4950
order_info=None,
51+
bot=None,
5052
**kwargs):
5153
self.id = id
5254
self.from_user = from_user
@@ -56,6 +58,8 @@ def __init__(self,
5658
self.shipping_option_id = shipping_option_id
5759
self.order_info = order_info
5860

61+
self.bot = bot
62+
5963
self._id_attrs = (self.id,)
6064

6165
@staticmethod
@@ -88,3 +92,9 @@ def to_dict(self):
8892
data['from'] = data.pop('from_user', None)
8993

9094
return data
95+
96+
def answer(self, *args, **kwargs):
97+
"""
98+
Shortcut for ``bot.answerPreCheckoutQuery(update.pre_checkout_query.id, *args, **kwargs)``
99+
"""
100+
return self.bot.answerPreCheckoutQuery(self.id, *args, **kwargs)

telegram/shippingquery.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,19 @@ class ShippingQuery(TelegramObject):
3232
from_user (:class:`telegram.User`): User who sent the query
3333
invoice_payload (str): Bot specified invoice payload
3434
shipping_address (:class:`telegram.ShippingQuery`): User specified shipping address
35+
bot (Optional[Bot]): The Bot to use for instance methods
3536
**kwargs (dict): Arbitrary keyword arguments.
3637
3738
"""
3839

39-
def __init__(self, id, from_user, invoice_payload, shipping_address, **kwargs):
40+
def __init__(self, id, from_user, invoice_payload, shipping_address, bot=None, **kwargs):
4041
self.id = id
4142
self.from_user = from_user
4243
self.invoice_payload = invoice_payload
4344
self.shipping_address = shipping_address
4445

46+
self.bot = bot
47+
4548
self._id_attrs = (self.id,)
4649

4750
@staticmethod
@@ -74,3 +77,7 @@ def to_dict(self):
7477
data['from'] = data.pop('from_user', None)
7578

7679
return data
80+
81+
def answer(self, *args, **kwargs):
82+
"""Shortcut for ``bot.answerShippingQuery(update.shipping_query.id, *args, **kwargs)``"""
83+
return self.bot.answerShippingQuery(self.id, *args, **kwargs)

0 commit comments

Comments
 (0)