Telegram机器人开发中,内联查询(Inline Query)是用户直接在聊天输入框输入@机器人 关键词时触发的功能。当搜索结果很多时,Telegram允许机器人分页返回结果,用户通过“加载更多”或翻页按钮查看后续内容。本文详解实现原理和两种主流的实现方法。
一、理解Telegram内联查询的分页机制
Telegram内联查询有一个重要参数 offset。当机器人返回结果时,可以附带一个字符串类型的offset,Telegram会将此值原样传回给机器人的下一次查询请求。利用这个特性,我们可以实现游标分页。
注意:Telegram的内联查询一次最多返回50个结果。如果搜索项超过50个,就必须分页。
二、方法一:使用offset参数实现基础分页
- 在InlineQueryHandler中读取
query.offset。 - 根据offset从数据库或API获取下一组数据。
- 构造新的结果列表时,设置新的offset值。
- 返回结果给Telegram。
# aiogram示例
@router.inline_query()
async def inline_query_handler(query: InlineQuery):
offset = int(query.offset or 0)
results = fetch_items(offset, limit=10)
next_offset = str(offset + 10) if len(results) == 10 else ""
await query.answer(
results=results,
next_offset=next_offset,
cache_time=0
)
当返回next_offset非空时,Telegram会在客户端显示一个“加载更多”按钮,用户点击后自动发起带新offset的查询。
三、方法二:通过回调按钮加载更多
有些场景下我们希望自己在结果下方添加“更多”按钮,而不是依赖Telegram默认的加载按钮。此时可以结合内联键盘(InlineKeyboardButton)和CallbackQuery实现。
- 在内联查询结果中附加一个回调按钮,按钮的callback_data包含当前页码或游标。
- 用户点击按钮时,机器人收到CallbackQuery。
- 在回调中获取新的数据,并编辑原始消息,替换内联键盘或新增结果。
# 伪代码示意
CALLBACK_LOAD_MORE = "load_more"
@router.callback_query(lambda c: c.data == CALLBACK_LOAD_MORE)
async def load_more_callback(callback: CallbackQuery):
# 从callback.message中获取当前状态,例如页码
page = int(getattr(callback.message, 'page', 1))
new_results = fetch_items(page * 10, 10)
# 构建新的内联键盘,页码+1
# 编辑消息内容或按钮
await callback.message.edit_reply_markup(reply_markup=build_keyboard(page+1))
await callback.answer()
这种方式需要自己在消息里维护状态。
四、进阶技巧:搜索状态管理与防重复提交
- 搜索状态管理:每次查询都是无状态的,推荐将查询关键字和页码编码进offset。例如
f":",否则容易混淆。 - 防止重复点击加载更多:在回调中处理时,可以先禁用按钮或检查时间戳。
- 缓存优化:适当设置cache_time可减轻服务器压力,但要注意更新数据时设置cache_time=0。
总结
Telegram内联查询分页主要依赖offset机制,也有回调式交互方案。开发者应根据交互体验选择合适的方式。掌握分页能让您的机器人在搜索结果中游刃有余。