Merge branch 'master' of github.com:python-telegram-bot/python-telegram-bot

This commit is contained in:
Jannes Höke 2017-06-16 04:16:45 +02:00
commit 845312da59
12 changed files with 212 additions and 63 deletions

View file

@ -12,7 +12,7 @@ Setting things up
.. code-block:: bash
$ git clone https://github.com/<your username>/python-telegram-bot
$ git clone https://github.com/<your username>/python-telegram-bot --recursive
$ cd python-telegram-bot
3. Add a track to the original repository:

View file

@ -15,6 +15,7 @@ Contributors
The following wonderful people contributed directly or indirectly to this project:
- `Alateas <https://github.com/alateas>`_
- `Avanatiker <https://github.com/Avanatiker>`_
- `Anton Tagunov <https://github.com/anton-tagunov>`_
- `Balduro <https://github.com/Balduro>`_
@ -50,6 +51,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Pieter Schutz <https://github.com/eldinnie>`_
- `Rahiel Kasim <https://github.com/rahiel>`_
- `Joscha Götzer <https://github.com/Rostgnom>`_
- `Sascha <https://github.com/saschalalala>`_
- `Shelomentsev D <https://github.com/shelomentsevd>`_
- `sooyhwang <https://github.com/sooyhwang>`_
- `thodnev <https://github.com/thodnev>`_

View file

@ -0,0 +1,146 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Basic example for a bot that can receive payment from user.
# This program is dedicated to the public domain under the CC0 license.
from telegram import (LabeledPrice, ShippingOption)
from telegram.ext import (Updater, CommandHandler, MessageHandler,
Filters, PreCheckoutQueryHandler, ShippingQueryHandler)
import logging
# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
def error(bot, update, error):
logger.warn('Update "%s" caused error "%s"' % (update, error))
def start_callback(bot, update):
msg = "Use /shipping to get an invoice for shipping-payment, "
msg += "or /noshipping for an invoice without shipping."
update.message.reply_text(msg)
def start_with_shipping_callback(bot, update):
chat_id = update.message.chat_id
title = "Payment Example"
description = "Payment Example using python-telegram-bot"
# select a payload just for you to recognize its the donation from your bot
payload = "Custom-Payload"
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
provider_token = "PROVIDER_TOKEN"
start_parameter = "test-payment"
currency = "USD"
# price in dollars
price = 1
# price * 100 so as to include 2 d.p.
# check https://core.telegram.org/bots/payments#supported-currencies for more details
prices = [LabeledPrice("Test", price * 100)]
# optionally pass need_name=True, need_phone_number=True,
# need_email=True, need_shipping_address=True, is_flexible=True
bot.sendInvoice(chat_id, title, description, payload,
provider_token, start_parameter, currency, prices,
need_name=True, need_phone_number=True,
need_email=True, need_shipping_address=True, is_flexible=True)
def start_without_shipping_callback(bot, update):
chat_id = update.message.chat_id
title = "Payment Example"
description = "Payment Example using python-telegram-bot"
# select a payload just for you to recognize its the donation from your bot
payload = "Custom-Payload"
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
provider_token = "PROVIDER_TOKEN"
start_parameter = "test-payment"
currency = "USD"
# price in dollars
price = 1
# price * 100 so as to include 2 d.p.
prices = [LabeledPrice("Test", price * 100)]
# optionally pass need_name=True, need_phone_number=True,
# need_email=True, need_shipping_address=True, is_flexible=True
bot.sendInvoice(chat_id, title, description, payload,
provider_token, start_parameter, currency, prices)
def shipping_callback(bot, update):
query = update.shipping_query
# check the payload, is this from your bot?
if query.invoice_payload != 'Custom-Payload':
# answer False pre_checkout_query
bot.answer_shipping_query(shipping_query_id=query.id, ok=False,
error_message="Something went wrong...")
return
else:
options = list()
# a single LabeledPrice
options.append(ShippingOption('1', 'Shipping Option A', [LabeledPrice('A', 100)]))
# an array of LabeledPrice objects
price_list = [LabeledPrice('B1', 150), LabeledPrice('B2', 200)]
options.append(ShippingOption('2', 'Shipping Option B', price_list))
bot.answer_shipping_query(shipping_query_id=query.id, ok=True,
shipping_options=options)
# after (optional) shipping, it's the pre-checkout
def precheckout_callback(bot, update):
query = update.pre_checkout_query
# check the payload, is this from your bot?
if query.invoice_payload != 'Custom-Payload':
# answer False pre_checkout_query
bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=False,
error_message="Something went wrong...")
else:
bot.answer_pre_checkout_query(pre_checkout_query_id=query.id, ok=True)
# finally, after contacting to the payment provider...
def successful_payment_callback(bot, update):
# do something after successful receive of payment?
update.message.reply_text("Thank you for your payment!")
def main():
# Create the EventHandler and pass it your bot's token.
updater = Updater(token="BOT_TOKEN")
# Get the dispatcher to register handlers
dp = updater.dispatcher
# simple start function
dp.add_handler(CommandHandler("start", start_callback))
# Add command handler to start the payment invoice
dp.add_handler(CommandHandler("shipping", start_with_shipping_callback))
dp.add_handler(CommandHandler("noshipping", start_without_shipping_callback))
# Optional handler if your product requires shipping
dp.add_handler(ShippingQueryHandler(shipping_callback))
# Pre-checkout handler to final check
dp.add_handler(PreCheckoutQueryHandler(precheckout_callback))
# Success! Notify your user!
dp.add_handler(MessageHandler(Filters.successful_payment, successful_payment_callback))
# log all errors
dp.add_error_handler(error)
# Start the Bot
updater.start_polling()
# Run the bot until you press Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__':
main()

