后端【免费下载链接】instagram-private-apiNodeJS Instagram private API SDK. Written in TypeScript.项目地址https://gitcode.com/gh_mirrors/in/instagram-private-api点击查看免费下载本篇技术指南以 instagram-private-apiNodeJS 编写的 TypeScript Instagram 私有 API SDK中的DirectThreadEntity类为讲解主线系统覆盖该实体在私信Direct Message场景下的完整能力如何获取线程实例、发送文本/链接/图片/视频/语音/故事/帖子/个人主页等各类消息以及线程的改名、静音、隐藏、退出、加人与已读标记等管理操作。读完本文你将掌握基于该 SDK 封装 Instagram DM 收发与线程治理的一整套可落地实战方案。DirectThreadEntity 在 SDK 中的定位与类层次DirectThreadEntity是 entities 模块下对一条 Instagram 私信线程的对象化封装。它继承自抽象基类 Entity而Entity又继承自Repositorysrc/core/entity.ts。这条继承链意味着每个实体实例天然持有IgApiClient客户端引用Repository构造函数注入见 src/core/repository.ts因此实体上的每个方法都能直接发起私信相关的 API 请求使用者无需再手动组装客户端调用。类定义位于 src/entities/direct-thread.entity.ts完整 API 文档见 DirectThreadEntity 文档。类层级关系可表示为Repository (持有 IgApiClient) └── Entity └── DirectThreadEntity ├── 属性: threadId, userIds └── 方法: 消息广播 / 线程管理 两大类SDK 中与DirectThreadEntity同级的实体还有MediaEntity、ProfileEntity、LiveEntity见 src/entities/index.ts它们共同构成实体层的对象模型。两个核心属性属性类型默认值含义threadIdstringnull目标线程的 ID表示往某条已存在的线程里发消息userIdsstring[]null目标用户 ID 数组表示与这些用户开一条新线程并发送这两个属性在 src/entities/direct-thread.entity.ts#L16-L17 中定义二者互斥生效发送消息时若threadId非空则按线程发送否则按userIds创建新线程发送。关于二者的最终判定逻辑见下文私有 broadcast 统一入口一节。获取 DirectThreadEntity 的三种途径途径一从收件箱 Feed 的 records() 批量获取DirectInboxFeed与DirectPendingInboxFeed均提供了records()方法把每一页响应里的thread_id自动映射为DirectThreadEntity数组// 获取收件箱第一页线程 const [thread] await ig.feed.directInbox().records(); // 获取待处理请求陌生人消息列表 const pendingThreads await ig.feed.directPending().records();对应实现见 src/feeds/direct-inbox.feed.ts 与 src/feeds/direct-pending.feed.ts两处均为async records(): PromiseDirectThreadEntity[] { const threads await this.items(); return threads.map(thread this.client.entity.directThread(thread.thread_id)); }途径二通过 EntityFactory 直接构造ig.entity.directThread(id)是工厂方法签名位于 src/core/entity.factory.tspublic directThread(id: string | string[]): DirectThreadEntity { const thread new DirectThreadEntity(this.client); if (id instanceof Array) { thread.userIds id; // 传入数组 → 目标用户列表用于新建线程 } else { thread.threadId id; // 传入字符串 → 目标线程 ID用于已有线程 } return thread; }这一设计是本实体最灵活的用法同一个工厂方法传入单个thread_id即对已有线程操作传入用户 ID 数组即与新用户开启私信。途径三从线程 Feed 的分页数据中组合在遍历线程历史消息时ig.feed.directThread({ thread_id, oldest_cursor }, seqId)会构造一个DirectThreadFeedsrc/core/feed.factory.ts其内部请求/api/v1/direct_v2/threads/{id}/分页拉取thread.itemssrc/feeds/direct-thread.feed.ts。该 Feed 负责读取DirectThreadEntity负责写入/管理两者配合即可完成读历史 发新消息的完整闭环。消息广播能力全景18 个方法逐一拆解DirectThreadEntity的消息发送统一收敛到私有方法broadcast()src/entities/direct-thread.entity.ts#L247-L274其核心逻辑是若threadId与userIds均为null抛出Error(DirectThread: No recipients set)组装item / form / qs / signed基础参数有threadId则附加threadIds否则附加userIds调用this.client.directThread.broadcast(params)根据响应回填实体状态若响应含payload则threadId payload.thread_id并清空userIds若响应含message_metadata则取第一条的thread_id回填。这意味着第一次按用户列表发送后实体会被自动升级为已知线程后续再调用同一实例即可直接复用threadId。底层实际请求由DirectThreadRepository.broadcast()完成src/repositories/direct-thread.repository.ts#L204-L230它会自动生成mutationTokenChance().guid()、client_context、device_id、_csrftoken、_uuid等表单字段并可选地对表单签名options.signed时调用this.client.request.sign(form)最终 POST 到/api/v1/direct_v2/threads/broadcast/{item}/。全部广播方法的返回类型均为DirectThreadRepositoryBroadcastResponseRootObject或DirectThreadRepositoryBroadcastResponsePayload结构见 src/responses/direct-thread.repository.broadcast.response.ts含action、status_code、payload、message_metadata、status等字段。文本与链接类broadcastText(text, skipLinkCheck?)发送纯文本消息src/entities/direct-thread.entity.ts#L33-L46。若文本包含 URLSDK 会借助url-regex-safe正则库识别链接并自动转为broadcastLink发送让链接在 App 中以下拉卡片形式展示await thread.broadcastText(Hello from instagram-private-api!); await thread.broadcastText(https://example.com/some/page); // 自动识别为链接消息 await thread.broadcastText(http://example.com, true); // skipLinkChecktrue强制按纯文本发送参数说明参数类型说明textstring要发送的文本内容skipLinkCheck?boolean省略时自动检测链接传true跳过检测。该开关是为了仅在必要时引入url-regex-safe依赖该库在某些环境下可能引发问题见 SDK issue #1328broadcastLink(link_text, link_urls)显式发送链接消息src/entities/direct-thread.entity.ts#L95-L103link_urls会被JSON.stringify后写入表单await thread.broadcastLink(点击查看, [https://example.com/a, https://example.com/b]);broadcastProfile(id)发送用户主页卡片id接受string | numbersrc/entities/direct-thread.entity.ts#L86-L93对应item: profileawait thread.broadcastProfile(1234567890);媒体上传类broadcastPhoto(options)发送图片消息src/entities/direct-thread.entity.ts#L105-L117。流程为先调用ig.upload.photo()上传拿到upload_id再广播configure_photoawait thread.broadcastPhoto({ file: await readFileAsync(photo.jpg), // Buffer 图片数据 allowFullAspectRatio: true, // 可选默认 true // uploadId: 自定义上传ID, // 可选 });选项类型DirectThreadBroadcastPhotoOptions定义见 src/types/direct-thread.broadcast-media.options.ts 与 接口文档字段类型必填说明fileBuffer是图片二进制数据allowFullAspectRatioboolean否是否允许全宽高比展示默认trueuploadIdstring否自定义上传 ID省略时由上传仓库生成broadcastVideo(options)发送视频消息src/entities/direct-thread.entity.ts#L131-L157。完整链路涉及视频元信息解析时长/宽高由PublishService.getVideoInfo从 MP4 容器中读取见 src/services/publish.service.ts、upload.video()直传、media.uploadFinish()收尾以及对202 Accepted转码中错误的重试等待await thread.broadcastVideo({ video: await readFileAsync(video.mp4), transcodeDelay: 5 * 1000, // 遇到 202 转码错误时的等待毫秒数默认 4000 });选项类型DirectThreadBroadcastVideoOptionssrc/types/direct-thread.broadcast-media.options.ts#L7-L12接口文档字段类型必填说明videoBuffer是视频二进制数据uploadIdstring否自定义上传 ID省略时使用Date.now().toString()sampledboolean否采样标志省略时默认truetranscodeDelaynumber否202 转码等待毫秒数默认4 * 1000转码重试逻辑由PublishService.catchTranscodeError提供src/services/publish.service.ts#L42-L53收到 202 状态码则Bluebird.delay等待指定毫秒数后重试否则抛出IgUploadVideoError。broadcastVoice(options)发送语音消息src/entities/direct-thread.entity.ts#L159-L188对应item: share_voice。上传使用mediaType: 11与isDirectVoice: true标记并附带波形数据。若未提供waveformSDK 会自动生成一条平滑正弦波形await thread.broadcastVoice({ file: await readFileAsync(voice.m4a), waveformSamplingFrequencyHz: 10, // 可选采样频率默认 10 // waveform: [0.1, 0.3, 0.5, ...], // 可选自定义波形数组 });选项类型DirectThreadBroadcastVoiceOptionssrc/types/direct-thread.broadcast-media.options.ts#L31-L37file必填、waveform?、waveformSamplingFrequencyHz?、uploadId?、transcodeDelay?。broadcastPost(mediaId)转发一条已发布的帖子到线程src/entities/direct-thread.entity.ts#L119-L129对应item: media_share并附带carousel_share_child_media_id、send_attribution: feed_contextual_profile、unified_broadcast_format: 1等表单字段await thread.broadcastPost(2830000000000000000);Story 分享类broadcastReel(options)用于向上滑动回复某条 Story 的发布者即 swipe-up 回复对应item: reel_sharesrc/entities/direct-thread.entity.ts#L52-L65await thread.broadcastReel({ mediaId: 2830000000000000000_1234567890, // reelId: 2830000000000000000, // 可选省略时从 mediaId 的 _ 后半段推导 text: 这段内容很棒, mediaType: photo, // 可选photo | video默认 photo });broadcastUserStory(options)模拟 App 中分享按钮把某条 Story 分享到线程对应item: story_share且会走签名表单signed: truesrc/entities/direct-thread.entity.ts#L71-L84await thread.broadcastUserStory({ mediaId: 2830000000000000000_1234567890, text: 看看这个, });两者共享选项类型DirectThreadBroadcastReelOptionssrc/types/direct-thread.broadcast-reel.options.ts字段类型必填说明mediaIdstring是被分享媒体的 IDreelId?string否Story 所属 Reel ID省略时取mediaId.split(_)[1]text?string否附带文本mediaType?photo \| video否媒体类型默认photobroadcastStory(input)直接向线程发布一条 Storysrc/entities/direct-thread.entity.ts#L195-L217。这是唯一一个不经过broadcast()私有入口的方法它复用ig.publish.story()src/services/publish.service.ts能力通过threadIds: [this.threadId]或recipientUsers: this.userIds指定私信接收人。Story 支持一次性查看once阅后即焚或可回放replayable两种模式。入参可以是Buffer等价于{ file: input }也可以是照片/视频 Story 选项对象// 发送一次性照片 Story await thread.broadcastStory({ file: await readFileAsync(story-photo.jpg), viewMode: once, }); // 发送可回放视频 Story需提供封面图 await thread.broadcastStory({ video: await readFileAsync(story-video.mp4), coverImage: await readFileAsync(cover.jpg), viewMode: replayable, });相关选项类型src/types/direct-thread.broadcast-media.options.ts#L14-L29DirectThreadBroadcastStoryOptionsviewMode?replayable | once默认replayable、replyType?story、uploadId?DirectThreadBroadcastPhotoStoryOptionsfile: Buffer图片数据DirectThreadBroadcastVideoStoryOptionsvideo: BuffercoverImage: Buffer。需要特别说明的限制当 Story 的目标是私信线程即携带threadIds/recipientUsers时PublishService会将configure_mode置为2并显式跳过 sticker 相关处理——私信 Story 不支持贴纸见 src/services/publish.service.ts#L302-L315 的注释 check for directThread no stickers supported。线程管理类方法以下方法均返回StatusResponse仅含status: string字段见 src/responses/status.response.ts底层请求由 DirectThreadRepository 承担方法签名底层端点说明deleteItem(itemId: string \| number)POST /api/v1/direct_v2/threads/{id}/items/{itemId}/delete/删除线程中的某条消息。若threadId为 null 会抛出IgClientError(threadId was null.)updateTitle(title: string)POST /api/v1/direct_v2/threads/{id}/update_title/修改群聊标题返回DirectThreadRepositoryUpdateTitleResponseRootObjectmute()POST /api/v1/direct_v2/threads/{id}/mute/静音线程unmute()POST /api/v1/direct_v2/threads/{id}/unmute/取消静音hide()POST /api/v1/direct_v2/threads/{id}/hide/携带use_unified_inbox: true隐藏线程收件箱中移除leave()POST /api/v1/direct_v2/threads/{id}/leave/退出线程addUser(userIds: string[] \| number[])POST /api/v1/direct_v2/threads/{id}/add_user/向群聊添加成员返回DirectThreadRepositoryAddUserResponseRootObjectmarkItemSeen(threadItemId: string)POST /api/v1/direct_v2/threads/{id}/items/{itemId}/seen/将某条消息标记为已读action: mark_seen典型调用await thread.updateTitle(新的群名); await thread.mute(); await thread.markItemSeen(2830000000000000000000000); await thread.addUser([9876543210]); await thread.deleteItem(2830000000000000000000000);完整可运行示例从登录到发送四种媒体仓库中的官方示例 examples/dm-thrad.broadast-media.example.ts 展示了从登录、取线程到发送图片/视频/照片 Story/视频 Story 的完整链路将其整理为可直接运行的骨架import { DirectThreadEntity, IgApiClient } from instagram-private-api; import { promisify } from util; import { readFile } from fs; const readFileAsync promisify(readFile); const ig new IgApiClient(); async function login() { ig.state.generateDevice(process.env.IG_USERNAME); // 必须按用户名生成设备指纹 ig.state.proxyUrl process.env.IG_PROXY; // 可选代理 await ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD); } (async () { await login(); // 从收件箱取第一条线程实体 const [thread] await ig.feed.directInbox().records(); await thread.broadcastPhoto({ file: await readFileAsync(photo.jpg) }); await thread.broadcastVideo({ video: await readFileAsync(video.mp4), transcodeDelay: 5 * 1000 }); await thread.broadcastStory({ file: await readFileAsync(photo.jpg), viewMode: once }); await thread.broadcastStory({ video: await readFileAsync(video.mp4), coverImage: await readFileAsync(cover.jpg), viewMode: replayable, }); })();要点提示登录前必须调用ig.state.generateDevice(username)否则账号登录会被 Instagram 风控拦截broadcastVideo遇到202 Accepted转码中时SDK 默认等待 4 秒后由PublishService.catchTranscodeError处理重试可通过transcodeDelay调整broadcastStory的viewMode决定收件人是否可以回看once为阅后即焚replayable为可回放。新会话发送与自动升级机制当你手中只有用户 ID 而没有现成线程时可以用数组形式构造实体并直接发送SDK 会自动创建线程并回填线程 ID// 用用户 ID 数组新建线程实体 const fresh ig.entity.directThread([1234567890, 9876543210]); // 第一次发送会创建线程userIds 模式 await fresh.broadcastText(Hi!); // 发送成功后fresh.threadId 已被服务端返回的 thread_id 回填 // 后续再调用 fresh.broadcastPhoto(...) 时将直接走已有线程模式这一自动升级机制由私有broadcast()实现src/entities/direct-thread.entity.ts#L263-L273响应含payload时取payload.thread_id否则从message_metadata[0].thread_id取无论哪种情况都会把userIds置为null。返回类型的具体字段见 DirectThreadRepositoryBroadcastResponseRootObject。参数模型速查四类广播选项接口所有广播选项均可在 docs/interfaces/types 目录下找到对应文档页汇总如下接口必填字段可选字段对应方法DirectThreadBroadcastPhotoOptionsfileallowFullAspectRatio、uploadIdbroadcastPhotoDirectThreadBroadcastVideoOptionsvideouploadId、sampled、transcodeDelaybroadcastVideoDirectThreadBroadcastVoiceOptionsfilewaveform、waveformSamplingFrequencyHz、uploadId、transcodeDelaybroadcastVoiceDirectThreadBroadcastReelOptionsmediaIdreelId、text、mediaTypebroadcastReel/broadcastUserStoryDirectThreadBroadcastPhotoStoryOptionsfileviewMode、replyType、uploadIdbroadcastStoryDirectThreadBroadcastVideoStoryOptionsvideo、coverImageviewMode、replyType、uploadIdbroadcastStory而底层broadcast()使用的DirectThreadBroadcastOptionssrc/types/direct-thread.broadcast.options.ts通过ts-xor的XOR类型约束保证threadIds与userIds二者只能传其一从类型层面杜绝了同时按线程和按用户发送的非法状态。边界条件与注意事项未设置接收人时报错无论走broadcast()还是broadcastStory()只要threadId与userIds同时为nullSDK 都会抛出Error(DirectThread: No recipients set)src/entities/direct-thread.entity.ts#L216 与 #L248-L250删除消息依赖 threadIddeleteItem内部会先校验threadId为null时抛出IgClientError(threadId was null.)私信 Story 不支持贴纸broadcastStory经PublishService发送时会跳过所有 sticker 逻辑无需也无法为其配置贴纸签名表单broadcastUserStory使用signed: true表单会通过ig.request.sign()进行请求签名其余消息类型默认不签名链接检测的开销broadcastText默认加载url-regex-safe检测链接如遇该依赖兼容性问题SDK issue #1328 所述场景可传skipLinkCheck: true规避或直接改用broadcastLink。综上DirectThreadEntity是 instagram-private-api 私信能力的统一入口文本、链接、图片、视频、语音、帖子、用户名片与 Story 共 10 种消息类型全部通过实体方法一键发送线程管理操作也集中在同一对象上配合ig.entity.directThread()与收件箱 Feed 的records()无论是读取现有会话还是主动发起新会话都能以最少的样板代码完成开发。赞分享后端【免费下载链接】instagram-private-apiNodeJS Instagram private API SDK. Written in TypeScript.项目地址https://gitcode.com/gh_mirrors/in/instagram-private-api点击查看免费下载相关推荐Instagram私有API终极指南instagram-private-api完整入门教程Instagram私有API终极指南instagram private api完整入门教程 想要完全掌控你的Instagram账户操作吗 instagr后端Instagram私有API实战使用dilame/instagram-private-api实现直播功能全解析Instagram私有API实战使用dilame/instagram private api实现直播功能全解析 前言 在当今社交媒体盛行的时代Instagr后端instagram-private-api DirectThreadFeed 详解私信会话消息的分页拉取与状态同步instagram private api DirectThreadFeed 详解私信会话消息的分页拉取与状态同步 DirectThreadFeed 是 Ty后端上一篇企业级安全编码规范构建坚不可摧的软件防御体系下一篇pytest框架完整指南Python自动化测试从入门到精通创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考