homebridge-melcloud-control 4.0.0-beta.296 → 4.0.0-beta.298
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 -36
- package/src/melcloudhometoken.js +42 -42
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.298",
|
|
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
|
@@ -291,8 +291,6 @@ class MelCloud extends EventEmitter {
|
|
|
291
291
|
const melCloudHomeToken = new MelCloudHomeToken();
|
|
292
292
|
const url = await melCloudHomeToken.buildAuthorizeUrl();
|
|
293
293
|
|
|
294
|
-
this.emit('warn', url);
|
|
295
|
-
|
|
296
294
|
const page = await browser.newPage();
|
|
297
295
|
await page.goto(url, { waitUntil: 'networkidle2' });
|
|
298
296
|
|
|
@@ -302,40 +300,8 @@ class MelCloud extends EventEmitter {
|
|
|
302
300
|
const button1 = await page.$('input[type="submit"]');
|
|
303
301
|
await Promise.all([button1.click(), page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 10000 })]);
|
|
304
302
|
const html = await page.content();
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
console.log(code);
|
|
308
|
-
return
|
|
309
|
-
// Check for form_post response (HTML with hidden form)
|
|
310
|
-
const formCodeMatch = html.match(/name="code"\s+value="([^"]+)"/);
|
|
311
|
-
const formStateMatch = html.match(/name="state"\s+value="([^"]+)"/);
|
|
312
|
-
const formActionMatch = html.match(/action="([^"]+)"/);
|
|
313
|
-
|
|
314
|
-
if (formCodeMatch && formStateMatch && formActionMatch) {
|
|
315
|
-
console.log('Found form_post response, submitting to callback endpoint...');
|
|
316
|
-
this.submitFormPost(formActionMatch[1], formCodeMatch[1], formStateMatch[1], cookies)
|
|
317
|
-
.then(code => resolve(code))
|
|
318
|
-
.catch(err => reject(err));
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Check for melcloudhome:// redirect in JS
|
|
323
|
-
const bodyCodeMatch = html.match(/melcloudhome:\/\/[^"'\s]*[?&]code=([^&"'\s]+)/);
|
|
324
|
-
if (bodyCodeMatch) {
|
|
325
|
-
console.log('Found authorization code in response body (JS)');
|
|
326
|
-
resolve(bodyCodeMatch[1]);
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// 🆕 NEW: Check for data-url with code parameter (like in 500 error pages)
|
|
331
|
-
const dataUrlMatch = html.match(/data-url="[^"]*code=([^&"']+)/);
|
|
332
|
-
if (dataUrlMatch) {
|
|
333
|
-
console.log('Found authorization code in data-url attribute');
|
|
334
|
-
resolve(dataUrlMatch[1]);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
reject(new Error('Authorization code not found in URL or HTML'));
|
|
303
|
+
const authCode = await melCloudHomeToken.extractCodeFromHtml(html);
|
|
304
|
+
this.emit('warn', authCode);
|
|
339
305
|
|
|
340
306
|
// 5. Wymień code na access_token
|
|
341
307
|
const tokenResponse = await axios.post(TOKEN_ENDPOINT, new URLSearchParams({
|
package/src/melcloudhometoken.js
CHANGED
|
@@ -11,8 +11,7 @@ const TOKEN_ENDPOINT = 'https://auth.melcloudhome.com/connect/token';
|
|
|
11
11
|
const AUTHORIZE_ENDPOINT = 'https://auth.melcloudhome.com/connect/authorize';
|
|
12
12
|
|
|
13
13
|
class MelCloudHomeToken {
|
|
14
|
-
constructor(
|
|
15
|
-
this.log = log;
|
|
14
|
+
constructor() {
|
|
16
15
|
const jar = new CookieJar();
|
|
17
16
|
this.client = wrapper(axios.create({ jar, withCredentials: true }));
|
|
18
17
|
this.client.defaults.headers['User-Agent'] = MOBILE_USER_AGENT;
|
|
@@ -33,49 +32,50 @@ class MelCloudHomeToken {
|
|
|
33
32
|
return { url: res.request.res.responseUrl };
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
async extractCodeFromHtml(html) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
console.
|
|
72
|
-
|
|
73
|
-
|
|
35
|
+
async extractCodeFromHtml(html, cookies = '') {
|
|
36
|
+
try {
|
|
37
|
+
// Code w URL
|
|
38
|
+
const urlMatch = html.match(/[?&]code=([^&]+)/);
|
|
39
|
+
if (urlMatch) {
|
|
40
|
+
return urlMatch[1];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Hidden form (form_post)
|
|
44
|
+
const formCodeMatch = html.match(/name="code"\s+value="([^"]+)"/);
|
|
45
|
+
const formStateMatch = html.match(/name="state"\s+value="([^"]+)"/);
|
|
46
|
+
const formActionMatch = html.match(/action="([^"]+)"/);
|
|
47
|
+
|
|
48
|
+
if (formCodeMatch && formStateMatch && formActionMatch) {
|
|
49
|
+
const code = await this.submitFormPost(
|
|
50
|
+
formActionMatch[1],
|
|
51
|
+
formCodeMatch[1],
|
|
52
|
+
formStateMatch[1],
|
|
53
|
+
cookies
|
|
54
|
+
);
|
|
55
|
+
return code;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// melcloudhome:// w body
|
|
59
|
+
const bodyCodeMatch = html.match(/melcloudhome:\/\/[^"'\s]*[?&]code=([^&"'\s]+)/);
|
|
60
|
+
if (bodyCodeMatch) {
|
|
61
|
+
return bodyCodeMatch[1];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// data-url (np. z błędnej strony 500)
|
|
65
|
+
const dataUrlMatch = html.match(/data-url="[^"]*code=([^&"']+)/);
|
|
66
|
+
if (dataUrlMatch) {
|
|
67
|
+
return dataUrlMatch[1];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.warn('Authorization code not found in HTML response');
|
|
71
|
+
return null;
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error('extractCodeFromHtml error:', err);
|
|
74
|
+
return null;
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
-
return code;
|
|
77
76
|
}
|
|
78
77
|
|
|
78
|
+
|
|
79
79
|
async buildAuthorizeUrl() {
|
|
80
80
|
try {
|
|
81
81
|
const pkce = this.generatePKCE();
|