如何在aiogram 3中编辑媒体消息及实现内联按钮更新消息内容
aiogram 3 媒体消息编辑与多图更新方案
一、替换原消息编辑单媒体内容
你的代码使用answer_photo会发送新消息,要更新原消息需改用edit_media方法,步骤如下:
- 用
InputMediaPhoto构造包含图片和标题的媒体对象 - 调用
call.message.edit_media覆盖原消息内容,同时可更新内联键盘 - 必须调用
call.answer()结束回调查询,避免用户端显示加载状态
修正后的代码:
@catalog_router.callback_query(lambda c: c.data.startswith('cookies')) async def cookies(call: types.CallbackQuery): # 构造图片媒体对象 input_media = types.InputMediaPhoto( media=FSInputFile('./data/assets/cookies.jpg'), caption=( "Привіт друзі YUMMYK на зв'язку) Сьогодні, ми попрацювали на славу! І готували надзвичайно смачне печиво, як з дитинства. " "Бо кожному батьки купляли саме \"вівсяне печиво\" кажучи, що воно корисне. Наша команда вирішила, що ми також будемо готувати корисне печиво. " "Процес приготування цього рецепту нас просто заворожив, і в результаті отримали печиво, яке точно заслуговує вашої уваги!" ) ) # 编辑原消息的媒体内容与键盘 await call.message.edit_media( media=input_media, reply_markup=conditers_catalog ) # 结束回调查询 await call.answer()
二、多图展示与更新实现
Telegram的媒体组(单条消息含多张可滑动图片)需用InputMediaGroup构造,但Bot API暂不支持直接编辑整个媒体组,需通过「删除原组+发送新组」的方式实现更新,或改用单图切换逻辑(适合需要逐张展示带描述的场景)。
方式1:媒体组替换(多图批量更新)
1. 发送初始媒体组
@catalog_router.callback_query(lambda c: c.data == 'show_cookie_group') async def send_cookie_group(call: types.CallbackQuery): # 构造多图媒体组,每个图片可单独设置描述(部分客户端切换图片时会显示对应描述) media_group = [ types.InputMediaPhoto( media=FSInputFile('./data/assets/cookie1.jpg'), caption="经典燕麦款:童年味道复刻" ), types.InputMediaPhoto( media=FSInputFile('./data/assets/cookie2.jpg'), caption="巧克力豆款:浓郁可可香气" ), types.InputMediaPhoto( media=FSInputFile('./data/assets/cookie3.jpg'), caption="坚果混合款:香脆口感升级" ) ] # 发送媒体组,返回的是一组消息对象(每个图片对应一条消息) sent_messages = await call.message.answer_media_group(media=media_group) # 存储第一个消息的ID,后续用于定位删除整个媒体组(媒体组消息ID连续) # 可通过缓存/数据库存储,例如:redis.set(f"user_{call.from_user.id}_media_group", sent_messages[0].message_id) await call.answer()
2. 点击按钮更新媒体组
@catalog_router.callback_query(lambda c: c.data == 'update_cookie_group') async def update_cookie_group(call: types.CallbackQuery): chat_id = call.message.chat.id # 从缓存/数据库获取原媒体组第一个消息的ID original_msg_id = ... # 示例:await redis.get(f"user_{call.from_user.id}_media_group") original_msg_id = int(original_msg_id) # 删除原媒体组的所有消息(媒体组消息ID连续,共3条则循环删除) for i in range(3): await call.bot.delete_message(chat_id=chat_id, message_id=original_msg_id + i) # 构造新的媒体组 new_media_group = [ types.InputMediaPhoto( media=FSInputFile('./data/assets/new_cookie1.jpg'), caption="低糖燕麦款:健康无负担" ), types.InputMediaPhoto( media=FSInputFile('./data/assets/new_cookie2.jpg'), caption="水果干款:酸甜风味碰撞" ) ] # 发送新的媒体组 await call.message.answer_media_group(media=new_media_group) await call.answer()
方式2:单图切换(逐张展示带描述)
如果不需要同时展示所有图片,可通过内联按钮切换单张图片与对应描述,直接用edit_media实现无删除更新:
# 假设内联键盘包含切换按钮:"燕麦曲奇"、"巧克力曲奇" @catalog_router.callback_query(lambda c: c.data.startswith('switch_cookie_')) async def switch_cookie(call: types.CallbackQuery): # 解析回调数据中的曲奇类型 cookie_type = call.data.split('_')[-1] # 根据类型选择图片与描述 if cookie_type == 'oat': photo_path = './data/assets/oat_cookie.jpg' caption = "燕麦曲奇:富含膳食纤维,还原童年经典味道" elif cookie_type == 'chocolate': photo_path = './data/assets/chocolate_cookie.jpg' caption = "巧克力曲奇:进口可可豆,丝滑口感层次丰富" # 构造新的媒体对象 input_media = types.InputMediaPhoto( media=FSInputFile(photo_path), caption=caption ) # 编辑原消息的媒体内容与键盘 await call.message.edit_media(media=input_media, reply_markup=conditers_catalog) await call.answer()
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

