n8n-nodes-pinterest 0.1.3 → 0.1.5
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.
|
@@ -6,15 +6,18 @@ function randomCsrf() {
|
|
|
6
6
|
const seed = `${Date.now()}${Math.floor(Math.random() * 100000)}`;
|
|
7
7
|
return Buffer.from(seed).toString('base64');
|
|
8
8
|
}
|
|
9
|
-
function buildCommonHeaders(csrf) {
|
|
10
|
-
|
|
9
|
+
function buildCommonHeaders(csrf, strict = false) {
|
|
10
|
+
const base = {
|
|
11
11
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0',
|
|
12
12
|
'x-pinterest-pws-handler': 'www/[username].js',
|
|
13
13
|
'x-CSRFToken': csrf,
|
|
14
|
-
'Accept-Language': 'en-US,en;q=0.9',
|
|
15
|
-
Accept: 'application/json, text/plain, */*',
|
|
16
|
-
'X-Requested-With': 'XMLHttpRequest',
|
|
17
14
|
};
|
|
15
|
+
if (!strict) {
|
|
16
|
+
base['Accept-Language'] = 'en-US,en;q=0.9';
|
|
17
|
+
base['Accept'] = 'application/json, text/plain, */*';
|
|
18
|
+
base['X-Requested-With'] = 'XMLHttpRequest';
|
|
19
|
+
}
|
|
20
|
+
return base;
|
|
18
21
|
}
|
|
19
22
|
function buildCookieHeader(sess, csrf) {
|
|
20
23
|
return `_pinterest_sess=${sess}; csrftoken=${csrf};`;
|
|
@@ -135,6 +138,22 @@ class PinterestCookie {
|
|
|
135
138
|
},
|
|
136
139
|
],
|
|
137
140
|
},
|
|
141
|
+
{
|
|
142
|
+
displayName: 'Strict Plugin Mode',
|
|
143
|
+
name: 'strictPluginMode',
|
|
144
|
+
type: 'boolean',
|
|
145
|
+
default: false,
|
|
146
|
+
description: 'Force exact request shape and headers used by the referenced plugin. Disables retries/fallbacks for 1:1 parity while debugging.',
|
|
147
|
+
displayOptions: { show: { resource: ['pin'], operation: ['create'] } },
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
displayName: 'Debug: Return Raw Response',
|
|
151
|
+
name: 'debugRaw',
|
|
152
|
+
type: 'boolean',
|
|
153
|
+
default: false,
|
|
154
|
+
description: 'When enabled, include the full server response body and request payload in the output for troubleshooting. The node will not throw if Continue On Fail is enabled.',
|
|
155
|
+
displayOptions: { show: { resource: ['pin'], operation: ['create'] } },
|
|
156
|
+
},
|
|
138
157
|
// Board ops
|
|
139
158
|
{
|
|
140
159
|
displayName: 'Operation',
|
|
@@ -292,6 +311,8 @@ class PinterestCookie {
|
|
|
292
311
|
const title = this.getNodeParameter('title', i, '');
|
|
293
312
|
const description = this.getNodeParameter('description', i, '');
|
|
294
313
|
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
314
|
+
const debugRaw = this.getNodeParameter('debugRaw', i, false);
|
|
315
|
+
const strictPluginMode = this.getNodeParameter('strictPluginMode', i, false);
|
|
295
316
|
const binary = (_c = items[i].binary) === null || _c === void 0 ? void 0 : _c[binaryProperty];
|
|
296
317
|
if (!binary)
|
|
297
318
|
throw new Error(`Binary property "${binaryProperty}" is missing on item ${i}`);
|
|
@@ -303,7 +324,16 @@ class PinterestCookie {
|
|
|
303
324
|
source_url: '/pin-builder/',
|
|
304
325
|
data: '{"options":{"type":"pinimage"},"context":{}}',
|
|
305
326
|
},
|
|
306
|
-
headers:
|
|
327
|
+
headers: strictPluginMode
|
|
328
|
+
? { ...buildCommonHeaders(csrf, true), Cookie: cookieHeader }
|
|
329
|
+
: {
|
|
330
|
+
...baseHeaders,
|
|
331
|
+
Cookie: cookieHeader,
|
|
332
|
+
Referer: `${base}/pin-builder/`,
|
|
333
|
+
Origin: base,
|
|
334
|
+
'X-Pinterest-Source-Url': '/pin-builder/',
|
|
335
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
336
|
+
},
|
|
307
337
|
proxy: proxy || undefined,
|
|
308
338
|
}));
|
|
309
339
|
const vip = JSON.parse(vipResp);
|
|
@@ -332,9 +362,23 @@ class PinterestCookie {
|
|
|
332
362
|
headers: {
|
|
333
363
|
Accept: '*/*',
|
|
334
364
|
'Accept-Encoding': 'gzip',
|
|
335
|
-
'User-Agent':
|
|
336
|
-
|
|
337
|
-
|
|
365
|
+
'User-Agent': strictPluginMode
|
|
366
|
+
? 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
|
|
367
|
+
: baseHeaders['User-Agent'],
|
|
368
|
+
Origin: strictPluginMode ? 'https://www.pinterest.com' : base,
|
|
369
|
+
Referer: strictPluginMode ? 'https://www.pinterest.com' : `${base}/pin-builder/`,
|
|
370
|
+
...(strictPluginMode
|
|
371
|
+
? {
|
|
372
|
+
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
|
|
373
|
+
'sec-ch-ua-mobile': '?0',
|
|
374
|
+
'sec-ch-ua-full': '?1',
|
|
375
|
+
'sec-ch-ua-platform': '"Windows"',
|
|
376
|
+
'Sec-Fetch-Dest': 'empty',
|
|
377
|
+
'Sec-Fetch-Mode': 'cors',
|
|
378
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
379
|
+
Connection: 'keep-alive',
|
|
380
|
+
}
|
|
381
|
+
: {}),
|
|
338
382
|
},
|
|
339
383
|
formData,
|
|
340
384
|
proxy: proxy || undefined,
|
|
@@ -350,19 +394,24 @@ class PinterestCookie {
|
|
|
350
394
|
const imageUrl = `https://i.pinimg.com/736x/${etag[0]}${etag[1]}/${etag[2]}${etag[3]}/${etag[4]}${etag[5]}/${etag}.jpg`;
|
|
351
395
|
// Step 3: create pin
|
|
352
396
|
const attachLink = (additionalFields.attachLink !== undefined) ? Boolean(additionalFields.attachLink) : true;
|
|
397
|
+
// Build payload
|
|
353
398
|
const sendData = {
|
|
354
399
|
options: {
|
|
355
|
-
board_id: boardId,
|
|
400
|
+
board_id: String(boardId),
|
|
356
401
|
field_set_key: 'create_success',
|
|
357
402
|
skip_pin_create_log: true,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
403
|
+
description: String(description || ''),
|
|
404
|
+
alt_text: String(additionalFields.alt_text || ''),
|
|
405
|
+
// Strict mode: always include link key
|
|
406
|
+
link: String(additionalFields.link || ''),
|
|
407
|
+
// Non-strict: allow disabling link entirely
|
|
408
|
+
...(strictPluginMode ? {} : (!attachLink ? { link: '' } : {})),
|
|
409
|
+
title: String(title || ''),
|
|
410
|
+
image_url: String(imageUrl),
|
|
363
411
|
method: 'uploaded',
|
|
364
412
|
upload_metric: { source: 'pinner_upload_standalone' },
|
|
365
|
-
|
|
413
|
+
user_mention_tags: [],
|
|
414
|
+
no_fetch_context_on_resource: false,
|
|
366
415
|
},
|
|
367
416
|
context: {},
|
|
368
417
|
};
|
|
@@ -375,7 +424,16 @@ class PinterestCookie {
|
|
|
375
424
|
source_url: '/pin-builder/',
|
|
376
425
|
data: JSON.stringify(payload),
|
|
377
426
|
},
|
|
378
|
-
headers:
|
|
427
|
+
headers: strictPluginMode
|
|
428
|
+
? { ...buildCommonHeaders(csrf, true), Cookie: cookieHeader }
|
|
429
|
+
: {
|
|
430
|
+
...baseHeaders,
|
|
431
|
+
Cookie: cookieHeader,
|
|
432
|
+
Referer: `${base}/pin-builder/`,
|
|
433
|
+
Origin: base,
|
|
434
|
+
'X-Pinterest-Source-Url': '/pin-builder/',
|
|
435
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
436
|
+
},
|
|
379
437
|
proxy: proxy || undefined,
|
|
380
438
|
// Get body even on 4xx
|
|
381
439
|
simple: false,
|
|
@@ -392,39 +450,50 @@ class PinterestCookie {
|
|
|
392
450
|
const id = String(pinData.id || '');
|
|
393
451
|
const msg = createdRes.message || ((_a = createdRes.error) === null || _a === void 0 ? void 0 : _a.message) || '';
|
|
394
452
|
const msgDetail = ((_b = createdRes.error) === null || _b === void 0 ? void 0 : _b.message_detail) || '';
|
|
395
|
-
return { ok: Boolean(id), id, msg: String(msg || msgDetail || ''), body };
|
|
453
|
+
return { ok: Boolean(id), id, msg: String(msg || msgDetail || ''), body, payload };
|
|
396
454
|
};
|
|
397
|
-
// Try strategies progressively to avoid generic "Invalid parameters"
|
|
398
|
-
const strategies = [];
|
|
399
|
-
// 1) As built
|
|
400
|
-
strategies.push(JSON.parse(JSON.stringify(sendData)));
|
|
401
|
-
// 2) Without link
|
|
402
|
-
const s2 = JSON.parse(JSON.stringify(sendData));
|
|
403
|
-
if (s2.options)
|
|
404
|
-
delete s2.options.link;
|
|
405
|
-
strategies.push(s2);
|
|
406
|
-
// 3) Minimal fields only
|
|
407
|
-
strategies.push({
|
|
408
|
-
options: {
|
|
409
|
-
board_id: boardId,
|
|
410
|
-
field_set_key: 'create_success',
|
|
411
|
-
image_url: imageUrl,
|
|
412
|
-
method: 'uploaded',
|
|
413
|
-
},
|
|
414
|
-
context: {},
|
|
415
|
-
});
|
|
416
455
|
let result = { ok: false };
|
|
417
|
-
|
|
418
|
-
result = await attemptCreate(
|
|
419
|
-
if (result.ok)
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
456
|
+
if (strictPluginMode) {
|
|
457
|
+
result = await attemptCreate(sendData);
|
|
458
|
+
if (!result.ok) {
|
|
459
|
+
if (debugRaw && this.continueOnFail()) {
|
|
460
|
+
returnData.push({ json: { error: result.msg || 'Create failed', response: result.body, request: sendData } });
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
throw new Error(result.msg || result.body || 'Create failed');
|
|
464
|
+
}
|
|
424
465
|
}
|
|
425
|
-
|
|
426
|
-
//
|
|
427
|
-
|
|
466
|
+
else {
|
|
467
|
+
// Try strategies progressively to avoid generic errors
|
|
468
|
+
const strategies = [];
|
|
469
|
+
strategies.push(JSON.parse(JSON.stringify(sendData)));
|
|
470
|
+
const s2 = JSON.parse(JSON.stringify(sendData));
|
|
471
|
+
if (s2.options)
|
|
472
|
+
delete s2.options.link;
|
|
473
|
+
strategies.push(s2);
|
|
474
|
+
strategies.push({
|
|
475
|
+
options: {
|
|
476
|
+
board_id: boardId,
|
|
477
|
+
field_set_key: 'create_success',
|
|
478
|
+
image_url: imageUrl,
|
|
479
|
+
method: 'uploaded',
|
|
480
|
+
},
|
|
481
|
+
context: {},
|
|
482
|
+
});
|
|
483
|
+
for (const strat of strategies) {
|
|
484
|
+
result = await attemptCreate(strat);
|
|
485
|
+
if (result.ok)
|
|
486
|
+
break;
|
|
487
|
+
if (/doesn\'t allow you to save Pins|does not allow you to save Pins/i.test(result.msg || ''))
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
if (!result.ok) {
|
|
491
|
+
if (debugRaw && this.continueOnFail()) {
|
|
492
|
+
returnData.push({ json: { error: result.msg || 'Create failed', response: result.body, request: strategies[strategies.length - 1] } });
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
throw new Error(result.msg || result.body || 'Create failed');
|
|
496
|
+
}
|
|
428
497
|
}
|
|
429
498
|
returnData.push({ json: { id: result.id, link: `https://www.pinterest.com/pin/${result.id}` } });
|
|
430
499
|
}
|