From 5c6de8aa042d6237bd13cd6880c00f13081e97f3 Mon Sep 17 00:00:00 2001 From: eternnoir Date: Wed, 19 Aug 2015 18:36:10 +0800 Subject: [PATCH 1/4] Update version. Change log: - New type Voice - Update audio - sendAduio - sendVoice checkout: https://core.telegram.org/bots/api-changelog 20150815 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 0fec122..8606778 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,14 @@ from setuptools import setup setup(name='pyTelegramBotAPI', - version='0.3.0', + version='0.3.1', description='Python Telegram bot api. ', author='eternnoir', author_email='eternnoir@gmail.com', url='https://github.com/eternnoir/pyTelegramBotAPI', packages=['telebot'], license='GPL2', - keywords='tools', + keywords='telegram bot api tools', install_requires=['pytest', 'requests', 'six'], classifiers=[ 'Development Status :: 5 - Production/Stable', From 596df2ef2cbe61ad976980c130127a7ec13d570e Mon Sep 17 00:00:00 2001 From: 97Pedrito Date: Wed, 19 Aug 2015 21:29:17 +0200 Subject: [PATCH 2/4] Extended error descriptions They should provide more information about the origin of the failure. --- telebot/apihelper.py | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index fafd5d9..66cb6e3 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -16,20 +16,44 @@ def _make_request(token, method_name, method='get', params=None, files=None): :param method: HTTP method to be used. Defaults to 'get'. :param params: Optional parameters. Should be a dictionary with key-value pairs. :param files: Optional files. - :return: + :return: The result parsed to a JSON dictionary. """ request_url = telebot.API_URL + 'bot' + token + '/' + method_name result = requests.request(method, request_url, params=params, files=files) logger.debug(result.text) + return _check_result(method_name, result)['result'] + + +def _check_result(method_name, result): + """ + Checks whether `result` is a valid API response. + A result is considered invalid if: + - The server returned an HTTP response code other than 200 + - The content of the result is invalid JSON. + - The method call was unsuccessful (The JSON 'ok' field equals False) + + :raises ApiException: if one of the above listed cases is applicable + :param method_name: The name of the method called + :param result: The returned result of the method request + :return: The result parsed to a JSON dictionary. + """ if result.status_code != 200: - raise ApiException(method_name, result) + msg = 'The server returned HTTP {0} {1}. Response body:\n[{2}]'\ + .format(result.status_code, result.reason, result.text) + raise ApiException(msg, method_name, result) + try: result_json = result.json() - if not result_json['ok']: - raise Exception() except: - raise ApiException(method_name, result) - return result_json['result'] + msg = 'The server returned an invalid JSON response. Response body:\n[{0}]'\ + .format(result.text) + raise ApiException(msg, method_name, result) + + if not result_json['ok']: + msg = 'Error code: {0} Description: {1}'\ + .format(result_json['error_code'], result_json['description']) + raise ApiException(msg, method_name, result) + return result_json def get_me(token): @@ -251,9 +275,12 @@ def split_string(text, chars_per_string): class ApiException(Exception): """ This class represents an Exception thrown when a call to the Telegram API fails. + In addition to an informative message, it has a `function_name` and a `result` attribute, which respectively + contain the name of the failed function and the returned result that made the function to be considered as + failed. """ - def __init__(self, function_name, result): - super(ApiException, self).__init__('{0} failed. Returned result: {1}'.format(function_name, result)) + def __init__(self, msg, function_name, result): + super(ApiException, self).__init__("A request to the Telegram API was unsuccessful. {0}".format(msg)) self.function_name = function_name self.result = result From 8412be133685f54cce97a9bb458c37b3dc09e3c6 Mon Sep 17 00:00:00 2001 From: 97Pedrito Date: Wed, 19 Aug 2015 22:10:33 +0200 Subject: [PATCH 3/4] (Attempt to) fix failing Travis CI tests. --- tests/test_telebot.py | 300 ++++++++++++++++++++---------------------- 1 file changed, 142 insertions(+), 158 deletions(-) diff --git a/tests/test_telebot.py b/tests/test_telebot.py index a53a3f0..de704e7 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -1,200 +1,184 @@ # -*- coding: utf-8 -*- import sys import time - -sys.path.append('../') -from telebot import types -from telebot import apihelper -import telebot +import pytest import os -TOKEN = os.environ['TOKEN'] -CHAT_ID = os.environ['CHAT_ID'] +import telebot +from telebot import types +from telebot import apihelper +sys.path.append('../') -def test_message_listener(): - msg_list = [] - for x in range(100): - msg_list.append(create_text_message('Message ' + str(x))) +should_skip = 'TOKEN' and 'CHAT_ID' not in os.environ - def listener(messages): - assert len(messages) == 100 +if not should_skip: + TOKEN = os.environ['TOKEN'] + CHAT_ID = os.environ['CHAT_ID'] - tb = telebot.TeleBot('') - tb.set_update_listener(listener) +@pytest.mark.skipif(should_skip, reason="No environment variables configured") +class TestTeleBot: + def test_message_listener(self): + msg_list = [] + for x in range(100): + msg_list.append(self.create_text_message('Message ' + str(x))) -def test_message_handler(): - tb = telebot.TeleBot('') - msg = create_text_message('/help') + def listener(messages): + assert len(messages) == 100 - @tb.message_handler(commands=['help', 'start']) - def command_handler(message): - message.text = 'got' + tb = telebot.TeleBot('') + tb.set_update_listener(listener) - tb.process_new_messages([msg]) - time.sleep(1) - assert msg.text == 'got' + def test_message_handler(self): + tb = telebot.TeleBot('') + msg = self.create_text_message('/help') + @tb.message_handler(commands=['help', 'start']) + def command_handler(message): + message.text = 'got' -def test_message_handler_reg(): - bot = telebot.TeleBot('') - msg = create_text_message(r'https://web.telegram.org/') + tb.process_new_messages([msg]) + time.sleep(1) + assert msg.text == 'got' - @bot.message_handler(regexp='((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)') - def command_url(message): - msg.text = 'got' + def test_message_handler_reg(self): + bot = telebot.TeleBot('') + msg = self.create_text_message(r'https://web.telegram.org/') - bot.process_new_messages([msg]) - time.sleep(1) - assert msg.text == 'got' + @bot.message_handler(regexp='((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)') + def command_url(message): + msg.text = 'got' + bot.process_new_messages([msg]) + time.sleep(1) + assert msg.text == 'got' -def test_message_handler_reg_fail(): - bot = telebot.TeleBot('') - msg = create_text_message(r'web.telegram.org/') + def test_message_handler_reg_fail(self): + bot = telebot.TeleBot('') + msg = self.create_text_message(r'web.telegram.org/') - @bot.message_handler(regexp='((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)') - def command_url(message): - msg.text = 'got' + @bot.message_handler(regexp='((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)') + def command_url(message): + msg.text = 'got' - bot.process_new_messages([msg]) - time.sleep(1) - assert not msg.text == 'got' + bot.process_new_messages([msg]) + time.sleep(1) + assert not msg.text == 'got' + def test_send_file_by_id(self): + file_id = 'BQADBQADjAIAAsYifgbvqwq1he9REAI' + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_document(CHAT_ID, file_id) + assert ret_msg.message_id -def test_send_file_by_id(): - file_id = 'BQADBQADjAIAAsYifgbvqwq1he9REAI' - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_document(CHAT_ID, file_id) - assert ret_msg.message_id + def test_send_file(self): + file_data = open('../examples/detailed_example/kitten.jpg', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_document(CHAT_ID, file_data) + assert ret_msg.message_id + def test_send_video(self): + file_data = open('./test_data/test_video.mp4', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_video(CHAT_ID, file_data) + assert ret_msg.message_id -def test_send_file(): - file_data = open('../examples/detailed_example/kitten.jpg', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_document(CHAT_ID, file_data) - assert ret_msg.message_id + def test_send_video_more_params(self): + file_data = open('./test_data/test_video.mp4', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_video(CHAT_ID, file_data, 1) + assert ret_msg.message_id + def test_send_file_exception(self): + tb = telebot.TeleBot(TOKEN) + try: + tb.send_document(CHAT_ID, None) + assert False + except Exception as e: + print(e) + assert True -def test_send_video(): - file_data = open('./test_data/test_video.mp4', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_video(CHAT_ID, file_data) - assert ret_msg.message_id + def test_send_photo_by_id(self): + photo_id = 'AgADBQADTKgxG8YifgbcWQAB7Da9yYIx1rEyAAT-HYJ3CrJEqdA2AQABAg' + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_photo(CHAT_ID, photo_id) + assert ret_msg.message_id + def test_send_photo(self): + file_data = open('../examples/detailed_example/kitten.jpg', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_photo(CHAT_ID, file_data) + assert ret_msg.message_id -def test_send_video_more_params(): - file_data = open('./test_data/test_video.mp4', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_video(CHAT_ID, file_data, 1) - assert ret_msg.message_id + def test_send_audio(self): + file_data = open('./test_data/record.mp3', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_audio(CHAT_ID, file_data, 1, 'eternnoir', 'pyTelegram') + assert ret_msg.content_type == 'audio' + assert ret_msg.audio.performer == 'eternnoir' + assert ret_msg.audio.title == 'pyTelegram' + def test_send_voice(self): + file_data = open('./test_data/record.ogg', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_voice(CHAT_ID, file_data) + assert ret_msg.voice.mime_type == 'audio/ogg' -def test_send_file_exception(): - tb = telebot.TeleBot(TOKEN) - try: - ret_msg = tb.send_document(CHAT_ID, None) - assert False - except Exception as e: - print(e) - assert True + def test_send_message(self): + text = 'CI Test Message' + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_message(CHAT_ID, text) + assert ret_msg.message_id + def test_forward_message(self): + text = 'CI forward_message Test Message' + tb = telebot.TeleBot(TOKEN) + msg = tb.send_message(CHAT_ID, text) + ret_msg = tb.forward_message(CHAT_ID, CHAT_ID, msg.message_id) + assert ret_msg.forward_from -def test_send_photo_by_id(): - photo_id = 'AgADBQADTKgxG8YifgbcWQAB7Da9yYIx1rEyAAT-HYJ3CrJEqdA2AQABAg' - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_photo(CHAT_ID, photo_id) - assert ret_msg.message_id + def test_reply_to(self): + text = 'CI reply_to Test Message' + tb = telebot.TeleBot(TOKEN) + msg = tb.send_message(CHAT_ID, text) + ret_msg = tb.reply_to(msg, text + ' REPLY') + assert ret_msg.reply_to_message.message_id == msg.message_id + def test_register_for_reply(self): + text = 'CI reply_to Test Message' + tb = telebot.TeleBot(TOKEN) + msg = tb.send_message(CHAT_ID, text, reply_markup=types.ForceReply()) + reply_msg = tb.reply_to(msg, text + ' REPLY') -def test_send_photo(): - file_data = open('../examples/detailed_example/kitten.jpg', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_photo(CHAT_ID, file_data) - assert ret_msg.message_id + def process_reply(message): + assert msg.message_id == message.reply_to_message.message_id + tb.register_for_reply(msg, process_reply) -def test_send_audio(): - file_data = open('./test_data/record.mp3', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_audio(CHAT_ID, file_data, 1, 'eternnoir', 'pyTelegram') - assert ret_msg.content_type == 'audio' - assert ret_msg.audio.performer == 'eternnoir' - assert ret_msg.audio.title == 'pyTelegram' + tb.process_new_messages([reply_msg]) + def test_send_location(self): + tb = telebot.TeleBot(TOKEN) + lat = 26.3875591 + lon = -161.2901042 + ret_msg = tb.send_location(CHAT_ID, lat, lon) + assert int(ret_msg.location.longitude) == int(lon) + assert int(ret_msg.location.latitude) == int(lat) -def test_send_voice(): - file_data = open('./test_data/record.ogg', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_voice(CHAT_ID, file_data) - assert ret_msg.voice.mime_type == 'audio/ogg' + def create_text_message(self, text): + params = {'text': text} + chat = types.User(11, 'test') + return types.Message(1, None, None, chat, 'text', params) + def test_is_string_unicode(self): + s1 = u'string' + assert apihelper.is_string(s1) -def test_send_message(): - text = 'CI Test Message' - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_message(CHAT_ID, text) - assert ret_msg.message_id + def test_is_string_string(self): + s1 = 'string' + assert apihelper.is_string(s1) - -def test_forward_message(): - text = 'CI forward_message Test Message' - tb = telebot.TeleBot(TOKEN) - msg = tb.send_message(CHAT_ID, text) - ret_msg = tb.forward_message(CHAT_ID, CHAT_ID, msg.message_id) - assert ret_msg.forward_from - - -def test_reply_to(): - text = 'CI reply_to Test Message' - tb = telebot.TeleBot(TOKEN) - msg = tb.send_message(CHAT_ID, text) - ret_msg = tb.reply_to(msg, text + ' REPLY') - assert ret_msg.reply_to_message.message_id == msg.message_id - - -def test_register_for_reply(): - text = 'CI reply_to Test Message' - tb = telebot.TeleBot(TOKEN) - msg = tb.send_message(CHAT_ID, text, reply_markup=types.ForceReply()) - reply_msg = tb.reply_to(msg, text + ' REPLY') - - def process_reply(message): - assert msg.message_id == message.reply_to_message.message_id - - tb.register_for_reply(msg, process_reply) - - tb.process_new_messages([reply_msg]) - - -def test_send_location(): - tb = telebot.TeleBot(TOKEN) - lat = 26.3875591 - lon = -161.2901042 - ret_msg = tb.send_location(CHAT_ID, lat, lon) - assert int(ret_msg.location.longitude) == int(lon) - assert int(ret_msg.location.latitude) == int(lat) - - -def create_text_message(text): - params = {'text': text} - chat = types.User(11, 'test') - return types.Message(1, None, None, chat, 'text', params) - - -def test_is_string_unicode(): - s1 = u'string' - assert apihelper.is_string(s1) - - -def test_is_string_string(): - s1 = 'string' - assert apihelper.is_string(s1) - - -def test_not_string(): - i1 = 10 - assert not apihelper.is_string(i1) - -test_send_voice() + def test_not_string(self): + i1 = 10 + assert not apihelper.is_string(i1) From ee0ff8b1fb1c067b48e0dbe92a698add1fc5b78e Mon Sep 17 00:00:00 2001 From: 97Pedrito Date: Wed, 19 Aug 2015 22:15:40 +0200 Subject: [PATCH 4/4] Fix test case --- tests/test_telebot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_telebot.py b/tests/test_telebot.py index de704e7..989563b 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- import sys +sys.path.append('../') + import time import pytest import os @@ -8,14 +10,13 @@ import telebot from telebot import types from telebot import apihelper -sys.path.append('../') - should_skip = 'TOKEN' and 'CHAT_ID' not in os.environ if not should_skip: TOKEN = os.environ['TOKEN'] CHAT_ID = os.environ['CHAT_ID'] + @pytest.mark.skipif(should_skip, reason="No environment variables configured") class TestTeleBot: