Spaces:
Paused
Paused
Create server.js
Browse files
server.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
require('dotenv').config();
|
| 2 |
+
const express = require('express');
|
| 3 |
+
const admin = require('firebase-admin');
|
| 4 |
+
const Groq = require('groq-sdk');
|
| 5 |
+
const { Octokit } = require('@octokit/rest');
|
| 6 |
+
|
| 7 |
+
const app = report = express();
|
| 8 |
+
|
| 9 |
+
// Hugging Face-এর জন্য রিকোয়েস্ট সাইজ অপ্টিমাইজেশন
|
| 10 |
+
app.use(express.json({ limit: '10mb' }));
|
| 11 |
+
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
| 12 |
+
|
| 13 |
+
// ১. ফায়ারবেস অ্যাডমিন এসডিকে ইনিশিয়ালিলাইজেশন (এনভায়রনমেন্ট ভেরিয়েবল থেকে)
|
| 14 |
+
try {
|
| 15 |
+
if (!process.env.FIREBASE_ADMIN_API) {
|
| 16 |
+
throw new Error("FIREBASE_ADMIN_API এনভায়রনমেন্ট ভেরিয়েবলটি পাওয়া যায়নি!");
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
// সেটিংসের সিক্রেট থেকে সম্পূর্ণ JSON স্ট্রিংটি অবজেক্টে কনভার্ট করা হচ্ছে
|
| 20 |
+
const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_API);
|
| 21 |
+
|
| 22 |
+
admin.initializeApp({
|
| 23 |
+
credential: admin.credential.cert(serviceAccount),
|
| 24 |
+
databaseURL: process.env.FIREBASE_REALTIME_URL
|
| 25 |
+
});
|
| 26 |
+
console.log("Firebase Admin SDK successfully connected.");
|
| 27 |
+
} catch (error) {
|
| 28 |
+
console.error("Firebase Initialization Error:", error.message);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
const db = admin.database();
|
| 32 |
+
|
| 33 |
+
// ২. Groq এবং GitHub (Octokit) ইনিশিয়ালিলাইজেশন
|
| 34 |
+
const groq = new Groq({ apiKey: process.env.GROQ_API });
|
| 35 |
+
const octokit = new Octokit({ auth: process.env.GITHUB_API_TOKEN });
|
| 36 |
+
|
| 37 |
+
const REPO_OWNER = 'chaingroupworld-rgb';
|
| 38 |
+
const REPO_NAME = 'Website-visit-1';
|
| 39 |
+
|
| 40 |
+
// ৩. চ্যাট এপিআই (Dynamic Model Selection লজিক)
|
| 41 |
+
app.post('/api/chat', async (req, res) => {
|
| 42 |
+
const { userId, message } = req.body;
|
| 43 |
+
|
| 44 |
+
if (!userId || !message) {
|
| 45 |
+
return res.status(400).json({ error: "userId এবং message পাঠানো বাধ্যতামূলক।" });
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
try {
|
| 49 |
+
// ডায়নামিক মডেল ট্রিক: টেক্সট ৩০০ ক্যারেক্টারের বেশি হলে ১৭ বিলিয়ন (Llama 4 Scout), কম হলে ইনস্ট্যান্ট
|
| 50 |
+
let selectedModel = "llama-3.1-8b-instant";
|
| 51 |
+
|
| 52 |
+
if (message.length > 300) {
|
| 53 |
+
selectedModel = "meta-llama/llama-4-scout-17b-16e-instruct";
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
// Groq এপিআই কল
|
| 57 |
+
const chatCompletion = await groq.chat.completions.create({
|
| 58 |
+
messages: [{ role: "user", content: message }],
|
| 59 |
+
model: selectedModel,
|
| 60 |
+
});
|
| 61 |
+
|
| 62 |
+
const aiResponse = chatCompletion.choices[0]?.message?.content || "";
|
| 63 |
+
|
| 64 |
+
// ফায়ারবেস রিয়েলটাইম ডাটাবেজে ইউজার ও এআই কথোপকথন সেভ
|
| 65 |
+
const chatRef = db.ref(`chats/${userId}`).push();
|
| 66 |
+
await chatRef.set({
|
| 67 |
+
userMessage: message,
|
| 68 |
+
aiResponse: aiResponse,
|
| 69 |
+
modelUsed: selectedModel,
|
| 70 |
+
timestamp: admin.database.ServerValue.TIMESTAMP
|
| 71 |
+
});
|
| 72 |
+
|
| 73 |
+
res.status(200).json({
|
| 74 |
+
success: true,
|
| 75 |
+
model: selectedModel,
|
| 76 |
+
reply: aiResponse
|
| 77 |
+
});
|
| 78 |
+
|
| 79 |
+
} catch (error) {
|
| 80 |
+
console.error("Chat API Error:", error);
|
| 81 |
+
res.status(500).json({ error: "সার্ভারে এআই বা ডাটাবেজ প্রসেস করতে সমস্যা হয়েছে।" });
|
| 82 |
+
}
|
| 83 |
+
});
|
| 84 |
+
|
| 85 |
+
// ৪. গিটহাব ফাইল পুশ এপিআই (ফ্রন্টএন্ড ফাইল আপলোডের জন্য)
|
| 86 |
+
app.post('/api/github/push', async (req, res) => {
|
| 87 |
+
const { filePath, fileContent, commitMessage } = req.body;
|
| 88 |
+
|
| 89 |
+
if (!filePath || !fileContent) {
|
| 90 |
+
return res.status(400).json({ error: "filePath এবং fileContent পাঠানো বাধ্যতামূলক।" });
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
try {
|
| 94 |
+
let sha;
|
| 95 |
+
// ফাইল আগে থেকে আছে কিনা চেক করা (আপডেটের জন্য SHA কোড দরকার হয়)
|
| 96 |
+
try {
|
| 97 |
+
const { data } = await octokit.repos.getContent({
|
| 98 |
+
owner: REPO_OWNER,
|
| 99 |
+
repo: REPO_NAME,
|
| 100 |
+
path: filePath,
|
| 101 |
+
});
|
| 102 |
+
sha = data.sha;
|
| 103 |
+
} catch (e) {
|
| 104 |
+
sha = undefined; // ফাইল নতুন হলে SHA থাকবে না
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// ফাইল ডেটাকে Base64 ফরম্যাটে রূপান্তর
|
| 108 |
+
const base64Content = Buffer.from(fileContent).toString('base64');
|
| 109 |
+
|
| 110 |
+
// গিটহাবে পুশ বা আপডেট করা
|
| 111 |
+
const response = await octokit.repos.createOrUpdateFileContents({
|
| 112 |
+
owner: REPO_OWNER,
|
| 113 |
+
repo: REPO_NAME,
|
| 114 |
+
path: filePath,
|
| 115 |
+
message: commitMessage || "Uploaded via Mobile-first Backend API",
|
| 116 |
+
content: base64Content,
|
| 117 |
+
sha: sha
|
| 118 |
+
});
|
| 119 |
+
|
| 120 |
+
res.status(200).json({
|
| 121 |
+
success: true,
|
| 122 |
+
message: "GitHub রিপোজিটরিতে ফাইল সফলভাবে পুশ হয়েছে।",
|
| 123 |
+
download_url: response.data.content.download_url
|
| 124 |
+
});
|
| 125 |
+
|
| 126 |
+
} catch (error) {
|
| 127 |
+
console.error("GitHub API Error:", error);
|
| 128 |
+
res.status(500).json({ error: "GitHub এপিআই-তে ফাইল পুশ করতে ব্যর্থ হয়েছে।" });
|
| 129 |
+
}
|
| 130 |
+
});
|
| 131 |
+
|
| 132 |
+
// ৫. বেসিক রুট (Hugging Face Spaces হেলথ চেকের জন্য জরুরি)
|
| 133 |
+
app.get('/', (req, res) => {
|
| 134 |
+
res.status(200).send('Hugging Face Free Space Backend Engine is Active!');
|
| 135 |
+
});
|
| 136 |
+
|
| 137 |
+
// Hugging Face ফ্রি স্পেসের ডিফল্ট পোর্ট ৭৮৬০ রিড করা
|
| 138 |
+
const PORT = process.env.PORT || 7860;
|
| 139 |
+
app.listen(PORT, () => {
|
| 140 |
+
console.log(`Server is running smoothly on port ${PORT}`);
|
| 141 |
+
});
|