106 lines
2.9 KiB
JavaScript
106 lines
2.9 KiB
JavaScript
/**
|
|
* 后端 API 服务(可单独部署)。仅提供 /api/* 接口,不提供静态资源。
|
|
* 弹幕开关与位置由 GET /api/config 返回(默认不显示弹幕)。
|
|
*/
|
|
const express = require('express');
|
|
const db = require('./db.js');
|
|
|
|
db.initDb();
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
const corsOrigin = process.env.CORS_ORIGIN || '*';
|
|
app.use((req, res, next) => {
|
|
res.setHeader('Access-Control-Allow-Origin', corsOrigin);
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
if (req.method === 'OPTIONS') return res.sendStatus(204);
|
|
next();
|
|
});
|
|
|
|
app.get('/config', (req, res) => {
|
|
try {
|
|
res.json(db.getConfig());
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.get('/stats', (req, res) => {
|
|
try {
|
|
res.json(db.getStats());
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/view', (req, res) => {
|
|
try {
|
|
res.json(db.incView());
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/like', (req, res) => {
|
|
try {
|
|
res.json(db.incLike());
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/share', (req, res) => {
|
|
try {
|
|
res.json(db.incShare());
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/join', (req, res) => {
|
|
try {
|
|
const viewerId = req.body && req.body.viewerId ? String(req.body.viewerId) : null;
|
|
if (!viewerId) return res.status(400).json({ error: 'viewerId required' });
|
|
const watchingNow = db.joinViewer(viewerId);
|
|
res.json({ watchingNow });
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/leave', (req, res) => {
|
|
try {
|
|
const viewerId = req.body && req.body.viewerId ? String(req.body.viewerId) : null;
|
|
if (!viewerId) return res.status(400).json({ error: 'viewerId required' });
|
|
const watchingNow = db.leaveViewer(viewerId);
|
|
res.json({ watchingNow });
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.get('/comments', (req, res) => {
|
|
try {
|
|
const limit = Math.min(parseInt(req.query.limit, 10) || 100, 200);
|
|
res.json(db.getComments(limit));
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
app.post('/comments', (req, res) => {
|
|
try {
|
|
const content = req.body && req.body.content != null ? String(req.body.content) : '';
|
|
const nickname = req.body && req.body.nickname != null ? String(req.body.nickname) : '';
|
|
if (!content.trim()) return res.status(400).json({ error: 'content required' });
|
|
const comment = db.addComment(content.trim(), nickname.trim() || null);
|
|
res.json(comment);
|
|
} catch (e) {
|
|
res.status(500).json({ error: String(e.message) });
|
|
}
|
|
});
|
|
|
|
module.exports = app;
|