continente-mcp 4.1.0 → 4.1.1
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/continente-auto-login.js +45 -53
- package/package.json +1 -1
- package/src/index.js +2 -2
package/continente-auto-login.js
CHANGED
|
@@ -100,33 +100,55 @@ export async function isLoggedIn(page) {
|
|
|
100
100
|
return payload?.resources?.customerAuthenticated === true;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
103
|
+
const EMAIL_INPUTS = '#userNameCC:visible, input[name="userNameCC"]:visible, input[type="email"]:visible, input[name="email"]:visible, input[name="username"]:visible, input[type="text"]:visible';
|
|
104
|
+
const PASSWORD_INPUTS = '#password_input:visible, input[name="password_input"]:visible, input[type="password"]:visible, input[name="password"]:visible';
|
|
105
|
+
const VERIFICATION_INPUT = 'input[id^="altcha_checkbox_"]:visible';
|
|
106
|
+
|
|
107
|
+
async function submitLoginStep(frame) {
|
|
108
|
+
await frame.getByRole('button', { name: /^(Avançar|Continuar|Entrar|Login)$/i })
|
|
109
|
+
.click({ timeout: 15000 });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function completeLoginForm(frame, { email, password, log: logger = log }) {
|
|
113
|
+
logger('Entering email.');
|
|
114
|
+
await frame.locator(EMAIL_INPUTS).first().fill(email, { timeout: 15000 });
|
|
115
|
+
await submitLoginStep(frame);
|
|
116
|
+
|
|
117
|
+
// Continente may ask for its native verification before showing the password.
|
|
118
|
+
// Wait for either stage: the verification widget is inserted asynchronously.
|
|
119
|
+
await frame.locator(`${PASSWORD_INPUTS}, ${VERIFICATION_INPUT}`).first()
|
|
120
|
+
.waitFor({ state: 'visible', timeout: 15000 });
|
|
121
|
+
const verification = frame.locator(VERIFICATION_INPUT);
|
|
122
|
+
if (await verification.count()) {
|
|
123
|
+
logger('Completing login verification.');
|
|
124
|
+
await verification.click({ timeout: 10000 });
|
|
125
|
+
await frame.getByText(/^(Verificado|Verified)$/i)
|
|
126
|
+
.waitFor({ state: 'visible', timeout: 60000 });
|
|
127
|
+
await submitLoginStep(frame);
|
|
110
128
|
}
|
|
111
|
-
|
|
129
|
+
|
|
130
|
+
logger('Entering password.');
|
|
131
|
+
await frame.locator(PASSWORD_INPUTS).first().fill(password, { timeout: 15000 });
|
|
132
|
+
await submitLoginStep(frame);
|
|
112
133
|
}
|
|
113
134
|
|
|
114
|
-
async function
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
135
|
+
export async function acceptCookies(page) {
|
|
136
|
+
const button = page.getByRole('button', { name: /PERMITIR TODOS|Permitir todos/i });
|
|
137
|
+
if (!await button.isVisible()) {
|
|
138
|
+
await button.waitFor({ state: 'visible', timeout: 10000 }).catch(() => {});
|
|
139
|
+
if (!await button.isVisible()) return;
|
|
140
|
+
}
|
|
141
|
+
// The banner can render before its click handler is ready. Confirm dismissal
|
|
142
|
+
// before interacting with the iframe, which the banner otherwise covers.
|
|
143
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
144
|
+
await button.click({ timeout: 5000 });
|
|
145
|
+
try {
|
|
146
|
+
await button.waitFor({ state: 'hidden', timeout: 5000 });
|
|
147
|
+
return;
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (attempt === 2) throw new Error('Could not dismiss the Continente cookie banner');
|
|
120
150
|
}
|
|
121
151
|
}
|
|
122
|
-
await page.keyboard.press('Enter');
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async function acceptCookies(page) {
|
|
127
|
-
await page.getByRole('button', { name: /PERMITIR TODOS|Permitir todos/i })
|
|
128
|
-
.click({ timeout: 5000 })
|
|
129
|
-
.catch(() => {});
|
|
130
152
|
}
|
|
131
153
|
|
|
132
154
|
async function findLoginFrame(page) {
|
|
@@ -172,37 +194,7 @@ export async function autoLogin({
|
|
|
172
194
|
await acceptCookies(page);
|
|
173
195
|
const loginFrame = await findLoginFrame(page);
|
|
174
196
|
|
|
175
|
-
|
|
176
|
-
await fillFirst(loginFrame, [
|
|
177
|
-
'#userNameCC',
|
|
178
|
-
'input[name="userNameCC"]',
|
|
179
|
-
'input[type="email"]',
|
|
180
|
-
'input[name="email"]',
|
|
181
|
-
'input[name="username"]',
|
|
182
|
-
'input[type="text"]',
|
|
183
|
-
], email, 'email');
|
|
184
|
-
|
|
185
|
-
await clickFirst(loginFrame, [
|
|
186
|
-
'button[type="submit"]',
|
|
187
|
-
'button:has-text("Avançar")',
|
|
188
|
-
'button:has-text("Continuar")',
|
|
189
|
-
]);
|
|
190
|
-
|
|
191
|
-
logger('Entering password.');
|
|
192
|
-
await page.waitForTimeout(1500);
|
|
193
|
-
await fillFirst(loginFrame, [
|
|
194
|
-
'#password_input',
|
|
195
|
-
'input[name="password_input"]',
|
|
196
|
-
'input[type="password"]',
|
|
197
|
-
'input[name="password"]',
|
|
198
|
-
], password, 'password');
|
|
199
|
-
|
|
200
|
-
await clickFirst(loginFrame, [
|
|
201
|
-
'button[type="submit"]',
|
|
202
|
-
'button:has-text("Avançar")',
|
|
203
|
-
'button:has-text("Entrar")',
|
|
204
|
-
'button:has-text("Login")',
|
|
205
|
-
]);
|
|
197
|
+
await completeLoginForm(loginFrame, { email, password, log: logger });
|
|
206
198
|
|
|
207
199
|
await page.waitForTimeout(4000);
|
|
208
200
|
await page.waitForLoadState('domcontentloaded', { timeout: 15000 }).catch(() => {});
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -89,7 +89,7 @@ async function ensureBrowser() {
|
|
|
89
89
|
return browser;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
async function goto(url, wait = '
|
|
92
|
+
async function goto(url, wait = 'domcontentloaded') {
|
|
93
93
|
await ensureBrowser();
|
|
94
94
|
const response = await page.goto(url, { waitUntil: wait, timeout: 20000 });
|
|
95
95
|
if (!response?.ok()) throw new Error(`Continente page returned HTTP ${response?.status() ?? 'unknown'}`);
|
|
@@ -455,7 +455,7 @@ async function getOrderHistory(limit = 5) {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
async function getOrderProducts(orderDetailUrl) {
|
|
458
|
-
const response = await page.goto(orderDetailUrl, { waitUntil: '
|
|
458
|
+
const response = await page.goto(orderDetailUrl, { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
459
459
|
if (!response?.ok() || page.url().includes('/login')) throw new Error('order_detail_unavailable');
|
|
460
460
|
|
|
461
461
|
const products = await page.evaluate(() => {
|