2015-09-11 01:06:27 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# A library that provides a Python interface to the Telegram Bot API
|
2018-01-04 16:16:06 +01:00
|
|
|
# Copyright (C) 2015-2018
|
2016-01-05 14:12:03 +01:00
|
|
|
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
2015-09-11 01:06:27 +02:00
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
2017-08-11 23:58:41 +02:00
|
|
|
# it under the terms of the GNU Lesser Public License as published by
|
2015-09-11 01:06:27 +02:00
|
|
|
# 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
|
2017-08-11 23:58:41 +02:00
|
|
|
# GNU Lesser Public License for more details.
|
2015-09-11 01:06:27 +02:00
|
|
|
#
|
2017-08-11 23:58:41 +02:00
|
|
|
# You should have received a copy of the GNU Lesser Public License
|
2015-09-11 01:06:27 +02:00
|
|
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
2019-02-13 12:07:25 +01:00
|
|
|
import os
|
|
|
|
import sys
|
2016-10-09 12:39:05 +02:00
|
|
|
import time
|
2019-11-15 21:51:22 +01:00
|
|
|
import datetime as dtm
|
2017-08-11 23:58:41 +02:00
|
|
|
from platform import python_implementation
|
2016-04-27 00:28:21 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
import pytest
|
2016-02-21 12:52:47 +01:00
|
|
|
from flaky import flaky
|
2017-08-11 23:58:41 +02:00
|
|
|
from future.utils import string_types
|
2015-12-31 20:33:37 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
from telegram import (Bot, Update, ChatAction, TelegramError, User, InlineKeyboardMarkup,
|
|
|
|
InlineKeyboardButton, InlineQueryResultArticle, InputTextMessageContent,
|
2019-09-06 21:41:43 +02:00
|
|
|
ShippingOption, LabeledPrice, ChatPermissions, Poll)
|
2017-09-14 17:54:00 +02:00
|
|
|
from telegram.error import BadRequest, InvalidToken, NetworkError, RetryAfter
|
2017-08-11 23:58:41 +02:00
|
|
|
from telegram.utils.helpers import from_timestamp
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2016-12-11 22:44:52 +01:00
|
|
|
BASE_TIME = time.time()
|
|
|
|
HIGHSCORE_DELTA = 1450000000
|
|
|
|
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.fixture(scope='class')
|
|
|
|
def message(bot, chat_id):
|
2019-04-01 13:05:45 +02:00
|
|
|
to_reply_to = bot.send_message(chat_id, 'Text',
|
|
|
|
disable_web_page_preview=True, disable_notification=True)
|
|
|
|
return bot.send_message(chat_id, 'Text', reply_to_message_id=to_reply_to.message_id,
|
2017-08-11 23:58:41 +02:00
|
|
|
disable_web_page_preview=True, disable_notification=True)
|
2017-07-01 17:08:45 +02:00
|
|
|
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.fixture(scope='class')
|
|
|
|
def media_message(bot, chat_id):
|
|
|
|
with open('tests/data/telegram.ogg', 'rb') as f:
|
|
|
|
return bot.send_voice(chat_id, voice=f, caption='my caption', timeout=10)
|
2015-09-11 01:06:27 +02:00
|
|
|
|
|
|
|
|
2019-09-06 21:41:43 +02:00
|
|
|
@pytest.fixture(scope='class')
|
|
|
|
def chat_permissions():
|
|
|
|
return ChatPermissions(can_send_messages=False, can_change_info=False, can_invite_users=False)
|
|
|
|
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
class TestBot(object):
|
|
|
|
@pytest.mark.parametrize('token', argvalues=[
|
|
|
|
'123',
|
|
|
|
'12a:abcd1234',
|
|
|
|
'12:abcd1234',
|
|
|
|
'1234:abcd1234\n',
|
|
|
|
' 1234:abcd1234',
|
|
|
|
' 1234:abcd1234\r',
|
|
|
|
'1234:abcd 1234'
|
|
|
|
])
|
|
|
|
def test_invalid_token(self, token):
|
|
|
|
with pytest.raises(InvalidToken, match='Invalid token'):
|
|
|
|
Bot(token)
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2016-02-22 00:52:31 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_invalid_token_server_response(self, monkeypatch):
|
|
|
|
monkeypatch.setattr('telegram.Bot._validate_token', lambda x, y: True)
|
|
|
|
bot = Bot('12')
|
|
|
|
with pytest.raises(InvalidToken):
|
|
|
|
bot.get_me()
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2016-03-11 07:37:43 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_get_me_and_properties(self, bot):
|
|
|
|
get_me_bot = bot.get_me()
|
2016-03-11 07:37:43 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert isinstance(get_me_bot, User)
|
|
|
|
assert get_me_bot.id == bot.id
|
|
|
|
assert get_me_bot.username == bot.username
|
|
|
|
assert get_me_bot.first_name == bot.first_name
|
|
|
|
assert get_me_bot.last_name == bot.last_name
|
|
|
|
assert get_me_bot.name == bot.name
|
2016-03-11 07:37:43 +01:00
|
|
|
|
2019-10-12 22:40:42 +02:00
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_to_dict(self, bot):
|
|
|
|
to_dict_bot = bot.to_dict()
|
|
|
|
|
|
|
|
assert isinstance(to_dict_bot, dict)
|
|
|
|
assert to_dict_bot["id"] == bot.id
|
|
|
|
assert to_dict_bot["username"] == bot.username
|
|
|
|
assert to_dict_bot["first_name"] == bot.first_name
|
|
|
|
if bot.last_name:
|
|
|
|
assert to_dict_bot["last_name"] == bot.last_name
|
|
|
|
|
2016-10-13 21:52:53 +02:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_forward_message(self, bot, chat_id, message):
|
|
|
|
message = bot.forward_message(chat_id, from_chat_id=chat_id, message_id=message.message_id)
|
2016-10-13 21:52:53 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.text == message.text
|
|
|
|
assert message.forward_from.username == message.from_user.username
|
2019-11-15 21:51:22 +01:00
|
|
|
assert isinstance(message.forward_date, dtm.datetime)
|
2016-10-13 21:52:53 +02:00
|
|
|
|
2016-02-22 00:52:31 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_delete_message(self, bot, chat_id):
|
|
|
|
message = bot.send_message(chat_id, text='will be deleted')
|
2019-11-09 19:33:51 +01:00
|
|
|
time.sleep(2)
|
2017-05-12 17:40:57 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert bot.delete_message(chat_id=chat_id, message_id=message.message_id) is True
|
2017-05-12 17:40:57 +02:00
|
|
|
|
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_delete_message_old_message(self, bot, chat_id):
|
2019-11-09 19:33:51 +01:00
|
|
|
with pytest.raises(BadRequest):
|
2017-05-12 17:40:57 +02:00
|
|
|
# Considering that the first message is old enough
|
2017-08-11 23:58:41 +02:00
|
|
|
bot.delete_message(chat_id=chat_id, message_id=1)
|
|
|
|
|
Bot API 4.0 (#1168)
Telegram Passport (#1174):
- Add full support for telegram passport.
- New types: PassportData, PassportFile, EncryptedPassportElement, EncryptedCredentials, PassportElementError, PassportElementErrorDataField, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorFile and PassportElementErrorFiles.
- New bot method: set_passport_data_errors
- New filter: Filters.passport_data
- Field passport_data field on Message
- PassportData is automagically decrypted when you specify your private key when creating Updater or Bot.
- PassportFiles is also automagically decrypted as you download/retrieve them.
- See new passportbot.py example for details on how to use, or go to our telegram passport wiki page for more info
- NOTE: Passport decryption requires new dependency `cryptography`.
Inputfile rework (#1184):
- Change how Inputfile is handled internally
- This allows support for specifying the thumbnails of photos and videos using the thumb= argument in the different send_ methods.
- Also allows Bot.send_media_group to actually finally send more than one media.
- Add thumb to Audio, Video and Videonote
- Add Bot.edit_message_media together with InputMediaAnimation, InputMediaAudio, and inputMediaDocument.
Other Bot API 4.0 changes:
- Add forusquare_type to Venue, InlineQueryResultVenue, InputVenueMessageContent, and Bot.send_venue. (#1170)
- Add vCard support by adding vcard field to Contact, InlineQueryResultContact, InputContactMessageContent, and Bot.send_contact. (#1166)
- Support new message entities: CASHTAG and PHONE_NUMBER. (#1179)
- Cashtag seems to be things like $USD and $GBP, but it seems telegram doesn't currently send them to bots.
- Phone number also seems to have limited support for now
- Add Bot.send_animation, add width, height, and duration to Animation, and add Filters.animation. (#1172)
Co-authored-by: Jasmin Bom <jsmnbom@gmail.com>
Co-authored-by: code1mountain <32801117+code1mountain@users.noreply.github.com>
Co-authored-by: Eldinnie <pieter.schutz+github@gmail.com>
Co-authored-by: mathefreak1 <mathefreak@hi2.in>
2018-08-29 14:18:58 +02:00
|
|
|
# send_photo, send_audio, send_document, send_sticker, send_video, send_voice, send_video_note,
|
|
|
|
# send_media_group and send_animation are tested in their respective test modules. No need to
|
|
|
|
# duplicate here.
|
2017-05-12 17:40:57 +02:00
|
|
|
|
2016-02-22 00:52:31 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_send_venue(self, bot, chat_id):
|
|
|
|
longitude = -46.788279
|
|
|
|
latitude = -23.691288
|
|
|
|
title = 'title'
|
|
|
|
address = 'address'
|
Bot API 4.0 (#1168)
Telegram Passport (#1174):
- Add full support for telegram passport.
- New types: PassportData, PassportFile, EncryptedPassportElement, EncryptedCredentials, PassportElementError, PassportElementErrorDataField, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorFile and PassportElementErrorFiles.
- New bot method: set_passport_data_errors
- New filter: Filters.passport_data
- Field passport_data field on Message
- PassportData is automagically decrypted when you specify your private key when creating Updater or Bot.
- PassportFiles is also automagically decrypted as you download/retrieve them.
- See new passportbot.py example for details on how to use, or go to our telegram passport wiki page for more info
- NOTE: Passport decryption requires new dependency `cryptography`.
Inputfile rework (#1184):
- Change how Inputfile is handled internally
- This allows support for specifying the thumbnails of photos and videos using the thumb= argument in the different send_ methods.
- Also allows Bot.send_media_group to actually finally send more than one media.
- Add thumb to Audio, Video and Videonote
- Add Bot.edit_message_media together with InputMediaAnimation, InputMediaAudio, and inputMediaDocument.
Other Bot API 4.0 changes:
- Add forusquare_type to Venue, InlineQueryResultVenue, InputVenueMessageContent, and Bot.send_venue. (#1170)
- Add vCard support by adding vcard field to Contact, InlineQueryResultContact, InputContactMessageContent, and Bot.send_contact. (#1166)
- Support new message entities: CASHTAG and PHONE_NUMBER. (#1179)
- Cashtag seems to be things like $USD and $GBP, but it seems telegram doesn't currently send them to bots.
- Phone number also seems to have limited support for now
- Add Bot.send_animation, add width, height, and duration to Animation, and add Filters.animation. (#1172)
Co-authored-by: Jasmin Bom <jsmnbom@gmail.com>
Co-authored-by: code1mountain <32801117+code1mountain@users.noreply.github.com>
Co-authored-by: Eldinnie <pieter.schutz+github@gmail.com>
Co-authored-by: mathefreak1 <mathefreak@hi2.in>
2018-08-29 14:18:58 +02:00
|
|
|
foursquare_id = 'foursquare id'
|
|
|
|
foursquare_type = 'foursquare type'
|
2017-08-11 23:58:41 +02:00
|
|
|
message = bot.send_venue(chat_id=chat_id, title=title, address=address, latitude=latitude,
|
Bot API 4.0 (#1168)
Telegram Passport (#1174):
- Add full support for telegram passport.
- New types: PassportData, PassportFile, EncryptedPassportElement, EncryptedCredentials, PassportElementError, PassportElementErrorDataField, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorFile and PassportElementErrorFiles.
- New bot method: set_passport_data_errors
- New filter: Filters.passport_data
- Field passport_data field on Message
- PassportData is automagically decrypted when you specify your private key when creating Updater or Bot.
- PassportFiles is also automagically decrypted as you download/retrieve them.
- See new passportbot.py example for details on how to use, or go to our telegram passport wiki page for more info
- NOTE: Passport decryption requires new dependency `cryptography`.
Inputfile rework (#1184):
- Change how Inputfile is handled internally
- This allows support for specifying the thumbnails of photos and videos using the thumb= argument in the different send_ methods.
- Also allows Bot.send_media_group to actually finally send more than one media.
- Add thumb to Audio, Video and Videonote
- Add Bot.edit_message_media together with InputMediaAnimation, InputMediaAudio, and inputMediaDocument.
Other Bot API 4.0 changes:
- Add forusquare_type to Venue, InlineQueryResultVenue, InputVenueMessageContent, and Bot.send_venue. (#1170)
- Add vCard support by adding vcard field to Contact, InlineQueryResultContact, InputContactMessageContent, and Bot.send_contact. (#1166)
- Support new message entities: CASHTAG and PHONE_NUMBER. (#1179)
- Cashtag seems to be things like $USD and $GBP, but it seems telegram doesn't currently send them to bots.
- Phone number also seems to have limited support for now
- Add Bot.send_animation, add width, height, and duration to Animation, and add Filters.animation. (#1172)
Co-authored-by: Jasmin Bom <jsmnbom@gmail.com>
Co-authored-by: code1mountain <32801117+code1mountain@users.noreply.github.com>
Co-authored-by: Eldinnie <pieter.schutz+github@gmail.com>
Co-authored-by: mathefreak1 <mathefreak@hi2.in>
2018-08-29 14:18:58 +02:00
|
|
|
longitude=longitude, foursquare_id=foursquare_id,
|
|
|
|
foursquare_type=foursquare_type)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
|
|
|
assert message.venue
|
|
|
|
assert message.venue.title == title
|
|
|
|
assert message.venue.address == address
|
|
|
|
assert message.venue.location.latitude == latitude
|
|
|
|
assert message.venue.location.longitude == longitude
|
Bot API 4.0 (#1168)
Telegram Passport (#1174):
- Add full support for telegram passport.
- New types: PassportData, PassportFile, EncryptedPassportElement, EncryptedCredentials, PassportElementError, PassportElementErrorDataField, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorFile and PassportElementErrorFiles.
- New bot method: set_passport_data_errors
- New filter: Filters.passport_data
- Field passport_data field on Message
- PassportData is automagically decrypted when you specify your private key when creating Updater or Bot.
- PassportFiles is also automagically decrypted as you download/retrieve them.
- See new passportbot.py example for details on how to use, or go to our telegram passport wiki page for more info
- NOTE: Passport decryption requires new dependency `cryptography`.
Inputfile rework (#1184):
- Change how Inputfile is handled internally
- This allows support for specifying the thumbnails of photos and videos using the thumb= argument in the different send_ methods.
- Also allows Bot.send_media_group to actually finally send more than one media.
- Add thumb to Audio, Video and Videonote
- Add Bot.edit_message_media together with InputMediaAnimation, InputMediaAudio, and inputMediaDocument.
Other Bot API 4.0 changes:
- Add forusquare_type to Venue, InlineQueryResultVenue, InputVenueMessageContent, and Bot.send_venue. (#1170)
- Add vCard support by adding vcard field to Contact, InlineQueryResultContact, InputContactMessageContent, and Bot.send_contact. (#1166)
- Support new message entities: CASHTAG and PHONE_NUMBER. (#1179)
- Cashtag seems to be things like $USD and $GBP, but it seems telegram doesn't currently send them to bots.
- Phone number also seems to have limited support for now
- Add Bot.send_animation, add width, height, and duration to Animation, and add Filters.animation. (#1172)
Co-authored-by: Jasmin Bom <jsmnbom@gmail.com>
Co-authored-by: code1mountain <32801117+code1mountain@users.noreply.github.com>
Co-authored-by: Eldinnie <pieter.schutz+github@gmail.com>
Co-authored-by: mathefreak1 <mathefreak@hi2.in>
2018-08-29 14:18:58 +02:00
|
|
|
assert message.venue.foursquare_id == foursquare_id
|
|
|
|
assert message.venue.foursquare_type == foursquare_type
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
@pytest.mark.xfail(raises=RetryAfter)
|
|
|
|
@pytest.mark.skipif(python_implementation() == 'PyPy',
|
|
|
|
reason='Unstable on pypy for some reason')
|
|
|
|
def test_send_contact(self, bot, chat_id):
|
|
|
|
phone_number = '+11234567890'
|
|
|
|
first_name = 'Leandro'
|
|
|
|
last_name = 'Toledo'
|
|
|
|
message = bot.send_contact(chat_id=chat_id, phone_number=phone_number,
|
|
|
|
first_name=first_name, last_name=last_name)
|
|
|
|
|
|
|
|
assert message.contact
|
|
|
|
assert message.contact.phone_number == phone_number
|
|
|
|
assert message.contact.first_name == first_name
|
|
|
|
assert message.contact.last_name == last_name
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2019-08-23 21:20:41 +02:00
|
|
|
# TODO: Add bot to group to test polls too
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_send_and_stop_poll(self, bot, super_group_id):
|
|
|
|
question = 'Is this a test?'
|
|
|
|
answers = ['Yes', 'No', 'Maybe']
|
|
|
|
message = bot.send_poll(chat_id=super_group_id, question=question, options=answers,
|
|
|
|
timeout=60)
|
|
|
|
|
|
|
|
assert message.poll
|
|
|
|
assert message.poll.question == question
|
|
|
|
assert message.poll.options[0].text == answers[0]
|
|
|
|
assert message.poll.options[1].text == answers[1]
|
|
|
|
assert message.poll.options[2].text == answers[2]
|
|
|
|
assert not message.poll.is_closed
|
|
|
|
|
|
|
|
poll = bot.stop_poll(chat_id=super_group_id, message_id=message.message_id, timeout=60)
|
|
|
|
assert isinstance(poll, Poll)
|
|
|
|
assert poll.is_closed
|
|
|
|
assert poll.options[0].text == answers[0]
|
|
|
|
assert poll.options[0].voter_count == 0
|
|
|
|
assert poll.options[1].text == answers[1]
|
|
|
|
assert poll.options[1].voter_count == 0
|
|
|
|
assert poll.options[2].text == answers[2]
|
|
|
|
assert poll.options[2].voter_count == 0
|
|
|
|
assert poll.question == question
|
|
|
|
|
2016-02-22 00:52:31 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_send_game(self, bot, chat_id):
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
message = bot.send_game(chat_id, game_short_name)
|
2016-10-07 23:55:46 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.game
|
2018-10-14 11:39:35 +02:00
|
|
|
assert message.game.description == ('A no-op test game, for python-telegram-bot '
|
|
|
|
'bot framework testing.')
|
|
|
|
assert message.game.animation.file_id != ''
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.game.photo[0].file_size == 851
|
2016-10-07 23:55:46 +02:00
|
|
|
|
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_send_chat_action(self, bot, chat_id):
|
|
|
|
assert bot.send_chat_action(chat_id, ChatAction.TYPING)
|
|
|
|
|
|
|
|
# TODO: Needs improvement. We need incoming inline query to test answer.
|
|
|
|
def test_answer_inline_query(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'cache_time': 300,
|
|
|
|
'results': [{'title': 'first', 'id': '11', 'type': 'article',
|
|
|
|
'input_message_content': {'message_text': 'first'}},
|
|
|
|
{'title': 'second', 'id': '12', 'type': 'article',
|
|
|
|
'input_message_content': {'message_text': 'second'}}],
|
|
|
|
'next_offset': '42', 'switch_pm_parameter': 'start_pm',
|
|
|
|
'inline_query_id': 1234, 'is_personal': True,
|
|
|
|
'switch_pm_text': 'switch pm'}
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
results = [InlineQueryResultArticle('11', 'first', InputTextMessageContent('first')),
|
|
|
|
InlineQueryResultArticle('12', 'second', InputTextMessageContent('second'))]
|
|
|
|
|
|
|
|
assert bot.answer_inline_query(1234,
|
|
|
|
results=results,
|
|
|
|
cache_time=300,
|
|
|
|
is_personal=True,
|
|
|
|
next_offset='42',
|
|
|
|
switch_pm_text='switch pm',
|
|
|
|
switch_pm_parameter='start_pm')
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2016-02-22 00:52:31 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
2018-10-14 11:39:35 +02:00
|
|
|
def test_get_user_profile_photos(self, bot, chat_id):
|
2017-08-11 23:58:41 +02:00
|
|
|
user_profile_photos = bot.get_user_profile_photos(chat_id)
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2018-10-14 11:39:35 +02:00
|
|
|
assert user_profile_photos.photos[0][0].file_size == 5403
|
2015-09-11 01:06:27 +02:00
|
|
|
|
2016-10-13 21:52:53 +02:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
2018-10-14 11:39:35 +02:00
|
|
|
def test_get_one_user_profile_photo(self, bot, chat_id):
|
2017-08-11 23:58:41 +02:00
|
|
|
user_profile_photos = bot.get_user_profile_photos(chat_id, offset=0, limit=1)
|
2018-10-14 11:39:35 +02:00
|
|
|
assert user_profile_photos.photos[0][0].file_size == 5403
|
2017-08-11 23:58:41 +02:00
|
|
|
|
|
|
|
# get_file is tested multiple times in the test_*media* modules.
|
2016-10-13 21:52:53 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
# TODO: Needs improvement. No feasable way to test until bots can add members.
|
|
|
|
def test_kick_chat_member(self, monkeypatch, bot):
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
chat_id = data['chat_id'] == 2
|
|
|
|
user_id = data['user_id'] == 32
|
|
|
|
until_date = data.get('until_date', 1577887200) == 1577887200
|
|
|
|
return chat_id and user_id and until_date
|
2015-12-26 18:32:36 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
until = from_timestamp(1577887200)
|
2015-12-26 18:32:36 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert bot.kick_chat_member(2, 32)
|
|
|
|
assert bot.kick_chat_member(2, 32, until_date=until)
|
|
|
|
assert bot.kick_chat_member(2, 32, until_date=1577887200)
|
2015-12-26 18:32:36 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
# TODO: Needs improvement.
|
|
|
|
def test_unban_chat_member(self, monkeypatch, bot):
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
chat_id = data['chat_id'] == 2
|
|
|
|
user_id = data['user_id'] == 32
|
|
|
|
return chat_id and user_id
|
2015-12-26 18:32:36 +01:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
2016-05-22 23:21:51 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert bot.unban_chat_member(2, 32)
|
2015-12-31 21:23:23 +01:00
|
|
|
|
2019-09-06 21:41:43 +02:00
|
|
|
def test_set_chat_permissions(self, monkeypatch, bot, chat_permissions):
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
chat_id = data['chat_id'] == 2
|
|
|
|
permissions = data['permissions'] == chat_permissions.to_dict()
|
|
|
|
return chat_id and permissions
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
|
|
|
|
assert bot.set_chat_permissions(2, chat_permissions)
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
# TODO: Needs improvement. Need an incoming callbackquery to test
|
|
|
|
def test_answer_callback_query(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'callback_query_id': 23, 'show_alert': True, 'url': 'no_url',
|
|
|
|
'cache_time': 1, 'text': 'answer'}
|
2016-04-21 14:21:12 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
|
|
|
|
assert bot.answer_callback_query(23, text='answer', show_alert=True, url='no_url',
|
|
|
|
cache_time=1)
|
2015-12-31 21:23:23 +01:00
|
|
|
|
2016-05-26 02:15:17 +02:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_edit_message_text(self, bot, message):
|
|
|
|
message = bot.edit_message_text(text='new_text', chat_id=message.chat_id,
|
|
|
|
message_id=message.message_id, parse_mode='HTML',
|
|
|
|
disable_web_page_preview=True)
|
|
|
|
|
|
|
|
assert message.text == 'new_text'
|
2016-05-26 02:15:17 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.skip(reason='need reference to an inline message')
|
|
|
|
def test_edit_message_text_inline(self):
|
|
|
|
pass
|
2016-05-26 03:09:18 +02:00
|
|
|
|
2016-05-25 01:31:10 +02:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_edit_message_caption(self, bot, media_message):
|
|
|
|
message = bot.edit_message_caption(caption='new_caption', chat_id=media_message.chat_id,
|
|
|
|
message_id=media_message.message_id)
|
2016-05-25 01:31:10 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.caption == 'new_caption'
|
|
|
|
|
Bot API 4.0 (#1168)
Telegram Passport (#1174):
- Add full support for telegram passport.
- New types: PassportData, PassportFile, EncryptedPassportElement, EncryptedCredentials, PassportElementError, PassportElementErrorDataField, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorFile and PassportElementErrorFiles.
- New bot method: set_passport_data_errors
- New filter: Filters.passport_data
- Field passport_data field on Message
- PassportData is automagically decrypted when you specify your private key when creating Updater or Bot.
- PassportFiles is also automagically decrypted as you download/retrieve them.
- See new passportbot.py example for details on how to use, or go to our telegram passport wiki page for more info
- NOTE: Passport decryption requires new dependency `cryptography`.
Inputfile rework (#1184):
- Change how Inputfile is handled internally
- This allows support for specifying the thumbnails of photos and videos using the thumb= argument in the different send_ methods.
- Also allows Bot.send_media_group to actually finally send more than one media.
- Add thumb to Audio, Video and Videonote
- Add Bot.edit_message_media together with InputMediaAnimation, InputMediaAudio, and inputMediaDocument.
Other Bot API 4.0 changes:
- Add forusquare_type to Venue, InlineQueryResultVenue, InputVenueMessageContent, and Bot.send_venue. (#1170)
- Add vCard support by adding vcard field to Contact, InlineQueryResultContact, InputContactMessageContent, and Bot.send_contact. (#1166)
- Support new message entities: CASHTAG and PHONE_NUMBER. (#1179)
- Cashtag seems to be things like $USD and $GBP, but it seems telegram doesn't currently send them to bots.
- Phone number also seems to have limited support for now
- Add Bot.send_animation, add width, height, and duration to Animation, and add Filters.animation. (#1172)
Co-authored-by: Jasmin Bom <jsmnbom@gmail.com>
Co-authored-by: code1mountain <32801117+code1mountain@users.noreply.github.com>
Co-authored-by: Eldinnie <pieter.schutz+github@gmail.com>
Co-authored-by: mathefreak1 <mathefreak@hi2.in>
2018-08-29 14:18:58 +02:00
|
|
|
# edit_message_media is tested in test_inputmedia
|
|
|
|
|
2018-02-18 16:11:04 +01:00
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_edit_message_caption_with_parse_mode(self, bot, media_message):
|
|
|
|
message = bot.edit_message_caption(caption='new *caption*', parse_mode='Markdown',
|
|
|
|
chat_id=media_message.chat_id,
|
|
|
|
message_id=media_message.message_id)
|
|
|
|
|
|
|
|
assert message.caption == 'new caption'
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
def test_edit_message_caption_without_required(self, bot):
|
|
|
|
with pytest.raises(ValueError, match='Both chat_id and message_id are required when'):
|
|
|
|
bot.edit_message_caption(caption='new_caption')
|
|
|
|
|
|
|
|
@pytest.mark.skip(reason='need reference to an inline message')
|
|
|
|
def test_edit_message_caption_inline(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_edit_reply_markup(self, bot, message):
|
|
|
|
new_markup = InlineKeyboardMarkup([[InlineKeyboardButton(text='test', callback_data='1')]])
|
|
|
|
message = bot.edit_message_reply_markup(chat_id=message.chat_id,
|
|
|
|
message_id=message.message_id,
|
|
|
|
reply_markup=new_markup)
|
|
|
|
|
|
|
|
assert message is not True
|
|
|
|
|
|
|
|
def test_edit_message_reply_markup_without_required(self, bot):
|
|
|
|
new_markup = InlineKeyboardMarkup([[InlineKeyboardButton(text='test', callback_data='1')]])
|
|
|
|
with pytest.raises(ValueError, match='Both chat_id and message_id are required when'):
|
|
|
|
bot.edit_message_reply_markup(reply_markup=new_markup)
|
|
|
|
|
|
|
|
@pytest.mark.skip(reason='need reference to an inline message')
|
|
|
|
def test_edit_reply_markup_inline(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
# TODO: Actually send updates to the test bot so this can be tested properly
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_get_updates(self, bot):
|
|
|
|
bot.delete_webhook() # make sure there is no webhook set if webhook tests failed
|
|
|
|
updates = bot.get_updates(timeout=1)
|
|
|
|
|
|
|
|
assert isinstance(updates, list)
|
|
|
|
if updates:
|
|
|
|
assert isinstance(updates[0], Update)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(15)
|
|
|
|
@pytest.mark.xfail
|
2019-02-13 12:07:25 +01:00
|
|
|
@pytest.mark.skipif(os.getenv('APPVEYOR') and (sys.version_info < (3, 6)),
|
|
|
|
reason='only run on 3.6 on appveyor')
|
2017-08-11 23:58:41 +02:00
|
|
|
def test_set_webhook_get_webhook_info_and_delete_webhook(self, bot):
|
|
|
|
url = 'https://python-telegram-bot.org/test/webhook'
|
|
|
|
max_connections = 7
|
|
|
|
allowed_updates = ['message']
|
|
|
|
bot.set_webhook(url, max_connections=max_connections, allowed_updates=allowed_updates)
|
|
|
|
time.sleep(2)
|
|
|
|
live_info = bot.get_webhook_info()
|
|
|
|
time.sleep(6)
|
|
|
|
bot.delete_webhook()
|
|
|
|
time.sleep(2)
|
|
|
|
info = bot.get_webhook_info()
|
|
|
|
assert info.url == ''
|
|
|
|
assert live_info.url == url
|
|
|
|
assert live_info.max_connections == max_connections
|
|
|
|
assert live_info.allowed_updates == allowed_updates
|
2016-05-25 01:31:10 +02:00
|
|
|
|
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_leave_chat(self, bot):
|
|
|
|
with pytest.raises(BadRequest, match='Chat not found'):
|
|
|
|
bot.leave_chat(-123456)
|
|
|
|
|
|
|
|
with pytest.raises(NetworkError, match='Chat not found'):
|
|
|
|
bot.leave_chat(-123456)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
2019-08-23 21:20:41 +02:00
|
|
|
def test_get_chat(self, bot, super_group_id):
|
|
|
|
chat = bot.get_chat(super_group_id)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
2019-08-23 21:20:41 +02:00
|
|
|
assert chat.type == 'supergroup'
|
2018-10-14 11:39:35 +02:00
|
|
|
assert chat.title == '>>> telegram.Bot(test)'
|
2019-08-23 21:20:41 +02:00
|
|
|
assert chat.id == int(super_group_id)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_get_chat_administrators(self, bot, channel_id):
|
|
|
|
admins = bot.get_chat_administrators(channel_id)
|
|
|
|
assert isinstance(admins, list)
|
2016-05-25 01:31:10 +02:00
|
|
|
|
|
|
|
for a in admins:
|
2017-08-11 23:58:41 +02:00
|
|
|
assert a.status in ('administrator', 'creator')
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_get_chat_members_count(self, bot, channel_id):
|
|
|
|
count = bot.get_chat_members_count(channel_id)
|
|
|
|
assert isinstance(count, int)
|
|
|
|
assert count > 3
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
2018-10-14 11:39:35 +02:00
|
|
|
def test_get_chat_member(self, bot, channel_id, chat_id):
|
|
|
|
chat_member = bot.get_chat_member(channel_id, chat_id)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
|
|
|
assert chat_member.status == 'administrator'
|
2018-10-14 11:39:35 +02:00
|
|
|
assert chat_member.user.first_name == 'PTB'
|
|
|
|
assert chat_member.user.last_name == 'Test user'
|
2017-08-11 23:58:41 +02:00
|
|
|
|
2017-10-14 20:03:02 +02:00
|
|
|
@pytest.mark.skip(reason="Not implemented yet.")
|
|
|
|
def test_set_chat_sticker_set(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@pytest.mark.skip(reason="Not implemented yet.")
|
|
|
|
def test_delete_chat_sticker_set(self):
|
|
|
|
pass
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_game_score_1(self, bot, chat_id):
|
2016-12-11 22:44:52 +01:00
|
|
|
# NOTE: numbering of methods assures proper order between test_set_game_scoreX methods
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
2016-10-09 12:39:05 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
message = bot.set_game_score(
|
|
|
|
user_id=chat_id,
|
2016-12-11 22:44:52 +01:00
|
|
|
score=int(BASE_TIME) - HIGHSCORE_DELTA,
|
2016-10-09 12:39:05 +02:00
|
|
|
chat_id=game.chat_id,
|
2016-12-11 22:44:52 +01:00
|
|
|
message_id=game.message_id)
|
2016-10-09 12:39:05 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.game.description == game.game.description
|
|
|
|
assert message.game.animation.file_id == game.game.animation.file_id
|
|
|
|
assert message.game.photo[0].file_size == game.game.photo[0].file_size
|
|
|
|
assert message.game.text != game.game.text
|
2016-10-09 12:39:05 +02:00
|
|
|
|
2016-12-11 22:44:52 +01:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_game_score_2(self, bot, chat_id):
|
2016-12-11 22:44:52 +01:00
|
|
|
# NOTE: numbering of methods assures proper order between test_set_game_scoreX methods
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
2016-12-11 22:44:52 +01:00
|
|
|
|
|
|
|
score = int(BASE_TIME) - HIGHSCORE_DELTA + 1
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
message = bot.set_game_score(
|
|
|
|
user_id=chat_id,
|
2016-12-11 22:44:52 +01:00
|
|
|
score=score,
|
|
|
|
chat_id=game.chat_id,
|
|
|
|
message_id=game.message_id,
|
|
|
|
disable_edit_message=True)
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.game.description == game.game.description
|
|
|
|
assert message.game.animation.file_id == game.game.animation.file_id
|
|
|
|
assert message.game.photo[0].file_size == game.game.photo[0].file_size
|
|
|
|
assert message.game.text == game.game.text
|
2016-12-11 22:44:52 +01:00
|
|
|
|
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_game_score_3(self, bot, chat_id):
|
2016-12-11 22:44:52 +01:00
|
|
|
# NOTE: numbering of methods assures proper order between test_set_game_scoreX methods
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
2016-12-11 22:44:52 +01:00
|
|
|
|
|
|
|
score = int(BASE_TIME) - HIGHSCORE_DELTA - 1
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
with pytest.raises(BadRequest, match='Bot_score_not_modified'):
|
|
|
|
bot.set_game_score(
|
|
|
|
user_id=chat_id,
|
2016-12-11 22:44:52 +01:00
|
|
|
score=score,
|
|
|
|
chat_id=game.chat_id,
|
|
|
|
message_id=game.message_id)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_game_score_4(self, bot, chat_id):
|
2016-12-11 22:44:52 +01:00
|
|
|
# NOTE: numbering of methods assures proper order between test_set_game_scoreX methods
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
2016-12-11 22:44:52 +01:00
|
|
|
|
|
|
|
score = int(BASE_TIME) - HIGHSCORE_DELTA - 2
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
message = bot.set_game_score(
|
|
|
|
user_id=chat_id,
|
2016-12-11 22:44:52 +01:00
|
|
|
score=score,
|
|
|
|
chat_id=game.chat_id,
|
|
|
|
message_id=game.message_id,
|
|
|
|
force=True)
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
assert message.game.description == game.game.description
|
|
|
|
assert message.game.animation.file_id == game.game.animation.file_id
|
|
|
|
assert message.game.photo[0].file_size == game.game.photo[0].file_size
|
2016-12-11 22:44:52 +01:00
|
|
|
|
|
|
|
# For some reason the returned message does not contain the updated score. need to fetch
|
|
|
|
# the game again...
|
2017-08-11 23:58:41 +02:00
|
|
|
game2 = bot.send_game(chat_id, game_short_name)
|
|
|
|
assert str(score) in game2.game.text
|
2016-12-11 22:44:52 +01:00
|
|
|
|
2016-10-16 12:33:22 +02:00
|
|
|
@flaky(3, 1)
|
2017-08-11 23:58:41 +02:00
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_game_score_too_low_score(self, bot, chat_id):
|
2016-10-16 12:33:22 +02:00
|
|
|
# We need a game to set the score for
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
|
|
|
|
|
|
|
with pytest.raises(BadRequest):
|
|
|
|
bot.set_game_score(user_id=chat_id, score=100,
|
|
|
|
chat_id=game.chat_id, message_id=game.message_id)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_get_game_high_scores(self, bot, chat_id):
|
|
|
|
# We need a game to get the scores for
|
2018-10-14 11:39:35 +02:00
|
|
|
game_short_name = 'test_game'
|
2017-08-11 23:58:41 +02:00
|
|
|
game = bot.send_game(chat_id, game_short_name)
|
|
|
|
high_scores = bot.get_game_high_scores(chat_id, game.chat_id, game.message_id)
|
|
|
|
# We assume that the other game score tests ran within 20 sec
|
|
|
|
assert pytest.approx(high_scores[0].score, abs=20) == int(BASE_TIME) - HIGHSCORE_DELTA
|
|
|
|
|
|
|
|
# send_invoice is tested in test_invoice
|
|
|
|
|
|
|
|
# TODO: Needs improvement. Need incoming shippping queries to test
|
|
|
|
def test_answer_shipping_query_ok(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'shipping_query_id': 1, 'ok': True,
|
|
|
|
'shipping_options': [{'title': 'option1',
|
|
|
|
'prices': [{'label': 'price', 'amount': 100}],
|
|
|
|
'id': 1}]}
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
shipping_options = ShippingOption(1, 'option1', [LabeledPrice('price', 100)])
|
|
|
|
assert bot.answer_shipping_query(1, True, shipping_options=[shipping_options])
|
|
|
|
|
|
|
|
def test_answer_shipping_query_error_message(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'shipping_query_id': 1, 'error_message': 'Not enough fish',
|
|
|
|
'ok': False}
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
assert bot.answer_shipping_query(1, False, error_message='Not enough fish')
|
|
|
|
|
|
|
|
def test_answer_shipping_query_errors(self, monkeypatch, bot):
|
|
|
|
shipping_options = ShippingOption(1, 'option1', [LabeledPrice('price', 100)])
|
|
|
|
|
|
|
|
with pytest.raises(TelegramError, match='should not be empty and there should not be'):
|
|
|
|
bot.answer_shipping_query(1, True, error_message='Not enough fish')
|
|
|
|
|
|
|
|
with pytest.raises(TelegramError, match='should not be empty and there should not be'):
|
|
|
|
bot.answer_shipping_query(1, False)
|
2017-06-18 12:14:24 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
with pytest.raises(TelegramError, match='should not be empty and there should not be'):
|
|
|
|
bot.answer_shipping_query(1, False, shipping_options=shipping_options)
|
|
|
|
|
|
|
|
with pytest.raises(TelegramError, match='should not be empty and there should not be'):
|
|
|
|
bot.answer_shipping_query(1, True)
|
|
|
|
|
|
|
|
# TODO: Needs improvement. Need incoming pre checkout queries to test
|
|
|
|
def test_answer_pre_checkout_query_ok(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'pre_checkout_query_id': 1, 'ok': True}
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
assert bot.answer_pre_checkout_query(1, True)
|
|
|
|
|
|
|
|
def test_answer_pre_checkout_query_error_message(self, monkeypatch, bot):
|
|
|
|
# For now just test that our internals pass the correct data
|
|
|
|
def test(_, url, data, *args, **kwargs):
|
|
|
|
return data == {'pre_checkout_query_id': 1, 'error_message': 'Not enough fish',
|
|
|
|
'ok': False}
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request.post', test)
|
|
|
|
assert bot.answer_pre_checkout_query(1, False, error_message='Not enough fish')
|
|
|
|
|
|
|
|
def test_answer_pre_checkout_query_errors(self, monkeypatch, bot):
|
|
|
|
with pytest.raises(TelegramError, match='should not be'):
|
|
|
|
bot.answer_pre_checkout_query(1, True, error_message='Not enough fish')
|
|
|
|
|
|
|
|
with pytest.raises(TelegramError, match='should not be empty'):
|
|
|
|
bot.answer_pre_checkout_query(1, False)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
2019-09-06 21:41:43 +02:00
|
|
|
def test_restrict_chat_member(self, bot, channel_id, chat_permissions):
|
2017-08-11 23:58:41 +02:00
|
|
|
# TODO: Add bot to supergroup so this can be tested properly
|
|
|
|
with pytest.raises(BadRequest, match='Method is available only for supergroups'):
|
|
|
|
assert bot.restrict_chat_member(channel_id,
|
|
|
|
95205500,
|
2019-09-06 21:41:43 +02:00
|
|
|
chat_permissions,
|
2019-11-15 21:51:22 +01:00
|
|
|
until_date=dtm.datetime.utcnow())
|
2017-06-18 12:14:24 +02:00
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_promote_chat_member(self, bot, channel_id):
|
|
|
|
# TODO: Add bot to supergroup so this can be tested properly / give bot perms
|
2018-10-14 11:39:35 +02:00
|
|
|
with pytest.raises(BadRequest, match='Not enough rights'):
|
2017-08-11 23:58:41 +02:00
|
|
|
assert bot.promote_chat_member(channel_id,
|
|
|
|
95205500,
|
|
|
|
can_change_info=True,
|
|
|
|
can_post_messages=True,
|
|
|
|
can_edit_messages=True,
|
|
|
|
can_delete_messages=True,
|
|
|
|
can_invite_users=True,
|
|
|
|
can_restrict_members=True,
|
|
|
|
can_pin_messages=True,
|
|
|
|
can_promote_members=True)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_export_chat_invite_link(self, bot, channel_id):
|
|
|
|
# Each link is unique apparently
|
|
|
|
invite_link = bot.export_chat_invite_link(channel_id)
|
|
|
|
assert isinstance(invite_link, string_types)
|
|
|
|
assert invite_link != ''
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_delete_chat_photo(self, bot, channel_id):
|
|
|
|
assert bot.delete_chat_photo(channel_id)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_chat_photo(self, bot, channel_id):
|
|
|
|
with open('tests/data/telegram_test_channel.jpg', 'rb') as f:
|
|
|
|
assert bot.set_chat_photo(channel_id, f)
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_chat_title(self, bot, channel_id):
|
|
|
|
assert bot.set_chat_title(channel_id, '>>> telegram.Bot() - Tests')
|
|
|
|
|
|
|
|
@flaky(3, 1)
|
|
|
|
@pytest.mark.timeout(10)
|
|
|
|
def test_set_chat_description(self, bot, channel_id):
|
|
|
|
assert bot.set_chat_description(channel_id, 'Time: ' + str(time.time()))
|
|
|
|
|
2019-08-23 21:20:41 +02:00
|
|
|
# TODO: Add bot to group to test there too
|
|
|
|
def test_pin_and_unpin_message(self, bot, super_group_id):
|
|
|
|
message = bot.send_message(super_group_id, text="test_pin_message")
|
|
|
|
assert bot.pin_chat_message(chat_id=super_group_id, message_id=message.message_id,
|
|
|
|
disable_notification=True)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
2019-08-23 21:20:41 +02:00
|
|
|
chat = bot.get_chat(super_group_id)
|
|
|
|
assert chat.pinned_message == message
|
|
|
|
|
|
|
|
assert bot.unpinChatMessage(super_group_id)
|
2017-08-11 23:58:41 +02:00
|
|
|
|
|
|
|
# get_sticker_set, upload_sticker_file, create_new_sticker_set, add_sticker_to_set,
|
|
|
|
# set_sticker_position_in_set and delete_sticker_from_set are tested in the
|
|
|
|
# test_sticker module.
|
2019-02-13 16:04:48 +01:00
|
|
|
|
2019-02-13 11:37:13 +01:00
|
|
|
def test_timeout_propagation_explicit(self, monkeypatch, bot, chat_id):
|
2019-01-30 19:38:15 +01:00
|
|
|
|
|
|
|
from telegram.vendor.ptb_urllib3.urllib3.util.timeout import Timeout
|
|
|
|
|
2017-08-11 23:58:41 +02:00
|
|
|
class OkException(Exception):
|
|
|
|
pass
|
2017-06-18 12:14:24 +02:00
|
|
|
|
2019-01-30 19:38:15 +01:00
|
|
|
TIMEOUT = 500
|
2017-06-18 12:14:24 +02:00
|
|
|
|
2019-01-30 19:38:15 +01:00
|
|
|
def request_wrapper(*args, **kwargs):
|
|
|
|
obj = kwargs.get('timeout')
|
|
|
|
if isinstance(obj, Timeout) and obj._read == TIMEOUT:
|
2017-08-11 23:58:41 +02:00
|
|
|
raise OkException
|
2017-06-18 12:14:24 +02:00
|
|
|
|
2019-01-30 19:38:15 +01:00
|
|
|
return b'{"ok": true, "result": []}'
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request._request_wrapper', request_wrapper)
|
|
|
|
|
|
|
|
# Test file uploading
|
|
|
|
with pytest.raises(OkException):
|
|
|
|
bot.send_photo(chat_id, open('tests/data/telegram.jpg', 'rb'), timeout=TIMEOUT)
|
2015-12-26 18:32:36 +01:00
|
|
|
|
2019-01-30 19:38:15 +01:00
|
|
|
# Test JSON submition
|
2017-08-11 23:58:41 +02:00
|
|
|
with pytest.raises(OkException):
|
2019-01-30 19:38:15 +01:00
|
|
|
bot.get_chat_administrators(chat_id, timeout=TIMEOUT)
|
2019-02-13 11:37:13 +01:00
|
|
|
|
|
|
|
def test_timeout_propagation_implicit(self, monkeypatch, bot, chat_id):
|
|
|
|
|
|
|
|
from telegram.vendor.ptb_urllib3.urllib3.util.timeout import Timeout
|
|
|
|
|
|
|
|
class OkException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def request_wrapper(*args, **kwargs):
|
|
|
|
obj = kwargs.get('timeout')
|
|
|
|
if isinstance(obj, Timeout) and obj._read == 20:
|
|
|
|
raise OkException
|
|
|
|
|
|
|
|
return b'{"ok": true, "result": []}'
|
|
|
|
|
|
|
|
monkeypatch.setattr('telegram.utils.request.Request._request_wrapper', request_wrapper)
|
|
|
|
|
|
|
|
# Test file uploading
|
|
|
|
with pytest.raises(OkException):
|
|
|
|
bot.send_photo(chat_id, open('tests/data/telegram.jpg', 'rb'))
|