cck / app.js
newservers's picture
Update app.js
2a08770 verified
Raw
History Blame Contribute Delete
15.5 kB
const express = require('express');
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const randomUseragent = require('random-useragent');
const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');
puppeteer.use(StealthPlugin());
const app = express();
app.use(express.json());
// Enhanced random delay function
const randomDelay = (min = 100, max = 300) =>
new Promise(resolve => setTimeout(resolve, Math.random() * (max - min) + min));
// Realistic mouse movement simulation
const humanMouseMove = async (page, selector) => {
const element = await page.$(selector);
const box = await element.boundingBox();
// Simulate realistic mouse path
await page.mouse.move(
box.x + Math.random() * box.width,
box.y + Math.random() * box.height,
{ steps: Math.floor(Math.random() * 10) + 5 }
);
await randomDelay(50, 150);
};
// Human-like typing with realistic patterns
const humanType = async (page, selector, text, options = {}) => {
await page.focus(selector);
await randomDelay(100, 300);
for (let i = 0; i < text.length; i++) {
const char = text[i];
await page.keyboard.type(char);
// Realistic typing delays
let delay = Math.random() * 120 + 50;
// Longer pauses for special characters
if (['.', '@', '_', '-'].includes(char)) {
delay += Math.random() * 100;
}
// Occasional longer pauses (thinking)
if (Math.random() < 0.1) {
delay += Math.random() * 400 + 200;
}
await new Promise(resolve => setTimeout(resolve, delay));
}
};
// Random scrolling to simulate human behavior
const humanScroll = async (page) => {
const scrolls = Math.floor(Math.random() * 3) + 1;
for (let i = 0; i < scrolls; i++) {
const scrollDistance = Math.random() * 500 + 100;
const direction = Math.random() > 0.5 ? 1 : -1;
await page.evaluate((distance, dir) => {
window.scrollBy(0, distance * dir);
}, scrollDistance, direction);
await randomDelay(500, 1500);
}
// Scroll back to top
await page.evaluate(() => window.scrollTo(0, 0));
await randomDelay(300, 800);
};
// Simulate random mouse movements
const simulateHumanActivity = async (page) => {
// Random mouse movements
for (let i = 0; i < Math.random() * 5 + 2; i++) {
await page.mouse.move(
Math.random() * 1920,
Math.random() * 1080,
{ steps: Math.floor(Math.random() * 20) + 10 }
);
await randomDelay(200, 800);
}
// Random clicks in empty areas
if (Math.random() > 0.7) {
await page.mouse.click(Math.random() * 200 + 100, Math.random() * 200 + 100);
await randomDelay(100, 300);
}
};
async function uploadToCatbox(filePath) {
const form = new FormData();
form.append('reqtype', 'fileupload');
form.append('fileToUpload', fs.createReadStream(filePath));
const response = await axios.post('https://catbox.moe/user/api.php', form, {
headers: form.getHeaders(),
});
return response.data;
}
app.post('/login', async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: 'Missing email or password' });
}
let browser;
try {
// Enhanced browser launch options
browser = await puppeteer.launch({
headless: true,
defaultViewport: null,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-blink-features=AutomationControlled',
'--disable-dev-shm-usage',
'--disable-infobars',
'--disable-extensions',
'--disable-plugins',
'--disable-images',
'--disable-javascript-harmony-shipping',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--disable-features=TranslateUI',
'--disable-ipc-flooding-protection',
'--disable-hang-monitor',
'--disable-popup-blocking',
'--disable-prompt-on-repost',
'--disable-sync',
'--disable-domain-reliability',
'--disable-component-extensions-with-background-pages',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--password-store=basic',
'--use-mock-keychain',
'--disable-background-networking',
'--disable-default-apps',
'--disable-translate',
'--disable-device-discovery-notifications',
'--window-size=1920,1080',
'--window-position=0,0',
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
],
ignoreDefaultArgs: ['--enable-automation'],
ignoreHTTPSErrors: true,
});
const page = await browser.newPage();
// Enhanced stealth configurations
await page.evaluateOnNewDocument(() => {
// Remove webdriver property
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
});
// Spoof navigator properties
Object.defineProperty(navigator, 'languages', {
get: () => ['en-US', 'en'],
});
Object.defineProperty(navigator, 'plugins', {
get: () => [
{
0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format", enabledPlugin: "[object Plugin]"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Chrome PDF Plugin"
},
{
0: {type: "application/pdf", suffixes: "pdf", description: "", enabledPlugin: "[object Plugin]"},
description: "",
filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
length: 1,
name: "Chrome PDF Viewer"
}
],
});
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32',
});
Object.defineProperty(navigator, 'hardwareConcurrency', {
get: () => 8,
});
Object.defineProperty(navigator, 'deviceMemory', {
get: () => 8,
});
// Spoof screen properties
Object.defineProperty(screen, 'width', {
get: () => 1920,
});
Object.defineProperty(screen, 'height', {
get: () => 1080,
});
Object.defineProperty(screen, 'colorDepth', {
get: () => 24,
});
Object.defineProperty(screen, 'pixelDepth', {
get: () => 24,
});
// Override permissions
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
// Spoof timezone
Date.prototype.getTimezoneOffset = function() {
return -300; // EST timezone
};
// Remove automation indicators
delete navigator.__proto__.webdriver;
// Mock chrome runtime
window.chrome = {
runtime: {
onConnect: undefined,
onMessage: undefined,
connect: undefined,
sendMessage: undefined,
},
};
// Spoof canvas fingerprinting
const getContext = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function(a, b) {
const context = getContext.call(this, a, b);
if (a === '2d') {
const originalIsPointInPath = context.isPointInPath;
context.isPointInPath = function() {
return originalIsPointInPath.apply(this, arguments);
};
}
return context;
};
// Spoof WebGL fingerprinting
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameter) {
if (parameter === 37445) {
return 'Intel Open Source Technology Center';
}
if (parameter === 37446) {
return 'Mesa DRI Intel(R) Ivybridge Mobile ';
}
return getParameter.call(this, parameter);
};
});
// Set realistic viewport and user agent
const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36';
await page.setUserAgent(userAgent);
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 1,
hasTouch: false,
isLandscape: true,
isMobile: false,
});
// Enhanced HTTP headers
await page.setExtraHTTPHeaders({
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
});
// Request interception for performance
await page.setRequestInterception(true);
page.on('request', (req) => {
const type = req.resourceType();
if (['image', 'stylesheet', 'font', 'media'].includes(type)) {
req.abort();
} else {
req.continue();
}
});
console.log('🌐 Navigating to login page...');
await page.goto('https://sso.crunchyroll.com/login', {
waitUntil: 'networkidle2',
timeout: 60000,
});
// Wait and simulate human behavior
await randomDelay(2000, 4000);
await simulateHumanActivity(page);
await humanScroll(page);
// Wait for form elements with better error handling
try {
await page.waitForSelector('input[name="email"]', { timeout: 30000 });
console.log('πŸ“§ Email input found');
} catch (error) {
console.log('❌ Email input not found, trying alternative selectors');
await page.waitForSelector('input[type="email"], #email, [placeholder*="email" i]', { timeout: 30000 });
}
// Simulate human-like interaction with email field
await humanMouseMove(page, 'input[name="email"]');
await page.click('input[name="email"]');
await randomDelay(500, 1200);
// Clear field first (in case there's placeholder text)
await page.keyboard.down('Control');
await page.keyboard.press('a');
await page.keyboard.up('Control');
await page.keyboard.press('Backspace');
await randomDelay(200, 500);
await humanType(page, 'input[name="email"]', email);
console.log('βœ… Email entered');
await randomDelay(800, 1500);
// Similar approach for password
try {
await page.waitForSelector('input[name="password"]', { timeout: 10000 });
} catch (error) {
await page.waitForSelector('input[type="password"], #password, [placeholder*="password" i]', { timeout: 30000 });
}
await humanMouseMove(page, 'input[name="password"]');
await page.click('input[name="password"]');
await randomDelay(300, 800);
await humanType(page, 'input[name="password"]', password);
console.log('πŸ”’ Password entered');
// Random delay before clicking login
await randomDelay(1000, 2500);
await simulateHumanActivity(page);
// Find and interact with login button
let loginButton;
try {
await page.waitForSelector('button[data-t="login-button"]', { visible: true, timeout: 10000 });
loginButton = 'button[data-t="login-button"]';
} catch (error) {
// Try alternative selectors
const buttonSelectors = [
'button[type="submit"]',
'input[type="submit"]',
'button:contains("Log in")',
'button:contains("Sign in")',
'[role="button"]:contains("Log")',
'.login-button',
'#login-button'
];
for (const selector of buttonSelectors) {
try {
await page.waitForSelector(selector, { visible: true, timeout: 2000 });
loginButton = selector;
break;
} catch (e) {
continue;
}
}
}
if (!loginButton) {
throw new Error('Login button not found');
}
// Screenshot before clicking login
const beforePath = './before-login.png';
await page.screenshot({ path: beforePath, fullPage: true });
const beforeUrl = await uploadToCatbox(beforePath);
console.log('🟑 Before login screenshot uploaded:', beforeUrl);
// Human-like button interaction
await humanMouseMove(page, loginButton);
await randomDelay(200, 500);
// Sometimes hover before clicking
if (Math.random() > 0.5) {
await page.hover(loginButton);
await randomDelay(100, 300);
}
await page.click(loginButton);
console.log('πŸ”„ Login button clicked');
// Wait for navigation or response
try {
await Promise.race([
page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 45000 }),
page.waitForSelector('.error, [class*="error"], [id*="error"]', { timeout: 30000 })
.then(() => { throw new Error('Login error detected'); }),
new Promise(resolve => setTimeout(resolve, 40000)) // Fallback timeout
]);
} catch (navError) {
console.log('⚠️ Navigation wait completed with potential issues');
}
// Additional wait for any dynamic content
await randomDelay(3000, 6000);
// Screenshot after login attempt
const afterPath = './after-login.png';
await page.screenshot({ path: afterPath, fullPage: true });
const afterUrl = await uploadToCatbox(afterPath);
console.log('🟒 After login screenshot uploaded:', afterUrl);
const currentUrl = page.url();
const loginSuccess = !currentUrl.includes('/login') && !currentUrl.includes('sso.crunchyroll.com');
// Additional success indicators
const hasAuthCookie = (await page.cookies()).some(cookie =>
cookie.name.toLowerCase().includes('auth') ||
cookie.name.toLowerCase().includes('session') ||
cookie.name.toLowerCase().includes('token')
);
console.log(`🎯 Login Result: ${loginSuccess ? 'SUCCESS' : 'FAILED'}`);
console.log(`πŸ“ Current URL: ${currentUrl}`);
console.log(`πŸͺ Auth cookies present: ${hasAuthCookie}`);
res.json({
success: loginSuccess,
currentUrl: currentUrl,
userAgent: userAgent,
hasAuthCookie: hasAuthCookie,
screenshots: {
before: beforeUrl,
after: afterUrl
},
timestamp: new Date().toISOString()
});
} catch (err) {
console.error('❌ Error during login:', err);
res.status(500).json({
error: 'Login failed',
details: err.message,
timestamp: new Date().toISOString()
});
} finally {
if (browser) {
await browser.close();
}
}
});
const PORT = process.env.PORT || 7860;
app.listen(PORT, () => {
console.log(`πŸš€ Enhanced Anti-Detection Server running on port ${PORT}`);
console.log(`πŸ›‘οΈ Stealth features enabled: Human typing, mouse movement, scrolling, fingerprint spoofing`);
});