Raybilhelp commited on
Commit
4c03281
·
verified ·
1 Parent(s): 70a6180

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +96 -75
server.js CHANGED
@@ -1,137 +1,158 @@
1
  require('dotenv').config();
2
  const express = require('express');
3
- const cors = require('cors'); // 👈 ১. এখানে cors ইমপোর্ট করা হয়েছে
4
  const admin = require('firebase-admin');
5
  const Groq = require('groq-sdk');
6
  const { Octokit } = require('@octokit/rest');
7
 
8
  const app = express();
9
-
10
- // 👈 ২. সব অরিজিন বা ফ্রন্টএন্ড থেকে রিকোয়েস্ট এক্সেপ্ট করার জন্য এটি যুক্ত করা হয়েছে
11
- app.use(cors({ origin: '*' }));
12
-
13
- // Hugging Face-এর জন্য রিকোয়েস্ট সাইজ অপ্টিমাইজেশন
14
- app.use(express.json({ limit: '10mb' }));
15
- app.use(express.urlencoded({ extended: true, limit: '10mb' }));
16
 
17
  // ১. ফায়ারবেস অ্যাডমিন এসডিকে ইনিশিয়ালিলাইজেশন
18
  try {
19
- if (!process.env.FIREBASE_ADMIN_API) {
20
- throw new Error("FIREBASE_ADMIN_API এনভায়রনমেন্ট ভেরিয়েবলটি পাওয়া যায়নি!");
21
- }
22
-
23
  const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_API);
24
-
25
  admin.initializeApp({
26
  credential: admin.credential.cert(serviceAccount),
27
  databaseURL: process.env.FIREBASE_REALTIME_URL
28
  });
29
- console.log("Firebase Admin SDK successfully connected.");
30
  } catch (error) {
31
- console.error("Firebase Initialization Error:", error.message);
32
  }
33
-
34
  const db = admin.database();
35
 
36
- // ২. Groq এবং GitHub (Octokit) ইনিশিয়ালিলাইজেশন
37
  const groq = new Groq({ apiKey: process.env.GROQ_API });
38
  const octokit = new Octokit({ auth: process.env.GITHUB_API_TOKEN });
39
 
40
  const REPO_OWNER = 'chaingroupworld-rgb';
41
  const REPO_NAME = 'Website-visit-1';
42
 
43
- // ৩. াট এিআই (Dynamic Model Selection)
44
- app.post('/api/chat', async (req, res) => {
45
- const { userId, message } = req.body;
 
46
 
47
- if (!userId || !message) {
48
- return res.status(400).json({ error: "userId এবং message পাঠানো বাধ্যতামূলক।" });
49
- }
 
 
50
 
 
 
 
51
  try {
52
- let selectedModel = "llama-3.1-8b-instant";
 
 
 
 
 
 
53
 
54
- if (message.length > 300) {
55
- selectedModel = "meta-llama/llama-4-scout-17b-16e-instruct";
 
56
  }
57
 
58
- const chatCompletion = await groq.chat.completions.create({
59
- messages: [{ role: "user", content: message }],
60
- model: selectedModel,
61
- });
62
 
63
- const aiResponse = chatCompletion.choices[0]?.message?.content || "";
 
 
 
 
 
 
 
 
 
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
  try {
96
  const { data } = await octokit.repos.getContent({
97
  owner: REPO_OWNER,
98
  repo: REPO_NAME,
99
- path: filePath,
100
  });
101
- sha = data.sha;
 
102
  } catch (e) {
103
- sha = undefined;
 
104
  }
105
 
106
- const base64Content = Buffer.from(fileContent).toString('base64');
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
- const response = await octokit.repos.createOrUpdateFileContents({
 
109
  owner: REPO_OWNER,
110
  repo: REPO_NAME,
111
- path: filePath,
112
- message: commitMessage || "Uploaded via Mobile-first Backend API",
113
- content: base64Content,
114
- sha: sha
115
  });
 
116
 
117
- res.status(200).json({
118
- success: true,
119
- message: "GitHub রিপোজিটরিতে ফাইল সফলভাবে পুশ হয়েছে।",
120
- download_url: response.data.content.download_url
121
- });
122
-
123
- } catch (error) {
124
- console.error("GitHub API Error:", error);
125
- res.status(500).json({ error: "GitHub এপিআই-তে ফাইল পুশ ক��তে ব্যর্থ হয়েছে।" });
126
  }
127
- });
 
 
 
 
128
 
129
- // ৫. বেসিক রুট
130
  app.get('/', (req, res) => {
131
- res.status(200).send('Hugging Face Free Space Backend Engine is Active!');
 
 
 
 
 
 
132
  });