View file

@ -85,7 +85,7 @@ class Bot(TelegramObject):
@functools.wraps(func)
def decorator(self, *args, **kwargs):
if not self.bot:
self.getMe()
self.get_me()
result = func(self, *args, **kwargs)
return result
@ -443,7 +443,7 @@ class Bot(TelegramObject):
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
timeout=20.,
timeout=timeout,
**kwargs)
@log
@ -1975,7 +1975,7 @@ class Bot(TelegramObject):
data = {'shipping_query_id': shipping_query_id, 'ok': ok}
if ok is True:
data['shipping_options'] = shipping_options
data['shipping_options'] = [option.to_dict() for option in shipping_options]
if error_message is not None:
data['error_message'] = error_message
@ -2009,7 +2009,7 @@ class Bot(TelegramObject):
"""
if not (ok ^ (error_message is None)):
if not (ok ^ (error_message is not None)):
raise TelegramError(
'answerPreCheckoutQuery: If ok is True, there should '
'not be error_message; if ok is False, error_message '

View file

@ -89,29 +89,29 @@ class Chat(TelegramObject):
return Chat(bot=bot, **data)
def send_action(self, *args, **kwargs):
"""Shortcut for ``bot.sendChatAction(update.message.chat.id, *args, **kwargs)``"""
return self.bot.sendChatAction(self.id, *args, **kwargs)
"""Shortcut for ``bot.send_chat_action(update.message.chat.id, *args, **kwargs)``"""
return self.bot.send_chat_action(self.id, *args, **kwargs)
def leave(self, *args, **kwargs):
"""Shortcut for ``bot.leaveChat(update.message.chat.id, *args, **kwargs)``"""
return self.bot.leaveChat(self.id, *args, **kwargs)
"""Shortcut for ``bot.leave_chat(update.message.chat.id, *args, **kwargs)``"""
return self.bot.leave_chat(self.id, *args, **kwargs)
def get_administrators(self, *args, **kwargs):
"""Shortcut for ``bot.getChatAdministrators(update.message.chat.id, *args, **kwargs)``"""
return self.bot.getChatAdministrators(self.id, *args, **kwargs)
"""Shortcut for ``bot.get_chat_administrators(update.message.chat.id, *args, **kwargs)``"""
return self.bot.get_chat_administrators(self.id, *args, **kwargs)
def get_members_count(self, *args, **kwargs):
"""Shortcut for ``bot.getChatMembersCount(update.message.chat.id, *args, **kwargs)``"""
return self.bot.getChatMembersCount(self.id, *args, **kwargs)
"""Shortcut for ``bot.get_chat_members_count(update.message.chat.id, *args, **kwargs)``"""
return self.bot.get_chat_members_count(self.id, *args, **kwargs)
def get_member(self, *args, **kwargs):
"""Shortcut for ``bot.getChatMember(update.message.chat.id, *args, **kwargs)``"""
return self.bot.getChatMember(self.id, *args, **kwargs)
"""Shortcut for ``bot.get_chat_member(update.message.chat.id, *args, **kwargs)``"""
return self.bot.get_chat_member(self.id, *args, **kwargs)
def kick_member(self, *args, **kwargs):
"""Shortcut for ``bot.kickChatMember(update.message.chat.id, *args, **kwargs)``"""
return self.bot.kickChatMember(self.id, *args, **kwargs)
"""Shortcut for ``bot.kick_chat_member(update.message.chat.id, *args, **kwargs)``"""
return self.bot.kick_chat_member(self.id, *args, **kwargs)
def unban_member(self, *args, **kwargs):
"""Shortcut for ``bot.unbanChatMember(update.message.chat.id, *args, **kwargs)``"""
return self.bot.unbanChatMember(self.id, *args, **kwargs)
"""Shortcut for ``bot.unban_chat_member(update.message.chat.id, *args, **kwargs)``"""
return self.bot.unban_chat_member(self.id, *args, **kwargs)

View file

@ -264,7 +264,7 @@ class Updater(object):
while self.running:
try:
updates = self.bot.getUpdates(
updates = self.bot.get_updates(
self.last_update_id,
timeout=timeout,
read_latency=read_latency,
@ -367,11 +367,11 @@ class Updater(object):
try:
if clean:
# Disable webhook for cleaning
self.bot.deleteWebhook()
self.bot.delete_webhook()
self._clean_updates()
sleep(1)
self.bot.setWebhook(
self.bot.set_webhook(
url=webhook_url, certificate=cert, allowed_updates=allowed_updates)
except (Unauthorized, InvalidToken):
raise
@ -390,9 +390,9 @@ class Updater(object):
def _clean_updates(self):
self.logger.debug('Cleaning updates from Telegram server')
updates = self.bot.getUpdates()
updates = self.bot.get_updates()
while updates:
updates = self.bot.getUpdates(updates[-1].update_id + 1)
updates = self.bot.get_updates(updates[-1].update_id + 1)
def stop(self):
"""

