const express = require('express'); const cors = require('cors'); const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const app = express(); const PORT = process.env.PORT || 3001; const INVITE_CODE = 'Moka'; // 注册需校验此邀请码 // 启用中间件 app.use(cors()); // 允许 Chrome 扩展跨域请求 app.use(express.json()); // 解析 application/json // 初始化 SQLite 数据库 (建议使用绝对路径并指向挂载的目录) const dbPath = process.env.DB_PATH || path.join(__dirname, 'data', 'data.db'); const dbDir = path.dirname(dbPath); // 确保目录存在 const fs = require('fs'); if (!fs.existsSync(dbDir)) { fs.mkdirSync(dbDir, { recursive: true }); } const db = new sqlite3.Database(dbPath, (err) => { if (err) { console.error('Could not connect to database', err); } else { console.log('Connected to sqlite3 database at:', dbPath); // 初始化用户表 db.run(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, rules TEXT DEFAULT '[]', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); } }); // === 接口 1: 注册 === app.post('/api/register', (req, res) => { const { username, password, inviteCode } = req.body; if (inviteCode !== INVITE_CODE) { return res.json({ code: 1, msg: '注册码错误' }); } if (!username || !password) { return res.json({ code: 1, msg: '用户名和密码不能为空' }); } // 写入数据库 (直接使用 db.run 更简洁) db.run('INSERT INTO users (username, password) VALUES (?, ?)', [username, password], function (err) { if (err) { if (err.message.includes('UNIQUE constraint failed')) { return res.json({ code: 1, msg: '用户名太火爆,已被注册' }); } console.error('Register error:', err); return res.json({ code: 1, msg: '服务器内部错误' }); } res.json({ code: 0, msg: '注册成功' }); }); }); // === 接口 2: 登录 === app.post('/api/login', (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.json({ code: 1, msg: '请输入用户名和密码' }); } db.get('SELECT * FROM users WHERE username = ? AND password = ?', [username, password], (err, row) => { if (err) { console.error('Login error:', err); return res.json({ code: 1, msg: '服务器内部错误' }); } if (!row) { return res.json({ code: 1, msg: '账号或密码错误' }); } let parsedRules = []; try { parsedRules = row.rules ? JSON.parse(row.rules) : []; } catch (e) { console.error('Failed to parse rules JSON', e); } res.json({ code: 0, msg: '登录成功', data: { rules: parsedRules } }); }); }); // === 接口 3: 同步配置数据 (保存更新) === app.post('/api/sync', (req, res) => { const { username, rules } = req.body; if (!username || !Array.isArray(rules)) { return res.json({ code: 1, msg: '参数不合法' }); } const rulesJsonStr = JSON.stringify(rules); // 覆盖更新该用户的 rules 列 // (简化起见,此处信任前端传来的 username。真实生产在这一步应当检验 token/session,不过做个人小工具够用即可防君子) db.run('UPDATE users SET rules = ? WHERE username = ?', [rulesJsonStr, username], function (err) { if (err) { console.error('Sync error:', err); return res.json({ code: 1, msg: '同步失败:服务器内部错误' }); } if (this.changes === 0) { return res.json({ code: 1, msg: '同步失败:未找到该用户' }); } res.json({ code: 0, msg: '同步成功' }); }); }); // 启动服务器 app.listen(PORT, '0.0.0.0', () => { console.log(`Server is running on http://0.0.0.0:${PORT}`); console.log(`API endpoints available:`); console.log(`- POST /api/register`); console.log(`- POST /api/login`); console.log(`- POST /api/sync`); });