naystack 1.8.14 → 1.8.16
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/dist/auth/index.cjs.js +32 -10
- package/dist/auth/index.esm.js +32 -10
- package/dist/auth/instagram/index.cjs.js +32 -10
- package/dist/auth/instagram/index.esm.js +32 -10
- package/dist/auth/instagram/route.cjs.js +32 -10
- package/dist/auth/instagram/route.esm.js +32 -10
- package/dist/socials/index.cjs.js +57 -18
- package/dist/socials/index.d.mts +1 -1
- package/dist/socials/index.d.ts +1 -1
- package/dist/socials/index.esm.js +56 -18
- package/dist/socials/instagram/setters.cjs.js +42 -15
- package/dist/socials/instagram/setters.esm.js +42 -15
- package/dist/socials/instagram/types.d.mts +3 -1
- package/dist/socials/instagram/types.d.ts +3 -1
- package/dist/socials/meta/container.cjs.js +32 -10
- package/dist/socials/meta/container.d.mts +21 -3
- package/dist/socials/meta/container.d.ts +21 -3
- package/dist/socials/meta/container.esm.js +32 -10
- package/dist/socials/threads/setters.cjs.js +38 -13
- package/dist/socials/threads/setters.esm.js +38 -13
- package/dist/socials/threads/types.d.mts +3 -1
- package/dist/socials/threads/types.d.ts +3 -1
- package/package.json +1 -1
|
@@ -159,25 +159,47 @@ function createPublisher(platform) {
|
|
|
159
159
|
}
|
|
160
160
|
return true;
|
|
161
161
|
};
|
|
162
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
163
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
164
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
165
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
166
|
+
const id = await platform.createContainer(token, params);
|
|
167
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
168
|
+
if (attempt < attempts) {
|
|
169
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
170
|
+
console.warn(
|
|
171
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
172
|
+
);
|
|
173
|
+
await sleep(delay);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
};
|
|
162
178
|
return {
|
|
163
179
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
164
|
-
publish: async (token, params, wait) => {
|
|
165
|
-
const containerID = await
|
|
180
|
+
publish: async (token, params, wait, retry) => {
|
|
181
|
+
const containerID = await createReady(
|
|
182
|
+
token,
|
|
183
|
+
params,
|
|
184
|
+
"container",
|
|
185
|
+
wait,
|
|
186
|
+
retry
|
|
187
|
+
);
|
|
166
188
|
if (!containerID) return null;
|
|
167
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
168
189
|
return platform.publish(token, containerID);
|
|
169
190
|
},
|
|
170
191
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
171
|
-
createChildren: async (token, items, wait) => {
|
|
192
|
+
createChildren: async (token, items, wait, retry) => {
|
|
172
193
|
const children = [];
|
|
173
194
|
for (const item of items) {
|
|
174
|
-
const childID = await
|
|
175
|
-
|
|
176
|
-
is_carousel_item: true
|
|
177
|
-
|
|
195
|
+
const childID = await createReady(
|
|
196
|
+
token,
|
|
197
|
+
{ ...item, is_carousel_item: true },
|
|
198
|
+
"carousel item",
|
|
199
|
+
wait,
|
|
200
|
+
retry
|
|
201
|
+
);
|
|
178
202
|
if (!childID) return null;
|
|
179
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
180
|
-
return null;
|
|
181
203
|
children.push(childID);
|
|
182
204
|
}
|
|
183
205
|
return children;
|
|
@@ -185,6 +207,13 @@ function createPublisher(platform) {
|
|
|
185
207
|
};
|
|
186
208
|
}
|
|
187
209
|
|
|
210
|
+
// src/socials/meta/types.ts
|
|
211
|
+
var MetaMediaType = /* @__PURE__ */ ((MetaMediaType2) => {
|
|
212
|
+
MetaMediaType2["Photo"] = "photo";
|
|
213
|
+
MetaMediaType2["Video"] = "video";
|
|
214
|
+
return MetaMediaType2;
|
|
215
|
+
})(MetaMediaType || {});
|
|
216
|
+
|
|
188
217
|
// src/socials/instagram/setters.ts
|
|
189
218
|
var publisher = createPublisher({
|
|
190
219
|
name: "Instagram",
|
|
@@ -228,14 +257,16 @@ var createInstagramPost = async (token, input) => {
|
|
|
228
257
|
media_type: "STORIES",
|
|
229
258
|
alt_text: void 0
|
|
230
259
|
},
|
|
231
|
-
input.wait
|
|
260
|
+
input.wait,
|
|
261
|
+
input.retry
|
|
232
262
|
);
|
|
233
263
|
}
|
|
234
264
|
if (media.length > 1) {
|
|
235
265
|
const children = await publisher.createChildren(
|
|
236
266
|
token,
|
|
237
267
|
media.map(mediaParams),
|
|
238
|
-
input.wait
|
|
268
|
+
input.wait,
|
|
269
|
+
input.retry
|
|
239
270
|
);
|
|
240
271
|
if (!children) return null;
|
|
241
272
|
return publisher.publish(
|
|
@@ -245,7 +276,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
245
276
|
children: children.join(","),
|
|
246
277
|
caption: input.caption
|
|
247
278
|
},
|
|
248
|
-
input.wait
|
|
279
|
+
input.wait,
|
|
280
|
+
input.retry
|
|
249
281
|
);
|
|
250
282
|
}
|
|
251
283
|
if (first.type === "video" /* Video */) {
|
|
@@ -261,7 +293,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
261
293
|
audio_name: input.audioName,
|
|
262
294
|
collaborators: input.collaborators && JSON.stringify(input.collaborators)
|
|
263
295
|
},
|
|
264
|
-
input.wait
|
|
296
|
+
input.wait,
|
|
297
|
+
input.retry
|
|
265
298
|
);
|
|
266
299
|
}
|
|
267
300
|
return publisher.publish(
|
|
@@ -272,7 +305,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
272
305
|
alt_text: first.altText,
|
|
273
306
|
location_id: input.locationID
|
|
274
307
|
},
|
|
275
|
-
input.wait
|
|
308
|
+
input.wait,
|
|
309
|
+
input.retry
|
|
276
310
|
);
|
|
277
311
|
};
|
|
278
312
|
var sendInstagramMessage = (token, to, text) => {
|
|
@@ -377,13 +411,15 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
377
411
|
const children = await publisher2.createChildren(
|
|
378
412
|
token,
|
|
379
413
|
media.map((item) => mediaParams2(item)),
|
|
380
|
-
post.wait
|
|
414
|
+
post.wait,
|
|
415
|
+
post.retry
|
|
381
416
|
);
|
|
382
417
|
if (!children) return null;
|
|
383
418
|
return publisher2.publish(
|
|
384
419
|
token,
|
|
385
420
|
{ ...shared, media_type: "CAROUSEL", children: children.join(",") },
|
|
386
|
-
post.wait
|
|
421
|
+
post.wait,
|
|
422
|
+
post.retry
|
|
387
423
|
);
|
|
388
424
|
}
|
|
389
425
|
return publisher2.publish(
|
|
@@ -393,7 +429,8 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
393
429
|
...shared,
|
|
394
430
|
link_attachment: post.linkAttachment
|
|
395
431
|
},
|
|
396
|
-
post.wait
|
|
432
|
+
post.wait,
|
|
433
|
+
post.retry
|
|
397
434
|
);
|
|
398
435
|
};
|
|
399
436
|
var createThread = async (token, posts) => {
|
|
@@ -421,6 +458,7 @@ var setupThreadsWebhook = (options) => {
|
|
|
421
458
|
};
|
|
422
459
|
};
|
|
423
460
|
export {
|
|
461
|
+
MetaMediaType,
|
|
424
462
|
canPublishToInstagram,
|
|
425
463
|
createInstagramPost,
|
|
426
464
|
createThread,
|
|
@@ -99,25 +99,47 @@ function createPublisher(platform) {
|
|
|
99
99
|
}
|
|
100
100
|
return true;
|
|
101
101
|
};
|
|
102
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
103
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
104
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
105
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
106
|
+
const id = await platform.createContainer(token, params);
|
|
107
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
108
|
+
if (attempt < attempts) {
|
|
109
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
110
|
+
console.warn(
|
|
111
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
112
|
+
);
|
|
113
|
+
await sleep(delay);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
};
|
|
102
118
|
return {
|
|
103
119
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
104
|
-
publish: async (token, params, wait) => {
|
|
105
|
-
const containerID = await
|
|
120
|
+
publish: async (token, params, wait, retry) => {
|
|
121
|
+
const containerID = await createReady(
|
|
122
|
+
token,
|
|
123
|
+
params,
|
|
124
|
+
"container",
|
|
125
|
+
wait,
|
|
126
|
+
retry
|
|
127
|
+
);
|
|
106
128
|
if (!containerID) return null;
|
|
107
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
108
129
|
return platform.publish(token, containerID);
|
|
109
130
|
},
|
|
110
131
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
111
|
-
createChildren: async (token, items, wait) => {
|
|
132
|
+
createChildren: async (token, items, wait, retry) => {
|
|
112
133
|
const children = [];
|
|
113
134
|
for (const item of items) {
|
|
114
|
-
const childID = await
|
|
115
|
-
|
|
116
|
-
is_carousel_item: true
|
|
117
|
-
|
|
135
|
+
const childID = await createReady(
|
|
136
|
+
token,
|
|
137
|
+
{ ...item, is_carousel_item: true },
|
|
138
|
+
"carousel item",
|
|
139
|
+
wait,
|
|
140
|
+
retry
|
|
141
|
+
);
|
|
118
142
|
if (!childID) return null;
|
|
119
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
120
|
-
return null;
|
|
121
143
|
children.push(childID);
|
|
122
144
|
}
|
|
123
145
|
return children;
|
|
@@ -168,14 +190,16 @@ var createInstagramPost = async (token, input) => {
|
|
|
168
190
|
media_type: "STORIES",
|
|
169
191
|
alt_text: void 0
|
|
170
192
|
},
|
|
171
|
-
input.wait
|
|
193
|
+
input.wait,
|
|
194
|
+
input.retry
|
|
172
195
|
);
|
|
173
196
|
}
|
|
174
197
|
if (media.length > 1) {
|
|
175
198
|
const children = await publisher.createChildren(
|
|
176
199
|
token,
|
|
177
200
|
media.map(mediaParams),
|
|
178
|
-
input.wait
|
|
201
|
+
input.wait,
|
|
202
|
+
input.retry
|
|
179
203
|
);
|
|
180
204
|
if (!children) return null;
|
|
181
205
|
return publisher.publish(
|
|
@@ -185,7 +209,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
185
209
|
children: children.join(","),
|
|
186
210
|
caption: input.caption
|
|
187
211
|
},
|
|
188
|
-
input.wait
|
|
212
|
+
input.wait,
|
|
213
|
+
input.retry
|
|
189
214
|
);
|
|
190
215
|
}
|
|
191
216
|
if (first.type === "video" /* Video */) {
|
|
@@ -201,7 +226,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
201
226
|
audio_name: input.audioName,
|
|
202
227
|
collaborators: input.collaborators && JSON.stringify(input.collaborators)
|
|
203
228
|
},
|
|
204
|
-
input.wait
|
|
229
|
+
input.wait,
|
|
230
|
+
input.retry
|
|
205
231
|
);
|
|
206
232
|
}
|
|
207
233
|
return publisher.publish(
|
|
@@ -212,7 +238,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
212
238
|
alt_text: first.altText,
|
|
213
239
|
location_id: input.locationID
|
|
214
240
|
},
|
|
215
|
-
input.wait
|
|
241
|
+
input.wait,
|
|
242
|
+
input.retry
|
|
216
243
|
);
|
|
217
244
|
};
|
|
218
245
|
var sendInstagramMessage = (token, to, text) => {
|
|
@@ -72,25 +72,47 @@ function createPublisher(platform) {
|
|
|
72
72
|
}
|
|
73
73
|
return true;
|
|
74
74
|
};
|
|
75
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
76
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
77
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
78
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
79
|
+
const id = await platform.createContainer(token, params);
|
|
80
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
81
|
+
if (attempt < attempts) {
|
|
82
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
83
|
+
console.warn(
|
|
84
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
85
|
+
);
|
|
86
|
+
await sleep(delay);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
};
|
|
75
91
|
return {
|
|
76
92
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
77
|
-
publish: async (token, params, wait) => {
|
|
78
|
-
const containerID = await
|
|
93
|
+
publish: async (token, params, wait, retry) => {
|
|
94
|
+
const containerID = await createReady(
|
|
95
|
+
token,
|
|
96
|
+
params,
|
|
97
|
+
"container",
|
|
98
|
+
wait,
|
|
99
|
+
retry
|
|
100
|
+
);
|
|
79
101
|
if (!containerID) return null;
|
|
80
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
81
102
|
return platform.publish(token, containerID);
|
|
82
103
|
},
|
|
83
104
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
84
|
-
createChildren: async (token, items, wait) => {
|
|
105
|
+
createChildren: async (token, items, wait, retry) => {
|
|
85
106
|
const children = [];
|
|
86
107
|
for (const item of items) {
|
|
87
|
-
const childID = await
|
|
88
|
-
|
|
89
|
-
is_carousel_item: true
|
|
90
|
-
|
|
108
|
+
const childID = await createReady(
|
|
109
|
+
token,
|
|
110
|
+
{ ...item, is_carousel_item: true },
|
|
111
|
+
"carousel item",
|
|
112
|
+
wait,
|
|
113
|
+
retry
|
|
114
|
+
);
|
|
91
115
|
if (!childID) return null;
|
|
92
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
93
|
-
return null;
|
|
94
116
|
children.push(childID);
|
|
95
117
|
}
|
|
96
118
|
return children;
|
|
@@ -141,14 +163,16 @@ var createInstagramPost = async (token, input) => {
|
|
|
141
163
|
media_type: "STORIES",
|
|
142
164
|
alt_text: void 0
|
|
143
165
|
},
|
|
144
|
-
input.wait
|
|
166
|
+
input.wait,
|
|
167
|
+
input.retry
|
|
145
168
|
);
|
|
146
169
|
}
|
|
147
170
|
if (media.length > 1) {
|
|
148
171
|
const children = await publisher.createChildren(
|
|
149
172
|
token,
|
|
150
173
|
media.map(mediaParams),
|
|
151
|
-
input.wait
|
|
174
|
+
input.wait,
|
|
175
|
+
input.retry
|
|
152
176
|
);
|
|
153
177
|
if (!children) return null;
|
|
154
178
|
return publisher.publish(
|
|
@@ -158,7 +182,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
158
182
|
children: children.join(","),
|
|
159
183
|
caption: input.caption
|
|
160
184
|
},
|
|
161
|
-
input.wait
|
|
185
|
+
input.wait,
|
|
186
|
+
input.retry
|
|
162
187
|
);
|
|
163
188
|
}
|
|
164
189
|
if (first.type === "video" /* Video */) {
|
|
@@ -174,7 +199,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
174
199
|
audio_name: input.audioName,
|
|
175
200
|
collaborators: input.collaborators && JSON.stringify(input.collaborators)
|
|
176
201
|
},
|
|
177
|
-
input.wait
|
|
202
|
+
input.wait,
|
|
203
|
+
input.retry
|
|
178
204
|
);
|
|
179
205
|
}
|
|
180
206
|
return publisher.publish(
|
|
@@ -185,7 +211,8 @@ var createInstagramPost = async (token, input) => {
|
|
|
185
211
|
alt_text: first.altText,
|
|
186
212
|
location_id: input.locationID
|
|
187
213
|
},
|
|
188
|
-
input.wait
|
|
214
|
+
input.wait,
|
|
215
|
+
input.retry
|
|
189
216
|
);
|
|
190
217
|
};
|
|
191
218
|
var sendInstagramMessage = (token, to, text) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WaitForContainerOptions } from '../meta/container.mjs';
|
|
1
|
+
import { WaitForContainerOptions, RetryOptions } from '../meta/container.mjs';
|
|
2
2
|
import { MetaMediaType } from '../meta/types.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -121,6 +121,7 @@ type InstagramPostMedia = {
|
|
|
121
121
|
* @property audioName - Reels: name for the audio track. Can only be set once.
|
|
122
122
|
* @property collaborators - Reels: up to 3 public usernames to invite as collaborators.
|
|
123
123
|
* @property wait - Container polling settings.
|
|
124
|
+
* @property retry - Container-creation retry settings. See {@link RetryOptions}.
|
|
124
125
|
*
|
|
125
126
|
* @category Socials
|
|
126
127
|
*/
|
|
@@ -135,6 +136,7 @@ type InstagramPostInput = {
|
|
|
135
136
|
audioName?: string;
|
|
136
137
|
collaborators?: string[];
|
|
137
138
|
wait?: WaitForContainerOptions;
|
|
139
|
+
retry?: RetryOptions;
|
|
138
140
|
};
|
|
139
141
|
|
|
140
142
|
export type { InstagramConversation, InstagramMedia, InstagramMessage, InstagramPostInput, InstagramPostMedia, InstagramUser };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WaitForContainerOptions } from '../meta/container.js';
|
|
1
|
+
import { WaitForContainerOptions, RetryOptions } from '../meta/container.js';
|
|
2
2
|
import { MetaMediaType } from '../meta/types.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -121,6 +121,7 @@ type InstagramPostMedia = {
|
|
|
121
121
|
* @property audioName - Reels: name for the audio track. Can only be set once.
|
|
122
122
|
* @property collaborators - Reels: up to 3 public usernames to invite as collaborators.
|
|
123
123
|
* @property wait - Container polling settings.
|
|
124
|
+
* @property retry - Container-creation retry settings. See {@link RetryOptions}.
|
|
124
125
|
*
|
|
125
126
|
* @category Socials
|
|
126
127
|
*/
|
|
@@ -135,6 +136,7 @@ type InstagramPostInput = {
|
|
|
135
136
|
audioName?: string;
|
|
136
137
|
collaborators?: string[];
|
|
137
138
|
wait?: WaitForContainerOptions;
|
|
139
|
+
retry?: RetryOptions;
|
|
138
140
|
};
|
|
139
141
|
|
|
140
142
|
export type { InstagramConversation, InstagramMedia, InstagramMessage, InstagramPostInput, InstagramPostMedia, InstagramUser };
|
|
@@ -51,25 +51,47 @@ function createPublisher(platform) {
|
|
|
51
51
|
}
|
|
52
52
|
return true;
|
|
53
53
|
};
|
|
54
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
55
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
56
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
57
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
58
|
+
const id = await platform.createContainer(token, params);
|
|
59
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
60
|
+
if (attempt < attempts) {
|
|
61
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
62
|
+
console.warn(
|
|
63
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
64
|
+
);
|
|
65
|
+
await sleep(delay);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
};
|
|
54
70
|
return {
|
|
55
71
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
56
|
-
publish: async (token, params, wait) => {
|
|
57
|
-
const containerID = await
|
|
72
|
+
publish: async (token, params, wait, retry) => {
|
|
73
|
+
const containerID = await createReady(
|
|
74
|
+
token,
|
|
75
|
+
params,
|
|
76
|
+
"container",
|
|
77
|
+
wait,
|
|
78
|
+
retry
|
|
79
|
+
);
|
|
58
80
|
if (!containerID) return null;
|
|
59
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
60
81
|
return platform.publish(token, containerID);
|
|
61
82
|
},
|
|
62
83
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
63
|
-
createChildren: async (token, items, wait) => {
|
|
84
|
+
createChildren: async (token, items, wait, retry) => {
|
|
64
85
|
const children = [];
|
|
65
86
|
for (const item of items) {
|
|
66
|
-
const childID = await
|
|
67
|
-
|
|
68
|
-
is_carousel_item: true
|
|
69
|
-
|
|
87
|
+
const childID = await createReady(
|
|
88
|
+
token,
|
|
89
|
+
{ ...item, is_carousel_item: true },
|
|
90
|
+
"carousel item",
|
|
91
|
+
wait,
|
|
92
|
+
retry
|
|
93
|
+
);
|
|
70
94
|
if (!childID) return null;
|
|
71
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
72
|
-
return null;
|
|
73
95
|
children.push(childID);
|
|
74
96
|
}
|
|
75
97
|
return children;
|
|
@@ -12,6 +12,24 @@ type WaitForContainerOptions = {
|
|
|
12
12
|
intervalMS?: number;
|
|
13
13
|
timeoutMS?: number;
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Retry settings for creating a media container.
|
|
17
|
+
*
|
|
18
|
+
* Meta intermittently rejects a perfectly valid container — most visibly on
|
|
19
|
+
* carousels, where one arbitrary child fails with "Only photo or video can be
|
|
20
|
+
* accepted as media type." and the identical call succeeds moments later. The
|
|
21
|
+
* failure is transient and carries no distinguishing error code, so container
|
|
22
|
+
* creation is simply retried rather than pattern-matched against Meta's copy.
|
|
23
|
+
*
|
|
24
|
+
* @property attempts - Total tries, including the first. Default: `3`.
|
|
25
|
+
* @property backoffMS - Delay before the second try, doubled each time after. Default: `2000`.
|
|
26
|
+
*
|
|
27
|
+
* @category Socials
|
|
28
|
+
*/
|
|
29
|
+
type RetryOptions = {
|
|
30
|
+
attempts?: number;
|
|
31
|
+
backoffMS?: number;
|
|
32
|
+
};
|
|
15
33
|
/**
|
|
16
34
|
* Wires up the create → wait → publish flow Meta platforms share. Instagram and
|
|
17
35
|
* Threads differ only in their endpoints, so each builds one publisher and every
|
|
@@ -30,9 +48,9 @@ declare function createPublisher(platform: {
|
|
|
30
48
|
publish: (token: string, creationID: string) => Promise<string | null>;
|
|
31
49
|
}): {
|
|
32
50
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
33
|
-
publish: (token: string, params: GraphParams, wait?: WaitForContainerOptions) => Promise<string | null>;
|
|
51
|
+
publish: (token: string, params: GraphParams, wait?: WaitForContainerOptions, retry?: RetryOptions) => Promise<string | null>;
|
|
34
52
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
35
|
-
createChildren: (token: string, items: GraphParams[], wait?: WaitForContainerOptions) => Promise<string[] | null>;
|
|
53
|
+
createChildren: (token: string, items: GraphParams[], wait?: WaitForContainerOptions, retry?: RetryOptions) => Promise<string[] | null>;
|
|
36
54
|
};
|
|
37
55
|
|
|
38
|
-
export { type WaitForContainerOptions, createPublisher };
|
|
56
|
+
export { type RetryOptions, type WaitForContainerOptions, createPublisher };
|
|
@@ -12,6 +12,24 @@ type WaitForContainerOptions = {
|
|
|
12
12
|
intervalMS?: number;
|
|
13
13
|
timeoutMS?: number;
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Retry settings for creating a media container.
|
|
17
|
+
*
|
|
18
|
+
* Meta intermittently rejects a perfectly valid container — most visibly on
|
|
19
|
+
* carousels, where one arbitrary child fails with "Only photo or video can be
|
|
20
|
+
* accepted as media type." and the identical call succeeds moments later. The
|
|
21
|
+
* failure is transient and carries no distinguishing error code, so container
|
|
22
|
+
* creation is simply retried rather than pattern-matched against Meta's copy.
|
|
23
|
+
*
|
|
24
|
+
* @property attempts - Total tries, including the first. Default: `3`.
|
|
25
|
+
* @property backoffMS - Delay before the second try, doubled each time after. Default: `2000`.
|
|
26
|
+
*
|
|
27
|
+
* @category Socials
|
|
28
|
+
*/
|
|
29
|
+
type RetryOptions = {
|
|
30
|
+
attempts?: number;
|
|
31
|
+
backoffMS?: number;
|
|
32
|
+
};
|
|
15
33
|
/**
|
|
16
34
|
* Wires up the create → wait → publish flow Meta platforms share. Instagram and
|
|
17
35
|
* Threads differ only in their endpoints, so each builds one publisher and every
|
|
@@ -30,9 +48,9 @@ declare function createPublisher(platform: {
|
|
|
30
48
|
publish: (token: string, creationID: string) => Promise<string | null>;
|
|
31
49
|
}): {
|
|
32
50
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
33
|
-
publish: (token: string, params: GraphParams, wait?: WaitForContainerOptions) => Promise<string | null>;
|
|
51
|
+
publish: (token: string, params: GraphParams, wait?: WaitForContainerOptions, retry?: RetryOptions) => Promise<string | null>;
|
|
34
52
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
35
|
-
createChildren: (token: string, items: GraphParams[], wait?: WaitForContainerOptions) => Promise<string[] | null>;
|
|
53
|
+
createChildren: (token: string, items: GraphParams[], wait?: WaitForContainerOptions, retry?: RetryOptions) => Promise<string[] | null>;
|
|
36
54
|
};
|
|
37
55
|
|
|
38
|
-
export { type WaitForContainerOptions, createPublisher };
|
|
56
|
+
export { type RetryOptions, type WaitForContainerOptions, createPublisher };
|
|
@@ -27,25 +27,47 @@ function createPublisher(platform) {
|
|
|
27
27
|
}
|
|
28
28
|
return true;
|
|
29
29
|
};
|
|
30
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
31
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
32
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
33
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
34
|
+
const id = await platform.createContainer(token, params);
|
|
35
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
36
|
+
if (attempt < attempts) {
|
|
37
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
38
|
+
console.warn(
|
|
39
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
40
|
+
);
|
|
41
|
+
await sleep(delay);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
30
46
|
return {
|
|
31
47
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
32
|
-
publish: async (token, params, wait) => {
|
|
33
|
-
const containerID = await
|
|
48
|
+
publish: async (token, params, wait, retry) => {
|
|
49
|
+
const containerID = await createReady(
|
|
50
|
+
token,
|
|
51
|
+
params,
|
|
52
|
+
"container",
|
|
53
|
+
wait,
|
|
54
|
+
retry
|
|
55
|
+
);
|
|
34
56
|
if (!containerID) return null;
|
|
35
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
36
57
|
return platform.publish(token, containerID);
|
|
37
58
|
},
|
|
38
59
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
39
|
-
createChildren: async (token, items, wait) => {
|
|
60
|
+
createChildren: async (token, items, wait, retry) => {
|
|
40
61
|
const children = [];
|
|
41
62
|
for (const item of items) {
|
|
42
|
-
const childID = await
|
|
43
|
-
|
|
44
|
-
is_carousel_item: true
|
|
45
|
-
|
|
63
|
+
const childID = await createReady(
|
|
64
|
+
token,
|
|
65
|
+
{ ...item, is_carousel_item: true },
|
|
66
|
+
"carousel item",
|
|
67
|
+
wait,
|
|
68
|
+
retry
|
|
69
|
+
);
|
|
46
70
|
if (!childID) return null;
|
|
47
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
48
|
-
return null;
|
|
49
71
|
children.push(childID);
|
|
50
72
|
}
|
|
51
73
|
return children;
|