no / server.js
reikernx's picture
Update server.js
b483071 verified
Raw
History Blame Contribute Delete
10.7 kB
const express = require("express");
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
const cheerio = require("cheerio");
require('dotenv').config();
// Add stealth plugin
puppeteer.use(StealthPlugin());
const app = express();
const PORT = 7860;
// Browser instance management
let browser = null;
let authenticatedPage = null;
let isLoggedIn = false;
async function getBrowser() {
if (!browser) {
browser = await puppeteer.launch({
headless: "new", // Use new headless mode
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu',
'--disable-web-security',
'--disable-features=VizDisplayCompositor'
]
});
}
return browser;
}
// Get or create authenticated page
async function getAuthenticatedPage() {
if (!authenticatedPage || authenticatedPage.isClosed()) {
const browser = await getBrowser();
authenticatedPage = await setupPage(browser);
isLoggedIn = false; // Reset login status for new page
}
return authenticatedPage;
}
// Login function with extensive debugging
async function performLogin() {
if (isLoggedIn) return true;
const page = await getAuthenticatedPage();
try {
console.log('Performing login...');
console.log('Using email:', process.env.LOGIN_EMAIL ? 'Found' : 'Missing');
console.log('Using password:', process.env.LOGIN_PASSWORD ? 'Found' : 'Missing');
// Navigate to login page
await page.goto('https://getsms.cc/auth/login', {
waitUntil: 'networkidle2',
timeout: 30000
});
console.log('Loaded login page');
// Wait for form to be visible
await page.waitForSelector('form#login', { timeout: 10000 });
console.log('Found login form');
// Take screenshot before login (for debugging)
// await page.screenshot({ path: 'before-login.png' });
// Clear and fill email field
await page.evaluate(() => {
const emailField = document.querySelector('input[name="mail"]');
if (emailField) emailField.value = '';
});
await page.focus('input[name="mail"]');
await page.type('input[name="mail"]', process.env.LOGIN_EMAIL, { delay: 50 });
// Clear and fill password field
await page.evaluate(() => {
const passwordField = document.querySelector('input[name="password"]');
if (passwordField) passwordField.value = '';
});
await page.focus('input[name="password"]');
await page.type('input[name="password"]', process.env.LOGIN_PASSWORD, { delay: 50 });
console.log('Filled login form');
// Wait a moment before submitting
await new Promise(resolve => setTimeout(resolve, 1000));
// Submit form with different approach
await page.evaluate(() => {
const form = document.querySelector('form#login');
if (form) {
form.submit();
}
});
console.log('Submitted form, waiting for response...');
// Wait for either navigation or page update
try {
await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 });
console.log('Navigation detected');
} catch (e) {
console.log('No navigation, checking for page updates...');
await new Promise(resolve => setTimeout(resolve, 3000));
}
const currentUrl = page.url();
console.log('Current URL after login attempt:', currentUrl);
// Take screenshot after login (for debugging)
// await page.screenshot({ path: 'after-login.png' });
// Check for error messages on the page
const errorMessage = await page.evaluate(() => {
const errorElements = document.querySelectorAll('.alert-danger, .text-danger, .error, .alert-error');
for (let el of errorElements) {
if (el.textContent.trim()) {
return el.textContent.trim();
}
}
return null;
});
if (errorMessage) {
console.log('Login error message:', errorMessage);
return false;
}
// More comprehensive login success check
const loginCheck = await page.evaluate(() => {
const url = window.location.href;
const bodyText = document.body.innerText.toLowerCase();
// Check various indicators of successful login
const indicators = {
notOnLoginPage: !url.includes('/auth/login'),
hasLogoutLink: document.querySelector('[href*="logout"]') !== null,
hasUserDropdown: document.querySelector('.dropdown-toggle') !== null,
hasUserProfile: document.querySelector('.user-profile') !== null,
hasDashboard: bodyText.includes('dashboard'),
hasWelcome: bodyText.includes('welcome'),
hasMyAccount: bodyText.includes('my account'),
urlIndicatesSuccess: url.includes('/dashboard') || url.includes('/account') || url === 'https://getsms.cc/'
};
console.log('Login indicators:', indicators);
return {
success: Object.values(indicators).some(v => v),
indicators,
url,
pageTitle: document.title
};
});
console.log('Login check result:', loginCheck);
if (loginCheck.success) {
isLoggedIn = true;
console.log('✅ Login successful - authenticated session established');
return true;
} else {
console.log('❌ Login failed - no success indicators found');
// Get page content for debugging
const pageContent = await page.evaluate(() => {
return document.body.innerText.substring(0, 1000);
});
console.log('Page content after login:', pageContent);
return false;
}
} catch (error) {
console.error('Login error:', error);
return false;
}
}
// Enhanced page setup for maximum stealth
async function setupPage(browser) {
const page = await browser.newPage();
// Set viewport to common resolution
await page.setViewport({ width: 1366, height: 768 });
// Set realistic user agent
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
// Set additional headers
await page.setExtraHTTPHeaders({
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,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',
});
return page;
}
// Scraper function for numbers list with stealth
async function scrapeUK(pageNum = 1) {
const browser = await getBrowser();
const page = await setupPage(browser);
try {
const url = pageNum === 1
? "https://getsms.cc/temporary-phone-numbers/UK"
: `https://getsms.cc/temporary-phone-numbers/UK/${pageNum}`;
// Navigate with realistic options
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 30000
});
// Add random delay to mimic human behavior
await new Promise(resolve => setTimeout(resolve, Math.random() * 2000 + 1000));
// Get page content
const content = await page.content();
const $ = cheerio.load(content);
const results = [];
$(".card").each((i, el) => {
const number = $(el).find("p.p-0.m-0.font-weight-bold").text().trim();
const timeAgo = $(el).find("p.p-0.m-0.small").text().trim();
const link = $(el).find("a.btn.btn-primary").attr("href");
if (number && timeAgo && link) {
results.push({
number,
timeAgo,
link: `https://getsms.cc${link}`,
});
}
});
return results;
} catch (error) {
console.error('Error scraping UK numbers:', error);
throw error;
} finally {
await page.close();
}
}
// Scraper function for messages with stealth
async function scrapeMessages(number) {
const browser = await getBrowser();
const page = await setupPage(browser);
try {
const url = `https://getsms.cc/info/${number}`;
// Navigate with realistic options
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 30000
});
// Add random delay
await new Promise(resolve => setTimeout(resolve, Math.random() * 2000 + 1000));
// Get page content
const content = await page.content();
const $ = cheerio.load(content);
const messages = [];
$(".direct-chat-msg").each((i, el) => {
const from = $(el).find(".direct-chat-name").text().trim();
const timeAgo = $(el).find("time").text().trim();
const text = $(el).find(".direct-chat-text").text().trim();
// Skip ads/empty messages
if (from && text) {
messages.push({ from, timeAgo, text });
}
});
// Return latest 3 (newest first)
return messages.slice(-3).reverse();
} catch (error) {
console.error('Error scraping messages:', error);
throw error;
} finally {
await page.close();
}
}
// Endpoint: UK numbers
app.get(["/uk", "/uk/:page"], async (req, res) => {
try {
const page = parseInt(req.params.page) || 1;
const numbers = await scrapeUK(page);
res.json({
country: "United Kingdom",
page,
count: numbers.length,
numbers,
});
} catch (err) {
console.error("Error:", err.message);
res.status(500).json({ error: "Failed to scrape numbers" });
}
});
// Endpoint: messages
app.get("/msg/:number", async (req, res) => {
try {
const number = req.params.number;
const messages = await scrapeMessages(number);
res.json({
number,
count: messages.length,
messages,
});
} catch (err) {
console.error("Error:", err.message);
res.status(500).json({ error: "Failed to scrape messages" });
}
});
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('Shutting down gracefully...');
if (authenticatedPage && !authenticatedPage.isClosed()) {
await authenticatedPage.close();
}
if (browser) {
await browser.close();
}
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('Shutting down gracefully...');
if (authenticatedPage && !authenticatedPage.isClosed()) {
await authenticatedPage.close();
}
if (browser) {
await browser.close();
}
process.exit(0);
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
console.log('Using Puppeteer with stealth mode to avoid detection');
});