n8n-nodes-jygse-vw-weconnect 0.2.13 → 0.2.15
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.
|
@@ -32,10 +32,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.VwWeConnect = void 0;
|
|
37
40
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
38
41
|
const crypto = __importStar(require("crypto"));
|
|
42
|
+
const axios_1 = __importDefault(require("axios"));
|
|
43
|
+
const axios_cookiejar_support_1 = require("axios-cookiejar-support");
|
|
44
|
+
const tough_cookie_1 = require("tough-cookie");
|
|
39
45
|
class VwWeConnect {
|
|
40
46
|
constructor() {
|
|
41
47
|
this.description = {
|
|
@@ -216,6 +222,9 @@ async function vwLogin(context, email, password) {
|
|
|
216
222
|
const state = generateTraceId(); // Use UUID as state
|
|
217
223
|
const traceId = generateTraceId(); // For weconnect-trace-id header
|
|
218
224
|
const codeVerifier = generateCodeVerifier();
|
|
225
|
+
// Create cookie jar for session management (like ioBroker)
|
|
226
|
+
const jar = new tough_cookie_1.CookieJar();
|
|
227
|
+
const client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({ jar }));
|
|
219
228
|
// Browser-like headers (EXACTLY from ioBroker.vw-connect)
|
|
220
229
|
const browserHeaders = {
|
|
221
230
|
'User-Agent': VW_USER_AGENT,
|
|
@@ -238,48 +247,39 @@ async function vwLogin(context, email, password) {
|
|
|
238
247
|
'&state=' + state +
|
|
239
248
|
'&code_challenge=' + codeChallenge +
|
|
240
249
|
'&code_challenge_method=S256';
|
|
241
|
-
// Use
|
|
242
|
-
|
|
243
|
-
const authorizeResponse = await context.helpers.httpRequest({
|
|
244
|
-
method: 'GET',
|
|
245
|
-
url: authorizeUrl,
|
|
250
|
+
// Use axios with cookie jar for session management
|
|
251
|
+
const authorizeResponse = await client.get(authorizeUrl, {
|
|
246
252
|
headers: browserHeaders,
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
253
|
+
maxRedirects: 0, // Don't follow any redirects
|
|
254
|
+
validateStatus: () => true, // Accept any status code
|
|
255
|
+
}).catch(err => {
|
|
256
|
+
// axios throws on redirect when maxRedirects=0, but we can get the response
|
|
257
|
+
if (err.response)
|
|
258
|
+
return err.response;
|
|
259
|
+
throw err;
|
|
251
260
|
});
|
|
252
|
-
// Extract response body and check for redirect
|
|
261
|
+
// Extract response body and check for redirect (axios format)
|
|
253
262
|
let htmlContent;
|
|
254
263
|
let currentUrl = '';
|
|
255
264
|
let stateToken = '';
|
|
256
265
|
let httpStatusCode = 0;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
// Check for redirect in headers (case-insensitive)
|
|
265
|
-
if (respHeaders) {
|
|
266
|
-
const locationHeader = respHeaders.location || respHeaders.Location;
|
|
267
|
-
if (locationHeader) {
|
|
268
|
-
currentUrl = locationHeader;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
if (respObj.body && typeof respObj.body === 'string') {
|
|
272
|
-
htmlContent = respObj.body;
|
|
273
|
-
}
|
|
274
|
-
else if (respObj.data && typeof respObj.data === 'string') {
|
|
275
|
-
htmlContent = respObj.data;
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
htmlContent = JSON.stringify(respObj);
|
|
266
|
+
// axios response format: { data, status, headers, ... }
|
|
267
|
+
httpStatusCode = authorizeResponse.status || 0;
|
|
268
|
+
// Check for redirect in headers
|
|
269
|
+
if (authorizeResponse.headers) {
|
|
270
|
+
const locationHeader = authorizeResponse.headers.location || authorizeResponse.headers.Location;
|
|
271
|
+
if (locationHeader) {
|
|
272
|
+
currentUrl = locationHeader;
|
|
279
273
|
}
|
|
280
274
|
}
|
|
275
|
+
if (typeof authorizeResponse.data === 'string') {
|
|
276
|
+
htmlContent = authorizeResponse.data;
|
|
277
|
+
}
|
|
278
|
+
else if (authorizeResponse.data) {
|
|
279
|
+
htmlContent = JSON.stringify(authorizeResponse.data);
|
|
280
|
+
}
|
|
281
281
|
else {
|
|
282
|
-
htmlContent =
|
|
282
|
+
htmlContent = '';
|
|
283
283
|
}
|
|
284
284
|
// Debug: If we got an error page (status 400/500 or "Oops" in content), throw with details
|
|
285
285
|
if (httpStatusCode >= 400 || htmlContent.includes('Oops!, something went wrong')) {
|
|
@@ -306,38 +306,23 @@ async function vwLogin(context, email, password) {
|
|
|
306
306
|
if (!currentUrl.startsWith('http') && !currentUrl.startsWith('/')) {
|
|
307
307
|
break;
|
|
308
308
|
}
|
|
309
|
-
// Follow the redirect using
|
|
309
|
+
// Follow the redirect using axios with cookie jar
|
|
310
310
|
const followUrl = currentUrl.startsWith('http') ? currentUrl : `https://identity.vwgroup.io${currentUrl}`;
|
|
311
|
-
const followResponse = await
|
|
312
|
-
method: 'GET',
|
|
313
|
-
url: followUrl,
|
|
311
|
+
const followResponse = await client.get(followUrl, {
|
|
314
312
|
headers: browserHeaders,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
324
|
-
else if (followResponse && typeof followResponse === 'object') {
|
|
325
|
-
const respObj = followResponse;
|
|
326
|
-
const respHeaders = respObj.headers;
|
|
327
|
-
currentUrl = '';
|
|
328
|
-
if (respHeaders) {
|
|
329
|
-
const locationHeader = respHeaders.location || respHeaders.Location;
|
|
330
|
-
if (locationHeader) {
|
|
331
|
-
currentUrl = locationHeader;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
if (respObj.body && typeof respObj.body === 'string') {
|
|
335
|
-
htmlContent = respObj.body;
|
|
336
|
-
}
|
|
337
|
-
else if (respObj.data && typeof respObj.data === 'string') {
|
|
338
|
-
htmlContent = respObj.data;
|
|
313
|
+
maxRedirects: 0,
|
|
314
|
+
validateStatus: () => true,
|
|
315
|
+
}).catch(err => err.response || { data: '', headers: {}, status: 0 });
|
|
316
|
+
currentUrl = '';
|
|
317
|
+
if (followResponse.headers) {
|
|
318
|
+
const locationHeader = followResponse.headers.location || followResponse.headers.Location;
|
|
319
|
+
if (locationHeader) {
|
|
320
|
+
currentUrl = locationHeader;
|
|
339
321
|
}
|
|
340
322
|
}
|
|
323
|
+
if (typeof followResponse.data === 'string') {
|
|
324
|
+
htmlContent = followResponse.data;
|
|
325
|
+
}
|
|
341
326
|
maxInitialRedirects--;
|
|
342
327
|
}
|
|
343
328
|
// Try to extract state token from the final HTML if not found in URL
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-jygse-vw-weconnect",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "n8n community node for VW We Connect - Control your Volkswagen T6.1 and other VW vehicles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -43,8 +43,14 @@
|
|
|
43
43
|
"dist/nodes/VwWeConnect/VwWeConnect.node.js"
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"axios": "^1.6.0",
|
|
48
|
+
"axios-cookiejar-support": "^5.0.0",
|
|
49
|
+
"tough-cookie": "^4.1.0"
|
|
50
|
+
},
|
|
46
51
|
"devDependencies": {
|
|
47
52
|
"@types/node": "^20.10.0",
|
|
53
|
+
"@types/tough-cookie": "^4.0.5",
|
|
48
54
|
"@typescript-eslint/parser": "^6.0.0",
|
|
49
55
|
"eslint": "^8.56.0",
|
|
50
56
|
"gulp": "^4.0.2",
|