newtest / server.ts
Eissa's picture
Update server.ts
b73cd07 verified
Raw
History Blame Contribute Delete
4.78 kB
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);
});