- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
本篇基于 aiogram 官方 API 参考文档 Story,以aiogram.types.story.Story类型为核心,完整讲解其字段定义、源码实现机制,以及与post_story/edit_story/delete_story/repost_story四个方法之间的调用关系。读完后你将能够在 aiogram 3.x 中正确处理Story对象的序列化与反序列化,并为受管业务账号(managed business account)编写带富文本、可点击区域的完整故事发布代码。
Story 类型:官方文档中的核心定义
docs/api/types/story.rst通过 Sphinx 的automodule指令自动生成 aiogram.types.story 模块的 API 页面(:member-order: bysource、:undoc-members: True,并排除model_config、model_fields两个 Pydantic 内部成员)。其渲染出的核心内容即Story类的定义:
This object represents a story.(该对象表示一条故事)
在 aiogram/types/story.py 中,Story仅有两个字段的声明式定义:
class Story(TelegramObject): """ This object represents a story. """ chat: Chat """Chat that posted the story""" # 发布该故事的聊天(通常是对应业务账号的账号 ID) id: int """Unique identifier for the story in the chat""" # 该故事在所属聊天内的唯一标识两个字段都是必填项:
| 字段 | 类型 | 说明 |
|---|---|---|
chat | Chat | 发布该故事的聊天对象,从源码结构看它携带完整聊天信息(ID、类型、标题等),可进一步用于调用repost_story的from_chat_id参数 |
id | int | 故事在其所属聊天范围内的唯一 ID,是edit_story与delete_story定位目标故事的关键 |
值得注意的源码细节:TYPE_CHECKING块内由butcher工具自动生成了一个__init__方法(标注 “DO NOT EDIT MANUALLY!!!”),它仅存在于类型检查阶段,用于在没有额外 Pydantic 插件的 IDE 中提供参数补全和类型提示;运行时并不依赖它,实例化仍走 Pydantic 的标准流程。
底层机制:Story 继承自 TelegramObject
Story继承的 TelegramObject 是整个aiogram.types命名空间的基类,其model_config决定了包括Story在内的所有 Telegram 对象的行为特征:
frozen=True:对象不可变,Story实例创建后不能重新赋值字段;extra="allow":允许未知字段透传,保证 Telegram Bot API 新增字段时旧版本客户端不会反序列化失败;use_enum_values=True:枚举字段以字符串值存储;validate_assignment=True:(配合MutableTelegramObject的frozen=False使用)赋值时校验;populate_by_name=True:同时支持字段名与别名填充。
此外基类还定义了一个mode="before"的模型校验器remove_unset,会在字段校验前剔除UNSET哨兵值——这是parse_mode/protect_content等使用Default哨兵机制的方法参数在构造请求体时的必要处理。理解这一层机制,就能明白为什么Story等响应类型既严格(必填字段缺失会报错)又宽容(未知字段不会丢失)。
所有 Story 相关类型均已在 aiogram/types/init.py 与 aiogram/types/init.py 中统一导出,可直接from aiogram.types import Story, StoryArea, InputStoryContentPhoto使用。
谁产生 Story:四个业务账号故事管理方法
Story不是通过 Update 推送进来的被动对象——在 aiogram 的 Bot 客户端 中,它由四个can_manage_stories权限下的业务账号方法作为返回值产生:
| 方法 | 源文件 | 返回值 | 用途 |
|---|---|---|---|
post_story | post_story.py | Story | 以受管业务账号名义发布新故事 |
edit_story | edit_story.py | Story | 编辑已发布的故事内容、文案与可点击区域 |
repost_story | repost_story.py | Story | 将同一机器人管理的另一个业务账号的故事转载至当前业务账号 |
delete_story | delete_story.py | bool | 删除机器人此前发布的某个故事 |
四个方法都以business_connection_id(业务连接唯一标识)定位操作对象;post_story的完整参数列表(见 aiogram/client/bot.py 中的方法签名)如下:
async def post_story( self, business_connection_id: str, content: InputStoryContentUnion, # 故事内容:InputStoryContentPhoto 或 InputStoryContentVideo active_period: int, # 归档时长(秒):必须为 6*3600、12*3600、86400 或 2*86400 caption: str | None = None, # 说明文字,实体解析后 0-2048 字符 parse_mode: str | Default | None = ..., # 富文本解析模式 caption_entities: list[MessageEntity] | None = None, # 与 parse_mode 二选一的实体列表 areas: list[StoryArea] | None = None, # 可点击区域列表 post_to_chat_page: bool | None = None, # True 时故事过期后仍保留可访问 protect_content: bool | Default | None = ..., # 保护内容不被转发与截屏 request_timeout: int | None = None, ) -> Story:其中active_period是被 Telegram 侧强约束的枚举式取值:只能取 6 小时、12 小时、1 天或 2 天四个值之一。edit_story相比post_story去掉了active_period/post_to_chat_page/protect_content(这些属性在创建时确定),增加了story_id用于定位目标故事;repost_story则通过from_chat_id+from_story_id指明源账号与源故事,且要求两个业务账号同属一个机器人管理、源故事必须是该机器人发布(或转载)的。
故事内容类型:InputStoryContent 联合类型
content参数的静态类型是 InputStoryContentUnion,它是带Field(discriminator="type")判别字段的 Pydantic 联合类型,由两种具体类型组成:
- InputStoryContentPhoto:
type固定为"photo",photo为图片文件标识。文档明确图片必须为1080x1920且不超过10 MB,且图片不可复用、只能作为新文件上传——因此通过multipart/form-data上传时应使用attach://<file_attach_name>引用; - InputStoryContentVideo:
type固定为"video",视频要求720x1280、H.265 编码、MPEG4 容器、每秒一个关键帧、不超过30 MB;可选参数包括duration(0-60 秒)、cover_frame_timestamp(静态封面帧时间戳,默认 0.0)与is_animation(无声音频时传True)。
判别联合的意义在于:无论是从 Bot 请求体序列化,还是(在类型层面)从响应反序列化,Pydantic 都能依据type字段自动选中正确的子类,无需手写类型分派逻辑。
可点击区域:StoryArea 及其五种类型
post_story/edit_story的areas参数接收 StoryArea 列表,描述故事媒体上的可点击区域。StoryArea由两个字段组成:position: StoryAreaPosition与type: StoryAreaTypeUnion。
StoryAreaPosition 全部使用百分比/角度制描述矩形区域,共六个必填浮点字段:
| 字段 | 含义 |
|---|---|
x_percentage/y_percentage | 区域中心点的横/纵坐标,分别为媒体宽度/高度的百分比 |
width_percentage/height_percentage | 区域矩形的宽/高,分别为媒体宽度/高度的百分比 |
rotation_angle | 矩形顺时针旋转角度(度),取值 0-360 |
corner_radius_percentage | 矩形圆角半径,为媒体宽度的百分比 |
type的静态类型 StoryAreaTypeUnion 同样是discriminator="type"判别联合,对应 StoryAreaTypeType 枚举的五个取值:
| 类型 | 类 | 附加字段 | 单条故事的数量上限 |
|---|---|---|---|
link | StoryAreaTypeLink | url(HTTP 或tg://链接) | 3 个 |
location | StoryAreaTypeLocation | latitude、longitude、可选address | 10 个 |
suggested_reaction | StoryAreaTypeSuggestedReaction | reaction_type、可选is_dark/is_flipped | 5 个 |
weather | StoryAreaTypeWeather | temperature(摄氏度)、emoji、background_color(ARGB 颜色值) | 3 个 |
unique_gift | StoryAreaTypeUniqueGift | name(礼品唯一名称) | 1 个 |
每个具体类型的type字段都被声明为Literal[StoryAreaTypeType.XXX]并带有枚举默认值,序列化时天然输出正确的判别字符串。
实战示例:构造带可点击区域的照片故事
综合以上类型与参数约束,一次典型的post_story调用如下(示例遵循测试用例 test_post_story.py 的写法风格):
from aiogram import Bot from aiogram.types import ( InputStoryContentPhoto, StoryArea, StoryAreaPosition, StoryAreaTypeLink, ) bot = Bot(token="...") story = await bot.post_story( business_connection_id="AgACAgIAA...", # 来自 get_business_connection 的连接 ID content=InputStoryContentPhoto( photo="attach://story_photo", # 通过 multipart 上传的文件引用 ), active_period=6 * 3600, # 6 小时后归档 caption="**新品上架** 🎉 点击查看活动详情", parse_mode="HTML", areas=[ StoryArea( position=StoryAreaPosition( x_percentage=50.0, y_percentage=80.0, width_percentage=60.0, height_percentage=15.0, rotation_angle=0.0, corner_radius_percentage=5.0, ), type=StoryAreaTypeLink(url="https://example.com/promo"), ) ], ) # story: Story,story.chat 为发布聊天,story.id 可用于后续 edit_story / delete_story / repost_story调用成功后,返回值即本文开头介绍的Story对象:用story.chat.id可作为repost_story的from_chat_id,用story.id作为edit_story/delete_story的story_id,构成“发布 → 编辑 → 跨账号转载 → 删除”的完整生命周期闭环。
测试验证与参考路径
仓库使用MockedBot对四个方法做了单元测试,验证了请求构造与结果类型的对应关系(如 test_repost_story.py 断言repost_story返回与预设一致的Story实例,test_delete_story.py 断言返回True)。如需继续深入,可参考以下仓库路径:
- 类型定义:aiogram/types/story.py、aiogram/types/story_area.py、aiogram/types/input_story_content_photo.py、aiogram/types/input_story_content_video.py
- 方法实现:aiogram/methods/post_story.py、aiogram/methods/edit_story.py、aiogram/methods/repost_story.py、aiogram/methods/delete_story.py
- 客户端入口:aiogram/client/bot.py
- 枚举与联合类型:aiogram/enums/story_area_type_type.py、aiogram/types/story_area_type_union.py
- 官方 API 文档页:docs/api/types/story.rst、docs/api/methods/post_story.rst
需要提醒的适用前提:上述故事管理能力要求机器人与业务账号建立business_connection并具备can_manage_stories权限,且各媒体格式(1080x1920 照片、720x1280 H.265 视频)、大小上限与区域数量上限均由 Telegram Bot API 规定;若账号未开通相应业务权限,对应方法调用将收到错误响应。
- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
相关推荐
aiogram 中 postStory 方法详解:用管理型企业账户发布 Telegram 故事
aiogram 中 postStory 方法详解:用管理型企业账户发布 Telegram 故事 postStory 是 aiogram 提供的 Telegram
后端即时通讯API设计aiogram 中 EditStory 方法详解:编辑已发布商业账号 Story 的完整实战指南
aiogram 中 EditStory 方法详解:编辑已发布商业账号 Story 的完整实战指南 导读 editStory 是 Telegram Bot API
后端即时通讯API设计aiogram deleteStory 方法详解:删除企业账号 Story 的三种调用方式与底层实现
aiogram deleteStory 方法详解:删除企业账号 Story 的三种调用方式与底层实现 deleteStory 是 Telegram Bot AP
后端即时通讯API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考