homebridge-melcloud-control 4.0.0-beta.293 → 4.0.0-beta.295
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/package.json +1 -1
- package/src/melcloud.js +2 -33
- package/src/melcloudhometoken.js +25 -28
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.0.0-beta.
|
|
4
|
+
"version": "4.0.0-beta.295",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
package/src/melcloud.js
CHANGED
|
@@ -301,43 +301,12 @@ class MelCloud extends EventEmitter {
|
|
|
301
301
|
await page.type('input[name="password"]', this.passwd, { delay: 50 });
|
|
302
302
|
const button1 = await page.$('input[type="submit"]');
|
|
303
303
|
await Promise.all([button1.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 10000 })]);
|
|
304
|
-
const html = await page.content(
|
|
305
|
-
const code = await melCloudHomeToken.extractCodeFromHtml();
|
|
304
|
+
const html = await page.content();
|
|
305
|
+
const code = await melCloudHomeToken.extractCodeFromHtml(html);
|
|
306
306
|
|
|
307
307
|
console.log(code);
|
|
308
308
|
return
|
|
309
309
|
|
|
310
|
-
// Check for form_post response (HTML with hidden form)
|
|
311
|
-
const formCodeMatch = html.match(/name="code"\s+value="([^"]+)"/);
|
|
312
|
-
const formStateMatch = html.match(/name="state"\s+value="([^"]+)"/);
|
|
313
|
-
const formActionMatch = html.match(/action="([^"]+)"/);
|
|
314
|
-
|
|
315
|
-
if (formCodeMatch && formStateMatch && formActionMatch) {
|
|
316
|
-
console.log('Found form_post response, submitting to callback endpoint...');
|
|
317
|
-
this.submitFormPost(formActionMatch[1], formCodeMatch[1], formStateMatch[1], cookies)
|
|
318
|
-
.then(code => resolve(code))
|
|
319
|
-
.catch(err => reject(err));
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Check for melcloudhome:// redirect in JS
|
|
324
|
-
const bodyCodeMatch = html.match(/melcloudhome:\/\/[^"'\s]*[?&]code=([^&"'\s]+)/);
|
|
325
|
-
if (bodyCodeMatch) {
|
|
326
|
-
console.log('Found authorization code in response body (JS)');
|
|
327
|
-
resolve(bodyCodeMatch[1]);
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// 🆕 NEW: Check for data-url with code parameter (like in 500 error pages)
|
|
332
|
-
const dataUrlMatch = html.match(/data-url="[^"]*code=([^&"']+)/);
|
|
333
|
-
if (dataUrlMatch) {
|
|
334
|
-
console.log('Found authorization code in data-url attribute');
|
|
335
|
-
resolve(dataUrlMatch[1]);
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
reject(new Error('Authorization code not found in URL or HTML'));
|
|
340
|
-
|
|
341
310
|
// 5. Wymień code na access_token
|
|
342
311
|
const tokenResponse = await axios.post(TOKEN_ENDPOINT, new URLSearchParams({
|
|
343
312
|
client_id: 'homemobile',
|
package/src/melcloudhometoken.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import { wrapper } from 'axios-cookiejar-support';
|
|
3
|
-
import { CookieJar } from 'tough-cookie';
|
|
4
1
|
import crypto from 'crypto';
|
|
5
|
-
import * as cheerio from 'cheerio';
|
|
6
2
|
|
|
7
3
|
const MOBILE_USER_AGENT = 'MonitorAndControl.App.Mobile/35 CFNetwork/3860.100.1 Darwin/25.0.0';
|
|
8
4
|
const CLIENT_ID = 'homemobile';
|
|
@@ -15,9 +11,6 @@ const LOGIN_ENDPOINT = 'https://auth.melcloudhome.com/Account/Login';
|
|
|
15
11
|
class MelCloudHomeToken {
|
|
16
12
|
constructor(log = console) {
|
|
17
13
|
this.log = log;
|
|
18
|
-
const jar = new CookieJar();
|
|
19
|
-
this.client = wrapper(axios.create({ jar, withCredentials: true }));
|
|
20
|
-
this.client.defaults.headers['User-Agent'] = MOBILE_USER_AGENT;
|
|
21
14
|
}
|
|
22
15
|
|
|
23
16
|
generatePKCE() {
|
|
@@ -49,35 +42,39 @@ class MelCloudHomeToken {
|
|
|
49
42
|
}
|
|
50
43
|
|
|
51
44
|
async extractCodeFromHtml(html) {
|
|
52
|
-
const $ = cheerio.load(html);
|
|
53
45
|
let code = null;
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
47
|
+
// Check for form_post response (HTML with hidden form)
|
|
48
|
+
const formCodeMatch = html.match(/name="code"\s+value="([^"]+)"/);
|
|
49
|
+
const formStateMatch = html.match(/name="state"\s+value="([^"]+)"/);
|
|
50
|
+
const formActionMatch = html.match(/action="([^"]+)"/);
|
|
51
|
+
|
|
52
|
+
if (formCodeMatch && formStateMatch && formActionMatch) {
|
|
53
|
+
console.log('Found form_post response, submitting to callback endpoint...');
|
|
54
|
+
this.submitFormPost(formActionMatch[1], formCodeMatch[1], formStateMatch[1], cookies)
|
|
55
|
+
.then(code => resolve(code))
|
|
56
|
+
.catch(err => reject(err));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
// Check for melcloudhome:// redirect in JS
|
|
61
|
+
const bodyCodeMatch = html.match(/melcloudhome:\/\/[^"'\s]*[?&]code=([^&"'\s]+)/);
|
|
62
|
+
if (bodyCodeMatch) {
|
|
63
|
+
console.log('Found authorization code in response body (JS)');
|
|
64
|
+
resolve(bodyCodeMatch[1]);
|
|
65
|
+
return;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
68
|
+
// 🆕 NEW: Check for data-url with code parameter (like in 500 error pages)
|
|
69
|
+
const dataUrlMatch = html.match(/data-url="[^"]*code=([^&"']+)/);
|
|
70
|
+
if (dataUrlMatch) {
|
|
71
|
+
console.log('Found authorization code in data-url attribute');
|
|
72
|
+
resolve(dataUrlMatch[1]);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
74
75
|
|
|
75
76
|
return code;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
78
|
}
|
|
82
79
|
|
|
83
80
|
export default MelCloudHomeToken;
|