This commit is contained in:
爱喝水的木子
2026-03-02 15:35:39 +08:00
commit 00b48da363
1590 changed files with 285117 additions and 0 deletions

163
server.js Normal file
View File

@@ -0,0 +1,163 @@
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const crypto = require('crypto');
const app = express();
app.use(cors());
app.use(express.json());
const ipRequestCount = new Map();
const RATE_LIMIT = 10;
const RATE_WINDOW = 60 * 1000;
const rateLimitMiddleware = (req, res, next) => {
const ip = req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
const now = Date.now();
if (!ipRequestCount.has(ip)) {
ipRequestCount.set(ip, { count: 1, resetTime: now + RATE_WINDOW });
return next();
}
const ipData = ipRequestCount.get(ip);
if (now > ipData.resetTime) {
ipData.count = 1;
ipData.resetTime = now + RATE_WINDOW;
return next();
}
if (ipData.count >= RATE_LIMIT) {
return res.status(429).json({ error: '提交过于频繁,请稍后再试' });
}
ipData.count++;
next();
};
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
let Suggestion;
const getSuggestionModel = () => {
if (!Suggestion) {
const suggestionSchema = new mongoose.Schema({
title: { type: String, required: true },
type: {
type: String,
required: true,
enum: ['网站建议', '其他建议', '个人建议', '开发建议']
},
text: { type: String, required: true },
deviceHash: { type: String, default: '' },
deviceDetail: {
userAgent: String,
language: String,
platform: String,
screenWidth: Number,
screenHeight: Number,
timezone: String,
ip: String,
cpuCores: String,
deviceMemory: String,
gpu: String,
hardDisk: String
},
status: {
type: String,
enum: ['待处理', '处理中', '已完成', '已拒绝'],
default: '待处理'
},
progress: { type: Number, default: 0 },
createdAt: { type: Date, default: Date.now }
}, { collection: 'suggestions' });
Suggestion = mongoose.model('Suggestion', suggestionSchema);
}
return Suggestion;
};
const connectDB = async () => {
if (mongoose.connection.readyState === 0) {
const uri = process.env.MONGODB_URI;
if (!uri) {
throw new Error('MONGODB_URI not configured');
}
await mongoose.connect(uri);
}
};
app.post('/api/suggestions', rateLimitMiddleware, async (req, res) => {
try {
await connectDB();
let { title, type, text, deviceInfo } = req.body;
if (!title || !type || !text) {
return res.status(400).json({ error: '请填写所有必填字段' });
}
try {
const decodedTitle = Buffer.from(title, 'base64').toString('utf8');
const decodedText = Buffer.from(text, 'base64').toString('utf8');
if (decodedTitle && decodedText) {
title = decodedTitle;
text = decodedText;
}
} catch (e) {}
let hashedDeviceInfo = '';
let deviceDetail = {};
const clientIp = req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
if (deviceInfo) {
try {
const decodedDevice = Buffer.from(deviceInfo, 'base64').toString('utf8');
hashedDeviceInfo = md5(decodedDevice);
deviceDetail = JSON.parse(decodedDevice);
deviceDetail.ip = clientIp;
} catch (e) {
hashedDeviceInfo = md5(deviceInfo);
}
}
const SuggestionModel = getSuggestionModel();
const suggestion = new SuggestionModel({
title,
type,
text,
deviceHash: hashedDeviceInfo,
deviceDetail: deviceDetail
});
const saved = await suggestion.save();
res.json({ id: saved._id.toString(), message: '建议提交成功' });
} catch (error) {
console.error('Save error:', error);
res.status(500).json({ error: '提交失败: ' + error.message });
}
});
app.get('/api/suggestions/:id', async (req, res) => {
try {
await connectDB();
const SuggestionModel = getSuggestionModel();
const suggestion = await SuggestionModel.findById(req.params.id);
if (!suggestion) {
return res.status(404).json({ error: '未找到该建议' });
}
res.json(suggestion);
} catch (error) {
console.error('Query error:', error);
res.status(500).json({ error: '查询失败' });
}
});
app.get('/', (req, res) => {
res.send('Suggestion API Running');
});
module.exports = app;