| |
| |
| |
| |
| |
| |
| |
|
|
| const admin = require("firebase-admin"); |
| const express = require("express"); |
| const helmet = require("helmet"); |
| const cors = require("cors"); |
| const natural = require("natural"); |
| const http = require("http"); |
| const { Server } = require("socket.io"); |
| const os = require("os"); |
| const cron = require("node-cron"); |
| const { GoogleGenerativeAI } = require("@google/generative-ai"); |
| const https = require("https"); |
| const { pipeline } = require("stream"); |
| const { promisify } = require("util"); |
| const streamPipeline = promisify(pipeline); |
| const initExtensions = require('./server-extensions'); |
|
|
| |
| const app = express(); |
| app.set('trust proxy', 2); |
| const PORT = process.env.PORT || 7860; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| const REQUIRED_ENV = ['FIREBASE_SERVICE_ACCOUNT', 'GEMINI_API_KEY', 'GROQ_API_KEY', 'ADMIN_ID', 'TITAN_GATEWAY_KEY', 'TITAN_RELAY_KEY']; |
| const missingEnv = REQUIRED_ENV.filter(k => !process.env[k]); |
| if (missingEnv.length > 0) { |
| console.error(`\x1b[31m[FATAL] Missing required environment variables: ${missingEnv.join(', ')}\x1b[0m`); |
| console.error('\x1b[31m[FATAL] Set them in Hugging Face Space → Settings → Repository secrets\x1b[0m'); |
| process.exit(1); |
| } |
|
|
| |
| let SERVICE_ACCOUNT; |
| try { |
| SERVICE_ACCOUNT = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT); |
| } catch (e) { |
| console.error('\x1b[31m[FATAL] FIREBASE_SERVICE_ACCOUNT is not valid JSON. Paste the full serviceAccountKey.json content.\x1b[0m'); |
| process.exit(1); |
| } |
|
|
| const ADMIN_ID = process.env.ADMIN_ID; |
|
|
| |
| const ROYAL_FAMILY = [ |
| process.env.ADMIN_ID, |
| "jcVOBGfUpkVnZOI8CQ0HRelRsed2" |
| ]; |
|
|
| |
| const GEMINI_API_KEY = process.env.GEMINI_API_KEY; |
| const genAI = new GoogleGenerativeAI(GEMINI_API_KEY); |
| const geminiModel = genAI.getGenerativeModel({ model: "gemini-2.5-flash-lite" }); |
|
|
| |
| const GROQ_API_KEY = process.env.GROQ_API_KEY; |
| const GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"; |
| const GROQ_MARKET_MODEL = "compound-beta"; |
|
|
| |
| |
| |
| const MAILER_URL = process.env.MAILER_URL; |
| const MAILER_TOKEN = process.env.MAILER_TOKEN; |
|
|
| async function sendTitanEmail(to, subject, htmlBody) { |
| if (!MAILER_URL) throw new Error('MAILER_URL not set in HF Secrets'); |
| if (!MAILER_TOKEN) throw new Error('MAILER_TOKEN not set in HF Secrets'); |
|
|
| const toStr = Array.isArray(to) ? to.join(',') : to; |
| const payload = JSON.stringify({ token: MAILER_TOKEN, to: toStr, subject, htmlBody }); |
|
|
| |
| return new Promise((resolve, reject) => { |
| const url = new URL(MAILER_URL); |
| const options = { |
| hostname: url.hostname, |
| path: url.pathname + url.search, |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Content-Length': Buffer.byteLength(payload) |
| } |
| }; |
|
|
| function makeRequest(reqOptions, body, redirectCount = 0) { |
| if (redirectCount > 5) return reject(new Error('Too many redirects')); |
| const req = https.request(reqOptions, (res) => { |
| |
| if ((res.statusCode === 301 || res.statusCode === 302 || res.statusCode === 307) && res.headers.location) { |
| const redirectUrl = new URL(res.headers.location); |
| res.resume(); |
| |
| const newOpts = { |
| hostname: redirectUrl.hostname, |
| path: redirectUrl.pathname + redirectUrl.search, |
| method: res.statusCode === 307 ? reqOptions.method : 'GET', |
| headers: { 'Content-Type': 'application/json' } |
| }; |
| return makeRequest(newOpts, res.statusCode === 307 ? body : null, redirectCount + 1); |
| } |
|
|
| let d = ''; |
| res.on('data', c => d += c); |
| res.on('end', () => { |
| try { |
| |
| const parsed = JSON.parse(d); |
| if (parsed.status !== 'success') reject(new Error(parsed.message || 'Non-success status')); |
| else resolve(parsed); |
| } catch { |
| |
| if (res.statusCode >= 200 && res.statusCode < 300) { |
| resolve({ status: 'success', note: 'HTML response treated as success' }); |
| } else { |
| reject(new Error(`Non-JSON response (${res.statusCode}): ${d.slice(0, 100)}`)); |
| } |
| } |
| }); |
| }); |
| req.setTimeout(20000, () => { req.destroy(); reject(new Error('Mailer timeout')); }); |
| req.on('error', reject); |
| if (body) req.write(body); |
| req.end(); |
| } |
|
|
| makeRequest(options, payload); |
| }); |
| } |
|
|
| |
| const SERVER_START_TIME = Date.now(); |
|
|
| |
| if (!admin.apps.length) { |
| admin.initializeApp({ |
| credential: admin.credential.cert(SERVICE_ACCOUNT), |
| databaseURL: `https://${SERVICE_ACCOUNT.project_id}.firebaseio.com` |
| }); |
| } |
| const db = admin.firestore(); |
|
|
| |
| app.use(helmet({ |
| contentSecurityPolicy: { |
| directives: { |
| defaultSrc: ["'self'"], |
| styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"], |
| fontSrc: ["'self'", "https://fonts.gstatic.com"], |
| scriptSrc: ["'self'", "'unsafe-inline'"], |
| imgSrc: ["'self'", "data:"], |
| connectSrc: ["'self'"] |
| } |
| }, |
| crossOriginEmbedderPolicy: false, |
| hsts: { maxAge: 31536000, includeSubDomains: true } |
| })); |
|
|
| app.use(cors({ origin: true, credentials: true })); |
| app.use(express.json({ limit: '30mb' })); |
| app.use(express.urlencoded({ extended: true, limit: '30mb' })); |
|
|
| |
| async function logSys(mod, msg, type = 'info') { |
| const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19); |
| const colors = { |
| info: '\x1b[36m', |
| success: '\x1b[32m', |
| warning: '\x1b[33m', |
| error: '\x1b[31m', |
| system: '\x1b[35m', |
| cyber: '\x1b[34m', |
| royal: '\x1b[95m', |
| ai: '\x1b[96m' |
| }; |
| const reset = '\x1b[0m'; |
| const color = colors[type] || colors.info; |
| console.log(`${color}[${timestamp}] [${mod}]${reset} ${msg}`); |
| } |
|
|
| |
| function maskUid(uid) { |
| if (!uid || uid.length < 10) return '****'; |
| return uid.substring(0, 4) + '••••••••••••••••' + uid.substring(uid.length - 4); |
| } |
|
|
| |
| async function analyzeSentiment(text) { |
| try { |
| const analyzer = new natural.SentimentAnalyzer('English', natural.PorterStemmer, 'afinn'); |
| const tokenizer = new natural.WordTokenizer(); |
| const tokens = tokenizer.tokenize(text); |
| const sentiment = analyzer.getSentiment(tokens); |
| return { |
| score: sentiment, |
| category: sentiment > 0.5 ? 'positive' : sentiment < -0.5 ? 'negative' : 'neutral', |
| confidence: Math.abs(sentiment) |
| }; |
| } catch (e) { |
| return { score: 0, category: 'neutral', confidence: 0 }; |
| } |
| } |
|
|
| |
| class SentinelMK2 { |
| constructor() { |
| this.bannedPatterns = [ |
| /hack(er|ing)?\s*guide/i, |
| /crack\s*software/i, |
| /bypass\s*security/i, |
| /ddos\s*tool/i, |
| /virus\s*generator/i, |
| /credit\s*card\s*generator/i |
| ]; |
| this.suspiciousKeywords = ['password', 'login', 'admin', 'root', 'exploit', 'vulnerability']; |
| this.userReputation = new Map(); |
| this.reportPenalties = { |
| 'spam': -5, |
| 'harassment': -15, |
| 'fake_identity': -10, |
| 'fake identity': -10 |
| }; |
| } |
|
|
| async analyzeComment(comment) { |
| const analysis = { |
| riskLevel: 'low', |
| flags: [], |
| action: 'none', |
| confidence: 0 |
| }; |
|
|
| this.bannedPatterns.forEach(pattern => { |
| if (pattern.test(comment.text)) { |
| analysis.flags.push('banned_pattern'); |
| analysis.riskLevel = 'critical'; |
| analysis.confidence += 0.7; |
| } |
| }); |
|
|
| const links = (comment.text.match(/https?:\/\/[^\s]+/g) || []).length; |
| if (links > 2) { |
| analysis.flags.push('excessive_links'); |
| analysis.riskLevel = Math.max(analysis.riskLevel, 'high'); |
| analysis.confidence += 0.3; |
| } |
|
|
| const sentiment = await analyzeSentiment(comment.text); |
| if (sentiment.category === 'negative' && sentiment.confidence > 0.6) { |
| analysis.flags.push('negative_sentiment'); |
| analysis.riskLevel = Math.max(analysis.riskLevel, 'medium'); |
| analysis.confidence += 0.2; |
| } |
|
|
| const userRep = this.userReputation.get(comment.userId) || 0; |
| if (userRep < -5) { |
| analysis.flags.push('low_reputation_user'); |
| analysis.riskLevel = 'high'; |
| analysis.confidence += 0.4; |
| } |
|
|
| if (analysis.riskLevel === 'critical') { |
| analysis.action = 'delete_ban'; |
| } else if (analysis.riskLevel === 'high') { |
| analysis.action = 'delete_warn'; |
| } else if (analysis.riskLevel === 'medium') { |
| analysis.action = 'flag_review'; |
| } |
| return analysis; |
| } |
|
|
| async monitorComments() { |
| logSys('SENTINEL_MK2', '🛡️ Advanced comment monitoring activated', 'system'); |
| db.collectionGroup('comments').onSnapshot(async (snapshot) => { |
| snapshot.docChanges().forEach(async (change) => { |
| if (change.type === 'added') { |
| const comment = change.doc.data(); |
| const commentId = change.doc.id; |
|
|
| |
| if (ROYAL_FAMILY.includes(comment.userId)) { |
| logSys('SENTINEL_MK2', `👑 Royal user ${maskUid(comment.userId)} - Immunity shield active`, 'royal'); |
| return; |
| } |
|
|
| if (comment.userId === ADMIN_ID) return; |
|
|
| const analysis = await this.analyzeComment(comment); |
| if (analysis.action !== 'none') { |
| await this.handleViolation(comment, commentId, analysis); |
| } |
| await this.updateUserReputation(comment.userId, analysis); |
| } |
| }); |
| }, (error) => { |
| logSys('SENTINEL_MK2', `⚠️ Listener Error (Backoff/Connection): ${error.message}`, 'error'); |
| }); |
| } |
|
|
| async monitorReports() { |
| logSys('SENTINEL_MK2', '⚖️ Real-Time Report & Ban System activated', 'system'); |
| db.collection('reports') |
| .where('status', '==', 'pending') |
| .onSnapshot(async (snapshot) => { |
| snapshot.docChanges().forEach(async (change) => { |
| if (change.type === 'added') { |
| const report = change.doc.data(); |
| const reportId = change.doc.id; |
|
|
| |
| if (ROYAL_FAMILY.includes(report.reportedUserId)) { |
| logSys('SENTINEL_MK2', `👑 Report rejected - Royal immunity for ${maskUid(report.reportedUserId)}`, 'royal'); |
| await db.collection('reports').doc(reportId).update({ |
| status: 'rejected', |
| reviewedAt: admin.firestore.FieldValue.serverTimestamp(), |
| rejection_reason: 'Immunity Shield - Royal Family member', |
| processedBy: 'SENTINEL_MK2_ROYAL_GUARD' |
| }); |
| return; |
| } |
|
|
| await this.processReport(report, reportId); |
| } |
| }); |
| }, (error) => { |
| logSys('SENTINEL_MK2', `⚠️ Report Listener Error (Backoff/Connection): ${error.message}`, 'error'); |
| }); |
| } |
|
|
| async processReport(report, reportId) { |
| try { |
| logSys('SENTINEL_MK2', `⚖️ Processing report ${reportId} for user ${maskUid(report.reportedUserId)}`, 'info'); |
| const reportType = (report.reason || report.type || 'spam').toLowerCase(); |
| const penalty = this.reportPenalties[reportType] || -5; |
| let reputation = this.userReputation.get(report.reportedUserId) || 100; |
| reputation += penalty; |
| this.userReputation.set(report.reportedUserId, reputation); |
|
|
| await db.collection('user_reputation').doc(report.reportedUserId).set({ |
| userId: report.reportedUserId, |
| score: reputation, |
| updatedAt: admin.firestore.FieldValue.serverTimestamp(), |
| lastPenalty: { amount: penalty, reason: reportType, reportId } |
| }, { merge: true }); |
|
|
| logSys('SENTINEL_MK2', `📉 User ${maskUid(report.reportedUserId)} reputation: ${reputation} (${penalty} penalty)`, 'warning'); |
|
|
| let aiVerdict = `Reputation updated: ${reputation} points`; |
| let actionsTaken = []; |
|
|
| if (reputation <= 50 && reputation > 0) { |
| await db.collection('users').doc(report.reportedUserId).set({ |
| isShadowBanned: true, |
| shadowBanReason: `Low reputation (${reputation}) from report ${reportId}`, |
| shadowBannedAt: admin.firestore.FieldValue.serverTimestamp() |
| }, { merge: true }); |
| aiVerdict = `SHADOW BAN applied. User reputation: ${reputation}`; |
| actionsTaken.push('shadow_ban'); |
| logSys('SENTINEL_MK2', `👤 User ${maskUid(report.reportedUserId)} shadow banned (reputation: ${reputation})`, 'warning'); |
| } |
|
|
| if (reputation <= 0) { |
| try { |
| await admin.auth().revokeRefreshTokens(report.reportedUserId); |
| await db.collection('users').doc(report.reportedUserId).set({ |
| banned: true, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| banReason: `Automatic ban: Reputation dropped to ${reputation}`, |
| bannedBy: 'SENTINEL_MK2_AUTOMOD', |
| reportId |
| }, { merge: true }); |
| await db.collection('banned_users').doc(report.reportedUserId).set({ |
| userId: report.reportedUserId, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason: 'automatic_ban_reputation', |
| finalReputation: reputation, |
| reportId, |
| violations: [reportType] |
| }); |
| aiVerdict = `PERMABAN applied. Reputation dropped to ${reputation}. Firebase token revoked.`; |
| actionsTaken.push('permaban', 'token_revoked'); |
| logSys('SENTINEL_MK2', `🚨 PERMABAN user ${maskUid(report.reportedUserId)} (reputation: ${reputation})`, 'error'); |
| } catch (authError) { |
| logSys('SENTINEL_MK2', `Failed to revoke tokens for ${maskUid(report.reportedUserId)}: ${authError.message}`, 'error'); |
| } |
| } |
|
|
| await db.collection('reports').doc(reportId).update({ |
| status: 'reviewed', |
| reviewedAt: admin.firestore.FieldValue.serverTimestamp(), |
| ai_verdict: aiVerdict, |
| actions_taken: actionsTaken, |
| reputation_after: reputation, |
| penalty_applied: penalty, |
| processedBy: 'SENTINEL_MK2_AUTOMOD' |
| }); |
| logSys('SENTINEL_MK2', `✅ Report ${reportId} processed. Verdict: ${aiVerdict}`, 'success'); |
| } catch (error) { |
| logSys('SENTINEL_MK2', `❌ Failed to process report ${reportId}: ${error.message}`, 'error'); |
| await db.collection('reports').doc(reportId).update({ |
| status: 'error', |
| error: error.message, |
| processedAt: admin.firestore.FieldValue.serverTimestamp() |
| }); |
| } |
| } |
|
|
| async handleViolation(comment, commentId, analysis) { |
| const commentRef = db.collection('comments').doc(commentId); |
| switch (analysis.action) { |
| case 'delete_ban': |
| await commentRef.delete(); |
| await db.collection('banned_users').doc(comment.userId).set({ |
| userId: comment.userId, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason: 'automatic_ban', |
| violation: analysis.flags.join(', '), |
| commentPreview: comment.text.substring(0, 100) |
| }); |
| logSys('SENTINEL_MK2', `🚨 BANNED user ${maskUid(comment.userId)} for critical violation`, 'error'); |
| break; |
| case 'delete_warn': |
| await commentRef.delete(); |
| await db.collection('user_warnings').doc(`${comment.userId}_${Date.now()}`).set({ |
| userId: comment.userId, |
| warnedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason: analysis.flags.join(', '), |
| commentId, |
| action: 'comment_deleted' |
| }); |
| logSys('SENTINEL_MK2', `⚠️ Warned user ${maskUid(comment.userId)}`, 'warning'); |
| break; |
| case 'flag_review': |
| await commentRef.update({ flagged: true, flagReason: analysis.flags.join(', ') }); |
| logSys('SENTINEL_MK2', `🚩 Flagged comment for review`, 'warning'); |
| break; |
| } |
| await db.collection('security_logs').add({ |
| action: analysis.action, |
| userId: comment.userId, |
| commentId, |
| analysis, |
| timestamp: admin.firestore.FieldValue.serverTimestamp() |
| }); |
| } |
|
|
| async updateUserReputation(userId, analysis) { |
| let reputation = this.userReputation.get(userId) || 0; |
| switch (analysis.action) { |
| case 'delete_ban': reputation -= 10; break; |
| case 'delete_warn': reputation -= 3; break; |
| case 'flag_review': reputation -= 1; break; |
| default: reputation += 1; |
| } |
| this.userReputation.set(userId, reputation); |
| if (reputation < -5) { |
| await db.collection('user_reputation').doc(userId).set({ |
| userId, |
| score: reputation, |
| updatedAt: admin.firestore.FieldValue.serverTimestamp() |
| }, { merge: true }); |
| } |
| } |
| } |
|
|
| |
| class JanitorMK2 { |
| constructor() { |
| this.messageRetentionDays = 30; |
| } |
|
|
| async cleanOldMessages() { |
| const cutoff = new Date(Date.now() - this.messageRetentionDays * 24 * 60 * 60 * 1000); |
| try { |
| const snapshot = await db.collection('titan_news') |
| .where('timestamp', '<', cutoff) |
| .get(); |
|
|
| if (!snapshot.empty) { |
| const batch = db.batch(); |
| snapshot.docs.forEach(doc => { |
| const data = doc.data(); |
| |
| if (data.userId && ROYAL_FAMILY.includes(data.userId)) { |
| logSys('JANITOR_MK2', `👑 Preserving royal message from ${maskUid(data.userId)}`, 'royal'); |
| return; |
| } |
| batch.delete(doc.ref); |
| }); |
| await batch.commit(); |
| logSys('JANITOR_MK2', `🧹 Deleted ${snapshot.size} old messages (older than ${this.messageRetentionDays} days)`, 'info'); |
| } |
| } catch (error) { |
| logSys('JANITOR_MK2', `❌ Cleanup error: ${error.message}`, 'error'); |
| } |
| } |
| } |
|
|
| |
|
|
| |
| |
| |
| function getGregorianDateString(date) { |
| return date.toLocaleDateString('en-US', { |
| weekday: 'long', |
| year: 'numeric', |
| month: 'long', |
| day: 'numeric' |
| }); |
| } |
|
|
| |
| |
| |
| |
| function getHijriDateString(date) { |
| try { |
| return new Intl.DateTimeFormat('en-US-u-ca-islamic-umalqura', { |
| day: 'numeric', |
| month: 'long', |
| year: 'numeric' |
| }).format(date); |
| } catch (e) { |
| |
| return 'Hijri date unavailable'; |
| } |
| } |
|
|
| |
| |
| |
| |
| async function generateRiddleContent() { |
| try { |
| logSys('TIME_AWARE_AI', '🧩 Generating daily riddle...', 'ai'); |
|
|
| const today = new Date(); |
| const gregorianDate = getGregorianDateString(today); |
| const hijriDate = getHijriDateString(today); |
|
|
| |
| let recentRiddles = []; |
| try { |
| const recentSnap = await db.collection('riddle_history') |
| .orderBy('timestamp', 'desc') |
| .limit(30) |
| .get(); |
| recentRiddles = recentSnap.docs.map(d => d.data().riddleEn || ''); |
| logSys('TIME_AWARE_AI', `📚 Loaded ${recentRiddles.length} past riddles for dedup check`, 'info'); |
| } catch (e) { |
| logSys('TIME_AWARE_AI', '⚠️ Could not load riddle history (continuing anyway)', 'warning'); |
| } |
|
|
| const avoidSection = recentRiddles.length > 0 |
| ? `\n- DO NOT repeat or closely resemble any of these recent riddles:\n${recentRiddles.map((r, i) => ` ${i + 1}. "${r}"`).join('\n')}` |
| : ''; |
|
|
| const categories = ['nature', 'technology', 'food', 'animals', 'everyday objects', 'science', 'history', 'mathematics', 'human body', 'space']; |
| const category = categories[Math.floor(Math.random() * categories.length)]; |
|
|
| const prompt = `You are Titan Nexus AI. Create ONE original, clever riddle about "${category}". |
| |
| Rules: |
| - Must be genuinely clever and creative — not a common or well-known riddle |
| - Suitable for all ages |
| - Include the answer clearly at the end after " — answer: " |
| - Avoid ANY special characters that break JSON (no quotes, apostrophes inside strings) |
| - Date context: ${gregorianDate} / ${hijriDate}${avoidSection} |
| |
| Reply with ONLY valid JSON, nothing else: |
| {"riddle":{"en":"[Write a creative riddle about ${category}] — answer: [the answer]","ar":"[اكتب فزورة مبتكرة عن ${category}] — الإجابة: [الجواب]"}}`.trim(); |
|
|
| const result = await geminiModel.generateContent(prompt); |
| const response = await result.response; |
| let text = response.text().trim(); |
|
|
| |
| text = text |
| .replace(/^```json\s*/i, '') |
| .replace(/^```\s*/i, '') |
| .replace(/```\s*$/i, '') |
| |
| .replace(/[\u201C\u201D\u201E\u201F\u2033\u2036\u00AB\u00BB]/g, '"') |
| .replace(/[\u2018\u2019\u201A\u201B\u2032\u2035]/g, "'") |
| .trim(); |
|
|
| |
| const start = text.indexOf('{'); |
| const end = text.lastIndexOf('}'); |
| if (start === -1 || end === -1) throw new Error(`No JSON object found in: ${text.substring(0, 120)}`); |
| let jsonStr = text.slice(start, end + 1).replace(/[\x00-\x1F\x7F]/g, ' '); |
| let content; |
| try { |
| content = JSON.parse(jsonStr); |
| } catch (pe) { |
| const enM = jsonStr.match(/"en"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| const arM = jsonStr.match(/"ar"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| if (enM && arM) content = { riddle: { en: enM[1], ar: arM[1] } }; |
| else throw new Error(`JSON parse failed: ${pe.message}`); |
| } |
|
|
| if (!content.riddle || !content.riddle.en || !content.riddle.ar) { |
| throw new Error('Invalid riddle format from AI'); |
| } |
|
|
| |
| try { |
| await db.collection('riddle_history').add({ |
| riddleEn: content.riddle.en, |
| riddleAr: content.riddle.ar, |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| gregorianDate, |
| hijriDate |
| }); |
| logSys('TIME_AWARE_AI', `💾 Riddle saved to history`, 'info'); |
| } catch (e) { |
| logSys('TIME_AWARE_AI', '⚠️ Could not save riddle to history', 'warning'); |
| } |
|
|
| logSys('TIME_AWARE_AI', `✅ Riddle generated successfully.`, 'success'); |
| return content; |
|
|
| } catch (error) { |
| logSys('TIME_AWARE_AI', `❌ Riddle generation failed: ${error.message}`, 'error'); |
|
|
| |
| const fallbackRiddles = [ |
| { en: "I have cities, but no houses. Mountains, but no trees. Water, but no fish. What am I? (A map)", ar: "لدي مدن بلا منازل، وجبال بلا أشجار، ومياه بلا أسماك. من أنا؟ (الخريطة)" }, |
| { en: "The more you take, the more you leave behind. What am I? (Footsteps)", ar: "كلما أخذت مني ازددت. ما أنا؟ (الخطوات)" }, |
| { en: "I speak without a mouth and hear without ears. I have no body, but I come alive with wind. What am I? (An echo)", ar: "أتكلم بلا فم وأسمع بلا أذنين. ما أنا؟ (الصدى)" }, |
| { en: "I can fly without wings. I can cry without eyes. Wherever I go, darkness flies. What am I? (A cloud)", ar: "أطير بلا أجنحة وأبكي بلا عيون. ما أنا؟ (السحابة)" }, |
| { en: "I run, but I have no legs. I have a mouth, but I never talk. What am I? (A river)", ar: "أجري ولا أملك قدمين، ولدي فم لكنني لا أتكلم. ما أنا؟ (النهر)" }, |
| { en: "What has hands but cannot clap? (A clock)", ar: "ما الذي له يدان لكن لا يصفق؟ (الساعة)" }, |
| { en: "I get shorter as I grow older. What am I? (A candle)", ar: "أصير أقصر كلما كبرت. ما أنا؟ (الشمعة)" }, |
| { en: "I have a neck but no head, and I wear a cap. What am I? (A bottle)", ar: "لدي عنق بلا رأس وأرتدي غطاءً. ما أنا؟ (الزجاجة)" }, |
| { en: "What can you catch but not throw? (A cold)", ar: "ماذا يمكنك أن تلتقط لكن لا ترمي؟ (نزلة البرد)" }, |
| { en: "I have teeth but cannot eat. What am I? (A comb)", ar: "لدي أسنان لكنني لا آكل. ما أنا؟ (المشط)" } |
| ]; |
| const pick = fallbackRiddles[Math.floor(Math.random() * fallbackRiddles.length)]; |
| return { riddle: pick }; |
| } |
| } |
|
|
| |
| async function generateRoyalReport(stats) { |
| try { |
| logSys('GEMINI_AI', '👑 Generating royal report...', 'ai'); |
|
|
| const prompt = `You are generating a professional daily report for the administrators of Titan Nexus platform. |
| |
| Server Statistics: |
| - Uptime: ${stats.uptime} |
| - Memory Usage: ${stats.memory.percentage} |
| - Online Users: ${stats.connections.registered} |
| - Total Connections: ${stats.connections.total} |
| - Platform: ${stats.platform} |
| - Sentinel Status: ${stats.sentinel} |
| |
| Generate a concise, professional summary report. |
| Respond ONLY with valid JSON — no markdown, no backticks, no extra text. |
| |
| Required format: |
| {"en":"English summary (2-3 sentences, professional tone)","ar":"ملخص بالعربية"} |
| |
| Make it sound like a human executive summary, not a robot report.`; |
|
|
| const result = await geminiModel.generateContent(prompt); |
| const response = await result.response; |
| let text = response.text().trim(); |
| text = text |
| .replace(/```json\s*/gi, '').replace(/```\s*/gi, '') |
| .replace(/[\u201C\u201D\u201E\u201F\u2033\u2036\u00AB\u00BB]/g, '"') |
| .replace(/[\u2018\u2019\u201A\u201B\u2032\u2035]/g, "'") |
| .trim(); |
|
|
| const start = text.indexOf('{'); |
| const end = text.lastIndexOf('}'); |
| if (start === -1 || end === -1) throw new Error('No JSON object found in AI response'); |
| let rJson = text.slice(start, end + 1).replace(/[\x00-\x1F\x7F]/g, ' '); |
| let report; |
| try { report = JSON.parse(rJson); } |
| catch (pe) { |
| const enM = rJson.match(/"en"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| const arM = rJson.match(/"ar"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| if (enM && arM) report = { en: enM[1], ar: arM[1] }; |
| else throw new Error(`Parse failed: ${pe.message}`); |
| } |
|
|
| if (!report.en || !report.ar) throw new Error('Missing en/ar fields in report'); |
|
|
| logSys('GEMINI_AI', '✅ Royal report generated successfully', 'success'); |
| return report; |
| } catch (error) { |
| logSys('GEMINI_AI', `❌ Failed to generate royal report: ${error.message}`, 'error'); |
| return { |
| en: `Daily Report: Server uptime ${stats.uptime}. ${stats.connections.registered} users online. All systems operational.`, |
| ar: `تقرير يومي: وقت تشغيل الخادم ${stats.uptime}. ${stats.connections.registered} مستخدم متصل. جميع الأنظمة تعمل.` |
| }; |
| } |
| } |
|
|
| |
| |
| |
| |
|
|
| async function groqFetch(userPrompt, maxTokens = 150) { |
| const body = JSON.stringify({ |
| model: GROQ_MARKET_MODEL, |
| messages: [{ role: "user", content: userPrompt }], |
| temperature: 0.1, |
| max_tokens: maxTokens |
| }); |
| return new Promise((resolve, reject) => { |
| const url = new URL(GROQ_API_URL); |
| const req = https.request({ |
| hostname: url.hostname, path: url.pathname, method: 'POST', |
| headers: { |
| 'Authorization': `Bearer ${GROQ_API_KEY}`, |
| 'Content-Type': 'application/json', |
| 'Content-Length': Buffer.byteLength(body) |
| } |
| }, (res) => { |
| let d = ''; |
| res.on('data', c => d += c); |
| res.on('end', () => res.statusCode >= 200 && res.statusCode < 300 |
| ? resolve(d) |
| : reject(new Error(`${res.statusCode}: ${d.slice(0, 200)}`))); |
| }); |
| req.setTimeout(40000, () => { req.destroy(); reject(new Error('Timeout')); }); |
| req.on('error', reject); |
| req.write(body); req.end(); |
| }); |
| } |
|
|
| function parseJSON(raw) { |
| const parsed = JSON.parse(raw); |
| let text = (parsed.choices?.[0]?.message?.content || '') |
| .replace(/```json\s*/gi, '').replace(/```\s*/gi, '') |
| .replace(/[\u201C\u201D\u00AB\u00BB]/g, '"') |
| .replace(/[\x00-\x1F\x7F]/g, ' ').trim(); |
| const s = text.indexOf('{'), e = text.lastIndexOf('}'); |
| if (s === -1 || e === -1) throw new Error('No JSON'); |
| return JSON.parse(text.slice(s, e + 1)); |
| } |
|
|
| async function fetchMarketData() { |
| logSys('MARKET_AI', '📡 Fetching market data...', 'ai'); |
| const ozToGram = 0.0321507; |
| let goldUsdOz = 0, usdEgp = 50.9, eurEgp = 55.0, gbpEgp = 64.0, sarEgp = 13.6; |
| let stocks = {}; |
|
|
| |
| try { |
| const raw = await new Promise((resolve, reject) => { |
| const req = https.request({ hostname: 'open.er-api.com', path: '/v6/latest/USD', method: 'GET' }, (res) => { |
| let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d)); |
| }); |
| req.setTimeout(8000, () => { req.destroy(); reject(new Error('Timeout')); }); |
| req.on('error', reject); req.end(); |
| }); |
| const fx = JSON.parse(raw); |
| if (fx.rates?.EGP) { |
| usdEgp = fx.rates.EGP; |
| eurEgp = usdEgp / fx.rates.EUR; |
| gbpEgp = usdEgp / fx.rates.GBP; |
| sarEgp = usdEgp / fx.rates.SAR; |
| logSys('MARKET_AI', `✅ FX: 1 USD = ${usdEgp.toFixed(2)} EGP`, 'success'); |
| } |
| } catch (e) { logSys('MARKET_AI', `⚠️ FX: ${e.message.slice(0,50)}`, 'warning'); } |
|
|
| |
| const goldAPIs = [ |
| { host: 'api.gold-api.com', path: '/price/XAU' }, |
| { host: 'api.metals.live', path: '/v1/spot/gold' }, |
| { host: 'data.fixer.io', path: '/api/latest?access_key=free&symbols=XAU,USD' }, |
| ]; |
| for (const api of goldAPIs) { |
| if (goldUsdOz > 0) break; |
| try { |
| const raw = await new Promise((resolve, reject) => { |
| const req = https.request({ hostname: api.host, path: api.path, method: 'GET' }, (res) => { |
| let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d)); |
| }); |
| req.setTimeout(7000, () => { req.destroy(); reject(new Error('Timeout')); }); |
| req.on('error', reject); req.end(); |
| }); |
| const g = JSON.parse(raw); |
| |
| const candidate = parseFloat( |
| g.price || g.gold || g.XAU || |
| (g.rates?.XAU ? 1 / g.rates.XAU : 0) || |
| (Array.isArray(g) ? (g[0]?.price || Object.values(g[0])[0]) : 0) |
| ) || 0; |
| if (candidate > 1000 && candidate < 10000) { |
| goldUsdOz = candidate; |
| logSys('MARKET_AI', `✅ Gold spot: $${goldUsdOz.toFixed(2)}/oz (${api.host})`, 'success'); |
| } |
| } catch (e) { logSys('MARKET_AI', `⚠️ Gold API ${api.host}: ${e.message.slice(0,40)}`, 'warning'); } |
| } |
|
|
| |
| try { |
| const body = JSON.stringify({ |
| model: 'llama-3.3-70b-versatile', |
| messages: [{ role: 'user', content: 'Give approximate current market values: S&P500 index, NASDAQ composite, Dow Jones, EGX30 Egypt stock exchange, Bitcoin USD price, Brent crude oil USD/barrel. Reply JSON only: {"sp":"","nq":"","dj":"","eg":"","bt":"","br":""}' }], |
| temperature: 0.1, max_tokens: 100 |
| }); |
| const raw = await new Promise((resolve, reject) => { |
| const url = new URL(GROQ_API_URL); |
| const req = https.request({ |
| hostname: url.hostname, path: url.pathname, method: 'POST', |
| headers: { 'Authorization': `Bearer ${GROQ_API_KEY}`, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } |
| }, (res) => { |
| let d = ''; res.on('data', c => d += c); |
| res.on('end', () => res.statusCode < 300 ? resolve(d) : reject(new Error(`${res.statusCode}: ${d.slice(0,100)}`))); |
| }); |
| req.setTimeout(15000, () => { req.destroy(); reject(new Error('Timeout')); }); |
| req.on('error', reject); req.write(body); req.end(); |
| }); |
| stocks = parseJSON(raw); |
| logSys('MARKET_AI', `✅ Stocks: SP500=${stocks.sp} BTC=${stocks.bt}`, 'success'); |
| } catch (e) { logSys('MARKET_AI', `⚠️ Stocks: ${e.message.slice(0,80)}`, 'warning'); } |
|
|
| |
| |
| const localPremium = 1.07; |
| const g24Egp = goldUsdOz ? Math.round(goldUsdOz * usdEgp * ozToGram * localPremium) : 0; |
| const g21Egp = g24Egp ? Math.round(g24Egp * 21 / 24) : 0; |
| const g18Egp = g24Egp ? Math.round(g24Egp * 18 / 24) : 0; |
| const g21Sar = goldUsdOz ? Math.round(goldUsdOz * 3.75 * ozToGram * 21 / 24) : 0; |
| const g24Aed = goldUsdOz ? Math.round(goldUsdOz * 3.674 * ozToGram) : 0; |
|
|
| return { |
| gold: { |
| egypt_21k: g21Egp ? g21Egp.toString() : 'N/A', |
| egypt_24k: g24Egp ? g24Egp.toString() : 'N/A', |
| egypt_18k: g18Egp ? g18Egp.toString() : 'N/A', |
| global_usd_oz: goldUsdOz ? goldUsdOz.toFixed(2) : 'N/A', |
| saudi_21k: g21Sar ? g21Sar.toString() : 'N/A', |
| uae_24k: g24Aed ? g24Aed.toString() : 'N/A', |
| trend: 'stable', change_pct: 'N/A' |
| }, |
| markets: { |
| sp500: { v: stocks.sp || 'N/A', c: 'N/A', t: '➡️' }, |
| nasdaq: { v: stocks.nq || 'N/A', c: 'N/A', t: '➡️' }, |
| dow: { v: stocks.dj || 'N/A', c: 'N/A', t: '➡️' }, |
| egx30: { v: stocks.eg || 'N/A', c: 'N/A', t: '➡️' }, |
| brent: { v: stocks.br || 'N/A', c: 'N/A', t: '➡️' }, |
| btc: { v: stocks.bt || 'N/A', c: 'N/A', t: '➡️' } |
| }, |
| fx: { |
| usd_egp: usdEgp.toFixed(2), |
| eur_egp: eurEgp.toFixed(2), |
| gbp_egp: gbpEgp.toFixed(2), |
| sar_egp: sarEgp.toFixed(2) |
| }, |
| summary: { en: 'Market data updated.', ar: 'تم تحديث بيانات السوق.' } |
| }; |
| } |
|
|
| |
| |
| |
| async function broadcastPrayerTimes() { |
| try { |
| const today = new Date(); |
| const day = today.getDate(), month = today.getMonth() + 1, year = today.getFullYear(); |
|
|
| |
| const prayerData = await new Promise((resolve, reject) => { |
| const req = https.request({ |
| hostname: 'api.aladhan.com', |
| path: `/v1/timingsByCity/${day}-${month}-${year}?city=Cairo&country=Egypt&method=5`, |
| method: 'GET' |
| }, (res) => { |
| let d = ''; |
| res.on('data', c => d += c); |
| res.on('end', () => resolve(JSON.parse(d))); |
| }); |
| req.setTimeout(10000, () => { req.destroy(); reject(new Error('Timeout')); }); |
| req.on('error', reject); |
| req.end(); |
| }); |
|
|
| const t = prayerData.data?.timings; |
| if (!t) throw new Error('No timings data'); |
|
|
| const dateStr = getGregorianDateString(today); |
| const hijriStr = getHijriDateString(today); |
|
|
| const body = `🕌 مواقيت الصلاة — القاهرة |
| 📅 ${dateStr} | 🌙 ${hijriStr} |
| ━━━━━━━━━━━━━━━━━━━━ |
| 🌅 الفجر: ${t.Fajr} |
| 🌄 الشروق: ${t.Sunrise} |
| ☀️ الظهر: ${t.Dhuhr} |
| 🌤️ العصر: ${t.Asr} |
| 🌆 المغرب: ${t.Maghrib} |
| 🌙 العشاء: ${t.Isha} |
| ━━━━━━━━━━━━━━━━━━━━ |
| تقبل الله طاعتكم 🤲`; |
|
|
| await db.collection('notifications').add({ |
| title: `🕌 مواقيت الصلاة — ${dateStr}`, |
| body, type: 'PRAYER_TIMES', userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), read: false |
| }); |
| io.emit('prayer_times', { title: `🕌 مواقيت الصلاة`, body, timings: t }); |
| logSys('PRAYER', '✅ Prayer times broadcast sent', 'success'); |
| } catch (e) { |
| logSys('PRAYER', `❌ Prayer times failed: ${e.message}`, 'error'); |
| } |
| } |
|
|
| |
| |
| |
| async function broadcastDailyQuote() { |
| try { |
| const today = new Date(); |
| const dateStr = getGregorianDateString(today); |
| const hijriStr = getHijriDateString(today); |
| const hour = today.getHours(); |
| const period = hour < 12 ? 'صباحية' : 'مسائية'; |
|
|
| const result = await geminiModel.generateContent( |
| `اكتب تحية ${period} جميلة وحكمة إسلامية ملهمة. |
| أجب بـ JSON فقط (بدون أي نص خارجه): |
| {"g":"[اكتب التحية هنا]","q":"[اكتب الحكمة هنا]","s":"[اكتب المصدر هنا]"}` |
| ); |
| let text = result.response.text().trim() |
| .replace(/```json\s*/gi, '').replace(/```\s*/gi, '') |
| .replace(/[\u201C\u201D\u00AB\u00BB]/g, '"') |
| .replace(/[\x00-\x1F\x7F]/g, ' '); |
|
|
| const s = text.indexOf('{'), e = text.lastIndexOf('}'); |
| if (s === -1) throw new Error('No JSON'); |
|
|
| let q; |
| try { |
| q = JSON.parse(text.slice(s, e + 1)); |
| } catch (pe) { |
| |
| const gM = text.match(/"g"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| const qM = text.match(/"q"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| const sM = text.match(/"s"\s*:\s*"((?:[^"\\]|\\.)*)"/); |
| q = { g: gM?.[1] || '', q: qM?.[1] || '', s: sM?.[1] || '' }; |
| } |
|
|
| const icon = hour < 12 ? '🌅' : '🌆'; |
| const title = hour < 12 ? '🌅 صباح الخير' : '🌆 مساء الخير'; |
| const body = `${icon} ${q.g || ''}\n\n✨ "${q.q || ''}"\n— ${q.s || ''}\n\n📅 ${dateStr} | 🌙 ${hijriStr}`; |
|
|
| await db.collection('notifications').add({ |
| title, body, type: 'DAILY_QUOTE', userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), read: false |
| }); |
| io.emit('daily_quote', { title, body }); |
| logSys('QUOTE', '✅ Daily quote broadcast sent', 'success'); |
| } catch (e) { |
| logSys('QUOTE', `❌ Daily quote failed: ${e.message}`, 'error'); |
| } |
| } |
|
|
| |
| |
| |
| async function broadcastArabicNews() { |
| try { |
| const dateStr = getGregorianDateString(new Date()); |
| |
| const raw = await groqFetch( |
| `Top 3 Arab world news today. JSON: {"n":[{"t":"headline","s":"summary"},{"t":"","s":""},{"t":"","s":""}]}`, |
| 250 |
| ); |
| const parsed = parseJSON(raw); |
| const news = parsed.n || parsed.news || []; |
| if (!news.length) throw new Error('No news items'); |
|
|
| const icons = ['1️⃣','2️⃣','3️⃣']; |
| const body = `📰 أبرز الأخبار — ${dateStr}\n━━━━━━━━━━━━━━━━━━━━\n` + |
| news.slice(0, 3).map((n, i) => `${icons[i]} ${n.t || n.title || ''}\n ${n.s || n.summary || ''}`).join('\n\n') + |
| '\n━━━━━━━━━━━━━━━━━━━━\nTitan Nexus News'; |
|
|
| await db.collection('notifications').add({ |
| title: `📰 أخبار اليوم — ${dateStr}`, |
| body, type: 'NEWS_SUMMARY', userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), read: false |
| }); |
| io.emit('news_update', { title: `📰 أخبار اليوم`, body }); |
| logSys('NEWS', '✅ Arabic news broadcast sent', 'success'); |
| } catch (e) { |
| logSys('NEWS', `❌ News broadcast failed: ${e.message}`, 'error'); |
| } |
| } |
|
|
| function formatMarketNotification(data, dateStr, hijriStr, timeStr) { |
| const g = data.gold || {}; |
| const m = data.markets || {}; |
| const c = data.fx || {}; |
| const ti = (t) => t === 'up' ? '📈' : t === 'down' ? '📉' : '➡️'; |
| const mRow = (label, obj) => `${label}: ${obj?.v || 'N/A'}`; |
|
|
| const bodyEn = ` |
| ┌─────────────────────────────┐ |
| │ 📈 TITAN NEXUS MARKET REPORT │ |
| └─────────────────────────────┘ |
| 📅 ${dateStr} |
| 🌙 ${hijriStr} |
| ⏰ ${timeStr} |
| |
| 🥇 ══ GOLD PRICES ══ |
| 🇪🇬 Egypt 21K › ${g.egypt_21k || 'N/A'} EGP/g |
| 🇪🇬 Egypt 24K › ${g.egypt_24k || 'N/A'} EGP/g |
| 🇪🇬 Egypt 18K › ${g.egypt_18k || 'N/A'} EGP/g |
| 🌍 Global › $${g.global_usd_oz || 'N/A'} USD/oz |
| 🇸🇦 Saudi 21K › ${g.saudi_21k || 'N/A'} SAR/g |
| 🇦🇪 UAE 24K › ${g.uae_24k || 'N/A'} AED/g |
| |
| 📊 ══ GLOBAL MARKETS ══ |
| 🇺🇸 S&P 500 › ${m.sp500?.v || 'N/A'} |
| 🇺🇸 NASDAQ › ${m.nasdaq?.v || 'N/A'} |
| 🇺🇸 Dow Jones › ${m.dow?.v || 'N/A'} |
| 🇪🇬 EGX 30 › ${m.egx30?.v || 'N/A'} |
| 🛢️ Brent Oil › ${m.brent?.v || 'N/A'} USD/bbl |
| ₿ Bitcoin › $${m.btc?.v || 'N/A'} |
| |
| 💱 ══ EXCHANGE RATES ══ |
| 💵 USD › ${c.usd_egp || 'N/A'} EGP |
| 💶 EUR › ${c.eur_egp || 'N/A'} EGP |
| 💷 GBP › ${c.gbp_egp || 'N/A'} EGP |
| 🇸🇦 SAR › ${c.sar_egp || 'N/A'} EGP |
| |
| ⚡ Titan Nexus Market Intelligence |
| `.trim(); |
|
|
| const bodyAr = ` |
| ┌─────────────────────────────┐ |
| │ 📈 تقرير السوق اليومي │ |
| └─────────────────────────────┘ |
| 📅 ${dateStr} |
| 🌙 ${hijriStr} |
| ⏰ ${timeStr} |
| |
| 🥇 ══ أسعار الذهب ══ |
| 🇪🇬 مصر عيار 21 › ${g.egypt_21k || 'N/A'} جنيه/جرام |
| 🇪🇬 مصر عيار 24 › ${g.egypt_24k || 'N/A'} جنيه/جرام |
| 🇪🇬 مصر عيار 18 › ${g.egypt_18k || 'N/A'} جنيه/جرام |
| 🌍 عالمي › $${g.global_usd_oz || 'N/A'} دولار/أوقية |
| 🇸🇦 السعودية 21 › ${g.saudi_21k || 'N/A'} ريال/جرام |
| 🇦🇪 الإمارات 24 › ${g.uae_24k || 'N/A'} درهم/جرام |
| |
| 📊 ══ الأسواق العالمية ══ |
| 🇺🇸 S&P 500 › ${m.sp500?.v || 'N/A'} |
| 🇺🇸 NASDAQ › ${m.nasdaq?.v || 'N/A'} |
| 🇺🇸 داو جونز › ${m.dow?.v || 'N/A'} |
| 🇪🇬 EGX 30 › ${m.egx30?.v || 'N/A'} |
| 🛢️ برنت › ${m.brent?.v || 'N/A'} دولار/برميل |
| ₿ بيتكوين › $${m.btc?.v || 'N/A'} |
| |
| 💱 ══ أسعار الصرف ══ |
| 💵 دولار › ${c.usd_egp || 'N/A'} جنيه |
| 💶 يورو › ${c.eur_egp || 'N/A'} جنيه |
| 💷 إسترليني › ${c.gbp_egp || 'N/A'} جنيه |
| 🇸🇦 ريال › ${c.sar_egp || 'N/A'} جنيه |
| |
| ⚡ Titan Nexus Market Intelligence |
| `.trim(); |
|
|
| return { bodyEn, bodyAr }; |
| } |
|
|
| |
| |
| |
| async function broadcastMarketUpdate() { |
| logSys('MARKET_AI', '🌅 Starting morning market broadcast...', 'system'); |
|
|
| const today = new Date(); |
| const dateStr = getGregorianDateString(today); |
| const hijriStr = getHijriDateString(today); |
| const timeStr = today.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true }); |
|
|
| |
| let data = null; |
| for (let attempt = 1; attempt <= 3; attempt++) { |
| data = await fetchMarketData(); |
| if (data) break; |
| if (attempt < 3) { |
| |
| const waitMs = attempt === 1 ? 30000 : 60000; |
| logSys('MARKET_AI', `⏳ Waiting ${waitMs/1000}s before retry ${attempt + 1}...`, 'warning'); |
| await new Promise(r => setTimeout(r, waitMs)); |
| } |
| } |
|
|
| if (!data) { |
| logSys('MARKET_AI', '❌ All attempts failed. Skipping market broadcast.', 'error'); |
| return; |
| } |
|
|
| const { bodyEn, bodyAr } = formatMarketNotification(data, dateStr, hijriStr, timeStr); |
|
|
| |
| await db.collection('notifications').add({ |
| title: `📈 تقرير السوق اليومي — ${dateStr}`, |
| titleEn: `📈 Daily Market Report — ${dateStr}`, |
| body: bodyEn, |
| bodyAr: bodyAr, |
| type: 'MARKET_REPORT', |
| userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false, |
| marketData: data, |
| meta: { |
| gregorianDate: dateStr, |
| hijriDate: hijriStr, |
| fetchedAt: timeStr, |
| engine: 'GROQ_COMPOUND_MARKET_v1' |
| } |
| }); |
|
|
| |
| io.emit('market_update', { |
| title: `📈 Daily Market Report — ${dateStr}`, |
| bodyEn, |
| bodyAr, |
| marketData: data, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| logSys('MARKET_AI', `✅ Market report broadcast to ${io.sockets.sockets.size} connections`, 'success'); |
| } |
|
|
| |
| function initCronJobs() { |
|
|
| |
| cron.schedule('0 */6 * * *', async () => { |
| logSys('CRON', '⏳ 6-Hour cycle triggered — Generating daily riddle...', 'system'); |
|
|
| try { |
| const content = await generateRiddleContent(); |
| const riddleEn = content.riddle.en; |
| const riddleAr = content.riddle.ar; |
|
|
| |
| await db.collection('notifications').add({ |
| title: `🧩 فزورة Titan Nexus اليومية`, |
| body: riddleEn, |
| bodyAr: riddleAr, |
| type: 'DAILY_RIDDLE', |
| userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false, |
| meta: { |
| gregorianDate: getGregorianDateString(new Date()), |
| hijriDate: getHijriDateString(new Date()), |
| engine: 'TIME_AWARE_v14_RIDDLE' |
| } |
| }); |
|
|
| logSys('CRON', `✅ Daily riddle broadcast sent.`, 'success'); |
| } catch (error) { |
| logSys('CRON', `❌ 6-Hour riddle broadcast failed: ${error.message}`, 'error'); |
| } |
| }); |
|
|
| |
| cron.schedule('59 23 * * *', async () => { |
| logSys('CRON', '🌙 Royal report generation initiated', 'system'); |
| try { |
| const stats = getServerStats(); |
| const report = await generateRoyalReport(stats); |
|
|
| |
| for (const royalId of ROYAL_FAMILY) { |
| await db.collection('notifications').add({ |
| title: '👑 Daily Royal Report', |
| body: report.en, |
| bodyAr: report.ar, |
| type: 'ROYAL_REPORT', |
| userId: royalId, |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| stats: stats |
| }); |
| logSys('CRON', `👑 Royal report sent to ${royalId}`, 'royal'); |
| } |
|
|
| logSys('CRON', '✅ Royal reports sent to all family members', 'success'); |
| } catch (error) { |
| logSys('CRON', `❌ Royal report failed: ${error.message}`, 'error'); |
| } |
| }); |
|
|
| logSys('CRON', '📅 Automated schedules initialized (6h riddle + 11:59 PM royal report)', 'success'); |
|
|
| |
| cron.schedule('0 8 * * *', async () => { |
| logSys('CRON', '🌅 Morning market broadcast triggered (08:00)', 'system'); |
| try { await broadcastMarketUpdate(); } catch (e) { logSys('CRON', `❌ Market: ${e.message}`, 'error'); } |
| }); |
|
|
| |
| cron.schedule('0 15 * * *', async () => { |
| logSys('CRON', '🔔 Afternoon market update triggered (15:00)', 'system'); |
| try { await broadcastMarketUpdate(); } catch (e) { logSys('CRON', `❌ Market: ${e.message}`, 'error'); } |
| }); |
|
|
| |
| |
| |
| cron.schedule('0 1 * * *', async () => { |
| logSys('CRON', '🕌 Prayer times broadcast triggered (01:00 Cairo)', 'system'); |
| try { await broadcastPrayerTimes(); } catch (e) { logSys('CRON', `❌ Prayer: ${e.message}`, 'error'); } |
| }); |
|
|
| |
| cron.schedule('0 7 * * *', async () => { |
| logSys('CRON', '💡 Morning quote triggered (07:00)', 'system'); |
| try { await broadcastDailyQuote(); } catch (e) { logSys('CRON', `❌ Quote: ${e.message}`, 'error'); } |
| }); |
|
|
| |
| cron.schedule('0 18 * * *', async () => { |
| logSys('CRON', '💡 Evening quote triggered (18:00)', 'system'); |
| try { await broadcastDailyQuote(); } catch (e) { logSys('CRON', `❌ Quote: ${e.message}`, 'error'); } |
| }); |
|
|
| |
| cron.schedule('0 10 * * *', async () => { |
| logSys('CRON', '📰 Arabic news broadcast triggered (10:00)', 'system'); |
| try { await broadcastArabicNews(); } catch (e) { logSys('CRON', `❌ News: ${e.message}`, 'error'); } |
| }); |
| } |
|
|
| |
| cron.schedule('0 22 * * *', async () => { |
| logSys('GAME_MASTER', '🏆 Calculating Titan Gravity top players...', 'system'); |
|
|
| try { |
| const snapshot = await db.collection('titan_ghosts') |
| .orderBy('arcade_points', 'desc') |
| .limit(3) |
| .get(); |
|
|
| if (snapshot.empty) { |
| logSys('GAME_MASTER', '⚠️ No players found in rankings.', 'warning'); |
| return; |
| } |
|
|
| const medals = ['🥇', '🥈', '🥉']; |
| const titles = ['سيد الجاذبية (المركز الأول)', 'الوصيف (المركز الثاني)', 'المحارب (المركز الثالث)']; |
| const bonusPoints = [100, 50, 25]; |
|
|
| const batch = db.batch(); |
| let rank = 0; |
|
|
| snapshot.forEach(doc => { |
| const userId = doc.id; |
| const userData = doc.data(); |
| const currentPoints = userData.arcade_points || 0; |
|
|
| if (currentPoints === 0) return; |
|
|
| const msgEn = `Congratulations Champion! 🥳\nYou achieved rank #${rank + 1} in Titan Gravity with ${currentPoints} points.\nReward: +${bonusPoints[rank]} Bonus Points!`; |
| const msgAr = `مبروك يا بطل! 🥳\nلقد حققت ${medals[rank]} ${titles[rank]} في لعبة Titan Gravity برصيد ${currentPoints} نقطة.\nالجائزة: +${bonusPoints[rank]} نقطة إضافية!`; |
|
|
| const notifRef = db.collection('notifications').doc(); |
| batch.set(notifRef, { |
| title: `${medals[rank]} تكريم الأوائل`, |
| body: msgEn, |
| bodyAr: msgAr, |
| type: 'GAME_AWARD', |
| userId: userId, |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false, |
| rank: rank + 1 |
| }); |
|
|
| const userRef = db.collection('titan_ghosts').doc(userId); |
| batch.update(userRef, { |
| arcade_points: admin.firestore.FieldValue.increment(bonusPoints[rank]) |
| }); |
|
|
| logSys('GAME_MASTER', `🏆 Award sent to Rank #${rank + 1}: ${maskUid(userId)} (${currentPoints} pts)`, 'success'); |
| rank++; |
| }); |
|
|
| await batch.commit(); |
| logSys('GAME_MASTER', '✅ Top 3 players awarded & bonuses added.', 'success'); |
|
|
| } catch (error) { |
| logSys('GAME_MASTER', `❌ Failed to award players: ${error.message}`, 'error'); |
| } |
| }); |
|
|
| |
| const server = http.createServer(app); |
| const io = new Server(server, { |
| cors: { origin: "*", methods: ["GET", "POST"] } |
| }); |
|
|
| const onlineUsers = new Map(); |
|
|
| async function sendPushNotification(targetId, payload) { |
| try { |
| if (!targetId || !payload) return; |
| const userDoc = await db.collection('users').doc(targetId).get(); |
| const fcmToken = userDoc.exists ? userDoc.data().fcmToken : null; |
| if (!fcmToken) { |
| logSys('PUSH', `No FCM token for user ${targetId}`, 'warning'); |
| return; |
| } |
| const message = { |
| token: fcmToken, |
| notification: { |
| title: payload.title || 'New message', |
| body: payload.body || payload.msg || '' |
| }, |
| data: payload.data || {} |
| }; |
| await admin.messaging().send(message); |
| logSys('PUSH', `📲 Push sent to user ${targetId}`, 'success'); |
| } catch (error) { |
| logSys('PUSH', `❌ Failed to send push to ${targetId}: ${error.message}`, 'error'); |
| } |
| } |
|
|
| |
| function getServerStats() { |
| const uptimeMs = Date.now() - SERVER_START_TIME; |
| const uptimeHours = Math.floor(uptimeMs / (1000 * 60 * 60)); |
| const uptimeMinutes = Math.floor((uptimeMs % (1000 * 60 * 60)) / (1000 * 60)); |
|
|
| const memUsage = process.memoryUsage(); |
| const heapUsedMB = (memUsage.heapUsed / 1024 / 1024).toFixed(2); |
| const heapTotalMB = (memUsage.heapTotal / 1024 / 1024).toFixed(2); |
|
|
| const cpuLoad = os.loadavg(); |
| const totalSocketConnections = io.sockets.sockets.size; |
|
|
| return { |
| uptime: `${uptimeHours}h ${uptimeMinutes}m`, |
| uptimeMs, |
| memory: { |
| heapUsed: `${heapUsedMB} MB`, |
| heapTotal: `${heapTotalMB} MB`, |
| percentage: ((memUsage.heapUsed / memUsage.heapTotal) * 100).toFixed(1) + '%' |
| }, |
| connections: { |
| registered: onlineUsers.size, |
| total: totalSocketConnections |
| }, |
| cpuLoad: { |
| '1min': cpuLoad[0].toFixed(2), |
| '5min': cpuLoad[1].toFixed(2), |
| '15min': cpuLoad[2].toFixed(2) |
| }, |
| sentinel: 'Active', |
| platform: os.platform(), |
| nodeVersion: process.version |
| }; |
| } |
|
|
| |
| async function writeBlackboxResponse(message, level = 'SUCCESS', data = null) { |
| try { |
| await db.collection('titan_blackbox').add({ |
| type: 'CMD_RES', |
| message, |
| level, |
| data, |
| ts: admin.firestore.FieldValue.serverTimestamp() |
| }); |
| logSys('BLACKBOX', `📝 Response written: ${message}`, 'info'); |
| } catch (error) { |
| logSys('BLACKBOX', `❌ Failed to write response: ${error.message}`, 'error'); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| async function sweepOrphanedData() { |
| logSys('SWEEPER', '🔍 Starting orphaned data sweep...', 'system'); |
|
|
| |
| const validUids = new Set(); |
| let pageToken; |
|
|
| try { |
| do { |
| const listResult = await admin.auth().listUsers(1000, pageToken); |
| listResult.users.forEach(userRecord => validUids.add(userRecord.uid)); |
| pageToken = listResult.pageToken; |
| } while (pageToken); |
|
|
| logSys('SWEEPER', `✅ Loaded ${validUids.size} valid UIDs from Firebase Auth`, 'info'); |
| } catch (e) { |
| logSys('SWEEPER', `❌ Failed to list Auth users: ${e.message}`, 'error'); |
| throw new Error(`Auth pagination failed: ${e.message}`); |
| } |
|
|
| |
| let ghostsSnapshot; |
| try { |
| ghostsSnapshot = await db.collection('titan_ghosts').get(); |
| logSys('SWEEPER', `📋 Fetched ${ghostsSnapshot.size} docs from titan_ghosts`, 'info'); |
| } catch (e) { |
| logSys('SWEEPER', `❌ Failed to fetch titan_ghosts: ${e.message}`, 'error'); |
| throw new Error(`Firestore read failed: ${e.message}`); |
| } |
|
|
| |
| const orphanedUids = []; |
| ghostsSnapshot.forEach(doc => { |
| if (!validUids.has(doc.id)) { |
| orphanedUids.push(doc.id); |
| } |
| }); |
|
|
| if (orphanedUids.length === 0) { |
| logSys('SWEEPER', '✅ No orphaned records found. Database is clean.', 'success'); |
| return { |
| success: true, |
| message: 'No orphaned records found. Database is clean.', |
| orphansFound: 0, |
| docsDeleted: 0 |
| }; |
| } |
|
|
| logSys('SWEEPER', `⚠️ Found ${orphanedUids.length} orphaned UID(s) — beginning batch delete`, 'warning'); |
|
|
| |
| |
| const COLLECTIONS = ['titan_ghosts', 'titan_keys', 'users', 'user_reputation', 'welcome_sent']; |
| const CHUNK_LIMIT = 450; |
|
|
| let currentBatch = db.batch(); |
| let opsInCurrentBatch = 0; |
| let totalDocsDeleted = 0; |
| let batchesCommitted = 0; |
|
|
| try { |
| for (const uid of orphanedUids) { |
| for (const collectionName of COLLECTIONS) { |
| const docRef = db.collection(collectionName).doc(uid); |
| currentBatch.delete(docRef); |
| opsInCurrentBatch++; |
| totalDocsDeleted++; |
|
|
| |
| if (opsInCurrentBatch >= CHUNK_LIMIT) { |
| await currentBatch.commit(); |
| batchesCommitted++; |
| logSys('SWEEPER', `📦 Committed batch #${batchesCommitted} (${opsInCurrentBatch} ops)`, 'info'); |
| currentBatch = db.batch(); |
| opsInCurrentBatch = 0; |
| } |
| } |
| } |
|
|
| |
| if (opsInCurrentBatch > 0) { |
| await currentBatch.commit(); |
| batchesCommitted++; |
| logSys('SWEEPER', `📦 Committed final batch #${batchesCommitted} (${opsInCurrentBatch} ops)`, 'info'); |
| } |
| } catch (e) { |
| logSys('SWEEPER', `❌ Batch delete failed: ${e.message}`, 'error'); |
| throw new Error(`Batch delete failed: ${e.message}`); |
| } |
|
|
| const report = { |
| success: true, |
| message: `Sweep complete. Removed ${orphanedUids.length} orphaned user(s).`, |
| orphansFound: orphanedUids.length, |
| docsDeleted: totalDocsDeleted, |
| batchesCommitted, |
| collectionsSwept: COLLECTIONS, |
| orphanedUids: orphanedUids.map(uid => maskUid(uid)) |
| }; |
|
|
| logSys('SWEEPER', `✅ Sweep complete — ${orphanedUids.length} orphans, ${totalDocsDeleted} docs deleted across ${batchesCommitted} batch(es)`, 'success'); |
| return report; |
| } |
|
|
| async function processAdminCommand(docId, commandData) { |
| try { |
| const { adminKey, command } = commandData; |
|
|
| if (adminKey !== ADMIN_ID) { |
| await writeBlackboxResponse('Access denied. Invalid admin credentials.', 'HIGH'); |
| logSys('DEAD_DROP', `❌ Unauthorized access attempt (docId: ${docId})`, 'error'); |
| return; |
| } |
|
|
| logSys('DEAD_DROP', `🎛️ Processing command: ${command}`, 'system'); |
|
|
| const parts = command.trim().split(/\s+/); |
| const cmd = parts[0].toLowerCase(); |
| const args = parts.slice(1); |
|
|
| switch (cmd) { |
| case '/stats': { |
| const stats = getServerStats(); |
|
|
| const report = ` |
| ╔═══════════════════════════════════════════╗ |
| ║ 🎛️ TITAN NEXUS SERVER STATISTICS ║ |
| ╚═══════════════════════════════════════════╝ |
| |
| ⏱️ UPTIME: ${stats.uptime} |
| |
| 💾 MEMORY USAGE: |
| • Heap Used: ${stats.memory.heapUsed} |
| • Heap Total: ${stats.memory.heapTotal} |
| • Usage: ${stats.memory.percentage} |
| |
| 🔌 CONNECTIONS: |
| • Registered Users: ${stats.connections.registered} |
| • Total Sockets: ${stats.connections.total} |
| |
| ⚙️ SYSTEM LOAD (CPU): |
| • 1 min: ${stats.cpuLoad['1min']} |
| • 5 min: ${stats.cpuLoad['5min']} |
| • 15 min: ${stats.cpuLoad['15min']} |
| |
| 🛡️ SECURITY: |
| • Sentinel MK2: ${stats.sentinel} |
| |
| 👑 ROYAL FAMILY: |
| • Protected Members: ${ROYAL_FAMILY.length} |
| |
| 🖥️ PLATFORM: |
| • OS: ${stats.platform} |
| • Node: ${stats.nodeVersion} |
| |
| 🕰️ TIME-AWARE ENGINE: |
| • Gregorian: ${getGregorianDateString(new Date())} |
| • Hijri: ${getHijriDateString(new Date())} |
| |
| Generated: ${new Date().toISOString()} |
| `.trim(); |
|
|
| await writeBlackboxResponse('Server statistics generated', 'SYSTEM', { report, stats }); |
| logSys('DEAD_DROP', '📊 Stats report generated and written to blackbox', 'success'); |
| break; |
| } |
|
|
| case '/notify': { |
| if (args.length < 2) { |
| await writeBlackboxResponse('Usage: /notify [uid] [message]', 'HIGH'); |
| break; |
| } |
|
|
| const targetUid = args[0]; |
| const message = args.slice(1).join(' '); |
|
|
| await db.collection('notifications').add({ |
| userId: targetUid, |
| message, |
| sentBy: 'ADMIN_SYSTEM', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('admin_notification', { |
| message, |
| timestamp: new Date().toISOString() |
| }); |
| } |
|
|
| await sendPushNotification(targetUid, { |
| title: 'Admin Notification', |
| body: message, |
| data: { type: 'admin_notification' } |
| }); |
|
|
| await writeBlackboxResponse( |
| `Notification sent to user ${targetUid}`, |
| 'SUCCESS', |
| { online: !!targetSocketId, pushSent: true } |
| ); |
|
|
| logSys('DEAD_DROP', `📬 Notification sent to ${maskUid(targetUid)}`, 'success'); |
| break; |
| } |
|
|
| case '/ban': { |
| if (args.length < 2) { |
| await writeBlackboxResponse('Usage: /ban [uid] [reason]', 'HIGH'); |
| break; |
| } |
|
|
| const targetUid = args[0]; |
| const reason = args.slice(1).join(' '); |
|
|
| |
| if (ROYAL_FAMILY.includes(targetUid)) { |
| await writeBlackboxResponse( |
| `Cannot ban user ${targetUid} - Royal Immunity Shield`, |
| 'HIGH', |
| { royalProtection: true } |
| ); |
| logSys('DEAD_DROP', `👑 Ban attempt blocked - Royal immunity for ${maskUid(targetUid)}`, 'royal'); |
| break; |
| } |
|
|
| await admin.auth().updateUser(targetUid, { disabled: true }); |
| await admin.auth().revokeRefreshTokens(targetUid); |
|
|
| await db.collection('banned_users').doc(targetUid).set({ |
| userId: targetUid, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason, |
| bannedBy: ADMIN_ID, |
| method: 'admin_command_deaddrop' |
| }); |
|
|
| await db.collection('users').doc(targetUid).set({ |
| banned: true, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| banReason: reason, |
| bannedBy: ADMIN_ID |
| }, { merge: true }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('force_logout', { |
| reason: 'Account has been banned', |
| timestamp: new Date().toISOString() |
| }); |
| io.sockets.sockets.get(targetSocketId)?.disconnect(true); |
| onlineUsers.delete(targetUid); |
| } |
|
|
| await writeBlackboxResponse( |
| `User ${targetUid} banned successfully`, |
| 'SUCCESS', |
| { reason, wasOnline: !!targetSocketId, disconnected: !!targetSocketId } |
| ); |
|
|
| logSys('DEAD_DROP', `🚫 User ${maskUid(targetUid)} banned: ${reason}`, 'warning'); |
| break; |
| } |
|
|
| case '/clear': { |
| if (args[0] !== 'logs') { |
| await writeBlackboxResponse('Usage: /clear logs', 'HIGH'); |
| break; |
| } |
|
|
| const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); |
| const snapshot = await db.collection('titan_blackbox') |
| .where('ts', '<', cutoffDate) |
| .limit(500) |
| .get(); |
|
|
| if (snapshot.empty) { |
| await writeBlackboxResponse('No old logs found to clear', 'SYSTEM'); |
| break; |
| } |
|
|
| const batch = db.batch(); |
| snapshot.docs.forEach(doc => batch.delete(doc.ref)); |
| await batch.commit(); |
|
|
| await writeBlackboxResponse( |
| `Cleared ${snapshot.size} old log entries`, |
| 'SUCCESS', |
| { deleted: snapshot.size, olderThan: '7 days' } |
| ); |
|
|
| logSys('DEAD_DROP', `🗑️ Cleared ${snapshot.size} old logs`, 'info'); |
| break; |
| } |
|
|
| case '/broadcast': { |
| if (args.length === 0) { |
| await writeBlackboxResponse('Usage: /broadcast [message]', 'HIGH'); |
| break; |
| } |
|
|
| const message = args.join(' '); |
|
|
| await db.collection('notifications').add({ |
| title: '📢 تنبيه عام', |
| body: message, |
| bodyAr: message, |
| type: 'SYSTEM_BROADCAST', |
| userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
|
|
| io.emit('receive_direct', { |
| from: 'SYSTEM', |
| msg: message, |
| isSystem: true, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| await writeBlackboxResponse( |
| 'Broadcast sent to all users & saved to DB', |
| 'SUCCESS', |
| { recipients: io.sockets.sockets.size, message } |
| ); |
|
|
| logSys('DEAD_DROP', `📢 Broadcast sent to ${io.sockets.sockets.size} connections`, 'success'); |
| break; |
| } |
|
|
| case '/sweep-orphans': { |
| logSys('DEAD_DROP', '🧹 /sweep-orphans triggered via Dead Drop', 'system'); |
| const sweepResult = await sweepOrphanedData(); |
|
|
| const sweepReport = ` |
| ╔═══════════════════════════════════════════╗ |
| ║ 🧹 ORPHAN SWEEP REPORT ║ |
| ╚═══════════════════════════════════════════╝ |
| |
| ${sweepResult.orphansFound === 0 |
| ? '✅ Database is clean — no orphaned records found.' |
| : `⚠️ Orphaned UIDs found: ${sweepResult.orphansFound} |
| 🗑️ Total docs deleted: ${sweepResult.docsDeleted} |
| 📦 Batches committed: ${sweepResult.batchesCommitted} |
| 📂 Collections swept: ${sweepResult.collectionsSwept.join(', ')} |
| |
| Orphaned UIDs (masked): |
| ${sweepResult.orphanedUids.map(u => ` • ${u}`).join('\n')}`} |
| |
| Generated: ${new Date().toISOString()} |
| `.trim(); |
|
|
| await writeBlackboxResponse(sweepResult.message, 'SUCCESS', { ...sweepResult, report: sweepReport }); |
| logSys('DEAD_DROP', `🧹 Sweep report written to blackbox`, 'success'); |
| break; |
| } |
|
|
| default: { |
| await writeBlackboxResponse( |
| `Unknown command: ${cmd}`, |
| 'HIGH', |
| { availableCommands: ['/notify', '/ban', '/clear logs', '/broadcast', '/stats', '/sweep-orphans'] } |
| ); |
| logSys('DEAD_DROP', `❓ Unknown command attempted: ${cmd}`, 'warning'); |
| } |
| } |
| } catch (error) { |
| logSys('DEAD_DROP', `❌ Command error: ${error.message}`, 'error'); |
| await writeBlackboxResponse( |
| `Command execution failed: ${error.message}`, |
| 'HIGH' |
| ); |
| } |
| } |
|
|
| async function initCommandReader() { |
| logSys('DEAD_DROP', '📡 Firestore Dead Drop Command Reader initialized', 'system'); |
|
|
| db.collection('pending_bot_actions') |
| .where('status', '==', 'pending') |
| .onSnapshot(async (snapshot) => { |
| snapshot.docChanges().forEach(async (change) => { |
| if (change.type === 'added') { |
| const docId = change.doc.id; |
| const data = change.doc.data(); |
|
|
| try { |
| await db.collection('pending_bot_actions').doc(docId).update({ |
| status: 'processing', |
| processedAt: admin.firestore.FieldValue.serverTimestamp() |
| }); |
|
|
| logSys('DEAD_DROP', `📥 New command received (docId: ${docId})`, 'info'); |
|
|
| await processAdminCommand(docId, data); |
|
|
| await db.collection('pending_bot_actions').doc(docId).delete(); |
| logSys('DEAD_DROP', `✅ Command processed and deleted (docId: ${docId})`, 'success'); |
|
|
| } catch (error) { |
| logSys('DEAD_DROP', `❌ Failed to process command ${docId}: ${error.message}`, 'error'); |
| await db.collection('pending_bot_actions').doc(docId).update({ |
| status: 'error', |
| error: error.message, |
| errorAt: admin.firestore.FieldValue.serverTimestamp() |
| }); |
| } |
| } |
| }); |
| }, (error) => { |
| logSys('DEAD_DROP', `⚠️ Listener Error: ${error.message}`, 'error'); |
| }); |
| } |
|
|
| |
| io.on('connection', (socket) => { |
| logSys('SOCKET', `🔌 New connection: ${socket.id}`, 'cyber'); |
|
|
| socket.on('register', (userId) => { |
| if (!userId) return; |
| onlineUsers.set(userId, socket.id); |
|
|
| if (ROYAL_FAMILY.includes(userId)) { |
| logSys('SOCKET', `👑 Royal user ${maskUid(userId)} registered (socket: ${socket.id})`, 'royal'); |
| } else { |
| logSys('SOCKET', `✅ User ${maskUid(userId)} registered (socket: ${socket.id})`, 'success'); |
| } |
| }); |
|
|
| socket.on('send_direct', async (data) => { |
| const { to, msg } = data; |
| if (!to || !msg) return; |
|
|
| const targetSocketId = onlineUsers.get(to); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('receive_direct', { |
| from: socket.id, |
| msg, |
| timestamp: new Date().toISOString() |
| }); |
| logSys('SOCKET', `📨 Relayed DM to online user ${to}`, 'info'); |
| } else { |
| logSys('SOCKET', `📲 User ${to} offline, sending push`, 'info'); |
| await sendPushNotification(to, { |
| title: 'New direct message', |
| body: typeof msg === 'string' ? msg : JSON.stringify(msg), |
| data: { sender: socket.id, ...msg } |
| }); |
| } |
| }); |
|
|
| socket.on('admin_cmd', async (payload) => { |
| try { |
| const { adminKey, command } = payload; |
|
|
| if (adminKey !== ADMIN_ID) { |
| socket.emit('cmd_res', { |
| success: false, |
| error: 'Access denied. Invalid admin credentials.', |
| timestamp: new Date().toISOString() |
| }); |
| logSys('ADMIN_CMD', `❌ Unauthorized access attempt from socket ${socket.id}`, 'error'); |
| return; |
| } |
|
|
| logSys('ADMIN_CMD', `🎛️ Command received: ${command}`, 'system'); |
|
|
| const parts = command.trim().split(/\s+/); |
| const cmd = parts[0].toLowerCase(); |
| const args = parts.slice(1); |
|
|
| switch (cmd) { |
| case '/notify': { |
| if (args.length < 2) { |
| socket.emit('cmd_res', { |
| success: false, |
| error: 'Usage: /notify [uid] [message]' |
| }); |
| break; |
| } |
|
|
| const targetUid = args[0]; |
| const message = args.slice(1).join(' '); |
|
|
| await db.collection('notifications').add({ |
| userId: targetUid, |
| message, |
| sentBy: 'ADMIN_SYSTEM', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('admin_notification', { |
| message, |
| timestamp: new Date().toISOString() |
| }); |
| } |
|
|
| await sendPushNotification(targetUid, { |
| title: 'Admin Notification', |
| body: message, |
| data: { type: 'admin_notification' } |
| }); |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: `Notification sent to user ${targetUid}`, |
| details: { |
| online: !!targetSocketId, |
| pushSent: true |
| } |
| }); |
|
|
| logSys('ADMIN_CMD', `📬 Notification sent to ${maskUid(targetUid)}`, 'success'); |
| break; |
| } |
|
|
| case '/ban': { |
| if (args.length < 2) { |
| socket.emit('cmd_res', { |
| success: false, |
| error: 'Usage: /ban [uid] [reason]' |
| }); |
| break; |
| } |
|
|
| const targetUid = args[0]; |
| const reason = args.slice(1).join(' '); |
|
|
| |
| if (ROYAL_FAMILY.includes(targetUid)) { |
| socket.emit('cmd_res', { |
| success: false, |
| error: `Cannot ban user ${targetUid} - Royal Immunity Shield`, |
| royalProtection: true |
| }); |
| logSys('ADMIN_CMD', `👑 Ban attempt blocked - Royal immunity for ${maskUid(targetUid)}`, 'royal'); |
| break; |
| } |
|
|
| await admin.auth().updateUser(targetUid, { disabled: true }); |
| await admin.auth().revokeRefreshTokens(targetUid); |
|
|
| await db.collection('banned_users').doc(targetUid).set({ |
| userId: targetUid, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason, |
| bannedBy: ADMIN_ID, |
| method: 'admin_command' |
| }); |
|
|
| await db.collection('users').doc(targetUid).set({ |
| banned: true, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| banReason: reason, |
| bannedBy: ADMIN_ID |
| }, { merge: true }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('force_logout', { |
| reason: 'Account has been banned', |
| timestamp: new Date().toISOString() |
| }); |
| io.sockets.sockets.get(targetSocketId)?.disconnect(true); |
| onlineUsers.delete(targetUid); |
| } |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: `User ${targetUid} banned successfully`, |
| details: { |
| reason, |
| wasOnline: !!targetSocketId, |
| disconnected: !!targetSocketId |
| } |
| }); |
|
|
| logSys('ADMIN_CMD', `🚫 User ${maskUid(targetUid)} banned: ${reason}`, 'warning'); |
| break; |
| } |
|
|
| case '/clear': { |
| if (args[0] !== 'logs') { |
| socket.emit('cmd_res', { |
| success: false, |
| error: 'Usage: /clear logs' |
| }); |
| break; |
| } |
|
|
| const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); |
| const snapshot = await db.collection('titan_blackbox') |
| .where('timestamp', '<', cutoffDate) |
| .limit(500) |
| .get(); |
|
|
| if (snapshot.empty) { |
| socket.emit('cmd_res', { |
| success: true, |
| message: 'No old logs found to clear' |
| }); |
| break; |
| } |
|
|
| const batch = db.batch(); |
| snapshot.docs.forEach(doc => batch.delete(doc.ref)); |
| await batch.commit(); |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: `Cleared ${snapshot.size} old log entries`, |
| details: { |
| deleted: snapshot.size, |
| olderThan: '7 days' |
| } |
| }); |
|
|
| logSys('ADMIN_CMD', `🗑️ Cleared ${snapshot.size} old logs`, 'info'); |
| break; |
| } |
|
|
| case '/broadcast': { |
| if (args.length === 0) { |
| socket.emit('cmd_res', { |
| success: false, |
| error: 'Usage: /broadcast [message]' |
| }); |
| break; |
| } |
|
|
| const message = args.join(' '); |
|
|
| io.emit('receive_direct', { |
| from: 'SYSTEM', |
| msg: message, |
| isSystem: true, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: 'Broadcast sent to all users', |
| details: { |
| recipients: io.sockets.sockets.size, |
| message |
| } |
| }); |
|
|
| logSys('ADMIN_CMD', `📢 Broadcast sent to ${io.sockets.sockets.size} connections`, 'success'); |
| break; |
| } |
|
|
| case '/stats': { |
| const stats = getServerStats(); |
|
|
| const report = ` |
| ╔═══════════════════════════════════════════╗ |
| ║ 🎛️ TITAN NEXUS SERVER STATISTICS ║ |
| ╚═══════════════════════════════════════════╝ |
| |
| ⏱️ UPTIME: ${stats.uptime} |
| |
| 💾 MEMORY USAGE: |
| • Heap Used: ${stats.memory.heapUsed} |
| • Heap Total: ${stats.memory.heapTotal} |
| • Usage: ${stats.memory.percentage} |
| |
| 🔌 CONNECTIONS: |
| • Registered Users: ${stats.connections.registered} |
| • Total Sockets: ${stats.connections.total} |
| |
| ⚙️ SYSTEM LOAD (CPU): |
| • 1 min: ${stats.cpuLoad['1min']} |
| • 5 min: ${stats.cpuLoad['5min']} |
| • 15 min: ${stats.cpuLoad['15min']} |
| |
| 🛡️ SECURITY: |
| • Sentinel MK2: ${stats.sentinel} |
| |
| 👑 ROYAL FAMILY: |
| • Protected Members: ${ROYAL_FAMILY.length} |
| |
| 🕰️ TIME-AWARE ENGINE: |
| • Gregorian: ${getGregorianDateString(new Date())} |
| • Hijri: ${getHijriDateString(new Date())} |
| |
| 🖥️ PLATFORM: |
| • OS: ${stats.platform} |
| • Node: ${stats.nodeVersion} |
| |
| Generated: ${new Date().toISOString()} |
| `.trim(); |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: 'Server statistics', |
| report, |
| data: stats |
| }); |
|
|
| logSys('ADMIN_CMD', '📊 Stats report generated', 'info'); |
| break; |
| } |
|
|
| case '/sweep-orphans': { |
| logSys('ADMIN_CMD', '🧹 /sweep-orphans triggered via Socket.IO', 'system'); |
| const sweepResult = await sweepOrphanedData(); |
|
|
| socket.emit('cmd_res', { |
| success: true, |
| message: sweepResult.message, |
| details: sweepResult |
| }); |
|
|
| logSys('ADMIN_CMD', `🧹 Sweep complete — ${sweepResult.orphansFound} orphans, ${sweepResult.docsDeleted} docs deleted`, 'success'); |
| break; |
| } |
|
|
| default: { |
| socket.emit('cmd_res', { |
| success: false, |
| error: `Unknown command: ${cmd}`, |
| availableCommands: ['/notify', '/ban', '/clear logs', '/broadcast', '/stats', '/sweep-orphans'] |
| }); |
| logSys('ADMIN_CMD', `❓ Unknown command attempted: ${cmd}`, 'warning'); |
| } |
| } |
| } catch (error) { |
| logSys('ADMIN_CMD', `❌ Command error: ${error.message}`, 'error'); |
| socket.emit('cmd_res', { |
| success: false, |
| error: `Command execution failed: ${error.message}`, |
| timestamp: new Date().toISOString() |
| }); |
| } |
| }); |
|
|
| socket.on('disconnect', () => { |
| let disconnectedUserId = null; |
| for (const [userId, sockId] of onlineUsers.entries()) { |
| if (sockId === socket.id) { |
| disconnectedUserId = userId; |
| onlineUsers.delete(userId); |
| break; |
| } |
| } |
| if (disconnectedUserId) { |
| const logType = ROYAL_FAMILY.includes(disconnectedUserId) ? 'royal' : 'warning'; |
| const icon = ROYAL_FAMILY.includes(disconnectedUserId) ? '👑' : '🔴'; |
| logSys('SOCKET', `${icon} User ${maskUid(disconnectedUserId)} disconnected`, logType); |
| } else { |
| logSys('SOCKET', `🔴 Socket ${socket.id} disconnected (unregistered)`, 'info'); |
| } |
| }); |
| }); |
| |
| app.use(express.static('public')); |
|
|
| app.get('/admin', (req, res) => { |
| res.sendFile(__dirname + '/admin.html'); |
| }); |
|
|
| |
| app.get('/', (req, res) => { |
| const stats = getServerStats(); |
| res.json({ |
| service: 'TITAN NEXUS – Time-Aware Royal AI Edition', |
| status: 'operational', |
| version: '14.0', |
| security: 'Sentinel MK2 active', |
| realtime: 'Socket.io relay active', |
| adminCenter: 'Dead Drop Command System active', |
| ai: 'Gemini AI + Time-Aware Engine active', |
| royalFamily: ROYAL_FAMILY.length, |
| onlineUsers: onlineUsers.size, |
| uptime: stats.uptime, |
| memory: stats.memory.percentage, |
| timeAware: { |
| gregorian: getGregorianDateString(new Date()), |
| hijri: getHijriDateString(new Date()) |
| } |
| }); |
| }); |
|
|
| app.get('/ping', (req, res) => res.send('pong')); |
|
|
| app.get('/stats', (req, res) => { |
| const stats = getServerStats(); |
| res.json({ |
| ...stats, |
| timeAware: { |
| gregorian: getGregorianDateString(new Date()), |
| hijri: getHijriDateString(new Date()) |
| } |
| }); |
| }); |
|
|
| |
| app.post('/admin/check-auth', (req, res) => { |
| const { adminKey } = req.body; |
| if (!adminKey) return res.json({ ok: false, reason: 'no_key' }); |
| const match = adminKey === ADMIN_ID; |
| const adminLen = ADMIN_ID ? ADMIN_ID.length : 0; |
| const keyLen = adminKey.length; |
| res.json({ |
| ok: match, |
| reason: match ? 'matched' : 'mismatch', |
| keyLength: keyLen, |
| adminIdLength: adminLen, |
| adminIdSet: !!ADMIN_ID, |
| firstFour: ADMIN_ID ? ADMIN_ID.substring(0, 4) : 'NOT_SET' |
| }); |
| }); |
|
|
| |
| app.post('/api/admin/command', async (req, res) => { |
| try { |
| const { adminKey, command } = req.body; |
|
|
| if (!adminKey || !command) { |
| return res.status(400).json({ success: false, error: 'Missing adminKey or command' }); |
| } |
|
|
| if (adminKey !== ADMIN_ID) { |
| logSys('HTTP_ADMIN', `❌ Auth failed — key_len=${adminKey.length} admin_id_len=${ADMIN_ID ? ADMIN_ID.length : 'UNSET'} admin_id_set=${!!ADMIN_ID}`, 'error'); |
| return res.status(403).json({ success: false, error: 'Invalid admin credentials' }); |
| } |
|
|
| logSys('HTTP_ADMIN', `🎛️ HTTP command received: ${command}`, 'system'); |
|
|
| const parts = command.trim().split(/\s+/); |
| const cmd = parts[0].toLowerCase(); |
| const args = parts.slice(1); |
|
|
| |
| const executeCommand = async () => { |
| switch (cmd) { |
| case '/stats': { |
| const stats = getServerStats(); |
| return { |
| success: true, |
| message: 'Server statistics retrieved', |
| stats, |
| report: ` |
| Uptime: ${stats.uptime} |
| Memory: ${stats.memory.percentage} |
| Online Users: ${stats.connections.registered} |
| CPU Load: ${stats.cpuLoad['1min']} / ${stats.cpuLoad['5min']} / ${stats.cpuLoad['15min']} |
| Platform: ${stats.platform} |
| `.trim() |
| }; |
| } |
|
|
| case '/notify': { |
| if (args.length < 2) throw new Error('Usage: /notify [uid] [message]'); |
| const targetUid = args[0]; |
| const message = args.slice(1).join(' '); |
|
|
| await db.collection('notifications').add({ |
| userId: targetUid, |
| message, |
| sentBy: 'ADMIN_SYSTEM', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('admin_notification', { |
| message, |
| timestamp: new Date().toISOString() |
| }); |
| } |
|
|
| await sendPushNotification(targetUid, { |
| title: 'Admin Notification', |
| body: message, |
| data: { type: 'admin_notification' } |
| }); |
|
|
| return { |
| success: true, |
| message: `Notification sent to user ${targetUid}`, |
| details: { online: !!targetSocketId, pushSent: true } |
| }; |
| } |
|
|
| case '/ban': { |
| if (args.length < 2) throw new Error('Usage: /ban [uid] [reason]'); |
| const targetUid = args[0]; |
| const reason = args.slice(1).join(' '); |
|
|
| if (ROYAL_FAMILY.includes(targetUid)) { |
| return { |
| success: false, |
| error: `Cannot ban user ${targetUid} - Royal Immunity Shield`, |
| royalProtection: true |
| }; |
| } |
|
|
| await admin.auth().updateUser(targetUid, { disabled: true }); |
| await admin.auth().revokeRefreshTokens(targetUid); |
|
|
| await db.collection('banned_users').doc(targetUid).set({ |
| userId: targetUid, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| reason, |
| bannedBy: ADMIN_ID, |
| method: 'admin_command_http' |
| }); |
|
|
| await db.collection('users').doc(targetUid).set({ |
| banned: true, |
| bannedAt: admin.firestore.FieldValue.serverTimestamp(), |
| banReason: reason, |
| bannedBy: ADMIN_ID |
| }, { merge: true }); |
|
|
| const targetSocketId = onlineUsers.get(targetUid); |
| if (targetSocketId) { |
| io.to(targetSocketId).emit('force_logout', { |
| reason: 'Account has been banned', |
| timestamp: new Date().toISOString() |
| }); |
| io.sockets.sockets.get(targetSocketId)?.disconnect(true); |
| onlineUsers.delete(targetUid); |
| } |
|
|
| return { |
| success: true, |
| message: `User ${targetUid} banned successfully`, |
| details: { reason, wasOnline: !!targetSocketId } |
| }; |
| } |
|
|
| case '/clear': { |
| if (args[0] !== 'logs') throw new Error('Usage: /clear logs'); |
| const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); |
| const snapshot = await db.collection('titan_blackbox') |
| .where('ts', '<', cutoffDate) |
| .limit(500) |
| .get(); |
|
|
| if (snapshot.empty) { |
| return { success: true, message: 'No old logs found to clear' }; |
| } |
|
|
| const batch = db.batch(); |
| snapshot.docs.forEach(doc => batch.delete(doc.ref)); |
| await batch.commit(); |
|
|
| return { |
| success: true, |
| message: `Cleared ${snapshot.size} old log entries`, |
| details: { deleted: snapshot.size, olderThan: '7 days' } |
| }; |
| } |
|
|
| case '/broadcast': { |
| if (args.length === 0) throw new Error('Usage: /broadcast [message]'); |
| const message = args.join(' '); |
|
|
| await db.collection('notifications').add({ |
| title: '📢 تنبيه عام', |
| body: message, |
| bodyAr: message, |
| type: 'SYSTEM_BROADCAST', |
| userId: 'BROADCAST', |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
|
|
| io.emit('receive_direct', { |
| from: 'SYSTEM', |
| msg: message, |
| isSystem: true, |
| timestamp: new Date().toISOString() |
| }); |
|
|
| return { |
| success: true, |
| message: `Broadcast sent to ${io.sockets.sockets.size} connections`, |
| details: { recipients: io.sockets.sockets.size } |
| }; |
| } |
|
|
| case '/sweep-orphans': { |
| logSys('HTTP_ADMIN', '🧹 /sweep-orphans triggered via HTTP', 'system'); |
| const sweepResult = await sweepOrphanedData(); |
| return { |
| success: true, |
| message: sweepResult.message, |
| details: sweepResult |
| }; |
| } |
|
|
| default: |
| throw new Error(`Unknown command: ${cmd}. Available: /stats, /notify, /ban, /clear logs, /broadcast, /sweep-orphans`); |
| } |
| }; |
|
|
| const result = await executeCommand(); |
| res.json(result); |
|
|
| } catch (error) { |
| logSys('HTTP_ADMIN', `❌ Command error: ${error.message}`, 'error'); |
| res.status(500).json({ |
| success: false, |
| error: error.message |
| }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| function initWelcomeManager() { |
| db.collection('pending_welcomes').onSnapshot(snapshot => { |
| snapshot.docChanges().forEach(async change => { |
| if (change.type !== 'added') return; |
|
|
| const doc = change.doc; |
| const uid = doc.id; |
| const { email, displayName } = doc.data(); |
|
|
| if (!uid || !email) { |
| logSys('WELCOME', `⚠️ Skipping malformed pending_welcomes doc (missing uid/email)`, 'warning'); |
| await doc.ref.delete().catch(() => {}); |
| return; |
| } |
|
|
| |
| try { |
| const welcomeRef = db.collection('welcome_sent').doc(uid); |
| const sent = await welcomeRef.get(); |
| if (sent.exists) { |
| logSys('WELCOME', `⏭️ Welcome already sent for ${maskUid(uid)}, skipping`, 'info'); |
| await doc.ref.delete().catch(() => {}); |
| return; |
| } |
| |
| await welcomeRef.set({ sentAt: admin.firestore.FieldValue.serverTimestamp(), email }); |
| } catch (e) { |
| logSys('WELCOME', `⚠️ Firestore welcome_sent check failed: ${e.message}`, 'warning'); |
| |
| } |
|
|
| const name = displayName || 'عزيزي المستخدم'; |
| const today = new Date(); |
| const dateStr = getGregorianDateString(today); |
| const hijriStr = getHijriDateString(today); |
|
|
| |
| const notifBody = `مرحباً بك في Titan Connect يا ${name}! 🎉 |
| |
| أنت الآن جزء من مجتمعنا المتميز. |
| |
| اكتشف ما ينتظرك: |
| 🔐 شات وخزنة مشفرة تماماً |
| 📡 نقل ملفات P2P مباشر بدون خوادم |
| 🎬 سينما مع ترجمة ذكية بالذكاء الاصطناعي |
| 📚 الانغماس — تعلّم الإنجليزي بالقصص |
| 👥 جروبات ومجتمعات حية |
| |
| نتمنى لك تجربة ممتعة! 🌟`; |
|
|
| try { |
| await db.collection('notifications').add({ |
| title: '🎉 أهلاً بك في Titan Connect!', |
| body: notifBody, |
| type: 'WELCOME', |
| userId: uid, |
| timestamp: admin.firestore.FieldValue.serverTimestamp(), |
| read: false |
| }); |
| |
| io.emit('welcome_notification', { uid, title: '🎉 أهلاً بك!', body: notifBody }); |
| logSys('WELCOME', `✅ In-app notification sent to ${maskUid(uid)}`, 'success'); |
| } catch (e) { |
| logSys('WELCOME', `⚠️ Notification failed: ${e.message}`, 'warning'); |
| } |
|
|
| |
| if (MAILER_URL && MAILER_TOKEN) { |
| const htmlBody = `<!DOCTYPE html> |
| <html dir="rtl"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head> |
| <body style="margin:0;padding:0;background:#0a0e1a;font-family:Arial,Helvetica,sans-serif"> |
| <table width="100%" cellpadding="0" cellspacing="0" style="background:#0a0e1a;padding:24px 10px"> |
| <tr><td align="center"> |
| <table width="540" cellpadding="0" cellspacing="0" style="max-width:540px;width:100%;background:#0f1525;border-radius:16px;overflow:hidden;border:1px solid #1e3a5f"> |
| <tr><td style="height:3px;background:linear-gradient(90deg,#63b3ed,#4fd1c5,#63b3ed)"></td></tr> |
| <tr><td style="background:#0d1830;padding:28px;text-align:center;border-bottom:1px solid #1e3a5f"> |
| <div style="font-size:40px;margin-bottom:8px">👑</div> |
| <h1 style="color:#63b3ed;margin:0;font-size:22px;letter-spacing:3px;font-weight:bold">TITAN CONNECT</h1> |
| <p style="color:#4fd1c5;margin:6px 0 0;font-size:11px;letter-spacing:2px">WELCOME TO THE FAMILY</p> |
| </td></tr> |
| <tr><td style="padding:28px 32px"> |
| <p style="color:#e2ecff;font-size:15px;line-height:1.9;margin:0 0 20px">السلام عليكم ورحمة الله 🌙<br><br>مرحباً <strong style="color:#63b3ed">${name}</strong>،<br>يسعدنا انضمامك إلى <strong style="color:#63b3ed">Titan Connect</strong> — التطبيق الذي صممناه ليكون أكثر من مجرد تطبيق.</p> |
| <table width="100%" cellpadding="0" cellspacing="0" style="background:#0b1220;border-radius:10px;padding:18px;margin-bottom:24px"> |
| <tr><td><p style="color:#4fd1c5;font-size:11px;letter-spacing:2px;margin:0 0 14px;font-weight:bold">✨ ما ينتظرك بداخله</p></td></tr> |
| <tr><td style="padding-bottom:12px"><table cellpadding="0" cellspacing="0"><tr><td style="width:28px;vertical-align:top;padding-top:2px;font-size:16px">🔐</td><td><p style="color:#e2ecff;font-size:13px;font-weight:bold;margin:0">شات وخزنة مشفرة تماماً</p><p style="color:#5a7090;font-size:12px;margin:2px 0 0">محادثاتك لا يصل إليها أحد — حتى نحن</p></td></tr></table></td></tr> |
| <tr><td style="padding-bottom:12px"><table cellpadding="0" cellspacing="0"><tr><td style="width:28px;vertical-align:top;padding-top:2px;font-size:16px">📡</td><td><p style="color:#e2ecff;font-size:13px;font-weight:bold;margin:0">نقل ملفات P2P مباشر</p><p style="color:#5a7090;font-size:12px;margin:2px 0 0">بدون خوادم وسيطة — من جهازك مباشرة</p></td></tr></table></td></tr> |
| <tr><td style="padding-bottom:12px"><table cellpadding="0" cellspacing="0"><tr><td style="width:28px;vertical-align:top;padding-top:2px;font-size:16px">🎬</td><td><p style="color:#e2ecff;font-size:13px;font-weight:bold;margin:0">سينما + ترجمة بالذكاء الاصطناعي</p><p style="color:#5a7090;font-size:12px;margin:2px 0 0">شاهد وترجم الفيديوهات وأنشئ ملفات ترجمة</p></td></tr></table></td></tr> |
| <tr><td style="padding-bottom:12px"><table cellpadding="0" cellspacing="0"><tr><td style="width:28px;vertical-align:top;padding-top:2px;font-size:16px">📚</td><td><p style="color:#e2ecff;font-size:13px;font-weight:bold;margin:0">الانغماس — تعلّم الإنجليزي بالقصص</p><p style="color:#5a7090;font-size:12px;margin:2px 0 0">طريقة تعلم مختلفة وممتعة</p></td></tr></table></td></tr> |
| <tr><td><table cellpadding="0" cellspacing="0"><tr><td style="width:28px;vertical-align:top;padding-top:2px;font-size:16px">👥</td><td><p style="color:#e2ecff;font-size:13px;font-weight:bold;margin:0">جروبات ومجتمعات حية</p><p style="color:#5a7090;font-size:12px;margin:2px 0 0">تواصل في مساحة آمنة ومشفرة</p></td></tr></table></td></tr> |
| </table> |
| <table width="100%" cellpadding="0" cellspacing="0"><tr><td align="center" style="padding-bottom:20px"> |
| <a href="https://titan-connect.vercel.app" style="display:inline-block;background:#63b3ed;color:#000;text-decoration:none;padding:13px 36px;border-radius:30px;font-weight:bold;font-size:14px;letter-spacing:1px">ابدأ رحلتك ←</a> |
| </td></tr></table> |
| <p style="color:#5a7090;font-size:12px;line-height:1.7;margin:0;text-align:center">مع تحياتي — محمود حسن<br>المطور والمؤسس، Titan Connect</p> |
| </td></tr> |
| <tr><td style="background:#060a12;padding:16px;text-align:center;border-top:1px solid #1a2a40"> |
| <p style="color:#2a3a50;font-size:11px;margin:0">TITAN NEXUS · ROYAL COMMS SYSTEM</p> |
| <p style="color:#1e2a38;font-size:10px;margin:4px 0 0">📅 ${dateStr} | 🌙 ${hijriStr}</p> |
| </td></tr> |
| <tr><td style="height:2px;background:linear-gradient(90deg,#63b3ed,#4fd1c5,#63b3ed)"></td></tr> |
| </table> |
| </td></tr> |
| </table> |
| </body></html>`; |
|
|
| try { |
| await sendTitanEmail(email, '🎉 أهلاً بك في Titan Connect!', htmlBody); |
| logSys('WELCOME', `✅ Welcome email sent to ${email.slice(0,4)}***`, 'success'); |
| } catch (e) { |
| logSys('WELCOME', `⚠️ Welcome email failed: ${e.message.slice(0,80)}`, 'warning'); |
| } |
| } |
|
|
| |
| try { |
| await doc.ref.delete(); |
| logSys('WELCOME', `🗑️ Cleaned up pending_welcomes/${maskUid(uid)}`, 'info'); |
| } catch (e) { |
| logSys('WELCOME', `⚠️ Failed to delete pending_welcomes doc: ${e.message}`, 'warning'); |
| } |
| }); |
| }, err => { |
| logSys('WELCOME', `❌ pending_welcomes listener error: ${err.message}`, 'error'); |
| }); |
|
|
| logSys('WELCOME', '👂 Welcome Manager listening on pending_welcomes queue', 'success'); |
| } |
|
|
| |
| app.post('/admin/market-now', async (req, res) => { |
| const { adminKey } = req.body; |
| if (adminKey !== ADMIN_ID) return res.status(403).json({ success: false, error: 'Unauthorized' }); |
| logSys('HTTP_ADMIN', '📈 Manual market broadcast triggered via HTTP', 'system'); |
| broadcastMarketUpdate(); |
| res.json({ success: true, message: 'Market report fetch initiated.' }); |
| }); |
|
|
| app.post('/admin/prayer-now', async (req, res) => { |
| const { adminKey } = req.body; |
| if (adminKey !== ADMIN_ID) return res.status(403).json({ success: false, error: 'Unauthorized' }); |
| broadcastPrayerTimes(); |
| res.json({ success: true, message: 'Prayer times broadcast initiated.' }); |
| }); |
|
|
| app.post('/admin/quote-now', async (req, res) => { |
| const { adminKey } = req.body; |
| if (adminKey !== ADMIN_ID) return res.status(403).json({ success: false, error: 'Unauthorized' }); |
| broadcastDailyQuote(); |
| res.json({ success: true, message: 'Daily quote broadcast initiated.' }); |
| }); |
|
|
| app.post('/admin/news-now', async (req, res) => { |
| const { adminKey } = req.body; |
| if (adminKey !== ADMIN_ID) return res.status(403).json({ success: false, error: 'Unauthorized' }); |
| broadcastArabicNews(); |
| res.json({ success: true, message: 'News broadcast initiated.' }); |
| }); |
|
|
| |
| |
| |
| |
| app.post('/admin/send-email', async (req, res) => { |
| const { |
| adminKey, subject, body, targetEmail, |
| logoUrl, |
| buttonText, |
| buttonUrl, |
| pdfUrl, |
| accentColor |
| } = req.body; |
|
|
| if (adminKey !== ADMIN_ID) return res.status(403).json({ success: false, error: 'Unauthorized' }); |
| if (!subject || !body) return res.status(400).json({ success: false, error: 'subject and body are required' }); |
| if (!MAILER_URL || !MAILER_TOKEN) return res.status(500).json({ success: false, error: 'MAILER_URL and MAILER_TOKEN must be set in HF Secrets' }); |
|
|
| try { |
| let recipients = []; |
| if (targetEmail) { |
| recipients = [targetEmail]; |
| } else { |
| logSys('EMAIL', '📋 Fetching all user emails from Firebase Auth...', 'system'); |
| let pageToken; |
| do { |
| const result = await admin.auth().listUsers(1000, pageToken); |
| result.users.forEach(user => { if (user.email) recipients.push(user.email); }); |
| pageToken = result.pageToken; |
| } while (pageToken); |
| } |
|
|
| if (!recipients.length) return res.status(404).json({ success: false, error: 'No email recipients found' }); |
| logSys('EMAIL', `📧 Sending to ${recipients.length} recipients...`, 'system'); |
|
|
| const accent = accentColor || '#63b3ed'; |
| const accentDark = '#0f2044'; |
|
|
| |
| const logoSection = logoUrl |
| ? `<tr><td style="padding:0 0 20px;text-align:center"><img src="${logoUrl}" alt="Logo" style="max-width:180px;max-height:80px;object-fit:contain"></td></tr>` |
| : ''; |
|
|
| const ctaButton = (buttonText && buttonUrl) |
| ? `<tr><td style="padding:24px 0 0;text-align:center"> |
| <a href="${buttonUrl}" style="display:inline-block;background:linear-gradient(135deg,${accent},#4fd1c5);color:#000;text-decoration:none;padding:14px 36px;border-radius:30px;font-weight:bold;font-size:15px;letter-spacing:1px">${buttonText} →</a> |
| </td></tr>` |
| : `<tr><td style="padding:24px 0 0;text-align:center"> |
| <a href="https://m-hv1-titan-bot.hf.space" style="display:inline-block;background:linear-gradient(135deg,${accent},#4fd1c5);color:#000;text-decoration:none;padding:14px 36px;border-radius:30px;font-weight:bold;font-size:15px;letter-spacing:1px">Open Titan App →</a> |
| </td></tr>`; |
|
|
| const pdfSection = pdfUrl |
| ? `<tr><td style="padding:16px 0 0;text-align:center"> |
| <a href="${pdfUrl}" style="display:inline-block;background:rgba(99,179,237,.1);color:${accent};text-decoration:none;padding:10px 24px;border-radius:20px;font-size:13px;border:1px solid ${accent}">📎 Download PDF</a> |
| </td></tr>` |
| : ''; |
|
|
| const htmlBody = `<!DOCTYPE html> |
| <html dir="auto"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <title>${subject}</title> |
| </head> |
| <body style="margin:0;padding:0;background:#0a0e1a;font-family:Arial,Helvetica,sans-serif"> |
| <table width="100%" cellpadding="0" cellspacing="0" style="background:#0a0e1a;padding:30px 10px"> |
| <tr><td align="center"> |
| <table width="600" cellpadding="0" cellspacing="0" style="max-width:600px;width:100%;background:#0f1525;border-radius:20px;overflow:hidden;border:1px solid #1e3a5f;box-shadow:0 20px 60px rgba(0,0,0,.6)"> |
| |
| <!-- TOP ACCENT BAR --> |
| <tr><td style="height:4px;background:linear-gradient(90deg,${accent},#4fd1c5,${accent})"></td></tr> |
| |
| <!-- HEADER --> |
| <tr><td style="background:linear-gradient(135deg,${accentDark},#0a1628);padding:36px 40px;text-align:center"> |
| ${logoSection ? `<table width="100%" cellpadding="0" cellspacing="0">${logoSection}</table>` : ''} |
| <div style="font-size:42px;margin-bottom:10px;filter:drop-shadow(0 0 20px rgba(246,201,14,.4))">👑</div> |
| <h1 style="color:${accent};margin:0;font-size:26px;letter-spacing:3px;text-transform:uppercase;font-weight:bold">Titan App</h1> |
| <p style="color:#4fd1c5;margin:8px 0 0;font-size:13px;letter-spacing:2px;text-transform:uppercase">Royal Notification System</p> |
| </td></tr> |
| |
| <!-- DIVIDER --> |
| <tr><td style="height:1px;background:linear-gradient(90deg,transparent,${accent},transparent)"></td></tr> |
| |
| <!-- BODY --> |
| <tr><td style="padding:36px 40px"> |
| <div style="color:#e2ecff;font-size:15px;line-height:1.9;white-space:pre-wrap;background:rgba(99,179,237,.04);border-left:3px solid ${accent};padding:20px 20px 20px 20px;border-radius:0 8px 8px 0;margin-bottom:8px">${body}</div> |
| <table width="100%" cellpadding="0" cellspacing="0"> |
| ${ctaButton} |
| ${pdfSection} |
| </table> |
| </td></tr> |
| |
| <!-- FOOTER --> |
| <tr><td style="background:#060a12;padding:24px 40px;text-align:center;border-top:1px solid #1a2a40"> |
| <p style="color:#3a5070;font-size:12px;margin:0 0 6px;letter-spacing:1px">TITAN NEXUS · POWERED BY ROYAL AI</p> |
| <p style="color:#2a3a50;font-size:11px;margin:0">You received this because you are a registered Titan App user</p> |
| </td></tr> |
| |
| <!-- BOTTOM ACCENT BAR --> |
| <tr><td style="height:3px;background:linear-gradient(90deg,${accent},#4fd1c5,${accent})"></td></tr> |
| |
| </table> |
| </td></tr> |
| </table> |
| </body></html>`; |
|
|
| let sent = 0, failed = 0; |
| for (let i = 0; i < recipients.length; i++) { |
| const email = recipients[i]; |
| try { |
| await sendTitanEmail(email, subject, htmlBody); |
| sent++; |
| if (sent % 5 === 0) logSys('EMAIL', `📨 Progress: ${sent}/${recipients.length}`, 'system'); |
| } catch (err) { |
| logSys('EMAIL', `⚠️ Failed ${email.slice(0,6)}***: ${err.message.slice(0,60)}`, 'warning'); |
| failed++; |
| } |
| if (i < recipients.length - 1) await new Promise(r => setTimeout(r, 300)); |
| } |
|
|
| logSys('EMAIL', `✅ Done: ${sent} sent, ${failed} failed, ${recipients.length} total`, 'success'); |
| res.json({ success: true, sent, failed, total: recipients.length }); |
|
|
| } catch (error) { |
| logSys('EMAIL', `❌ Email error: ${error.message}`, 'error'); |
| res.status(500).json({ success: false, error: error.message }); |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const TITAN_GATEWAY_BASE = 'https://m-hv1-titan-gateway.hf.space'; |
| |
| |
| |
| const TITAN_CLOUD_RELAY_BASE = 'https://m-hv1-titan-messenger.hf.space/relay'; |
|
|
| |
| async function requireFirebaseAuth(req, res, next) { |
| const authHeader = req.headers['authorization'] || ''; |
| const token = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : null; |
|
|
| if (!token) { |
| logSys('PROXY', `❌ Missing Authorization header from ${req.ip}`, 'error'); |
| return res.status(403).json({ error: 'Forbidden: missing Authorization header' }); |
| } |
|
|
| try { |
| const decoded = await admin.auth().verifyIdToken(token); |
| req.titanUid = decoded.uid; |
| next(); |
| } catch (err) { |
| logSys('PROXY', `❌ Invalid Firebase ID Token: ${err.message}`, 'error'); |
| return res.status(403).json({ error: 'Forbidden: invalid or expired token' }); |
| } |
| } |
|
|
| |
| |
| |
| function forwardToUpstream(upstreamUrl, req, extraHeaders = {}) { |
| return new Promise((resolve, reject) => { |
| const parsed = new URL(upstreamUrl); |
|
|
| const contentType = req.headers['content-type'] || ''; |
| const isMultipart = contentType.includes('multipart/form-data'); |
| const isGet = req.method === 'GET'; |
|
|
| |
| |
| |
| |
| |
|
|
| let bodyBuffer = null; |
| let finalContentType = contentType; |
|
|
| if (!isGet && !isMultipart) { |
| const bodyStr = JSON.stringify(req.body ?? {}); |
| bodyBuffer = Buffer.from(bodyStr, 'utf8'); |
| finalContentType = 'application/json'; |
| } |
|
|
| const headers = { |
| ...((!isGet && finalContentType) ? { 'Content-Type': finalContentType } : {}), |
| ...(bodyBuffer ? { 'Content-Length': bodyBuffer.byteLength } : {}), |
| 'X-Titan-Key': process.env.TITAN_GATEWAY_KEY, |
| ...extraHeaders, |
| }; |
|
|
| const options = { |
| hostname: parsed.hostname, |
| port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80), |
| path: parsed.pathname + (parsed.search || ''), |
| method: req.method, |
| headers, |
| }; |
|
|
| const upstreamReq = https.request(options, (upstreamRes) => { |
| resolve(upstreamRes); |
| }); |
|
|
| upstreamReq.on('error', reject); |
| upstreamReq.setTimeout(120000, () => { |
| upstreamReq.destroy(); |
| reject(new Error('Upstream request timed out')); |
| }); |
|
|
| if (isGet) { |
| upstreamReq.end(); |
| } else if (isMultipart) { |
| |
| req.pipe(upstreamReq); |
| } else { |
| |
| upstreamReq.write(bodyBuffer); |
| upstreamReq.end(); |
| } |
| }); |
| } |
|
|
| |
| |
| |
| app.use('/api/gateway-proxy', requireFirebaseAuth, async (req, res) => { |
| |
| const downstreamPath = req.path; |
| const queryString = req.url.includes('?') |
| ? req.url.slice(req.url.indexOf('?')) |
| : ''; |
| const upstreamUrl = `${TITAN_GATEWAY_BASE}${downstreamPath}${queryString}`; |
|
|
| logSys('PROXY', `[${req.titanUid?.slice(0, 8)}…] ${req.method} ${upstreamUrl}`, 'info'); |
|
|
| try { |
| const upstreamRes = await forwardToUpstream(upstreamUrl, req); |
|
|
| |
| res.status(upstreamRes.statusCode); |
| const hopByHop = new Set(['connection', 'keep-alive', 'transfer-encoding', 'trailer', |
| 'upgrade', 'proxy-authorization', 'proxy-authenticate', 'te']); |
| Object.entries(upstreamRes.headers).forEach(([k, v]) => { |
| if (!hopByHop.has(k.toLowerCase())) res.setHeader(k, v); |
| }); |
|
|
| |
| upstreamRes.pipe(res); |
|
|
| } catch (err) { |
| logSys('PROXY', `❌ Gateway proxy error: ${err.message}`, 'error'); |
| if (!res.headersSent) { |
| res.status(502).json({ error: `Gateway proxy failed: ${err.message}` }); |
| } |
| } |
| }); |
|
|
| |
| |
| |
| |
| |
| app.use('/api/relay-proxy', requireFirebaseAuth, async (req, res) => { |
| const downstreamPath = req.path; |
| const queryString = req.url.includes('?') |
| ? req.url.slice(req.url.indexOf('?')) |
| : ''; |
| const upstreamUrl = `${TITAN_CLOUD_RELAY_BASE}${downstreamPath}${queryString}`; |
|
|
| logSys('PROXY', `[RELAY][${req.titanUid?.slice(0, 8)}…] ${req.method} ${upstreamUrl}`, 'info'); |
|
|
| try { |
| const upstreamRes = await forwardToUpstream(upstreamUrl, req, { |
| 'x-titan-type' : req.headers['x-titan-type'] || '', |
| |
| 'Authorization' : req.headers['authorization'] || '', |
| |
| 'X-Titan-Key' : process.env.TITAN_RELAY_KEY || process.env.TITAN_GATEWAY_KEY, |
| }); |
|
|
| res.status(upstreamRes.statusCode); |
| const hopByHop = new Set(['connection', 'keep-alive', 'transfer-encoding', 'trailer', |
| 'upgrade', 'proxy-authorization', 'proxy-authenticate', 'te']); |
| Object.entries(upstreamRes.headers).forEach(([k, v]) => { |
| if (!hopByHop.has(k.toLowerCase())) res.setHeader(k, v); |
| }); |
|
|
| upstreamRes.pipe(res); |
|
|
| } catch (err) { |
| logSys('PROXY', `❌ Relay proxy error: ${err.message}`, 'error'); |
| if (!res.headersSent) { |
| res.status(502).json({ error: `Relay proxy failed: ${err.message}` }); |
| } |
| } |
| }); |
|
|
| |
| server.listen(PORT, async () => { |
| console.log(`\n\x1b[36m╔═══════════════════════════════════════════════════════════════════════╗\x1b[0m`); |
| console.log(`\x1b[36m║ 🛡️ TITAN NEXUS v14.4 - ROYAL COMMS EDITION ║\x1b[0m`); |
| console.log(`\x1b[36m║ ⚡ Socket.IO | Sentinel MK2 | Janitor MK2 | Email Engine ║\x1b[0m`); |
| console.log(`\x1b[36m║ 📡 Dead Drop | 🧠 Gemini 3 | Free Gold APIs | Groq Stocks ║\x1b[0m`); |
| console.log(`\x1b[36m║ 🕌 Prayer | 💡 Quote | 📰 News | 📈 Market | 📧 Email ║\x1b[0m`); |
| console.log(`\x1b[36m║ 🔐 Auth Gateway Proxy | Relay Proxy | Firebase ID Token Guard ║\x1b[0m`); |
| console.log(`\x1b[36m║ 👑 Royal Immunity | 🚀 Port: ${PORT} ║\x1b[0m`); |
| console.log(`\x1b[36m╚═══════════════════════════════════════════════════════════════════════╝\x1b[0m\n`); |
|
|
| |
| logSys('CORE', `🗓️ Gregorian: ${getGregorianDateString(new Date())}`, 'ai'); |
| logSys('CORE', `🌙 Hijri: ${getHijriDateString(new Date())}`, 'ai'); |
|
|
| |
| const sentinel = new SentinelMK2(); |
| sentinel.monitorComments(); |
| sentinel.monitorReports(); |
| logSys('CORE', '🛡️ Sentinel MK2 armed (Royal Immunity active)', 'success'); |
|
|
| |
| const janitor = new JanitorMK2(); |
| setInterval(() => janitor.cleanOldMessages(), 60 * 60 * 1000); |
| logSys('CORE', '🧹 Janitor MK2 scheduled: hourly (Royal preservation enabled)', 'success'); |
|
|
| |
| initCommandReader(); |
| logSys('CORE', '📡 Firestore Dead Drop Command Reader activated', 'success'); |
|
|
| |
| initWelcomeManager(); |
| logSys('CORE', '🎉 Welcome Manager activated (pending_welcomes queue listener)', 'success'); |
|
|
| |
| initCronJobs(); |
| logSys('CORE', '🧠 Time-Aware AI automation initialized (Riddle-only mode)', 'success'); |
| logSys('CORE', '📅 Scheduled: Every 6h riddle, 8 AM & 3 PM market report, 10 PM game awards, 11:59 PM royal reports', 'success'); |
| logSys('CORE', '📈 Market Intelligence: Groq Compound (web search) — Gold EGP/SAR/AED/USD + Global Indices', 'ai'); |
|
|
| |
| try { |
| const repSnapshot = await db.collection('user_reputation').limit(100).get(); |
| repSnapshot.docs.forEach(doc => { |
| const data = doc.data(); |
| sentinel.userReputation.set(data.userId, data.score || 100); |
| }); |
| logSys('CORE', `📊 Loaded ${repSnapshot.size} user reputations`, 'info'); |
| } catch (e) { |
| logSys('CORE', '⚠️ Could not preload reputations', 'warning'); |
| } |
|
|
| logSys('CORE', `👑 Royal Family protection active for ${ROYAL_FAMILY.length} members`, 'royal'); |
| logSys('CORE', '🎛️ Admin Command Center (Socket + Dead Drop + HTTP) initialized', 'success'); |
| |
| initExtensions(app, io, db, admin, { ADMIN_ID, ROYAL_FAMILY, onlineUsers, logSys, maskUid, getServerStats }); |
|
|
| logSys('CORE', '✅ Nexus v14.2 operational. Market Intelligence Edition ready.', 'success'); |
| }); |