Files
What-to-watch/server.js
2026-02-09 11:24:43 +01:00

103 lines
3.3 KiB
JavaScript

const express = require('express');
const path = require('path');
const pool = require('./db');
require('dotenv').config();
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// Get all watchlist items
app.get('/api/watchlist', async (req, res) => {
try {
const [rows] = await pool.query('SELECT * FROM watchlist ORDER BY created_at DESC');
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Add a new watchlist item (now accepts poster)
app.post('/api/watchlist', async (req, res) => {
try {
const { title, type = 'movie', notes = '', poster = null } = req.body;
if (!title || !title.trim()) return res.status(400).json({ error: 'Title required' });
const [result] = await pool.query(
'INSERT INTO watchlist (title, type, notes, poster) VALUES (?, ?, ?, ?)',
[title.trim(), type, notes, poster]
);
const [rows] = await pool.query('SELECT * FROM watchlist WHERE id = ?', [result.insertId]);
res.status(201).json(rows[0]);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Delete an item
app.delete('/api/watchlist/:id', async (req, res) => {
try {
const { id } = req.params;
await pool.query('DELETE FROM watchlist WHERE id = ?', [id]);
res.json({ success: true });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Toggle watched state
app.put('/api/watchlist/:id/toggle', async (req, res) => {
try {
const { id } = req.params;
const [rows] = await pool.query('SELECT watched FROM watchlist WHERE id = ?', [id]);
if (!rows.length) return res.status(404).json({ error: 'Not found' });
const newState = rows[0].watched ? 0 : 1;
await pool.query('UPDATE watchlist SET watched = ? WHERE id = ?', [newState, id]);
res.json({ id: Number(id), watched: !!newState });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Suggest a random unwatched (or any) item
app.get('/api/suggest', async (req, res) => {
try {
const onlyUnwatched = req.query.unwatched === '1' || req.query.unwatched === 'true';
let rows;
if (onlyUnwatched) {
[rows] = await pool.query('SELECT * FROM watchlist WHERE watched = 0');
} else {
[rows] = await pool.query('SELECT * FROM watchlist');
}
if (!rows.length) return res.json({ message: 'No items available' });
const choice = rows[Math.floor(Math.random() * rows.length)];
res.json(choice);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
const tmdb = require('./tmdb');
app.get('/api/search', async (req, res) => {
try {
const q = req.query.q || req.query.query;
const type = req.query.type; // optional: movie or tv
if (!q || !q.trim()) return res.status(400).json({ error: 'query required' });
const results = await tmdb.search(q.trim(), type);
res.json(results);
} catch (err) {
console.error('TMDb search error:', err?.response?.data || err.message || err);
res.status(500).json({ error: 'search failed', details: err.message });
}
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});