View file

@ -91,5 +91,5 @@ class InlineQuery(TelegramObject):
return data
def answer(self, *args, **kwargs):
"""Shortcut for ``bot.answerInlineQuery(update.inline_query.id, *args, **kwargs)``"""
return self.bot.answerInlineQuery(self.id, *args, **kwargs)
"""Shortcut for ``bot.answer_inline_query(update.inline_query.id, *args, **kwargs)``"""
return self.bot.answer_inline_query(self.id, *args, **kwargs)

View file

@ -328,7 +328,7 @@ class Message(TelegramObject):
def reply_text(self, *args, **kwargs):
"""
Shortcut for ``bot.sendMessage(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_message(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the message is sent as an actual reply to
@ -337,11 +337,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendMessage(self.chat_id, *args, **kwargs)
return self.bot.send_message(self.chat_id, *args, **kwargs)
def reply_photo(self, *args, **kwargs):
"""
Shortcut for ``bot.sendPhoto(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_photo(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the photo is sent as an actual reply to
@ -354,11 +354,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendPhoto(self.chat_id, *args, **kwargs)
return self.bot.send_photo(self.chat_id, *args, **kwargs)
def reply_audio(self, *args, **kwargs):
"""
Shortcut for ``bot.sendAudio(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_audio(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the audio is sent as an actual reply to
@ -371,11 +371,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendAudio(self.chat_id, *args, **kwargs)
return self.bot.send_audio(self.chat_id, *args, **kwargs)
def reply_document(self, *args, **kwargs):
"""
Shortcut for ``bot.sendDocument(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_document(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the document is sent as an actual reply to
@ -388,11 +388,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendDocument(self.chat_id, *args, **kwargs)
return self.bot.send_document(self.chat_id, *args, **kwargs)
def reply_sticker(self, *args, **kwargs):
"""
Shortcut for ``bot.sendSticker(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_sticker(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the sticker is sent as an actual reply to
@ -405,11 +405,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendSticker(self.chat_id, *args, **kwargs)
return self.bot.send_sticker(self.chat_id, *args, **kwargs)
def reply_video(self, *args, **kwargs):
"""
Shortcut for ``bot.sendVideo(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_video(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the video is sent as an actual reply to
@ -422,7 +422,7 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendVideo(self.chat_id, *args, **kwargs)
return self.bot.send_video(self.chat_id, *args, **kwargs)
def reply_video_note(self, *args, **kwargs):
"""
@ -443,7 +443,7 @@ class Message(TelegramObject):
def reply_voice(self, *args, **kwargs):
"""
Shortcut for ``bot.sendVoice(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_voice(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the voice is sent as an actual reply to
@ -456,11 +456,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendVoice(self.chat_id, *args, **kwargs)
return self.bot.send_voice(self.chat_id, *args, **kwargs)
def reply_location(self, *args, **kwargs):
"""
Shortcut for ``bot.sendLocation(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_location(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the location is sent as an actual reply to
@ -473,11 +473,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendLocation(self.chat_id, *args, **kwargs)
return self.bot.send_location(self.chat_id, *args, **kwargs)
def reply_venue(self, *args, **kwargs):
"""
Shortcut for ``bot.sendVenue(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_venue(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the venue is sent as an actual reply to
@ -490,11 +490,11 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendVenue(self.chat_id, *args, **kwargs)
return self.bot.send_venue(self.chat_id, *args, **kwargs)
def reply_contact(self, *args, **kwargs):
"""
Shortcut for ``bot.sendContact(update.message.chat_id, *args, **kwargs)``
Shortcut for ``bot.send_contact(update.message.chat_id, *args, **kwargs)``
Keyword Args:
quote (Optional[bool]): If set to ``True``, the contact is sent as an actual reply to
@ -507,12 +507,12 @@ class Message(TelegramObject):
"""
self._quote(kwargs)
return self.bot.sendContact(self.chat_id, *args, **kwargs)
return self.bot.send_contact(self.chat_id, *args, **kwargs)
def forward(self, chat_id, disable_notification=False):
"""Shortcut for
>>> bot.forwardMessage(chat_id=chat_id,
>>> bot.forward_message(chat_id=chat_id,
... from_chat_id=update.message.chat_id,
... disable_notification=disable_notification,
... message_id=update.message.message_id)
@ -521,7 +521,7 @@ class Message(TelegramObject):
:class:`telegram.Message`: On success, instance representing the message forwarded.
"""
return self.bot.forwardMessage(
return self.bot.forward_message(
chat_id=chat_id,
from_chat_id=self.chat_id,
disable_notification=disable_notification,
@ -531,7 +531,7 @@ class Message(TelegramObject):
"""
Shortcut for
>>> bot.editMessageText(chat_id=message.chat_id,
>>> bot.edit_message_text(chat_id=message.chat_id,
... message_id=message.message_id,
... *args, **kwargs)
@ -548,7 +548,7 @@ class Message(TelegramObject):
"""
Shortcut for
>>> bot.editMessageCaption(chat_id=message.chat_id,
>>> bot.edit_message_caption(chat_id=message.chat_id,
... message_id=message.message_id,
... *args, **kwargs)
@ -564,7 +564,7 @@ class Message(TelegramObject):
"""
Shortcut for
>>> bot.editReplyMarkup(chat_id=message.chat_id,
>>> bot.edit_message_reply_markup(chat_id=message.chat_id,
... message_id=message.message_id,
... *args, **kwargs)

View file

@ -95,6 +95,7 @@ class PreCheckoutQuery(TelegramObject):
def answer(self, *args, **kwargs):
"""
Shortcut for ``bot.answerPreCheckoutQuery(update.pre_checkout_query.id, *args, **kwargs)``
Shortcut for
``bot.answer_pre_checkout_query(update.pre_checkout_query.id, *args, **kwargs)``
"""
return self.bot.answerPreCheckoutQuery(self.id, *args, **kwargs)
return self.bot.answer_pre_checkout_query(self.id, *args, **kwargs)

View file

@ -79,5 +79,5 @@ class ShippingQuery(TelegramObject):
return data
def answer(self, *args, **kwargs):
"""Shortcut for ``bot.answerShippingQuery(update.shipping_query.id, *args, **kwargs)``"""
return self.bot.answerShippingQuery(self.id, *args, **kwargs)
"""Shortcut for ``bot.answer_shipping_query(update.shipping_query.id, *args, **kwargs)``"""
return self.bot.answer_shipping_query(self.id, *args, **kwargs)

View file

@ -96,9 +96,9 @@ class User(TelegramObject):
def get_profile_photos(self, *args, **kwargs):
"""
Shortcut for ``bot.getUserProfilePhotos(update.message.from_user.id, *args, **kwargs)``
Shortcut for ``bot.get_user_profile_photos(update.message.from_user.id, *args, **kwargs)``
"""
return self.bot.getUserProfilePhotos(self.id, *args, **kwargs)
return self.bot.get_user_profile_photos(self.id, *args, **kwargs)
@staticmethod
def de_list(data, bot):

View file

@ -944,7 +944,7 @@ class MockBot(object):
self.edited = edited
self.username = "MockBot"
def mockUpdate(self, text):
def mock_update(self, text):
message = Message(0, User(0, 'Testuser'), None, Chat(0, Chat.GROUP), bot=self)
message.text = text
update = Update(0)
@ -956,7 +956,7 @@ class MockBot(object):
return update
def setWebhook(self, url=None, certificate=None, allowed_updates=None):
def set_webhook(self, url=None, certificate=None, allowed_updates=None):
if self.bootstrap_retries is None:
return
@ -964,7 +964,7 @@ class MockBot(object):
self.bootstrap_attempts += 1
raise self.bootstrap_err
def deleteWebhook(self):
def delete_webhook(self):
if self.bootstrap_retries is None:
return
@ -972,7 +972,7 @@ class MockBot(object):
self.bootstrap_attempts += 1
raise self.bootstrap_err
def getUpdates(self,
def get_updates(self,
offset=None,
limit=100,
timeout=0,
@ -984,10 +984,10 @@ class MockBot(object):
raise TelegramError('Test Error 2')
elif self.send_messages >= 2:
self.send_messages -= 2
return self.mockUpdate(self.text), self.mockUpdate(self.text)
return self.mock_update(self.text), self.mock_update(self.text)
elif self.send_messages == 1:
self.send_messages -= 1
return self.mockUpdate(self.text),
return self.mock_update(self.text),
else:
return []