Spaces:
Running
Running
File size: 4,473 Bytes
062c414 9953d0a 062c414 10299c3 062c414 10299c3 062c414 |
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 |
import { NextResponse } from 'next/server'
import fs from 'fs'
import path from 'path'
// Use /tmp for temporary message storage
// Messages will reset on rebuilds, which is fine for a global chat
const dataFilePath = path.join('/tmp', 'messages.json')
// Simple bad word list (expand as needed)
const BAD_WORDS = [
// English
'badword', 'spam', 'toxic', 'hate', 'violence', 'kill', 'stupid', 'idiot',
'fuck', 'fuxk', 'fck', 'shit', 'sh!t', 'bitch', 'asshole', 'damn', 'hell',
'crap', 'piss', 'dick', 'cock', 'pussy', 'bastard', 'slut', 'whore',
// Spanish
'puto', 'mierda', 'coño', 'cabron', 'pendejo', 'joder',
// French
'merde', 'putain', 'connard', 'salope', 'encule',
// German
'scheisse', 'arschloch', 'schlampe', 'fotze',
// Italian
'cazzo', 'merda', 'vaffanculo', 'stronzo',
// Portuguese
'porra', 'caralho', 'merda', 'puta',
// Russian (transliterated)
'cyka', 'blyat', 'nahui', 'pizda',
// Hindi (transliterated)
'madarchod', 'bhenchod', 'chutiya', 'kutta', 'kamina'
]
interface Message {
id: string
text: string
sender: string
userId: string
timestamp: number
}
const getMessages = (): Message[] => {
try {
if (!fs.existsSync(dataFilePath)) {
fs.writeFileSync(dataFilePath, '[]', 'utf8')
return []
}
const fileData = fs.readFileSync(dataFilePath, 'utf8')
return JSON.parse(fileData)
} catch (error) {
console.error('Error reading messages:', error)
return []
}
}
const saveMessages = (messages: Message[]) => {
try {
fs.writeFileSync(dataFilePath, JSON.stringify(messages, null, 2), 'utf8')
} catch (error) {
console.error('Error saving messages:', error)
}
}
export async function GET() {
const messages = getMessages()
return NextResponse.json(messages, {
headers: { 'Content-Type': 'application/json; charset=utf-8' }
})
}
export async function POST(request: Request) {
try {
const body = await request.json()
const { text, sender, userId } = body
// 1. Validation: Length
if (!text || text.length > 200) {
return NextResponse.json({ error: 'Message too long (max 200 chars)' }, { status: 400 })
}
if (!text.trim()) {
return NextResponse.json({ error: 'Message cannot be empty' }, { status: 400 })
}
// 2. Validation: Toxicity (whole word matching only)
const lowerText = text.toLowerCase()
const containsBadWord = BAD_WORDS.some(word => {
// Use word boundaries to match whole words only
const regex = new RegExp(`\\b${word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i')
return regex.test(text)
})
if (containsBadWord) {
return NextResponse.json({ error: 'Message contains inappropriate content' }, { status: 400 })
}
const messages = getMessages()
const now = Date.now()
// 3. Validation: Spam (Rate Limiting)
// Check if this user sent a message in the last 2 seconds
const lastMessageFromUser = messages
.filter(m => m.userId === userId)
.sort((a, b) => b.timestamp - a.timestamp)[0]
if (lastMessageFromUser && (now - lastMessageFromUser.timestamp) < 2000) {
return NextResponse.json({ error: 'You are sending messages too fast. Please wait.' }, { status: 429 })
}
// Check for duplicate message from same user
if (lastMessageFromUser && lastMessageFromUser.text === text) {
return NextResponse.json({ error: 'Do not send duplicate messages.' }, { status: 400 })
}
const newMessage: Message = {
id: Math.random().toString(36).substring(2, 15),
text: text.trim(),
sender: sender || 'Anonymous',
userId: userId,
timestamp: now
}
// Keep only last 100 messages to prevent file from growing too large
const updatedMessages = [...messages, newMessage].slice(-100)
saveMessages(updatedMessages)
return NextResponse.json(updatedMessages, {
headers: { 'Content-Type': 'application/json; charset=utf-8' }
})
} catch (error) {
console.error('Error processing message:', error)
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
}
}
|