|
|
@@ -2,7 +2,7 @@ import * as fs from 'fs';
|
|
|
import * as path from 'path';
|
|
|
import * as os from 'os';
|
|
|
import type { Page } from 'playwright';
|
|
|
-import { filterCookies, parseOutputMode } from '../shared/cookie-utils';
|
|
|
+import { filterCookies, parseOutputMode, parseUserDriven } from '../shared/cookie-utils';
|
|
|
import { handleOutput } from '../shared/api-client';
|
|
|
import { openPersistentContext, profileDir } from '../shared/browser';
|
|
|
import type { CredentialsPayload } from '../shared/types';
|
|
|
@@ -118,7 +118,7 @@ async function performLogin(page: Page, email: string, password: string): Promis
|
|
|
await page.locator('#password').waitFor({ state: 'hidden', timeout: 10_000 });
|
|
|
}
|
|
|
|
|
|
-export async function refresh(mode: string): Promise<CredentialsPayload> {
|
|
|
+export async function refresh(mode: string, userDriven = false): Promise<CredentialsPayload> {
|
|
|
const profile = profileDir('airbnb', mode);
|
|
|
fs.mkdirSync(profile, { recursive: true });
|
|
|
|
|
|
@@ -126,40 +126,52 @@ export async function refresh(mode: string): Promise<CredentialsPayload> {
|
|
|
const email = envText.match(/^AIRBNB_EMAIL=(\S+)/m)?.[1] ?? '';
|
|
|
const password = envText.match(/^AIRBNB_PASSWORD=(\S+)/m)?.[1] ?? '';
|
|
|
|
|
|
- console.error('Trying silent refresh (headless)...');
|
|
|
- let context = await openPersistentContext(profile, true);
|
|
|
+ let context = await openPersistentContext(profile, !userDriven);
|
|
|
let page = context.pages()[0] ?? await context.newPage();
|
|
|
|
|
|
- await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
- await page.waitForLoadState('domcontentloaded');
|
|
|
-
|
|
|
- if (!page.url().includes('/multicalendar')) {
|
|
|
- if (FORCE_HEADLESS) {
|
|
|
- await context.close();
|
|
|
- throw new Error('Not logged in — re-run without HEADLESS=1 to authenticate.');
|
|
|
+ if (userDriven) {
|
|
|
+ console.error('[airbnb] User-driven mode — not touching the UI.');
|
|
|
+ await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
+ await page.waitForLoadState('domcontentloaded');
|
|
|
+ if (!page.url().includes('/multicalendar')) {
|
|
|
+ console.error('[airbnb] Not logged in — log in then navigate to your calendar (5 min timeout)...');
|
|
|
+ await page.waitForURL('**/multicalendar**', { timeout: 300_000 });
|
|
|
+ } else {
|
|
|
+ console.error('[airbnb] Session valid.');
|
|
|
}
|
|
|
- console.error('Session expired — switching to headed browser for login...');
|
|
|
- await context.close();
|
|
|
- context = await openPersistentContext(profile, false);
|
|
|
- page = context.pages()[0] ?? await context.newPage();
|
|
|
-
|
|
|
- if (email && password) {
|
|
|
- console.error('Session expired — attempting auto-login (headed)...');
|
|
|
- await performLogin(page, email, password);
|
|
|
- await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
- await page.waitForLoadState('domcontentloaded');
|
|
|
- if (!page.url().includes('/multicalendar')) {
|
|
|
+ } else {
|
|
|
+ console.error('Trying silent refresh (headless)...');
|
|
|
+ await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
+ await page.waitForLoadState('domcontentloaded');
|
|
|
+
|
|
|
+ if (!page.url().includes('/multicalendar')) {
|
|
|
+ if (FORCE_HEADLESS) {
|
|
|
await context.close();
|
|
|
- throw new Error('[airbnb] Auto-login failed — multicalendar not reached after password submit.');
|
|
|
+ throw new Error('Not logged in — re-run without HEADLESS=1 to authenticate.');
|
|
|
+ }
|
|
|
+ console.error('Session expired — switching to headed browser for login...');
|
|
|
+ await context.close();
|
|
|
+ context = await openPersistentContext(profile, false);
|
|
|
+ page = context.pages()[0] ?? await context.newPage();
|
|
|
+
|
|
|
+ if (email && password) {
|
|
|
+ console.error('Session expired — attempting auto-login (headed)...');
|
|
|
+ await performLogin(page, email, password);
|
|
|
+ await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
+ await page.waitForLoadState('domcontentloaded');
|
|
|
+ if (!page.url().includes('/multicalendar')) {
|
|
|
+ await context.close();
|
|
|
+ throw new Error('[airbnb] Auto-login failed — multicalendar not reached after password submit.');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.error('Not logged in — log in then navigate to your calendar (5 min timeout)...');
|
|
|
+ await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
+ await page.waitForLoadState('domcontentloaded');
|
|
|
+ await page.waitForURL('**/multicalendar**', { timeout: 300_000 });
|
|
|
}
|
|
|
} else {
|
|
|
- console.error('Not logged in — log in then navigate to your calendar (5 min timeout)...');
|
|
|
- await page.goto('https://www.airbnb.com/multicalendar');
|
|
|
- await page.waitForLoadState('domcontentloaded');
|
|
|
- await page.waitForURL('**/multicalendar**', { timeout: 300_000 });
|
|
|
+ console.error('Session valid — continuing silently.');
|
|
|
}
|
|
|
- } else {
|
|
|
- console.error('Session valid — continuing silently.');
|
|
|
}
|
|
|
|
|
|
console.error('Capturing cookies...');
|
|
|
@@ -175,7 +187,8 @@ export async function refresh(mode: string): Promise<CredentialsPayload> {
|
|
|
|
|
|
async function main(): Promise<void> {
|
|
|
const mode = parseOutputMode(process.argv);
|
|
|
- const credentials = await refresh(mode);
|
|
|
+ const userDriven = parseUserDriven(process.argv);
|
|
|
+ const credentials = await refresh(mode, userDriven);
|
|
|
await handleOutput('airbnb', credentials, mode, ENV_PATH);
|
|
|
}
|
|
|
|