naystack 1.8.11 → 1.8.13
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/README.md +189 -31
- package/dist/auth/index.cjs.js +158 -18
- package/dist/auth/index.d.mts +3 -1
- package/dist/auth/index.d.ts +3 -1
- package/dist/auth/index.esm.js +158 -18
- package/dist/auth/instagram/index.cjs.js +158 -18
- package/dist/auth/instagram/index.d.mts +6 -1
- package/dist/auth/instagram/index.d.ts +6 -1
- package/dist/auth/instagram/index.esm.js +158 -18
- package/dist/auth/instagram/route.cjs.js +158 -18
- package/dist/auth/instagram/route.d.mts +3 -1
- package/dist/auth/instagram/route.d.ts +3 -1
- package/dist/auth/instagram/route.esm.js +158 -18
- package/dist/auth/instagram/utils.cjs.js +2 -2
- package/dist/auth/instagram/utils.d.mts +13 -2
- package/dist/auth/instagram/utils.d.ts +13 -2
- package/dist/auth/instagram/utils.esm.js +2 -2
- package/dist/file/index.cjs.js +9 -6
- package/dist/file/index.d.mts +1 -1
- package/dist/file/index.d.ts +1 -1
- package/dist/file/index.esm.js +9 -6
- package/dist/file/put.cjs.js +6 -4
- package/dist/file/put.d.mts +2 -0
- package/dist/file/put.d.ts +2 -0
- package/dist/file/put.esm.js +6 -4
- package/dist/file/setup.cjs.js +6 -4
- package/dist/file/setup.d.mts +22 -4
- package/dist/file/setup.d.ts +22 -4
- package/dist/file/setup.esm.js +6 -4
- package/dist/file/utils.cjs.js +6 -4
- package/dist/file/utils.d.mts +19 -3
- package/dist/file/utils.d.ts +19 -3
- package/dist/file/utils.esm.js +6 -4
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/socials/index.cjs.js +298 -72
- package/dist/socials/index.d.mts +6 -4
- package/dist/socials/index.d.ts +6 -4
- package/dist/socials/index.esm.js +296 -72
- package/dist/socials/instagram/getters.cjs.js +76 -25
- package/dist/socials/instagram/getters.d.mts +56 -6
- package/dist/socials/instagram/getters.d.ts +56 -6
- package/dist/socials/instagram/getters.esm.js +74 -25
- package/dist/socials/instagram/setters.cjs.js +192 -14
- package/dist/socials/instagram/setters.d.mts +43 -3
- package/dist/socials/instagram/setters.d.ts +43 -3
- package/dist/socials/instagram/setters.esm.js +191 -14
- package/dist/socials/instagram/types.d.mts +48 -11
- package/dist/socials/instagram/types.d.ts +48 -11
- package/dist/socials/instagram/utils.cjs.js +28 -15
- package/dist/socials/instagram/utils.d.mts +7 -18
- package/dist/socials/instagram/utils.d.ts +7 -18
- package/dist/socials/instagram/utils.esm.js +26 -14
- package/dist/socials/instagram/webhook.cjs.js +1 -1
- package/dist/socials/instagram/webhook.esm.js +1 -1
- package/dist/socials/meta/container.cjs.js +82 -0
- package/dist/socials/meta/container.d.mts +38 -0
- package/dist/socials/meta/container.d.ts +38 -0
- package/dist/socials/meta/container.esm.js +57 -0
- package/dist/socials/meta/request.cjs.js +60 -0
- package/dist/socials/meta/request.d.mts +50 -0
- package/dist/socials/meta/request.d.ts +50 -0
- package/dist/socials/meta/request.esm.js +34 -0
- package/dist/socials/meta/types.cjs.js +18 -0
- package/dist/socials/meta/types.d.mts +47 -0
- package/dist/socials/meta/types.d.ts +47 -0
- package/dist/socials/meta/types.esm.js +0 -0
- package/dist/socials/{meta-webhook.cjs.js → meta/webhook.cjs.js} +4 -4
- package/dist/socials/{meta-webhook.esm.js → meta/webhook.esm.js} +1 -1
- package/dist/socials/threads/getters.cjs.js +36 -11
- package/dist/socials/threads/getters.d.mts +23 -2
- package/dist/socials/threads/getters.d.ts +23 -2
- package/dist/socials/threads/getters.esm.js +35 -11
- package/dist/socials/threads/setters.cjs.js +150 -44
- package/dist/socials/threads/setters.d.mts +25 -34
- package/dist/socials/threads/setters.d.ts +25 -34
- package/dist/socials/threads/setters.esm.js +149 -41
- package/dist/socials/threads/types.d.mts +40 -1
- package/dist/socials/threads/types.d.ts +40 -1
- package/dist/socials/threads/utils.cjs.js +29 -11
- package/dist/socials/threads/utils.d.mts +8 -17
- package/dist/socials/threads/utils.d.ts +8 -17
- package/dist/socials/threads/utils.esm.js +27 -10
- package/dist/socials/threads/webhook.cjs.js +1 -1
- package/dist/socials/threads/webhook.esm.js +1 -1
- package/package.json +1 -1
- /package/dist/socials/{meta-webhook.d.mts → meta/webhook.d.mts} +0 -0
- /package/dist/socials/{meta-webhook.d.ts → meta/webhook.d.ts} +0 -0
|
@@ -125,40 +125,177 @@ async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
128
|
+
var getInstagramAuthorizationURL = (token, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
129
129
|
"INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
|
|
130
|
-
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope
|
|
130
|
+
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}#weblink`;
|
|
131
131
|
|
|
132
|
-
// src/socials/
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
method: postData ? "POST" : "GET",
|
|
139
|
-
body: JSON.stringify(postData),
|
|
140
|
-
headers: {
|
|
141
|
-
Authorization: `Bearer ${token}`,
|
|
142
|
-
"Content-Type": "application/json"
|
|
132
|
+
// src/socials/meta/request.ts
|
|
133
|
+
function createGraphClient(baseURL) {
|
|
134
|
+
const buildURL = (token, path, params = {}) => {
|
|
135
|
+
const search = new URLSearchParams();
|
|
136
|
+
for (const [key, value] of Object.entries(params)) {
|
|
137
|
+
if (value !== void 0) search.set(key, String(value));
|
|
143
138
|
}
|
|
144
|
-
|
|
139
|
+
search.set("access_token", token);
|
|
140
|
+
return `${baseURL}/${path}?${search.toString()}`;
|
|
141
|
+
};
|
|
142
|
+
const request = async (token, path, options = {}) => {
|
|
143
|
+
const response = await fetch(buildURL(token, path, options.params), {
|
|
144
|
+
method: options.method || (options.body ? "POST" : "GET"),
|
|
145
|
+
headers: {
|
|
146
|
+
Authorization: `Bearer ${token}`,
|
|
147
|
+
...options.body ? { "Content-Type": "application/json" } : {}
|
|
148
|
+
},
|
|
149
|
+
...options.body ? { body: JSON.stringify(options.body) } : {}
|
|
150
|
+
});
|
|
151
|
+
return response.json().catch(() => null);
|
|
152
|
+
};
|
|
153
|
+
return { buildURL, request };
|
|
145
154
|
}
|
|
155
|
+
function readGraphID(label, result) {
|
|
156
|
+
if (result?.error) {
|
|
157
|
+
console.error(`[naystack] ${label} failed: ${result.error.message}`);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
return result?.id || null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/socials/instagram/utils.ts
|
|
164
|
+
var client = createGraphClient("https://graph.instagram.com/v23.0");
|
|
165
|
+
var getInstagramData = client.request;
|
|
146
166
|
|
|
147
167
|
// src/socials/instagram/getters.ts
|
|
148
168
|
var getInstagramUser = (token, id, fields) => {
|
|
149
169
|
return getInstagramData(token, id || "me", {
|
|
150
|
-
|
|
170
|
+
params: {
|
|
171
|
+
fields: fields ? fields.join(",") : "username,followers_count,media_count"
|
|
172
|
+
}
|
|
151
173
|
});
|
|
152
174
|
};
|
|
175
|
+
var getInstagramContainerStatus = async (token, id) => {
|
|
176
|
+
const result = await getInstagramData(token, id, { params: { fields: "status_code,status" } });
|
|
177
|
+
if (!result?.status_code) return null;
|
|
178
|
+
return {
|
|
179
|
+
status: result.status_code,
|
|
180
|
+
error: result.status_code === "ERROR" ? result.status : void 0
|
|
181
|
+
};
|
|
182
|
+
};
|
|
153
183
|
|
|
154
|
-
// src/socials/meta
|
|
184
|
+
// src/socials/meta/container.ts
|
|
185
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
186
|
+
async function waitForContainer(getState, { intervalMS = 5e3, timeoutMS = 3e5 } = {}) {
|
|
187
|
+
const deadline = Date.now() + timeoutMS;
|
|
188
|
+
let state = await getState();
|
|
189
|
+
if (!state) {
|
|
190
|
+
await sleep(2e3);
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
while (state?.status === "IN_PROGRESS" && Date.now() < deadline) {
|
|
194
|
+
await sleep(intervalMS);
|
|
195
|
+
state = await getState();
|
|
196
|
+
}
|
|
197
|
+
return state;
|
|
198
|
+
}
|
|
199
|
+
function createPublisher(platform) {
|
|
200
|
+
const isReady = async (token, id, label, wait) => {
|
|
201
|
+
const state = await waitForContainer(
|
|
202
|
+
() => platform.getStatus(token, id),
|
|
203
|
+
wait
|
|
204
|
+
);
|
|
205
|
+
if (state && state.status !== "FINISHED" && state.status !== "PUBLISHED") {
|
|
206
|
+
console.error(
|
|
207
|
+
`[naystack] ${platform.name} ${label} ${id} is ${state.status}${state.error ? `: ${state.error}` : ""}`
|
|
208
|
+
);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
};
|
|
213
|
+
return {
|
|
214
|
+
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
215
|
+
publish: async (token, params, wait) => {
|
|
216
|
+
const containerID = await platform.createContainer(token, params);
|
|
217
|
+
if (!containerID) return null;
|
|
218
|
+
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
219
|
+
return platform.publish(token, containerID);
|
|
220
|
+
},
|
|
221
|
+
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
222
|
+
createChildren: async (token, items, wait) => {
|
|
223
|
+
const children = [];
|
|
224
|
+
for (const item of items) {
|
|
225
|
+
const childID = await platform.createContainer(token, {
|
|
226
|
+
...item,
|
|
227
|
+
is_carousel_item: true
|
|
228
|
+
});
|
|
229
|
+
if (!childID) return null;
|
|
230
|
+
if (!await isReady(token, childID, "carousel item", wait))
|
|
231
|
+
return null;
|
|
232
|
+
children.push(childID);
|
|
233
|
+
}
|
|
234
|
+
return children;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/socials/instagram/setters.ts
|
|
240
|
+
var publisher = createPublisher({
|
|
241
|
+
name: "Instagram",
|
|
242
|
+
getStatus: getInstagramContainerStatus,
|
|
243
|
+
createContainer: async (token, params) => readGraphID(
|
|
244
|
+
"Instagram media container",
|
|
245
|
+
await getInstagramData(token, "me/media", {
|
|
246
|
+
params,
|
|
247
|
+
method: "POST"
|
|
248
|
+
})
|
|
249
|
+
),
|
|
250
|
+
publish: async (token, creationID) => readGraphID(
|
|
251
|
+
"Instagram publish",
|
|
252
|
+
await getInstagramData(token, "me/media_publish", {
|
|
253
|
+
params: { creation_id: creationID },
|
|
254
|
+
method: "POST"
|
|
255
|
+
})
|
|
256
|
+
)
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// src/socials/meta/webhook.ts
|
|
155
260
|
var import_server2 = require("next/server");
|
|
156
261
|
|
|
262
|
+
// src/socials/threads/utils.ts
|
|
263
|
+
var client2 = createGraphClient("https://graph.threads.net/v1.0");
|
|
264
|
+
var getThreadsData = client2.request;
|
|
265
|
+
|
|
266
|
+
// src/socials/threads/getters.ts
|
|
267
|
+
var getThreadsContainerStatus = async (token, id) => {
|
|
268
|
+
const result = await getThreadsData(token, id, { params: { fields: "status,error_message" } });
|
|
269
|
+
if (!result?.status) return null;
|
|
270
|
+
return { status: result.status, error: result.error_message };
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// src/socials/threads/setters.ts
|
|
274
|
+
var publisher2 = createPublisher({
|
|
275
|
+
name: "Threads",
|
|
276
|
+
getStatus: getThreadsContainerStatus,
|
|
277
|
+
createContainer: async (token, params) => readGraphID(
|
|
278
|
+
"Threads container",
|
|
279
|
+
await getThreadsData(token, "me/threads", {
|
|
280
|
+
params,
|
|
281
|
+
method: "POST"
|
|
282
|
+
})
|
|
283
|
+
),
|
|
284
|
+
publish: async (token, creationID) => readGraphID(
|
|
285
|
+
"Threads publish",
|
|
286
|
+
await getThreadsData(token, "me/threads_publish", {
|
|
287
|
+
params: { creation_id: creationID },
|
|
288
|
+
method: "POST"
|
|
289
|
+
})
|
|
290
|
+
)
|
|
291
|
+
});
|
|
292
|
+
|
|
157
293
|
// src/auth/instagram/route.ts
|
|
158
294
|
var getInstagramRoute = ({
|
|
159
295
|
redirectURL,
|
|
160
296
|
errorRedirectURL,
|
|
161
|
-
onUser
|
|
297
|
+
onUser,
|
|
298
|
+
scopes
|
|
162
299
|
}) => {
|
|
163
300
|
const handleError = (message) => import_server3.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
|
|
164
301
|
return async (req) => {
|
|
@@ -168,7 +305,10 @@ var getInstagramRoute = ({
|
|
|
168
305
|
if (error) return handleError(error);
|
|
169
306
|
if (!accessCode) {
|
|
170
307
|
if (!stateToken) return handleError("Invalid request");
|
|
171
|
-
return import_server3.NextResponse.redirect(
|
|
308
|
+
return import_server3.NextResponse.redirect(
|
|
309
|
+
getInstagramAuthorizationURL(stateToken, scopes),
|
|
310
|
+
302
|
|
311
|
+
);
|
|
172
312
|
}
|
|
173
313
|
if (!stateToken) return handleError("Invalid request");
|
|
174
314
|
const instagramData = await getLongLivedToken(
|
|
@@ -2,12 +2,14 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import { SetupInstagramAuthOptions } from './index.mjs';
|
|
3
3
|
import './utils.mjs';
|
|
4
4
|
import '../../socials/instagram/types.mjs';
|
|
5
|
+
import '../../socials/meta/container.mjs';
|
|
6
|
+
import '../../socials/meta/types.mjs';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Returns the GET route handler for Instagram OAuth callback.
|
|
8
10
|
* @param options - SetupInstagramAuthOptions (onUser, redirect URLs)
|
|
9
11
|
* @returns Async route handler for the OAuth callback
|
|
10
12
|
*/
|
|
11
|
-
declare const getInstagramRoute: ({ redirectURL, errorRedirectURL, onUser, }: SetupInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
13
|
+
declare const getInstagramRoute: ({ redirectURL, errorRedirectURL, onUser, scopes, }: SetupInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
12
14
|
|
|
13
15
|
export { getInstagramRoute };
|
|
@@ -2,12 +2,14 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import { SetupInstagramAuthOptions } from './index.js';
|
|
3
3
|
import './utils.js';
|
|
4
4
|
import '../../socials/instagram/types.js';
|
|
5
|
+
import '../../socials/meta/container.js';
|
|
6
|
+
import '../../socials/meta/types.js';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Returns the GET route handler for Instagram OAuth callback.
|
|
8
10
|
* @param options - SetupInstagramAuthOptions (onUser, redirect URLs)
|
|
9
11
|
* @returns Async route handler for the OAuth callback
|
|
10
12
|
*/
|
|
11
|
-
declare const getInstagramRoute: ({ redirectURL, errorRedirectURL, onUser, }: SetupInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
13
|
+
declare const getInstagramRoute: ({ redirectURL, errorRedirectURL, onUser, scopes, }: SetupInstagramAuthOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
12
14
|
|
|
13
15
|
export { getInstagramRoute };
|
|
@@ -101,40 +101,177 @@ async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
104
|
+
var getInstagramAuthorizationURL = (token, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
105
105
|
"INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
|
|
106
|
-
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope
|
|
106
|
+
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}#weblink`;
|
|
107
107
|
|
|
108
|
-
// src/socials/
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
method: postData ? "POST" : "GET",
|
|
115
|
-
body: JSON.stringify(postData),
|
|
116
|
-
headers: {
|
|
117
|
-
Authorization: `Bearer ${token}`,
|
|
118
|
-
"Content-Type": "application/json"
|
|
108
|
+
// src/socials/meta/request.ts
|
|
109
|
+
function createGraphClient(baseURL) {
|
|
110
|
+
const buildURL = (token, path, params = {}) => {
|
|
111
|
+
const search = new URLSearchParams();
|
|
112
|
+
for (const [key, value] of Object.entries(params)) {
|
|
113
|
+
if (value !== void 0) search.set(key, String(value));
|
|
119
114
|
}
|
|
120
|
-
|
|
115
|
+
search.set("access_token", token);
|
|
116
|
+
return `${baseURL}/${path}?${search.toString()}`;
|
|
117
|
+
};
|
|
118
|
+
const request = async (token, path, options = {}) => {
|
|
119
|
+
const response = await fetch(buildURL(token, path, options.params), {
|
|
120
|
+
method: options.method || (options.body ? "POST" : "GET"),
|
|
121
|
+
headers: {
|
|
122
|
+
Authorization: `Bearer ${token}`,
|
|
123
|
+
...options.body ? { "Content-Type": "application/json" } : {}
|
|
124
|
+
},
|
|
125
|
+
...options.body ? { body: JSON.stringify(options.body) } : {}
|
|
126
|
+
});
|
|
127
|
+
return response.json().catch(() => null);
|
|
128
|
+
};
|
|
129
|
+
return { buildURL, request };
|
|
121
130
|
}
|
|
131
|
+
function readGraphID(label, result) {
|
|
132
|
+
if (result?.error) {
|
|
133
|
+
console.error(`[naystack] ${label} failed: ${result.error.message}`);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return result?.id || null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/socials/instagram/utils.ts
|
|
140
|
+
var client = createGraphClient("https://graph.instagram.com/v23.0");
|
|
141
|
+
var getInstagramData = client.request;
|
|
122
142
|
|
|
123
143
|
// src/socials/instagram/getters.ts
|
|
124
144
|
var getInstagramUser = (token, id, fields) => {
|
|
125
145
|
return getInstagramData(token, id || "me", {
|
|
126
|
-
|
|
146
|
+
params: {
|
|
147
|
+
fields: fields ? fields.join(",") : "username,followers_count,media_count"
|
|
148
|
+
}
|
|
127
149
|
});
|
|
128
150
|
};
|
|
151
|
+
var getInstagramContainerStatus = async (token, id) => {
|
|
152
|
+
const result = await getInstagramData(token, id, { params: { fields: "status_code,status" } });
|
|
153
|
+
if (!result?.status_code) return null;
|
|
154
|
+
return {
|
|
155
|
+
status: result.status_code,
|
|
156
|
+
error: result.status_code === "ERROR" ? result.status : void 0
|
|
157
|
+
};
|
|
158
|
+
};
|
|
129
159
|
|
|
130
|
-
// src/socials/meta
|
|
160
|
+
// src/socials/meta/container.ts
|
|
161
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
162
|
+
async function waitForContainer(getState, { intervalMS = 5e3, timeoutMS = 3e5 } = {}) {
|
|
163
|
+
const deadline = Date.now() + timeoutMS;
|
|
164
|
+
let state = await getState();
|
|
165
|
+
if (!state) {
|
|
166
|
+
await sleep(2e3);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
while (state?.status === "IN_PROGRESS" && Date.now() < deadline) {
|
|
170
|
+
await sleep(intervalMS);
|
|
171
|
+
state = await getState();
|
|
172
|
+
}
|
|
173
|
+
return state;
|
|
174
|
+
}
|
|
175
|
+
function createPublisher(platform) {
|
|
176
|
+
const isReady = async (token, id, label, wait) => {
|
|
177
|
+
const state = await waitForContainer(
|
|
178
|
+
() => platform.getStatus(token, id),
|
|
179
|
+
wait
|
|
180
|
+
);
|
|
181
|
+
if (state && state.status !== "FINISHED" && state.status !== "PUBLISHED") {
|
|
182
|
+
console.error(
|
|
183
|
+
`[naystack] ${platform.name} ${label} ${id} is ${state.status}${state.error ? `: ${state.error}` : ""}`
|
|
184
|
+
);
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return true;
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
/** Creates a container, waits for it to finish processing, then publishes it. */
|
|
191
|
+
publish: async (token, params, wait) => {
|
|
192
|
+
const containerID = await platform.createContainer(token, params);
|
|
193
|
+
if (!containerID) return null;
|
|
194
|
+
if (!await isReady(token, containerID, "container", wait)) return null;
|
|
195
|
+
return platform.publish(token, containerID);
|
|
196
|
+
},
|
|
197
|
+
/** Creates and awaits every carousel child, resolving to their ids — or `null` if any failed. */
|
|
198
|
+
createChildren: async (token, items, wait) => {
|
|
199
|
+
const children = [];
|
|
200
|
+
for (const item of items) {
|
|
201
|
+
const childID = await platform.createContainer(token, {
|
|
202
|
+
...item,
|
|
203
|
+
is_carousel_item: true
|
|
204
|
+
});
|
|
205
|
+
if (!childID) return null;
|
|
206
|
+
if (!await isReady(token, childID, "carousel item", wait))
|
|
207
|
+
return null;
|
|
208
|
+
children.push(childID);
|
|
209
|
+
}
|
|
210
|
+
return children;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/socials/instagram/setters.ts
|
|
216
|
+
var publisher = createPublisher({
|
|
217
|
+
name: "Instagram",
|
|
218
|
+
getStatus: getInstagramContainerStatus,
|
|
219
|
+
createContainer: async (token, params) => readGraphID(
|
|
220
|
+
"Instagram media container",
|
|
221
|
+
await getInstagramData(token, "me/media", {
|
|
222
|
+
params,
|
|
223
|
+
method: "POST"
|
|
224
|
+
})
|
|
225
|
+
),
|
|
226
|
+
publish: async (token, creationID) => readGraphID(
|
|
227
|
+
"Instagram publish",
|
|
228
|
+
await getInstagramData(token, "me/media_publish", {
|
|
229
|
+
params: { creation_id: creationID },
|
|
230
|
+
method: "POST"
|
|
231
|
+
})
|
|
232
|
+
)
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// src/socials/meta/webhook.ts
|
|
131
236
|
import { NextResponse as NextResponse2 } from "next/server";
|
|
132
237
|
|
|
238
|
+
// src/socials/threads/utils.ts
|
|
239
|
+
var client2 = createGraphClient("https://graph.threads.net/v1.0");
|
|
240
|
+
var getThreadsData = client2.request;
|
|
241
|
+
|
|
242
|
+
// src/socials/threads/getters.ts
|
|
243
|
+
var getThreadsContainerStatus = async (token, id) => {
|
|
244
|
+
const result = await getThreadsData(token, id, { params: { fields: "status,error_message" } });
|
|
245
|
+
if (!result?.status) return null;
|
|
246
|
+
return { status: result.status, error: result.error_message };
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/socials/threads/setters.ts
|
|
250
|
+
var publisher2 = createPublisher({
|
|
251
|
+
name: "Threads",
|
|
252
|
+
getStatus: getThreadsContainerStatus,
|
|
253
|
+
createContainer: async (token, params) => readGraphID(
|
|
254
|
+
"Threads container",
|
|
255
|
+
await getThreadsData(token, "me/threads", {
|
|
256
|
+
params,
|
|
257
|
+
method: "POST"
|
|
258
|
+
})
|
|
259
|
+
),
|
|
260
|
+
publish: async (token, creationID) => readGraphID(
|
|
261
|
+
"Threads publish",
|
|
262
|
+
await getThreadsData(token, "me/threads_publish", {
|
|
263
|
+
params: { creation_id: creationID },
|
|
264
|
+
method: "POST"
|
|
265
|
+
})
|
|
266
|
+
)
|
|
267
|
+
});
|
|
268
|
+
|
|
133
269
|
// src/auth/instagram/route.ts
|
|
134
270
|
var getInstagramRoute = ({
|
|
135
271
|
redirectURL,
|
|
136
272
|
errorRedirectURL,
|
|
137
|
-
onUser
|
|
273
|
+
onUser,
|
|
274
|
+
scopes
|
|
138
275
|
}) => {
|
|
139
276
|
const handleError = (message) => NextResponse3.redirect(`${errorRedirectURL}?error=${message}`);
|
|
140
277
|
return async (req) => {
|
|
@@ -144,7 +281,10 @@ var getInstagramRoute = ({
|
|
|
144
281
|
if (error) return handleError(error);
|
|
145
282
|
if (!accessCode) {
|
|
146
283
|
if (!stateToken) return handleError("Invalid request");
|
|
147
|
-
return NextResponse3.redirect(
|
|
284
|
+
return NextResponse3.redirect(
|
|
285
|
+
getInstagramAuthorizationURL(stateToken, scopes),
|
|
286
|
+
302
|
|
287
|
+
);
|
|
148
288
|
}
|
|
149
289
|
if (!stateToken) return handleError("Invalid request");
|
|
150
290
|
const instagramData = await getLongLivedToken(
|
|
@@ -112,9 +112,9 @@ async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
115
|
+
var getInstagramAuthorizationURL = (token, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
116
116
|
"INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
|
|
117
|
-
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope
|
|
117
|
+
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}#weblink`;
|
|
118
118
|
// Annotate the CommonJS export names for ESM import in node:
|
|
119
119
|
0 && (module.exports = {
|
|
120
120
|
getInstagramAuthorizationURL,
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions requestable during Instagram Login OAuth. `instagram_business_basic`
|
|
3
|
+
* is enough to read a profile; publishing needs `instagram_business_content_publish`.
|
|
4
|
+
*
|
|
5
|
+
* Widening the scopes only affects users who authorize afterwards — tokens already
|
|
6
|
+
* stored keep the permissions they were granted, so existing users must reconnect.
|
|
7
|
+
*
|
|
8
|
+
* @category Auth
|
|
9
|
+
*/
|
|
10
|
+
type InstagramScope = "instagram_business_basic" | "instagram_business_content_publish" | "instagram_business_manage_messages" | "instagram_business_manage_comments" | "instagram_business_manage_insights";
|
|
1
11
|
/**
|
|
2
12
|
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
3
13
|
* @param token - Current long-lived access token
|
|
@@ -29,6 +39,7 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
|
|
|
29
39
|
* simply built on the server instead of shipped in the client bundle.
|
|
30
40
|
*
|
|
31
41
|
* @param token - The state token to embed in the authorization URL (typically the user's session or access token).
|
|
42
|
+
* @param scopes - Permissions to request. Default: `["instagram_business_basic"]`.
|
|
32
43
|
* @returns The full Instagram OAuth authorization URL.
|
|
33
44
|
*
|
|
34
45
|
* @example
|
|
@@ -41,6 +52,6 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
|
|
|
41
52
|
*
|
|
42
53
|
* @category Auth
|
|
43
54
|
*/
|
|
44
|
-
declare const getInstagramAuthorizationURL: (token: string) => string;
|
|
55
|
+
declare const getInstagramAuthorizationURL: (token: string, scopes?: InstagramScope[]) => string;
|
|
45
56
|
|
|
46
|
-
export { getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|
|
57
|
+
export { type InstagramScope, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions requestable during Instagram Login OAuth. `instagram_business_basic`
|
|
3
|
+
* is enough to read a profile; publishing needs `instagram_business_content_publish`.
|
|
4
|
+
*
|
|
5
|
+
* Widening the scopes only affects users who authorize afterwards — tokens already
|
|
6
|
+
* stored keep the permissions they were granted, so existing users must reconnect.
|
|
7
|
+
*
|
|
8
|
+
* @category Auth
|
|
9
|
+
*/
|
|
10
|
+
type InstagramScope = "instagram_business_basic" | "instagram_business_content_publish" | "instagram_business_manage_messages" | "instagram_business_manage_comments" | "instagram_business_manage_insights";
|
|
1
11
|
/**
|
|
2
12
|
* Exchanges a long-lived Instagram token for a refreshed token.
|
|
3
13
|
* @param token - Current long-lived access token
|
|
@@ -29,6 +39,7 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
|
|
|
29
39
|
* simply built on the server instead of shipped in the client bundle.
|
|
30
40
|
*
|
|
31
41
|
* @param token - The state token to embed in the authorization URL (typically the user's session or access token).
|
|
42
|
+
* @param scopes - Permissions to request. Default: `["instagram_business_basic"]`.
|
|
32
43
|
* @returns The full Instagram OAuth authorization URL.
|
|
33
44
|
*
|
|
34
45
|
* @example
|
|
@@ -41,6 +52,6 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
|
|
|
41
52
|
*
|
|
42
53
|
* @category Auth
|
|
43
54
|
*/
|
|
44
|
-
declare const getInstagramAuthorizationURL: (token: string) => string;
|
|
55
|
+
declare const getInstagramAuthorizationURL: (token: string, scopes?: InstagramScope[]) => string;
|
|
45
56
|
|
|
46
|
-
export { getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|
|
57
|
+
export { type InstagramScope, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
|
|
@@ -84,9 +84,9 @@ async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
87
|
+
var getInstagramAuthorizationURL = (token, scopes = ["instagram_business_basic"]) => `https://www.instagram.com/oauth/authorize/?client_id=${getEnv(
|
|
88
88
|
"INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
|
|
89
|
-
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope
|
|
89
|
+
)}&response_type=code&enable_fb_login=0&force_authentication=1&scope=${scopes.join(",")}&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}#weblink`;
|
|
90
90
|
export {
|
|
91
91
|
getInstagramAuthorizationURL,
|
|
92
92
|
getLongLivedToken,
|
package/dist/file/index.cjs.js
CHANGED
|
@@ -165,14 +165,15 @@ var getDownloadURL = (keys) => {
|
|
|
165
165
|
};
|
|
166
166
|
var uploadFile = async (keys, {
|
|
167
167
|
url,
|
|
168
|
-
blob
|
|
168
|
+
blob,
|
|
169
|
+
put
|
|
169
170
|
}) => {
|
|
170
171
|
if (!checkClient(client)) return;
|
|
171
172
|
if (!blob && !url) return null;
|
|
172
173
|
const fileBlob = blob || await fetch(url).then((file) => file.blob());
|
|
173
174
|
if (fileBlob) {
|
|
174
175
|
const key = getKey(keys);
|
|
175
|
-
await uploadBlob(fileBlob, key);
|
|
176
|
+
await uploadBlob(fileBlob, key, put);
|
|
176
177
|
return getDownloadURL(key);
|
|
177
178
|
}
|
|
178
179
|
return null;
|
|
@@ -199,7 +200,7 @@ function checkClient(client2) {
|
|
|
199
200
|
if (!client2) throw new Error("Client does not exist");
|
|
200
201
|
return true;
|
|
201
202
|
}
|
|
202
|
-
var uploadBlob = async (file, key) => {
|
|
203
|
+
var uploadBlob = async (file, key, overrides) => {
|
|
203
204
|
if (!checkClient(client)) return;
|
|
204
205
|
const fileBuffer = await file.arrayBuffer();
|
|
205
206
|
return client.send(
|
|
@@ -209,7 +210,8 @@ var uploadBlob = async (file, key) => {
|
|
|
209
210
|
ACL: "public-read",
|
|
210
211
|
Body: Buffer.from(fileBuffer),
|
|
211
212
|
ContentType: file.type,
|
|
212
|
-
ContentLength: file.size
|
|
213
|
+
ContentLength: file.size,
|
|
214
|
+
...overrides
|
|
213
215
|
})
|
|
214
216
|
);
|
|
215
217
|
};
|
|
@@ -232,8 +234,9 @@ var getFileUploadPutRoute = (options) => async (req) => {
|
|
|
232
234
|
const fileKey = options.getKey ? await options.getKey(inputData) : (0, import_uuid.v4)();
|
|
233
235
|
const url = getDownloadURL(fileKey);
|
|
234
236
|
const blob = options.processFile ? await options.processFile(file, inputData) : file;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
const put = options.putOptions?.(inputData);
|
|
238
|
+
if (async) (0, import_functions.waitUntil)(uploadBlob(blob, fileKey, put));
|
|
239
|
+
else await uploadBlob(blob, fileKey, put);
|
|
237
240
|
const onUploadResponse = await options.onUpload({
|
|
238
241
|
...inputData,
|
|
239
242
|
url
|
package/dist/file/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { setupFileUpload } from './setup.mjs';
|
|
2
|
-
export { deleteFile, getDownloadURL, getUploadURL, uploadFile } from './utils.mjs';
|
|
2
|
+
export { PutOverrides, deleteFile, getDownloadURL, getUploadURL, uploadFile } from './utils.mjs';
|
|
3
3
|
import 'next/server';
|
|
4
4
|
import '@aws-sdk/client-s3';
|
package/dist/file/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { setupFileUpload } from './setup.js';
|
|
2
|
-
export { deleteFile, getDownloadURL, getUploadURL, uploadFile } from './utils.js';
|
|
2
|
+
export { PutOverrides, deleteFile, getDownloadURL, getUploadURL, uploadFile } from './utils.js';
|
|
3
3
|
import 'next/server';
|
|
4
4
|
import '@aws-sdk/client-s3';
|
package/dist/file/index.esm.js
CHANGED
|
@@ -139,14 +139,15 @@ var getDownloadURL = (keys) => {
|
|
|
139
139
|
};
|
|
140
140
|
var uploadFile = async (keys, {
|
|
141
141
|
url,
|
|
142
|
-
blob
|
|
142
|
+
blob,
|
|
143
|
+
put
|
|
143
144
|
}) => {
|
|
144
145
|
if (!checkClient(client)) return;
|
|
145
146
|
if (!blob && !url) return null;
|
|
146
147
|
const fileBlob = blob || await fetch(url).then((file) => file.blob());
|
|
147
148
|
if (fileBlob) {
|
|
148
149
|
const key = getKey(keys);
|
|
149
|
-
await uploadBlob(fileBlob, key);
|
|
150
|
+
await uploadBlob(fileBlob, key, put);
|
|
150
151
|
return getDownloadURL(key);
|
|
151
152
|
}
|
|
152
153
|
return null;
|
|
@@ -173,7 +174,7 @@ function checkClient(client2) {
|
|
|
173
174
|
if (!client2) throw new Error("Client does not exist");
|
|
174
175
|
return true;
|
|
175
176
|
}
|
|
176
|
-
var uploadBlob = async (file, key) => {
|
|
177
|
+
var uploadBlob = async (file, key, overrides) => {
|
|
177
178
|
if (!checkClient(client)) return;
|
|
178
179
|
const fileBuffer = await file.arrayBuffer();
|
|
179
180
|
return client.send(
|
|
@@ -183,7 +184,8 @@ var uploadBlob = async (file, key) => {
|
|
|
183
184
|
ACL: "public-read",
|
|
184
185
|
Body: Buffer.from(fileBuffer),
|
|
185
186
|
ContentType: file.type,
|
|
186
|
-
ContentLength: file.size
|
|
187
|
+
ContentLength: file.size,
|
|
188
|
+
...overrides
|
|
187
189
|
})
|
|
188
190
|
);
|
|
189
191
|
};
|
|
@@ -206,8 +208,9 @@ var getFileUploadPutRoute = (options) => async (req) => {
|
|
|
206
208
|
const fileKey = options.getKey ? await options.getKey(inputData) : v4();
|
|
207
209
|
const url = getDownloadURL(fileKey);
|
|
208
210
|
const blob = options.processFile ? await options.processFile(file, inputData) : file;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
const put = options.putOptions?.(inputData);
|
|
212
|
+
if (async) waitUntil(uploadBlob(blob, fileKey, put));
|
|
213
|
+
else await uploadBlob(blob, fileKey, put);
|
|
211
214
|
const onUploadResponse = await options.onUpload({
|
|
212
215
|
...inputData,
|
|
213
216
|
url
|