133
 
134
  const PORT = process.env.PORT || 7860;
135
  app.listen(PORT, () => {
136
- console.log(`Server is running smoothly on port ${PORT}`);
137
  });
 
1
  require('dotenv').config();
2
  const express = require('express');
3
+ const cors = require('cors');
4
  const admin = require('firebase-admin');
5
  const Groq = require('groq-sdk');
6
  const { Octokit } = require('@octokit/rest');
7
 
8
  const app = express();
9
+ app.use(cors({ origin: '*' }));
10
+ app.use(express.json({ limit: '10mb' }));
 
 
 
 
 
11
 
12
  // ১. ফায়ারবেস অ্যাডমিন এসডিকে ইনিশিয়ালিলাইজেশন
13
  try {
 
 
 
 
14
  const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_API);
 
15
  admin.initializeApp({
16
  credential: admin.credential.cert(serviceAccount),
17
  databaseURL: process.env.FIREBASE_REALTIME_URL
18
  });
19
+ console.log("Firebase Connected.");
20
  } catch (error) {
21
+ console.error("Firebase Init Error:", error.message);
22
  }
 
23
  const db = admin.database();
24
 
25
+ // ২. Groq এবং GitHub ইনিশিয়ালিলাইজেশন
26
  const groq = new Groq({ apiKey: process.env.GROQ_API });
27
  const octokit = new Octokit({ auth: process.env.GITHUB_API_TOKEN });
28
 
29
  const REPO_OWNER = 'chaingroupworld-rgb';
30
  const REPO_NAME = 'Website-visit-1';
31
 
32
+ // 🤖 মাসর প্রম্প:িআই-কে পিওর এসইও এইচটিএমএল ফাইল বানাতে বাধ্য করবে
33
+ const MASTER_PROMPT = `You are an expert web developer and storyteller. Generate a unique, interesting short story in Bengali.
34
+ The output MUST be a complete, production-ready, standalone HTML page code using Tailwind CSS.
35
+ Do NOT include any markdown code blocks like \`\`\`html or explanation. Just start with <!DOCTYPE html> and end with </html>.
36
 
37
+ SEO & Design Requirements:
38
+ 1. Include <title>, <meta name="description"> (max 160 chars), <meta name="keywords">, and JSON-LD Schema Markup for BlogPosting.
39
+ 2. In og:image, use a placeholder or your brand asset logo, but ensure the content has a stunning typographic banner.
40
+ 3. For the main body hero section, create a beautiful typography card using Tailwind CSS with dark gradients (slate-900 to indigo-950), glowing neon borders, and large glowing text displaying the story title. This acts as the visual image thumbnail.
41
+ 4. The story layout must be clean, readable, responsive for mobile, with elegant fonts. Use appropriate H1, H2 tags.`;
42
 
43
+ // 🚀 কোর অটোমেশন ফাংশন (গল্প তৈরি ও গিটহাবে পুশ)
44
+ async function generateAndPushStory() {
45
+ console.log("Automation triggered: Generating new story...");
46
  try {
47
+ // ক) Groq (Llama 4 Scout 17B) থেকে সম্পূর্ণ HTML কোড নেওয়া
48
+ const chatCompletion = await groq.chat.completions.create({
49
+ messages: [{ role: "user", content: MASTER_PROMPT }],
50
+ model: "meta-llama/llama-4-scout-17b-16e-instruct", // বড় কাজের জন্য ১৭বি মডেল
51
+ });
52
+
53
+ const htmlContent = chatCompletion.choices[0]?.message?.content || "";
54
 
55
+ if (!htmlContent.includes("<!DOCTYPE html>")) {
56
+ console.error("Invalid HTML output from AI");
57
+ return;
58
  }
59
 
60
+ // খ) একটি ইউনিক স্লাগ বা ফাইলের নাম তৈরি (টাইমস্ট্যাম্প দিয়ে)
61
+ const timestamp = Date.now();
62
+ const fileName = `story-${timestamp}.html`;
 
63
 
64
+ // গ) সরাসরি নতুন গল্পের ফাইলটি GitHub-এ পুশ করা
65
+ const base64Content = Buffer.from(htmlContent).toString('base64');
66
+ await octokit.repos.createOrUpdateFileContents({
67
+ owner: REPO_OWNER,
68
+ repo: REPO_NAME,
69
+ path: fileName,
70
+ message: `Automated Story Upload: ${fileName}`,
71
+ content: base64Content
72
+ });
73
+ console.log(`Successfully uploaded: ${fileName}`);
74
 
75
+ // ঘ) ফায়ারবেসে ট্র্যাক বা মেটাডাটা সেভ করা
76
+ const storyRef = db.ref('automated_stories').push();
77
+ await storyRef.set({
78
+ fileName: fileName,
 
79
  timestamp: admin.database.ServerValue.TIMESTAMP
80
  });
81
 
82
+ // 🔄 ঙ) মূল index.html ফাইলটি রিড করে নতুন গল্পের লিংক যুক্ত করা
83
+ await updateIndexHtml(fileName);
 
 
 
84
 
85
  } catch (error) {
86
+ console.error("Automation Logic Error:", error.message);
 
 
 
 
 
 
 
 
 
 
87
  }
88
+ }
89
 
