everydaycats commited on
Commit
eace673
·
verified ·
1 Parent(s): 2466829

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +23 -65
app.js CHANGED
@@ -1,7 +1,7 @@
1
  // server.js
2
  // Node + Express server to accept Snapshotter payloads from the Roblox plugin.
3
  // Save as server.js and run: node server.js
4
- // Installs: npm install express body-parser cors
5
 
6
  import express from "express";
7
  import bodyParser from "body-parser";
@@ -9,11 +9,7 @@ import cors from "cors";
9
  import fs from "fs";
10
  import path from "path";
11
  import { fileURLToPath } from "url";
12
- import fetch from "node-fetch"; // Node 18+ has fetch globally; if not, install node-fetch
13
-
14
- // If you're running Node 18+, you can use global fetch and remove node-fetch import.
15
- // If you get "fetch is not defined", run: npm install node-fetch
16
- // and uncomment the import above (already present).
17
 
18
  const __filename = fileURLToPath(import.meta.url);
19
  const __dirname = path.dirname(__filename);
@@ -25,77 +21,39 @@ if (!fs.existsSync(STORAGE_DIR)) fs.mkdirSync(STORAGE_DIR, { recursive: true });
25
 
26
  const app = express();
27
  app.use(cors());
28
- app.use(bodyParser.json({ limit: "10mb" })); // Allow larger payloads (tweak as needed)
 
29
 
30
- // Simple logging middleware
31
  app.use((req, res, next) => {
32
  console.log(new Date().toISOString(), req.method, req.url);
33
  next();
34
  });
35
 
36
- // Simple health/ping
37
  app.get("/ping", (req, res) => res.status(200).send("pong"));
38
 
39
- // Compatibility endpoint from your older plugin code
40
- app.post("/capture-and-upload", async (req, res) => {
41
  try {
42
  const payload = req.body;
43
  if (!payload) return res.status(400).json({ success: false, error: "empty payload" });
44
 
45
- // generate an id and save payload to disk
46
  const id = "asset_" + Math.random().toString(36).slice(2, 10);
47
  const filename = path.join(STORAGE_DIR, `${id}.json`);
48
- fs.writeFileSync(filename, JSON.stringify({ receivedAt: Date.now(), payload }, null, 2), "utf8");
49
 
50
- // Optionally perform immediate processing here (call AI service, upload images...).
51
- // For this demo we simply accept and return an assetId.
 
 
52
 
53
- // If client asked for a callbackUrl, try to POST back a small completion message
54
- if (payload.callbackUrl && typeof payload.callbackUrl === "string") {
55
- const cbBody = { assetId: id, status: "processed", ts: Date.now() };
56
- // fire-and-forget; do not block the main response on callback success
57
- (async () => {
58
- try {
59
- // Use fetch if available
60
- if (typeof fetch === "function") {
61
- const r = await fetch(payload.callbackUrl, {
62
- method: "POST",
63
- headers: { "Content-Type": "application/json" },
64
- body: JSON.stringify(cbBody),
65
- timeout: 10000
66
- });
67
- console.log("Callback posted, status:", r.status);
68
- } else {
69
- console.log("No fetch available to call callback URL.");
70
- }
71
- } catch (err) {
72
- console.warn("Callback POST failed:", err && err.message ? err.message : err);
73
- }
74
- })();
75
- }
76
-
77
- return res.json({ success: true, assetId: id });
78
- } catch (err) {
79
- console.error("capture-and-upload error:", err);
80
- return res.status(500).json({ success: false, error: String(err) });
81
- }
82
- });
83
-
84
- // New route name used in the plugin snippet: /api/ai-build
85
- app.post("/api/ai-build", async (req, res) => {
86
- try {
87
- const payload = req.body;
88
- if (!payload) return res.status(400).json({ success: false, error: "empty payload" });
89
-
90
- // Save payload to disk
91
- const id = "asset_" + Math.random().toString(36).slice(2, 10);
92
- const filename = path.join(STORAGE_DIR, `${id}.json`);
93
  fs.writeFileSync(filename, JSON.stringify({ receivedAt: Date.now(), payload }, null, 2), "utf8");
94
 
95
- // (Here you could call the Gemini API, save images, run processing, etc.)
96
- // For now we immediately return success with the generated asset id.
97
-
98
- // If payload provides callbackUrl, POST a callback (fire-and-forget)
99
  if (payload.callbackUrl && typeof payload.callbackUrl === "string") {
100
  const cbBody = { assetId: id, status: "processed", ts: Date.now() };
101
  (async () => {
@@ -109,19 +67,20 @@ app.post("/api/ai-build", async (req, res) => {
109
  console.log("Callback sent to", payload.callbackUrl);
110
  }
111
  } catch (err) {
112
- console.warn("Callback failed:", err && err.message ? err.message : err);
113
  }
114
  })();
115
  }
116
 
117
- return res.json({ success: true, assetId: id, message: "received" });
 
118
  } catch (err) {
119
  console.error("/api/ai-build error:", err);
120
  return res.status(500).json({ success: false, error: String(err) });
121
  }
122
  });
