Moved to playwright
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -21,3 +21,5 @@ Thumbs.db
|
|||||||
# Vite
|
# Vite
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
||||||
|
context
|
||||||
45
package-lock.json
generated
45
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@auth/sveltekit": "^1.10.0",
|
"@auth/sveltekit": "^1.10.0",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
"cron": "^4.3.2",
|
"cron": "^4.3.2",
|
||||||
|
"patchright": "^1.52.5",
|
||||||
"postgres": "^3.4.7",
|
"postgres": "^3.4.7",
|
||||||
"puppeteer": "^24.14.0",
|
"puppeteer": "^24.14.0",
|
||||||
"puppeteer-extra": "^3.3.6",
|
"puppeteer-extra": "^3.3.6",
|
||||||
@ -6113,6 +6114,50 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/patchright": {
|
||||||
|
"version": "1.52.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright/-/patchright-1.52.5.tgz",
|
||||||
|
"integrity": "sha512-wmRpsF9n02j0S+YDk0U3ouuWipHbUowwxbf/4K4G9ng311vvugoo8WndbU/fCsGtme8gYNfcEGcpfF6/L1NXHg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"patchright-core": "1.52.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"patchright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/patchright-core": {
|
||||||
|
"version": "1.52.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/patchright-core/-/patchright-core-1.52.5.tgz",
|
||||||
|
"integrity": "sha512-8rnLVEK9jDZWzFPy2hCQrp4xhU7zgE8IqseZyjGkgxf+jpAWTuGNgIAlcsKZMfQrDL8j1mZgRIGNAQT00nk6QA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"patchright-core": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/patchright/node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-is-absolute": {
|
"node_modules/path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"@auth/sveltekit": "^1.10.0",
|
"@auth/sveltekit": "^1.10.0",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
"cron": "^4.3.2",
|
"cron": "^4.3.2",
|
||||||
|
"patchright": "^1.52.5",
|
||||||
"postgres": "^3.4.7",
|
"postgres": "^3.4.7",
|
||||||
"puppeteer": "^24.14.0",
|
"puppeteer": "^24.14.0",
|
||||||
"puppeteer-extra": "^3.3.6",
|
"puppeteer-extra": "^3.3.6",
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import puppeteer from 'puppeteer-extra';
|
|
||||||
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
|
|
||||||
import db from './db.js';
|
import db from './db.js';
|
||||||
import { json } from '@sveltejs/kit';
|
import { chromium } from 'patchright';
|
||||||
|
|
||||||
puppeteer.use(StealthPlugin());
|
//const browser = await chromium.launch();
|
||||||
let state = [];
|
let state = [];
|
||||||
let code = null;
|
let code = null;
|
||||||
let needCode = false;
|
let needCode = false;
|
||||||
@ -31,67 +29,40 @@ export async function pullData(amount = 100) {
|
|||||||
code = null;
|
code = null;
|
||||||
needCode = false;
|
needCode = false;
|
||||||
state.push('Starting Browser');
|
state.push('Starting Browser');
|
||||||
const browser = await puppeteer.launch({
|
const browser = await chromium.launchPersistentContext('context', {
|
||||||
args: ['--no-sandbox'],
|
channel: 'chrome',
|
||||||
headless: true
|
headless: true,
|
||||||
//defaultViewport: null,
|
viewport: null
|
||||||
//args: ['--disable-blink-features=PrettyPrintJSONDocument']
|
// do NOT add custom browser headers or userAgent
|
||||||
});
|
});
|
||||||
|
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
state.push('Loading Cookies');
|
|
||||||
|
|
||||||
const cookiesdb = await db`SELECT
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
domain,
|
|
||||||
path,
|
|
||||||
expires,
|
|
||||||
size,
|
|
||||||
httpOnly,
|
|
||||||
secure,
|
|
||||||
session,
|
|
||||||
priority,
|
|
||||||
sameParty,
|
|
||||||
sourceScheme,
|
|
||||||
sourcePort
|
|
||||||
FROM cookies`;
|
|
||||||
|
|
||||||
cookiesdb.forEach((cookie) => {
|
|
||||||
cookie.expires = cookie.expires ? Number(cookie.expires) : undefined;
|
|
||||||
cookie.size = cookie.size ? Number(cookie.size) : undefined;
|
|
||||||
cookie.sourcePort = cookie.sourcePort ? Number(cookie.sourcePort) : undefined;
|
|
||||||
state.push('Loading cookie: ' + cookie.name);
|
|
||||||
browser.setCookie(cookie);
|
|
||||||
});
|
|
||||||
|
|
||||||
state.push('Navigating to United FCU');
|
state.push('Navigating to United FCU');
|
||||||
|
|
||||||
// Navigate the page to a URL.
|
|
||||||
await page.goto('https://online.unitedfcu.com/unitedfederalcredituniononline/uux.aspx#/login');
|
await page.goto('https://online.unitedfcu.com/unitedfederalcredituniononline/uux.aspx#/login');
|
||||||
|
|
||||||
state.push(`Current URL: ${page.url()}`);
|
state.push(`Current URL: ${page.url()}`);
|
||||||
|
|
||||||
if (page.url().includes('interstitial')) {
|
if (page.url().includes('interstitial')) {
|
||||||
await page.waitForNavigation();
|
await page.waitForLoadState();
|
||||||
state.push('Already logged in, navigating to dashboard');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page.url().includes('dashboard')) {
|
if (!page.url().includes('dashboard')) {
|
||||||
state.push('Logging in to United FCU');
|
state.push('Logging in to United FCU');
|
||||||
// Type into search box using accessible input name.
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
||||||
await page.locator('aria/Login ID').fill('92830');
|
await page.getByLabel('Login ID').fill('92830');
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
||||||
|
await page.getByLabel('Password').fill('Cmtjlt13');
|
||||||
await page.locator('aria/Password').fill('Cmtjlt13');
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
||||||
|
|
||||||
state.push('Submitting login form');
|
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
|
|
||||||
await page.waitForNavigation();
|
//await page.waitForLoadState();
|
||||||
|
//await new Promise((resolve) => setTimeout(resolve, 5 * 5000));
|
||||||
|
|
||||||
|
while (page.url().includes('interstitial')) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||||
|
await page.waitForLoadState();
|
||||||
|
}
|
||||||
|
|
||||||
const url = page.url();
|
const url = page.url();
|
||||||
state.push(`Current URL after login: ${url}`);
|
state.push(`Current URL after login: ${url}`);
|
||||||
|
|
||||||
@ -99,12 +70,9 @@ export async function pullData(amount = 100) {
|
|||||||
state.push('MFA required, selecting SMS option');
|
state.push('MFA required, selecting SMS option');
|
||||||
console.log('MFA required, please complete the authentication process.');
|
console.log('MFA required, please complete the authentication process.');
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
||||||
|
await page.getByText('SMS: (XXX) XXX-4029').click();
|
||||||
await page.locator('aria/SMS: (XXX) XXX-4029').click();
|
await page.waitForURL('**/mfa/entertarget');
|
||||||
await page.waitForNavigation();
|
await page.getByPlaceholder('Secure Access Code');
|
||||||
//need to do some stuff ehre
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
|
||||||
|
|
||||||
//await page.keyboard.press('Tab');
|
//await page.keyboard.press('Tab');
|
||||||
state.push('Waiting for code input');
|
state.push('Waiting for code input');
|
||||||
needCode = true;
|
needCode = true;
|
||||||
@ -118,32 +86,20 @@ export async function pullData(amount = 100) {
|
|||||||
throw new Error('Code not provided within 5 minutes');
|
throw new Error('Code not provided within 5 minutes');
|
||||||
}
|
}
|
||||||
state.push(`Got code: ${code}`);
|
state.push(`Got code: ${code}`);
|
||||||
|
await page.getByPlaceholder('Secure Access Code').fill(code);
|
||||||
await page.locator('>>> [placeholder="Secure Access Code"]').fill(code);
|
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
|
||||||
//await page.keyboard.type(code);
|
|
||||||
code = null;
|
|
||||||
needCode = false;
|
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
await page.locator('aria/Register Device').click();
|
|
||||||
await page.waitForNavigation();
|
await page.getByText('Access Code Accepted.').waitFor();
|
||||||
|
await page.keyboard.press('Tab');
|
||||||
|
await page.keyboard.press('Tab');
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.waitForURL('**/dashboard');
|
||||||
|
await page.screenshot({ path: 'united-login.png' });
|
||||||
|
state.push('Logged in successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
state.push('Saving cookies');
|
|
||||||
let cookies = await browser.cookies();
|
|
||||||
|
|
||||||
cookies.forEach(async (cookie) => {
|
|
||||||
state.push('Saving cookie: ' + cookie.name);
|
|
||||||
|
|
||||||
// Insert or update the cookie in the database
|
|
||||||
await db`DELETE FROM cookies WHERE name = ${cookie.name}`;
|
|
||||||
|
|
||||||
await db`INSERT INTO cookies (name, value, domain, path, expires, size, httpOnly, secure, session, priority, sameParty, sourceScheme, sourcePort)
|
|
||||||
VALUES (${cookie.name}, ${cookie.value}, ${cookie.domain}, ${cookie.path}, ${cookie.expires}, ${cookie.size}, ${cookie.httpOnly}, ${cookie.secure}, ${cookie.session}, ${cookie.priority}, ${cookie.sameParty}, ${cookie.sourceScheme}, ${cookie.sourcePort})`;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//await new Promise((resolve) => setTimeout(resolve, 60000));
|
|
||||||
|
|
||||||
state.push('Fetching q2token');
|
state.push('Fetching q2token');
|
||||||
const q2token = (await browser.cookies()).find((cookie) => cookie.name === 'q2token')?.value;
|
const q2token = (await browser.cookies()).find((cookie) => cookie.name === 'q2token')?.value;
|
||||||
|
|
||||||
@ -302,6 +258,9 @@ export async function pullData(amount = 100) {
|
|||||||
state.push(`Orphaning transaction: ${orphan.id}`);
|
state.push(`Orphaning transaction: ${orphan.id}`);
|
||||||
await db`UPDATE budget_transaction set transaction_id = null where id = ${orphan.id}`;
|
await db`UPDATE budget_transaction set transaction_id = null where id = ${orphan.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.push('Done');
|
||||||
|
await browser.close();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in pullData:', error);
|
console.error('Error in pullData:', error);
|
||||||
state.push(`Error: ${error.message}`);
|
state.push(`Error: ${error.message}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user