- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
在 Telegram Bot API 中,"建议帖(Suggested Post)"是频道直接消息(Direct Messages)场景下的一种特殊消息形态:用户或管理员可以在频道私聊中起草一篇帖子并提交审批,由频道管理员决定是否采纳、何时发布。aiogram 将这一能力封装为完整的数据类型与方法链,其中SuggestedPostInfo正是描述"一条建议帖当前处于什么状态、定价多少、计划何时发送"的核心信息载体。本文将围绕 aiogram 仓库中的 docs/api/types/suggested_post_info.rst 文档所指代的SuggestedPostInfo类型,逐字段拆解其语义,并结合SuggestedPostPrice、SuggestedPostParameters、approveSuggestedPost/declineSuggestedPost方法以及Message上的相关字段,带你掌握从"创建建议帖"到"审批发布/拒绝"的完整技术闭环。
一、SuggestedPostInfo 是什么:建议帖的"身份信息卡"
SuggestedPostInfo定义在 aiogram/types/suggested_post_info.py,继承自 aiogram 的TelegramObject基类(aiogram/types/base.py),用于承载 Bot API 中suggestedPostInfo对象的全部数据。当一条消息带有该字段时,说明这条消息本身就是一个"待审批的建议帖"——通常出现在频道的直接消息聊天(direct messages chat)中。
class SuggestedPostInfo(TelegramObject): state: str price: SuggestedPostPrice | None = None send_date: DateTime | None = None从类型定义可以看出,该对象包含三个字段:
| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
state | str | 是 | 建议帖当前状态,目前取值只能是'pending'(待审批)、'approved'(已通过)、'declined'(已拒绝) |
price | SuggestedPostPrice \| None | 否 | 建议帖的拟定价;缺省表示该帖为免费(unpaid) |
send_date | DateTime \| None | 否 | 拟发布时间;缺省表示可由批准它的用户或管理员在 30 天内的任意时刻自主发布 |
在 aiogram/types/message.py 中,Message通过suggested_post_info字段(SuggestedPostInfo | None)引用该类型,同时文档注释明确:"如果该消息已被批准或拒绝,则它不能再被编辑"。这意味着SuggestedPostInfo不仅是状态快照,也决定了消息的可编辑性约束。
1. state:三种状态的流转骨架
state是SuggestedPostInfo唯一必填字段,直接驱动整个建议帖生命周期:
pending:建议帖已提交、等待审批,这是新建建议帖的初始状态;approved:帖子已被管理员批准,等待(或按计划)发布;declined:帖子已被管理员拒绝。
从仓库的变更记录 CHANGES.rst 可以看到,这一批建议帖相关类型与方法是随 aiogram 对 Telegram Bot API 建议帖能力的支持一并引入的,其中就包括代表建议帖信息的SuggestedPostInfo。
2. send_date:拟发布时刻的时间语义
send_date使用 aiogram 自定义的DateTime类型(定义于 aiogram/types/custom.py),在反序列化时会被转换为datetime对象,因此你在业务代码中拿到的是标准的 Pythondatetime,可以直接参与时间运算。其取值范围由创建与审批两侧共同约束(详见下文SuggestedPostParameters与approveSuggestedPost)。
二、price 字段的深层结构:SuggestedPostPrice
当建议帖被定价时,price字段是一个完整的SuggestedPostPrice对象,定义在 aiogram/types/suggested_post_price.py:
class SuggestedPostPrice(TelegramObject): currency: str amount: int1. currency:仅支持两种"货币"
currency目前只能取两个值之一:
'XTR':Telegram Stars,即 Telegram 星标积分;'TON':TON 链上的 Toncoin(以 TON grams 计)。
注意它并不等同于 aiogram/enums/currency.py 中Currency枚举所列举的 ISO 4217 法定货币(AED、CNY、EUR、USD……),而是 Telegram 体系内的两种原生"计价单位"。
2. amount:以最小单位计价的整数
amount表示以最小货币单位计的价格:
- 当
currency='XTR'时,amount就是 Telegram Stars 的数量,取值必须在5 到 100000之间; - 当
currency='TON'时,amount以 nanograms(1 TON = 10⁹ nanograms)为单位,取值必须在10000000(即 0.01 TON)到 10000000000000(即 10000 TON)之间。
在 aiogram 的测试数据中(见 tests/test_api/test_types/test_message.py),可以直观看到SuggestedPostPrice(currency="XTR", amount=100)的构造方式——即一个 100 Stars 的定价建议帖。
三、建议帖生命周期全景:从创建到审批的完整链路
SuggestedPostInfo只是生命周期中的"状态载体",要完整理解它,还需要配合 aiogram 提供的创建参数类型、审批方法与各类服务消息。从源码结构看,aiogram 将整条链路拆成了清晰的几块。
1. 创建侧:SuggestedPostParameters 定义"拟定价与拟发布时间"
当机器人向频道的直接消息聊天发送一条"建议帖"时,需要在发送方法中携带suggested_post_parameters参数,其类型为 aiogram/types/suggested_post_parameters.py 中的SuggestedPostParameters:
class SuggestedPostParameters(TelegramObject): price: SuggestedPostPrice | None = None send_date: DateTime | None = None该对象与SuggestedPostInfo的字段几乎一一对应,区别在于语义方向不同:
SuggestedPostParameters是发送方主动声明的"期望价格 / 期望时间";SuggestedPostInfo是消息中携带的"当前状态 + 实际定价 / 拟发布时刻"。
send_date在创建侧有明确范围约束:若指定,则必须是**未来 300 秒到 2678400 秒(30 天)**之间;若省略,则帖子可在 30 天内由批准它的用户自行决定发布时间。
SuggestedPostParameters被广泛挂载在各类发送方法上,以 aiogram/methods/send_message.py 的SendMessage为例:
suggested_post_parameters: SuggestedPostParameters | None = None """A JSON-serialized object containing the parameters of the suggested post to send; for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post is automatically declined"""同样的参数也出现在send_photo、send_video、send_audio等大部分发送方法中(可从 aiogram/types/message.py 中suggested_post_parameters的大量出现位置看出,aiogram 在众多发送方法的签名里都透出了该参数)。这里有一个值得注意的隐含行为:如果你以"回复某条建议帖"的方式发送新消息,原建议帖会被自动拒绝(declined)——回复即视为替代。
2. 审批侧:ApproveSuggestedPost 与 DeclineSuggestedPost
审批动作由两个 Telegram 方法完成,aiogram 分别封装为 aiogram/methods/approve_suggested_post.py 与 aiogram/methods/decline_suggested_post.py,二者均返回True表示成功。
ApproveSuggestedPost(对应 Bot API 的approveSuggestedPost):
| 参数 | 类型 | 说明 |
|---|---|---|
chat_id | int | 目标直接消息聊天的唯一标识 |
message_id | int | 要批准的建议帖消息 ID |
send_date | DateTimeUnion \| None | 期望发布时刻(Unix 时间戳);若创建时已指定则省略。若指定,不得晚于未来 2678400 秒(30 天) |
这里send_date的类型是DateTimeUnion(见 aiogram/types/date_time_union.py),即datetime | timedelta | int的别名,因此你既可以直接传 Unix 时间戳整数,也可以传datetime或timedelta(相对偏移),aiogram 会在序列化时自动处理。
DeclineSuggestedPost(对应declineSuggestedPost):
| 参数 | 类型 | 说明 |
|---|---|---|
chat_id | int | 目标直接消息聊天的唯一标识 |
message_id | int | 要拒绝的建议帖消息 ID |
comment | str \| None | 写给建议帖创建者的备注,0-128 个字符 |
审批方法对机器人权限有明确要求:批准需要机器人持有对应频道聊天的can_post_messages管理员权限;拒绝需要机器人持有can_manage_direct_messages管理员权限。权限不满足时,Bot API 会返回相应错误。
3. 消息侧的六类承载字段:状态事件的"服务消息"
建议帖从提交到落地,其各阶段事件都会以服务消息的形式出现在Message上。aiogram 在 aiogram/types/message.py 中为Message添加了六类相关字段,形成了与SuggestedPostInfo.state对应的完整事件面:
| Message 字段 | 类型 | 触发场景 |
|---|---|---|
suggested_post_info | SuggestedPostInfo \| None | 消息本身就是一条建议帖(带state/price/send_date) |
suggested_post_approved | SuggestedPostApproved \| None | 建议帖被批准的服务消息(含send_date、可选的消息体与价格) |
suggested_post_declined | SuggestedPostDeclined \| None | 建议帖被拒绝的服务消息(含可选拒绝备注comment) |
suggested_post_paid | SuggestedPostPaid \| None | 建议帖完成支付的服务消息(含currency、Stars 金额或 TON 金额) |
suggested_post_approval_failed | SuggestedPostApprovalFailed \| None | 审批失败的服务消息(目前仅因审批时用户资金不足触发,携带期望价格) |
suggested_post_refunded | SuggestedPostRefunded \| None | 支付退款的服务消息(reason为'post_deleted'或'payment_refunded') |
这些类型分别定义在 aiogram/types/suggested_post_approved.py、aiogram/types/suggested_post_declined.py、aiogram/types/suggested_post_paid.py、aiogram/types/suggested_post_approval_failed.py 与 aiogram/types/suggested_post_refunded.py,并在 aiogram/types/init.py 中统一导出。
几点值得注意的细节:
SuggestedPostApproved.send_date是必填字段,即"帖子将于何时发布";SuggestedPostPaid.currency必填,金额则视货币不同分别由star_amount: StarAmount | None(Stars 场景)与amount: int | None(TON nanograms 场景)承载,StarAmount定义于 aiogram/types/star_amount.py,支持nanostar_amount的 1/10⁹ 级细分;- 上述服务消息类型中携带的
suggested_post_message字段有一个共性约束:该Message对象不会包含reply_to_message字段,即使原帖本身是回复消息; - 退款
reason目前只有两种取值:'post_deleted'(发布后 24 小时内被删除,或未发布即从定时消息中移除)与'payment_refunded'(付款方发起退款)。
在 aiogram 的测试中(tests/test_api/test_types/test_message.py),六类场景均有对应的构造用例,例如suggested_post_approved=SuggestedPostApproved(send_date=1234567890)、suggested_post_approval_failed=SuggestedPostApprovalFailed(price=SuggestedPostPrice(currency="XTR", amount=100))、suggested_post_refunded=SuggestedPostRefunded(reason="post_deleted")等,可作为字段构造方式的权威参考。
四、实战:基于 aiogram 构建建议帖审批机器人
下面用一个完整的示例,把SuggestedPostInfo与审批方法串起来:机器人监听频道直接消息聊天中携带suggested_post_info的消息,根据state做分发,并演示批准(携带发布时间)与拒绝(携带备注)两种操作。
import asyncio import datetime from aiogram import Bot, Dispatcher, F, Router, types BOT_TOKEN = "YOUR_BOT_TOKEN" router = Router() # 1. 捕获"建议帖"消息,读取 SuggestedPostInfo @router.message(F.suggested_post_info) async def on_suggested_post(message: types.Message) -> None: info = message.suggested_post_info # info 一定非空(由 F.suggested_post_info 过滤保证) assert info is not None state = info.state if state == "pending": await message.answer("收到一条待审批的建议帖!") # 定价与拟发布时间可从 info.price / info.send_date 读取 if info.price is not None: await message.answer( f"拟定价: {info.price.amount} {info.price.currency}" ) if info.send_date is not None: await message.answer(f"拟发布时间: {info.send_date}") elif state == "approved": await message.answer("该建议帖已通过审批。") elif state == "declined": await message.answer("该建议帖已被拒绝。") # 2. 捕获建议帖被批准 / 被拒绝等"服务消息"事件 @router.message(F.suggested_post_approved) async def on_approved(message: types.Message) -> None: approved = message.suggested_post_approved if approved is not None: await message.answer(f"建议帖已获批,将于 {approved.send_date} 发布。") @router.message(F.suggested_post_declined) async def on_declined(message: types.Message) -> None: declined = message.suggested_post_declined if declined is not None and declined.comment: await message.answer(f"建议帖被拒绝,理由:{declined.comment}") # 3. 处理审批动作:批准(30 天内的任意时刻)与拒绝(附 0-128 字备注) async def approve_post(bot: Bot, chat_id: int, message_id: int) -> None: # 直接传 datetime 亦可(DateTimeUnion 支持 datetime | timedelta | int) ok: bool = await bot.approve_suggested_post( chat_id=chat_id, message_id=message_id, send_date=datetime.datetime.now() + datetime.timedelta(hours=1), ) print("approve result:", ok) async def decline_post(bot: Bot, chat_id: int, message_id: int) -> None: ok: bool = await bot.decline_suggested_post( chat_id=chat_id, message_id=message_id, comment="内容暂不符合频道定位", ) print("decline result:", ok) async def main() -> None: bot = Bot(BOT_TOKEN) dp = Dispatcher() dp.include_router(router) await dp.start_polling(bot) if __name__ == "__main__": asyncio.run(main())关于上述代码的几点说明:
F.suggested_post_info是 aiogram 的 Magic Filter(见 aiogram/filters/magic_data.py),可在事件分发前就确认suggested_post_info非空,避免手写判空分支;bot.approve_suggested_post与bot.decline_suggested_post这两个 Bot 实例方法由 aiogram 根据方法类型自动生成(对应ApproveSuggestedPost/DeclineSuggestedPost),其正确调用方式可参考仓库测试 tests/test_api/test_methods/test_approve_suggested_post.py 与 tests/test_api/test_methods/test_decline_suggested_post.py;- 别忘了审批动作的权限前提:批准需
can_post_messages,拒绝需can_manage_direct_messages管理员权限; - 建议帖功能仅适用于频道的直接消息聊天场景,发送方在
send_message等方法的suggested_post_parameters参数中传入SuggestedPostParameters(price=..., send_date=...)即可提交一条带定价的建议帖。
五、常见问题与边界约束速查
围绕SuggestedPostInfo及相关类型,以下几个边界条件在实际开发中高频出现,这里汇总成速查表:
| 约束项 | 取值/范围 | 依据 |
|---|---|---|
state合法取值 | 'pending'/'approved'/'declined' | suggested_post_info.py |
| Stars 价格范围 | 5 ~ 100000(XTR) | suggested_post_price.py |
| TON 价格范围 | 10000000 ~ 10000000000000 nanograms | suggested_post_price.py |
创建时send_date范围 | 未来 300 秒 ~ 2678400 秒(30 天) | suggested_post_parameters.py |
批准时send_date上限 | 未来 2678400 秒(30 天) | approve_suggested_post.py |
| 拒绝备注长度 | 0 ~ 128 字符 | decline_suggested_post.py |
| 批准所需权限 | can_post_messages | approve_suggested_post.py |
| 拒绝所需权限 | can_manage_direct_messages | decline_suggested_post.py |
| 已批准/已拒绝的建议帖 | 不可再编辑 | message.py |
| 回复建议帖发送新消息 | 原建议帖自动被拒绝 | send_message.py |
结语
SuggestedPostInfo是 aiogram 对 Telegram"建议帖"能力的核心数据抽象:state标记生命周期阶段,price与send_date描述商业化与时间要素,再配合SuggestedPostPrice、SuggestedPostParameters、ApproveSuggestedPost/DeclineSuggestedPost方法与Message上的六类事件字段,构成了从提交、审批、发布到支付/退款的一整条可编程闭环。无论是实现频道内容审核机器人、接入 Stars/TON 付费投稿,还是构建定时发布系统,都可以直接复用 aiogram 这套开箱即用的类型体系——上述所有字段含义、取值边界与调用方式均可在仓库源码与测试用例中逐项验证。
- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
相关推荐
aiogram 中的 SuggestedPostApprovalFailed:频道建议帖子审批失败服务消息解析与实战
aiogram 中的 SuggestedPostApprovalFailed:频道建议帖子审批失败服务消息解析与实战 导读 SuggestedPostAppro
后端即时通讯API设计aiogram SuggestedPostApproved 类型深度解析:处理 Telegram「建议帖子已批准」服务消息
aiogram SuggestedPostApproved 类型深度解析:处理 Telegram「建议帖子已批准」服务消息 SuggestedPostAppro
后端即时通讯API设计aiogram 中 approveSuggestedPost 方法详解:批准直聊频道建议帖子的三种调用方式与实现原理
aiogram 中 approveSuggestedPost 方法详解:批准直聊频道建议帖子的三种调用方式与实现原理 本文以 aiogram 官方 API 文档
后端即时通讯API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考