Files
cuberoo/server.js
2025-06-04 15:06:27 -07:00

142 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// server.js
const express = require('express');
const bodyParser = require('body-parser');
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const http = require('http');
const { Server } = require('socket.io');
const fs = require('fs');
const app = express();
const server = http.createServer(app);
const io = new Server(server);
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
// open (or create) the SQLite database file
const db = new sqlite3.Database('positions.db', err => {
if (err) {
console.error('Could not open DB', err);
process.exit(1);
}
});
// create table if not exists
db.run(
`CREATE TABLE IF NOT EXISTS positions (
square_id TEXT PRIMARY KEY,
fruit TEXT
)`,
(err) => {
if (err) console.error('Could not ensure table', err);
}
);
// get all saved positions
app.get('/api/positions', (req, res) => {
db.all('SELECT square_id, fruit FROM positions', (err, rows) => {
if (err) return res.status(500).json({ error: err.message });
// convert to an object. should look like this: { "1": "Apple", "2": "Banana", … }
const mapping = {};
rows.forEach(r => (mapping[r.square_id] = r.fruit));
res.json(mapping);
});
});
// save (or update) a single squares item
app.post('/api/positions', (req, res) => {
const { squareId, fruit } = req.body;
if (!squareId || typeof fruit !== 'string') {
return res.status(400).json({ error: 'squareId and fruit required' });
}
db.run(
`INSERT INTO positions (square_id, fruit)
VALUES (?, ?)
ON CONFLICT(square_id) DO UPDATE SET fruit=excluded.fruit`,
[squareId, fruit],
function (err) {
if (err) return res.status(500).json({ error: err.message });
// broadcast update via Socket.io
io.emit('update', { squareId, fruit });
res.json({ success: true });
}
);
});
// Serve categories and fruits from a JSON file
app.get('/api/categories', (req, res) => {
const categoriesPath = path.join(__dirname, 'categories.json');
fs.readFile(categoriesPath, 'utf8', (err, data) => {
if (err) return res.status(500).json({ error: 'Could not load categories' });
try {
const categories = JSON.parse(data);
res.json(categories);
} catch (e) {
res.status(500).json({ error: 'Invalid categories file' });
}
});
});
// Add a fruit to a category in categories.json
app.post('/api/add-fruit', (req, res) => {
const { category, fruit } = req.body;
if (!category || !fruit) {
return res.status(400).json({ error: 'category and fruit required' });
}
const categoriesPath = path.join(__dirname, 'categories.json');
fs.readFile(categoriesPath, 'utf8', (err, data) => {
if (err) return res.status(500).json({ error: 'Could not load categories' });
let categories;
try {
categories = JSON.parse(data);
} catch (e) {
return res.status(500).json({ error: 'Invalid categories file' });
}
const cat = categories.find(c => c.name === category);
if (!cat) return res.status(404).json({ error: 'Category not found' });
// Prevent duplicates
if (cat.fruits.includes(fruit)) {
return res.status(400).json({ error: 'Fruit already exists in category' });
}
cat.fruits.push(fruit);
fs.writeFile(categoriesPath, JSON.stringify(categories, null, 2), err2 => {
if (err2) return res.status(500).json({ error: 'Could not save categories' });
res.json({ success: true });
});
});
});
// Delete a fruit from a category in categories.json
app.post('/api/delete-fruit', (req, res) => {
const { category, fruit } = req.body;
if (!category || !fruit) {
return res.status(400).json({ error: 'category and fruit required' });
}
const categoriesPath = path.join(__dirname, 'categories.json');
fs.readFile(categoriesPath, 'utf8', (err, data) => {
if (err) return res.status(500).json({ error: 'Could not load categories' });
let categories;
try {
categories = JSON.parse(data);
} catch (e) {
return res.status(500).json({ error: 'Invalid categories file' });
}
const cat = categories.find(c => c.name === category);
if (!cat) return res.status(404).json({ error: 'Category not found' });
const idx = cat.fruits.indexOf(fruit);
if (idx === -1) return res.status(404).json({ error: 'Fruit not found in category' });
cat.fruits.splice(idx, 1);
fs.writeFile(categoriesPath, JSON.stringify(categories, null, 2), err2 => {
if (err2) return res.status(500).json({ error: 'Could not save categories' });
res.json({ success: true });
});
});
});
// start server
const PORT = process.env.PORT || 3085;
server.listen(PORT, () => {
console.log(`Listening on http://localhost:${PORT}`);
});