mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-27 03:34:37 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ff4cc4445 | |||
| 32afc007aa | |||
| c758c19ef4 | |||
| 3bef2fa752 | |||
| b4cabecca2 | |||
| 0a8abccc78 | |||
| 5ff34fc0ba | |||
| 78fee3c1dc | |||
| 38d6f4d9f2 | |||
| 1ec12343f0 | |||
| b5196f00b2 | |||
| 39c679e519 | |||
| 7a6d2be101 | |||
| ef74c525b2 | |||
| 6d453b7fa2 | |||
| 716f52684f | |||
| 42497367c1 | |||
| b77b329dd6 | |||
| 5efd5e2586 | |||
| cbfb7df643 | |||
| 712baf0c07 | |||
| 59659eaf5e | |||
| 3ccf40e8cc | |||
| 38e3b91a87 | |||
| e182046376 | |||
| 1530ed20e5 | |||
| 2b221da9b9 |
@@ -5,5 +5,6 @@ formats:
|
||||
|
||||
python:
|
||||
setup_py_install: true
|
||||
version: 3
|
||||
|
||||
requirements_file: docs/requirements-docs.txt
|
||||
|
||||
@@ -24,6 +24,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `daimajia <https://github.com/daimajia>`_
|
||||
- `Daniel Reed <https://github.com/nmlorg>`_
|
||||
- `Eli Gao <https://github.com/eligao>`_
|
||||
- `Emilio Molinari <https://github.com/xates>`_
|
||||
- `ErgoZ Riftbit Vaper <https://github.com/ergoz>`_
|
||||
- `Eugene Lisitsky <https://github.com/lisitsky>`_
|
||||
- `Eugenio Panadero <https://github.com/azogue>`_
|
||||
@@ -52,6 +53,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Noam Meltzer <https://github.com/tsnoam>`_
|
||||
- `Oleg Shlyazhko <https://github.com/ollmer>`_
|
||||
- `Oleg Sushchenko <https://github.com/feuillemorte>`_
|
||||
- `Or Bin <https://github.com/OrBin>`_
|
||||
- `overquota <https://github.com/overquota>`_
|
||||
- `Patrick Hofmann <https://github.com/PH89>`_
|
||||
- `Paul Larsen <https://github.com/PaulSonOfLars>`_
|
||||
@@ -62,8 +64,10 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Simon Schürrle <https://github.com/SitiSchu>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `thodnev <https://github.com/thodnev>`_
|
||||
- `Trainer Jono <https://github.com/Tr-Jono>`_
|
||||
- `Valentijn <https://github.com/Faalentijn>`_
|
||||
- `voider1 <https://github.com/voider1>`_
|
||||
- `Wagner Macedo <https://github.com/wagnerluis1982>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
|
||||
Please add yourself here alphabetically when you submit your first pull request.
|
||||
|
||||
+60
@@ -1,10 +1,70 @@
|
||||
=======
|
||||
Changes
|
||||
=======
|
||||
**2018-05-02**
|
||||
*Released 10.1.0*
|
||||
|
||||
Fixes changing previous behaviour:
|
||||
|
||||
- Add urllib3 fix for socks5h support (`#1085`_)
|
||||
- Fix send_sticker() timeout=20 (`#1088`_)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Add a caption_entity filter for filtering caption entities (`#1068`_)
|
||||
- Inputfile encode filenames (`#1086`_)
|
||||
- InputFile: Fix proper naming of file when reading from subprocess.PIPE (`#1079`_)
|
||||
- Remove pytest-catchlog from requirements (`#1099`_)
|
||||
- Documentation fixes (`#1061`_, `#1078`_, `#1081`_, `#1096`_)
|
||||
|
||||
.. _`#1061`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1061
|
||||
.. _`#1068`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1068
|
||||
.. _`#1078`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1078
|
||||
.. _`#1079`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1079
|
||||
.. _`#1081`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1081
|
||||
.. _`#1085`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1085
|
||||
.. _`#1086`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1086
|
||||
.. _`#1088`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1088
|
||||
.. _`#1096`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1096
|
||||
.. _`#1099`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1099
|
||||
|
||||
**2018-04-17**
|
||||
*Released 10.0.2*
|
||||
|
||||
Important fix:
|
||||
|
||||
- Handle utf8 decoding errors (`#1076`_)
|
||||
|
||||
New features:
|
||||
|
||||
- Added Filter.regex (`#1028`_)
|
||||
- Filters for Category and file types (`#1046`_)
|
||||
- Added video note filter (`#1067`_)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Fix in telegram.Message (`#1042`_)
|
||||
- Make chat_id a positional argument inside shortcut methods of Chat and User classes (`#1050`_)
|
||||
- Make Bot.full_name return a unicode object. (`#1063`_)
|
||||
- CommandHandler faster check (`#1074`_)
|
||||
- Correct documentation of Dispatcher.add_handler (`#1071`_)
|
||||
- Various small fixes to documentation.
|
||||
|
||||
.. _`#1028`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1028
|
||||
.. _`#1042`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1042
|
||||
.. _`#1046`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1046
|
||||
.. _`#1050`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1050
|
||||
.. _`#1067`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1067
|
||||
.. _`#1063`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1063
|
||||
.. _`#1074`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1074
|
||||
.. _`#1076`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1076
|
||||
.. _`#1071`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1071
|
||||
|
||||
**2018-03-05**
|
||||
*Released 10.0.1*
|
||||
|
||||
Fixes:
|
||||
|
||||
- Fix conversationhandler timeout (PR `#1032`_)
|
||||
- Add missing docs utils (PR `#912`_)
|
||||
|
||||
|
||||
+8
-6
@@ -5,15 +5,17 @@
|
||||
|
||||
We have made you a wrapper you can't refuse
|
||||
|
||||
We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
|
||||
|
||||
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/python-telegram-bot.svg
|
||||
:target: https://pypi.python.org/pypi/python-telegram-bot
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: PyPi Package Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot.svg
|
||||
:target: https://pypi.python.org/pypi/python-telegram-bot
|
||||
:alt: Supported python versions
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://www.cpu.re/static/python-telegram-bot/downloads.svg
|
||||
:target: https://www.cpu.re/static/python-telegram-bot/downloads-by-python-version.txt
|
||||
@@ -31,8 +33,8 @@ We have made you a wrapper you can't refuse
|
||||
:target: https://travis-ci.org/python-telegram-bot/python-telegram-bot
|
||||
:alt: Travis CI Status
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/Eldinnie/python-telegram-bot/master.svg?logo=appveyor
|
||||
:target: https://ci.appveyor.com/project/Eldinnie/python-telegram-bot
|
||||
.. image:: https://img.shields.io/appveyor/ci/python-telegram-bot/python-telegram-bot/master.svg?logo=appveyor
|
||||
:target: https://ci.appveyor.com/project/python-telegram-bot/python-telegram-bot
|
||||
:alt: AppVeyor CI Status
|
||||
|
||||
|
||||
@@ -93,7 +95,7 @@ make the development of bots easy and straightforward. These classes are contain
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API 3.4 are supported.
|
||||
All types and methods of the Telegram Bot API 3.6 are supported.
|
||||
|
||||
==========
|
||||
Installing
|
||||
|
||||
+3
-11
@@ -58,9 +58,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '10.0' # telegram.__version__[:3]
|
||||
version = '10.1' # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '10.0.1' # telegram.__version__
|
||||
release = '10.1.0' # telegram.__version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -291,17 +291,9 @@ texinfo_documents = [
|
||||
|
||||
# -- 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
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Examples
|
||||
|
||||
The examples in this folder are small bots meant to show you how a bot that is written with `python-telegram-bot` looks like. Some bots focus on one specific aspect of the Telegram Bot API while others focus on one of the mechanics of this library. Except for the [`echobot.py`](#pure-api) example, they all use the high-level framework this library provides with the [`telegram.ext`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.html) submodule.
|
||||
In this folder there are small examples to show what a bot written with `python-telegram-bot` looks like. Some bots focus on one specific aspect of the Telegram Bot API while others focus on one of the mechanics of this library. Except for the [`echobot.py`](#pure-api) example, they all use the high-level framework this library provides with the [`telegram.ext`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.html) submodule.
|
||||
|
||||
All examples are licensed under the [CC0 License](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/LICENSE.txt) and are therefore fully dedicated to the public domain. You can use them as the base for your own bots without worrying about copyrights.
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ yapf
|
||||
pre-commit
|
||||
beautifulsoup4
|
||||
pytest
|
||||
pytest-catchlog
|
||||
pytest-timeout
|
||||
wheel
|
||||
|
||||
+60
-1
@@ -545,7 +545,7 @@ class Bot(TelegramObject):
|
||||
disable_notification=False,
|
||||
reply_to_message_id=None,
|
||||
reply_markup=None,
|
||||
timeout=None,
|
||||
timeout=20,
|
||||
**kwargs):
|
||||
"""Use this method to send .webp stickers.
|
||||
|
||||
@@ -3070,61 +3070,120 @@ class Bot(TelegramObject):
|
||||
|
||||
# camelCase aliases
|
||||
getMe = get_me
|
||||
"""Alias for :attr:`get_me`"""
|
||||
sendMessage = send_message
|
||||
"""Alias for :attr:`send_message`"""
|
||||
deleteMessage = delete_message
|
||||
"""Alias for :attr:`delete_message`"""
|
||||
forwardMessage = forward_message
|
||||
"""Alias for :attr:`forward_message`"""
|
||||
sendPhoto = send_photo
|
||||
"""Alias for :attr:`send_photo`"""
|
||||
sendAudio = send_audio
|
||||
"""Alias for :attr:`send_audio`"""
|
||||
sendDocument = send_document
|
||||
"""Alias for :attr:`send_document`"""
|
||||
sendSticker = send_sticker
|
||||
"""Alias for :attr:`send_sticker`"""
|
||||
sendVideo = send_video
|
||||
"""Alias for :attr:`send_video`"""
|
||||
sendVoice = send_voice
|
||||
"""Alias for :attr:`send_voice`"""
|
||||
sendVideoNote = send_video_note
|
||||
"""Alias for :attr:`send_video_note`"""
|
||||
sendMediaGroup = send_media_group
|
||||
"""Alias for :attr:`send_media_group`"""
|
||||
sendLocation = send_location
|
||||
"""Alias for :attr:`send_location`"""
|
||||
editMessageLiveLocation = edit_message_live_location
|
||||
"""Alias for :attr:`edit_message_live_location`"""
|
||||
stopMessageLiveLocation = stop_message_live_location
|
||||
"""Alias for :attr:`stop_message_live_location`"""
|
||||
sendVenue = send_venue
|
||||
"""Alias for :attr:`send_venue`"""
|
||||
sendContact = send_contact
|
||||
"""Alias for :attr:`send_contact`"""
|
||||
sendGame = send_game
|
||||
"""Alias for :attr:`send_game`"""
|
||||
sendChatAction = send_chat_action
|
||||
"""Alias for :attr:`send_chat_action`"""
|
||||
answerInlineQuery = answer_inline_query
|
||||
"""Alias for :attr:`answer_inline_query`"""
|
||||
getUserProfilePhotos = get_user_profile_photos
|
||||
"""Alias for :attr:`get_user_profile_photos`"""
|
||||
getFile = get_file
|
||||
"""Alias for :attr:`get_file`"""
|
||||
kickChatMember = kick_chat_member
|
||||
"""Alias for :attr:`kick_chat_member`"""
|
||||
unbanChatMember = unban_chat_member
|
||||
"""Alias for :attr:`unban_chat_member`"""
|
||||
answerCallbackQuery = answer_callback_query
|
||||
"""Alias for :attr:`answer_callback_query`"""
|
||||
editMessageText = edit_message_text
|
||||
"""Alias for :attr:`edit_message_text`"""
|
||||
editMessageCaption = edit_message_caption
|
||||
"""Alias for :attr:`edit_message_caption`"""
|
||||
editMessageReplyMarkup = edit_message_reply_markup
|
||||
"""Alias for :attr:`edit_message_reply_markup`"""
|
||||
getUpdates = get_updates
|
||||
"""Alias for :attr:`get_updates`"""
|
||||
setWebhook = set_webhook
|
||||
"""Alias for :attr:`set_webhook`"""
|
||||
deleteWebhook = delete_webhook
|
||||
"""Alias for :attr:`delete_webhook`"""
|
||||
leaveChat = leave_chat
|
||||
"""Alias for :attr:`leave_chat`"""
|
||||
getChat = get_chat
|
||||
"""Alias for :attr:`get_chat`"""
|
||||
getChatAdministrators = get_chat_administrators
|
||||
"""Alias for :attr:`get_chat_administrators`"""
|
||||
getChatMember = get_chat_member
|
||||
"""Alias for :attr:`get_chat_member`"""
|
||||
setChatStickerSet = set_chat_sticker_set
|
||||
"""Alias for :attr:`set_chat_sticker_set`"""
|
||||
deleteChatStickerSet = delete_chat_sticker_set
|
||||
"""Alias for :attr:`delete_chat_sticker_set`"""
|
||||
getChatMembersCount = get_chat_members_count
|
||||
"""Alias for :attr:`get_chat_members_count`"""
|
||||
getWebhookInfo = get_webhook_info
|
||||
"""Alias for :attr:`get_webhook_info`"""
|
||||
setGameScore = set_game_score
|
||||
"""Alias for :attr:`set_game_score`"""
|
||||
getGameHighScores = get_game_high_scores
|
||||
"""Alias for :attr:`get_game_high_scores`"""
|
||||
sendInvoice = send_invoice
|
||||
"""Alias for :attr:`send_invoice`"""
|
||||
answerShippingQuery = answer_shipping_query
|
||||
"""Alias for :attr:`answer_shipping_query`"""
|
||||
answerPreCheckoutQuery = answer_pre_checkout_query
|
||||
"""Alias for :attr:`answer_pre_checkout_query`"""
|
||||
restrictChatMember = restrict_chat_member
|
||||
"""Alias for :attr:`restrict_chat_member`"""
|
||||
promoteChatMember = promote_chat_member
|
||||
"""Alias for :attr:`promote_chat_member`"""
|
||||
exportChatInviteLink = export_chat_invite_link
|
||||
"""Alias for :attr:`export_chat_invite_link`"""
|
||||
setChatPhoto = set_chat_photo
|
||||
"""Alias for :attr:`set_chat_photo`"""
|
||||
deleteChatPhoto = delete_chat_photo
|
||||
"""Alias for :attr:`delete_chat_photo`"""
|
||||
setChatTitle = set_chat_title
|
||||
"""Alias for :attr:`set_chat_title`"""
|
||||
setChatDescription = set_chat_description
|
||||
"""Alias for :attr:`set_chat_description`"""
|
||||
pinChatMessage = pin_chat_message
|
||||
"""Alias for :attr:`pin_chat_message`"""
|
||||
unpinChatMessage = unpin_chat_message
|
||||
"""Alias for :attr:`unpin_chat_message`"""
|
||||
getStickerSet = get_sticker_set
|
||||
"""Alias for :attr:`get_sticker_set`"""
|
||||
uploadStickerFile = upload_sticker_file
|
||||
"""Alias for :attr:`upload_sticker_file`"""
|
||||
createNewStickerSet = create_new_sticker_set
|
||||
"""Alias for :attr:`create_new_sticker_set`"""
|
||||
addStickerToSet = add_sticker_to_set
|
||||
"""Alias for :attr:`add_sticker_to_set`"""
|
||||
setStickerPositionInSet = set_sticker_position_in_set
|
||||
"""Alias for :attr:`set_sticker_position_in_set`"""
|
||||
deleteStickerFromSet = delete_sticker_from_set
|
||||
"""Alias for :attr:`delete_sticker_from_set`"""
|
||||
|
||||
+16
-16
@@ -216,7 +216,7 @@ class Chat(TelegramObject):
|
||||
def send_message(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_message(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_message(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -224,12 +224,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_message(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_message(self.id, *args, **kwargs)
|
||||
|
||||
def send_photo(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_photo(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_photo(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -237,12 +237,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_photo(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_photo(self.id, *args, **kwargs)
|
||||
|
||||
def send_audio(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_audio(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_audio(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -250,12 +250,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_audio(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_audio(self.id, *args, **kwargs)
|
||||
|
||||
def send_document(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_document(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_document(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -263,12 +263,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_document(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_document(self.id, *args, **kwargs)
|
||||
|
||||
def send_sticker(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_sticker(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_sticker(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -276,12 +276,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_sticker(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_sticker(self.id, *args, **kwargs)
|
||||
|
||||
def send_video(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_video(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_video(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -289,12 +289,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_video(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_video(self.id, *args, **kwargs)
|
||||
|
||||
def send_video_note(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_video_note(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_video_note(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -302,12 +302,12 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_video_note(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_video_note(self.id, *args, **kwargs)
|
||||
|
||||
def send_voice(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_voice(Chat.chat_id, *args, **kwargs)
|
||||
bot.send_voice(Chat.id, *args, **kwargs)
|
||||
|
||||
Where Chat is the current instance.
|
||||
|
||||
@@ -315,4 +315,4 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_voice(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_voice(self.id, *args, **kwargs)
|
||||
|
||||
@@ -140,6 +140,10 @@ class CommandHandler(Handler):
|
||||
command.append(
|
||||
message.bot.username) # in case the command was sent without a username
|
||||
|
||||
if not (command[0].lower() in self.command
|
||||
and command[1].lower() == message.bot.username.lower()):
|
||||
return False
|
||||
|
||||
if self.filters is None:
|
||||
res = True
|
||||
elif isinstance(self.filters, list):
|
||||
@@ -147,8 +151,7 @@ class CommandHandler(Handler):
|
||||
else:
|
||||
res = self.filters(message)
|
||||
|
||||
return res and (command[0].lower() in self.command
|
||||
and command[1].lower() == message.bot.username.lower())
|
||||
return res
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ class Dispatcher(object):
|
||||
A handler must be an instance of a subclass of :class:`telegram.ext.Handler`. All handlers
|
||||
are organized in groups with a numeric value. The default group is 0. All groups will be
|
||||
evaluated for handling an update, but only 0 or 1 handler per group will be used. If
|
||||
:class:`telegram.DispatcherHandlerStop` is raised from one of the handlers, no further
|
||||
:class:`telegram.ext.DispatcherHandlerStop` is raised from one of the handlers, no further
|
||||
handlers (regardless of the group) will be called.
|
||||
|
||||
The priority/order of handlers is determined as follows:
|
||||
|
||||
+133
-1
@@ -17,6 +17,8 @@
|
||||
# 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 Filters for use with the MessageHandler class."""
|
||||
|
||||
import re
|
||||
from telegram import Chat
|
||||
from future.utils import string_types
|
||||
|
||||
@@ -171,6 +173,33 @@ class Filters(object):
|
||||
command = _Command()
|
||||
""":obj:`Filter`: Messages starting with ``/``."""
|
||||
|
||||
class regex(BaseFilter):
|
||||
"""
|
||||
Filters updates by searching for an occurence of ``pattern`` in the message text.
|
||||
The ``re.search`` function is used to determine whether an update should be filtered.
|
||||
Refer to the documentation of the ``re`` module for more information.
|
||||
|
||||
Note: Does not allow passing groups or a groupdict like the ``RegexHandler`` yet,
|
||||
but this will probably be implemented in a future update, gradually phasing out the
|
||||
RegexHandler (see https://github.com/python-telegram-bot/python-telegram-bot/issues/835).
|
||||
|
||||
Examples:
|
||||
Example ``CommandHandler("start", deep_linked_callback, Filters.regex('parameter'))``
|
||||
|
||||
Args:
|
||||
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
|
||||
"""
|
||||
|
||||
def __init__(self, pattern):
|
||||
self.pattern = re.compile(pattern)
|
||||
self.name = 'Filters.regex({})'.format(self.pattern)
|
||||
|
||||
# TODO: Once the callback revamp (#1026) is done, the regex filter should be able to pass
|
||||
# the matched groups and groupdict to the context object.
|
||||
|
||||
def filter(self, message):
|
||||
return bool(self.pattern.search(message.text))
|
||||
|
||||
class _Reply(BaseFilter):
|
||||
name = 'Filters.reply'
|
||||
|
||||
@@ -192,6 +221,79 @@ class Filters(object):
|
||||
class _Document(BaseFilter):
|
||||
name = 'Filters.document'
|
||||
|
||||
class category(BaseFilter):
|
||||
"""This Filter filters documents by their category in the mime-type attribute
|
||||
|
||||
Note:
|
||||
This Filter only filters by the mime_type of the document,
|
||||
it doesn't check the validity of the document.
|
||||
The user can manipulate the mime-type of a message and
|
||||
send media with wrong types that don't fit to this handler.
|
||||
|
||||
Examples:
|
||||
Filters.documents.category('audio/') returnes `True` for all types
|
||||
of audio sent as file, for example 'audio/mpeg' or 'audio/x-wav'
|
||||
"""
|
||||
|
||||
def __init__(self, category):
|
||||
"""Initialize the category you want to filter
|
||||
|
||||
Args:
|
||||
category (str, optional): category of the media you want to filter"""
|
||||
self.category = category
|
||||
self.name = "Filters.document.category('{}')".format(self.category)
|
||||
|
||||
def filter(self, message):
|
||||
if message.document:
|
||||
return message.document.mime_type.startswith(self.category)
|
||||
|
||||
application = category('application/')
|
||||
audio = category('audio/')
|
||||
image = category('image/')
|
||||
video = category('video/')
|
||||
text = category('text/')
|
||||
|
||||
class mime_type(BaseFilter):
|
||||
"""This Filter filters documents by their mime-type attribute
|
||||
|
||||
Note:
|
||||
This Filter only filters by the mime_type of the document,
|
||||
it doesn't check the validity of document.
|
||||
The user can manipulate the mime-type of a message and
|
||||
send media with wrong types that don't fit to this handler.
|
||||
|
||||
Examples:
|
||||
Filters.documents.mime_type('audio/mpeg') filters all audio in mp3 format.
|
||||
"""
|
||||
|
||||
def __init__(self, mimetype):
|
||||
"""Initialize the category you want to filter
|
||||
|
||||
Args:
|
||||
filetype (str, optional): mime_type of the media you want to filter"""
|
||||
self.mimetype = mimetype
|
||||
self.name = "Filters.document.mime_type('{}')".format(self.mimetype)
|
||||
|
||||
def filter(self, message):
|
||||
if message.document:
|
||||
return message.document.mime_type == self.mimetype
|
||||
|
||||
apk = mime_type('application/vnd.android.package-archive')
|
||||
doc = mime_type('application/msword')
|
||||
docx = mime_type('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
|
||||
exe = mime_type('application/x-ms-dos-executable')
|
||||
gif = mime_type('video/mp4')
|
||||
jpg = mime_type('image/jpeg')
|
||||
mp3 = mime_type('audio/mpeg')
|
||||
pdf = mime_type('application/pdf')
|
||||
py = mime_type('text/x-python')
|
||||
svg = mime_type('image/svg+xml')
|
||||
txt = mime_type('text/plain')
|
||||
targz = mime_type('application/x-compressed-tar')
|
||||
wav = mime_type('audio/x-wav')
|
||||
xml = mime_type('application/xml')
|
||||
zip = mime_type('application/zip')
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.document)
|
||||
|
||||
@@ -234,6 +336,15 @@ class Filters(object):
|
||||
voice = _Voice()
|
||||
""":obj:`Filter`: Messages that contain :class:`telegram.Voice`."""
|
||||
|
||||
class _VideoNote(BaseFilter):
|
||||
name = 'Filters.video_note'
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.video_note)
|
||||
|
||||
video_note = _VideoNote()
|
||||
""":obj:`Filter`: Messages that contain :class:`telegram.VideoNote`."""
|
||||
|
||||
class _Contact(BaseFilter):
|
||||
name = 'Filters.contact'
|
||||
|
||||
@@ -430,7 +541,28 @@ class Filters(object):
|
||||
self.name = 'Filters.entity({})'.format(self.entity_type)
|
||||
|
||||
def filter(self, message):
|
||||
return any([entity.type == self.entity_type for entity in message.entities])
|
||||
return any(entity.type == self.entity_type for entity in message.entities)
|
||||
|
||||
class caption_entity(BaseFilter):
|
||||
"""
|
||||
Filters media messages to only allow those which have a :class:`telegram.MessageEntity`
|
||||
where their `type` matches `entity_type`.
|
||||
|
||||
Examples:
|
||||
Example ``MessageHandler(Filters.caption_entity("hashtag"), callback_method)``
|
||||
|
||||
Args:
|
||||
entity_type: Caption Entity type to check for. All types can be found as constants
|
||||
in :class:`telegram.MessageEntity`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, entity_type):
|
||||
self.entity_type = entity_type
|
||||
self.name = 'Filters.caption_entity({})'.format(self.entity_type)
|
||||
|
||||
def filter(self, message):
|
||||
return any(entity.type == self.entity_type for entity in message.caption_entities)
|
||||
|
||||
class _Private(BaseFilter):
|
||||
name = 'Filters.private'
|
||||
|
||||
@@ -70,7 +70,9 @@ class InputFile(object):
|
||||
self.input_file_content = self.input_file.read()
|
||||
if 'filename' in data:
|
||||
self.filename = self.data.pop('filename')
|
||||
elif hasattr(self.input_file, 'name'):
|
||||
elif (hasattr(self.input_file, 'name') and
|
||||
not isinstance(self.input_file.name, int) and # py3
|
||||
self.input_file.name != '<fdopen>'): # py2
|
||||
# on py2.7, pylint fails to understand this properly
|
||||
# pylint: disable=E1101
|
||||
self.filename = os.path.basename(self.input_file.name)
|
||||
@@ -86,6 +88,10 @@ class InputFile(object):
|
||||
else:
|
||||
self.mimetype = DEFAULT_MIME_TYPE
|
||||
|
||||
if sys.version_info < (3,):
|
||||
if isinstance(self.filename, unicode): # flake8: noqa pylint: disable=E0602
|
||||
self.filename = self.filename.encode('utf-8', 'replace')
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
""":obj:`dict`: Headers."""
|
||||
|
||||
@@ -868,6 +868,9 @@ class Message(TelegramObject):
|
||||
|
||||
@staticmethod
|
||||
def _parse_html(message_text, entities, urled=False):
|
||||
if message_text is None:
|
||||
return None
|
||||
|
||||
if not sys.maxunicode == 0xffff:
|
||||
message_text = message_text.encode('utf-16-le')
|
||||
|
||||
@@ -962,6 +965,9 @@ class Message(TelegramObject):
|
||||
|
||||
@staticmethod
|
||||
def _parse_markdown(message_text, entities, urled=False):
|
||||
if message_text is None:
|
||||
return None
|
||||
|
||||
if not sys.maxunicode == 0xffff:
|
||||
message_text = message_text.encode('utf-16-le')
|
||||
|
||||
|
||||
+17
-17
@@ -88,7 +88,7 @@ class User(TelegramObject):
|
||||
|
||||
"""
|
||||
if self.last_name:
|
||||
return '{} {}'.format(self.first_name, self.last_name)
|
||||
return u'{} {}'.format(self.first_name, self.last_name)
|
||||
return self.first_name
|
||||
|
||||
@classmethod
|
||||
@@ -150,7 +150,7 @@ class User(TelegramObject):
|
||||
def send_message(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_message(User.chat_id, *args, **kwargs)
|
||||
bot.send_message(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -158,12 +158,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_message(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_message(self.id, *args, **kwargs)
|
||||
|
||||
def send_photo(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_photo(User.chat_id, *args, **kwargs)
|
||||
bot.send_photo(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -171,12 +171,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_photo(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_photo(self.id, *args, **kwargs)
|
||||
|
||||
def send_audio(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_audio(User.chat_id, *args, **kwargs)
|
||||
bot.send_audio(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -184,12 +184,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_audio(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_audio(self.id, *args, **kwargs)
|
||||
|
||||
def send_document(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_document(User.chat_id, *args, **kwargs)
|
||||
bot.send_document(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -197,12 +197,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_document(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_document(self.id, *args, **kwargs)
|
||||
|
||||
def send_sticker(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_sticker(User.chat_id, *args, **kwargs)
|
||||
bot.send_sticker(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -210,12 +210,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_sticker(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_sticker(self.id, *args, **kwargs)
|
||||
|
||||
def send_video(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_video(User.chat_id, *args, **kwargs)
|
||||
bot.send_video(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -223,12 +223,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_video(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_video(self.id, *args, **kwargs)
|
||||
|
||||
def send_video_note(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_video_note(User.chat_id, *args, **kwargs)
|
||||
bot.send_video_note(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -236,12 +236,12 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_video_note(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_video_note(self.id, *args, **kwargs)
|
||||
|
||||
def send_voice(self, *args, **kwargs):
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_voice(User.chat_id, *args, **kwargs)
|
||||
bot.send_voice(User.id, *args, **kwargs)
|
||||
|
||||
Where User is the current instance.
|
||||
|
||||
@@ -249,4 +249,4 @@ class User(TelegramObject):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
|
||||
"""
|
||||
return self.bot.send_voice(chat_id=self.id, *args, **kwargs)
|
||||
return self.bot.send_voice(self.id, *args, **kwargs)
|
||||
|
||||
@@ -145,9 +145,14 @@ class Request(object):
|
||||
dict: A JSON parsed as Python dict with results - on error this dict will be empty.
|
||||
|
||||
"""
|
||||
decoded_s = json_data.decode('utf-8')
|
||||
|
||||
try:
|
||||
decoded_s = json_data.decode('utf-8')
|
||||
data = json.loads(decoded_s)
|
||||
except UnicodeDecodeError:
|
||||
logging.getLogger(__name__).debug(
|
||||
'Logging raw invalid UTF-8 response:\n%r', json_data)
|
||||
raise TelegramError('Server response could not be decoded using UTF-8')
|
||||
except ValueError:
|
||||
raise TelegramError('Invalid server response')
|
||||
|
||||
|
||||
Vendored
+1
-1
Submodule telegram/vendor/ptb_urllib3 updated: 06d04e451f...2c6446aa6c
+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__ = '10.0.1'
|
||||
__version__ = '10.1.0'
|
||||
|
||||
+20
-13
@@ -126,52 +126,59 @@ class TestChat(object):
|
||||
|
||||
def test_instance_method_send_message(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and args[1] == 'test'
|
||||
return args[1] == chat.id and args[2] == 'test'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_message', test)
|
||||
assert chat.send_message('test')
|
||||
|
||||
def test_instance_method_send_photo(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return args[1] == chat.id and args[2] == 'test_photo'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_photo', test)
|
||||
assert chat.send_photo('test_photo')
|
||||
|
||||
def test_instance_method_send_audio(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['audio'] == 'test_audio'
|
||||
return args[1] == chat.id and args[2] == 'test_audio'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_audio', test)
|
||||
assert chat.send_audio(audio='test_audio')
|
||||
assert chat.send_audio('test_audio')
|
||||
|
||||
def test_instance_method_send_document(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['document'] == 'test_document'
|
||||
return args[1] == chat.id and args[2] == 'test_document'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_document', test)
|
||||
assert chat.send_document(document='test_document')
|
||||
assert chat.send_document('test_document')
|
||||
|
||||
def test_instance_method_send_sticker(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['sticker'] == 'test_sticker'
|
||||
return args[1] == chat.id and args[2] == 'test_sticker'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_sticker', test)
|
||||
assert chat.send_sticker(sticker='test_sticker')
|
||||
assert chat.send_sticker('test_sticker')
|
||||
|
||||
def test_instance_method_send_video(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['video'] == 'test_video'
|
||||
return args[1] == chat.id and args[2] == 'test_video'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_video', test)
|
||||
assert chat.send_video(video='test_video')
|
||||
assert chat.send_video('test_video')
|
||||
|
||||
def test_instance_method_send_video_note(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['video_note'] == 'test_video_note'
|
||||
return args[1] == chat.id and args[2] == 'test_video_note'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_video_note', test)
|
||||
assert chat.send_video_note(video_note='test_video_note')
|
||||
assert chat.send_video_note('test_video_note')
|
||||
|
||||
def test_instance_method_send_voice(self, monkeypatch, chat):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == chat.id and kwargs['voice'] == 'test_voice'
|
||||
return args[1] == chat.id and args[2] == 'test_voice'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_voice', test)
|
||||
assert chat.send_voice(voice='test_voice')
|
||||
assert chat.send_voice('test_voice')
|
||||
|
||||
def test_equality(self):
|
||||
a = Chat(self.id, self.title, self.type)
|
||||
|
||||
@@ -21,7 +21,7 @@ import pytest
|
||||
|
||||
from telegram import (Message, Update, Chat, Bot, User, CallbackQuery, InlineQuery,
|
||||
ChosenInlineResult, ShippingQuery, PreCheckoutQuery)
|
||||
from telegram.ext import CommandHandler, Filters
|
||||
from telegram.ext import CommandHandler, Filters, BaseFilter
|
||||
|
||||
message = Message(1, User(1, '', False), None, Chat(1, ''), text='test')
|
||||
|
||||
@@ -246,3 +246,22 @@ class TestCommandHandler(object):
|
||||
def test_other_update_types(self, false_update):
|
||||
handler = CommandHandler('test', self.callback_basic)
|
||||
assert not handler.check_update(false_update)
|
||||
|
||||
def test_filters_for_wrong_command(self, message):
|
||||
"""Filters should not be executed if the command does not match the handler"""
|
||||
|
||||
class TestFilter(BaseFilter):
|
||||
def __init__(self):
|
||||
self.tested = False
|
||||
|
||||
def filter(self, message):
|
||||
self.tested = True
|
||||
|
||||
test_filter = TestFilter()
|
||||
|
||||
handler = CommandHandler('foo', self.callback_basic, filters=test_filter)
|
||||
message.text = '/bar'
|
||||
|
||||
handler.check_update(Update(0, message=message))
|
||||
|
||||
assert not test_filter.tested
|
||||
|
||||
+137
-1
@@ -20,8 +20,9 @@ import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import Message, User, Chat, MessageEntity
|
||||
from telegram import Message, User, Chat, MessageEntity, Document
|
||||
from telegram.ext import Filters, BaseFilter
|
||||
import re
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@@ -51,6 +52,22 @@ class TestFilters(object):
|
||||
message.text = '/test'
|
||||
assert Filters.command(message)
|
||||
|
||||
def test_filters_regex(self, message):
|
||||
message.text = '/start deep-linked param'
|
||||
assert Filters.regex(r'deep-linked param')(message)
|
||||
message.text = '/help'
|
||||
assert Filters.regex(r'help')(message)
|
||||
message.text = '/help'
|
||||
assert Filters.regex('help')(message)
|
||||
|
||||
message.text = 'test'
|
||||
assert not Filters.regex(r'fail')(message)
|
||||
assert Filters.regex(r'test')(message)
|
||||
assert Filters.regex(re.compile(r'test'))(message)
|
||||
|
||||
message.text = 'i love python'
|
||||
assert Filters.regex(r'.\b[lo]{2}ve python')(message)
|
||||
|
||||
def test_filters_reply(self, message):
|
||||
another_message = Message(1, User(1, 'TestOther', False), datetime.datetime.now(),
|
||||
Chat(0, 'private'))
|
||||
@@ -69,6 +86,105 @@ class TestFilters(object):
|
||||
message.document = 'test'
|
||||
assert Filters.document(message)
|
||||
|
||||
def test_filters_document_type(self, message):
|
||||
message.document = Document("file_id", mime_type="application/vnd.android.package-archive")
|
||||
assert Filters.document.apk(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.doc(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "application/msword"
|
||||
assert Filters.document.doc(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.docx(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "application/vnd.openxmlformats-" \
|
||||
"officedocument.wordprocessingml.document"
|
||||
assert Filters.document.docx(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.exe(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "application/x-ms-dos-executable"
|
||||
assert Filters.document.exe(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.docx(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "video/mp4"
|
||||
assert Filters.document.gif(message)
|
||||
assert Filters.document.video(message)
|
||||
assert not Filters.document.jpg(message)
|
||||
assert not Filters.document.text(message)
|
||||
|
||||
message.document.mime_type = "image/jpeg"
|
||||
assert Filters.document.jpg(message)
|
||||
assert Filters.document.image(message)
|
||||
assert not Filters.document.mp3(message)
|
||||
assert not Filters.document.video(message)
|
||||
|
||||
message.document.mime_type = "audio/mpeg"
|
||||
assert Filters.document.mp3(message)
|
||||
assert Filters.document.audio(message)
|
||||
assert not Filters.document.pdf(message)
|
||||
assert not Filters.document.image(message)
|
||||
|
||||
message.document.mime_type = "application/pdf"
|
||||
assert Filters.document.pdf(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.py(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "text/x-python"
|
||||
assert Filters.document.py(message)
|
||||
assert Filters.document.text(message)
|
||||
assert not Filters.document.svg(message)
|
||||
assert not Filters.document.application(message)
|
||||
|
||||
message.document.mime_type = "image/svg+xml"
|
||||
assert Filters.document.svg(message)
|
||||
assert Filters.document.image(message)
|
||||
assert not Filters.document.txt(message)
|
||||
assert not Filters.document.video(message)
|
||||
|
||||
message.document.mime_type = "text/plain"
|
||||
assert Filters.document.txt(message)
|
||||
assert Filters.document.text(message)
|
||||
assert not Filters.document.targz(message)
|
||||
assert not Filters.document.application(message)
|
||||
|
||||
message.document.mime_type = "application/x-compressed-tar"
|
||||
assert Filters.document.targz(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.wav(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "audio/x-wav"
|
||||
assert Filters.document.wav(message)
|
||||
assert Filters.document.audio(message)
|
||||
assert not Filters.document.xml(message)
|
||||
assert not Filters.document.image(message)
|
||||
|
||||
message.document.mime_type = "application/xml"
|
||||
assert Filters.document.xml(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.zip(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "application/zip"
|
||||
assert Filters.document.zip(message)
|
||||
assert Filters.document.application(message)
|
||||
assert not Filters.document.apk(message)
|
||||
assert not Filters.document.audio(message)
|
||||
|
||||
message.document.mime_type = "image/x-rgb"
|
||||
assert not Filters.document.category("application/")(message)
|
||||
assert not Filters.document.mime_type("application/x-sh")(message)
|
||||
message.document.mime_type = "application/x-sh"
|
||||
assert Filters.document.category("application/")(message)
|
||||
assert Filters.document.mime_type("application/x-sh")(message)
|
||||
|
||||
def test_filters_photo(self, message):
|
||||
assert not Filters.photo(message)
|
||||
message.photo = 'test'
|
||||
@@ -89,6 +205,11 @@ class TestFilters(object):
|
||||
message.voice = 'test'
|
||||
assert Filters.voice(message)
|
||||
|
||||
def test_filters_video_note(self, message):
|
||||
assert not Filters.video_note(message)
|
||||
message.video_note = 'test'
|
||||
assert Filters.video_note(message)
|
||||
|
||||
def test_filters_contact(self, message):
|
||||
assert not Filters.contact(message)
|
||||
message.contact = 'test'
|
||||
@@ -189,6 +310,21 @@ class TestFilters(object):
|
||||
second = MessageEntity.de_json(second, None)
|
||||
message.entities = [message_entity, second]
|
||||
assert Filters.entity(message_entity.type)(message)
|
||||
assert not Filters.caption_entity(message_entity.type)(message)
|
||||
|
||||
def test_caption_entities_filter(self, message, message_entity):
|
||||
message.caption_entities = [message_entity]
|
||||
assert Filters.caption_entity(message_entity.type)(message)
|
||||
|
||||
message.caption_entities = []
|
||||
assert not Filters.caption_entity(MessageEntity.MENTION)(message)
|
||||
|
||||
second = message_entity.to_dict()
|
||||
second['type'] = 'bold'
|
||||
second = MessageEntity.de_json(second, None)
|
||||
message.caption_entities = [message_entity, second]
|
||||
assert Filters.caption_entity(message_entity.type)(message)
|
||||
assert not Filters.entity(message_entity.type)(message)
|
||||
|
||||
def test_private_filter(self, message):
|
||||
assert Filters.private(message)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
# 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/].
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from telegram import InputFile
|
||||
|
||||
|
||||
class TestInputFile(object):
|
||||
png = os.path.join('tests', 'data', 'game.png')
|
||||
|
||||
def test_subprocess_pipe(self):
|
||||
if sys.platform == 'win32':
|
||||
cmd = ['type', self.png]
|
||||
else:
|
||||
cmd = ['cat', self.png]
|
||||
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=(sys.platform == 'win32'))
|
||||
in_file = InputFile({'photo': proc.stdout})
|
||||
|
||||
assert in_file.input_file_content == open(self.png, 'rb').read()
|
||||
assert in_file.mimetype == 'image/png'
|
||||
assert in_file.filename == 'image.png'
|
||||
|
||||
proc.kill()
|
||||
@@ -173,6 +173,11 @@ class TestMessage(object):
|
||||
text_html = self.test_message.text_html
|
||||
assert text_html == test_html_string
|
||||
|
||||
def test_text_html_empty(self, message):
|
||||
message.text = None
|
||||
message.caption = "test"
|
||||
assert message.text_html is None
|
||||
|
||||
def test_text_html_urled(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>. '
|
||||
@@ -186,6 +191,11 @@ class TestMessage(object):
|
||||
text_markdown = self.test_message.text_markdown
|
||||
assert text_markdown == test_md_string
|
||||
|
||||
def test_text_markdown_empty(self, message):
|
||||
message.text = None
|
||||
message.caption = "test"
|
||||
assert message.text_markdown is None
|
||||
|
||||
def test_text_markdown_urled(self):
|
||||
test_md_string = ('Test for <*bold*, _ita\_lic_, `code`, [links](http://github.com/) and '
|
||||
'```pre```. [http://google.com](http://google.com)')
|
||||
@@ -215,6 +225,11 @@ class TestMessage(object):
|
||||
caption_html = self.test_message.caption_html
|
||||
assert caption_html == test_html_string
|
||||
|
||||
def test_caption_html_empty(self, message):
|
||||
message.text = "test"
|
||||
message.caption = None
|
||||
assert message.caption_html is None
|
||||
|
||||
def test_caption_html_urled(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>. '
|
||||
@@ -228,6 +243,11 @@ class TestMessage(object):
|
||||
caption_markdown = self.test_message.caption_markdown
|
||||
assert caption_markdown == test_md_string
|
||||
|
||||
def test_caption_markdown_empty(self, message):
|
||||
message.text = "test"
|
||||
message.caption = None
|
||||
assert message.caption_markdown is None
|
||||
|
||||
def test_caption_markdown_urled(self):
|
||||
test_md_string = ('Test for <*bold*, _ita\_lic_, `code`, [links](http://github.com/) and '
|
||||
'```pre```. [http://google.com](http://google.com)')
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ from telegram import Sticker, TelegramError, PhotoSize, InputFile
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def photo_file():
|
||||
f = open('tests/data/telegram.jpg', 'rb')
|
||||
f = open(u'tests/data/telegram.jpg', 'rb')
|
||||
yield f
|
||||
f.close()
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
# 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/].
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import TelegramError
|
||||
from telegram.utils.request import Request
|
||||
|
||||
|
||||
def test_parse_illegal_callback_data():
|
||||
"""
|
||||
Clients can send arbitrary bytes in callback data.
|
||||
Make sure the correct error is raised in this case.
|
||||
"""
|
||||
server_response = b'{"invalid utf-8": "\x80"}'
|
||||
|
||||
with pytest.raises(TelegramError, match='Server response could not be decoded using UTF-8'):
|
||||
Request._parse(server_response)
|
||||
+26
-19
@@ -42,8 +42,8 @@ def user(bot):
|
||||
class TestUser(object):
|
||||
id = 1
|
||||
is_bot = True
|
||||
first_name = 'first_name'
|
||||
last_name = 'last_name'
|
||||
first_name = u'first\u2022name'
|
||||
last_name = u'last\u2022name'
|
||||
username = 'username'
|
||||
language_code = 'en_us'
|
||||
|
||||
@@ -85,16 +85,16 @@ class TestUser(object):
|
||||
def test_name(self, user):
|
||||
assert user.name == '@username'
|
||||
user.username = None
|
||||
assert user.name == 'first_name last_name'
|
||||
assert user.name == u'first\u2022name last\u2022name'
|
||||
user.last_name = None
|
||||
assert user.name == 'first_name'
|
||||
assert user.name == u'first\u2022name'
|
||||
user.username = self.username
|
||||
assert user.name == '@username'
|
||||
|
||||
def test_full_name(self, user):
|
||||
assert user.full_name == 'first_name last_name'
|
||||
assert user.full_name == u'first\u2022name last\u2022name'
|
||||
user.last_name = None
|
||||
assert user.full_name == 'first_name'
|
||||
assert user.full_name == u'first\u2022name'
|
||||
|
||||
def test_get_profile_photos(self, monkeypatch, user):
|
||||
def test(_, *args, **kwargs):
|
||||
@@ -105,52 +105,59 @@ class TestUser(object):
|
||||
|
||||
def test_instance_method_send_message(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and args[1] == 'test'
|
||||
return args[1] == user.id and args[2] == 'test'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_message', test)
|
||||
assert user.send_message('test')
|
||||
|
||||
def test_instance_method_send_photo(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return args[1] == user.id and args[2] == 'test_photo'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_photo', test)
|
||||
assert user.send_photo('test_photo')
|
||||
|
||||
def test_instance_method_send_audio(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['audio'] == 'test_audio'
|
||||
return args[1] == user.id and args[2] == 'test_audio'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_audio', test)
|
||||
assert user.send_audio(audio='test_audio')
|
||||
assert user.send_audio('test_audio')
|
||||
|
||||
def test_instance_method_send_document(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['document'] == 'test_document'
|
||||
return args[1] == user.id and args[2] == 'test_document'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_document', test)
|
||||
assert user.send_document(document='test_document')
|
||||
assert user.send_document('test_document')
|
||||
|
||||
def test_instance_method_send_sticker(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['sticker'] == 'test_sticker'
|
||||
return args[1] == user.id and args[2] == 'test_sticker'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_sticker', test)
|
||||
assert user.send_sticker(sticker='test_sticker')
|
||||
assert user.send_sticker('test_sticker')
|
||||
|
||||
def test_instance_method_send_video(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['video'] == 'test_video'
|
||||
return args[1] == user.id and args[2] == 'test_video'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_video', test)
|
||||
assert user.send_video(video='test_video')
|
||||
assert user.send_video('test_video')
|
||||
|
||||
def test_instance_method_send_video_note(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['video_note'] == 'test_video_note'
|
||||
return args[1] == user.id and args[2] == 'test_video_note'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_video_note', test)
|
||||
assert user.send_video_note(video_note='test_video_note')
|
||||
assert user.send_video_note('test_video_note')
|
||||
|
||||
def test_instance_method_send_voice(self, monkeypatch, user):
|
||||
def test(*args, **kwargs):
|
||||
return kwargs['chat_id'] == user.id and kwargs['voice'] == 'test_voice'
|
||||
return args[1] == user.id and args[2] == 'test_voice'
|
||||
|
||||
monkeypatch.setattr('telegram.Bot.send_voice', test)
|
||||
assert user.send_voice(voice='test_voice')
|
||||
assert user.send_voice('test_voice')
|
||||
|
||||
def test_equality(self):
|
||||
a = User(self.id, self.first_name, self.is_bot, self.last_name)
|
||||
|
||||
Reference in New Issue
Block a user