diff --git a/README.md b/README.md index 15708ac..c950015 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,16 @@ tb.send_location(chat_id, lat, lon) # action_string can be one of the following strings: 'typing', 'upload_photo', 'record_video', 'upload_video', # 'record_audio', 'upload_audio', 'upload_document' or 'find_location'. tb.send_chat_action(chat_id, action_string) + +# getFile +# Downloading a file is straightforward +# Returns a File object +import requests +file_info = tb.get_file(file_id) + +file = requests.get('https://api.telegram.org/file/bot{0}/{1}'.format(API_TOKEN, file_info.file_path)) + + ``` #### Reply markup All `send_xyz` functions of TeleBot take an optional `reply_markup` argument. This argument must be an instance of `ReplyKeyboardMarkup`, `ReplyKeyboardHide` or `ForceReply`, which are defined in types.py. diff --git a/examples/download_file_example.py b/examples/download_file_example.py new file mode 100644 index 0000000..d9003d1 --- /dev/null +++ b/examples/download_file_example.py @@ -0,0 +1,15 @@ +import telebot + +TOKEN = 'YOUR BOT TOKEN' +CHAT_ID = 'YOUR CHAT ID' + +bot = telebot.TeleBot(TOKEN) + +ret_msg = bot.send_voice(CHAT_ID, open('tests/test_data/record.ogg')) + +file_info = bot.get_file(ret_msg.voice.file_id) + +downloaded_file = bot.download_file(file_info.file_path) + +with open('new_file.ogg', 'wb') as new_file: + new_file.write(downloaded_file) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3474c09..7274187 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -22,10 +22,6 @@ from telebot import apihelper, types, util """ Module : telebot """ - -API_URL = r"https://api.telegram.org/" - - class TeleBot: """ This is TeleBot Class Methods: @@ -169,6 +165,12 @@ class TeleBot: result = apihelper.get_me(self.token) return types.User.de_json(result) + def get_file(self, file_id): + return types.File.de_json(apihelper.get_file(self.token, file_id)) + + def download_file(self, file_path): + return apihelper.download_file(self.token, file_path) + def get_user_profile_photos(self, user_id, offset=None, limit=None): """ Retrieves the user profile photos of the person with 'user_id' diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 07e8d3e..0e9e14b 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -7,8 +7,11 @@ from telebot import util logger = telebot.logger +API_URL = "https://api.telegram.org/bot{0}/{1}" +FILE_URL = "https://api.telegram.org/file/bot{0}/{1}" -def _make_request(token, method_name, method='get', params=None, files=None): + +def _make_request(token, method_name, method='get', params=None, files=None, base_url=API_URL): """ Makes a request to the Telegram API. :param token: The bot's API token. (Created with @BotFather) @@ -18,10 +21,10 @@ def _make_request(token, method_name, method='get', params=None, files=None): :param files: Optional files. :return: The result parsed to a JSON dictionary. """ - request_url = telebot.API_URL + 'bot' + token + '/' + method_name + request_url = base_url.format(token, method_name) logger.debug("Request: method={0} url={1} params={2} files={3}".format(method, request_url, params, files)) result = requests.request(method, request_url, params=params, files=files) - logger.debug("The server returned: '{0}'".format(result.text)) + logger.debug("The server returned: '{0}'".format(result.text.encode('utf8'))) return _check_result(method_name, result)['result'] @@ -62,6 +65,21 @@ def get_me(token): return _make_request(token, method_url) +def get_file(token, file_id): + method_url = 'getFile' + return _make_request(token, method_url, params={'file_id': file_id}) + + +def download_file(token, file_path): + url = FILE_URL.format(token, file_path) + result = requests.get(url) + if result.status_code != 200: + msg = 'The server returned HTTP {0} {1}. Response body:\n[{2}]'\ + .format(result.status_code, result.reason, result.text) + raise ApiException(msg, 'Download file', result) + return result.content + + def send_message(token, chat_id, text, disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None, parse_mode=None): """ diff --git a/telebot/types.py b/telebot/types.py index 37d84ea..e71ac05 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -408,6 +408,26 @@ class UserProfilePhotos(JsonDeserializable): self.total_count = total_count self.photos = photos +class File(JsonDeserializable): + + @classmethod + def de_json(cls, json_type): + obj = cls.check_json(json_type) + file_id = obj['file_id'] + + file_size = None + file_path = None + if 'file_size' in obj: + file_size = obj['file_size'] + if 'file_path' in obj: + file_path = obj['file_path'] + return File(file_id, file_size, file_path) + + def __init__(self, file_id, file_size, file_path): + self.file_id = file_id + self.file_size = file_size + self.file_path = file_path + class ForceReply(JsonSerializable): def __init__(self, selective=None): diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 6090bec..8c72302 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -155,6 +155,14 @@ class TestTeleBot: ret_msg = tb.send_voice(CHAT_ID, file_data) assert ret_msg.voice.mime_type == 'audio/ogg' + def test_get_file(self): + file_data = open('./test_data/record.ogg', 'rb') + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_voice(CHAT_ID, file_data) + file_id = ret_msg.voice.file_id + file_info = tb.get_file(file_id) + assert file_info.file_id == file_id + def test_send_message(self): text = 'CI Test Message' tb = telebot.TeleBot(TOKEN)