Download server.js from reikernx/msg: direct link, hf CLI and curl.
- Browser
- Download file 7.34 kB
-
https://huggingface.co/spaces/reikernx/msg/resolve/main/server.js
- Command line
-
hf download hf://spaces/reikernx/msg/server.js
-
curl -L -o server.js https://huggingface.co/spaces/reikernx/msg/resolve/main/server.js
7.34 kB
| const express = require('express'); | |
| const puppeteer = require('puppeteer-extra'); | |
| const StealthPlugin = require('puppeteer-extra-plugin-stealth'); | |
| puppeteer.use(StealthPlugin()); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| // Store browser instance to reuse | |
| let browser = null; | |
| // Middleware | |
| app.use(express.json()); | |
| // Delay function to replace waitForTimeout | |
| const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); | |
| // Initialize browser once on startup | |
| async function initializeBrowser() { | |
| try { | |
| console.log('🚀 Initializing browser...'); | |
| browser = await puppeteer.launch({ | |
| headless: true, // Set to false for debugging | |
| args: ["--no-sandbox", "--disable-setuid-sandbox"] | |
| }); | |
| console.log("✅ Browser initialized successfully!"); | |
| } catch (error) { | |
| console.error("❌ Failed to initialize browser:", error); | |
| throw error; | |
| } | |
| } | |
| // Login function for a given page | |
| async function login(page) { | |
| try { | |
| console.log('🔐 Checking login status...'); | |
| await page.goto("https://getsms.cc/auth/login", { | |
| waitUntil: "networkidle2" | |
| }); | |
| // Check if we're already logged in by looking for the #email field | |
| const isLoginPage = await page.evaluate(() => { | |
| return !!document.querySelector('#email'); | |
| }); | |
| if (!isLoginPage) { | |
| console.log('✅ Already logged in, skipping login process.'); | |
| return; | |
| } | |
| console.log('🔐 Performing login...'); | |
| // Clear any existing form data | |
| await page.evaluate(() => { | |
| const emailInput = document.querySelector('#email'); | |
| const passwordInput = document.querySelector('#password'); | |
| if (emailInput) emailInput.value = ''; | |
| if (passwordInput) passwordInput.value = ''; | |
| }); | |
| // Replace with your actual credentials | |
| await page.type("#email", "reikernx@gmail.com", { delay: 50 }); | |
| await page.type("#password", "Ogombo12", { delay: 50 }); | |
| await Promise.all([ | |
| page.click("input[type=submit]"), | |
| page.waitForNavigation({ waitUntil: "networkidle2" }) | |
| ]); | |
| // Verify login success | |
| const finalUrl = page.url(); | |
| if (finalUrl.includes('/auth/login')) { | |
| throw new Error('Login failed - still on login page'); | |
| } | |
| console.log("✅ Logged in successfully!"); | |
| } catch (error) { | |
| console.error("❌ Failed to login:", error); | |
| throw error; | |
| } | |
| } | |
| // API endpoint to get messages for a phone number | |
| app.get('/api/messages', async (req, res) => { | |
| let page = null; | |
| try { | |
| const { number } = req.query; | |
| if (!number) { | |
| return res.status(400).json({ | |
| error: 'Phone number is required', | |
| message: 'Please provide a phone number in the query parameter: ?number=447414848795' | |
| }); | |
| } | |
| console.log(`📱 Fetching messages for number: ${number}`); | |
| // Create a new page for each request | |
| page = await browser.newPage(); | |
| // Perform login or skip if already logged in | |
| await login(page); | |
| // Navigate to the specific info page | |
| const url = `https://getsms.cc/info/${number}`; | |
| await page.goto(url, { | |
| waitUntil: "networkidle2" | |
| }); | |
| // Verify we didn't get redirected to login page | |
| const finalUrl = page.url(); | |
| if (finalUrl.includes('/auth/login')) { | |
| throw new Error('Session invalid - redirected to login page'); | |
| } | |
| console.log(`✅ Successfully navigated to: ${finalUrl}`); | |
| // Wait for content to load | |
| await delay(2000); | |
| // Extract the latest 5 messages | |
| const lastMessages = await page.evaluate(() => { | |
| const messageElements = document.querySelectorAll('.direct-chat-msg'); | |
| // Double-check we're not seeing login messages | |
| const bodyText = document.body.textContent || ''; | |
| if (bodyText.includes('Login to view')) { | |
| return []; // Return empty array if still showing login message | |
| } | |
| const messages = Array.from(messageElements).map(msg => { | |
| const nameElement = msg.querySelector('.direct-chat-name'); | |
| const timeElement = msg.querySelector('.direct-chat-timestamp'); | |
| const textElement = msg.querySelector('.direct-chat-text'); | |
| // Skip ads/empty messages | |
| const text = textElement?.textContent?.trim() || ''; | |
| if (text.includes('adsbygoogle') || text === '' || text.includes('Login to view')) { | |
| return null; | |
| } | |
| return { | |
| sender: nameElement?.textContent?.trim() || 'Unknown', | |
| time: timeElement?.textContent?.trim() || 'Unknown time', | |
| message: text | |
| }; | |
| }).filter(msg => msg !== null); // Remove null entries (ads) | |
| // Return latest 5 messages | |
| return messages.slice(0, 5); | |
| }); | |
| // Check if we got empty results due to login requirement | |
| if (lastMessages.length === 0) { | |
| const pageContent = await page.evaluate(() => document.body.textContent); | |
| if (pageContent.includes('Login to view')) { | |
| throw new Error('Session invalid - still showing "Login to view"'); | |
| } | |
| } | |
| console.log(`✅ Found ${lastMessages.length} messages for ${number}`); | |
| // Return the response | |
| res.json({ | |
| success: true, | |
| number: number, | |
| timestamp: new Date().toISOString(), | |
| messageCount: lastMessages.length, | |
| messages: lastMessages | |
| }); | |
| } catch (error) { | |
| console.error(`❌ Error fetching messages for ${req.query.number}:`, error); | |
| res.status(500).json({ | |
| success: false, | |
| error: 'Failed to fetch messages', | |
| message: error.message | |
| }); | |
| } finally { | |
| // Close the page to avoid memory leaks | |
| if (page) { | |
| await page.close(); | |
| } | |
| } | |
| }); | |
| // Health check endpoint | |
| app.get('/api/health', (req, res) => { | |
| res.json({ | |
| status: 'OK', | |
| message: 'GetSMS API is running', | |
| timestamp: new Date().toISOString(), | |
| browserStatus: browser ? 'Connected' : 'Disconnected' | |
| }); | |
| }); | |
| // Get available endpoints | |
| app.get('/', (req, res) => { | |
| res.json({ | |
| message: 'GetSMS Message Extraction API', | |
| endpoints: { | |
| 'GET /api/messages?number={phone_number}': 'Get latest 5 messages for a phone number', | |
| 'GET /api/health': 'Check API health status', | |
| 'GET /': 'This help page' | |
| }, | |
| example: { | |
| url: '/api/messages?number=447414848795', | |
| description: 'Get messages for phone number 447414848795' | |
| } | |
| }); | |
| }); | |
| // Graceful shutdown | |
| process.on('SIGINT', async () => { | |
| console.log('\n🔄 Shutting down gracefully...'); | |
| if (browser) { | |
| await browser.close(); | |
| } | |
| process.exit(0); | |
| }); | |
| process.on('SIGTERM', async () => { | |
| console.log('\n🔄 Shutting down gracefully...'); | |
| if (browser) { | |
| await browser.close(); | |
| } | |
| process.exit(0); | |
| }); | |
| // Start server | |
| async function startServer() { | |
| try { | |
| await initializeBrowser(); | |
| app.listen(PORT, () => { | |
| console.log(`\n🌟 GetSMS API Server running on port ${PORT}`); | |
| console.log(`📋 Available endpoints:`); | |
| console.log(` GET http://localhost:${PORT}/api/messages?number=447414848795`); | |
| console.log(` GET http://localhost:${PORT}/api/health`); | |
| console.log(` GET http://localhost:${PORT}/`); | |
| }); | |
| } catch (error) { | |
| console.error('❌ Failed to start server:', error); | |
| process.exit(1); | |
| } | |
| } | |
| // Start the server | |
| startServer(); |