Comic Developer
Initial clean commit - Comic generator with SDXL
4595df6
const http = require('http');
const fs = require('fs');
const path = require('path');
// Porta do servidor
const PORT = 8081;
// Tipos MIME para diferentes extens玫es de arquivo
const MIME_TYPES = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'text/javascript',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon'
};
// Fun莽茫o para servir arquivos est谩ticos
function serveStaticFile(res, pathname, contentType) {
// Se for a raiz, servir o index.html
if (pathname === '/') {
pathname = '/index.html';
}
let filePath;
// Verificar se 茅 um diret贸rio de hist贸ria em quadrinhos
if (pathname.startsWith('/comic_')) {
// Servir arquivos de hist贸rias em quadrinhos do diret贸rio raiz
filePath = path.join(process.cwd(), pathname);
} else {
// Servir arquivos web do diret贸rio web
filePath = path.join(process.cwd(), 'web', pathname);
}
// Verificar se o arquivo existe
fs.access(filePath, fs.constants.F_OK, (err) => {
if (err) {
// Arquivo n茫o encontrado
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 Not Found</h1><p>O arquivo solicitado n茫o foi encontrado.</p>');
return;
}
// Ler e servir o arquivo
fs.readFile(filePath, (err, data) => {
if (err) {
// Erro ao ler o arquivo
res.writeHead(500, { 'Content-Type': 'text/html' });
res.end('<h1>500 Internal Server Error</h1><p>Ocorreu um erro ao ler o arquivo.</p>');
return;
}
// Servir o arquivo com o tipo de conte煤do correto
res.writeHead(200, { 'Content-Type': contentType });
res.end(data);
});
});
}
// Fun莽茫o para gerar uma hist贸ria em quadrinhos
function generateComicStory(theme, title, res) {
const { spawn } = require('child_process');
// Criar um processo filho para executar o script Python
const pythonProcess = spawn('python3', ['comic_story_generator.py', theme, title], {
cwd: process.cwd()
});
let output = '';
let errorOutput = '';
// Capturar a sa铆da do processo
pythonProcess.stdout.on('data', (data) => {
output += data.toString();
});
// Capturar erros do processo
pythonProcess.stderr.on('data', (data) => {
errorOutput += data.toString();
});
// Quando o processo terminar
pythonProcess.on('close', (code) => {
if (code === 0) {
// Processo terminou com sucesso
// Procurar o nome do diret贸rio da hist贸ria gerada na sa铆da
const directoryMatch = output.match(/Saving to directory: (comic_\d+)/);
if (directoryMatch) {
const directory = directoryMatch[1];
// Gerar o visualizador HTML
const viewerProcess = spawn('python3', ['comic_viewer.py', directory], {
cwd: process.cwd()
});
viewerProcess.on('close', (viewerCode) => {
if (viewerCode === 0) {
// Retornar sucesso com o diret贸rio da hist贸ria gerada
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
directory: directory,
message: 'Hist贸ria em quadrinhos gerada com sucesso!'
}));
} else {
// Erro ao gerar o visualizador
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
error: 'Erro ao gerar o visualizador HTML',
details: errorOutput
}));
}
});
} else {
// N茫o foi poss铆vel encontrar o diret贸rio da hist贸ria gerada
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
error: 'N茫o foi poss铆vel encontrar o diret贸rio da hist贸ria gerada',
output: output
}));
}
} else {
// Processo terminou com erro
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
error: 'Erro ao gerar a hist贸ria em quadrinhos',
details: errorOutput
}));
}
});
}
// Criar o servidor
const server = http.createServer((req, res) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
// Endpoint para gerar hist贸rias em quadrinhos
if (req.method === 'POST' && req.url === '/api/generate-comic') {
let body = '';
// Coletar os dados da requisi莽茫o
req.on('data', chunk => {
body += chunk.toString();
});
// Processar a requisi莽茫o quando todos os dados forem recebidos
req.on('end', () => {
try {
const data = JSON.parse(body);
const { theme, title } = data;
// Validar os dados
if (!theme || !title) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
error: 'Tema e t铆tulo s茫o obrigat贸rios'
}));
return;
}
// Gerar a hist贸ria em quadrinhos
generateComicStory(theme, title, res);
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: false,
error: 'Dados inv谩lidos',
details: error.message
}));
}
});
return;
}
// Determinar o tipo de conte煤do com base na extens茫o do arquivo
const extname = path.extname(req.url);
const contentType = MIME_TYPES[extname] || 'text/html';
// Servir o arquivo solicitado
serveStaticFile(res, req.url, contentType);
});
// Iniciar o servidor
server.listen(PORT, () => {
console.log(`Servidor HD French Comic Generator rodando em http://localhost:${PORT}`);
console.log('Pressione Ctrl+C para parar o servidor');
});