1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
| const express = require('express'); const Redis = require('ioredis'); const path = require('path');
const app = express(); app.use(express.json({ limit: '4mb' })); app.use(express.static(path.join(__dirname, 'public')));
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const KV_KEY = 'guestbook:messages'; const MAX_MESSAGES = 500;
app.get('/api/messages', async (req, res) => { try { const messages = await redis.lrange(KV_KEY, 0, -1); const parsed = messages.map(m => JSON.parse(m)); res.json(parsed); } catch (err) { console.error('GET Error:', err); res.status(500).json({ error: '服务器错误' }); } });
app.post('/api/messages', async (req, res) => { try { const { nickname, content, emoji, imageUrl, avatarUrl } = req.body; if (!nickname || !content) { return res.status(400).json({ error: '昵称和内容不能为空' }); }
const message = { id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6), nickname, content, emoji: emoji || null, imageUrl: imageUrl || null, avatarUrl: avatarUrl || null, createdAt: new Date().toISOString(), };
await redis.lpush(KV_KEY, JSON.stringify(message)); const len = await redis.llen(KV_KEY); if (len > MAX_MESSAGES) { await redis.ltrim(KV_KEY, 0, MAX_MESSAGES - 1); }
res.status(201).json(message); } catch (err) { console.error('POST Error:', err); res.status(500).json({ error: '服务器错误' }); } });
app.delete('/api/messages', async (req, res) => { try { const { id } = req.body; if (!id) return res.status(400).json({ error: '缺少留言 ID' });
const messages = await redis.lrange(KV_KEY, 0, -1); const filtered = messages.filter(m => JSON.parse(m).id !== id);
if (filtered.length === messages.length) { return res.status(404).json({ error: '留言不存在' }); }
await redis.del(KV_KEY); if (filtered.length > 0) { await redis.lpush(KV_KEY, ...filtered.reverse()); }
res.json({ success: true }); } catch (err) { console.error('DELETE Error:', err); res.status(500).json({ error: '服务器错误' }); } });
app.post('/api/upload', async (req, res) => { try { const { filename, base64, data } = req.body; const fileData = base64 || data;
if (!filename || !fileData) { return res.status(400).json({ error: '缺少文件数据' }); }
const sizeKB = Math.round((fileData.length * 3) / 4 / 1024); if (sizeKB > 1024) { return res.status(400).json({ error: '图片不能超过 1MB' }); }
const ext = filename.split('.').pop().toLowerCase() || 'png'; const imageId = `img_${Date.now().toString(36)}.${ext}`;
await redis.set(imageId, fileData, 'EX', 7776000);
const protocol = req.secure ? 'https' : 'http'; const url = `${protocol}://${req.headers.host}/api/image?id=${imageId}`;
res.json({ url }); } catch (err) { console.error('Upload Error:', err); res.status(500).json({ error: '上传失败' }); } });
app.get('/api/image', async (req, res) => { try { const { id } = req.query; if (!id) return res.status(400).json({ error: '缺少图片 ID' });
const base64Data = await redis.get(id); if (!base64Data) { return res.status(404).json({ error: '图片不存在或已过期' }); }
const ext = id.split('.').pop().toLowerCase(); const mimeMap = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp', }; const contentType = mimeMap[ext] || 'image/png';
const buffer = Buffer.from(base64Data, 'base64');
res.setHeader('Content-Type', contentType); res.setHeader('Content-Disposition', 'inline'); res.setHeader('Cache-Control', 'public, max-age=86400'); res.send(buffer); } catch (err) { console.error('Image Error:', err); res.status(500).json({ error: '服务器错误' }); } });
app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); });
const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
|