mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-27 19:54:38 +00:00
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5583190b8 | |||
| faddb92395 | |||
| 9b5e014a0a | |||
| 845312da59 | |||
| 3863b4f371 | |||
| 25912dca6e | |||
| 6877886f7d | |||
| d16d38530c | |||
| c7ed87d475 | |||
| a68e0ad044 | |||
| ad603bd2f9 | |||
| 179fc141bb | |||
| da8a3cee44 | |||
| bc3669fa4b | |||
| 7def2c53e1 | |||
| 09230e6e84 | |||
| 011e321583 | |||
| 0afb38f45c | |||
| 4247dc0e21 | |||
| 896392d01e | |||
| 61c5d6ff08 | |||
| aa1c4e0e02 | |||
| 92183a5bbc | |||
| 87b096c7f9 | |||
| 3329d15691 | |||
| 0fb00c4c8b | |||
| 2680740316 | |||
| b6ba66ba8e | |||
| eaf765dcbc | |||
| f735a37828 | |||
| e9d08c6f7a | |||
| c0e3453a62 | |||
| 90e9e32632 | |||
| 1e3e8973ba | |||
| 0ed997cc53 | |||
| 760737345d | |||
| 137ffe2e73 | |||
| c4b78673a3 | |||
| ee1cf6b9b0 | |||
| c15371e8c0 | |||
| f66076b06c | |||
| 5b1252ac2d | |||
| 647059735c | |||
| d0f6860bac | |||
| d98b18d1e3 | |||
| 9d6c394b02 | |||
| 1951d6fdcd | |||
| 84b59c8cb2 | |||
| b46bdf5304 | |||
| cd24bb4ba5 | |||
| ae33d33580 | |||
| 706f79fa99 | |||
| a5bfc52326 | |||
| 858684ab64 | |||
| f4c6197c5f | |||
| a7044562af | |||
| 27a4fa8dba | |||
| a41ee3b040 | |||
| 8499dcc33c | |||
| ff897ce9ef | |||
| f314915954 | |||
| 1bf0078573 | |||
| 1210e4ef04 | |||
| 05ed693fb6 | |||
| 18822d1396 | |||
| 73ac259721 | |||
| 96171112bf | |||
| 27238c52e2 | |||
| 43f4128b31 | |||
| 1142953108 | |||
| 1e250f2415 | |||
| 8f2f29c7d4 | |||
| 3767d26fc8 | |||
| a78f72c086 | |||
| cc03649f1c | |||
| ee057e76ef | |||
| 2c05b03fba | |||
| 630b63ec10 | |||
| 23b37c9ea4 | |||
| 01430a24a5 | |||
| acda19b7e7 | |||
| 48fa3d975b | |||
| d220ff4e38 | |||
| 5a15d1b5d6 | |||
| ad347b5c02 | |||
| 017fdeaae8 | |||
| ba6c4fd517 | |||
| 99ecac5649 | |||
| 1c4c228cf1 | |||
| 2e89e21261 | |||
| 7583fa9d65 | |||
| 2dd5290ec2 | |||
| 41299244b7 | |||
| 0e2bcf28a6 | |||
| 2746ab77e5 | |||
| ae39c902ed | |||
| 65929a0813 | |||
| 4426eb0c61 | |||
| d4f2f2e077 | |||
| 73d75b964a | |||
| 45897048aa | |||
| 76db279624 | |||
| a97da5cb20 | |||
| 9f6ec125b9 | |||
| 5f96c507b9 | |||
| 402e1381bb | |||
| b276b06b31 | |||
| b69ecc3015 | |||
| 77f06888cb | |||
| 834c1ab3c5 | |||
| c78d697b0e | |||
| 2929c76248 | |||
| 034bcf0895 | |||
| 8be57198b4 | |||
| 8e62b02ff6 |
@@ -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:
|
||||
|
||||
@@ -65,6 +65,7 @@ target/
|
||||
# unitests files
|
||||
telegram.mp3
|
||||
telegram.mp4
|
||||
telegram2.mp4
|
||||
telegram.ogg
|
||||
telegram.png
|
||||
telegram.webp
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[submodule "telegram/vendor/urllib3"]
|
||||
path = telegram/vendor/urllib3
|
||||
path = telegram/vendor/ptb_urllib3
|
||||
url = https://github.com/python-telegram-bot/urllib3.git
|
||||
branch = ptb
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
hooks:
|
||||
- id: yapf
|
||||
files: ^(telegram|tests)/.*\.py$
|
||||
args:
|
||||
- --diff
|
||||
- repo: git://github.com/pre-commit/pre-commit-hooks
|
||||
sha: 18d7035de5388cc7775be57f529c154bf541aab9
|
||||
hooks:
|
||||
|
||||
@@ -18,5 +18,6 @@ install:
|
||||
script:
|
||||
- nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/ tests
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 3.5 ]]; then pre-commit run --all-files; fi
|
||||
- python ./setup.py bdist_dumb
|
||||
after_success:
|
||||
coveralls
|
||||
|
||||
@@ -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>`_
|
||||
@@ -24,11 +25,13 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Eli Gao <https://github.com/eligao>`_
|
||||
- `ErgoZ Riftbit Vaper <https://github.com/ergoz>`_
|
||||
- `Eugene Lisitsky <https://github.com/lisitsky>`_
|
||||
- `Eugenio Panadero <https://github.com/azogue>`_
|
||||
- `evgfilim1 <https://github.com/evgfilim1>`_
|
||||
- `franciscod <https://github.com/franciscod>`_
|
||||
- `Hugo Damer <https://github.com/HakimusGIT>`_
|
||||
- `Jacob Bom <https://github.com/bomjacob>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `jeffffc <https://github.com/jeffffc>`_
|
||||
- `jh0ker <https://github.com/jh0ker>`_
|
||||
- `John Yong <https://github.com/whipermr5>`_
|
||||
- `jossalgon <https://github.com/jossalgon>`_
|
||||
@@ -48,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>`_
|
||||
|
||||
+28
@@ -2,6 +2,33 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
**2017-06-18**
|
||||
|
||||
*Released 6.1.0*
|
||||
|
||||
- Fully support Bot API 3.0
|
||||
- Add more fine-grained filters for status updates
|
||||
- Bug fixes and other improvements
|
||||
|
||||
**2017-05-29**
|
||||
|
||||
*Released 6.0.3*
|
||||
|
||||
- Faulty PyPI release
|
||||
|
||||
**2017-05-29**
|
||||
|
||||
*Released 6.0.2*
|
||||
|
||||
- Avoid confusion with user's ``urllib3`` by renaming vendored ``urllib3`` to ``ptb_urllib3``
|
||||
|
||||
**2017-05-19**
|
||||
|
||||
*Released 6.0.1*
|
||||
|
||||
- Add support for ``User.language_code``
|
||||
- Fix ``Message.text_html`` and ``Message.text_markdown`` for messages with emoji
|
||||
|
||||
**2017-05-19**
|
||||
|
||||
*Released 6.0.0*
|
||||
@@ -73,6 +100,7 @@ Changes
|
||||
|
||||
- Rework ``JobQueue``
|
||||
- Introduce ``ConversationHandler``
|
||||
- Introduce ``telegram.constants`` - https://github.com/python-telegram-bot/python-telegram-bot/pull/342
|
||||
|
||||
**2016-07-12**
|
||||
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ make the development of bots easy and straightforward. These classes are contain
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
As of **4. Dec 2016**, all types and methods of the Telegram Bot API are supported.
|
||||
As of **18. June 2017**, all types and methods of the Telegram Bot API 3.0 are supported.
|
||||
|
||||
==========
|
||||
Installing
|
||||
|
||||
+22
-5
@@ -11,7 +11,6 @@
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
@@ -25,7 +24,7 @@ sys.path.insert(0, os.path.abspath('../..'))
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
needs_sphinx = '1.5.4' # fixes issues with autodoc-skip-member and napoleon
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
@@ -59,9 +58,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '6.0' # telegram.__version__[:3]
|
||||
version = '6.1' # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '6.0.0' # telegram.__version__
|
||||
release = '6.1.0' # telegram.__version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -136,7 +135,7 @@ html_logo = 'ptb-logo-orange.png'
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
html_favicon = 'ptb-logo-orange.ico'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
@@ -289,3 +288,21 @@ texinfo_documents = [
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
# -- script stuff --------------------------------------------------------
|
||||
|
||||
import inspect
|
||||
|
||||
|
||||
def autodoc_skip_member(app, what, name, obj, skip, options):
|
||||
try:
|
||||
if inspect.getmodule(obj).__name__.startswith('telegram') and inspect.isfunction(obj):
|
||||
if name.lower() != name:
|
||||
return True
|
||||
except AttributeError:
|
||||
pass
|
||||
# Return None so napoleon can handle it
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.connect('autodoc-skip-member', autodoc_skip_member)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
@@ -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()
|
||||
@@ -18,11 +18,6 @@ def requirements():
|
||||
|
||||
|
||||
packages = find_packages(exclude=['tests*'])
|
||||
packages.extend(['telegram.vendor.urllib3.urllib3',
|
||||
'telegram.vendor.urllib3.urllib3.packages', 'telegram.vendor.urllib3.urllib3.packages.ssl_match_hostname',
|
||||
'telegram.vendor.urllib3.urllib3.packages.backports', 'telegram.vendor.urllib3.urllib3.contrib',
|
||||
'telegram.vendor.urllib3.urllib3.util',
|
||||
])
|
||||
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as fd:
|
||||
fn = os.path.join('telegram', 'version.py')
|
||||
|
||||
+11
-3
@@ -22,8 +22,6 @@ from sys import version_info
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'vendor', 'urllib3'))
|
||||
|
||||
from .base import TelegramObject
|
||||
from .user import User
|
||||
from .chat import Chat
|
||||
@@ -52,6 +50,10 @@ from .parsemode import ParseMode
|
||||
from .messageentity import MessageEntity
|
||||
from .animation import Animation
|
||||
from .game import Game
|
||||
from .shippingaddress import ShippingAddress
|
||||
from .orderinfo import OrderInfo
|
||||
from .successfulpayment import SuccessfulPayment
|
||||
from .invoice import Invoice
|
||||
from .message import Message
|
||||
from .inputmessagecontent import InputMessageContent
|
||||
from .callbackquery import CallbackQuery
|
||||
@@ -84,8 +86,13 @@ from .inputtextmessagecontent import InputTextMessageContent
|
||||
from .inputlocationmessagecontent import InputLocationMessageContent
|
||||
from .inputvenuemessagecontent import InputVenueMessageContent
|
||||
from .inputcontactmessagecontent import InputContactMessageContent
|
||||
from .labeledprice import LabeledPrice
|
||||
from .shippingoption import ShippingOption
|
||||
from .precheckoutquery import PreCheckoutQuery
|
||||
from .shippingquery import ShippingQuery
|
||||
from .webhookinfo import WebhookInfo
|
||||
from .gamehighscore import GameHighScore
|
||||
from .videonote import VideoNote
|
||||
from .update import Update
|
||||
from .bot import Bot
|
||||
from .constants import (MAX_MESSAGE_LENGTH, MAX_CAPTION_LENGTH, SUPPORTED_WEBHOOK_PORTS,
|
||||
@@ -115,5 +122,6 @@ __all__ = [
|
||||
'Video', 'Voice', 'MAX_MESSAGE_LENGTH', 'MAX_CAPTION_LENGTH', 'SUPPORTED_WEBHOOK_PORTS',
|
||||
'MAX_FILESIZE_DOWNLOAD', 'MAX_FILESIZE_UPLOAD', 'MAX_MESSAGES_PER_SECOND_PER_CHAT',
|
||||
'MAX_MESSAGES_PER_SECOND', 'MAX_MESSAGES_PER_MINUTE_PER_GROUP', 'WebhookInfo', 'Animation',
|
||||
'Game', 'GameHighScore'
|
||||
'Game', 'GameHighScore', 'VideoNote', 'LabeledPrice', 'SuccessfulPayment', 'ShippingOption',
|
||||
'ShippingAddress', 'PreCheckoutQuery', 'OrderInfo', 'Invoice', 'ShippingQuery'
|
||||
]
|
||||
|
||||
+339
-108
@@ -31,10 +31,45 @@ from telegram.utils.request import Request
|
||||
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
||||
|
||||
|
||||
def info(func):
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
if not self.bot:
|
||||
self.get_me()
|
||||
|
||||
result = func(self, *args, **kwargs)
|
||||
return result
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def log(func):
|
||||
logger = logging.getLogger(func.__module__)
|
||||
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
logger.debug('Entering: %s', func.__name__)
|
||||
result = func(self, *args, **kwargs)
|
||||
logger.debug(result)
|
||||
logger.debug('Exiting: %s', func.__name__)
|
||||
return result
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def message(func):
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
url, data = func(self, *args, **kwargs)
|
||||
return self._message_wrapper(url, data, *args, **kwargs)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class Bot(TelegramObject):
|
||||
"""This object represents a Telegram Bot.
|
||||
|
||||
Attributes:
|
||||
Properties:
|
||||
id (int): Unique identifier for this bot.
|
||||
first_name (str): Bot's first name.
|
||||
last_name (str): Bot's last name.
|
||||
@@ -80,18 +115,6 @@ class Bot(TelegramObject):
|
||||
|
||||
return token
|
||||
|
||||
def info(func):
|
||||
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
if not self.bot:
|
||||
self.getMe()
|
||||
|
||||
result = func(self, *args, **kwargs)
|
||||
return result
|
||||
|
||||
return decorator
|
||||
|
||||
@property
|
||||
@info
|
||||
def id(self):
|
||||
@@ -116,19 +139,6 @@ class Bot(TelegramObject):
|
||||
def name(self):
|
||||
return '@{0}'.format(self.username)
|
||||
|
||||
def log(func):
|
||||
logger = logging.getLogger(func.__module__)
|
||||
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
logger.debug('Entering: %s', func.__name__)
|
||||
result = func(self, *args, **kwargs)
|
||||
logger.debug(result)
|
||||
logger.debug('Exiting: %s', func.__name__)
|
||||
return result
|
||||
|
||||
return decorator
|
||||
|
||||
def _message_wrapper(self, url, data, *args, **kwargs):
|
||||
if kwargs.get('reply_to_message_id'):
|
||||
data['reply_to_message_id'] = kwargs.get('reply_to_message_id')
|
||||
@@ -150,15 +160,6 @@ class Bot(TelegramObject):
|
||||
|
||||
return Message.de_json(result, self)
|
||||
|
||||
def message(func):
|
||||
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
url, data = func(self, *args, **kwargs)
|
||||
return Bot._message_wrapper(self, url, data, *args, **kwargs)
|
||||
|
||||
return decorator
|
||||
|
||||
@log
|
||||
def get_me(self, timeout=None, **kwargs):
|
||||
"""A simple method for testing your bot's auth token.
|
||||
@@ -242,8 +243,7 @@ class Bot(TelegramObject):
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def delete_message(self, chat_id, message_id):
|
||||
def delete_message(self, chat_id, message_id, timeout=None, **kwargs):
|
||||
"""Use this method to delete a message. A message can only be deleted if it was sent less
|
||||
than 48 hours ago. Any such recently sent outgoing message may be deleted. Additionally,
|
||||
if the bot is an administrator in a group chat, it can delete any message. If the bot is
|
||||
@@ -257,6 +257,10 @@ class Bot(TelegramObject):
|
||||
username of the target channel (in the format
|
||||
@channelusername).
|
||||
message_id (int): Unique message identifier.
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
bool: On success, `True` is returned.
|
||||
@@ -269,7 +273,9 @@ class Bot(TelegramObject):
|
||||
|
||||
data = {'chat_id': chat_id, 'message_id': message_id}
|
||||
|
||||
return url, data
|
||||
result = self._request.post(url, data, timeout=timeout)
|
||||
|
||||
return result
|
||||
|
||||
@log
|
||||
@message
|
||||
@@ -315,6 +321,7 @@ class Bot(TelegramObject):
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_photo(self,
|
||||
chat_id,
|
||||
photo,
|
||||
@@ -356,19 +363,10 @@ class Bot(TelegramObject):
|
||||
if caption:
|
||||
data['caption'] = caption
|
||||
|
||||
return self._message_wrapper(
|
||||
url,
|
||||
data,
|
||||
chat_id=chat_id,
|
||||
photo=photo,
|
||||
caption=caption,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_markup=reply_markup,
|
||||
timeout=timeout,
|
||||
**kwargs)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_audio(self,
|
||||
chat_id,
|
||||
audio,
|
||||
@@ -431,22 +429,10 @@ class Bot(TelegramObject):
|
||||
if caption:
|
||||
data['caption'] = caption
|
||||
|
||||
return self._message_wrapper(
|
||||
url,
|
||||
data,
|
||||
chat_id=chat_id,
|
||||
audio=audio,
|
||||
duration=duration,
|
||||
performer=performer,
|
||||
title=title,
|
||||
caption=caption,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_markup=reply_markup,
|
||||
timeout=20.,
|
||||
**kwargs)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_document(self,
|
||||
chat_id,
|
||||
document,
|
||||
@@ -493,18 +479,7 @@ class Bot(TelegramObject):
|
||||
if caption:
|
||||
data['caption'] = caption
|
||||
|
||||
return self._message_wrapper(
|
||||
url,
|
||||
data,
|
||||
chat_id=chat_id,
|
||||
document=document,
|
||||
filename=filename,
|
||||
caption=caption,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_markup=reply_markup,
|
||||
timeout=timeout,
|
||||
**kwargs)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
@@ -549,6 +524,7 @@ class Bot(TelegramObject):
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_video(self,
|
||||
chat_id,
|
||||
video,
|
||||
@@ -595,20 +571,10 @@ class Bot(TelegramObject):
|
||||
if caption:
|
||||
data['caption'] = caption
|
||||
|
||||
return self._message_wrapper(
|
||||
url,
|
||||
data,
|
||||
chat_id=chat_id,
|
||||
video=video,
|
||||
duration=duration,
|
||||
caption=caption,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_markup=reply_markup,
|
||||
timeout=timeout,
|
||||
**kwargs)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_voice(self,
|
||||
chat_id,
|
||||
voice,
|
||||
@@ -658,18 +624,57 @@ class Bot(TelegramObject):
|
||||
if caption:
|
||||
data['caption'] = caption
|
||||
|
||||
return self._message_wrapper(
|
||||
url,
|
||||
data,
|
||||
chat_id=chat_id,
|
||||
voice=voice,
|
||||
duration=duration,
|
||||
caption=caption,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_markup=reply_markup,
|
||||
timeout=timeout,
|
||||
**kwargs)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_video_note(self,
|
||||
chat_id,
|
||||
video_note,
|
||||
duration=None,
|
||||
length=None,
|
||||
disable_notification=False,
|
||||
reply_to_message_id=None,
|
||||
reply_markup=None,
|
||||
timeout=20.,
|
||||
**kwargs):
|
||||
"""As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute
|
||||
long. Use this method to send video messages
|
||||
|
||||
Args:
|
||||
chat_id (int|str): Unique identifier for the message recipient - Chat id.
|
||||
video_note (InputFile|str): Video note to send. Pass a file_id as String to send a
|
||||
video note that exists on the Telegram servers (recommended) or upload a new video.
|
||||
Sending video notes by a URL is currently unsupported
|
||||
duration (Optional[int]): Duration of sent audio in seconds.
|
||||
length (Optional[int]): Video width and height
|
||||
disable_notification (Optional[bool]): Sends the message silently. iOS users will not
|
||||
receive a notification, Android users will receive a notification with no sound.
|
||||
reply_to_message_id (Optional[int]): If the message is a reply, ID of the original
|
||||
message.
|
||||
reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A
|
||||
JSON-serialized object for an inline keyboard, custom reply keyboard, instructions
|
||||
to remove reply keyboard or to force a reply from the user.
|
||||
timeout (Optional[int|float]): Send file timeout (default: 20 seconds).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.TelegramError`
|
||||
|
||||
"""
|
||||
url = '{0}/sendVideoNote'.format(self.base_url)
|
||||
|
||||
data = {'chat_id': chat_id, 'video_note': video_note}
|
||||
|
||||
if duration is not None:
|
||||
data['duration'] = duration
|
||||
if length is not None:
|
||||
data['length'] = length
|
||||
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
@@ -838,8 +843,6 @@ class Bot(TelegramObject):
|
||||
channel (in the format @channelusername).
|
||||
game_short_name (str): Short name of the game, serves as the unique identifier for the
|
||||
game.
|
||||
|
||||
Keyword Args:
|
||||
disable_notification (Optional[bool]): Sends the message silently. iOS users will not
|
||||
receive a notification, Android users will receive a notification with no sound.
|
||||
reply_to_message_id (Optional[int]): If the message is a reply,
|
||||
@@ -850,6 +853,7 @@ class Bot(TelegramObject):
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, the sent message is returned.
|
||||
@@ -865,7 +869,6 @@ class Bot(TelegramObject):
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_chat_action(self, chat_id, action, timeout=None, **kwargs):
|
||||
"""Use this method when you need to tell the user that something is happening on the bot's
|
||||
side. The status is set for 5 seconds or less (when a message arrives from your bot,
|
||||
@@ -892,7 +895,9 @@ class Bot(TelegramObject):
|
||||
|
||||
data = {'chat_id': chat_id, 'action': action}
|
||||
|
||||
return url, data
|
||||
result = self._request.post(url, data, timeout=timeout)
|
||||
|
||||
return result
|
||||
|
||||
@log
|
||||
def answer_inline_query(self,
|
||||
@@ -1638,6 +1643,7 @@ class Bot(TelegramObject):
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
:class: `telegram.WebhookInfo`
|
||||
@@ -1651,6 +1657,8 @@ class Bot(TelegramObject):
|
||||
|
||||
return WebhookInfo.de_json(result, self)
|
||||
|
||||
@log
|
||||
@message
|
||||
def set_game_score(self,
|
||||
user_id,
|
||||
score,
|
||||
@@ -1683,6 +1691,7 @@ class Bot(TelegramObject):
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.Message` or True: The edited message, or if the
|
||||
@@ -1710,12 +1719,9 @@ class Bot(TelegramObject):
|
||||
else:
|
||||
warnings.warn('edit_message is ignored when disable_edit_message is used')
|
||||
|
||||
result = self._request.post(url, data, timeout=timeout)
|
||||
if result is True:
|
||||
return result
|
||||
else:
|
||||
return Message.de_json(result, self)
|
||||
return url, data
|
||||
|
||||
@log
|
||||
def get_game_high_scores(self,
|
||||
user_id,
|
||||
chat_id=None,
|
||||
@@ -1737,6 +1743,7 @@ class Bot(TelegramObject):
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
list[:class:`telegram.GameHighScore`]: Scores of the specified user and several of his
|
||||
@@ -1758,6 +1765,226 @@ class Bot(TelegramObject):
|
||||
|
||||
return [GameHighScore.de_json(hs, self) for hs in result]
|
||||
|
||||
@log
|
||||
@message
|
||||
def send_invoice(self,
|
||||
chat_id,
|
||||
title,
|
||||
description,
|
||||
payload,
|
||||
provider_token,
|
||||
start_parameter,
|
||||
currency,
|
||||
prices,
|
||||
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=False,
|
||||
reply_to_message_id=None,
|
||||
reply_markup=None,
|
||||
timeout=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Use this method to send invoices.
|
||||
|
||||
Args:
|
||||
chat_id (int|str): Unique identifier for the target private chat
|
||||
title (str): Product name
|
||||
description (str): Product description
|
||||
payload (str): Bot-defined invoice payload, 1-128 bytes. This will not be displayed
|
||||
to the user, use for your internal processes.
|
||||
provider_token (str): Payments provider token, obtained via Botfather
|
||||
start_parameter (str): Unique deep-linking parameter that can be used to generate
|
||||
this invoice when used as a start parameter
|
||||
currency (str): Three-letter ISO 4217 currency code
|
||||
prices (List[:class:`telegram.LabeledPrice`]): Price breakdown, a list of components
|
||||
(e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.)
|
||||
photo_url (Optional[str]): URL of the product photo for the invoice. Can be a photo of
|
||||
the goods or a marketing image for a service. People like it better when they
|
||||
see what they are paying for.
|
||||
photo_size (Optional[str]): Photo size
|
||||
photo_width (Optional[int]): Photo width
|
||||
photo_height (Optional[int]): Photo height
|
||||
need_name (Optional[bool]): Pass True, if you require the user's full name to complete
|
||||
the order
|
||||
need_phone_number (Optional[bool]): Pass True, if you require the user's phone number
|
||||
to complete the order
|
||||
need_email (Optional[bool]): Pass True, if you require the user's email to
|
||||
complete the order
|
||||
need_shipping_address (Optional[bool]): Pass True, if you require the user's shipping
|
||||
address to complete the order
|
||||
is_flexible (Optional[bool]): Pass True, if the final price depends on the shipping
|
||||
method
|
||||
disable_notification (Optional[bool]): Sends the message silently. iOS users will not
|
||||
receive a notification, Android users will receive a notification with no sound.
|
||||
reply_to_message_id (Optional[int]): If the message is a reply, ID of the original
|
||||
message.
|
||||
reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options.
|
||||
An inlinekeyboard. If empty, one 'Pay total price' button will be shown. If not
|
||||
empty, the first button must be a Pay button.
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.TelegramError`
|
||||
|
||||
"""
|
||||
url = '{0}/sendInvoice'.format(self.base_url)
|
||||
|
||||
data = {
|
||||
'chat_id': chat_id,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'payload': payload,
|
||||
'provider_token': provider_token,
|
||||
'start_parameter': start_parameter,
|
||||
'currency': currency,
|
||||
'prices': [p.to_dict() for p in prices]
|
||||
}
|
||||
|
||||
if photo_url is not None:
|
||||
data['photo_url'] = photo_url
|
||||
if photo_size is not None:
|
||||
data['photo_size'] = photo_size
|
||||
if photo_width is not None:
|
||||
data['photo_width'] = photo_width
|
||||
if photo_height is not None:
|
||||
data['photo_height'] = photo_height
|
||||
if need_name is not None:
|
||||
data['need_name'] = need_name
|
||||
if need_phone_number is not None:
|
||||
data['need_phone_number'] = need_phone_number
|
||||
if need_email is not None:
|
||||
data['need_email'] = need_email
|
||||
if need_shipping_address is not None:
|
||||
data['need_shipping_address'] = need_shipping_address
|
||||
if is_flexible is not None:
|
||||
data['is_flexible'] = is_flexible
|
||||
|
||||
return url, data
|
||||
|
||||
@log
|
||||
def answer_shipping_query(self,
|
||||
shipping_query_id,
|
||||
ok,
|
||||
shipping_options=None,
|
||||
error_message=None,
|
||||
timeout=None,
|
||||
**kwargs):
|
||||
"""
|
||||
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.
|
||||
|
||||
Args:
|
||||
shipping_query_id (str): Unique identifier for the query to be answered
|
||||
ok (bool): Specify True if delivery to the specified address is possible and False if
|
||||
there are any problems (for example, if delivery to the specified address
|
||||
is not possible)
|
||||
shipping_options (Optional[List[:class:`telegram.ShippingOption`]]): Required if ok is
|
||||
True. A list of available shipping options.
|
||||
error_message (Optional[str]): Required if ok is False. Error message in human readable
|
||||
form that explains why it is impossible to complete the order (e.g. "Sorry,
|
||||
delivery to your desired address is unavailable'). Telegram will display this
|
||||
message to the user.
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
bool: On success, `True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.TelegramError`
|
||||
|
||||
"""
|
||||
|
||||
ok = bool(ok)
|
||||
|
||||
if ok and (shipping_options is None or error_message is not None):
|
||||
raise TelegramError(
|
||||
'answerShippingQuery: If ok is True, shipping_options '
|
||||
'should not be empty and there should not be error_message')
|
||||
|
||||
if not ok and (shipping_options is not None or error_message is None):
|
||||
raise TelegramError(
|
||||
'answerShippingQuery: If ok is False, error_message '
|
||||
'should not be empty and there should not be shipping_options')
|
||||
|
||||
url_ = '{0}/answerShippingQuery'.format(self.base_url)
|
||||
|
||||
data = {'shipping_query_id': shipping_query_id, 'ok': ok}
|
||||
|
||||
if ok:
|
||||
data['shipping_options'] = [option.to_dict() for option in shipping_options]
|
||||
if error_message is not None:
|
||||
data['error_message'] = error_message
|
||||
|
||||
result = self._request.post(url_, data, timeout=timeout)
|
||||
|
||||
return result
|
||||
|
||||
@log
|
||||
def answer_pre_checkout_query(self, pre_checkout_query_id, ok,
|
||||
error_message=None, timeout=None, **kwargs):
|
||||
"""
|
||||
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.
|
||||
|
||||
Args:
|
||||
pre_checkout_query_id (str): Unique identifier for the query to be answered
|
||||
ok (bool): Specify True if everything is alright (goods are available, etc.) and the
|
||||
bot is ready to proceed with the order. Use False if there are any problems.
|
||||
error_message (Optional[str]): Required if ok is False. Error message in human readable
|
||||
form that explains the reason for failure to proceed with the checkout (e.g.
|
||||
"Sorry, somebody just bought the last of our amazing black T-shirts while you were
|
||||
busy filling out your payment details. Please choose a different color or
|
||||
garment!"). Telegram will display this message to the user.
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
Returns:
|
||||
bool: On success, `True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.TelegramError`
|
||||
|
||||
"""
|
||||
|
||||
ok = bool(ok)
|
||||
|
||||
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 '
|
||||
'should not be empty')
|
||||
|
||||
url_ = '{0}/answerPreCheckoutQuery'.format(self.base_url)
|
||||
|
||||
data = {'pre_checkout_query_id': pre_checkout_query_id, 'ok': ok}
|
||||
|
||||
if error_message is not None:
|
||||
data['error_message'] = error_message
|
||||
|
||||
result = self._request.post(url_, data, timeout=timeout)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
data = super(Bot, Bot).de_json(data, bot)
|
||||
@@ -1787,6 +2014,7 @@ class Bot(TelegramObject):
|
||||
sendSticker = send_sticker
|
||||
sendVideo = send_video
|
||||
sendVoice = send_voice
|
||||
sendVideoNote = send_video_note
|
||||
sendLocation = send_location
|
||||
sendVenue = send_venue
|
||||
sendContact = send_contact
|
||||
@@ -1812,3 +2040,6 @@ class Bot(TelegramObject):
|
||||
getWebhookInfo = get_webhook_info
|
||||
setGameScore = set_game_score
|
||||
getGameHighScores = get_game_high_scores
|
||||
sendInvoice = send_invoice
|
||||
answerShippingQuery = answer_shipping_query
|
||||
answerPreCheckoutQuery = answer_pre_checkout_query
|
||||
|
||||
+15
-15
@@ -41,7 +41,7 @@ class Chat(TelegramObject):
|
||||
username(Optional[str]):
|
||||
first_name(Optional[str]):
|
||||
last_name(Optional[str]):
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
bot (Optional[telegram.Bot]): The Bot to use for instance methods
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
@@ -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)
|
||||
|
||||
@@ -31,3 +31,5 @@ class ChatAction(object):
|
||||
UPLOAD_AUDIO = 'upload_audio'
|
||||
UPLOAD_DOCUMENT = 'upload_document'
|
||||
FIND_LOCATION = 'find_location'
|
||||
RECORD_VIDEO_NOTE = 'record_video_note'
|
||||
UPLOAD_VIDEO_NOTE = 'upload_video_note'
|
||||
|
||||
@@ -33,8 +33,11 @@ from .stringcommandhandler import StringCommandHandler
|
||||
from .stringregexhandler import StringRegexHandler
|
||||
from .typehandler import TypeHandler
|
||||
from .conversationhandler import ConversationHandler
|
||||
from .precheckoutqueryhandler import PreCheckoutQueryHandler
|
||||
from .shippingqueryhandler import ShippingQueryHandler
|
||||
|
||||
__all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
|
||||
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
|
||||
'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'StringRegexHandler', 'TypeHandler', 'ConversationHandler')
|
||||
'StringRegexHandler', 'TypeHandler', 'ConversationHandler',
|
||||
'PreCheckoutQueryHandler', 'ShippingQueryHandler')
|
||||
|
||||
@@ -86,9 +86,9 @@ class CommandHandler(Handler):
|
||||
_str = str # Python 3
|
||||
|
||||
if isinstance(command, _str):
|
||||
self.command = [command]
|
||||
self.command = [command.lower()]
|
||||
else:
|
||||
self.command = command
|
||||
self.command = [x.lower() for x in command]
|
||||
self.filters = filters
|
||||
self.allow_edited = allow_edited
|
||||
self.pass_args = pass_args
|
||||
@@ -117,7 +117,7 @@ class CommandHandler(Handler):
|
||||
else:
|
||||
res = self.filters(message)
|
||||
|
||||
return res and (message.text.startswith('/') and command[0] in self.command
|
||||
return res and (message.text.startswith('/') and command[0].lower() in self.command
|
||||
and command[1].lower() == message.bot.username.lower())
|
||||
else:
|
||||
return False
|
||||
|
||||
+101
-6
@@ -19,6 +19,11 @@
|
||||
""" This module contains the Filters for use with the MessageHandler class """
|
||||
from telegram import Chat
|
||||
|
||||
try:
|
||||
str_type = base_string
|
||||
except NameError:
|
||||
str_type = str
|
||||
|
||||
|
||||
class BaseFilter(object):
|
||||
"""Base class for all Message Filters
|
||||
@@ -209,13 +214,68 @@ class Filters(object):
|
||||
|
||||
class _StatusUpdate(BaseFilter):
|
||||
|
||||
class _NewChatMembers(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.new_chat_members)
|
||||
|
||||
new_chat_members = _NewChatMembers()
|
||||
|
||||
class _LeftChatMember(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.left_chat_member)
|
||||
|
||||
left_chat_member = _LeftChatMember()
|
||||
|
||||
class _NewChatTitle(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.new_chat_title)
|
||||
|
||||
new_chat_title = _NewChatTitle()
|
||||
|
||||
class _NewChatPhoto(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.new_chat_photo)
|
||||
|
||||
new_chat_photo = _NewChatPhoto()
|
||||
|
||||
class _DeleteChatPhoto(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.delete_chat_photo)
|
||||
|
||||
delete_chat_photo = _DeleteChatPhoto()
|
||||
|
||||
class _ChatCreated(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.group_chat_created or message.supergroup_chat_created or
|
||||
message.channel_chat_created)
|
||||
|
||||
chat_created = _ChatCreated()
|
||||
|
||||
class _Migrate(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.migrate_from_chat_id or message.migrate_to_chat_id)
|
||||
|
||||
migrate = _Migrate()
|
||||
|
||||
class _PinnedMessage(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.pinned_message)
|
||||
|
||||
pinned_message = _PinnedMessage()
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.new_chat_member or message.left_chat_member
|
||||
or message.new_chat_title or message.new_chat_photo
|
||||
or message.delete_chat_photo or message.group_chat_created
|
||||
or message.supergroup_chat_created or message.channel_chat_created
|
||||
or message.migrate_to_chat_id or message.migrate_from_chat_id
|
||||
or message.pinned_message)
|
||||
return bool(self.new_chat_members(message) or self.left_chat_member(message) or
|
||||
self.new_chat_title(message) or self.new_chat_photo(message) or
|
||||
self.delete_chat_photo(message) or self.chat_created(message) or
|
||||
self.migrate(message) or self.pinned_message(message))
|
||||
|
||||
status_update = _StatusUpdate()
|
||||
|
||||
@@ -263,3 +323,38 @@ class Filters(object):
|
||||
return message.chat.type in [Chat.GROUP, Chat.SUPERGROUP]
|
||||
|
||||
group = _Group()
|
||||
|
||||
class _Invoice(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.invoice)
|
||||
|
||||
invoice = _Invoice()
|
||||
|
||||
class _SuccessfulPayment(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.successful_payment)
|
||||
|
||||
successful_payment = _SuccessfulPayment()
|
||||
|
||||
class language(BaseFilter):
|
||||
"""
|
||||
Filters messages to only allow those which are from users with a certain language code.
|
||||
Note that according to telegrams documentation, every single user does not have the
|
||||
language_code attribute.
|
||||
|
||||
Args:
|
||||
lang (str|list): Which language code(s) to allow through. This will be matched using
|
||||
.startswith meaning that 'en' will match both 'en_US' and 'en_GB'
|
||||
"""
|
||||
|
||||
def __init__(self, lang):
|
||||
if isinstance(lang, str_type):
|
||||
self.lang = [lang]
|
||||
else:
|
||||
self.lang = lang
|
||||
|
||||
def filter(self, message):
|
||||
return message.from_user.language_code and any(
|
||||
[message.from_user.language_code.startswith(x) for x in self.lang])
|
||||
|
||||
@@ -166,7 +166,8 @@ class JobQueue(object):
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
Job: The new ``Job`` instance that has been added to the job queue.
|
||||
telegram.ext.jobqueue.Job: The new ``Job`` instance that has been added to the
|
||||
job queue.
|
||||
|
||||
"""
|
||||
job = Job(callback, repeat=False, context=context, name=name, job_queue=self)
|
||||
@@ -201,7 +202,8 @@ class JobQueue(object):
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
Job: The new ``Job`` instance that has been added to the job queue.
|
||||
telegram.ext.jobqueue.Job: The new ``Job`` instance that has been added to the
|
||||
job queue.
|
||||
|
||||
"""
|
||||
job = Job(callback,
|
||||
@@ -228,7 +230,8 @@ class JobQueue(object):
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
Job: The new ``Job`` instance that has been added to the job queue.
|
||||
telegram.ext.jobqueue.Job: The new ``Job`` instance that has been added to the
|
||||
job queue.
|
||||
|
||||
"""
|
||||
job = Job(callback,
|
||||
@@ -366,7 +369,7 @@ class Job(object):
|
||||
job runs
|
||||
repeat (bool): If the job runs periodically or only once
|
||||
name (str): The name of this job
|
||||
job_queue (JobQueue): The ``JobQueue`` this job belongs to
|
||||
job_queue (telegram.ext.JobQueue): The ``JobQueue`` this job belongs to
|
||||
enabled (bool): Boolean property that decides if this job is currently active
|
||||
|
||||
Args:
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the PreCheckoutQueryHandler class """
|
||||
|
||||
from telegram import Update
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class PreCheckoutQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram PreCheckout callback queries.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
Default is ``False``.
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
callback,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(PreCheckoutQueryHandler, self).__init__(
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.pre_checkout_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the ShippingQueryHandler class """
|
||||
|
||||
from telegram import Update
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class ShippingQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram shipping callback queries.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
Default is ``False``.
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
callback,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(ShippingQueryHandler, self).__init__(
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.shipping_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
@@ -27,7 +27,7 @@ class TypeHandler(Handler):
|
||||
Handler class to handle updates of custom types.
|
||||
|
||||
Args:
|
||||
type (type): The ``type`` of updates this handler should process, as
|
||||
type (class): The ``type`` of updates this handler should process, as
|
||||
determined by ``isinstance``
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
|
||||
@@ -59,9 +59,9 @@ class Updater(object):
|
||||
base_url (Optional[str]):
|
||||
workers (Optional[int]): Amount of threads in the thread pool for
|
||||
functions decorated with @run_async
|
||||
bot (Optional[Bot]): A pre-initialized bot instance. If a pre-initizlied bot is used, it is
|
||||
the user's responsibility to create it using a `Request` instance with a large enough
|
||||
connection pool.
|
||||
bot (Optional[telegram.Bot]): A pre-initialized bot instance. If a pre-initizlied bot is
|
||||
used, it is the user's responsibility to create it using a `Request` instance with
|
||||
a large enough connection pool.
|
||||
user_sig_handler (Optional[function]): Takes ``signum, frame`` as positional arguments.
|
||||
This will be called when a signal is received, defaults are (SIGINT, SIGTERM, SIGABRT)
|
||||
setable with Updater.idle(stop_signals=(signals))
|
||||
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -46,7 +46,10 @@ class InlineKeyboardButton(TelegramObject):
|
||||
the bot's username and the specified inline query in the current chat's input field.
|
||||
Can be empty, in which case only the bot's username will be inserted.
|
||||
callback_game (Optional[:class:`telegram.CallbackGame`]): Description of the game that will
|
||||
be launched when the user presses the button.
|
||||
be launched when the user presses the button. NOTE: This type of button must always be
|
||||
the first button in the first row.
|
||||
pay (Optional[bool]): Specify True, to send a Pay button. NOTE: This type of button must
|
||||
always be the first button in the first row.
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
@@ -58,6 +61,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||
switch_inline_query=None,
|
||||
switch_inline_query_current_chat=None,
|
||||
callback_game=None,
|
||||
pay=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.text = text
|
||||
@@ -68,6 +72,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
|
||||
@@ -40,7 +40,7 @@ class InlineQuery(TelegramObject):
|
||||
query (str):
|
||||
offset (str):
|
||||
location (optional[:class:`telegram.Location`]):
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
bot (Optional[telegram.Bot]): The Bot to use for instance methods
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
@@ -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)
|
||||
|
||||
@@ -32,6 +32,7 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||
thumb_url (str): URL of the static thumbnail for the result (jpeg or gif).
|
||||
gif_width (Optional[int]): Width of the GIF.
|
||||
gif_height (Optional[int]): Height of the GIF.
|
||||
gif_duration (Optional[int]): Duration of the GIF.
|
||||
title (Optional[str]): Title for the result.
|
||||
caption (Optional[str]): Caption of the GIF file to be sent, 0-200 characters.
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]): Inline keyboard attached
|
||||
@@ -45,6 +46,7 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||
thumb_url (str):
|
||||
gif_width (Optional[int]):
|
||||
gif_height (Optional[int]):
|
||||
gif_duration (Optional[int]):
|
||||
title (Optional[str]):
|
||||
caption (Optional[str]):
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]):
|
||||
@@ -63,6 +65,7 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||
caption=None,
|
||||
reply_markup=None,
|
||||
input_message_content=None,
|
||||
gif_duration=None,
|
||||
**kwargs):
|
||||
|
||||
# Required
|
||||
@@ -75,6 +78,8 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||
self.gif_width = gif_width
|
||||
if gif_height:
|
||||
self.gif_height = gif_height
|
||||
if gif_duration:
|
||||
self.gif_duration = gif_duration
|
||||
if title:
|
||||
self.title = title
|
||||
if caption:
|
||||
|
||||
@@ -32,6 +32,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||
thumb_url (str): URL of the static thumbnail (jpeg or gif) for the result.
|
||||
mpeg4_width (Optional[int]): Video width.
|
||||
mpeg4_height (Optional[int]): Video height.
|
||||
mpeg4_duration (Optional[int]): Video duration
|
||||
title (Optional[str]): Title for the result.
|
||||
caption (Optional[str]): Caption of the MPEG-4 file to be sent, 0-200 characters.
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]): Inline keyboard attached
|
||||
@@ -44,6 +45,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||
thumb_url (str): URL of the static thumbnail (jpeg or gif) for the result.
|
||||
mpeg4_width (Optional[int]): Video width.
|
||||
mpeg4_height (Optional[int]): Video height.
|
||||
mpeg4_duration (Optional[int]): Video duration
|
||||
title (Optional[str]): Title for the result.
|
||||
caption (Optional[str]): Caption of the MPEG-4 file to be sent, 0-200 characters.
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]): Inline keyboard attached
|
||||
@@ -64,6 +66,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||
caption=None,
|
||||
reply_markup=None,
|
||||
input_message_content=None,
|
||||
mpeg4_duration=None,
|
||||
**kwargs):
|
||||
|
||||
# Required
|
||||
@@ -76,6 +79,8 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||
self.mpeg4_width = mpeg4_width
|
||||
if mpeg4_height:
|
||||
self.mpeg4_height = mpeg4_height
|
||||
if mpeg4_duration:
|
||||
self.mpeg4_duration = mpeg4_duration
|
||||
if title:
|
||||
self.title = title
|
||||
if caption:
|
||||
|
||||
+16
-27
@@ -35,7 +35,8 @@ from telegram import TelegramError
|
||||
|
||||
DEFAULT_MIME_TYPE = 'application/octet-stream'
|
||||
USER_AGENT = 'Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)'
|
||||
FILE_TYPES = ('audio', 'document', 'photo', 'sticker', 'video', 'voice', 'certificate')
|
||||
FILE_TYPES = ('audio', 'document', 'photo', 'sticker', 'video', 'voice', 'certificate',
|
||||
'video_note')
|
||||
|
||||
|
||||
class InputFile(object):
|
||||
@@ -45,27 +46,11 @@ class InputFile(object):
|
||||
self.data = data
|
||||
self.boundary = choose_boundary()
|
||||
|
||||
if 'audio' in data:
|
||||
self.input_name = 'audio'
|
||||
self.input_file = data.pop('audio')
|
||||
elif 'document' in data:
|
||||
self.input_name = 'document'
|
||||
self.input_file = data.pop('document')
|
||||
elif 'photo' in data:
|
||||
self.input_name = 'photo'
|
||||
self.input_file = data.pop('photo')
|
||||
elif 'sticker' in data:
|
||||
self.input_name = 'sticker'
|
||||
self.input_file = data.pop('sticker')
|
||||
elif 'video' in data:
|
||||
self.input_name = 'video'
|
||||
self.input_file = data.pop('video')
|
||||
elif 'voice' in data:
|
||||
self.input_name = 'voice'
|
||||
self.input_file = data.pop('voice')
|
||||
elif 'certificate' in data:
|
||||
self.input_name = 'certificate'
|
||||
self.input_file = data.pop('certificate')
|
||||
for t in FILE_TYPES:
|
||||
if t in data:
|
||||
self.input_name = t
|
||||
self.input_file = data.pop(t)
|
||||
break
|
||||
else:
|
||||
raise TelegramError('Unknown inputfile type')
|
||||
|
||||
@@ -84,13 +69,17 @@ class InputFile(object):
|
||||
if not self.filename or '.' not in self.filename:
|
||||
self.filename = self.mimetype.replace('/', '.')
|
||||
except TelegramError:
|
||||
self.mimetype = mimetypes.guess_type(self.filename)[0] or DEFAULT_MIME_TYPE
|
||||
if self.filename:
|
||||
self.mimetype = mimetypes.guess_type(
|
||||
self.filename)[0] or DEFAULT_MIME_TYPE
|
||||
else:
|
||||
self.mimetype = DEFAULT_MIME_TYPE
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
"""
|
||||
Returns:
|
||||
str:
|
||||
str
|
||||
"""
|
||||
return {'User-agent': USER_AGENT, 'Content-type': self.content_type}
|
||||
|
||||
@@ -98,14 +87,14 @@ class InputFile(object):
|
||||
def content_type(self):
|
||||
"""
|
||||
Returns:
|
||||
str:
|
||||
str
|
||||
"""
|
||||
return 'multipart/form-data; boundary=%s' % self.boundary
|
||||
|
||||
def to_form(self):
|
||||
"""
|
||||
Returns:
|
||||
str:
|
||||
str
|
||||
"""
|
||||
form = []
|
||||
form_boundary = '--' + self.boundary
|
||||
@@ -133,7 +122,7 @@ class InputFile(object):
|
||||
def _parse(form):
|
||||
"""
|
||||
Returns:
|
||||
str:
|
||||
str
|
||||
"""
|
||||
if sys.version_info > (3,):
|
||||
# on Python 3 form needs to be byte encoded
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Invoice."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class Invoice(TelegramObject):
|
||||
"""This object contains basic information about an invoice.
|
||||
|
||||
Attributes:
|
||||
title (str): Product name
|
||||
description (str): Product description
|
||||
start_parameter (str): Unique bot deep-linking parameter that can
|
||||
be used to generate this invoice
|
||||
currency (str): Three-letter ISO 4217 currency code
|
||||
total_amount (int): Total price in the smallest units of the currency (integer)
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, title, description, start_parameter, currency, total_amount, **kwargs):
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.start_parameter = start_parameter
|
||||
self.currency = currency
|
||||
self.total_amount = total_amount
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.Invoice:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return Invoice(**data)
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram LabeledPrice."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class LabeledPrice(TelegramObject):
|
||||
"""This object represents a portion of the price for goods or services.
|
||||
|
||||
Attributes:
|
||||
label (str): Portion label
|
||||
amount (int): Price of the product in the smallest units of the currency (integer)
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
"""
|
||||
|
||||
def __init__(self, label, amount, **kwargs):
|
||||
self.label = label
|
||||
self.amount = amount
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.LabeledPrice:
|
||||
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return LabeledPrice(**data)
|
||||
|
||||
@staticmethod
|
||||
def de_list(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (list):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
List<telegram.PhotoSize>:
|
||||
"""
|
||||
if not data:
|
||||
return []
|
||||
|
||||
labeled_prices = list()
|
||||
for labeled_price in data:
|
||||
labeled_prices.append(LabeledPrice.de_json(labeled_price, bot))
|
||||
|
||||
return labeled_prices
|
||||
+154
-95
@@ -23,8 +23,10 @@ from datetime import datetime
|
||||
from time import mktime
|
||||
|
||||
from telegram import (Audio, Contact, Document, Chat, Location, PhotoSize, Sticker, TelegramObject,
|
||||
User, Video, Voice, Venue, MessageEntity, Game)
|
||||
User, Video, Voice, Venue, MessageEntity, Game, Invoice, SuccessfulPayment)
|
||||
from telegram.utils.deprecate import warn_deprecate_obj
|
||||
from telegram.utils.helpers import escape_html, escape_markdown
|
||||
from telegram.videonote import VideoNote
|
||||
|
||||
|
||||
class Message(TelegramObject):
|
||||
@@ -34,36 +36,69 @@ class Message(TelegramObject):
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
message_id (int):
|
||||
from_user (:class:`telegram.User`):
|
||||
date (:class:`datetime.datetime`):
|
||||
forward_from (:class:`telegram.User`):
|
||||
forward_from_chat (:class:`telegram.Chat`):
|
||||
forward_from_message_id (int):
|
||||
forward_date (:class:`datetime.datetime`):
|
||||
reply_to_message (:class:`telegram.Message`):
|
||||
edit_date (:class:`datetime.datetime`):
|
||||
text (str):
|
||||
audio (:class:`telegram.Audio`):
|
||||
document (:class:`telegram.Document`):
|
||||
game (:class:`telegram.Game`):
|
||||
photo (List[:class:`telegram.PhotoSize`]):
|
||||
sticker (:class:`telegram.Sticker`):
|
||||
video (:class:`telegram.Video`):
|
||||
voice (:class:`telegram.Voice`):
|
||||
caption (str):
|
||||
contact (:class:`telegram.Contact`):
|
||||
location (:class:`telegram.Location`):
|
||||
new_chat_member (:class:`telegram.User`):
|
||||
left_chat_member (:class:`telegram.User`):
|
||||
new_chat_title (str):
|
||||
new_chat_photo (List[:class:`telegram.PhotoSize`]):
|
||||
delete_chat_photo (bool):
|
||||
group_chat_created (bool):
|
||||
supergroup_chat_created (bool):
|
||||
migrate_to_chat_id (int):
|
||||
migrate_from_chat_id (int):
|
||||
channel_chat_created (bool):
|
||||
message_id (int): Unique message identifier inside this chat
|
||||
from_user (:class:`telegram.User`): Sender, can be empty for messages sent to channels
|
||||
date (:class:`datetime.datetime`): Date the message was sent in Unix time
|
||||
chat (:class:`telegram.Chat`): Conversation the message belongs to
|
||||
forward_from (:class:`telegram.User`): For forwarded messages, sender of the original
|
||||
message
|
||||
forward_from_chat (:class:`telegram.Chat`): For messages forwarded from a channel,
|
||||
information about the original channel
|
||||
forward_from_message_id (int): For forwarded channel posts, identifier of the original
|
||||
message in the channel
|
||||
forward_date (:class:`datetime.datetime`): For forwarded messages, date the original
|
||||
message was sent in Unix time
|
||||
reply_to_message (:class:`telegram.Message`): For replies, the original message. Note
|
||||
that the Message object in this field will not contain further reply_to_message
|
||||
fields even if it itself is a reply.
|
||||
edit_date (:class:`datetime.datetime`): Date the message was last edited in Unix time
|
||||
text (str): For text messages, the actual UTF-8 text of the message, 0-4096 characters.
|
||||
entities (List[:class:`telegram.MessageEntity`]): For text messages, special entities
|
||||
like usernames, URLs, bot commands, etc. that appear in the text. See
|
||||
parse_entity and parse_entities methods for how to use properly
|
||||
video_note (:class:`telegram.VideoNote`): Message is a video note, information about the
|
||||
video message
|
||||
audio (:class:`telegram.Audio`): Message is an audio file, information about the file
|
||||
document (:class:`telegram.Document`): Message is a general file, information about the
|
||||
file
|
||||
game (:class:`telegram.Game`):Message is a game, information about the game
|
||||
photo (List[:class:`telegram.PhotoSize`]): Message is a photo, available sizes of the photo
|
||||
sticker (:class:`telegram.Sticker`): Message is a sticker, information about the sticker
|
||||
video (:class:`telegram.Video`): Message is a video, information about the video
|
||||
voice (:class:`telegram.Voice`): Message is a voice message, information about the file
|
||||
caption (str): Caption for the document, photo or video, 0-200 characters
|
||||
contact (:class:`telegram.Contact`): Message is a shared contact, information about the
|
||||
contact
|
||||
location (:class:`telegram.Location`): Message is a shared location, information about the
|
||||
location
|
||||
new_chat_member (:class:`telegram.User`): A new member was added to the group,
|
||||
information about them (this member may be the bot itself)
|
||||
left_chat_member (:class:`telegram.User`): A member was removed from the group,
|
||||
information about them (this member may be the bot itself)
|
||||
new_chat_title (str): A chat title was changed to this value
|
||||
new_chat_photo (List[:class:`telegram.PhotoSize`]): A chat photo was change to this value
|
||||
delete_chat_photo (bool): Service message: the chat photo was deleted
|
||||
group_chat_created (bool): Service message: the group has been created
|
||||
supergroup_chat_created (bool): Service message: the supergroup has been created. This
|
||||
field can't be received in a message coming through updates, because bot can't be a
|
||||
member of a supergroup when it is created. It can only be found in reply_to_message
|
||||
if someone replies to a very first message in a directly created supergroup.
|
||||
migrate_to_chat_id (int): The group has been migrated to a supergroup with the specified
|
||||
identifier.
|
||||
migrate_from_chat_id (int): The supergroup has been migrated from a group with the
|
||||
specified identifier.
|
||||
channel_chat_created (bool): Service message: the channel has been created. This field
|
||||
can't be received in a message coming through updates, because bot can't be a member
|
||||
of a channel when it is created. It can only be found in reply_to_message if someone
|
||||
replies to a very first message in a channel.
|
||||
pinned_message (:class:`telegram.message`): Specified message was pinned. Note that the
|
||||
Message object in this field will not contain further reply_to_message fields even if
|
||||
it is itself a reply.
|
||||
invoice (:class:`telegram.Invoice`): Message is an invoice for a payment, information
|
||||
about the invoice.
|
||||
successful_payment (:class:`telegram.SuccessfulPayment`): Message is a service message
|
||||
about a successful payment, information about the payment.
|
||||
bot (Optional[telegram.Bot]): The Bot to use for instance methods
|
||||
|
||||
Deprecated: 4.0
|
||||
new_chat_participant (:class:`telegram.User`): Use `new_chat_member`
|
||||
@@ -71,40 +106,6 @@ class Message(TelegramObject):
|
||||
|
||||
left_chat_participant (:class:`telegram.User`): Use `left_chat_member`
|
||||
instead.
|
||||
|
||||
Args:
|
||||
message_id (int):
|
||||
from_user (:class:`telegram.User`):
|
||||
date (:class:`datetime.datetime`):
|
||||
chat (:class:`telegram.Chat`):
|
||||
forward_from (Optional[:class:`telegram.User`]):
|
||||
forward_from_chat (Optional[:class:`telegram.Chat`]):
|
||||
forward_from_message_id (Optional[int]):
|
||||
forward_date (Optional[:class:`datetime.datetime`]):
|
||||
reply_to_message (Optional[:class:`telegram.Message`]):
|
||||
edit_date (Optional[:class:`datetime.datetime`]):
|
||||
text (Optional[str]):
|
||||
audio (Optional[:class:`telegram.Audio`]):
|
||||
document (Optional[:class:`telegram.Document`]):
|
||||
game (Optional[:class:`telegram.Game`]):
|
||||
photo (Optional[List[:class:`telegram.PhotoSize`]]):
|
||||
sticker (Optional[:class:`telegram.Sticker`]):
|
||||
video (Optional[:class:`telegram.Video`]):
|
||||
voice (Optional[:class:`telegram.Voice`]):
|
||||
caption (Optional[str]):
|
||||
contact (Optional[:class:`telegram.Contact`]):
|
||||
location (Optional[:class:`telegram.Location`]):
|
||||
new_chat_member (Optional[:class:`telegram.User`]):
|
||||
left_chat_member (Optional[:class:`telegram.User`]):
|
||||
new_chat_title (Optional[str]):
|
||||
new_chat_photo (Optional[List[:class:`telegram.PhotoSize`]):
|
||||
delete_chat_photo (Optional[bool]):
|
||||
group_chat_created (Optional[bool]):
|
||||
supergroup_chat_created (Optional[bool]):
|
||||
migrate_to_chat_id (Optional[int]):
|
||||
migrate_from_chat_id (Optional[int]):
|
||||
channel_chat_created (Optional[bool]):
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -130,6 +131,7 @@ class Message(TelegramObject):
|
||||
location=None,
|
||||
venue=None,
|
||||
new_chat_member=None,
|
||||
new_chat_members=None,
|
||||
left_chat_member=None,
|
||||
new_chat_title=None,
|
||||
new_chat_photo=None,
|
||||
@@ -141,7 +143,10 @@ class Message(TelegramObject):
|
||||
channel_chat_created=False,
|
||||
pinned_message=None,
|
||||
forward_from_message_id=None,
|
||||
invoice=None,
|
||||
successful_payment=None,
|
||||
bot=None,
|
||||
video_note=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.message_id = int(message_id)
|
||||
@@ -163,11 +168,13 @@ class Message(TelegramObject):
|
||||
self.sticker = sticker
|
||||
self.video = video
|
||||
self.voice = voice
|
||||
self.video_note = video_note
|
||||
self.caption = caption
|
||||
self.contact = contact
|
||||
self.location = location
|
||||
self.venue = venue
|
||||
self.new_chat_member = new_chat_member
|
||||
self._new_chat_member = new_chat_member
|
||||
self.new_chat_members = new_chat_members
|
||||
self.left_chat_member = left_chat_member
|
||||
self.new_chat_title = new_chat_title
|
||||
self.new_chat_photo = new_chat_photo
|
||||
@@ -179,6 +186,8 @@ class Message(TelegramObject):
|
||||
self.channel_chat_created = bool(channel_chat_created)
|
||||
self.pinned_message = pinned_message
|
||||
self.forward_from_message_id = forward_from_message_id
|
||||
self.invoice = invoice
|
||||
self.successful_payment = successful_payment
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@@ -220,13 +229,17 @@ class Message(TelegramObject):
|
||||
data['sticker'] = Sticker.de_json(data.get('sticker'), bot)
|
||||
data['video'] = Video.de_json(data.get('video'), bot)
|
||||
data['voice'] = Voice.de_json(data.get('voice'), bot)
|
||||
data['video_note'] = VideoNote.de_json(data.get('video_note'), bot)
|
||||
data['contact'] = Contact.de_json(data.get('contact'), bot)
|
||||
data['location'] = Location.de_json(data.get('location'), bot)
|
||||
data['venue'] = Venue.de_json(data.get('venue'), bot)
|
||||
data['new_chat_member'] = User.de_json(data.get('new_chat_member'), bot)
|
||||
data['new_chat_members'] = User.de_list(data.get('new_chat_members'), bot)
|
||||
data['left_chat_member'] = User.de_json(data.get('left_chat_member'), bot)
|
||||
data['new_chat_photo'] = PhotoSize.de_list(data.get('new_chat_photo'), bot)
|
||||
data['pinned_message'] = Message.de_json(data.get('pinned_message'), bot)
|
||||
data['invoice'] = Invoice.de_json(data.get('invoice'), bot)
|
||||
data['successful_payment'] = SuccessfulPayment.de_json(data.get('successful_payment'), bot)
|
||||
|
||||
return Message(bot=bot, **data)
|
||||
|
||||
@@ -257,6 +270,9 @@ class Message(TelegramObject):
|
||||
data['entities'] = [e.to_dict() for e in self.entities]
|
||||
if self.new_chat_photo:
|
||||
data['new_chat_photo'] = [p.to_dict() for p in self.new_chat_photo]
|
||||
data['new_chat_member'] = data.pop('_new_chat_member', None)
|
||||
if self.new_chat_members:
|
||||
data['new_chat_members'] = [u.to_dict() for u in self.new_chat_members]
|
||||
|
||||
return data
|
||||
|
||||
@@ -312,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
|
||||
@@ -321,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
|
||||
@@ -338,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
|
||||
@@ -355,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
|
||||
@@ -372,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
|
||||
@@ -389,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
|
||||
@@ -406,11 +422,28 @@ 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):
|
||||
"""
|
||||
Shortcut for ``bot.send_video_note(update.message.chat_id, *args, **kwargs)``
|
||||
|
||||
Keyword Args:
|
||||
quote (Optional[bool]): If set to ``True``, the video is sent as an actual reply to
|
||||
this message. If ``reply_to_message_id`` is passed in ``kwargs``, this parameter
|
||||
will be ignored. Default: ``True`` in group chats and ``False`` in private chats.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
|
||||
self._quote(kwargs)
|
||||
return self.bot.send_video_note(self.chat_id, *args, **kwargs)
|
||||
|
||||
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
|
||||
@@ -423,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
|
||||
@@ -440,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
|
||||
@@ -457,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
|
||||
@@ -474,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)
|
||||
@@ -488,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,
|
||||
@@ -498,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)
|
||||
|
||||
@@ -515,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)
|
||||
|
||||
@@ -531,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)
|
||||
|
||||
@@ -628,6 +661,9 @@ class Message(TelegramObject):
|
||||
"""
|
||||
entities = self.parse_entities()
|
||||
message_text = self.text
|
||||
if not sys.maxunicode == 0xffff:
|
||||
message_text = message_text.encode('utf-16-le')
|
||||
|
||||
markdown_text = ''
|
||||
last_offset = 0
|
||||
|
||||
@@ -647,10 +683,18 @@ class Message(TelegramObject):
|
||||
else:
|
||||
insert = text
|
||||
|
||||
markdown_text += escape_html(message_text[last_offset:entity.offset]) + insert
|
||||
if sys.maxunicode == 0xffff:
|
||||
markdown_text += escape_html(message_text[last_offset:entity.offset]) + insert
|
||||
else:
|
||||
markdown_text += escape_html(message_text[last_offset * 2:entity.offset * 2]
|
||||
.decode('utf-16-le')) + insert
|
||||
|
||||
last_offset = entity.offset + entity.length
|
||||
|
||||
markdown_text += escape_html(message_text[last_offset:])
|
||||
if sys.maxunicode == 0xffff:
|
||||
markdown_text += escape_html(message_text[last_offset:])
|
||||
else:
|
||||
markdown_text += escape_html(message_text[last_offset * 2:].decode('utf-16-le'))
|
||||
return markdown_text
|
||||
|
||||
@property
|
||||
@@ -667,6 +711,9 @@ class Message(TelegramObject):
|
||||
"""
|
||||
entities = self.parse_entities()
|
||||
message_text = self.text
|
||||
if not sys.maxunicode == 0xffff:
|
||||
message_text = message_text.encode('utf-16-le')
|
||||
|
||||
markdown_text = ''
|
||||
last_offset = 0
|
||||
|
||||
@@ -685,9 +732,21 @@ class Message(TelegramObject):
|
||||
insert = '```' + text + '```'
|
||||
else:
|
||||
insert = text
|
||||
if sys.maxunicode == 0xffff:
|
||||
markdown_text += escape_markdown(message_text[last_offset:entity.offset]) + insert
|
||||
else:
|
||||
markdown_text += escape_markdown(message_text[last_offset * 2:entity.offset * 2]
|
||||
.decode('utf-16-le')) + insert
|
||||
|
||||
markdown_text += escape_markdown(message_text[last_offset:entity.offset]) + insert
|
||||
last_offset = entity.offset + entity.length
|
||||
|
||||
markdown_text += escape_markdown(message_text[last_offset:])
|
||||
if sys.maxunicode == 0xffff:
|
||||
markdown_text += escape_markdown(message_text[last_offset:])
|
||||
else:
|
||||
markdown_text += escape_markdown(message_text[last_offset * 2:].decode('utf-16-le'))
|
||||
return markdown_text
|
||||
|
||||
@property
|
||||
def new_chat_member(self):
|
||||
warn_deprecate_obj('new_chat_member', 'new_chat_members')
|
||||
return self._new_chat_member
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram OrderInfo."""
|
||||
|
||||
from telegram import TelegramObject, ShippingAddress
|
||||
|
||||
|
||||
class OrderInfo(TelegramObject):
|
||||
"""This object represents information about an order.
|
||||
|
||||
Attributes:
|
||||
name (Optional[str]): User name
|
||||
phone_number (Optional[str]): User's phone number
|
||||
email (Optional[str]): User email
|
||||
shipping_address (Optional[:class:`telegram.ShippingAddress`]): User shipping address
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name=None, phone_number=None, email=None, shipping_address=None, **kwargs):
|
||||
self.name = name
|
||||
self.phone_number = phone_number
|
||||
self.email = email
|
||||
self.shipping_address = shipping_address
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.OrderInfo:
|
||||
"""
|
||||
if not data:
|
||||
return OrderInfo()
|
||||
|
||||
data = super(OrderInfo, OrderInfo).de_json(data, bot)
|
||||
|
||||
data['shipping_address'] = ShippingAddress.de_json(data.get('shipping_address'), bot)
|
||||
|
||||
return OrderInfo(**data)
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram PreCheckoutQuery."""
|
||||
|
||||
from telegram import TelegramObject, User, OrderInfo
|
||||
|
||||
|
||||
class PreCheckoutQuery(TelegramObject):
|
||||
"""This object contains information about an incoming pre-checkout query.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
id (str): Unique query identifier
|
||||
from_user (:class:`telegram.User`): User who sent the query
|
||||
currency (str): Three-letter ISO 4217 currency code
|
||||
total_amount (int): Total price in the smallest units of the currency (integer)
|
||||
invoice_payload (str): Bot specified invoice payload
|
||||
shipping_option_id (Optional[str]): Identifier of the shipping option chosen by the user
|
||||
order_info (Optional[:class:`telegram.OrderInfo`]): Order info provided by the user
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
id,
|
||||
from_user,
|
||||
currency,
|
||||
total_amount,
|
||||
invoice_payload,
|
||||
shipping_option_id=None,
|
||||
order_info=None,
|
||||
bot=None,
|
||||
**kwargs):
|
||||
self.id = id
|
||||
self.from_user = from_user
|
||||
self.currency = currency
|
||||
self.total_amount = total_amount
|
||||
self.invoice_payload = invoice_payload
|
||||
self.shipping_option_id = shipping_option_id
|
||||
self.order_info = order_info
|
||||
|
||||
self.bot = bot
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.PreCheckoutQuery:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(PreCheckoutQuery, PreCheckoutQuery).de_json(data, bot)
|
||||
|
||||
data['from_user'] = User.de_json(data.pop('from'), bot)
|
||||
data['order_info'] = OrderInfo.de_json(data.get('order_info'), bot)
|
||||
|
||||
return PreCheckoutQuery(**data)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns:
|
||||
dict:
|
||||
"""
|
||||
data = super(PreCheckoutQuery, self).to_dict()
|
||||
|
||||
data['from'] = data.pop('from_user', None)
|
||||
|
||||
return data
|
||||
|
||||
def answer(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for
|
||||
``bot.answer_pre_checkout_query(update.pre_checkout_query.id, *args, **kwargs)``
|
||||
"""
|
||||
return self.bot.answer_pre_checkout_query(self.id, *args, **kwargs)
|
||||
@@ -31,9 +31,11 @@ class ReplyKeyboardRemove(ReplyMarkup):
|
||||
Args:
|
||||
selective (Optional[bool]): Use this parameter if you want to remove the keyboard for
|
||||
specific users only. Targets:
|
||||
1) users that are @mentioned in the text of the Message object;
|
||||
2) if the bot's message is a reply (has reply_to_message_id), sender of the
|
||||
original message.
|
||||
|
||||
- users that are @mentioned in the text of the Message object
|
||||
- if the bot's message is a reply (has reply_to_message_id), sender of the
|
||||
original message.
|
||||
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ShippingAddress."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class ShippingAddress(TelegramObject):
|
||||
"""This object represents a Telegram ShippingAddress.
|
||||
|
||||
Attributes:
|
||||
country_code (str): ISO 3166-1 alpha-2 country code
|
||||
state (str): State, if applicable
|
||||
city (str): City
|
||||
street_line1 (str): First line for the address
|
||||
street_line2 (str): Second line for the address
|
||||
post_code (str): Address post code
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, country_code, state, city, street_line1, street_line2, post_code, **kwargs):
|
||||
self.country_code = country_code
|
||||
self.state = state
|
||||
self.city = city
|
||||
self.street_line1 = street_line1
|
||||
self.street_line2 = street_line2
|
||||
self.post_code = post_code
|
||||
|
||||
self._id_attrs = (self.country_code, self.state, self.city, self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.ShippingAddress:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return ShippingAddress(**data)
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ShippingOption."""
|
||||
|
||||
from telegram import TelegramObject, LabeledPrice
|
||||
|
||||
|
||||
class ShippingOption(TelegramObject):
|
||||
"""This object represents one shipping option.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
id (str): Shipping option identifier
|
||||
title (str): Option title
|
||||
prices (List[:class:`telegram.LabeledPrice`]): List of price portions
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, id, title, prices, **kwargs):
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.prices = prices
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.ShippingOption:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(ShippingOption, ShippingOption).de_json(data, bot)
|
||||
|
||||
data['prices'] = LabeledPrice.de_list(data.get('prices'), bot)
|
||||
|
||||
return ShippingOption(**data)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns:
|
||||
dict:
|
||||
"""
|
||||
data = super(ShippingOption, self).to_dict()
|
||||
|
||||
data['prices'] = [p.to_dict() for p in self.prices]
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ShippingQuery."""
|
||||
|
||||
from telegram import TelegramObject, User, ShippingAddress
|
||||
|
||||
|
||||
class ShippingQuery(TelegramObject):
|
||||
"""This object contains information about an incoming shipping query.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
id (str): Unique query identifier
|
||||
from_user (:class:`telegram.User`): User who sent the query
|
||||
invoice_payload (str): Bot specified invoice payload
|
||||
shipping_address (:class:`telegram.ShippingQuery`): User specified shipping address
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, id, from_user, invoice_payload, shipping_address, bot=None, **kwargs):
|
||||
self.id = id
|
||||
self.from_user = from_user
|
||||
self.invoice_payload = invoice_payload
|
||||
self.shipping_address = shipping_address
|
||||
|
||||
self.bot = bot
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.ShippingQuery:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(ShippingQuery, ShippingQuery).de_json(data, bot)
|
||||
|
||||
data['from_user'] = User.de_json(data.pop('from'), bot)
|
||||
data['shipping_address'] = ShippingAddress.de_json(data.get('shipping_address'), bot)
|
||||
|
||||
return ShippingQuery(**data)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns:
|
||||
dict:
|
||||
"""
|
||||
data = super(ShippingQuery, self).to_dict()
|
||||
|
||||
data['from'] = data.pop('from_user', None)
|
||||
|
||||
return data
|
||||
|
||||
def answer(self, *args, **kwargs):
|
||||
"""Shortcut for ``bot.answer_shipping_query(update.shipping_query.id, *args, **kwargs)``"""
|
||||
return self.bot.answer_shipping_query(self.id, *args, **kwargs)
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram SuccessfulPayment."""
|
||||
|
||||
from telegram import TelegramObject, OrderInfo
|
||||
|
||||
|
||||
class SuccessfulPayment(TelegramObject):
|
||||
"""This object contains basic information about a successful payment.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
currency (str): Three-letter ISO 4217 currency code
|
||||
total_amount (int): Total price in the smallest units of the currency (integer)
|
||||
invoice_payload (str): Bot specified invoice payload
|
||||
telegram_payment_charge_id (str): Telegram payment identifier
|
||||
provider_payment_charge_id (str): Provider payment identifier
|
||||
shipping_option_id (Optional[str]): Identifier of the shipping option chosen by the user
|
||||
order_info (Optional[:class:`telegram.OrderInfo`]): Order info provided by the user
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
currency,
|
||||
total_amount,
|
||||
invoice_payload,
|
||||
telegram_payment_charge_id,
|
||||
provider_payment_charge_id,
|
||||
shipping_option_id=None,
|
||||
order_info=None,
|
||||
**kwargs):
|
||||
self.currency = currency
|
||||
self.total_amount = total_amount
|
||||
self.invoice_payload = invoice_payload
|
||||
self.shipping_option_id = shipping_option_id
|
||||
self.order_info = order_info
|
||||
self.telegram_payment_charge_id = telegram_payment_charge_id
|
||||
self.provider_payment_charge_id = provider_payment_charge_id
|
||||
|
||||
self._id_attrs = (self.telegram_payment_charge_id, self.provider_payment_charge_id)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.SuccessfulPayment:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(SuccessfulPayment, SuccessfulPayment).de_json(data, bot)
|
||||
data['order_info'] = OrderInfo.de_json(data.get('order_info'), bot)
|
||||
|
||||
return SuccessfulPayment(**data)
|
||||
+19
-1
@@ -18,7 +18,8 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Update."""
|
||||
|
||||
from telegram import (Message, TelegramObject, InlineQuery, ChosenInlineResult, CallbackQuery)
|
||||
from telegram import (Message, TelegramObject, InlineQuery, ChosenInlineResult,
|
||||
CallbackQuery, ShippingQuery, PreCheckoutQuery)
|
||||
|
||||
|
||||
class Update(TelegramObject):
|
||||
@@ -38,6 +39,9 @@ class Update(TelegramObject):
|
||||
text, photo, sticker, etc.
|
||||
edited_channel_post (Optional[:class:`telegram.Message`]): New version of a channel post
|
||||
that is known to the bot and was edited.
|
||||
shipping_query (:class:`telegram.ShippingQuery`): New incoming shipping query.
|
||||
pre_checkout_query (:class:`telegram.PreCheckoutQuery`): New incoming pre-checkout query.
|
||||
|
||||
|
||||
Args:
|
||||
update_id (int):
|
||||
@@ -48,6 +52,8 @@ class Update(TelegramObject):
|
||||
callback_query (Optional[:class:`telegram.CallbackQuery`]):
|
||||
channel_post (Optional[:class:`telegram.Message`]):
|
||||
edited_channel_post (Optional[:class:`telegram.Message`]):
|
||||
shipping_query (Optional[:class:`telegram.ShippingQuery`]):
|
||||
pre_checkout_query (Optional[:class:`telegram.PreCheckoutQuery`]):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
@@ -61,6 +67,8 @@ class Update(TelegramObject):
|
||||
callback_query=None,
|
||||
channel_post=None,
|
||||
edited_channel_post=None,
|
||||
shipping_query=None,
|
||||
pre_checkout_query=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.update_id = int(update_id)
|
||||
@@ -70,6 +78,8 @@ class Update(TelegramObject):
|
||||
self.inline_query = inline_query
|
||||
self.chosen_inline_result = chosen_inline_result
|
||||
self.callback_query = callback_query
|
||||
self.shipping_query = shipping_query
|
||||
self.pre_checkout_query = pre_checkout_query
|
||||
self.channel_post = channel_post
|
||||
self.edited_channel_post = edited_channel_post
|
||||
|
||||
@@ -100,6 +110,8 @@ class Update(TelegramObject):
|
||||
data['chosen_inline_result'] = ChosenInlineResult.de_json(
|
||||
data.get('chosen_inline_result'), bot)
|
||||
data['callback_query'] = CallbackQuery.de_json(data.get('callback_query'), bot)
|
||||
data['shipping_query'] = ShippingQuery.de_json(data.get('shipping_query'), bot)
|
||||
data['pre_checkout_query'] = PreCheckoutQuery.de_json(data.get('pre_checkout_query'), bot)
|
||||
data['channel_post'] = Message.de_json(data.get('channel_post'), bot)
|
||||
data['edited_channel_post'] = Message.de_json(data.get('edited_channel_post'), bot)
|
||||
|
||||
@@ -132,6 +144,12 @@ class Update(TelegramObject):
|
||||
elif self.callback_query:
|
||||
user = self.callback_query.from_user
|
||||
|
||||
elif self.shipping_query:
|
||||
user = self.shipping_query.from_user
|
||||
|
||||
elif self.pre_checkout_query:
|
||||
user = self.pre_checkout_query.from_user
|
||||
|
||||
self._effective_user = user
|
||||
return user
|
||||
|
||||
|
||||
+36
-13
@@ -26,22 +26,24 @@ class User(TelegramObject):
|
||||
"""This object represents a Telegram User.
|
||||
|
||||
Attributes:
|
||||
id (int):
|
||||
first_name (str):
|
||||
last_name (str):
|
||||
username (str):
|
||||
type (str):
|
||||
id (int): Unique identifier for this user or bot
|
||||
first_name (str): User's or bot's first name
|
||||
last_name (str): User's or bot's last name
|
||||
username (str): User's or bot's username
|
||||
language_code (str): IETF language tag of the user's language
|
||||
type (str): Deprecated
|
||||
|
||||
Args:
|
||||
id (int):
|
||||
first_name (str):
|
||||
id (int): Unique identifier for this user or bot
|
||||
first_name (str): User's or bot's first name
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
type (Optional[str]):
|
||||
last_name (Optional[str]):
|
||||
username (Optional[str]):
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
type (Optional[str]): Deprecated
|
||||
last_name (Optional[str]): User's or bot's last name
|
||||
username (Optional[str]): User's or bot's username
|
||||
language_code (Optional[str]): IETF language tag of the user's language
|
||||
bot (Optional[telegram.Bot]): The Bot to use for instance methods
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -50,6 +52,7 @@ class User(TelegramObject):
|
||||
type=None,
|
||||
last_name=None,
|
||||
username=None,
|
||||
language_code=None,
|
||||
bot=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
@@ -59,6 +62,7 @@ class User(TelegramObject):
|
||||
self.type = type
|
||||
self.last_name = last_name
|
||||
self.username = username
|
||||
self.language_code = language_code
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@@ -92,6 +96,25 @@ 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):
|
||||
"""
|
||||
Args:
|
||||
data (list):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
List<telegram.User>:
|
||||
"""
|
||||
if not data:
|
||||
return []
|
||||
|
||||
users = list()
|
||||
for user in data:
|
||||
users.append(User.de_json(user, bot))
|
||||
|
||||
return users
|
||||
|
||||
@@ -21,8 +21,18 @@
|
||||
import warnings
|
||||
|
||||
|
||||
def warn_deprecate_obj(old, new):
|
||||
warnings.warn('{0} is being deprecated, please use {1} from now on'.format(old, new))
|
||||
# We use our own DeprecationWarning since they are muted by default and "UserWarning" makes it
|
||||
# seem like it's the user that issued the warning
|
||||
# We name it something else so that you don't get confused when you attempt to suppress it
|
||||
class TelegramDeprecationWarning(Warning):
|
||||
pass
|
||||
|
||||
|
||||
def warn_deprecate_obj(old, new, stacklevel=3):
|
||||
warnings.warn(
|
||||
'{0} is being deprecated, please use {1} from now on.'.format(old, new),
|
||||
category=TelegramDeprecationWarning,
|
||||
stacklevel=stacklevel)
|
||||
|
||||
|
||||
def deprecate(func, old, new):
|
||||
|
||||
@@ -18,9 +18,14 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the Promise class """
|
||||
|
||||
import logging
|
||||
from threading import Event
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.addHandler(logging.NullHandler())
|
||||
|
||||
|
||||
class Promise(object):
|
||||
"""A simple Promise implementation for the run_async decorator"""
|
||||
|
||||
@@ -37,6 +42,7 @@ class Promise(object):
|
||||
self._result = self.pooled_function(*self.args, **self.kwargs)
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception('An uncaught error was raised while running the promise')
|
||||
self._exception = exc
|
||||
|
||||
finally:
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import os
|
||||
import socket
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
try:
|
||||
import ujson as json
|
||||
@@ -27,10 +28,15 @@ except ImportError:
|
||||
import json
|
||||
|
||||
import certifi
|
||||
import urllib3
|
||||
import urllib3.contrib.appengine
|
||||
from urllib3.connection import HTTPConnection
|
||||
from urllib3.util.timeout import Timeout
|
||||
try:
|
||||
import telegram.vendor.ptb_urllib3.urllib3 as urllib3
|
||||
import telegram.vendor.ptb_urllib3.urllib3.contrib.appengine as appengine
|
||||
from telegram.vendor.ptb_urllib3.urllib3.connection import HTTPConnection
|
||||
from telegram.vendor.ptb_urllib3.urllib3.util.timeout import Timeout
|
||||
except ImportError:
|
||||
warnings.warn("python-telegram-bot wasn't properly installed. Please refer to README.rst on "
|
||||
"how to properly install.")
|
||||
raise
|
||||
|
||||
from telegram import (InputFile, TelegramError)
|
||||
from telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,
|
||||
@@ -90,16 +96,16 @@ class Request(object):
|
||||
proxy_url = os.environ.get('HTTPS_PROXY') or os.environ.get('https_proxy')
|
||||
|
||||
if not proxy_url:
|
||||
if urllib3.contrib.appengine.is_appengine_sandbox():
|
||||
if appengine.is_appengine_sandbox():
|
||||
# Use URLFetch service if running in App Engine
|
||||
mgr = urllib3.contrib.appengine.AppEngineManager()
|
||||
mgr = appengine.AppEngineManager()
|
||||
else:
|
||||
mgr = urllib3.PoolManager(**kwargs)
|
||||
else:
|
||||
kwargs.update(urllib3_proxy_kwargs)
|
||||
if proxy_url.startswith('socks'):
|
||||
try:
|
||||
from urllib3.contrib.socks import SOCKSProxyManager
|
||||
from telegram.vendor.ptb_urllib3.urllib3.contrib.socks import SOCKSProxyManager
|
||||
except ImportError:
|
||||
raise RuntimeError('PySocks is missing')
|
||||
mgr = SOCKSProxyManager(proxy_url, **kwargs)
|
||||
@@ -218,7 +224,7 @@ class Request(object):
|
||||
"""Request an URL.
|
||||
Args:
|
||||
url (str): The web location we want to retrieve.
|
||||
data (dict[str, str]): A dict of key/value pairs. Note: On py2.7 value is unicode.
|
||||
data (dict[str, str|int]): A dict of key/value pairs. Note: On py2.7 value is unicode.
|
||||
timeout (Optional[int|float]): If this value is specified, use it as the read timeout
|
||||
from the server (instead of the one specified during creation of the connection
|
||||
pool).
|
||||
|
||||
Vendored
+1
Submodule telegram/vendor/ptb_urllib3 added at ddb4953401
Vendored
-1
Submodule telegram/vendor/urllib3 deleted from 4b076eedff
+1
-1
@@ -17,4 +17,4 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
__version__ = '6.0.0'
|
||||
__version__ = '6.1.0'
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram VideoNote."""
|
||||
|
||||
from telegram import PhotoSize, TelegramObject
|
||||
|
||||
|
||||
class VideoNote(TelegramObject):
|
||||
"""This object represents a Telegram VideoNote.
|
||||
|
||||
Attributes:
|
||||
file_id (str): Unique identifier for this file
|
||||
length (int): Video width and height as defined by sender
|
||||
duration (int): Duration of the video in seconds as defined by sender
|
||||
thumb (Optional[:class:`telegram.PhotoSize`]): Video thumbnail
|
||||
file_size (Optional[int]): File size
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, length, duration, thumb=None, file_size=None, **kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
self.length = int(length)
|
||||
self.duration = int(duration)
|
||||
# Optionals
|
||||
self.thumb = thumb
|
||||
self.file_size = file_size
|
||||
|
||||
self._id_attrs = (self.file_id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.VideoNote:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(VideoNote, VideoNote).de_json(data, bot)
|
||||
|
||||
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
|
||||
|
||||
return VideoNote(**data)
|
||||
@@ -44,6 +44,8 @@ class BaseTest(object):
|
||||
self._channel_id = os.environ.get('CHANNEL_ID', '@pythontelegrambottests')
|
||||
self._bot = bot
|
||||
self._chat_id = chat_id
|
||||
self._payment_provider_token = os.environ.get('PAYMENT_PROVIDER_TOKEN',
|
||||
'284685063:TEST:ZGJlMmQxZDI3ZTc3')
|
||||
|
||||
@staticmethod
|
||||
def is_json(string):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
+20
-1
@@ -31,6 +31,7 @@ from flaky import flaky
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from telegram.utils.request import Request
|
||||
from telegram.error import BadRequest
|
||||
from tests.base import BaseTest, timeout
|
||||
|
||||
@@ -317,7 +318,7 @@ class BotTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(text, fwdmsg.text)
|
||||
self.assertEqual(fwdmsg.forward_from_message_id, msg.message_id)
|
||||
|
||||
@flaky(3, 1)
|
||||
@flaky(20, 1)
|
||||
@timeout(10)
|
||||
def test_set_webhook_get_webhook_info(self):
|
||||
url = 'https://python-telegram-bot.org/test/webhook'
|
||||
@@ -467,6 +468,24 @@ class BotTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(name, message.contact.first_name)
|
||||
self.assertEqual(last, message.contact.last_name)
|
||||
|
||||
def test_timeout_propagation(self):
|
||||
class OkException(Exception):
|
||||
pass
|
||||
|
||||
class MockRequest(Request):
|
||||
def post(self, url, data, timeout=None):
|
||||
raise OkException(timeout)
|
||||
|
||||
_request = self._bot._request
|
||||
self._bot._request = MockRequest()
|
||||
|
||||
timeout = 500
|
||||
|
||||
with self.assertRaises(OkException) as ok:
|
||||
self._bot.send_photo(self._chat_id, open('tests/data/telegram.jpg'), timeout=timeout)
|
||||
self.assertEqual(ok.exception.args[0], timeout)
|
||||
|
||||
self._bot._request = _request
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
+51
-2
@@ -118,51 +118,74 @@ class FiltersTest(BaseTest, unittest.TestCase):
|
||||
self.message.game = None
|
||||
self.assertFalse(Filters.game(self.message))
|
||||
|
||||
def test_filters_successful_payment(self):
|
||||
self.message.successful_payment = 'test'
|
||||
self.assertTrue(Filters.successful_payment(self.message))
|
||||
self.message.successful_payment = None
|
||||
self.assertFalse(Filters.successful_payment(self.message))
|
||||
|
||||
def test_filters_invoice(self):
|
||||
self.message.invoice = 'test'
|
||||
self.assertTrue(Filters.invoice(self.message))
|
||||
self.message.invoice = None
|
||||
self.assertFalse(Filters.invoice(self.message))
|
||||
|
||||
def test_filters_status_update(self):
|
||||
self.assertFalse(Filters.status_update(self.message))
|
||||
|
||||
self.message.new_chat_member = 'test'
|
||||
self.message.new_chat_members = ['test']
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.message.new_chat_member = None
|
||||
self.assertTrue(Filters.status_update.new_chat_members(self.message))
|
||||
self.message.new_chat_members = None
|
||||
|
||||
self.message.left_chat_member = 'test'
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.left_chat_member(self.message))
|
||||
self.message.left_chat_member = None
|
||||
|
||||
self.message.new_chat_title = 'test'
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.new_chat_title(self.message))
|
||||
self.message.new_chat_title = ''
|
||||
|
||||
self.message.new_chat_photo = 'test'
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.new_chat_photo(self.message))
|
||||
self.message.new_chat_photo = None
|
||||
|
||||
self.message.delete_chat_photo = True
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.delete_chat_photo(self.message))
|
||||
self.message.delete_chat_photo = False
|
||||
|
||||
self.message.group_chat_created = True
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.chat_created(self.message))
|
||||
self.message.group_chat_created = False
|
||||
|
||||
self.message.supergroup_chat_created = True
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.chat_created(self.message))
|
||||
self.message.supergroup_chat_created = False
|
||||
|
||||
self.message.migrate_to_chat_id = 100
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.migrate(self.message))
|
||||
self.message.migrate_to_chat_id = 0
|
||||
|
||||
self.message.migrate_from_chat_id = 100
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.migrate(self.message))
|
||||
self.message.migrate_from_chat_id = 0
|
||||
|
||||
self.message.channel_chat_created = True
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.chat_created(self.message))
|
||||
self.message.channel_chat_created = False
|
||||
|
||||
self.message.pinned_message = 'test'
|
||||
self.assertTrue(Filters.status_update(self.message))
|
||||
self.assertTrue(Filters.status_update.pinned_message(self.message))
|
||||
self.message.pinned_message = None
|
||||
|
||||
def test_entities_filter(self):
|
||||
@@ -274,6 +297,32 @@ class FiltersTest(BaseTest, unittest.TestCase):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
(custom & Filters.text)(self.message)
|
||||
|
||||
def test_language_filter_single(self):
|
||||
self.message.from_user.language_code = 'en_US'
|
||||
self.assertTrue((Filters.language('en_US'))(self.message))
|
||||
self.assertTrue((Filters.language('en'))(self.message))
|
||||
self.assertFalse((Filters.language('en_GB'))(self.message))
|
||||
self.assertFalse((Filters.language('da'))(self.message))
|
||||
self.message.from_user.language_code = 'en_GB'
|
||||
self.assertFalse((Filters.language('en_US'))(self.message))
|
||||
self.assertTrue((Filters.language('en'))(self.message))
|
||||
self.assertTrue((Filters.language('en_GB'))(self.message))
|
||||
self.assertFalse((Filters.language('da'))(self.message))
|
||||
self.message.from_user.language_code = 'da'
|
||||
self.assertFalse((Filters.language('en_US'))(self.message))
|
||||
self.assertFalse((Filters.language('en'))(self.message))
|
||||
self.assertFalse((Filters.language('en_GB'))(self.message))
|
||||
self.assertTrue((Filters.language('da'))(self.message))
|
||||
|
||||
def test_language_filter_multiple(self):
|
||||
f = Filters.language(['en_US', 'da'])
|
||||
self.message.from_user.language_code = 'en_US'
|
||||
self.assertTrue(f(self.message))
|
||||
self.message.from_user.language_code = 'en_GB'
|
||||
self.assertFalse(f(self.message))
|
||||
self.message.from_user.language_code = 'da'
|
||||
self.assertTrue(f(self.message))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -37,6 +37,7 @@ class InlineQueryResultGifTest(BaseTest, unittest.TestCase):
|
||||
self.gif_url = 'gif url'
|
||||
self.gif_width = 10
|
||||
self.gif_height = 15
|
||||
self.gif_duration = 1
|
||||
self.thumb_url = 'thumb url'
|
||||
self.title = 'title'
|
||||
self.caption = 'caption'
|
||||
@@ -50,6 +51,7 @@ class InlineQueryResultGifTest(BaseTest, unittest.TestCase):
|
||||
'gif_url': self.gif_url,
|
||||
'gif_width': self.gif_width,
|
||||
'gif_height': self.gif_height,
|
||||
'gif_duration': self.gif_duration,
|
||||
'thumb_url': self.thumb_url,
|
||||
'title': self.title,
|
||||
'caption': self.caption,
|
||||
@@ -65,6 +67,7 @@ class InlineQueryResultGifTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(gif.gif_url, self.gif_url)
|
||||
self.assertEqual(gif.gif_width, self.gif_width)
|
||||
self.assertEqual(gif.gif_height, self.gif_height)
|
||||
self.assertEqual(gif.gif_duration, self.gif_duration)
|
||||
self.assertEqual(gif.thumb_url, self.thumb_url)
|
||||
self.assertEqual(gif.title, self.title)
|
||||
self.assertEqual(gif.caption, self.caption)
|
||||
|
||||
@@ -37,6 +37,7 @@ class InlineQueryResultMpeg4GifTest(BaseTest, unittest.TestCase):
|
||||
self.mpeg4_url = 'mpeg4 url'
|
||||
self.mpeg4_width = 10
|
||||
self.mpeg4_height = 15
|
||||
self.mpeg4_duration = 1
|
||||
self.thumb_url = 'thumb url'
|
||||
self.title = 'title'
|
||||
self.caption = 'caption'
|
||||
@@ -50,6 +51,7 @@ class InlineQueryResultMpeg4GifTest(BaseTest, unittest.TestCase):
|
||||
'mpeg4_url': self.mpeg4_url,
|
||||
'mpeg4_width': self.mpeg4_width,
|
||||
'mpeg4_height': self.mpeg4_height,
|
||||
'mpeg4_duration': self.mpeg4_duration,
|
||||
'thumb_url': self.thumb_url,
|
||||
'title': self.title,
|
||||
'caption': self.caption,
|
||||
@@ -65,6 +67,7 @@ class InlineQueryResultMpeg4GifTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(mpeg4.mpeg4_url, self.mpeg4_url)
|
||||
self.assertEqual(mpeg4.mpeg4_width, self.mpeg4_width)
|
||||
self.assertEqual(mpeg4.mpeg4_height, self.mpeg4_height)
|
||||
self.assertEqual(mpeg4.mpeg4_duration, self.mpeg4_duration)
|
||||
self.assertEqual(mpeg4.thumb_url, self.thumb_url)
|
||||
self.assertEqual(mpeg4.title, self.title)
|
||||
self.assertEqual(mpeg4.caption, self.caption)
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
Invoice"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from flaky import flaky
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest, timeout
|
||||
|
||||
|
||||
class InvoiceTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram Invoice."""
|
||||
|
||||
def setUp(self):
|
||||
self.payload = 'payload'
|
||||
self.provider_token = self._payment_provider_token
|
||||
self.prices = [telegram.LabeledPrice('Fish', 100), telegram.LabeledPrice('Fish Tax', 1000)]
|
||||
|
||||
self.title = 'title'
|
||||
self.description = 'description'
|
||||
self.start_parameter = 'start_parameter'
|
||||
self.currency = 'EUR'
|
||||
self.total_amount = sum([p.amount for p in self.prices])
|
||||
|
||||
self.json_dict = {
|
||||
'title': self.title,
|
||||
'description': self.description,
|
||||
'start_parameter': self.start_parameter,
|
||||
'currency': self.currency,
|
||||
'total_amount': self.total_amount
|
||||
}
|
||||
|
||||
def test_invoice_de_json(self):
|
||||
invoice = telegram.Invoice.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(invoice.title, self.title)
|
||||
self.assertEqual(invoice.description, self.description)
|
||||
self.assertEqual(invoice.start_parameter, self.start_parameter)
|
||||
self.assertEqual(invoice.currency, self.currency)
|
||||
self.assertEqual(invoice.total_amount, self.total_amount)
|
||||
|
||||
def test_invoice_to_json(self):
|
||||
invoice = telegram.Invoice.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(invoice.to_json()))
|
||||
|
||||
def test_invoice_to_dict(self):
|
||||
invoice = telegram.Invoice.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(invoice))
|
||||
self.assertDictEqual(self.json_dict, invoice)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_invoice_required_args_only(self):
|
||||
message = self._bot.send_invoice(self._chat_id, self.title, self.description, self.payload,
|
||||
self.provider_token, self.start_parameter, self.currency,
|
||||
self.prices)
|
||||
invoice = message.invoice
|
||||
|
||||
self.assertEqual(invoice.currency, self.currency)
|
||||
self.assertEqual(invoice.start_parameter, self.start_parameter)
|
||||
self.assertEqual(invoice.description, self.description)
|
||||
self.assertEqual(invoice.title, self.title)
|
||||
self.assertEqual(invoice.total_amount, self.total_amount)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_invoice_all_args(self):
|
||||
message = self._bot.send_invoice(
|
||||
self._chat_id,
|
||||
self.title,
|
||||
self.description,
|
||||
self.payload,
|
||||
self.provider_token,
|
||||
self.start_parameter,
|
||||
self.currency,
|
||||
self.prices,
|
||||
photo_url='https://raw.githubusercontent.com/'
|
||||
'python-telegram-bot/logos/master/'
|
||||
'logo/png/ptb-logo_240.png',
|
||||
photo_size=240,
|
||||
photo_width=240,
|
||||
photo_height=240,
|
||||
need_name=True,
|
||||
need_phone_number=True,
|
||||
need_shipping_address=True,
|
||||
is_flexible=True)
|
||||
invoice = message.invoice
|
||||
|
||||
self.assertEqual(invoice.currency, self.currency)
|
||||
self.assertEqual(invoice.start_parameter, self.start_parameter)
|
||||
self.assertEqual(invoice.description, self.description)
|
||||
self.assertEqual(invoice.title, self.title)
|
||||
self.assertEqual(invoice.total_amount, self.total_amount)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
LabeledPrice"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class LabeledPriceTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram LabeledPrice."""
|
||||
|
||||
def setUp(self):
|
||||
self.label = 'label'
|
||||
self.amount = 100
|
||||
|
||||
self.json_dict = {'label': self.label, 'amount': self.amount}
|
||||
|
||||
def test_labeledprice_de_json(self):
|
||||
labeledprice = telegram.LabeledPrice.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(labeledprice.label, self.label)
|
||||
self.assertEqual(labeledprice.amount, self.amount)
|
||||
|
||||
def test_labeledprice_to_json(self):
|
||||
labeledprice = telegram.LabeledPrice.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(labeledprice.to_json()))
|
||||
|
||||
def test_labeledprice_to_dict(self):
|
||||
labeledprice = telegram.LabeledPrice.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(labeledprice))
|
||||
self.assertDictEqual(self.json_dict, labeledprice)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+32
-2
@@ -98,16 +98,46 @@ class MessageTest(BaseTest, unittest.TestCase):
|
||||
{entity: 'http://google.com',
|
||||
entity_2: 'h'})
|
||||
|
||||
def test_text_html(self):
|
||||
def test_text_html_simple(self):
|
||||
test_html_string = 'Test for <<b>bold</b>, <i>ita_lic</i>, <code>code</code>, <a href="http://github.com/">links</a> and <pre>pre</pre>.'
|
||||
text_html = self.test_message.text_html
|
||||
self.assertEquals(test_html_string, text_html)
|
||||
|
||||
def test_text_markdown(self):
|
||||
def test_text_markdown_simple(self):
|
||||
test_md_string = 'Test for <*bold*, _ita\_lic_, `code`, [links](http://github.com/) and ```pre```.'
|
||||
text_markdown = self.test_message.text_markdown
|
||||
self.assertEquals(test_md_string, text_markdown)
|
||||
|
||||
def test_text_html_emoji(self):
|
||||
text = (b'\\U0001f469\\u200d\\U0001f469\\u200d ABC').decode('unicode-escape')
|
||||
expected = (b'\\U0001f469\\u200d\\U0001f469\\u200d <b>ABC</b>').decode('unicode-escape')
|
||||
bold_entity = telegram.MessageEntity(type=telegram.MessageEntity.BOLD, offset=7, length=3)
|
||||
message = telegram.Message(
|
||||
message_id=1, from_user=None, date=None, chat=None, text=text, entities=[bold_entity])
|
||||
self.assertEquals(expected, message.text_html)
|
||||
|
||||
def test_text_markdown_emoji(self):
|
||||
text = (b'\\U0001f469\\u200d\\U0001f469\\u200d ABC').decode('unicode-escape')
|
||||
expected = (b'\\U0001f469\\u200d\\U0001f469\\u200d *ABC*').decode('unicode-escape')
|
||||
bold_entity = telegram.MessageEntity(type=telegram.MessageEntity.BOLD, offset=7, length=3)
|
||||
message = telegram.Message(
|
||||
message_id=1, from_user=None, date=None, chat=None, text=text, entities=[bold_entity])
|
||||
self.assertEquals(expected, message.text_markdown)
|
||||
|
||||
def test_parse_entities_url_emoji(self):
|
||||
url = b'http://github.com/?unicode=\\u2713\\U0001f469'.decode('unicode-escape')
|
||||
text = 'some url'
|
||||
link_entity = telegram.MessageEntity(type=telegram.MessageEntity.URL, offset=0, length=8, url=url)
|
||||
message = telegram.Message(
|
||||
message_id=1,
|
||||
from_user=None,
|
||||
date=None,
|
||||
chat=None,
|
||||
text=text,
|
||||
entities=[link_entity])
|
||||
self.assertDictEqual(message.parse_entities(), {link_entity: text})
|
||||
self.assertEqual(next(iter(message.parse_entities())).url, url)
|
||||
|
||||
@flaky(3, 1)
|
||||
def test_reply_text(self):
|
||||
"""Test for Message.reply_text"""
|
||||
|
||||
+13
-13
@@ -44,24 +44,24 @@ class MessageEntityTest(BaseTest, unittest.TestCase):
|
||||
'url': self.url
|
||||
}
|
||||
|
||||
def test_sticker_de_json(self):
|
||||
sticker = telegram.MessageEntity.de_json(self.json_dict, self._bot)
|
||||
def test_messageentity_de_json(self):
|
||||
entity = telegram.MessageEntity.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(sticker.type, self.type)
|
||||
self.assertEqual(sticker.offset, self.offset)
|
||||
self.assertEqual(sticker.length, self.length)
|
||||
self.assertEqual(sticker.url, self.url)
|
||||
self.assertEqual(entity.type, self.type)
|
||||
self.assertEqual(entity.offset, self.offset)
|
||||
self.assertEqual(entity.length, self.length)
|
||||
self.assertEqual(entity.url, self.url)
|
||||
|
||||
def test_sticker_to_json(self):
|
||||
sticker = telegram.MessageEntity.de_json(self.json_dict, self._bot)
|
||||
def test_messageentity_to_json(self):
|
||||
entity = telegram.MessageEntity.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(sticker.to_json()))
|
||||
self.assertTrue(self.is_json(entity.to_json()))
|
||||
|
||||
def test_sticker_to_dict(self):
|
||||
sticker = telegram.MessageEntity.de_json(self.json_dict, self._bot).to_dict()
|
||||
def test_messageentity_to_dict(self):
|
||||
entity = telegram.MessageEntity.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(sticker))
|
||||
self.assertDictEqual(self.json_dict, sticker)
|
||||
self.assertTrue(self.is_dict(entity))
|
||||
self.assertDictEqual(self.json_dict, entity)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
OrderInfo"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class OrderInfoTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram OrderInfo."""
|
||||
|
||||
def setUp(self):
|
||||
self.name = 'name'
|
||||
self.phone_number = 'phone_number'
|
||||
self.email = 'email'
|
||||
self.shipping_address = telegram.ShippingAddress('GB', '', 'London', '12 Grimmauld Place',
|
||||
'', 'WC1')
|
||||
|
||||
self.json_dict = {
|
||||
'name': self.name,
|
||||
'phone_number': self.phone_number,
|
||||
'email': self.email,
|
||||
'shipping_address': self.shipping_address.to_dict()
|
||||
}
|
||||
|
||||
def test_orderinfo_de_json(self):
|
||||
orderinfo = telegram.OrderInfo.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(orderinfo.name, self.name)
|
||||
self.assertEqual(orderinfo.phone_number, self.phone_number)
|
||||
self.assertEqual(orderinfo.email, self.email)
|
||||
self.assertEqual(orderinfo.shipping_address, self.shipping_address)
|
||||
|
||||
def test_orderinfo_to_json(self):
|
||||
orderinfo = telegram.OrderInfo.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(orderinfo.to_json()))
|
||||
|
||||
def test_orderinfo_to_dict(self):
|
||||
orderinfo = telegram.OrderInfo.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(orderinfo))
|
||||
self.assertDictEqual(self.json_dict, orderinfo)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -18,6 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram Photo"""
|
||||
|
||||
from io import BytesIO
|
||||
import sys
|
||||
import unittest
|
||||
import os
|
||||
@@ -37,6 +38,7 @@ class PhotoTest(BaseTest, unittest.TestCase):
|
||||
self.photo_file = open('tests/data/telegram.jpg', 'rb')
|
||||
self.photo_file_id = 'AgADAQADgEsyGx8j9QfmDMmwkPBrFcKRzy8ABHW8ul9nW7FoNHYBAAEC'
|
||||
self.photo_file_url = 'https://raw.githubusercontent.com/python-telegram-bot/python-telegram-bot/master/tests/data/telegram.jpg'
|
||||
self.photo_bytes_jpg_no_standard = 'tests/data/telegram_no_standard_header.jpg'
|
||||
self.width = 300
|
||||
self.height = 300
|
||||
self.thumb = {
|
||||
@@ -122,6 +124,32 @@ class PhotoTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(photo.height, self.height)
|
||||
self.assertEqual(photo.file_size, self.file_size)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_photo_bytesio_jpg_file(self):
|
||||
from telegram.inputfile import InputFile
|
||||
# raw image bytes
|
||||
raw_bytes = BytesIO(open(self.photo_bytes_jpg_no_standard, 'rb').read())
|
||||
inputfile = InputFile({"photo": raw_bytes})
|
||||
self.assertEqual(inputfile.mimetype, 'application/octet-stream')
|
||||
|
||||
# raw image bytes with name info
|
||||
raw_bytes = BytesIO(open(self.photo_bytes_jpg_no_standard, 'rb').read())
|
||||
raw_bytes.name = self.photo_bytes_jpg_no_standard
|
||||
inputfile = InputFile({"photo": raw_bytes})
|
||||
self.assertEqual(inputfile.mimetype, 'image/jpeg')
|
||||
|
||||
# send raw photo
|
||||
raw_bytes = BytesIO(open(self.photo_bytes_jpg_no_standard, 'rb').read())
|
||||
message = self._bot.sendPhoto(self._chat_id, photo=raw_bytes)
|
||||
photo = message.photo[-1]
|
||||
self.assertTrue(isinstance(photo.file_id, str))
|
||||
self.assertNotEqual(photo.file_id, '')
|
||||
self.assertTrue(isinstance(photo, telegram.PhotoSize))
|
||||
self.assertEqual(photo.width, 1920)
|
||||
self.assertEqual(photo.height, 1080)
|
||||
self.assertEqual(photo.file_size, 30907)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_photo_resend(self):
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
PreCheckoutQuery"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class PreCheckoutQueryTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram PreCheckoutQuery."""
|
||||
|
||||
def setUp(self):
|
||||
self._id = 5
|
||||
self.invoice_payload = 'invoice_payload'
|
||||
self.shipping_option_id = 'shipping_option_id'
|
||||
self.currency = 'EUR'
|
||||
self.total_amount = 100
|
||||
self.from_user = telegram.User(0, '')
|
||||
self.order_info = telegram.OrderInfo()
|
||||
|
||||
self.json_dict = {
|
||||
'id': self._id,
|
||||
'invoice_payload': self.invoice_payload,
|
||||
'shipping_option_id': self.shipping_option_id,
|
||||
'currency': self.currency,
|
||||
'total_amount': self.total_amount,
|
||||
'from': self.from_user.to_dict(),
|
||||
'order_info': self.order_info.to_dict()
|
||||
}
|
||||
|
||||
def test_precheckoutquery_de_json(self):
|
||||
precheckoutquery = telegram.PreCheckoutQuery.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(precheckoutquery.id, self._id)
|
||||
self.assertEqual(precheckoutquery.invoice_payload, self.invoice_payload)
|
||||
self.assertEqual(precheckoutquery.shipping_option_id, self.shipping_option_id)
|
||||
self.assertEqual(precheckoutquery.currency, self.currency)
|
||||
self.assertEqual(precheckoutquery.from_user, self.from_user)
|
||||
self.assertEqual(precheckoutquery.order_info, self.order_info)
|
||||
|
||||
def test_precheckoutquery_to_json(self):
|
||||
precheckoutquery = telegram.PreCheckoutQuery.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(precheckoutquery.to_json()))
|
||||
|
||||
def test_precheckoutquery_to_dict(self):
|
||||
precheckoutquery = telegram.PreCheckoutQuery.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(precheckoutquery))
|
||||
self.assertDictEqual(self.json_dict, precheckoutquery)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.PreCheckoutQuery(self._id, self.from_user, self.currency, self.total_amount,
|
||||
self.invoice_payload)
|
||||
b = telegram.PreCheckoutQuery(self._id, self.from_user, self.currency, self.total_amount,
|
||||
self.invoice_payload)
|
||||
c = telegram.PreCheckoutQuery(self._id, None, '', 0, '')
|
||||
d = telegram.PreCheckoutQuery(0, self.from_user, self.currency, self.total_amount,
|
||||
self.invoice_payload)
|
||||
e = telegram.Update(self._id)
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertEqual(a, c)
|
||||
self.assertEqual(hash(a), hash(c))
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
self.assertNotEqual(a, e)
|
||||
self.assertNotEqual(hash(a), hash(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
ShippingAddress"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class ShippingAddressTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram ShippingAddress."""
|
||||
|
||||
def setUp(self):
|
||||
self.country_code = 'GB'
|
||||
self.state = 'state'
|
||||
self.city = 'London'
|
||||
self.street_line1 = '12 Grimmauld Place'
|
||||
self.street_line2 = 'street_line2'
|
||||
self.post_code = 'WC1'
|
||||
|
||||
self.json_dict = {
|
||||
'country_code': self.country_code,
|
||||
'state': self.state,
|
||||
'city': self.city,
|
||||
'street_line1': self.street_line1,
|
||||
'street_line2': self.street_line2,
|
||||
'post_code': self.post_code
|
||||
}
|
||||
|
||||
def test_shippingaddress_de_json(self):
|
||||
shippingaddress = telegram.ShippingAddress.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(shippingaddress.country_code, self.country_code)
|
||||
self.assertEqual(shippingaddress.state, self.state)
|
||||
self.assertEqual(shippingaddress.city, self.city)
|
||||
self.assertEqual(shippingaddress.street_line1, self.street_line1)
|
||||
self.assertEqual(shippingaddress.street_line2, self.street_line2)
|
||||
self.assertEqual(shippingaddress.post_code, self.post_code)
|
||||
|
||||
def test_shippingaddress_to_json(self):
|
||||
shippingaddress = telegram.ShippingAddress.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(shippingaddress.to_json()))
|
||||
|
||||
def test_shippingaddress_to_dict(self):
|
||||
shippingaddress = telegram.ShippingAddress.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(shippingaddress))
|
||||
self.assertDictEqual(self.json_dict, shippingaddress)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.ShippingAddress(self.country_code, self.state, self.city, self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
b = telegram.ShippingAddress(self.country_code, self.state, self.city, self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
d = telegram.ShippingAddress('', self.state, self.city, self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
d2 = telegram.ShippingAddress(self.country_code, '', self.city, self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
d3 = telegram.ShippingAddress(self.country_code, self.state, '', self.street_line1,
|
||||
self.street_line2, self.post_code)
|
||||
d4 = telegram.ShippingAddress(self.country_code, self.state, self.city, '',
|
||||
self.street_line2, self.post_code)
|
||||
d5 = telegram.ShippingAddress(self.country_code, self.state, self.city, self.street_line1,
|
||||
'', self.post_code)
|
||||
d6 = telegram.ShippingAddress(self.country_code, self.state, self.city, self.street_line1,
|
||||
self.street_line2, '')
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
self.assertNotEqual(a, d2)
|
||||
self.assertNotEqual(hash(a), hash(d2))
|
||||
|
||||
self.assertNotEqual(a, d3)
|
||||
self.assertNotEqual(hash(a), hash(d3))
|
||||
|
||||
self.assertNotEqual(a, d4)
|
||||
self.assertNotEqual(hash(a), hash(d4))
|
||||
|
||||
self.assertNotEqual(a, d5)
|
||||
self.assertNotEqual(hash(a), hash(d5))
|
||||
|
||||
self.assertNotEqual(a, d6)
|
||||
self.assertNotEqual(hash(6), hash(d6))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
ShippingOption"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class ShippingOptionTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram ShippingOption."""
|
||||
|
||||
def setUp(self):
|
||||
self._id = 'id'
|
||||
self.title = 'title'
|
||||
self.prices = [
|
||||
telegram.LabeledPrice('Fish Container', 100),
|
||||
telegram.LabeledPrice('Premium Fish Container', 1000)
|
||||
]
|
||||
|
||||
self.json_dict = {
|
||||
'id': self._id,
|
||||
'title': self.title,
|
||||
'prices': [x.to_dict() for x in self.prices]
|
||||
}
|
||||
|
||||
def test_shippingoption_de_json(self):
|
||||
shippingoption = telegram.ShippingOption.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(shippingoption.id, self._id)
|
||||
self.assertEqual(shippingoption.title, self.title)
|
||||
self.assertEqual(shippingoption.prices, self.prices)
|
||||
|
||||
def test_shippingoption_to_json(self):
|
||||
shippingoption = telegram.ShippingOption.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(shippingoption.to_json()))
|
||||
|
||||
def test_shippingoption_to_dict(self):
|
||||
shippingoption = telegram.ShippingOption.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(shippingoption))
|
||||
self.assertDictEqual(self.json_dict, shippingoption)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.ShippingOption(self._id, self.title, self.prices)
|
||||
b = telegram.ShippingOption(self._id, self.title, self.prices)
|
||||
c = telegram.ShippingOption(self._id, '', [])
|
||||
d = telegram.ShippingOption(0, self.title, self.prices)
|
||||
e = telegram.Voice(self._id, 0)
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertEqual(a, c)
|
||||
self.assertEqual(hash(a), hash(c))
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
self.assertNotEqual(a, e)
|
||||
self.assertNotEqual(hash(a), hash(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
ShippingQuery"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class ShippingQueryTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram ShippingQuery."""
|
||||
|
||||
def setUp(self):
|
||||
self._id = 5
|
||||
self.invoice_payload = 'invoice_payload'
|
||||
self.from_user = telegram.User(0, '')
|
||||
self.shipping_address = telegram.ShippingAddress('GB', '', 'London', '12 Grimmauld Place',
|
||||
'', 'WC1')
|
||||
|
||||
self.json_dict = {
|
||||
'id': self._id,
|
||||
'invoice_payload': self.invoice_payload,
|
||||
'from': self.from_user.to_dict(),
|
||||
'shipping_address': self.shipping_address.to_dict()
|
||||
}
|
||||
|
||||
def test_shippingquery_de_json(self):
|
||||
shippingquery = telegram.ShippingQuery.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(shippingquery.id, self._id)
|
||||
self.assertEqual(shippingquery.invoice_payload, self.invoice_payload)
|
||||
self.assertEqual(shippingquery.from_user, self.from_user)
|
||||
self.assertEqual(shippingquery.shipping_address, self.shipping_address)
|
||||
|
||||
def test_shippingquery_to_json(self):
|
||||
shippingquery = telegram.ShippingQuery.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(shippingquery.to_json()))
|
||||
|
||||
def test_shippingquery_to_dict(self):
|
||||
shippingquery = telegram.ShippingQuery.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(shippingquery))
|
||||
self.assertDictEqual(self.json_dict, shippingquery)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.ShippingQuery(self._id, self.from_user, self.invoice_payload,
|
||||
self.shipping_address)
|
||||
b = telegram.ShippingQuery(self._id, self.from_user, self.invoice_payload,
|
||||
self.shipping_address)
|
||||
c = telegram.ShippingQuery(self._id, None, '', None)
|
||||
d = telegram.ShippingQuery(0, self.from_user, self.invoice_payload, self.shipping_address)
|
||||
e = telegram.Update(self._id)
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertEqual(a, c)
|
||||
self.assertEqual(hash(a), hash(c))
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
self.assertNotEqual(a, e)
|
||||
self.assertNotEqual(hash(a), hash(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram
|
||||
SuccessfulPayment"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest
|
||||
|
||||
|
||||
class SuccessfulPaymentTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram SuccessfulPayment."""
|
||||
|
||||
def setUp(self):
|
||||
self.invoice_payload = 'invoice_payload'
|
||||
self.shipping_option_id = 'shipping_option_id'
|
||||
self.currency = 'EUR'
|
||||
self.total_amount = 100
|
||||
self.order_info = telegram.OrderInfo()
|
||||
self.telegram_payment_charge_id = 'telegram_payment_charge_id'
|
||||
self.provider_payment_charge_id = 'provider_payment_charge_id'
|
||||
|
||||
self.json_dict = {
|
||||
'invoice_payload': self.invoice_payload,
|
||||
'shipping_option_id': self.shipping_option_id,
|
||||
'currency': self.currency,
|
||||
'total_amount': self.total_amount,
|
||||
'order_info': self.order_info.to_dict(),
|
||||
'telegram_payment_charge_id': self.telegram_payment_charge_id,
|
||||
'provider_payment_charge_id': self.provider_payment_charge_id
|
||||
}
|
||||
|
||||
def test_successfulpayment_de_json(self):
|
||||
successfulpayment = telegram.SuccessfulPayment.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(successfulpayment.invoice_payload, self.invoice_payload)
|
||||
self.assertEqual(successfulpayment.shipping_option_id, self.shipping_option_id)
|
||||
self.assertEqual(successfulpayment.currency, self.currency)
|
||||
self.assertEqual(successfulpayment.order_info, self.order_info)
|
||||
self.assertEqual(successfulpayment.telegram_payment_charge_id,
|
||||
self.telegram_payment_charge_id)
|
||||
self.assertEqual(successfulpayment.provider_payment_charge_id,
|
||||
self.provider_payment_charge_id)
|
||||
|
||||
def test_successfulpayment_to_json(self):
|
||||
successfulpayment = telegram.SuccessfulPayment.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(successfulpayment.to_json()))
|
||||
|
||||
def test_successfulpayment_to_dict(self):
|
||||
successfulpayment = telegram.SuccessfulPayment.de_json(self.json_dict, self._bot).to_dict()
|
||||
|
||||
self.assertTrue(self.is_dict(successfulpayment))
|
||||
self.assertDictEqual(self.json_dict, successfulpayment)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.SuccessfulPayment(self.currency, self.total_amount, self.invoice_payload,
|
||||
self.telegram_payment_charge_id,
|
||||
self.provider_payment_charge_id)
|
||||
b = telegram.SuccessfulPayment(self.currency, self.total_amount, self.invoice_payload,
|
||||
self.telegram_payment_charge_id,
|
||||
self.provider_payment_charge_id)
|
||||
c = telegram.SuccessfulPayment('', 0, '', self.telegram_payment_charge_id,
|
||||
self.provider_payment_charge_id)
|
||||
d = telegram.SuccessfulPayment(self.currency, self.total_amount, self.invoice_payload,
|
||||
self.telegram_payment_charge_id, '')
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertEqual(a, c)
|
||||
self.assertEqual(hash(a), hash(c))
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+67
-7
@@ -46,7 +46,8 @@ except ImportError:
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
from telegram import Update, Message, TelegramError, User, Chat, Bot, InlineQuery, CallbackQuery
|
||||
from telegram import (Update, Message, TelegramError, User, Chat, Bot,
|
||||
InlineQuery, CallbackQuery, ShippingQuery, PreCheckoutQuery)
|
||||
from telegram.ext import *
|
||||
from telegram.ext.dispatcher import run_async
|
||||
from telegram.error import Unauthorized, InvalidToken
|
||||
@@ -119,6 +120,14 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||
self.received_message = update.callback_query
|
||||
self.message_count += 1
|
||||
|
||||
def telegramShippingHandlerTest(self, bot, update):
|
||||
self.received_message = update.shipping_query
|
||||
self.message_count += 1
|
||||
|
||||
def telegramPreCheckoutHandlerTest(self, bot, update):
|
||||
self.received_message = update.pre_checkout_query
|
||||
self.message_count += 1
|
||||
|
||||
@run_async
|
||||
def asyncHandlerTest(self, bot, update):
|
||||
sleep(1)
|
||||
@@ -271,6 +280,19 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||
sleep(.1)
|
||||
self.assertTrue(None is self.received_message)
|
||||
|
||||
# case insensitivity
|
||||
self.reset()
|
||||
message = Message(0, user, None, None, text="/Test", bot=bot)
|
||||
queue.put(Update(update_id=0, message=message))
|
||||
sleep(.1)
|
||||
self.assertTrue(self.received_message, '/Test')
|
||||
handler = CommandHandler('Test', self.telegramHandlerTest)
|
||||
self.updater.dispatcher.add_handler(handler)
|
||||
message = Message(0, user, None, None, text="/test", bot=bot)
|
||||
queue.put(Update(update_id=0, message=message))
|
||||
sleep(.1)
|
||||
self.assertTrue(self.received_message, '/test')
|
||||
|
||||
# Remove handler
|
||||
d.remove_handler(handler)
|
||||
handler = CommandHandler('test', self.telegramHandlerEditedTest, allow_edited=False)
|
||||
@@ -488,6 +510,44 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||
sleep(.1)
|
||||
self.assertTrue(None is self.received_message)
|
||||
|
||||
def test_addRemoveShippingQueryHandler(self):
|
||||
self._setup_updater('', messages=0)
|
||||
d = self.updater.dispatcher
|
||||
handler = ShippingQueryHandler(self.telegramShippingHandlerTest)
|
||||
d.add_handler(handler)
|
||||
queue = self.updater.start_polling(0.01)
|
||||
update = Update(update_id=0, shipping_query="testshipping")
|
||||
queue.put(update)
|
||||
sleep(.1)
|
||||
self.assertEqual(self.received_message, "testshipping")
|
||||
|
||||
# Remove handler
|
||||
d.remove_handler(handler)
|
||||
self.reset()
|
||||
|
||||
queue.put(update)
|
||||
sleep(.1)
|
||||
self.assertTrue(None is self.received_message)
|
||||
|
||||
def test_addRemovePreCheckoutQueryHandler(self):
|
||||
self._setup_updater('', messages=0)
|
||||
d = self.updater.dispatcher
|
||||
handler = PreCheckoutQueryHandler(self.telegramPreCheckoutHandlerTest)
|
||||
d.add_handler(handler)
|
||||
queue = self.updater.start_polling(0.01)
|
||||
update = Update(update_id=0, pre_checkout_query="testprecheckout")
|
||||
queue.put(update)
|
||||
sleep(.1)
|
||||
self.assertEqual(self.received_message, "testprecheckout")
|
||||
|
||||
# Remove handler
|
||||
d.remove_handler(handler)
|
||||
self.reset()
|
||||
|
||||
queue.put(update)
|
||||
sleep(.1)
|
||||
self.assertTrue(None is self.received_message)
|
||||
|
||||
def test_runAsync(self):
|
||||
self._setup_updater('Test5', messages=2)
|
||||
d = self.updater.dispatcher
|
||||
@@ -884,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)
|
||||
@@ -896,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
|
||||
|
||||
@@ -904,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
|
||||
|
||||
@@ -912,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,
|
||||
@@ -924,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 []
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ class UserTest(BaseTest, unittest.TestCase):
|
||||
self.first_name = "Leandro"
|
||||
self.last_name = "S."
|
||||
self.username = "leandrotoledo"
|
||||
self.language_code = "pt-BR"
|
||||
self.type = "private"
|
||||
|
||||
self.json_dict = {
|
||||
@@ -44,6 +45,7 @@ class UserTest(BaseTest, unittest.TestCase):
|
||||
'first_name': self.first_name,
|
||||
'last_name': self.last_name,
|
||||
'username': self.username,
|
||||
'language_code': self.language_code,
|
||||
'type': self.type
|
||||
}
|
||||
|
||||
@@ -54,6 +56,7 @@ class UserTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(user.first_name, self.first_name)
|
||||
self.assertEqual(user.last_name, self.last_name)
|
||||
self.assertEqual(user.username, self.username)
|
||||
self.assertEqual(user.language_code, self.language_code)
|
||||
self.assertEqual(user.type, self.type)
|
||||
|
||||
self.assertEqual(user.name, '@leandrotoledo')
|
||||
@@ -98,6 +101,7 @@ class UserTest(BaseTest, unittest.TestCase):
|
||||
self.assertEqual(user['first_name'], self.first_name)
|
||||
self.assertEqual(user['last_name'], self.last_name)
|
||||
self.assertEqual(user['username'], self.username)
|
||||
self.assertEqual(user['language_code'], self.language_code)
|
||||
self.assertEqual(user['type'], self.type)
|
||||
|
||||
@flaky(3, 1)
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents Tests for Telegram VideoNote"""
|
||||
import numbers
|
||||
import sys
|
||||
import unittest
|
||||
import os
|
||||
|
||||
from flaky import flaky
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import telegram
|
||||
from tests.base import BaseTest, timeout
|
||||
|
||||
|
||||
class VideoNoteTest(BaseTest, unittest.TestCase):
|
||||
"""This object represents Tests for Telegram VideoNote."""
|
||||
|
||||
def setUp(self):
|
||||
self.videonote_file = open('tests/data/telegram2.mp4', 'rb')
|
||||
self.videonote_file_id = 'DQADAQADBwAD5VIIRYemhHpbPmIQAg'
|
||||
self.duration = 3
|
||||
self.length = 1 # No bloody clue what this does
|
||||
self.thumb = telegram.PhotoSize.de_json({
|
||||
'file_id': 'AAQBABMsDPcvAAQX7NUVpGq-s34OAAIC',
|
||||
'width': 90,
|
||||
'file_size': 3043,
|
||||
'height': 90
|
||||
}, self._bot)
|
||||
self.thumb_resend = telegram.PhotoSize.de_json({
|
||||
'file_id': 'AAQBABOMsecvAAQqqoY1Pee_MqcyAAIC',
|
||||
'width': 51,
|
||||
'file_size': 645,
|
||||
'height': 90
|
||||
}, self._bot)
|
||||
|
||||
self.file_size = 132084
|
||||
|
||||
self.json_dict = {
|
||||
'file_id': self.videonote_file_id,
|
||||
'duration': self.duration,
|
||||
'length': self.length,
|
||||
'thumb': self.thumb.to_dict(),
|
||||
'file_size': self.file_size
|
||||
}
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_videonote_required_args_only(self):
|
||||
message = self._bot.sendVideoNote(self._chat_id, self.videonote_file, timeout=10)
|
||||
|
||||
videonote = message.video_note
|
||||
|
||||
self.assertTrue(isinstance(videonote.file_id, str))
|
||||
self.assertNotEqual(videonote.file_id, None)
|
||||
self.assertEqual(videonote.duration, self.duration)
|
||||
# self.assertEqual(videonote.length, self.length)
|
||||
self.assertIsInstance(videonote.length, numbers.Number)
|
||||
self.assertEqual(videonote.thumb, self.thumb)
|
||||
self.assertEqual(videonote.file_size, self.file_size)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_videonote_all_args(self):
|
||||
message = self._bot.sendVideoNote(
|
||||
self._chat_id,
|
||||
self.videonote_file,
|
||||
timeout=10,
|
||||
duration=self.duration,
|
||||
length=self.length)
|
||||
|
||||
videonote = message.video_note
|
||||
|
||||
self.assertTrue(isinstance(videonote.file_id, str))
|
||||
self.assertNotEqual(videonote.file_id, None)
|
||||
# self.assertEqual(videonote.length, self.length)
|
||||
self.assertIsInstance(videonote.length, numbers.Number)
|
||||
self.assertEqual(videonote.duration, self.duration)
|
||||
self.assertEqual(videonote.thumb, self.thumb)
|
||||
self.assertEqual(videonote.file_size, self.file_size)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_send_videonote_resend(self):
|
||||
message = self._bot.sendVideoNote(
|
||||
chat_id=self._chat_id,
|
||||
video_note=self.videonote_file_id,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
videonote = message.video_note
|
||||
|
||||
self.assertEqual(videonote.file_id, self.videonote_file_id)
|
||||
# self.assertEqual(videonote.length, self.length)
|
||||
self.assertIsInstance(videonote.length, numbers.Number)
|
||||
self.assertEqual(videonote.duration, 5)
|
||||
self.assertEqual(videonote.thumb, self.thumb_resend)
|
||||
# Telegram doesn't send file_size for resends?
|
||||
# self.assertEqual(videonote.file_size, self.file_size)
|
||||
|
||||
def test_videonote_de_json(self):
|
||||
videonote = telegram.VideoNote.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertEqual(videonote.file_id, self.videonote_file_id)
|
||||
self.assertEqual(videonote.duration, self.duration)
|
||||
self.assertEqual(videonote.thumb, self.thumb)
|
||||
self.assertEqual(videonote.length, self.length)
|
||||
self.assertEqual(videonote.file_size, self.file_size)
|
||||
|
||||
def test_videonote_to_json(self):
|
||||
videonote = telegram.VideoNote.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_json(videonote.to_json()))
|
||||
|
||||
def test_videonote_to_dict(self):
|
||||
videonote = telegram.VideoNote.de_json(self.json_dict, self._bot)
|
||||
|
||||
self.assertTrue(self.is_dict(videonote.to_dict()))
|
||||
self.assertEqual(videonote['file_id'], self.videonote_file_id)
|
||||
self.assertEqual(videonote['duration'], self.duration)
|
||||
self.assertEqual(videonote['length'], self.length)
|
||||
self.assertEqual(videonote['file_size'], self.file_size)
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_error_send_videonote_empty_file(self):
|
||||
json_dict = self.json_dict
|
||||
|
||||
del (json_dict['file_id'])
|
||||
json_dict['video_note'] = open(os.devnull, 'rb')
|
||||
|
||||
self.assertRaises(telegram.TelegramError,
|
||||
lambda: self._bot.sendVideoNote(chat_id=self._chat_id,
|
||||
timeout=10,
|
||||
**json_dict))
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_error_send_videonote_empty_file_id(self):
|
||||
json_dict = self.json_dict
|
||||
|
||||
del (json_dict['file_id'])
|
||||
json_dict['video_note'] = ''
|
||||
|
||||
self.assertRaises(telegram.TelegramError,
|
||||
lambda: self._bot.sendVideoNote(chat_id=self._chat_id,
|
||||
timeout=10,
|
||||
**json_dict))
|
||||
|
||||
@flaky(3, 1)
|
||||
@timeout(10)
|
||||
def test_reply_videonote(self):
|
||||
"""Test for Message.reply_videonote"""
|
||||
message = self._bot.sendMessage(self._chat_id, '.')
|
||||
# Length is needed... see first test
|
||||
message = message.reply_video_note(self.videonote_file, length=self.length)
|
||||
|
||||
self.assertNotEqual(message.video_note.file_id, None)
|
||||
|
||||
def test_equality(self):
|
||||
a = telegram.VideoNote(self.videonote_file_id, self.length, self.duration)
|
||||
b = telegram.VideoNote(self.videonote_file_id, self.length, self.duration)
|
||||
c = telegram.VideoNote(self.videonote_file_id, 0, 0, 0)
|
||||
d = telegram.VideoNote("", self.length, self.duration)
|
||||
e = telegram.Voice(self.videonote_file_id, self.duration)
|
||||
|
||||
self.assertEqual(a, b)
|
||||
self.assertEqual(hash(a), hash(b))
|
||||
self.assertIsNot(a, b)
|
||||
|
||||
self.assertEqual(a, c)
|
||||
self.assertEqual(hash(a), hash(c))
|
||||
|
||||
self.assertNotEqual(a, d)
|
||||
self.assertNotEqual(hash(a), hash(d))
|
||||
|
||||
self.assertNotEqual(a, e)
|
||||
self.assertNotEqual(hash(a), hash(e))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user