Telegram bots. Uploading files larger than 50mb

  • Tutorial

Telegram bots allow you to automate many processes. Their use is not limited to one chat, in fact - a bot is just an input-output interface , which, in addition to text , can also receive and transfer files : images, video, audio, documents ...

  • For users, the maximum file size is 1.5GB
  • Bots are limited to only 50mb in size

How to get around this restriction - under the cut.

Telegram API


Since users can upload files up to 1.5GB - that means we can - for this we will create an agent (named so as not to be confused with bots) that will work in conjunction with our Telegram bot. This will require a separate account and Telegram API.

First, go to https://core.telegram.org and follow the instructions to register the application, in the end you should get api_id and api_hash



What does an agent do?


The bot cannot upload files larger than 50mb, but if it has the file_id of a file already uploaded to the Telegram server, then it can send it. So the algorithm is as follows

  1. An application running on the server through the Bot API generates a file for sending
  2. Calls an agent to upload a file to the Telegram server
  3. Gets file_id from agent
  4. Uses a downloaded file

Code example


The need to download large files appeared when writing @AudioTubeBot - initially the audio file was divided into parts and sent in parts. The functionality of downloading large files, it was decided to put in a separate application, which is called through subprocess.check_call

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from telethon import TelegramClient
from telethon.tl.types import DocumentAttributeAudio
import mimetypes
entity = 'AudioTube_bot' #имя сессии - все равно какое
api_id = 1959
api_hash = '88b68d6da53fe68c1c3541bbefc'
phone =  '+79620181488'
client = TelegramClient(entity, api_id, api_hash, update_workers=None, spawn_read_thread=False)
client.connect()
if not client.is_user_authorized():
    # client.send_code_request(phone) #при первом запуске - раскомментить, после авторизации для избежания FloodWait советую закомментить
    client.sign_in(phone, input('Enter code: '))
client.start()
def main(argv):
    file_path = argv[1]
    file_name = argv[2]
    chat_id = argv[3]
    object_id = argv[4]
    bot_name = argv[5]
    duration = argv[6]
    mimetypes.add_type('audio/aac','.aac')
    mimetypes.add_type('audio/ogg','.ogg')
    msg = client.send_file(
                           str(bot_name),
                           file_path,
                           caption=str(chat_id + ':' + object_id + ':' + duration),
                           file_name=str(file_name),
                           use_cache=False,
                           part_size_kb=512,
                           attributes=[DocumentAttributeAudio(
                                                      int(duration),
                                                      voice=None,
                                                      title=file_name[:-4],
                                                      performer='')]
                           )
    client.disconnect()
    return 0
if __name__ == '__main__':
    import sys
    main(sys.argv[0:])

Comments:


That's the whole code - the Telethon library is used here - at startup the program receives the path to the file to send, the file name, chat_id - who the file is for), the name of the bot that called the agent (for example, I have beta and release bots).

client.send_file


Just uploading the file to the server via upload , getting file_id and passing it to the bot will not work, file_id only works inside the chat in which it was created - so that our bot can send the file to the user by file_id - the agent must send him this file
- then the bot will receive own file_id for this file and will be able to dispose of it.

caption = str (...) - wat ?!


The agent sends files only to the bot, adding a comment to caption - I have this:

  • end user chat_id
  • track duration
  • object_id in the database to which file_id needs to be bound so as not to reload the file (indexing, optimization and all that)



Example call in bot code


A file has already been saved on path_file_mp3 for loading, we call the subroutine and wait for it to complete.

the code
status = subprocess.check_call(
             "python3.6 audiotubeagent36/main.py " +
             path_file_mp3 + ' ' +
             audio_title + '.'+ us_audio_codec +
             ' ' + str(chat_id) + 
             ' ' + str(pool_object['_id']) +
             ' ' + config.BOT_NAME + 
             ' ' + str(duration),shell=True)


In the inbox, do something like this.

the code
    if message.content_type in ['document','audio']:
        user_id = message.from_user.id
        bot_settings = SafeConfigParser()
        bot_settings.read(config.PATH_SETTINGS_FILE)
        c_type = message.content_type
        if functions.check_is_admin(bot_settings, user_id):
            if c_type == 'audio':
                file_id = message.audio.file_id
                audio_title = message.audio.title
            else:
                file_id = message.document.file_id
                audio_title = message.document.file_name[:-4]
            client_chat_id = message.caption
            if client_chat_id.find(u':') != -1:
                client_chat_id, q_pool_obj_id, duration_s = re.split(r':',client_chat_id)
#добавляем file_id в базу
                q_pool.update_request_file_id(str(q_pool_obj_id), str(file_id))
#пересылаем конечному адресату
            bot.send_audio(int(client_chat_id), 
                                   file_id,caption='',
                                   duration=int(duration_s),
                                   title=audio_title,
                                   performer='')
        return


Questions / suggestions write in the comments or chat .

Also popular now: