nsfw-ai-image-generator
kèm cấu trúc cơ bản.Thư mục/Tập tin | Mô tả |
---|---|
pages/_app.tsx | Entry point cho toàn bộ app |
pages/index.tsx | Trang chính |
public/ | Chứa tài nguyên tĩnh (ảnh,...) |
styles/globals.css | CSS toàn cục |
tsconfig.json | Cấu hình TypeScript |
package.json | Quản lý thư viện & script |
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.js
để khai báo đường dẫn các file template:module.exports = { content: [ './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}', ], theme: { extend: {} }, plugins: [],}
styles/globals.css
, thêm 3 dòng sau:@tailwind base;@tailwind components;@tailwind utilities;
pages/index.tsx
và thay thế bằng mã nguồn sau:import { useState } from 'react';
const Home = () => { const [prompt, setPrompt] = useState(''); const [imageSrc, setImageSrc] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState('');
const handleGenerateImage = async () => { setIsLoading(true); setError(''); try { const response = await fetch('/api/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt }), }); if (!response.ok) throw new Error('Image generation failed'); const { imageUrl, isNSFW } = await response.json(); if (isNSFW) { setError('NSFW content detected'); return; } setImageSrc(imageUrl); } catch (err) { setError(err.message || 'Failed to generate image'); } finally { setIsLoading(false); } };
return ( <div className="min-h-screen bg-gray-100 py-8 px-4"> <div className="max-w-2xl mx-auto"> <h1 className="text-4xl font-bold text-center mb-8">NSFW AI Image Generator</h1> <div className="bg-white rounded-lg shadow-md p-6"> <div className="flex gap-4 mb-4"> <input type="text" value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder="Enter your prompt..." className="flex-1 p-2 border rounded-md" /> <button onClick={handleGenerateImage} disabled={isLoading} className="bg-blue-600 text-white px-6 py-2 rounded-md hover:bg-blue-700 disabled:opacity-50" > {isLoading ? 'Generating...' : 'Generate'} </button> </div> {error && <div className="text-red-500 mb-4">{error}</div>} {imageSrc && ( <div className="mt-6"> <h2 className="text-xl font-semibold mb-4">Generated Image:</h2> <img src={imageSrc} alt="Generated" className="w-full h-auto rounded-lg shadow-md" /> </div> )} </div> </div> </div> );};
export default Home;
pages/api/generate.ts
:import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { const { prompt } = req.body;
try { const response = await fetch('https://api.replicate.com/v1/predictions', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Token ${process.env.REPLICATE_API_TOKEN}`, }, body: JSON.stringify({ version: 'a9758cbfbd5f3c2094457d996681af52552901775aa2d6dd0b17fd15df959bef', input: { prompt: prompt, width: 512, height: 512, num_outputs: 1, }, }), });
const prediction = await response.json();
// Kiểm tra NSFW const isNSFW = await checkNSFW(prediction.output[0]);
res.status(200).json({ imageUrl: prediction.output[0], isNSFW }); } catch (error: any) { res.status(500).json({ error: error.message }); }}
// Ví dụ sử dụng NSFWJS để phân loại ảnhasync function checkNSFW(imageUrl: string): Promise<boolean> { const tf = await import('@tensorflow/tfjs'); const nsfwjs = await import('nsfwjs'); const model = await nsfwjs.load();
const image = await fetch(imageUrl); const buffer = await image.arrayBuffer();
const img = tf.node.decodeImage(new Uint8Array(buffer), 3); const predictions = await model.classify(img);
return predictions.some(p => ['Hentai', 'Porn', 'Sexy'].includes(p.className));}
nsfwjs
kết hợp TensorFlow để phân tích ảnh tạo ra, kiểm tra xem có thuộc nội dung NSFW không.isNSFW
để hiển thị hoặc cảnh báo.function validatePrompt(prompt: string): boolean { const blockedTerms = ['nudity', 'explicit', 'porn', 'sexual', 'nsfw', 'adult']; return !new RegExp(blockedTerms.join('|'), 'i').test(prompt);}
.env.local
với nội dung:REPLICATE_API_TOKEN=your_api_token_here
vercel.json
:{ "build": { "env": { "REPLICATE_API_TOKEN": "@replicate-api-token" } }}
vercel deploy --prod