-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBuzzButton.js
More file actions
359 lines (305 loc) · 15.6 KB
/
BuzzButton.js
File metadata and controls
359 lines (305 loc) · 15.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
const path = require('path');
/**
* BuzzButton.js
* Handles the logic for finding and clicking unlock buttons on the Kisi dashboard
*/
/**
* Attempts to find and click unlock buttons on the page
* @param {Page} page - Puppeteer Page object
* @returns {Promise<boolean>} - Whether buttons were successfully found and clicked
*/
async function pressButtons(page) {
console.log('Looking for unlock buttons...');
// Take a screenshot to see what's on the page before we start
const screenshotPath = path.join(__dirname, 'dashboard-before.png');
await page.screenshot({ path: screenshotPath });
console.log(`Screenshot saved as ${screenshotPath}`);
// Wait for the unlock buttons to be available
console.log('Waiting for unlock buttons to be available...');
try {
await page.waitForSelector('button[data-test-id="unlock-button"]', { timeout: 10000 });
} catch (e) {
console.log('Timeout waiting for unlock buttons, will try to find them anyway');
}
// Find all unlock buttons
const unlockButtons = await page.$$('button[data-test-id="unlock-button"]');
console.log(`Found ${unlockButtons.length} unlock buttons on the page`);
if (unlockButtons.length === 0) {
console.log('No unlock buttons found. Trying alternative selectors...');
// Try to find buttons with LockIcon images
try {
await page.waitForSelector('img[alt="LockIcon"]', { timeout: 5000 });
} catch (e) {
console.log('Timeout waiting for LockIcon images, will try to find them anyway');
}
const buttonsWithLockIcon = await page.$$('button:has(img[alt="LockIcon"])');
console.log(`Found ${buttonsWithLockIcon.length} buttons with LockIcon images`);
if (buttonsWithLockIcon.length > 0) {
unlockButtons.push(...buttonsWithLockIcon);
}
}
if (unlockButtons.length === 0) {
console.log('Still no unlock buttons found. Trying to evaluate in page context...');
// Try to find and click buttons using page.evaluate
const clickResult = await page.evaluate(() => {
// Find all buttons with the unlock button data-test-id
const unlockBtns = Array.from(document.querySelectorAll('button[data-test-id="unlock-button"]'));
console.log('Found', unlockBtns.length, 'buttons with data-test-id="unlock-button"');
// Find buttons containing LockIcon images - this matches the exact HTML provided by the user
const lockIconBtns = Array.from(document.querySelectorAll('button.MuiButtonBase-root.MuiIconButton-root.MuiIconButton-sizeLarge'));
console.log('Found', lockIconBtns.length, 'buttons with MuiIconButton-sizeLarge class');
// Filter to only those with LockIcon images
const buttonsWithLockIcon = lockIconBtns.filter(btn => {
const img = btn.querySelector('img[alt="LockIcon"]');
return img !== null;
});
console.log('Found', buttonsWithLockIcon.length, 'buttons with LockIcon images');
if (buttonsWithLockIcon.length > 0) {
// Return the IDs of the buttons we found so we can click them from outside
const buttonIds = [];
// Select 2nd and 3rd buttons (index 1 and 2) if available
const startIndex = Math.min(1, buttonsWithLockIcon.length - 1); // Start from index 1 if possible
const endIndex = Math.min(startIndex + 2, buttonsWithLockIcon.length); // Get up to 2 buttons
for (let i = startIndex; i < endIndex; i++) {
// Add a unique ID to each button so we can find it later
const uniqueId = 'unlock-btn-' + i;
buttonsWithLockIcon[i].setAttribute('id', uniqueId);
buttonIds.push(uniqueId);
}
return buttonIds;
}
return [];
});
if (clickResult.length > 0) {
console.log(`Found ${clickResult.length} buttons to click`);
// Click each button 2 times with a 5-second delay
for (const buttonId of clickResult) {
console.log(`Clicking button with ID ${buttonId} 2 times...`);
for (let i = 0; i < 2; i++) {
console.log(`Click ${i+1} on button ${buttonId}`);
try {
// Check if the button still exists before clicking
const buttonExists = await page.evaluate((id) => {
const button = document.getElementById(id);
if (button) {
return true;
} else {
// Try to find and mark the button again if it was removed/replaced
const lockIconBtns = Array.from(document.querySelectorAll('button.MuiButtonBase-root.MuiIconButton-root.MuiIconButton-sizeLarge'));
const buttonsWithLockIcon = lockIconBtns.filter(btn => {
const img = btn.querySelector('img[alt="LockIcon"]');
return img !== null;
});
if (buttonsWithLockIcon.length > 0) {
// Re-add the ID to the first button
buttonsWithLockIcon[0].setAttribute('id', id);
return true;
}
return false;
}
}, buttonId);
if (buttonExists) {
// First click using Puppeteer's click method
await page.click(`#${buttonId}`).catch(e => console.error(`Error clicking button ${buttonId}:`, e));
// Second click using JavaScript's click method for redundancy
await page.evaluate((id) => {
const button = document.getElementById(id);
if (button) button.click();
}, buttonId);
} else {
console.log(`Button ${buttonId} no longer exists in the DOM for click ${i+1}`);
// Try to find buttons again using alternative methods
await page.evaluate(() => {
const allButtons = document.querySelectorAll('button');
const lockButtons = Array.from(allButtons).filter(btn => {
return btn.innerHTML.includes('LockIcon');
});
if (lockButtons[0]) lockButtons[0].click();
});
}
} catch (e) {
console.error(`Error with button ${buttonId}:`, e);
}
await new Promise(resolve => setTimeout(resolve, 5000)); // 5-second delay between clicks
}
}
// Take a screenshot after all attempts
const afterAttemptsPath = path.join(__dirname, 'buttons-after-attempts.png');
await page.screenshot({ path: afterAttemptsPath });
console.log(`Screenshot saved as ${afterAttemptsPath}`);
return true;
} else {
// Last resort: Try to directly click based on the exact HTML structure
console.log('Trying one last approach - direct evaluation and click...');
// Try clicking buttons multiple times with delays between attempts
for (let attempt = 0; attempt < 2; attempt++) {
console.log(`Last resort attempt ${attempt+1} of 2`);
const lastAttempt = await page.evaluate(() => {
// This is the exact button structure from the user's input
const buttonSelector = 'button.MuiButtonBase-root.MuiIconButton-root.MuiIconButton-sizeLarge[data-test-id="unlock-button"]';
const buttons = document.querySelectorAll(buttonSelector);
let clickedAny = false;
// Function to click buttons simultaneously
const clickButtons = (buttonArray) => {
if (buttonArray.length > 0) {
// Click 2nd and 3rd buttons if available (index 1 and 2)
const secondButtonIndex = Math.min(1, buttonArray.length - 1);
const thirdButtonIndex = Math.min(2, buttonArray.length - 1);
if (buttonArray[secondButtonIndex]) {
console.log('Clicking second button');
buttonArray[secondButtonIndex].click();
clickedAny = true;
}
if (buttonArray[thirdButtonIndex] && secondButtonIndex !== thirdButtonIndex) {
console.log('Clicking third button');
buttonArray[thirdButtonIndex].click();
clickedAny = true;
}
}
return clickedAny;
};
if (buttons.length === 0) {
// Try a more general selector
const allButtons = document.querySelectorAll('button');
const lockButtons = Array.from(allButtons).filter(btn => {
return btn.innerHTML.includes('LockIcon');
});
if (lockButtons.length > 0) {
console.log(`Found ${lockButtons.length} lock buttons`);
clickButtons(lockButtons);
}
// Try even more general approach - any button that might be related to locks
if (!clickedAny) {
const possibleLockButtons = Array.from(allButtons).filter(btn => {
const buttonText = btn.textContent || '';
return buttonText.toLowerCase().includes('unlock') ||
buttonText.toLowerCase().includes('lock') ||
buttonText.toLowerCase().includes('door');
});
if (possibleLockButtons.length > 0) {
console.log(`Found ${possibleLockButtons.length} possible lock-related buttons by text`);
clickButtons(possibleLockButtons);
// Make sure the clicks register by clicking again
setTimeout(() => {
const secondButtonIndex = Math.min(1, possibleLockButtons.length - 1);
const thirdButtonIndex = Math.min(2, possibleLockButtons.length - 1);
if (possibleLockButtons[secondButtonIndex]) possibleLockButtons[secondButtonIndex].click();
if (possibleLockButtons[thirdButtonIndex] && secondButtonIndex !== thirdButtonIndex)
possibleLockButtons[thirdButtonIndex].click();
}, 500);
}
}
} else {
console.log(`Found ${buttons.length} buttons with exact selector`);
clickButtons(buttons);
}
return clickedAny;
});
if (lastAttempt) {
console.log('Successfully clicked buttons in last attempt');
// Wait between attempts
await new Promise(resolve => setTimeout(resolve, 5000));
} else {
console.log(`No buttons found in attempt ${attempt+1}`);
// Wait before trying again
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
// Take a screenshot after all attempts
const afterAttemptsPath = path.join(__dirname, 'buttons-after-attempts.png');
await page.screenshot({ path: afterAttemptsPath });
console.log(`Screenshot saved as ${afterAttemptsPath}`);
return true;
}
} else {
// We found buttons using the selector, now click both buttons simultaneously 2 times with a delay
console.log('Clicking both unlock buttons simultaneously 2 times with a 5-second delay');
// Click both buttons 2 times simultaneously
for (let i = 0; i < 2; i++) {
console.log(`Click attempt ${i+1} on both buttons simultaneously`);
try {
// Re-query the DOM for buttons each time to avoid detached node errors
const freshButtons = await page.$$('button[data-test-id="unlock-button"]');
const altButtons = await page.$$('button:has(img[alt="LockIcon"])');
// Create an array to hold our click promises
const clickPromises = [];
// Try to click the first button (now targeting the 2nd button)
if (freshButtons.length > 1) {
console.log('Clicking second button with primary selector');
clickPromises.push(freshButtons[1].click().catch(e => console.error('Error clicking second button with primary selector:', e)));
} else if (altButtons.length > 1) {
console.log('Clicking second button with alternative selector');
clickPromises.push(altButtons[1].click().catch(e => console.error('Error clicking second button with alternative selector:', e)));
} else {
console.log(`No second button found for click ${i+1}`);
}
// Try to click the second button (now targeting the 3rd button)
if (freshButtons.length > 2) {
console.log('Clicking third button with primary selector');
clickPromises.push(freshButtons[2].click().catch(e => console.error('Error clicking third button with primary selector:', e)));
} else if (altButtons.length > 2) {
console.log('Clicking third button with alternative selector');
clickPromises.push(altButtons[2].click().catch(e => console.error('Error clicking third button with alternative selector:', e)));
} else {
console.log(`No third button found for click ${i+1}`);
}
// Execute all clicks simultaneously
if (clickPromises.length > 0) {
await Promise.all(clickPromises);
console.log(`Successfully clicked ${clickPromises.length} button(s) simultaneously`);
// Follow up with direct DOM clicks for redundancy
await page.evaluate(() => {
const unlockButtons = document.querySelectorAll('button[data-test-id="unlock-button"]');
if (unlockButtons.length > 1) unlockButtons[1].click(); // 2nd button
if (unlockButtons.length > 2) unlockButtons[2].click(); // 3rd button
});
} else {
// If no buttons were found with standard selectors, try page.evaluate as a fallback
console.log('No buttons found with standard selectors, trying page.evaluate');
await page.evaluate(() => {
const allButtons = document.querySelectorAll('button');
const lockButtons = Array.from(allButtons).filter(btn => {
return btn.innerHTML.includes('LockIcon');
});
// Click buttons simultaneously
if (lockButtons.length > 1) lockButtons[1].click(); // 2nd button
if (lockButtons.length > 2) lockButtons[2].click(); // 3rd button
});
}
} catch (e) {
console.error('Error during simultaneous button clicks:', e);
}
// Wait between click attempts
await new Promise(resolve => setTimeout(resolve, 5000)); // 5-second delay between clicks
}
return true;
}
return false;
}
/**
* Checks if the door was successfully unlocked
* @param {Page} page - Puppeteer Page objectd
* @returns {Promise<boolean>} - Whether the door was successfully unlocked
*/
async function checkUnlockSuccess(page) {
// Take a screenshot to see what's on the page after clicking
const afterScreenshotPath = path.join(__dirname, 'dashboard-after.png');
await page.screenshot({ path: afterScreenshotPath });
console.log(`Screenshot saved as ${afterScreenshotPath}`);
// Check if we were successful
const doorUnlocked = await page.evaluate(() => {
// Look for success messages or indicators
const successElements = Array.from(document.querySelectorAll('*')).filter(el =>
(el.textContent || '').includes('successfully') ||
(el.textContent || '').includes('unlocked')
);
return successElements.length > 0;
});
if (doorUnlocked) {
console.log('CEN - Front Door unlock button clicked successfully!');
} else {
console.log('Could not find or click the CEN - Front Door unlock button');
}
return doorUnlocked;
}
module.exports = { pressButtons, checkUnlockSuccess };