90
+ // 🔄 index.html ডাইনামিকালি আপডেট করার ফাংশน
91
+ async function updateIndexHtml(newStoryFile) {
92
  try {
93
+ let indexSha, indexContentRaw;
94
+
95
+ // গিটহাব থেকে বর্তমান index.html তুলে আনা
96
  try {
97
  const { data } = await octokit.repos.getContent({
98
  owner: REPO_OWNER,
99
  repo: REPO_NAME,
100
+ path: 'index.html',
101
  });
102
+ indexSha = data.sha;
103
+ indexContentRaw = Buffer.from(data.content, 'base64').toString('utf-8');
104
  } catch (e) {
105
+ // যদি index.html না থাকে, তবে একটি বেসিক স্ট্রাকচার তৈরি হবে
106
+ indexContentRaw = `<!DOCTYPE html><html><head><title>Raybil Stories</title></head><body class="bg-slate-950 text-white"><h1>গল্পের তালিকা</h1><div id="story-list"></div></body></html>`;
107
  }
108
 
109
+ // নতুন গল্পের জন্য লিংকের এইচটিএমএল এলিমেন্ট
110
+ const newLinkHtml = `<p><a href="${newStoryFile}" class="text-indigo-400 hover:underline">নতুন গল্প (${new Date().toLocaleTimeString()})</a></p>\n`;
111
+
112
+ // কোডের ভেতরের নির্দিষ্ট জায়গাতে (যেমন <div id="story-list"> এর ঠিক নিচে) লিংকটি পুশ করা
113
+ let updatedIndexContent;
114
+ if (indexContentRaw.includes('<div id="story-list">')) {
115
+ updatedIndexContent = indexContentRaw.replace(
116
+ '<div id="story-list">',
117
+ `<div id="story-list">\n${newLinkHtml}`
118
+ );
119
+ } else {
120
+ // সেফটি ফলব্যাক: যদি ট্যাগ না মেলে তবে বডির শেষে পুশ করবে
121
+ updatedIndexContent = indexContentRaw.replace('</body>', `${newLinkHtml}</body>`);
122
+ }
123
 
124
+ // আপডেট হওয়া index.html গিটহাবে পুশ ব্যাক করা
125
+ await octokit.repos.createOrUpdateFileContents({
126
  owner: REPO_OWNER,
127
  repo: REPO_NAME,
128
+ path: 'index.html',
129
+ message: 'Updated index.html with latest story link',
130
+ content: Buffer.from(updatedIndexContent).toString('base64'),
131
+ sha: indexSha
132
  });
133
+ console.log("index.html successfully updated on GitHub!");
134
 
135
+ } catch (err) {
136
+ console.error("Error updating index.html:", err.message);
 
 
 
 
 
 
 
137
  }
138
+ }
139
+
140
+ // ⏱️ টেস্ট করার জন্য প্রতি ২ মিনিট (১২০০০০ মিলিসেকেন্ড) পর পর রান হবে
141
+ // যখন আপনি ৪ ঘণ্টা করতে চাইবেন, তখন ১২০০০০ বদলে ১৪৪০০০০০ (14400000) দিয়ে দেবেন।
142
+ setInterval(generateAndPushStory, 120000);
143
 
144
+ // বেসিক রুট ও হেলথ চেক
145
  app.get('/', (req, res) => {
146
+ res.status(200).send('Raybil Autonomous AI Engine is Running...');
147
+ });
148
+
149
+ // ম্যানুয়ালি টেস্ট ট্রিগার করার জন্য একটি গোপন এপিআই রুট
150
+ app.get('/api/trigger-now', async (req, res) => {
151
+ await generateAndPushStory();
152
+ res.json({ success: true, message: "Story generation forced successfully." });
153
  });
154
 
155
  const PORT = process.env.PORT || 7860;
156
  app.listen(PORT, () => {
157
+ console.log(`Server running on port ${PORT}`);
158
  });