134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
import { chromium } from 'playwright';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
import readline from 'readline';
|
|
|
|
const SESSION_DIR = path.resolve(process.cwd(), './data/browser-session');
|
|
|
|
async function waitForEnter(prompt: string): Promise<void> {
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout,
|
|
});
|
|
|
|
return new Promise((resolve) => {
|
|
rl.question(prompt, () => {
|
|
rl.close();
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
async function manualLogin(): Promise<void> {
|
|
console.log('='.repeat(60));
|
|
console.log('Reddit Bot - Manual Login');
|
|
console.log('='.repeat(60));
|
|
console.log();
|
|
|
|
// Ensure session directory exists
|
|
if (!fs.existsSync(SESSION_DIR)) {
|
|
fs.mkdirSync(SESSION_DIR, { recursive: true });
|
|
}
|
|
|
|
console.log(`Session will be saved to: ${SESSION_DIR}`);
|
|
console.log();
|
|
|
|
const context = await chromium.launchPersistentContext(SESSION_DIR, {
|
|
headless: false,
|
|
viewport: { width: 1280, height: 720 },
|
|
args: ['--disable-blink-features=AutomationControlled'],
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
|
|
console.log('Opening Reddit login page...');
|
|
await page.goto('https://www.reddit.com/login/');
|
|
|
|
console.log();
|
|
console.log('-'.repeat(60));
|
|
console.log('Please log in to Reddit in the browser window.');
|
|
console.log();
|
|
console.log('After logging in successfully:');
|
|
console.log('1. Make sure you see your username in the top right');
|
|
console.log('2. Come back here and press Enter');
|
|
console.log('-'.repeat(60));
|
|
console.log();
|
|
|
|
await waitForEnter('Press Enter when you have logged in... ');
|
|
|
|
// Verify login
|
|
console.log();
|
|
console.log('Verifying login status...');
|
|
|
|
await page.goto('https://www.reddit.com');
|
|
await page.waitForTimeout(3000);
|
|
|
|
const visibleIndicators = [
|
|
'[data-testid="user-drawer-button"]',
|
|
'button[aria-label*="User menu"]',
|
|
];
|
|
|
|
let isLoggedIn = false;
|
|
for (const selector of visibleIndicators) {
|
|
const el = page.locator(selector).first();
|
|
if (await el.isVisible().catch(() => false)) {
|
|
isLoggedIn = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isLoggedIn) {
|
|
const attributeIndicators = [
|
|
'reddit-header-large[is-logged-in="true"]',
|
|
'shreddit-post-overflow-menu[current-user-id]',
|
|
];
|
|
for (const selector of attributeIndicators) {
|
|
const el = await page.$(selector);
|
|
if (el) {
|
|
isLoggedIn = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isLoggedIn) {
|
|
isLoggedIn = await page.evaluate(async () => {
|
|
try {
|
|
const res = await fetch('https://www.reddit.com/api/me.json', { credentials: 'include' });
|
|
if (!res.ok) return false;
|
|
const data = await res.json();
|
|
return Boolean(data && data.name);
|
|
} catch {
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log();
|
|
if (isLoggedIn) {
|
|
console.log('SUCCESS! You are logged in.');
|
|
console.log(`Session saved to: ${SESSION_DIR}`);
|
|
console.log();
|
|
console.log('You can now run the bot with: npm start');
|
|
} else {
|
|
console.log('WARNING: Login could not be verified.');
|
|
console.log('The session has been saved, but you may need to try again.');
|
|
console.log();
|
|
console.log('Tips:');
|
|
console.log('- Make sure you completed the login process');
|
|
console.log('- Try clicking on your profile to ensure the page loaded');
|
|
console.log('- Run this script again if needed');
|
|
}
|
|
|
|
console.log();
|
|
console.log('Closing browser...');
|
|
await context.close();
|
|
|
|
console.log('Done!');
|
|
}
|
|
|
|
manualLogin().catch((error) => {
|
|
console.error('Error during login:', error);
|
|
process.exit(1);
|
|
});
|