nodebb-plugin-facebook-post 1.0.37 → 1.0.39
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/library.js +40 -9
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -247,6 +247,26 @@ async function getInstagramUserId() {
|
|
|
247
247
|
return igId;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
async function waitForIgContainer(containerId, accessToken, graphVersion, { maxAttempts = 20, intervalMs = 3000 } = {}) {
|
|
251
|
+
const url = `https://graph.facebook.com/${graphVersion}/${containerId}`;
|
|
252
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
253
|
+
// eslint-disable-next-line no-await-in-loop
|
|
254
|
+
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
255
|
+
// eslint-disable-next-line no-await-in-loop
|
|
256
|
+
const resp = await axios.get(url, {
|
|
257
|
+
params: { fields: 'status_code,status', access_token: accessToken },
|
|
258
|
+
timeout: 10000,
|
|
259
|
+
});
|
|
260
|
+
const statusCode = resp.data && resp.data.status_code;
|
|
261
|
+
if (statusCode === 'FINISHED') return;
|
|
262
|
+
if (statusCode === 'ERROR' || statusCode === 'EXPIRED') {
|
|
263
|
+
throw new Error(`Instagram container ${containerId} status: ${statusCode} (${resp.data && resp.data.status})`);
|
|
264
|
+
}
|
|
265
|
+
// IN_PROGRESS or PUBLISHED → keep waiting
|
|
266
|
+
}
|
|
267
|
+
throw new Error(`Instagram container ${containerId} did not reach FINISHED after ${maxAttempts} attempts`);
|
|
268
|
+
}
|
|
269
|
+
|
|
250
270
|
async function postToInstagram(ctx) {
|
|
251
271
|
const rawContent = ctx.post.content || '';
|
|
252
272
|
const topicTitle = decodeHtmlEntities(ctx.topic.title || 'Nouveau sujet');
|
|
@@ -269,17 +289,21 @@ async function postToInstagram(ctx) {
|
|
|
269
289
|
|
|
270
290
|
const igUserId = await getInstagramUserId();
|
|
271
291
|
const baseUrl = `https://graph.facebook.com/${settings.fbGraphVersion}/${igUserId}`;
|
|
292
|
+
const token = settings.fbPageAccessToken;
|
|
293
|
+
const graphVersion = settings.fbGraphVersion;
|
|
272
294
|
|
|
273
295
|
if (imageUrls.length === 1) {
|
|
274
296
|
const containerResp = await axios.post(`${baseUrl}/media`, null, {
|
|
275
|
-
params: { image_url: imageUrls[0], caption, access_token:
|
|
297
|
+
params: { image_url: imageUrls[0], caption, access_token: token },
|
|
276
298
|
timeout: 20000,
|
|
277
299
|
});
|
|
278
300
|
const containerId = containerResp.data && containerResp.data.id;
|
|
279
301
|
if (!containerId) return null;
|
|
280
302
|
|
|
303
|
+
await waitForIgContainer(containerId, token, graphVersion);
|
|
304
|
+
|
|
281
305
|
const publishResp = await axios.post(`${baseUrl}/media_publish`, null, {
|
|
282
|
-
params: { creation_id: containerId, access_token:
|
|
306
|
+
params: { creation_id: containerId, access_token: token },
|
|
283
307
|
timeout: 20000,
|
|
284
308
|
});
|
|
285
309
|
return publishResp.data && publishResp.data.id;
|
|
@@ -294,25 +318,30 @@ async function postToInstagram(ctx) {
|
|
|
294
318
|
image_url: url,
|
|
295
319
|
media_type: 'IMAGE',
|
|
296
320
|
is_carousel_item: true,
|
|
297
|
-
access_token:
|
|
321
|
+
access_token: token,
|
|
298
322
|
},
|
|
299
323
|
timeout: 20000,
|
|
300
324
|
});
|
|
301
325
|
const childId = childResp.data && childResp.data.id;
|
|
302
|
-
if (childId)
|
|
326
|
+
if (childId) {
|
|
327
|
+
// eslint-disable-next-line no-await-in-loop
|
|
328
|
+
await waitForIgContainer(childId, token, graphVersion);
|
|
329
|
+
childIds.push(childId);
|
|
330
|
+
}
|
|
303
331
|
}
|
|
304
332
|
if (!childIds.length) return null;
|
|
305
333
|
|
|
306
334
|
// Instagram requires at least 2 children for a carousel; fall back to single image
|
|
307
335
|
if (childIds.length < 2) {
|
|
308
336
|
const singleResp = await axios.post(`${baseUrl}/media`, null, {
|
|
309
|
-
params: { image_url: imageUrls[0], caption, access_token:
|
|
337
|
+
params: { image_url: imageUrls[0], caption, access_token: token },
|
|
310
338
|
timeout: 20000,
|
|
311
339
|
});
|
|
312
340
|
const singleId = singleResp.data && singleResp.data.id;
|
|
313
341
|
if (!singleId) return null;
|
|
342
|
+
await waitForIgContainer(singleId, token, graphVersion);
|
|
314
343
|
const pubResp = await axios.post(`${baseUrl}/media_publish`, null, {
|
|
315
|
-
params: { creation_id: singleId, access_token:
|
|
344
|
+
params: { creation_id: singleId, access_token: token },
|
|
316
345
|
timeout: 20000,
|
|
317
346
|
});
|
|
318
347
|
return pubResp.data && pubResp.data.id;
|
|
@@ -321,8 +350,8 @@ async function postToInstagram(ctx) {
|
|
|
321
350
|
const form = new URLSearchParams();
|
|
322
351
|
form.append('media_type', 'CAROUSEL');
|
|
323
352
|
form.append('caption', caption);
|
|
324
|
-
form.append('children',
|
|
325
|
-
form.append('access_token',
|
|
353
|
+
form.append('children', JSON.stringify(childIds));
|
|
354
|
+
form.append('access_token', token);
|
|
326
355
|
|
|
327
356
|
const carouselResp = await axios.post(`${baseUrl}/media`, form, {
|
|
328
357
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
@@ -331,8 +360,10 @@ async function postToInstagram(ctx) {
|
|
|
331
360
|
const carouselId = carouselResp.data && carouselResp.data.id;
|
|
332
361
|
if (!carouselId) return null;
|
|
333
362
|
|
|
363
|
+
await waitForIgContainer(carouselId, token, graphVersion);
|
|
364
|
+
|
|
334
365
|
const publishResp = await axios.post(`${baseUrl}/media_publish`, null, {
|
|
335
|
-
params: { creation_id: carouselId, access_token:
|
|
366
|
+
params: { creation_id: carouselId, access_token: token },
|
|
336
367
|
timeout: 20000,
|
|
337
368
|
});
|
|
338
369
|
return publishResp.data && publishResp.data.id;
|
package/package.json
CHANGED