Download server.js from reikernx/no: direct link, hf CLI and curl.
- Browser
- Download file 10.7 kB
-
https://huggingface.co/spaces/reikernx/no/resolve/main/server.js
- Command line
-
hf download hf://spaces/reikernx/no/server.js
-
curl -L -o server.js https://huggingface.co/spaces/reikernx/no/resolve/main/server.js
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'); | |
| }); |