homebridge-melcloud-control 4.4.1-beta.26 → 4.4.1-beta.27

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/melcloudhome.js +57 -23
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.4.1-beta.26",
4
+ "version": "4.4.1-beta.27",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -33,8 +33,6 @@ class MelCloudHome extends EventEmitter {
33
33
  this.socketConnected = false;
34
34
  this.heartbeat = null;
35
35
 
36
- this.cookies = [];
37
-
38
36
  this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
39
37
  .on('warn', warn => this.emit('warn', warn))
40
38
  .on('error', error => this.emit('error', error))
@@ -449,53 +447,93 @@ class MelCloudHome extends EventEmitter {
449
447
  }
450
448
 
451
449
 
452
- async axiosRequest(url, options, jar, maxRedirects = 10) {
450
+ async axiosRequest(url, options, jar, maxRedirects = 15) {
453
451
  let currentUrl = url;
452
+ let previousUrl = null;
453
+ let method = options.method || 'GET';
454
+ let body = options.body;
454
455
 
455
456
  for (let i = 0; i < maxRedirects; i++) {
457
+ const cookieHeader = jar.headerFor(currentUrl);
458
+
459
+ const headers = {
460
+ 'User-Agent': options.headers?.['User-Agent'],
461
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
462
+ 'Accept-Language': 'en-US,en;q=0.9',
463
+ 'Accept-Encoding': 'identity',
464
+ ...(previousUrl ? { Referer: previousUrl } : {}),
465
+ ...(cookieHeader ? { Cookie: cookieHeader } : {}),
466
+ ...options.headers,
467
+ };
468
+
456
469
  const response = await axios({
457
470
  url: currentUrl,
458
- method: options.method || 'GET',
459
- data: options.body,
460
- headers: {
461
- ...options.headers,
462
- ...(jar.headerFor(currentUrl) && { Cookie: jar.headerFor(currentUrl) }),
463
- },
464
- validateStatus: () => true,
471
+ method,
472
+ data: body,
473
+ headers,
465
474
  maxRedirects: 0,
475
+ validateStatus: () => true,
466
476
  responseType: 'text',
467
477
  });
468
478
 
469
479
  jar.addFromHeader(response.headers['set-cookie'], currentUrl);
470
480
 
481
+ /* ========= HTTP REDIRECT ========= */
471
482
  if ([301, 302, 303, 307, 308].includes(response.status)) {
472
483
  const location = response.headers.location;
473
484
  if (!location) break;
474
485
 
486
+ // SUCCESS: app redirect
475
487
  if (location.startsWith('melcloudhome://')) {
476
488
  return { url: location, data: response.data };
477
489
  }
478
490
 
491
+ previousUrl = currentUrl;
479
492
  currentUrl = location.startsWith('http')
480
493
  ? location
481
494
  : new URL(location, currentUrl).toString();
482
495
 
483
- options.method = 'GET';
484
- options.body = undefined;
496
+ method = 'GET';
497
+ body = undefined;
485
498
  continue;
486
499
  }
487
500
 
488
- return { url: currentUrl, data: response.data };
501
+ /* ========= META REFRESH ========= */
502
+ const metaMatch = response.data?.match(
503
+ /<meta[^>]+http-equiv=["']?refresh["']?[^>]+content=["']?\d+;\s*url=([^"'>]+)["']?/i
504
+ );
505
+
506
+ if (metaMatch) {
507
+ const redirectPath = metaMatch[1]
508
+ .replace(/&amp;/g, '&')
509
+ .replace(/&#x2F;/g, '/');
510
+
511
+ previousUrl = currentUrl;
512
+ currentUrl = redirectPath.startsWith('http')
513
+ ? redirectPath
514
+ : new URL(redirectPath, currentUrl).toString();
515
+
516
+ method = 'GET';
517
+ body = undefined;
518
+ continue;
519
+ }
520
+
521
+ /* ========= FINAL RESPONSE ========= */
522
+ return {
523
+ url: currentUrl,
524
+ data: response.data,
525
+ headers: response.headers,
526
+ };
489
527
  }
490
528
 
491
- throw new Error('Too many redirects');
529
+ throw new Error('OAuth flow aborted: too many redirects');
492
530
  }
493
531
 
532
+
494
533
  async loginWithCredentials(email, password) {
495
534
  const jar = new CookieJar();
496
535
 
497
- const userAgent =
498
- 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1 Mobile Safari/604.1';
536
+ const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1 Mobile Safari/604.1';
499
537
 
500
538
  const codeVerifier = crypto.randomBytes(32).toString('base64url');
501
539
  const codeChallenge = crypto
@@ -503,8 +541,7 @@ class MelCloudHome extends EventEmitter {
503
541
  .update(codeVerifier)
504
542
  .digest('base64url');
505
543
 
506
- const authUrl =
507
- 'https://auth.melcloudhome.com/connect/authorize?' +
544
+ const authUrl = 'https://auth.melcloudhome.com/connect/authorize?' +
508
545
  new URLSearchParams({
509
546
  client_id: 'homemobile',
510
547
  redirect_uri: 'melcloudhome://',
@@ -519,9 +556,7 @@ class MelCloudHome extends EventEmitter {
519
556
  headers: { 'User-Agent': userAgent },
520
557
  }, jar);
521
558
 
522
- const csrfMatch =
523
- loginPage.data.match(/name="(_csrf|__RequestVerificationToken)".*?value="([^"]+)"/);
524
-
559
+ const csrfMatch = loginPage.data.match(/name="(_csrf|__RequestVerificationToken)".*?value="([^"]+)"/);
525
560
  if (!csrfMatch) throw new Error('CSRF token not found');
526
561
  const csrfToken = csrfMatch[2];
527
562
 
@@ -550,8 +585,7 @@ class MelCloudHome extends EventEmitter {
550
585
  if (!code) throw new Error('Authorization code missing');
551
586
 
552
587
  // STEP 3 – exchange token
553
- const tokenResponse = await axios.post(
554
- 'https://auth.melcloudhome.com/connect/token',
588
+ const tokenResponse = await axios.post('https://auth.melcloudhome.com/connect/token',
555
589
  new URLSearchParams({
556
590
  grant_type: 'authorization_code',
557
591
  client_id: 'homemobile',