- 后端
【免费下载链接】instagram-private-api
NodeJS Instagram private API SDK. Written in TypeScript.
本指南以 instagram-private-api 仓库中 TypeDoc 生成的接口文档 ReelsMediaFeedResponseStoryCountdownsItem 为核心,深入解析 Instagram Story 中"倒计时贴纸"(Countdown Sticker)在 API 响应里的完整数据模型,包括 10 个贴纸布局字段与嵌套的countdown_sticker载荷结构。读完本文,你将掌握通过ReelsMediaFeed拉取并解析带倒计时贴纸的 Story、将响应字段与发布侧StickerBuilder.countdown参数一一对应,以及基于end_ts做倒计时业务判断的完整实战能力。
一、接口定位:倒计时贴纸在响应树中的位置
ReelsMediaFeedResponseStoryCountdownsItem是 instagram-private-api 中reels_media(Story 批量拉取)响应嵌套结构里的一个叶子节点接口,定义在 src/responses/reels-media.feed.response.ts:181-192。
从接口文档的命名空间归属(responses 模块)可以看出,它属于响应类型族(response interfaces),即 SDK 对 Instagram 私有 API 返回 JSON 的 TypeScript 静态类型映射。其完整数据链路如下:
ReelsMediaFeedResponseRootObject └── reels: ReelsMediaFeedResponseReels(以用户 pk 为键) └── ReelsMediaFeedResponse └── items: ReelsMediaFeedResponseItem[] └── story_countdowns?: ReelsMediaFeedResponseStoryCountdownsItem[] └── countdown_sticker: ReelsMediaFeedResponseCountdown_sticker其中story_countdowns在 ReelsMediaFeedResponseItem 中声明为可选数组(Optional story_countdowns: ReelsMediaFeedResponseStoryCountdownsItem[],对应 src/responses/reels-media.feed.response.ts:80)——只有当该条 Story 确实附加了倒计时贴纸时,此字段才会出现。
ReelsMediaFeedResponseStoryCountdownsItem与同文件中并列的ReelsMediaFeedResponseStoryPollsItem、ReelsMediaFeedResponseStoryQuestionsItem、ReelsMediaFeedResponseStoryQuizsItem、ReelsMediaFeedResponseStorySlidersItem结构完全平行,都遵循"布局字段 + 专属贴纸载荷"的模式,这也从源码层面印证了 Instagram 对各类 Story 贴纸统一建模的规律。
二、布局与状态字段详解:贴纸"画在"哪里、是否可见
ReelsMediaFeedResponseStoryCountdownsItem的 10 个属性中,前 9 个描述贴纸在 Story 画面上的布局与显示状态,类型均为number:
| 属性 | 类型 | 语义说明 |
|---|---|---|
x | number | 贴纸中心点的归一化横坐标(0 ~ 1,相对画面宽度) |
y | number | 贴纸中心点的归一化纵坐标(0 ~ 1,相对画面高度) |
z | number | 贴纸层叠次序(z-index),数值越大越靠前 |
width | number | 贴纸宽度的归一化比例(相对画面宽度) |
height | number | 贴纸高度的归一化比例(相对画面高度) |
rotation | number | 贴纸旋转角度(0 ~ 360°) |
is_pinned | number | 是否被用户"固定/置顶"在 Story 上(0 或 1) |
is_hidden | number | 是否对观众隐藏(0 或 1) |
is_sticker | number | 是否属于贴纸类型标记(通常为 1) |
countdown_sticker | ReelsMediaFeedResponseCountdown_sticker | 倒计时贴纸的实际内容载荷 |
值得注意的是:is_pinned、is_hidden、is_sticker三个字段在服务端返回中类型是number(0/1)而非boolean,这与 SDK 发布侧(见下文第四节)使用true/false的布尔表达不同,是读取响应时常见的"坑点"。
坐标与尺寸的归一化语义
这 9 个布局字段并非随机生成,而是与 InstaSticker 基类一一对应:该基类定义了width、height、rotation(默认 0.0)、x(默认 0.0)、y(默认 0.0)、z(默认 0)以及isSticker(默认true),并提供center()、rotateDeg(deg)、scale(factor)、moveForward/moveBackwards(layers)、right/left/top/bottom()等链式布局方法。
其中right()将x设为1.0 - width / 2,left()将x设为width / 2,可见 SDK 以画面宽高的归一化比例(0 ~ 1)为坐标系:x = 0.5, y = 0.5即画面正中央(center()的实现)。因此响应中的width: 0.703125、height: 0.26013514(countdown.sticker.ts 中的默认值)表示贴纸约占画面宽度 70.3%、高度 26%,在服务端渲染时按此比例换算为像素坐标。
三、countdown_sticker:倒计时贴纸的核心载荷
接口文档将countdown_sticker指向独立的嵌套接口 ReelsMediaFeedResponseCountdown_sticker,定义在 src/responses/reels-media.feed.response.ts:193-206,共 12 个字段:
| 属性 | 类型 | 语义说明 |
|---|---|---|
countdown_id | number | 倒计时贴纸的服务端唯一 ID(可用于后续业务关联) |
end_ts | number | 倒计时截止的Unix 时间戳(秒),用于计算剩余时间 |
text | string | 贴纸上显示的标题文案(如 "My Countdown") |
text_color | string | 文案颜色(十六进制,如#ffffff) |
start_background_color | string | 背景渐变起始色(十六进制) |
end_background_color | string | 背景渐变结束色(十六进制) |
digit_color | string | 倒计时数字颜色(十六进制) |
digit_card_color | string | 倒计时数字卡片背景色(十六进制,支持带 alpha 的#ffffffcc形式) |
following_enabled | boolean | 是否开启"关注提醒"(倒计时结束后推送) |
is_owner | boolean | 当前登录用户是否是该倒计时贴纸的创建者 |
attribution | null | 归因信息,服务端当前固定返回null |
viewer_is_following | boolean | 当前查看者是否已关注贴纸创建者 |
从接口文档的源码锚点(reels-media.feed.response.ts:194-205)可以看出,这些字段与发布侧参数(见第四节)一一对应,颜色字段全部要求十六进制格式。end_ts是业务上最有价值的字段:它是 Unix 秒级时间戳,可直接用end_ts * 1000得到毫秒时间戳与Date.now()对比,判断倒计时是否已经结束。
四、读写闭环:从 StickerBuilder.countdown 发布到响应回读
要真正理解响应模型,必须看懂它的"来源"——SDK 发布 Story 时如何构造这组数据。仓库提供了完整的读写闭环:
4.1 发布侧:CountdownSticker 与 StoryCountdown 类型
- CountdownSticker 是贴纸构建类,
id固定返回'countdown_sticker_time',key固定返回'story_countdowns'——key决定了它在StickerBuilder.build()中序列化后写入的配置键名(sticker-builder.ts:30-52),即story_countdowns字段。 - 其
endTssetter 支持传入DateTime(luxon)或数字:传入DateTime时执行Math.floor(value.toUTC().toSeconds())转为UTC 秒级 Unix 时间戳(countdown.sticker.ts:12-18),与响应中end_ts: number的类型与语义完全吻合。 - 默认样式值(
textColor = '#ffffff'、startBackgroundColor = '#ca2ee1'、endBackgroundColor = '#5eb1ff'、digitColor = '#7e0091'、digitCardColor = '#ffffffcc'、followingEnabled = true)在 countdown.sticker.ts:21-26 中定义。 - 底层配置类型 StoryCountdown 扩展自
StorySticker(即 x/y/width/height/rotation 布局字段),要求text、四个颜色字段、end_ts、following_enabled、is_sticker: true全部存在——这正是响应接口countdown_sticker各字段(除服务端补充的countdown_id、is_owner、viewer_is_following、attribution之外)的镜像。
4.2 PublishService 的写入路径
PublishService.story 在检测到options.countdown存在时,会执行:
if (typeof options.countdown !== 'undefined') { configureOptions.story_countdowns = [options.countdown]; storyStickerIds.push('countdown_sticker_time'); }(见 src/services/publish.service.ts:370-373),并把countdown_sticker_time追加进story_sticker_ids逗号分隔串(与 media.configure-story.options.ts:23 的类型注释story_sticker_ids = 'countdown_sticker_time'一致)。而StickerBuilder.build()会把 sticker 按key分组后JSON.stringify输出(sticker-builder.ts:42-46),最终随configureToStory请求发送。
4.3 读取侧:ReelsMediaFeed 拉取与解析
ReelsMediaFeed 通过POST /api/v1/feed/reels_media/拉取指定userIds的 Story 媒体(请求体携带_uuid、_uid、_csrftoken、device_id与supported_capabilities_new,见 reels-media.feed.ts:12-27),其items()方法将body.reels中所有用户的items扁平化返回(reels-media.feed.ts:29-35)。每条 item 若含倒计时贴纸,其story_countdowns数组的每个元素即为本文档所述的ReelsMediaFeedResponseStoryCountdownsItem。
五、实战示例:解析带倒计时贴纸的 Story
结合 examples/upload-story.example.ts 中StickerBuilder.countdown({ text, endTs })的用法,下面给出从发布到回读的完整闭环示例:
import { IgApiClient } from 'instagram-private-api'; import { DateTime, Duration } from 'luxon'; import { StickerBuilder } from 'instagram-private-api/sticker-builder'; import { readFile } from 'fs'; import { promisify } from 'util'; const readFileAsync = promisify(readFile); const ig = new IgApiClient(); // 1. 发布:附带 1 小时后截止的倒计时贴纸(与 examples/upload-story.example.ts:74-80 相同) async function publishWithCountdown() { await ig.state.generateDevice(process.env.IG_USERNAME); await ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD); const file = await readFileAsync('./myStory.jpg'); await ig.publish.story({ file, stickerConfig: new StickerBuilder() .add( StickerBuilder.countdown({ text: 'My Countdown', // @ts-ignore endTs: DateTime.local().plus(Duration.fromObject({ hours: 1 })), // 1 小时后截止 }).center(), ) .build(), }); } // 2. 回读:拉取用户 Story,解析倒计时贴纸 async function readCountdowns(userId: number | string) { const feed = ig.feed.reelsMedia({ userIds: [userId] }); const items = await feed.items(); for (const item of items) { for (const countdown of item.story_countdowns ?? []) { const remainingMs = countdown.countdown_sticker.end_ts * 1000 - Date.now(); console.log({ text: countdown.countdown_sticker.text, endAt: new Date(countdown.countdown_sticker.end_ts * 1000), remainingSec: Math.max(0, Math.floor(remainingMs / 1000)), isOwner: countdown.countdown_sticker.is_owner, viewerIsFollowing: countdown.countdown_sticker.viewer_is_following, position: { x: countdown.x, y: countdown.y, z: countdown.z }, size: { width: countdown.width, height: countdown.height }, rotation: countdown.rotation, }); } } }要点提醒:
- 响应中
is_pinned/is_hidden/is_sticker是number(0/1),如需布尔语义可自行Boolean(countdown.is_sticker); end_ts为 UTC 秒级时间戳,跨时区计算剩余时间时直接* 1000与Date.now()比较即可;story_countdowns为可选字段,读取时应做空值保护(如?./?? []),与 ReelsMediaFeedResponseItem 中Optional标注一致;attribution固定为null,无需解析逻辑。
六、类型族对比与小结
ReelsMediaFeedResponseStoryCountdownsItem与ReelsMediaFeedResponseStoryPollsItem、ReelsMediaFeedResponseStoryQuestionsItem、ReelsMediaFeedResponseStoryQuizsItem、ReelsMediaFeedResponseStorySlidersItem共享同一套"布局字段(x/y/z/width/height/rotation/is_pinned/is_hidden/is_sticker)+ 专属载荷"骨架(全部定义于 src/responses/reels-media.feed.response.ts 的 82-206 行区间),区别仅在载荷对象的字段:
- 倒计时:
countdown_sticker(end_ts+ 颜色 +following_enabled); - 投票:
poll_sticker(tallies统计 +viewer_can_vote); - 提问:
question_sticker(question+ 配色 +viewer_can_interact); - 测验:
quiz_sticker(correct_answer+tallies+viewer_can_answer); - 滑动评分:
slider_sticker(slider_vote_average+slider_vote_count)。
理解这一统一模型后,你可以用同一种遍历方式处理全部贴纸类型,并根据载荷对象的差异分别提取业务数据。若需追溯完整的响应根结构,可继续阅读 ReelsMediaFeedResponse 与 ReelsMediaFeedResponseRootObject;若需了解构建端能力,可查看 CountdownSticker 与 StickerBuilder 的完整源码。
- 后端
【免费下载链接】instagram-private-api
NodeJS Instagram private API SDK. Written in TypeScript.
相关推荐
instagram-private-api 响应模型详解:ReelsMediaFeedResponseStorySlidersItem 与 Story 滑块贴纸数据链路
instagram private api 响应模型详解:ReelsMediaFeedResponseStorySlidersItem 与 Story 滑块贴纸
后端instagram-private-api 响应类型详解:MediaUpdatedMediaResponsePoll_sticker 与 Story 投票贴纸数据结构
instagram private api 响应类型详解:MediaUpdatedMediaResponsePoll_sticker 与 Story 投票贴纸数
后端instagram-private-api 响应类型详解:MediaUpdatedMediaResponseStoryPollsItem 与 Story 投票贴纸数据结构
instagram private api 响应类型详解:MediaUpdatedMediaResponseStoryPollsItem 与 Story 投票贴
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考