instagram-private-api 响应解析:HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem 接口实战指南
instagram-private-api 响应解析:HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem 接口实战指南
本文聚焦 instagram-private-api(NodeJS Instagram private API SDK,TypeScript 编写)中用于承载「Story 测验(Quiz)参与详情」的响应接口
HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem。该接口定义在 editReel 响应模型 内,是解析edit_reel(编辑快拍精选集)接口返回的参与者名单、分页游标与答题记录的核心结构。读完本文你将掌握:该接口四个字段的精确含义与类型约束、参与者的数据结构、它与story_quiz_participantsFeed 的对应关系,以及如何在实际业务代码中读取并分页遍历测验参与者数据。
一、接口定位:隐藏在 edit_reel 响应中的测验参与者信息
HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem 属于响应(response)模型层,完整定义位于 src/responses/highlights.repository.edit-reel.response.ts,其 TypeScript 定义如下:
export interface HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem {
quiz_id: string;
participants: HighlightsRepositoryEditReelResponseParticipantsItem[];
max_id: null;
more_available: boolean;
}
它在整个响应树中的位置可以通过源码推断出来:编辑精选集(highlight reel)的响应根对象 HighlightsRepositoryEditReelResponseRootObject 包含 reel 与 status 两个字段(见 RootObject 文档);reel.items 数组中的每个元素(HighlightsRepositoryEditReelResponseItemsItem)在包含测验贴纸(quiz sticker)的 Story 媒体上会携带两个可选字段(见 ItemsItem 文档):
story_quizs?: HighlightsRepositoryEditReelResponseStoryQuizsItem[]—— 记录测验贴纸的布局坐标与题目元数据;story_quiz_participant_infos?: HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem[]—— 即本文主角,记录该测验的参与者分页信息。
由于两个字段在源码中均为 Optional(可选),只有该 Story 真实包含测验贴纸时,服务端才会返回 story_quiz_participant_infos,读取前应做空值防御。
二、字段详解:quiz_id、participants、max_id、more_available
该接口仅含四个属性,对应源码 highlights.repository.edit-reel.response.ts:153-156:
| 属性 | 类型 | 源码行号 | 含义与使用建议 |
|---|---|---|---|
quiz_id |
string |
L153 | 该测验贴纸的唯一 ID。与 story_quizs 中 quiz_sticker.quiz_id 对应,可用于后续调用 storyQuizAnswer、查询 story_quiz_participants Feed 时的 stickerId 参数。 |
participants |
HighlightsRepositoryEditReelResponseParticipantsItem[] |
L154 | 当前页的参与者数组(结构见下文第三节)。 |
max_id |
null |
L155 | 分页游标。该类型在此处被固定声明为 null,说明 edit_reel 响应中默认不带下一页游标;而独立的参与者 Feed 会将游标写入同名字段,用于翻页。 |
more_available |
boolean |
L156 | 是否还有更多参与者可加载。在 edit_reel 场景下通常与 max_id: null 搭配出现;在 Feed 场景中作为分页终止条件,见 media.sticker-responses.feed.ts 的 moreAvailable 赋值逻辑。 |
读取示例(从 editReel 返回中取出测验参与者):
import { IgApiClient } from 'instagram-private-api';
const ig = new IgApiClient();
// ... 登录与状态恢复逻辑
const result = await ig.highlights.editReel({
highlightId: '17842114900000000',
title: '我的精选集',
coverId: 'mediaId_xxx',
added: ['mediaId_xxx'],
removed: [],
});
for (const item of result.reel.items) {
const infos = item.story_quiz_participant_infos;
if (!infos) continue; // 该 Story 没有测验贴纸,跳过
for (const info of infos) {
console.log(`quiz=${info.quiz_id}, more=${info.more_available}`);
for (const p of info.participants) {
console.log(` ${p.user.username} 选择 #${p.answer},时间戳=${p.ts}`);
}
}
}
editReel 方法的完整签名可查看 HighlightsRepository.editReel,其底层请求为 POST /api/v1/highlights/{highlightId}/edit_reel/,表单参数经 client.request.sign() 签名后提交(包含 _csrftoken、_uid、_uuid、added_media_ids、removed_media_ids、cover、title 等);入参类型见 EditHighlightsReelOptions。
三、参与者子结构:ParticipantsItem 与 User
participants 数组的元素类型 HighlightsRepositoryEditReelResponseParticipantsItem 定义在 highlights.repository.edit-reel.response.ts:158-162,其文档见 ParticipantsItem 接口文档:
export interface HighlightsRepositoryEditReelResponseParticipantsItem {
user: HighlightsRepositoryEditReelResponseUser;
answer: number; // 参与者选择的选项索引(0 起)
ts: number; // 参与/作答的 Unix 时间戳
}
| 属性 | 类型 | 含义 |
|---|---|---|
user |
HighlightsRepositoryEditReelResponseUser |
参与者账号信息,包含 pk(用户数字 ID)、username、full_name、is_private、profile_pic_url、profile_pic_id、is_verified 等字段(见 User 接口定义)。 |
answer |
number |
参与者勾选的选项索引。correct_answer 由 quiz_sticker 给出(见下文),将两者比对即可判断答对与否。 |
ts |
number |
作答时间戳(Unix 秒),可用于统计参与时段或排序。 |
题目与选项的元数据存在于同一条媒体(item)的 story_quizs 字段中:每个 HighlightsRepositoryEditReelResponseStoryQuizsItem 承载贴纸坐标(x/y/z、width、height、rotation、is_pinned、is_hidden、is_sticker),并通过 quiz_sticker 指向题目详情 HighlightsRepositoryEditReelResponseQuiz_sticker(见 Quiz_sticker 文档),其中:
id/quiz_id:贴纸实例 ID 与测验 ID;question:题目文本;tallies:各选项的统计(text+count,见 TalliesItem 文档);correct_answer:正确答案的选项索引;viewer_can_answer/finished:当前查看者是否可作答、测验是否已结束;text_color、start_background_color、end_background_color:贴纸配色。
由此可以完整重建「题目 → 选项 → 每位参与者选择」的映射关系。
四、与 story_quiz_participants Feed 的对应关系与分页
值得强调的是,edit_reel 响应中的该接口与独立的分页 Feed story_quiz_participants 共享几乎一致的字段骨架,可以相互印证。
在 src/responses/story-quiz-participants.feed.response.ts 中,StoryQuizParticipantsFeedResponseParticipant_info 同样包含 quiz_id: string、participants、max_id: null、more_available: boolean 四个字段,且参与者结构 StoryQuizParticipantsFeedResponseParticipantsItem 也是 user + answer + ts 三元组——与 HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem 形成对应。
获取该 Feed 的入口在 FeedFactory.storyQuizParticipants:
public storyQuizParticipants(
mediaId: string,
stickerId: string | number,
): MediaStickerResponsesFeed<
StoryQuizParticipantsFeedResponseRootObject,
StoryQuizParticipantsFeedResponseParticipantsItem
> {
return plainToClassFromExist(new MediaStickerResponsesFeed<any, any>(this.client), {
mediaId,
stickerId,
name: 'story_quiz_participants',
rootName: 'participant_info',
itemName: 'participants',
});
}
底层请求由 MediaStickerResponsesFeed.request 发出,地址为 GET /api/v1/media/{mediaId}/{stickerId}/story_quiz_participants/,并携带 max_id 查询参数;状态回写逻辑见 同文件 L31-L34:用响应的 max_id 更新内部游标、用 more_available 更新 moreAvailable,从而驱动标准 Feed 的迭代翻页。实际使用时:
const feed = ig.feed.storyQuizParticipants(mediaId, quizId);
const participants = await feed.items(); // 第一页
while (feed.isMoreAvailable()) {
await feed.request();
const more = await feed.items();
// 处理后续页的参与者
}
五、完整链路:从创建测验贴纸到读取答题者
将上述结构串联起来,可以梳理出 instagram-private-api 中围绕「Story 测验」的完整调用链:
- 创建测验贴纸:使用 StickerBuilder.quiz 与 QuizSticker,可设置
question、options(字符串数组会被自动转换为{ text, count: 0 }结构)、correctAnswer、viewerCanAnswer等属性,并作为story_quizs键写入 Story 配置(QuizSticker.key返回'story_quizs',id返回'quiz_story_sticker_default'); - 发布 Story:通过
PublishService/StoryService上传带测验贴纸的 Story 媒体; - 参与者作答:若需要以账户视角模拟作答,可调用 MediaRepository.storyQuizAnswer,向
POST /api/v1/media/{mediaId}/{quizId}/story_quiz_answer/提交选项索引(answer支持'0'/'1'/'2'/'3'); - 读取参与者:通过
editReel响应中的story_quiz_participant_infos(即本文接口)或ig.feed.storyQuizParticipants(mediaId, quizId)获取参与者名单,并将answer与quiz_sticker.correct_answer比对,即可统计答对/答错分布。
其中第 4 步返回结构中的 max_id 类型被严格声明为 null,意味着该结构在“内嵌于编辑响应”的场景下不具备直接翻页能力;如需遍历全部答题者,应优先使用第 4 步的独立 Feed 路径。
六、使用注意事项
- 空值防御:
story_quizs与story_quiz_participant_infos均为可选字段(源码中带?标记),解析时务必先判断存在性,避免undefined访问错误。 - 类型精度:
max_id被固定为null字面量类型而非string | null,这是服务端在该场景下的真实返回形态;迁移到 Feed 场景时,游标字段才具有实际翻页意义。 - 索引语义:
answer与correct_answer均为从 0 开始的选项索引,与tallies数组顺序一一对应;跨接口比对时请保持一致。 - 隐私边界:仅当账户具备查看该精选集/Story 的权限时,接口才会返回完整参与者数据;私有账户与限流场景可能返回空数组或触发相应异常(如 IgPrivateUserError、IgActionSpamError)。
七、参考文件索引
- 本接口文档:HighlightsRepositoryEditReelResponseStoryQuizParticipantInfosItem.md
- 源码定义:src/responses/highlights.repository.edit-reel.response.ts
- 编辑精选集仓库:src/repositories/highlights.repository.ts
- 参与者 Feed 响应模型:src/responses/story-quiz-participants.feed.response.ts
- Feed 工厂与分页实现:src/core/feed.factory.ts、src/feeds/media.sticker-responses.feed.ts
- 测验作答与贴纸构建:src/repositories/media.repository.ts、src/sticker-builder/stickers/quiz.sticker.ts、src/sticker-builder/sticker-builder.ts
- 响应模块索引:docs/modules/responses.md