@eryxenx/insta-chat 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eryxenx/insta-chat",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": " Unofficial Instagram Chat API for Node.js | Build Instagram DM bots on personal accounts — send messages, media, voice notes, reactions, edit & unsend, listen for incoming chats. No browser at runtime",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -78,20 +78,34 @@ class MediaMethods {
78
78
  }
79
79
 
80
80
  async _commitMedia(threadID, attachmentFbid, options = {}) {
81
- return this.http.postGraphQL(
82
- "IGDirectMediaSendMutation",
83
- DOC_ID.MEDIA_SEND,
84
- {
85
- attachment_fbid: String(attachmentFbid),
86
- thread_id: String(threadID),
87
- offline_threading_id: this._offlineThreadingId(),
88
- reply_to_message_id: options.replyToMessageId || null,
89
- forwarded_from_thread_id: null,
90
- is_forwarded_from_own_message: null
91
- },
92
- this._threadReferer(threadID),
93
- { throwOnError: true }
94
- );
81
+ // Instagram intermittently answers IGDirectMediaSendMutation with a
82
+ // transient `field_exception` even though the upload already succeeded; a
83
+ // short backoff retry (same attachment fbid, fresh offline_threading_id)
84
+ // commits it. Without this a media send fails once and the caller sees a
85
+ // hard error while the bytes are already uploaded.
86
+ for (let attempt = 0; ; attempt++) {
87
+ try {
88
+ return await this.http.postGraphQL(
89
+ "IGDirectMediaSendMutation",
90
+ DOC_ID.MEDIA_SEND,
91
+ {
92
+ attachment_fbid: String(attachmentFbid),
93
+ thread_id: String(threadID),
94
+ offline_threading_id: this._offlineThreadingId(),
95
+ reply_to_message_id: options.replyToMessageId || null,
96
+ forwarded_from_thread_id: null,
97
+ is_forwarded_from_own_message: null
98
+ },
99
+ this._threadReferer(threadID),
100
+ { throwOnError: true }
101
+ );
102
+ } catch (error) {
103
+ const msg = String((error && error.message) || "");
104
+ const retriable = /field_exception|field exception|temporary failure|internal server error/i.test(msg);
105
+ if (!retriable || attempt >= 2) throw error;
106
+ await new Promise((r) => setTimeout(r, 1200 * (attempt + 1)));
107
+ }
108
+ }
95
109
  }
96
110
 
97
111
  async _send(threadID, uploadOptions, options) {