n8n-nodes-pinterest 0.1.3 → 0.1.4
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,14 @@ 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
|
+
},
|
|
138
149
|
// Board ops
|
|
139
150
|
{
|
|
140
151
|
displayName: 'Operation',
|
|
@@ -292,6 +303,7 @@ class PinterestCookie {
|
|
|
292
303
|
const title = this.getNodeParameter('title', i, '');
|
|
293
304
|
const description = this.getNodeParameter('description', i, '');
|
|
294
305
|
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
306
|
+
const strictPluginMode = this.getNodeParameter('strictPluginMode', i, false);
|
|
295
307
|
const binary = (_c = items[i].binary) === null || _c === void 0 ? void 0 : _c[binaryProperty];
|
|
296
308
|
if (!binary)
|
|
297
309
|
throw new Error(`Binary property "${binaryProperty}" is missing on item ${i}`);
|
|
@@ -303,7 +315,16 @@ class PinterestCookie {
|
|
|
303
315
|
source_url: '/pin-builder/',
|
|
304
316
|
data: '{"options":{"type":"pinimage"},"context":{}}',
|
|
305
317
|
},
|
|
306
|
-
headers:
|
|
318
|
+
headers: strictPluginMode
|
|
319
|
+
? { ...buildCommonHeaders(csrf, true), Cookie: cookieHeader }
|
|
320
|
+
: {
|
|
321
|
+
...baseHeaders,
|
|
322
|
+
Cookie: cookieHeader,
|
|
323
|
+
Referer: `${base}/pin-builder/`,
|
|
324
|
+
Origin: base,
|
|
325
|
+
'X-Pinterest-Source-Url': '/pin-builder/',
|
|
326
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
327
|
+
},
|
|
307
328
|
proxy: proxy || undefined,
|
|
308
329
|
}));
|
|
309
330
|
const vip = JSON.parse(vipResp);
|
|
@@ -332,9 +353,23 @@ class PinterestCookie {
|
|
|
332
353
|
headers: {
|
|
333
354
|
Accept: '*/*',
|
|
334
355
|
'Accept-Encoding': 'gzip',
|
|
335
|
-
'User-Agent':
|
|
336
|
-
|
|
337
|
-
|
|
356
|
+
'User-Agent': strictPluginMode
|
|
357
|
+
? 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
|
|
358
|
+
: baseHeaders['User-Agent'],
|
|
359
|
+
Origin: strictPluginMode ? 'https://www.pinterest.com' : base,
|
|
360
|
+
Referer: strictPluginMode ? 'https://www.pinterest.com' : `${base}/pin-builder/`,
|
|
361
|
+
...(strictPluginMode
|
|
362
|
+
? {
|
|
363
|
+
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
|
|
364
|
+
'sec-ch-ua-mobile': '?0',
|
|
365
|
+
'sec-ch-ua-full': '?1',
|
|
366
|
+
'sec-ch-ua-platform': '"Windows"',
|
|
367
|
+
'Sec-Fetch-Dest': 'empty',
|
|
368
|
+
'Sec-Fetch-Mode': 'cors',
|
|
369
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
370
|
+
Connection: 'keep-alive',
|
|
371
|
+
}
|
|
372
|
+
: {}),
|
|
338
373
|
},
|
|
339
374
|
formData,
|
|
340
375
|
proxy: proxy || undefined,
|
|
@@ -350,19 +385,24 @@ class PinterestCookie {
|
|
|
350
385
|
const imageUrl = `https://i.pinimg.com/736x/${etag[0]}${etag[1]}/${etag[2]}${etag[3]}/${etag[4]}${etag[5]}/${etag}.jpg`;
|
|
351
386
|
// Step 3: create pin
|
|
352
387
|
const attachLink = (additionalFields.attachLink !== undefined) ? Boolean(additionalFields.attachLink) : true;
|
|
388
|
+
// Build payload
|
|
353
389
|
const sendData = {
|
|
354
390
|
options: {
|
|
355
|
-
board_id: boardId,
|
|
391
|
+
board_id: String(boardId),
|
|
356
392
|
field_set_key: 'create_success',
|
|
357
393
|
skip_pin_create_log: true,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
394
|
+
description: String(description || ''),
|
|
395
|
+
alt_text: String(additionalFields.alt_text || ''),
|
|
396
|
+
// Strict mode: always include link key
|
|
397
|
+
link: String(additionalFields.link || ''),
|
|
398
|
+
// Non-strict: allow disabling link entirely
|
|
399
|
+
...(strictPluginMode ? {} : (!attachLink ? { link: '' } : {})),
|
|
400
|
+
title: String(title || ''),
|
|
401
|
+
image_url: String(imageUrl),
|
|
363
402
|
method: 'uploaded',
|
|
364
403
|
upload_metric: { source: 'pinner_upload_standalone' },
|
|
365
|
-
|
|
404
|
+
user_mention_tags: [],
|
|
405
|
+
no_fetch_context_on_resource: false,
|
|
366
406
|
},
|
|
367
407
|
context: {},
|
|
368
408
|
};
|
|
@@ -375,7 +415,16 @@ class PinterestCookie {
|
|
|
375
415
|
source_url: '/pin-builder/',
|
|
376
416
|
data: JSON.stringify(payload),
|
|
377
417
|
},
|
|
378
|
-
headers:
|
|
418
|
+
headers: strictPluginMode
|
|
419
|
+
? { ...buildCommonHeaders(csrf, true), Cookie: cookieHeader }
|
|
420
|
+
: {
|
|
421
|
+
...baseHeaders,
|
|
422
|
+
Cookie: cookieHeader,
|
|
423
|
+
Referer: `${base}/pin-builder/`,
|
|
424
|
+
Origin: base,
|
|
425
|
+
'X-Pinterest-Source-Url': '/pin-builder/',
|
|
426
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
427
|
+
},
|
|
379
428
|
proxy: proxy || undefined,
|
|
380
429
|
// Get body even on 4xx
|
|
381
430
|
simple: false,
|
|
@@ -394,37 +443,39 @@ class PinterestCookie {
|
|
|
394
443
|
const msgDetail = ((_b = createdRes.error) === null || _b === void 0 ? void 0 : _b.message_detail) || '';
|
|
395
444
|
return { ok: Boolean(id), id, msg: String(msg || msgDetail || ''), body };
|
|
396
445
|
};
|
|
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
446
|
let result = { ok: false };
|
|
417
|
-
|
|
418
|
-
result = await attemptCreate(
|
|
419
|
-
if (result.ok)
|
|
420
|
-
|
|
421
|
-
// If explicit site-block message, skip to minimal next
|
|
422
|
-
if (/doesn\'t allow you to save Pins|does not allow you to save Pins/i.test(result.msg || ''))
|
|
423
|
-
continue;
|
|
447
|
+
if (strictPluginMode) {
|
|
448
|
+
result = await attemptCreate(sendData);
|
|
449
|
+
if (!result.ok)
|
|
450
|
+
throw new Error(result.msg || result.body || 'Create failed');
|
|
424
451
|
}
|
|
425
|
-
|
|
426
|
-
//
|
|
427
|
-
|
|
452
|
+
else {
|
|
453
|
+
// Try strategies progressively to avoid generic errors
|
|
454
|
+
const strategies = [];
|
|
455
|
+
strategies.push(JSON.parse(JSON.stringify(sendData)));
|
|
456
|
+
const s2 = JSON.parse(JSON.stringify(sendData));
|
|
457
|
+
if (s2.options)
|
|
458
|
+
delete s2.options.link;
|
|
459
|
+
strategies.push(s2);
|
|
460
|
+
strategies.push({
|
|
461
|
+
options: {
|
|
462
|
+
board_id: boardId,
|
|
463
|
+
field_set_key: 'create_success',
|
|
464
|
+
image_url: imageUrl,
|
|
465
|
+
method: 'uploaded',
|
|
466
|
+
},
|
|
467
|
+
context: {},
|
|
468
|
+
});
|
|
469
|
+
for (const strat of strategies) {
|
|
470
|
+
result = await attemptCreate(strat);
|
|
471
|
+
if (result.ok)
|
|
472
|
+
break;
|
|
473
|
+
if (/doesn\'t allow you to save Pins|does not allow you to save Pins/i.test(result.msg || ''))
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (!result.ok) {
|
|
477
|
+
throw new Error(result.msg || result.body || 'Create failed');
|
|
478
|
+
}
|
|
428
479
|
}
|
|
429
480
|
returnData.push({ json: { id: result.id, link: `https://www.pinterest.com/pin/${result.id}` } });
|
|
430
481
|
}
|