import express from "express"; import path from "path"; import { createServer as createViteServer } from "vite"; import dotenv from "dotenv"; dotenv.config(); const app = express(); const PORT = 3000; app.use(express.json({ limit: "50mb" })); app.use(express.urlencoded({ limit: "50mb", extended: true })); app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "*"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization" ); res.header( "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" ); if (req.method === "OPTIONS") { return res.sendStatus(200); } next(); }); // Proxy Endpoint app.get("/api/proxy", async (req, res) => { const targetUrl = req.query.url as string; if (!targetUrl) { return res.status(400).json({ error: "الرابط مطلوب" }); } try { const formattedUrl = targetUrl.startsWith("http") ? targetUrl : `https://${targetUrl}`; const response = await fetch(formattedUrl); if (!response.ok) { return res.status(response.status).json({ error: `فشل جلب الموقع: ${response.statusText}` }); } const contentType = response.headers.get("content-type") || ""; if ( contentType.includes("html") || contentType.includes("css") || contentType.includes("javascript") || contentType.includes("text") || contentType.includes("json") ) { const text = await response.text(); res.setHeader("Content-Type", contentType); return res.send(text); } const buffer = await response.arrayBuffer(); res.setHeader("Content-Type", contentType); return res.send(Buffer.from(buffer)); } catch (err: any) { return res.status(500).json({ error: err.message }); } }); // Groq AI Endpoint app.post("/api/ai/chat", async (req, res) => { const { messages, customApiKey } = req.body; if (!messages || !Array.isArray(messages)) { return res.status(400).json({ error: "المحادثة غير صالحة" }); } const apiKeys = [ customApiKey, process.env.GROQ_API_KEY, process.env.GROQ_API_KEY_2, process.env.GROQ_API_KEY_3 ].filter(Boolean); if (!apiKeys.length) { return res.status(400).json({ error: "لا يوجد مفتاح Groq" }); } const systemPrompt = ` أنت مساعد SiteClone Pro v20. متخصص في: - Web cloning - Workflows - APIs - Debugging - Hosting أجب دائمًا بالعربية. `; const formattedMessages = [ { role: "system", content: systemPrompt }, ...messages.map((m: any) => ({ role: m.role === "model" ? "assistant" : "user", content: m.content })) ]; let lastError: any = null; for (const key of apiKeys) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 20000); const response = await fetch( "https://api.groq.com/openai/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` }, body: JSON.stringify({ model: "llama-3.3-70b-versatile", messages: formattedMessages, temperature: 0.7 }), signal: controller.signal } ); clearTimeout(timeoutId); if (!response.ok) { const errText = await response.text(); throw new Error(errText); } const data = await response.json(); return res.json({ text: data.choices?.[0]?.message?.content || "لم يتم الحصول على رد.", activeProvider: "Groq", activeModel: "llama-3.3-70b-versatile" }); } catch (err: any) { console.warn("Groq Key Failed:", err.message); lastError = err; continue; } } return res.status(500).json({ error: `فشل جميع مفاتيح Groq: ${lastError?.message}` }); }); // Vite / Production Static Serving async function initServer() { if (process.env.NODE_ENV !== "production") { const vite = await createViteServer({ server: { middlewareMode: true }, appType: "spa" }); app.use(vite.middlewares); } else { const distPath = path.join(process.cwd(), "dist"); app.use(express.static(distPath)); app.get("*", (req, res) => { res.sendFile(path.join(distPath, "index.html")); }); } app.listen(PORT, "0.0.0.0", () => { console.log(`SiteClone Pro running on port ${PORT}`); }); } initServer().catch((err) => { console.error("Initialization error:", err); });