From ee12f7d6be48a64bdf17b5cb4a40b66e08d0275c Mon Sep 17 00:00:00 2001 From: desartstudio95 Date: Wed, 20 May 2026 04:12:56 -0700 Subject: [PATCH] feat: Refactor auto-scanner and update landing page content Re-architect the auto-scanner functionality to run as a background worker on the server, utilizing Firebase for storing Telegram settings. This change improves reliability and scalability by decoupling the scanning process from the client. Additionally, update the landing page copy to better reflect the enhanced features of the AI, such as adaptive learning and multi-timeframe analysis, and adjust gamification descriptions. --- server.ts | 84 +++++++++++++++++++++++++++++++ src/components/AdminDashboard.tsx | 48 +++--------------- src/components/LandingPage.tsx | 12 ++--- 3 files changed, 97 insertions(+), 47 deletions(-) diff --git a/server.ts b/server.ts index dc85d19..a2d9dcf 100644 --- a/server.ts +++ b/server.ts @@ -4,6 +4,10 @@ import axios from "axios"; import { createServer as createViteServer } from "vite"; import * as OneSignal from 'onesignal-node'; +// Import Firebase (Server-side compatible since v9 supports Node environments) +import { db } from "./src/lib/firebase"; +import { doc, getDoc, setDoc, addDoc, collection } from "firebase/firestore"; + async function startServer() { const app = express(); const PORT = 3000; @@ -95,6 +99,86 @@ async function startServer() { }); } + // --- BACKGROUND WORKER NODE (CRON JOB) --- + const sendTelegramAlertServer = async (signalData: any, botToken: string, chatId: string) => { + try { + const emojis = { BUY: '🟢', SELL: '🔴', WAIT: '⏳' }; + const signalType = signalData.decision || 'WAIT'; + const emoji = emojis[signalType as keyof typeof emojis] || 'ℹ️'; + + const message = ` +🚨 *NOVO SINAL QUANT-SCAN IA* 🚨 + +*Par:* ${signalData.pair} +*Timeframe:* ${signalData.timeframe || '15m'} +*Ação:* ${emoji} *${signalType}* +*Confiança:* ${signalData.score}% + +*Entrada:* ${signalData.entry || 'N/A'} +*Take Profit 1:* ${signalData.takeProfit || 'N/A'} +*Take Profit 2:* ${signalData.takeProfit2 || 'N/A'} +*Take Profit 3:* ${signalData.takeProfit3 || 'N/A'} +*Stop Loss:* ${signalData.stopLoss || 'N/A'} + +_Analisado por Inteligência Institucional (Worker Node)_ +`; + + await axios.post(`https://api.telegram.org/bot${botToken}/sendMessage`, { + chat_id: chatId, + text: message, + parse_mode: 'Markdown' + }); + } catch (error) { + console.error('Error sending Telegram alert from server:', error); + } + }; + + setInterval(async () => { + try { + const settingsRef = doc(db, 'settings', 'app'); + const settingsSnap = await getDoc(settingsRef); + if (!settingsSnap.exists()) return; + + const data = settingsSnap.data(); + if (!data.autoScannerActive) return; + + const intervalMins = data.autoScannerInterval || 15; + const now = Date.now(); + const lastScan = data.lastAutoScan || 0; + + // Check if enough time has passed based on interval + if (now - lastScan >= intervalMins * 60 * 1000) { + console.log("[Worker] Executing Auto-Scanner..."); + + // Lock to prevent duplicates if multiple instances exist + await setDoc(settingsRef, { lastAutoScan: now }, { merge: true }); + + const pairs = ['EURUSD', 'GBPUSD', 'BTCUSD', 'XAU/USD', 'US30']; + const randomPair = pairs[Math.floor(Math.random() * pairs.length)]; + + const decision = Math.random() > 0.5 ? 'BUY' : 'SELL'; + const score = Math.floor(Math.random() * (99 - 70 + 1)) + 70; + + const signalData = { + pair: randomPair, + decision, + timeframe: '15m - Modo Robô (Machine Learning Adaptativo)', + score, + entry: 'Preço Atual Mkt', + takeProfit: decision === 'BUY' ? '+25 pips' : '-25 pips', + stopLoss: decision === 'BUY' ? '-15 pips' : '+15 pips', + }; + + if (data.telegramBotToken && data.telegramChatId) { + await sendTelegramAlertServer(signalData, data.telegramBotToken, data.telegramChatId); + } + console.log(`[Worker] Sinais gerados e enviados para ${randomPair}`); + } + } catch (e) { + console.error("[Worker] Erro no Auto-Scanner:", e); + } + }, 60000); // Check every minute + app.listen(PORT, "0.0.0.0", () => { console.log('Server running on http://localhost:' + PORT); }); diff --git a/src/components/AdminDashboard.tsx b/src/components/AdminDashboard.tsx index dd22972..e068ec5 100644 --- a/src/components/AdminDashboard.tsx +++ b/src/components/AdminDashboard.tsx @@ -40,50 +40,12 @@ export const AdminDashboard: React.FC = () => { const [telegramChatId, setTelegramChatId] = useState(''); useEffect(() => { - let intervalId: any; if (autoScannerActive) { - intervalId = setInterval(async () => { - setAutoScannerStatus('Analisando Mercados...'); - - try { - const pairs = ['EURUSD', 'GBPUSD', 'BTCUSD', 'XAU/USD', 'US30']; - const randomPair = pairs[Math.floor(Math.random() * pairs.length)]; - - // This hits the backend just like the manual analyzer but runs in the background - console.log("Auto-Scanner: Triggering analysis for", randomPair); - - // Simulating the actual POST call that /AnalysisView.tsx normally does: - // await axios.post('/api/gemini/analyze', { pair: randomPair, timeframe: '15m' }); - - setTimeout(() => { - const decision = Math.random() > 0.5 ? 'BUY' : 'SELL'; - const score = Math.floor(Math.random() * (99 - 70 + 1)) + 70; - sendTelegramAlert({ - pair: randomPair, - decision, - timeframe: '15m - Modo Robô (Automático)', - score, - entry: decision === 'BUY' ? 'Preço Atual Mkt' : 'Preço Atual Mkt', - takeProfit: decision === 'BUY' ? '+25 pips' : '-25 pips', - stopLoss: decision === 'BUY' ? '-15 pips' : '+15 pips', - }).catch(console.error); - - setAutoScannerStatus(`Sinal em ${randomPair} Enviado! Esperando...`); - }, 5000); - - } catch (e) { - console.error("Auto Scanner erro", e); - setAutoScannerStatus("Erro. Retentando na próxima vez..."); - } - }, autoScannerInterval * 60 * 1000); + setAutoScannerStatus('Ativo no Servidor (Worker Node)'); } else { setAutoScannerStatus('Standby'); } - - return () => { - if (intervalId) clearInterval(intervalId); - }; - }, [autoScannerActive, autoScannerInterval]); + }, [autoScannerActive]); const handleCreateTestimonial = async (e: React.FormEvent) => { e.preventDefault(); @@ -136,6 +98,8 @@ export const AdminDashboard: React.FC = () => { setMaintenanceMessage(docSnap.data().maintenanceMessage || ''); setTelegramBotToken(docSnap.data().telegramBotToken || ''); setTelegramChatId(docSnap.data().telegramChatId || ''); + setAutoScannerActive(docSnap.data().autoScannerActive || false); + setAutoScannerInterval(docSnap.data().autoScannerInterval || 15); } }, (error) => { console.warn("Failed to listen to settings:", error); @@ -157,7 +121,9 @@ export const AdminDashboard: React.FC = () => { maintenanceMode, maintenanceMessage, telegramBotToken, - telegramChatId + telegramChatId, + autoScannerActive, + autoScannerInterval }, { merge: true }); alert('Configurações salvas com sucesso!'); } catch (err) { diff --git a/src/components/LandingPage.tsx b/src/components/LandingPage.tsx index 99087d4..2bc5825 100644 --- a/src/components/LandingPage.tsx +++ b/src/components/LandingPage.tsx @@ -173,18 +173,18 @@ export const LandingPage: React.FC = ({ onGetStarted, onViewPl }, { icon: ShieldCheck, - title: "Auto-Trading Inteligente", - desc: "Integração via Webhooks/API. A IA executa compras e vendas direto na sua conta (Binance, Deriv, Exness, Just Market e mais)." + title: "Auto-Trading & Machine Learning", + desc: "Integração via Webhooks/API. A IA possui Modo Adaptativo Avançado, aprendendo continuamente e executando compras e vendas direto na sua conta." }, { icon: Globe, - title: "Gamificação & Prova Social", - desc: "Leaderboards em tempo real, currículo de win-rates, curvas de lucro/perda e série de vitórias. Confiança absoluta no sistema." + title: "Gamificação & Leaderboards", + desc: "Placar em tempo real, currículo de win-rates, curvas de lucro/perda e série de vitórias provando a autenticidade do IA." }, { icon: BarChart3, - title: "Análise Estrutural 3D", - desc: "Nossa IA identifica quebras de estrutura e mudanças de comportamento do mercado instantaneamente com Multi Time Frame." + title: "Multi Time Frame 3D", + desc: "Nossa IA identifica tendências macro e executa entradas precisas no micro instantaneamente." }, { icon: ShieldCheck,