123
 
124
- // Optional: status endpoint for an asset (reads saved JSON)
125
  app.get("/asset/:id", (req, res) => {
126
  try {
127
  const id = req.params.id;
@@ -135,8 +94,7 @@ app.get("/asset/:id", (req, res) => {
135
  }
136
  });
137
 
138
- // Start server
139
  app.listen(PORT, () => {
140
- console.log(`Plugin backend listening on http://localhost:${PORT}`);
141
- console.log("Saved payloads will be stored in:", STORAGE_DIR);
142
  });
 
1
  // server.js
2
  // Node + Express server to accept Snapshotter payloads from the Roblox plugin.
3
  // Save as server.js and run: node server.js
4
+ // Installs: npm install express body-parser cors node-fetch
5
 
6
  import express from "express";
7
  import bodyParser from "body-parser";
 
9
  import fs from "fs";
10
  import path from "path";
11
  import { fileURLToPath } from "url";
12
+ import fetch from "node-fetch";
 
 
 
 
13
 
14
  const __filename = fileURLToPath(import.meta.url);
15
  const __dirname = path.dirname(__filename);
 
21
 
22
  const app = express();
23
  app.use(cors());
24
+ // Increase limit to 50mb to handle large complex workspaces
25
+ app.use(bodyParser.json({ limit: "50mb" }));
26
 
27
+ // Logging middleware
28
  app.use((req, res, next) => {
29
  console.log(new Date().toISOString(), req.method, req.url);
30
  next();
31
  });
32
 
33
+ // Health check
34
  app.get("/ping", (req, res) => res.status(200).send("pong"));
35
 
36
+ // Main endpoint for the Plugin
37
+ app.post("/api/ai-build", async (req, res) => {
38
  try {
39
  const payload = req.body;
40
  if (!payload) return res.status(400).json({ success: false, error: "empty payload" });
41
 
42
+ // Generate ID
43
  const id = "asset_" + Math.random().toString(36).slice(2, 10);
44
  const filename = path.join(STORAGE_DIR, `${id}.json`);
 
45
 
46
+ // Log what we received
47
+ console.log(`📥 Received snapshot from: ${payload.sender || "Unknown"}`);
48
+ console.log(`📝 Instruction: "${payload.instruction || "No instruction provided"}"`);
49
+ console.log(`Target Root: ${payload.selectionName}`);
50
 
51
+ // Save payload to disk (Game State + Instruction)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  fs.writeFileSync(filename, JSON.stringify({ receivedAt: Date.now(), payload }, null, 2), "utf8");
53
 
54
+ // FUTURE: Here is where you would trigger the Gemini API call using 'payload.instruction' and 'payload.state'
55
+
56
+ // If client provided a callback URL, fire-and-forget
 
57
  if (payload.callbackUrl && typeof payload.callbackUrl === "string") {
58
  const cbBody = { assetId: id, status: "processed", ts: Date.now() };
59
  (async () => {
 
67
  console.log("Callback sent to", payload.callbackUrl);
68
  }
69
  } catch (err) {
70
+ console.warn("Callback failed:", err.message);
71
  }
72
  })();
73
  }
74
 
75
+ return res.json({ success: true, assetId: id, message: "Snapshot received successfully" });
76
+
77
  } catch (err) {
78
  console.error("/api/ai-build error:", err);
79
  return res.status(500).json({ success: false, error: String(err) });
80
  }
81
  });
82
 
83
+ // Retrieve stored assets
84
  app.get("/asset/:id", (req, res) => {
85
  try {
86
  const id = req.params.id;
 
94
  }
95
  });
96
 
 
97
  app.listen(PORT, () => {
98
+ console.log(`🚀 Plugin backend listening on http://localhost:${PORT}`);
99
+ console.log(`📂 Storage: ${STORAGE_DIR}`);
100
  });