Telegram 机器人:如何在一次更新中从同一 media_group_id 下载多张照片?

问题描述 投票:0回答:1

这个问题是上一篇文章中提出的以下问题的后续问题。

这是我的代码块,用于从同一 media_group_id 上下文中的电报机器人下载所有照片。

async def download_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Download the highest resolution photo sent in each message update."""
    photo = update.message.photo
    media_paths = []

    if photo:
        # The last item in the photo array is the highest resolution version
        file_id = photo[-1].file_id
        logger.info(f'Processing photo with file_id: {file_id}')

        try:
            file_info = await context.bot.get_file(file_id)
            download_url = file_info.file_path  # This is already the full path
            print("download path")
            print(download_url)
            # Create a unique filename for each photo, using the message_id and unique file_id
            file_name = f'photo_{update.message.message_id}_{photo[-1].file_unique_id}.jpg'

            # Log the full download URL
            full_download_url = f"{download_url}"
            logger.info(f'Downloading photo from URL: {full_download_url}')

            # Download the photo using the download URL
            response = requests.get(full_download_url)
            response.raise_for_status()  # Check if the download was successful
            with open(file_name, 'wb') as f:
                f.write(response.content)
            media_paths.append(file_name)
            logger.info(f'Downloaded photo successfully with file_id: {file_id}')
        except Exception as e:
            logger.error(f'Error downloading photo with file_id {file_id}: {e}')

    logger.info(f'All downloaded media paths: {media_paths}')
    return media_paths

我能够下载我发送的 2 张图片中的 1 张,下面是日志

INFO:__main__:Downloading photo from URL: https://api.telegram.org/file/bot12800363:AAF7LWpZz79LOVevA6OmFUAMA6SjVn2esns/photos/file_42.jpg
download path
https://api.telegram.org/file/bot1200363:AAF7LWpZz79LMA6SjVn2esns/photos/file_42.jpg
INFO:__main__:Downloaded photo successfully with file_id: AgACAgUAAxkBAAIBx2sdFpfpjbDNU4nclU_ji1AALGvDEbpJVhVl6sAQADAgADeQADNQQ
INFO:__main__:All downloaded media paths: ['photo_455_AQADxrwxG6SVYVZ-.jpg']
INFO:__main__:Tweet posted: 1827892852770193799
INFO:__main__:Deleted file: photo_455_AQADxrwxG6SVYVZ-.jpg

该 URL 无法使用,因为我必须修改它以符合 SO 准则。我正在尝试下载我发送的两个图像(或者全部,以防更多),但只下载了 1 个。该代码不会迭代 media_group_id 内的整个更新。您能否告诉我如何解决这个问题。

telegram telegram-bot python-telegram-bot py-telegram-bot-api
1个回答
0
投票

当收到消息组时,它们实际上是单独的消息,只是通过相同的

media_group_id
相互关联。请看下面的图片(我使用 Cloudflare Workers 托管机器人并将更新打印到输出)。

正如您所看到的,对于看似包含两个图像的单个消息,实际上有两个单独的消息,在两个不同的更新中收到了不同的

message_id

解决方案:

因此,对于可能的解决方案,一种简单的方法是接收第一个更新并将

media_group_id
存储在变量中。然后对于连续更新,请检查
media_group_id
。如果相同,也下载这些图像;否则,在一个单独的函数中,继续执行其余的逻辑。

如果你事先不知道图片的数量,使用超时来决定何时开始下载是一种常见的做法:

group_id = None
urls = []

def download_all_photos():
    media_paths = []
    
    for download_url, file_name, file_id in urls:
        try:
            # Log the full download URL
            full_download_url = f"{download_url}"
            logger.info(f'Downloading photo from URL: {full_download_url}')
    
            # Download the photo using the download URL
            response = requests.get(full_download_url)
            response.raise_for_status()  # Check if the download was successful
            with open(file_name, 'wb') as f:
                f.write(response.content)
            media_paths.append(file_name)
            logger.info(f'Downloaded photo successfully with file_id: {file_id}')
        except Exception as e:
            logger.error(f'Error downloading photo with file_id {file_id}: {e}')

    logger.info(f'All downloaded media paths: {media_paths}')
    return media_paths

async def download_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    global group_id
    """Download the highest resolution photo sent in each message update."""
    photo = update.message.photo

    if photo:
        # The last item in the photo array is the highest resolution version
        file_id = photo[-1].file_id
        logger.info(f'Processing photo with file_id: {file_id}')

        file_info = await context.bot.get_file(file_id)
        download_url = file_info.file_path  # This is already the full path
        print("download path")
        print(download_url)
        # Create a unique filename for each photo, using the message_id and unique file_id
        file_name = f'photo_{update.message.message_id}_{photo[-1].file_unique_id}.jpg'
        
        # Append the download URL, file name, and file ID to the list of downloads
        urls.append([download_url, file_name, file_id])
        
        if group_id is None and update.message.media_group_id:
            group_id = update.message.media_group_id
            
        # Schedule the download after a short delay to ensure all updates are received
        await asyncio.sleep(2)
        
        # Check if no new message with the same media_group_id has been received
        if update.message.media_group_id != group_id:  # if there are 2 photos in the group 
            download_all_photos()
            group_id = None
            urls.clear()

另一种可能的解决方案是记下当前更新的

media_group_id
并迭代最后的消息以查找分组的消息。但是,目前机器人无法访问消息历史记录(请参阅此答案),因此您仍然需要依赖保存每个消息更新,这又回到了之前的方法。

© www.soinside.com 2019 - 2024. All rights reserved.