mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-23 06:50:29 +01:00
Merge pull request #308 from python-telegram-bot/bot2.1
New methods for Bot 2.1 API
This commit is contained in:
commit
792ad62fe8
26 changed files with 516 additions and 126 deletions
|
@ -23,6 +23,7 @@ from sys import version_info
|
||||||
from .base import TelegramObject
|
from .base import TelegramObject
|
||||||
from .user import User
|
from .user import User
|
||||||
from .chat import Chat
|
from .chat import Chat
|
||||||
|
from .chatmember import ChatMember
|
||||||
from .photosize import PhotoSize
|
from .photosize import PhotoSize
|
||||||
from .audio import Audio
|
from .audio import Audio
|
||||||
from .voice import Voice
|
from .voice import Voice
|
||||||
|
@ -82,24 +83,25 @@ from .bot import Bot
|
||||||
|
|
||||||
__author__ = 'devs@python-telegram-bot.org'
|
__author__ = 'devs@python-telegram-bot.org'
|
||||||
__version__ = '4.1.2'
|
__version__ = '4.1.2'
|
||||||
__all__ = ['Audio', 'Bot', 'Chat', 'ChatAction', 'ChosenInlineResult', 'CallbackQuery', 'Contact',
|
__all__ = ['Audio', 'Bot', 'Chat', 'ChatMember', 'ChatAction', 'ChosenInlineResult',
|
||||||
'Document', 'Emoji', 'File', 'ForceReply', 'InlineKeyboardButton',
|
'CallbackQuery', 'Contact', 'Document', 'Emoji', 'File', 'ForceReply',
|
||||||
'InlineKeyboardMarkup', 'InlineQuery', 'InlineQueryResult', 'InlineQueryResult',
|
'InlineKeyboardButton', 'InlineKeyboardMarkup', 'InlineQuery', 'InlineQueryResult',
|
||||||
'InlineQueryResultArticle', 'InlineQueryResultAudio', 'InlineQueryResultCachedAudio',
|
'InlineQueryResult', 'InlineQueryResultArticle', 'InlineQueryResultAudio',
|
||||||
'InlineQueryResultCachedDocument', 'InlineQueryResultCachedGif',
|
'InlineQueryResultCachedAudio', 'InlineQueryResultCachedDocument',
|
||||||
'InlineQueryResultCachedMpeg4Gif', 'InlineQueryResultCachedPhoto',
|
'InlineQueryResultCachedGif', 'InlineQueryResultCachedMpeg4Gif',
|
||||||
'InlineQueryResultCachedSticker', 'InlineQueryResultCachedVideo',
|
'InlineQueryResultCachedPhoto', 'InlineQueryResultCachedSticker',
|
||||||
'InlineQueryResultCachedVoice', 'InlineQueryResultContact', 'InlineQueryResultDocument',
|
'InlineQueryResultCachedVideo', 'InlineQueryResultCachedVoice',
|
||||||
'InlineQueryResultGif', 'InlineQueryResultLocation', 'InlineQueryResultMpeg4Gif',
|
'InlineQueryResultContact', 'InlineQueryResultDocument', 'InlineQueryResultGif',
|
||||||
'InlineQueryResultPhoto', 'InlineQueryResultVenue', 'InlineQueryResultVideo',
|
'InlineQueryResultLocation', 'InlineQueryResultMpeg4Gif', 'InlineQueryResultPhoto',
|
||||||
'InlineQueryResultVoice', 'InputContactMessageContent', 'InputFile',
|
'InlineQueryResultVenue', 'InlineQueryResultVideo', 'InlineQueryResultVoice',
|
||||||
'InputLocationMessageContent', 'InputMessageContent', 'InputTextMessageContent',
|
'InputContactMessageContent', 'InputFile', 'InputLocationMessageContent',
|
||||||
'InputVenueMessageContent', 'KeyboardButton', 'Location', 'Message', 'MessageEntity',
|
'InputMessageContent', 'InputTextMessageContent', 'InputVenueMessageContent',
|
||||||
'NullHandler', 'ParseMode', 'PhotoSize', 'ReplyKeyboardHide', 'ReplyKeyboardMarkup',
|
'KeyboardButton', 'Location', 'Message', 'MessageEntity', 'NullHandler', 'ParseMode',
|
||||||
'ReplyMarkup', 'Sticker', 'TelegramError', 'TelegramObject', 'Update', 'User',
|
'PhotoSize', 'ReplyKeyboardHide', 'ReplyKeyboardMarkup', 'ReplyMarkup', 'Sticker',
|
||||||
'UserProfilePhotos', 'Venue', 'Video', 'Voice']
|
'TelegramError', 'TelegramObject', 'Update', 'User', 'UserProfilePhotos', 'Venue',
|
||||||
|
'Video', 'Voice']
|
||||||
|
|
||||||
if version_info < (2, 7):
|
if version_info < (2, 7):
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
warn("python-telegram-bot will stop supporting Python 2.6 in a future release. "
|
warn("python-telegram-bot will stop supporting Python 2.6 in a future release. "
|
||||||
"Please upgrade your Python!")
|
"Please upgrade your Python version to at least Python 2.7!")
|
||||||
|
|
175
telegram/bot.py
175
telegram/bot.py
|
@ -19,11 +19,11 @@
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains a object that represents a Telegram Bot."""
|
"""This module contains a object that represents a Telegram Bot."""
|
||||||
|
|
||||||
import logging
|
|
||||||
import functools
|
import functools
|
||||||
|
import logging
|
||||||
|
|
||||||
from telegram import (User, Message, Update, UserProfilePhotos, File, ReplyMarkup, TelegramObject,
|
from telegram import (User, Message, Update, Chat, ChatMember, UserProfilePhotos, File,
|
||||||
NullHandler)
|
ReplyMarkup, TelegramObject, NullHandler)
|
||||||
from telegram.error import InvalidToken
|
from telegram.error import InvalidToken
|
||||||
from telegram.utils import request
|
from telegram.utils import request
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ class Bot(TelegramObject):
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def getMe(self):
|
def getMe(self, **kwargs):
|
||||||
"""A simple method for testing your bot's auth token.
|
"""A simple method for testing your bot's auth token.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -1182,7 +1182,7 @@ class Bot(TelegramObject):
|
||||||
return url, data
|
return url, data
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def getUpdates(self, offset=None, limit=100, timeout=0, network_delay=.2):
|
def getUpdates(self, offset=None, limit=100, timeout=0, network_delay=.2, **kwargs):
|
||||||
"""Use this method to receive incoming updates using long polling.
|
"""Use this method to receive incoming updates using long polling.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -1271,6 +1271,166 @@ class Bot(TelegramObject):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@log
|
||||||
|
def leaveChat(self, chat_id, **kwargs):
|
||||||
|
"""Use this method for your bot to leave a group, supergroup or
|
||||||
|
channel.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id:
|
||||||
|
Unique identifier for the target chat or username of the target
|
||||||
|
channel (in the format @channelusername).
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
timeout (Optional[float]): If this value is specified, use it as
|
||||||
|
the definitive timeout (in seconds) for urlopen() operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: On success, `True` is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = '{0}/leaveChat'.format(self.base_url)
|
||||||
|
|
||||||
|
data = {'chat_id': chat_id}
|
||||||
|
|
||||||
|
result = request.post(url, data, timeout=kwargs.get('timeout'))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@log
|
||||||
|
def getChat(self, chat_id, **kwargs):
|
||||||
|
"""Use this method to get up to date information about the chat
|
||||||
|
(current name of the user for one-on-one conversations, current
|
||||||
|
username of a user, group or channel, etc.).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id:
|
||||||
|
Unique identifier for the target chat or username of the target
|
||||||
|
channel (in the format @channelusername).
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
timeout (Optional[float]): If this value is specified, use it as
|
||||||
|
the definitive timeout (in seconds) for urlopen() operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.Chat`: On success, :class:`telegram.Chat` is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = '{0}/getChat'.format(self.base_url)
|
||||||
|
|
||||||
|
data = {'chat_id': chat_id}
|
||||||
|
|
||||||
|
result = request.post(url, data, timeout=kwargs.get('timeout'))
|
||||||
|
|
||||||
|
return Chat.de_json(result)
|
||||||
|
|
||||||
|
@log
|
||||||
|
def getChatAdministrators(self, chat_id, **kwargs):
|
||||||
|
"""Use this method to get a list of administrators in a chat. On
|
||||||
|
success, returns an Array of ChatMember objects that contains
|
||||||
|
information about all chat administrators except other bots. If the
|
||||||
|
chat is a group or a supergroup and no administrators were appointed,
|
||||||
|
only the creator will be returned.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id:
|
||||||
|
Unique identifier for the target chat or username of the target
|
||||||
|
channel (in the format @channelusername).
|
||||||
|
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
timeout (Optional[float]): If this value is specified, use it as
|
||||||
|
the definitive timeout (in seconds) for urlopen() operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[:class:`telegram.ChatMember`]: On success, a list of
|
||||||
|
:class:`telegram.ChatMember` objects are returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = '{0}/getChatAdministrators'.format(self.base_url)
|
||||||
|
|
||||||
|
data = {'chat_id': chat_id}
|
||||||
|
|
||||||
|
result = request.post(url, data, timeout=kwargs.get('timeout'))
|
||||||
|
|
||||||
|
return [ChatMember.de_json(x) for x in result]
|
||||||
|
|
||||||
|
@log
|
||||||
|
def getChatMembersCount(self, chat_id, **kwargs):
|
||||||
|
"""Use this method to get the number of members in a chat.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id:
|
||||||
|
Unique identifier for the target chat or username of the target
|
||||||
|
channel (in the format @channelusername).
|
||||||
|
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
timeout (Optional[float]): If this value is specified, use it as
|
||||||
|
the definitive timeout (in seconds) for urlopen() operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: On success, an `int` is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = '{0}/getChatMembersCount'.format(self.base_url)
|
||||||
|
|
||||||
|
data = {'chat_id': chat_id}
|
||||||
|
|
||||||
|
result = request.post(url, data, timeout=kwargs.get('timeout'))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@log
|
||||||
|
def getChatMember(self, chat_id, user_id, **kwargs):
|
||||||
|
"""Use this method to get information about a member of a chat.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id:
|
||||||
|
Unique identifier for the target chat or username of the target
|
||||||
|
channel (in the format @channelusername).
|
||||||
|
user_id:
|
||||||
|
Unique identifier of the target user.
|
||||||
|
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
timeout (Optional[float]): If this value is specified, use it as
|
||||||
|
the definitive timeout (in seconds) for urlopen() operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.ChatMember`: On success,
|
||||||
|
:class:`telegram.ChatMember` is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = '{0}/getChatMember'.format(self.base_url)
|
||||||
|
|
||||||
|
data = {'chat_id': chat_id, 'user_id': user_id}
|
||||||
|
|
||||||
|
result = request.post(url, data, timeout=kwargs.get('timeout'))
|
||||||
|
|
||||||
|
return ChatMember.de_json(result)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def de_json(data):
|
def de_json(data):
|
||||||
data = super(Bot, Bot).de_json(data)
|
data = super(Bot, Bot).de_json(data)
|
||||||
|
@ -1314,3 +1474,8 @@ class Bot(TelegramObject):
|
||||||
edit_message_reply_markup = editMessageReplyMarkup
|
edit_message_reply_markup = editMessageReplyMarkup
|
||||||
get_updates = getUpdates
|
get_updates = getUpdates
|
||||||
set_webhook = setWebhook
|
set_webhook = setWebhook
|
||||||
|
leave_chat = leaveChat
|
||||||
|
get_chat = getChat
|
||||||
|
get_chat_administrators = getChatAdministrators
|
||||||
|
get_chat_member = getChatMember
|
||||||
|
get_chat_members_count = getChatMembersCount
|
||||||
|
|
|
@ -42,6 +42,11 @@ class Chat(TelegramObject):
|
||||||
type (Optional[str]):
|
type (Optional[str]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
PRIVATE = 'private'
|
||||||
|
GROUP = 'group'
|
||||||
|
SUPERGROUP = 'supergroup'
|
||||||
|
CHANNEL = 'channel'
|
||||||
|
|
||||||
def __init__(self, id, type, **kwargs):
|
def __init__(self, id, type, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.id = int(id)
|
self.id = int(id)
|
||||||
|
|
62
telegram/chatmember.py
Normal file
62
telegram/chatmember.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# A library that provides a Python interface to the Telegram Bot API
|
||||||
|
# Copyright (C) 2015-2016
|
||||||
|
# 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 a object that represents a Telegram ChatMember."""
|
||||||
|
|
||||||
|
from telegram import User, TelegramObject
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMember(TelegramObject):
|
||||||
|
"""This object represents a Telegram ChatMember.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
status (str): The member's status in the chat. Can be 'creator', 'administrator', 'member',
|
||||||
|
'left' or 'kicked'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`):
|
||||||
|
status (str):
|
||||||
|
"""
|
||||||
|
|
||||||
|
CREATOR = 'creator'
|
||||||
|
ADMINISTRATOR = 'administrator'
|
||||||
|
MEMBER = 'member'
|
||||||
|
LEFT = 'left'
|
||||||
|
KICKED = 'kicked'
|
||||||
|
|
||||||
|
def __init__(self, user, status, **kwargs):
|
||||||
|
# Required
|
||||||
|
self.user = user
|
||||||
|
self.status = status
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def de_json(data):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
data (dict):
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
telegram.ChatMember:
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
data['user'] = User.de_json(data.get('user'))
|
||||||
|
|
||||||
|
return ChatMember(**data)
|
|
@ -41,7 +41,13 @@ class ChosenInlineResult(TelegramObject):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, result_id, from_user, query, location=None, inline_message_id=None):
|
def __init__(self,
|
||||||
|
result_id,
|
||||||
|
from_user,
|
||||||
|
query,
|
||||||
|
location=None,
|
||||||
|
inline_message_id=None,
|
||||||
|
**kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.result_id = result_id
|
self.result_id = result_id
|
||||||
self.from_user = from_user
|
self.from_user = from_user
|
||||||
|
|
|
@ -51,6 +51,7 @@ class TelegramError(Exception):
|
||||||
|
|
||||||
msg = _lstrip_str(message, 'Error: ')
|
msg = _lstrip_str(message, 'Error: ')
|
||||||
msg = _lstrip_str(msg, '[Error]: ')
|
msg = _lstrip_str(msg, '[Error]: ')
|
||||||
|
msg = _lstrip_str(msg, 'Bad Request: ')
|
||||||
if msg != message:
|
if msg != message:
|
||||||
# api_error - capitalize the msg...
|
# api_error - capitalize the msg...
|
||||||
msg = msg.capitalize()
|
msg = msg.capitalize()
|
||||||
|
@ -76,6 +77,10 @@ class NetworkError(TelegramError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BadRequest(NetworkError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TimedOut(NetworkError):
|
class TimedOut(NetworkError):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -34,6 +34,8 @@ class CommandHandler(Handler):
|
||||||
callback (function): A function that takes ``bot, update`` as
|
callback (function): A function that takes ``bot, update`` as
|
||||||
positional arguments. It will be called when the ``check_update``
|
positional arguments. It will be called when the ``check_update``
|
||||||
has determined that an update should be processed by this handler.
|
has determined that an update should be processed by this handler.
|
||||||
|
allow_edited (Optional[bool]): If the handler should also accept edited messages.
|
||||||
|
Default is ``False``
|
||||||
pass_args (optional[bool]): If the handler should be passed the
|
pass_args (optional[bool]): If the handler should be passed the
|
||||||
arguments passed to the command as a keyword argument called `
|
arguments passed to the command as a keyword argument called `
|
||||||
``args``. It will contain a list of strings, which is the text
|
``args``. It will contain a list of strings, which is the text
|
||||||
|
@ -43,21 +45,35 @@ class CommandHandler(Handler):
|
||||||
be used to insert updates. Default is ``False``
|
be used to insert updates. Default is ``False``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, command, callback, pass_args=False, pass_update_queue=False):
|
def __init__(self,
|
||||||
|
command,
|
||||||
|
callback,
|
||||||
|
allow_edited=False,
|
||||||
|
pass_args=False,
|
||||||
|
pass_update_queue=False):
|
||||||
super(CommandHandler, self).__init__(callback, pass_update_queue)
|
super(CommandHandler, self).__init__(callback, pass_update_queue)
|
||||||
self.command = command
|
self.command = command
|
||||||
|
self.allow_edited = allow_edited
|
||||||
self.pass_args = pass_args
|
self.pass_args = pass_args
|
||||||
|
|
||||||
def check_update(self, update):
|
def check_update(self, update):
|
||||||
return (isinstance(update, Update) and update.message and update.message.text
|
if (isinstance(update, Update)
|
||||||
and update.message.text.startswith('/')
|
and (update.message or update.edited_message and self.allow_edited)):
|
||||||
and update.message.text[1:].split(' ')[0].split('@')[0] == self.command)
|
message = update.message or update.edited_message
|
||||||
|
|
||||||
|
return (message.text and message.text.startswith('/')
|
||||||
|
and message.text[1:].split(' ')[0].split('@')[0] == self.command)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def handle_update(self, update, dispatcher):
|
def handle_update(self, update, dispatcher):
|
||||||
optional_args = self.collect_optional_args(dispatcher)
|
optional_args = self.collect_optional_args(dispatcher)
|
||||||
|
|
||||||
|
message = update.message or update.edited_message
|
||||||
|
|
||||||
if self.pass_args:
|
if self.pass_args:
|
||||||
optional_args['args'] = update.message.text.split(' ')[1:]
|
optional_args['args'] = message.text.split(' ')[1:]
|
||||||
|
|
||||||
self.callback(dispatcher.bot, update, **optional_args)
|
self.callback(dispatcher.bot, update, **optional_args)
|
||||||
|
|
||||||
|
|
|
@ -30,57 +30,56 @@ class Filters(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def text(update):
|
def text(message):
|
||||||
return update.message.text and not update.message.text.startswith('/')
|
return message.text and not message.text.startswith('/')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def command(update):
|
def command(message):
|
||||||
return update.message.text and update.message.text.startswith('/')
|
return message.text and message.text.startswith('/')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def audio(update):
|
def audio(message):
|
||||||
return bool(update.message.audio)
|
return bool(message.audio)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def document(update):
|
def document(message):
|
||||||
return bool(update.message.document)
|
return bool(message.document)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def photo(update):
|
def photo(message):
|
||||||
return bool(update.message.photo)
|
return bool(message.photo)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sticker(update):
|
def sticker(message):
|
||||||
return bool(update.message.sticker)
|
return bool(message.sticker)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def video(update):
|
def video(message):
|
||||||
return bool(update.message.video)
|
return bool(message.video)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def voice(update):
|
def voice(message):
|
||||||
return bool(update.message.voice)
|
return bool(message.voice)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def contact(update):
|
def contact(message):
|
||||||
return bool(update.message.contact)
|
return bool(message.contact)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def location(update):
|
def location(message):
|
||||||
return bool(update.message.location)
|
return bool(message.location)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def venue(update):
|
def venue(message):
|
||||||
return bool(update.message.venue)
|
return bool(message.venue)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def status_update(update):
|
def status_update(message):
|
||||||
return bool(update.message.new_chat_member or update.message.left_chat_member
|
return bool(message.new_chat_member or message.left_chat_member or message.new_chat_title
|
||||||
or update.message.new_chat_title or update.message.new_chat_photo
|
or message.new_chat_photo or message.delete_chat_photo
|
||||||
or update.message.delete_chat_photo or update.message.group_chat_created
|
or message.group_chat_created or message.supergroup_chat_created
|
||||||
or update.message.supergroup_chat_created
|
or message.channel_chat_created or message.migrate_to_chat_id
|
||||||
or update.message.channel_chat_created or update.message.migrate_to_chat_id
|
or message.migrate_from_chat_id or message.pinned_message)
|
||||||
or update.message.migrate_from_chat_id or update.message.pinned_message)
|
|
||||||
|
|
||||||
|
|
||||||
class MessageHandler(Handler):
|
class MessageHandler(Handler):
|
||||||
|
@ -99,23 +98,32 @@ class MessageHandler(Handler):
|
||||||
callback (function): A function that takes ``bot, update`` as
|
callback (function): A function that takes ``bot, update`` as
|
||||||
positional arguments. It will be called when the ``check_update``
|
positional arguments. It will be called when the ``check_update``
|
||||||
has determined that an update should be processed by this handler.
|
has determined that an update should be processed by this handler.
|
||||||
|
allow_edited (Optional[bool]): If the handler should also accept edited messages.
|
||||||
|
Default is ``False``
|
||||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||||
update queue as a keyword argument called ``update_queue``. It can
|
update queue as a keyword argument called ``update_queue``. It can
|
||||||
be used to insert updates. Default is ``False``
|
be used to insert updates. Default is ``False``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, filters, callback, pass_update_queue=False):
|
def __init__(self, filters, callback, allow_edited=False, pass_update_queue=False):
|
||||||
super(MessageHandler, self).__init__(callback, pass_update_queue)
|
super(MessageHandler, self).__init__(callback, pass_update_queue)
|
||||||
self.filters = filters
|
self.filters = filters
|
||||||
|
self.allow_edited = allow_edited
|
||||||
|
|
||||||
def check_update(self, update):
|
def check_update(self, update):
|
||||||
if isinstance(update, Update) and update.message:
|
if (isinstance(update, Update)
|
||||||
|
and (update.message or update.edited_message and self.allow_edited)):
|
||||||
|
|
||||||
if not self.filters:
|
if not self.filters:
|
||||||
res = True
|
res = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
res = any(func(update) for func in self.filters)
|
message = update.message or update.edited_message
|
||||||
|
res = any(func(message) for func in self.filters)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
res = False
|
res = False
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def handle_update(self, update, dispatcher):
|
def handle_update(self, update, dispatcher):
|
||||||
|
|
|
@ -33,7 +33,7 @@ class InlineKeyboardMarkup(ReplyMarkup):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, inline_keyboard):
|
def __init__(self, inline_keyboard, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.inline_keyboard = inline_keyboard
|
self.inline_keyboard = inline_keyboard
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ from telegram import InputMessageContent
|
||||||
class InputContactMessageContent(InputMessageContent):
|
class InputContactMessageContent(InputMessageContent):
|
||||||
"""Base class for Telegram InputContactMessageContent Objects"""
|
"""Base class for Telegram InputContactMessageContent Objects"""
|
||||||
|
|
||||||
def __init__(self, phone_number, first_name, last_name=None):
|
def __init__(self, phone_number, first_name, last_name=None, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.phone_number = phone_number
|
self.phone_number = phone_number
|
||||||
self.first_name = first_name
|
self.first_name = first_name
|
||||||
|
|
|
@ -25,7 +25,7 @@ from telegram import InputMessageContent
|
||||||
class InputLocationMessageContent(InputMessageContent):
|
class InputLocationMessageContent(InputMessageContent):
|
||||||
"""Base class for Telegram InputLocationMessageContent Objects"""
|
"""Base class for Telegram InputLocationMessageContent Objects"""
|
||||||
|
|
||||||
def __init__(self, latitude, longitude):
|
def __init__(self, latitude, longitude, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.latitude = latitude
|
self.latitude = latitude
|
||||||
self.longitude = longitude
|
self.longitude = longitude
|
||||||
|
|
|
@ -39,14 +39,14 @@ class InputMessageContent(TelegramObject):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from telegram import InputLocationMessageContent
|
from telegram import InputVenueMessageContent
|
||||||
return InputLocationMessageContent.de_json(data)
|
return InputVenueMessageContent.de_json(data)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from telegram import InputVenueMessageContent
|
from telegram import InputLocationMessageContent
|
||||||
return InputVenueMessageContent.de_json(data)
|
return InputLocationMessageContent.de_json(data)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ from telegram import InputMessageContent
|
||||||
class InputTextMessageContent(InputMessageContent):
|
class InputTextMessageContent(InputMessageContent):
|
||||||
"""Base class for Telegram InputTextMessageContent Objects"""
|
"""Base class for Telegram InputTextMessageContent Objects"""
|
||||||
|
|
||||||
def __init__(self, message_text, parse_mode=None, disable_web_page_preview=None):
|
def __init__(self, message_text, parse_mode=None, disable_web_page_preview=None, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.message_text = message_text
|
self.message_text = message_text
|
||||||
# Optionals
|
# Optionals
|
||||||
|
|
|
@ -25,7 +25,7 @@ from telegram import InputMessageContent
|
||||||
class InputVenueMessageContent(InputMessageContent):
|
class InputVenueMessageContent(InputMessageContent):
|
||||||
"""Base class for Telegram InputVenueMessageContent Objects"""
|
"""Base class for Telegram InputVenueMessageContent Objects"""
|
||||||
|
|
||||||
def __init__(self, latitude, longitude, title, address, foursquare_id=None):
|
def __init__(self, latitude, longitude, title, address, foursquare_id=None, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.latitude = latitude
|
self.latitude = latitude
|
||||||
self.longitude = longitude
|
self.longitude = longitude
|
||||||
|
|
|
@ -33,7 +33,7 @@ class KeyboardButton(TelegramObject):
|
||||||
request_contact (Optional[bool]):
|
request_contact (Optional[bool]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, text, request_contact=None, request_location=None):
|
def __init__(self, text, request_contact=None, request_location=None, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.text = text
|
self.text = text
|
||||||
# Optionals
|
# Optionals
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Location(TelegramObject):
|
||||||
latitude (float):
|
latitude (float):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, longitude, latitude):
|
def __init__(self, longitude, latitude, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.longitude = float(longitude)
|
self.longitude = float(longitude)
|
||||||
self.latitude = float(latitude)
|
self.latitude = float(latitude)
|
||||||
|
|
|
@ -40,6 +40,7 @@ class Message(TelegramObject):
|
||||||
forward_from_chat (:class:`telegram.Chat`):
|
forward_from_chat (:class:`telegram.Chat`):
|
||||||
forward_date (:class:`datetime.datetime`):
|
forward_date (:class:`datetime.datetime`):
|
||||||
reply_to_message (:class:`telegram.Message`):
|
reply_to_message (:class:`telegram.Message`):
|
||||||
|
edit_date (:class:`datetime.datetime`):
|
||||||
text (str):
|
text (str):
|
||||||
audio (:class:`telegram.Audio`):
|
audio (:class:`telegram.Audio`):
|
||||||
document (:class:`telegram.Document`):
|
document (:class:`telegram.Document`):
|
||||||
|
@ -80,6 +81,7 @@ class Message(TelegramObject):
|
||||||
forward_from_chat (:class:`telegram.Chat`):
|
forward_from_chat (:class:`telegram.Chat`):
|
||||||
forward_date (Optional[:class:`datetime.datetime`]):
|
forward_date (Optional[:class:`datetime.datetime`]):
|
||||||
reply_to_message (Optional[:class:`telegram.Message`]):
|
reply_to_message (Optional[:class:`telegram.Message`]):
|
||||||
|
edit_date (Optional[:class:`datetime.datetime`]):
|
||||||
text (Optional[str]):
|
text (Optional[str]):
|
||||||
audio (Optional[:class:`telegram.Audio`]):
|
audio (Optional[:class:`telegram.Audio`]):
|
||||||
document (Optional[:class:`telegram.Document`]):
|
document (Optional[:class:`telegram.Document`]):
|
||||||
|
@ -113,6 +115,7 @@ class Message(TelegramObject):
|
||||||
self.forward_from_chat = kwargs.get('forward_from_chat')
|
self.forward_from_chat = kwargs.get('forward_from_chat')
|
||||||
self.forward_date = kwargs.get('forward_date')
|
self.forward_date = kwargs.get('forward_date')
|
||||||
self.reply_to_message = kwargs.get('reply_to_message')
|
self.reply_to_message = kwargs.get('reply_to_message')
|
||||||
|
self.edit_date = kwargs.get('edit_date')
|
||||||
self.text = kwargs.get('text', '')
|
self.text = kwargs.get('text', '')
|
||||||
self.entities = kwargs.get('entities', list())
|
self.entities = kwargs.get('entities', list())
|
||||||
self.audio = kwargs.get('audio')
|
self.audio = kwargs.get('audio')
|
||||||
|
@ -162,6 +165,7 @@ class Message(TelegramObject):
|
||||||
data['forward_from_chat'] = Chat.de_json(data.get('forward_from_chat'))
|
data['forward_from_chat'] = Chat.de_json(data.get('forward_from_chat'))
|
||||||
data['forward_date'] = Message._fromtimestamp(data.get('forward_date'))
|
data['forward_date'] = Message._fromtimestamp(data.get('forward_date'))
|
||||||
data['reply_to_message'] = Message.de_json(data.get('reply_to_message'))
|
data['reply_to_message'] = Message.de_json(data.get('reply_to_message'))
|
||||||
|
data['edit_date'] = Message._fromtimestamp(data.get('edit_date'))
|
||||||
data['audio'] = Audio.de_json(data.get('audio'))
|
data['audio'] = Audio.de_json(data.get('audio'))
|
||||||
data['document'] = Document.de_json(data.get('document'))
|
data['document'] = Document.de_json(data.get('document'))
|
||||||
data['photo'] = PhotoSize.de_list(data.get('photo'))
|
data['photo'] = PhotoSize.de_list(data.get('photo'))
|
||||||
|
@ -197,6 +201,8 @@ class Message(TelegramObject):
|
||||||
# Optionals
|
# Optionals
|
||||||
if self.forward_date:
|
if self.forward_date:
|
||||||
data['forward_date'] = self._totimestamp(self.forward_date)
|
data['forward_date'] = self._totimestamp(self.forward_date)
|
||||||
|
if self.edit_date:
|
||||||
|
data['edit_date'] = self._totimestamp(self.edit_date)
|
||||||
if self.photo:
|
if self.photo:
|
||||||
data['photo'] = [p.to_dict() for p in self.photo]
|
data['photo'] = [p.to_dict() for p in self.photo]
|
||||||
if self.entities:
|
if self.entities:
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains a object that represents a Telegram MessageEntity."""
|
"""This module contains a object that represents a Telegram MessageEntity."""
|
||||||
|
|
||||||
from telegram import TelegramObject
|
from telegram import User, TelegramObject
|
||||||
|
|
||||||
|
|
||||||
class MessageEntity(TelegramObject):
|
class MessageEntity(TelegramObject):
|
||||||
|
@ -31,6 +31,7 @@ class MessageEntity(TelegramObject):
|
||||||
offset (int):
|
offset (int):
|
||||||
length (int):
|
length (int):
|
||||||
url (Optional[str]):
|
url (Optional[str]):
|
||||||
|
user (Optional[:class:`telegram.User`]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, type, offset, length, **kwargs):
|
def __init__(self, type, offset, length, **kwargs):
|
||||||
|
@ -40,11 +41,14 @@ class MessageEntity(TelegramObject):
|
||||||
self.length = length
|
self.length = length
|
||||||
# Optionals
|
# Optionals
|
||||||
self.url = kwargs.get('url')
|
self.url = kwargs.get('url')
|
||||||
|
self.user = kwargs.get('user')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def de_json(data):
|
def de_json(data):
|
||||||
data = super(MessageEntity, MessageEntity).de_json(data)
|
data = super(MessageEntity, MessageEntity).de_json(data)
|
||||||
|
|
||||||
|
data['user'] = User.de_json(data.get('user'))
|
||||||
|
|
||||||
return MessageEntity(**data)
|
return MessageEntity(**data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Update(TelegramObject):
|
||||||
Attributes:
|
Attributes:
|
||||||
update_id (int):
|
update_id (int):
|
||||||
message (:class:`telegram.Message`):
|
message (:class:`telegram.Message`):
|
||||||
|
edited_message (:class:`telegram.Message`):
|
||||||
inline_query (:class:`telegram.InlineQuery`):
|
inline_query (:class:`telegram.InlineQuery`):
|
||||||
chosen_inline_result (:class:`telegram.ChosenInlineResult`):
|
chosen_inline_result (:class:`telegram.ChosenInlineResult`):
|
||||||
callback_query (:class:`telegram.CallbackQuery`):
|
callback_query (:class:`telegram.CallbackQuery`):
|
||||||
|
@ -37,6 +38,7 @@ class Update(TelegramObject):
|
||||||
|
|
||||||
Keyword Args:
|
Keyword Args:
|
||||||
message (Optional[:class:`telegram.Message`]):
|
message (Optional[:class:`telegram.Message`]):
|
||||||
|
edited_message (Optional[:class:`telegram.Message`]):
|
||||||
inline_query (Optional[:class:`telegram.InlineQuery`]):
|
inline_query (Optional[:class:`telegram.InlineQuery`]):
|
||||||
chosen_inline_result (Optional[:class:`telegram.ChosenInlineResult`])
|
chosen_inline_result (Optional[:class:`telegram.ChosenInlineResult`])
|
||||||
callback_query (Optional[:class:`telegram.CallbackQuery`]):
|
callback_query (Optional[:class:`telegram.CallbackQuery`]):
|
||||||
|
@ -47,6 +49,7 @@ class Update(TelegramObject):
|
||||||
self.update_id = int(update_id)
|
self.update_id = int(update_id)
|
||||||
# Optionals
|
# Optionals
|
||||||
self.message = kwargs.get('message')
|
self.message = kwargs.get('message')
|
||||||
|
self.edited_message = kwargs.get('edited_message')
|
||||||
self.inline_query = kwargs.get('inline_query')
|
self.inline_query = kwargs.get('inline_query')
|
||||||
self.chosen_inline_result = kwargs.get('chosen_inline_result')
|
self.chosen_inline_result = kwargs.get('chosen_inline_result')
|
||||||
self.callback_query = kwargs.get('callback_query')
|
self.callback_query = kwargs.get('callback_query')
|
||||||
|
@ -64,6 +67,7 @@ class Update(TelegramObject):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
data['message'] = Message.de_json(data.get('message'))
|
data['message'] = Message.de_json(data.get('message'))
|
||||||
|
data['edited_message'] = Message.de_json(data.get('edited_message'))
|
||||||
data['inline_query'] = InlineQuery.de_json(data.get('inline_query'))
|
data['inline_query'] = InlineQuery.de_json(data.get('inline_query'))
|
||||||
data['chosen_inline_result'] = ChosenInlineResult.de_json(data.get('chosen_inline_result'))
|
data['chosen_inline_result'] = ChosenInlineResult.de_json(data.get('chosen_inline_result'))
|
||||||
data['callback_query'] = CallbackQuery.de_json(data.get('callback_query'))
|
data['callback_query'] = CallbackQuery.de_json(data.get('callback_query'))
|
||||||
|
|
|
@ -34,7 +34,7 @@ class UserProfilePhotos(TelegramObject):
|
||||||
photos (List[List[:class:`telegram.PhotoSize`]]):
|
photos (List[List[:class:`telegram.PhotoSize`]]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, total_count, photos):
|
def __init__(self, total_count, photos, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.total_count = int(total_count)
|
self.total_count = int(total_count)
|
||||||
self.photos = photos
|
self.photos = photos
|
||||||
|
|
|
@ -28,7 +28,7 @@ from future.moves.urllib.error import HTTPError, URLError
|
||||||
from future.moves.urllib.request import urlopen, urlretrieve, Request
|
from future.moves.urllib.request import urlopen, urlretrieve, Request
|
||||||
|
|
||||||
from telegram import (InputFile, TelegramError)
|
from telegram import (InputFile, TelegramError)
|
||||||
from telegram.error import Unauthorized, NetworkError, TimedOut
|
from telegram.error import Unauthorized, NetworkError, TimedOut, BadRequest
|
||||||
|
|
||||||
|
|
||||||
def _parse(json_data):
|
def _parse(json_data):
|
||||||
|
@ -67,13 +67,15 @@ def _try_except_req(func):
|
||||||
# come first.
|
# come first.
|
||||||
errcode = error.getcode()
|
errcode = error.getcode()
|
||||||
|
|
||||||
if errcode in (401, 403):
|
|
||||||
raise Unauthorized()
|
|
||||||
elif errcode == 502:
|
|
||||||
raise NetworkError('Bad Gateway')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
message = _parse(error.read())
|
message = _parse(error.read())
|
||||||
|
|
||||||
|
if errcode in (401, 403):
|
||||||
|
raise Unauthorized()
|
||||||
|
elif errcode == 400:
|
||||||
|
raise BadRequest(message)
|
||||||
|
elif errcode == 502:
|
||||||
|
raise NetworkError('Bad Gateway')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
message = 'Unknown HTTPError {0}'.format(error.getcode())
|
message = 'Unknown HTTPError {0}'.format(error.getcode())
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Venue(TelegramObject):
|
||||||
foursquare_id (Optional[str]):
|
foursquare_id (Optional[str]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, location, title, address, foursquare_id=None):
|
def __init__(self, location, title, address, foursquare_id=None, **kwargs):
|
||||||
# Required
|
# Required
|
||||||
self.location = location
|
self.location = location
|
||||||
self.title = title
|
self.title = title
|
||||||
|
|
|
@ -40,6 +40,8 @@ class BaseTest(object):
|
||||||
'133505823:AAHZFMHno3mzVLErU5b5jJvaeG--qUyLyG0'))
|
'133505823:AAHZFMHno3mzVLErU5b5jJvaeG--qUyLyG0'))
|
||||||
chat_id = os.environ.get('CHAT_ID', '12173560')
|
chat_id = os.environ.get('CHAT_ID', '12173560')
|
||||||
|
|
||||||
|
self._group_id = os.environ.get('GROUP_ID', '-49740850')
|
||||||
|
self._channel_id = os.environ.get('CHANNEL_ID', '@pythontelegrambottests')
|
||||||
self._bot = bot
|
self._bot = bot
|
||||||
self._chat_id = chat_id
|
self._chat_id = chat_id
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,7 @@ class BotTest(BaseTest, unittest.TestCase):
|
||||||
bot = self._bot.getMe()
|
bot = self._bot.getMe()
|
||||||
|
|
||||||
self.assertTrue(self.is_json(bot.to_json()))
|
self.assertTrue(self.is_json(bot.to_json()))
|
||||||
self.assertEqual(bot.id, 133505823)
|
self._testUserEqualsBot(bot)
|
||||||
self.assertEqual(bot.first_name, 'PythonTelegramBot')
|
|
||||||
self.assertEqual(bot.last_name, '')
|
|
||||||
self.assertEqual(bot.username, 'PythonTelegramBot')
|
|
||||||
self.assertEqual(bot.name, '@PythonTelegramBot')
|
|
||||||
|
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
@timeout(10)
|
@timeout(10)
|
||||||
|
@ -75,7 +71,7 @@ class BotTest(BaseTest, unittest.TestCase):
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
@timeout(10)
|
@timeout(10)
|
||||||
def testGetUpdates(self):
|
def testGetUpdates(self):
|
||||||
updates = self._bot.getUpdates()
|
updates = self._bot.getUpdates(timeout=1)
|
||||||
|
|
||||||
if updates:
|
if updates:
|
||||||
self.assertTrue(self.is_json(updates[0].to_json()))
|
self.assertTrue(self.is_json(updates[0].to_json()))
|
||||||
|
@ -212,6 +208,63 @@ class BotTest(BaseTest, unittest.TestCase):
|
||||||
|
|
||||||
bot.getMe()
|
bot.getMe()
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@timeout(10)
|
||||||
|
def testLeaveChat(self):
|
||||||
|
with self.assertRaisesRegexp(telegram.error.BadRequest, 'Chat not found'):
|
||||||
|
chat = self._bot.leaveChat(-123456)
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(telegram.error.NetworkError, 'Chat not found'):
|
||||||
|
chat = self._bot.leaveChat(-123456)
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@timeout(10)
|
||||||
|
def testGetChat(self):
|
||||||
|
chat = self._bot.getChat(self._group_id)
|
||||||
|
|
||||||
|
self.assertTrue(self.is_json(chat.to_json()))
|
||||||
|
self.assertEqual(chat.type, "group")
|
||||||
|
self.assertEqual(chat.title, ">>> telegram.Bot() - Developers")
|
||||||
|
self.assertEqual(chat.id, int(self._group_id))
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@timeout(10)
|
||||||
|
def testGetChatAdministrators(self):
|
||||||
|
admins = self._bot.getChatAdministrators(self._channel_id)
|
||||||
|
self.assertTrue(isinstance(admins, list))
|
||||||
|
self.assertTrue(self.is_json(admins[0].to_json()))
|
||||||
|
|
||||||
|
for a in admins:
|
||||||
|
self.assertTrue(a.status in ("administrator", "creator"))
|
||||||
|
|
||||||
|
bot = [a.user for a in admins if a.user.id == 133505823][0]
|
||||||
|
self._testUserEqualsBot(bot)
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@timeout(10)
|
||||||
|
def testGetChatMembersCount(self):
|
||||||
|
count = self._bot.getChatMembersCount(self._channel_id)
|
||||||
|
self.assertTrue(isinstance(count, int))
|
||||||
|
self.assertTrue(count > 3)
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@timeout(10)
|
||||||
|
def testGetChatMember(self):
|
||||||
|
chat_member = self._bot.getChatMember(self._channel_id, 133505823)
|
||||||
|
bot = chat_member.user
|
||||||
|
|
||||||
|
self.assertTrue(self.is_json(chat_member.to_json()))
|
||||||
|
self.assertEqual(chat_member.status, "administrator")
|
||||||
|
self._testUserEqualsBot(bot)
|
||||||
|
|
||||||
|
def _testUserEqualsBot(self, user):
|
||||||
|
"""Tests if user is our trusty @PythonTelegramBot."""
|
||||||
|
self.assertEqual(user.id, 133505823)
|
||||||
|
self.assertEqual(user.first_name, 'PythonTelegramBot')
|
||||||
|
self.assertEqual(user.last_name, '')
|
||||||
|
self.assertEqual(user.username, 'PythonTelegramBot')
|
||||||
|
self.assertEqual(user.name, '@PythonTelegramBot')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -26,7 +26,7 @@ from datetime import datetime
|
||||||
|
|
||||||
sys.path.append('.')
|
sys.path.append('.')
|
||||||
|
|
||||||
from telegram import Update, Message, User, Chat
|
from telegram import Message, User, Chat
|
||||||
from telegram.ext import Filters
|
from telegram.ext import Filters
|
||||||
from tests.base import BaseTest
|
from tests.base import BaseTest
|
||||||
|
|
||||||
|
@ -36,119 +36,118 @@ class FiltersTest(BaseTest, unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.message = Message(0, User(0, "Testuser"), datetime.now(), Chat(0, 'private'))
|
self.message = Message(0, User(0, "Testuser"), datetime.now(), Chat(0, 'private'))
|
||||||
self.update = Update(0, message=self.message)
|
|
||||||
|
|
||||||
def test_filters_text(self):
|
def test_filters_text(self):
|
||||||
self.message.text = 'test'
|
self.message.text = 'test'
|
||||||
self.assertTrue(Filters.text(self.update))
|
self.assertTrue(Filters.text(self.message))
|
||||||
self.message.text = '/test'
|
self.message.text = '/test'
|
||||||
self.assertFalse(Filters.text(self.update))
|
self.assertFalse(Filters.text(self.message))
|
||||||
|
|
||||||
def test_filters_command(self):
|
def test_filters_command(self):
|
||||||
self.message.text = 'test'
|
self.message.text = 'test'
|
||||||
self.assertFalse(Filters.command(self.update))
|
self.assertFalse(Filters.command(self.message))
|
||||||
self.message.text = '/test'
|
self.message.text = '/test'
|
||||||
self.assertTrue(Filters.command(self.update))
|
self.assertTrue(Filters.command(self.message))
|
||||||
|
|
||||||
def test_filters_audio(self):
|
def test_filters_audio(self):
|
||||||
self.message.audio = 'test'
|
self.message.audio = 'test'
|
||||||
self.assertTrue(Filters.audio(self.update))
|
self.assertTrue(Filters.audio(self.message))
|
||||||
self.message.audio = None
|
self.message.audio = None
|
||||||
self.assertFalse(Filters.audio(self.update))
|
self.assertFalse(Filters.audio(self.message))
|
||||||
|
|
||||||
def test_filters_document(self):
|
def test_filters_document(self):
|
||||||
self.message.document = 'test'
|
self.message.document = 'test'
|
||||||
self.assertTrue(Filters.document(self.update))
|
self.assertTrue(Filters.document(self.message))
|
||||||
self.message.document = None
|
self.message.document = None
|
||||||
self.assertFalse(Filters.document(self.update))
|
self.assertFalse(Filters.document(self.message))
|
||||||
|
|
||||||
def test_filters_photo(self):
|
def test_filters_photo(self):
|
||||||
self.message.photo = 'test'
|
self.message.photo = 'test'
|
||||||
self.assertTrue(Filters.photo(self.update))
|
self.assertTrue(Filters.photo(self.message))
|
||||||
self.message.photo = None
|
self.message.photo = None
|
||||||
self.assertFalse(Filters.photo(self.update))
|
self.assertFalse(Filters.photo(self.message))
|
||||||
|
|
||||||
def test_filters_sticker(self):
|
def test_filters_sticker(self):
|
||||||
self.message.sticker = 'test'
|
self.message.sticker = 'test'
|
||||||
self.assertTrue(Filters.sticker(self.update))
|
self.assertTrue(Filters.sticker(self.message))
|
||||||
self.message.sticker = None
|
self.message.sticker = None
|
||||||
self.assertFalse(Filters.sticker(self.update))
|
self.assertFalse(Filters.sticker(self.message))
|
||||||
|
|
||||||
def test_filters_video(self):
|
def test_filters_video(self):
|
||||||
self.message.video = 'test'
|
self.message.video = 'test'
|
||||||
self.assertTrue(Filters.video(self.update))
|
self.assertTrue(Filters.video(self.message))
|
||||||
self.message.video = None
|
self.message.video = None
|
||||||
self.assertFalse(Filters.video(self.update))
|
self.assertFalse(Filters.video(self.message))
|
||||||
|
|
||||||
def test_filters_voice(self):
|
def test_filters_voice(self):
|
||||||
self.message.voice = 'test'
|
self.message.voice = 'test'
|
||||||
self.assertTrue(Filters.voice(self.update))
|
self.assertTrue(Filters.voice(self.message))
|
||||||
self.message.voice = None
|
self.message.voice = None
|
||||||
self.assertFalse(Filters.voice(self.update))
|
self.assertFalse(Filters.voice(self.message))
|
||||||
|
|
||||||
def test_filters_contact(self):
|
def test_filters_contact(self):
|
||||||
self.message.contact = 'test'
|
self.message.contact = 'test'
|
||||||
self.assertTrue(Filters.contact(self.update))
|
self.assertTrue(Filters.contact(self.message))
|
||||||
self.message.contact = None
|
self.message.contact = None
|
||||||
self.assertFalse(Filters.contact(self.update))
|
self.assertFalse(Filters.contact(self.message))
|
||||||
|
|
||||||
def test_filters_location(self):
|
def test_filters_location(self):
|
||||||
self.message.location = 'test'
|
self.message.location = 'test'
|
||||||
self.assertTrue(Filters.location(self.update))
|
self.assertTrue(Filters.location(self.message))
|
||||||
self.message.location = None
|
self.message.location = None
|
||||||
self.assertFalse(Filters.location(self.update))
|
self.assertFalse(Filters.location(self.message))
|
||||||
|
|
||||||
def test_filters_venue(self):
|
def test_filters_venue(self):
|
||||||
self.message.venue = 'test'
|
self.message.venue = 'test'
|
||||||
self.assertTrue(Filters.venue(self.update))
|
self.assertTrue(Filters.venue(self.message))
|
||||||
self.message.venue = None
|
self.message.venue = None
|
||||||
self.assertFalse(Filters.venue(self.update))
|
self.assertFalse(Filters.venue(self.message))
|
||||||
|
|
||||||
def test_filters_status_update(self):
|
def test_filters_status_update(self):
|
||||||
self.assertFalse(Filters.status_update(self.update))
|
self.assertFalse(Filters.status_update(self.message))
|
||||||
|
|
||||||
self.message.new_chat_member = 'test'
|
self.message.new_chat_member = 'test'
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.new_chat_member = None
|
self.message.new_chat_member = None
|
||||||
|
|
||||||
self.message.left_chat_member = 'test'
|
self.message.left_chat_member = 'test'
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.left_chat_member = None
|
self.message.left_chat_member = None
|
||||||
|
|
||||||
self.message.new_chat_title = 'test'
|
self.message.new_chat_title = 'test'
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.new_chat_title = ''
|
self.message.new_chat_title = ''
|
||||||
|
|
||||||
self.message.new_chat_photo = 'test'
|
self.message.new_chat_photo = 'test'
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.new_chat_photo = None
|
self.message.new_chat_photo = None
|
||||||
|
|
||||||
self.message.delete_chat_photo = True
|
self.message.delete_chat_photo = True
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.delete_chat_photo = False
|
self.message.delete_chat_photo = False
|
||||||
|
|
||||||
self.message.group_chat_created = True
|
self.message.group_chat_created = True
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.group_chat_created = False
|
self.message.group_chat_created = False
|
||||||
|
|
||||||
self.message.supergroup_chat_created = True
|
self.message.supergroup_chat_created = True
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.supergroup_chat_created = False
|
self.message.supergroup_chat_created = False
|
||||||
|
|
||||||
self.message.migrate_to_chat_id = 100
|
self.message.migrate_to_chat_id = 100
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.migrate_to_chat_id = 0
|
self.message.migrate_to_chat_id = 0
|
||||||
|
|
||||||
self.message.migrate_from_chat_id = 100
|
self.message.migrate_from_chat_id = 100
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.migrate_from_chat_id = 0
|
self.message.migrate_from_chat_id = 0
|
||||||
|
|
||||||
self.message.channel_chat_created = True
|
self.message.channel_chat_created = True
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.channel_chat_created = False
|
self.message.channel_chat_created = False
|
||||||
|
|
||||||
self.message.pinned_message = 'test'
|
self.message.pinned_message = 'test'
|
||||||
self.assertTrue(Filters.status_update(self.update))
|
self.assertTrue(Filters.status_update(self.message))
|
||||||
self.message.pinned_message = None
|
self.message.pinned_message = None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,10 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||||
self.received_message = update.message.text
|
self.received_message = update.message.text
|
||||||
self.message_count += 1
|
self.message_count += 1
|
||||||
|
|
||||||
|
def telegramHandlerEditedTest(self, bot, update):
|
||||||
|
self.received_message = update.edited_message.text
|
||||||
|
self.message_count += 1
|
||||||
|
|
||||||
def telegramInlineHandlerTest(self, bot, update):
|
def telegramInlineHandlerTest(self, bot, update):
|
||||||
self.received_message = (update.inline_query, update.chosen_inline_result)
|
self.received_message = (update.inline_query, update.chosen_inline_result)
|
||||||
self.message_count += 1
|
self.message_count += 1
|
||||||
|
@ -157,6 +161,28 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||||
sleep(.1)
|
sleep(.1)
|
||||||
self.assertTrue(None is self.received_message)
|
self.assertTrue(None is self.received_message)
|
||||||
|
|
||||||
|
def test_editedMessageHandler(self):
|
||||||
|
self._setup_updater('Test', edited=True)
|
||||||
|
d = self.updater.dispatcher
|
||||||
|
from telegram.ext import Filters
|
||||||
|
handler = MessageHandler([Filters.text], self.telegramHandlerEditedTest, allow_edited=True)
|
||||||
|
d.addHandler(handler)
|
||||||
|
self.updater.start_polling(0.01)
|
||||||
|
sleep(.1)
|
||||||
|
self.assertEqual(self.received_message, 'Test')
|
||||||
|
|
||||||
|
# Remove handler
|
||||||
|
d.removeHandler(handler)
|
||||||
|
handler = MessageHandler([Filters.text],
|
||||||
|
self.telegramHandlerEditedTest,
|
||||||
|
allow_edited=False)
|
||||||
|
d.addHandler(handler)
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
self.updater.bot.send_messages = 1
|
||||||
|
sleep(.1)
|
||||||
|
self.assertTrue(None is self.received_message)
|
||||||
|
|
||||||
def test_addTelegramMessageHandlerMultipleMessages(self):
|
def test_addTelegramMessageHandlerMultipleMessages(self):
|
||||||
self._setup_updater('Multiple', 100)
|
self._setup_updater('Multiple', 100)
|
||||||
self.updater.dispatcher.addHandler(MessageHandler([], self.telegramHandlerTest))
|
self.updater.dispatcher.addHandler(MessageHandler([], self.telegramHandlerTest))
|
||||||
|
@ -200,6 +226,25 @@ class UpdaterTest(BaseTest, unittest.TestCase):
|
||||||
sleep(.1)
|
sleep(.1)
|
||||||
self.assertTrue(None is self.received_message)
|
self.assertTrue(None is self.received_message)
|
||||||
|
|
||||||
|
def test_editedCommandHandler(self):
|
||||||
|
self._setup_updater('/test', edited=True)
|
||||||
|
d = self.updater.dispatcher
|
||||||
|
handler = CommandHandler('test', self.telegramHandlerEditedTest, allow_edited=True)
|
||||||
|
d.addHandler(handler)
|
||||||
|
self.updater.start_polling(0.01)
|
||||||
|
sleep(.1)
|
||||||
|
self.assertEqual(self.received_message, '/test')
|
||||||
|
|
||||||
|
# Remove handler
|
||||||
|
d.removeHandler(handler)
|
||||||
|
handler = CommandHandler('test', self.telegramHandlerEditedTest, allow_edited=False)
|
||||||
|
d.addHandler(handler)
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
self.updater.bot.send_messages = 1
|
||||||
|
sleep(.1)
|
||||||
|
self.assertTrue(None is self.received_message)
|
||||||
|
|
||||||
def test_addRemoveStringRegexHandler(self):
|
def test_addRemoveStringRegexHandler(self):
|
||||||
self._setup_updater('', messages=0)
|
self._setup_updater('', messages=0)
|
||||||
d = self.updater.dispatcher
|
d = self.updater.dispatcher
|
||||||
|
@ -612,7 +657,8 @@ class MockBot(object):
|
||||||
messages=1,
|
messages=1,
|
||||||
raise_error=False,
|
raise_error=False,
|
||||||
bootstrap_retries=None,
|
bootstrap_retries=None,
|
||||||
bootstrap_err=TelegramError('test')):
|
bootstrap_err=TelegramError('test'),
|
||||||
|
edited=False):
|
||||||
self.text = text
|
self.text = text
|
||||||
self.send_messages = messages
|
self.send_messages = messages
|
||||||
self.raise_error = raise_error
|
self.raise_error = raise_error
|
||||||
|
@ -620,13 +666,18 @@ class MockBot(object):
|
||||||
self.bootstrap_retries = bootstrap_retries
|
self.bootstrap_retries = bootstrap_retries
|
||||||
self.bootstrap_attempts = 0
|
self.bootstrap_attempts = 0
|
||||||
self.bootstrap_err = bootstrap_err
|
self.bootstrap_err = bootstrap_err
|
||||||
|
self.edited = edited
|
||||||
|
|
||||||
@staticmethod
|
def mockUpdate(self, text):
|
||||||
def mockUpdate(text):
|
|
||||||
message = Message(0, None, None, None)
|
message = Message(0, None, None, None)
|
||||||
message.text = text
|
message.text = text
|
||||||
update = Update(0)
|
update = Update(0)
|
||||||
|
|
||||||
|
if self.edited:
|
||||||
|
update.edited_message = message
|
||||||
|
else:
|
||||||
update.message = message
|
update.message = message
|
||||||
|
|
||||||
return update
|
return update
|
||||||
|
|
||||||
def setWebhook(self, webhook_url=None, certificate=None):
|
def setWebhook(self, webhook_url=None, certificate=None):
|
||||||
|
|
Loading…
Reference in a new issue