naystack 1.8.15 → 1.8.17
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 +48 -18
- package/dist/socials/index.d.mts +1 -1
- package/dist/socials/index.d.ts +1 -1
- package/dist/socials/index.esm.js +48 -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/dist/utils/client/index.cjs.js +36 -22
- package/dist/utils/client/index.d.mts +1 -1
- package/dist/utils/client/index.d.ts +1 -1
- package/dist/utils/client/index.esm.js +36 -22
- package/dist/utils/client/seo.cjs.js +36 -22
- package/dist/utils/client/seo.d.mts +15 -3
- package/dist/utils/client/seo.d.ts +15 -3
- package/dist/utils/client/seo.esm.js +36 -22
- package/package.json +1 -1
|
@@ -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;
|
|
@@ -54,25 +54,47 @@ function createPublisher(platform) {
|
|
|
54
54
|
}
|
|
55
55
|
return true;
|
|
56
56
|
};
|
|
57
|
+
const createReady = async (token, params, label, wait, retry) => {
|
|
58
|
+
const attempts = Math.max(1, retry?.attempts ?? 3);
|
|
59
|
+
const backoffMS = retry?.backoffMS ?? 2e3;
|
|
60
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
61
|
+
const id = await platform.createContainer(token, params);
|
|
62
|
+
if (id && await isReady(token, id, label, wait)) return id;
|
|
63
|
+
if (attempt < attempts) {
|
|
64
|
+
const delay = backoffMS * 2 ** (attempt - 1);
|
|
65
|
+
console.warn(
|
|
66
|
+
`[naystack] ${platform.name} ${label} attempt ${attempt}/${attempts} failed \u2014 retrying in ${delay}ms`
|
|
67
|
+
);
|
|
68
|
+
await sleep(delay);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
};
|
|
57
73
|
return {
|
|
58
74
|
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
59
|
-
publish: async (token, params, wait) => {
|
|
60
|
-
const containerID = await
|
|
75
|
+
publish: async (token, params, wait, retry) => {
|
|
76
|
+
const containerID = await createReady(
|
|
77
|
+
token,
|
|
78
|
+
params,
|
|
79
|
+
"container",
|
|
80
|
+
wait,
|
|
81
|
+
retry
|
|
82
|
+
);
|
|
61
83
|
if (!containerID) return null;
|
|
62
|
-
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
63
84
|
return platform.publish(token, containerID);
|
|
64
85
|
},
|
|
65
86
|
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
66
|
-
createChildren: async (token, items, wait) => {
|
|
87
|
+
createChildren: async (token, items, wait, retry) => {
|
|
67
88
|
const children = [];
|
|
68
89
|
for (const item of items) {
|
|
69
|
-
const childID = await
|
|
70
|
-
|
|
71
|
-
is_carousel_item: true
|
|
72
|
-
|
|
90
|
+
const childID = await createReady(
|
|
91
|
+
token,
|
|
92
|
+
{ ...item, is_carousel_item: true },
|
|
93
|
+
"carousel item",
|
|
94
|
+
wait,
|
|
95
|
+
retry
|
|
96
|
+
);
|
|
73
97
|
if (!childID) return null;
|
|
74
|
-
if (!await isReady(token, childID, "carousel item", wait))
|
|
75
|
-
return null;
|
|
76
98
|
children.push(childID);
|
|
77
99
|
}
|
|
78
100
|
return children;
|
|
@@ -159,13 +181,15 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
159
181
|
const children = await publisher.createChildren(
|
|
160
182
|
token,
|
|
161
183
|
media.map((item) => mediaParams(item)),
|
|
162
|
-
post.wait
|
|
184
|
+
post.wait,
|
|
185
|
+
post.retry
|
|
163
186
|
);
|
|
164
187
|
if (!children) return null;
|
|
165
188
|
return publisher.publish(
|
|
166
189
|
token,
|
|
167
190
|
{ ...shared, media_type: "CAROUSEL", children: children.join(",") },
|
|
168
|
-
post.wait
|
|
191
|
+
post.wait,
|
|
192
|
+
post.retry
|
|
169
193
|
);
|
|
170
194
|
}
|
|
171
195
|
return publisher.publish(
|
|
@@ -175,7 +199,8 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
175
199
|
...shared,
|
|
176
200
|
link_attachment: post.linkAttachment
|
|
177
201
|
},
|
|
178
|
-
post.wait
|
|
202
|
+
post.wait,
|
|
203
|
+
post.retry
|
|
179
204
|
);
|
|
180
205
|
};
|
|
181
206
|
var createThread = async (token, posts) => {
|
|
@@ -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;
|
|
@@ -132,13 +154,15 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
132
154
|
const children = await publisher.createChildren(
|
|
133
155
|
token,
|
|
134
156
|
media.map((item) => mediaParams(item)),
|
|
135
|
-
post.wait
|
|
157
|
+
post.wait,
|
|
158
|
+
post.retry
|
|
136
159
|
);
|
|
137
160
|
if (!children) return null;
|
|
138
161
|
return publisher.publish(
|
|
139
162
|
token,
|
|
140
163
|
{ ...shared, media_type: "CAROUSEL", children: children.join(",") },
|
|
141
|
-
post.wait
|
|
164
|
+
post.wait,
|
|
165
|
+
post.retry
|
|
142
166
|
);
|
|
143
167
|
}
|
|
144
168
|
return publisher.publish(
|
|
@@ -148,7 +172,8 @@ var createThreadsPost = async (token, input, replyToID) => {
|
|
|
148
172
|
...shared,
|
|
149
173
|
link_attachment: post.linkAttachment
|
|
150
174
|
},
|
|
151
|
-
post.wait
|
|
175
|
+
post.wait,
|
|
176
|
+
post.retry
|
|
152
177
|
);
|
|
153
178
|
};
|
|
154
179
|
var createThread = async (token, posts) => {
|
|
@@ -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
|
/**
|
|
@@ -40,6 +40,7 @@ type ThreadsPostMedia = {
|
|
|
40
40
|
* @property replyToID - Parent post id, to make this post a reply.
|
|
41
41
|
* @property replyControl - Who may reply.
|
|
42
42
|
* @property wait - Container polling settings.
|
|
43
|
+
* @property retry - Container-creation retry settings. See {@link RetryOptions}.
|
|
43
44
|
*
|
|
44
45
|
* @category Socials
|
|
45
46
|
*/
|
|
@@ -50,6 +51,7 @@ type ThreadsPostInput = {
|
|
|
50
51
|
replyToID?: string;
|
|
51
52
|
replyControl?: "everyone" | "accounts_you_follow" | "mentioned_only";
|
|
52
53
|
wait?: WaitForContainerOptions;
|
|
54
|
+
retry?: RetryOptions;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
export type { ThreadsPost, ThreadsPostInput, ThreadsPostMedia };
|
|
@@ -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
|
/**
|
|
@@ -40,6 +40,7 @@ type ThreadsPostMedia = {
|
|
|
40
40
|
* @property replyToID - Parent post id, to make this post a reply.
|
|
41
41
|
* @property replyControl - Who may reply.
|
|
42
42
|
* @property wait - Container polling settings.
|
|
43
|
+
* @property retry - Container-creation retry settings. See {@link RetryOptions}.
|
|
43
44
|
*
|
|
44
45
|
* @category Socials
|
|
45
46
|
*/
|
|
@@ -50,6 +51,7 @@ type ThreadsPostInput = {
|
|
|
50
51
|
replyToID?: string;
|
|
51
52
|
replyControl?: "everyone" | "accounts_you_follow" | "mentioned_only";
|
|
52
53
|
wait?: WaitForContainerOptions;
|
|
54
|
+
retry?: RetryOptions;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
export type { ThreadsPost, ThreadsPostInput, ThreadsPostMedia };
|