diff --git a/endpoints/video.js b/endpoints/video.js index bfc3d88..6ff4788 100644 --- a/endpoints/video.js +++ b/endpoints/video.js @@ -1,20 +1,16 @@ var parameters = require('../helpers/parameters'); var properties = require('../helpers/properties'); -var requests = require('../helpers/requests'); +var files = require('../helpers/files'); +var core = require('../helpers/core'); -var exec = require('child_process').exec, child; -var querystring = require('querystring'); var uuid = require('node-uuid'); var mkdirp = require('mkdirp'); -var http = require('http'); -var url = require('url'); -var fs = require('fs'); +var async = require('async'); function init(req, res) { + res.set("Content-Type", "application/json"); - var id = uuid.v4(); - - /* Verifica se os paramêtros [posicao, tamanho, transparencia] possuem algum valor */ + /* Verifica se os paramêtros [transparencia, texto] possuem algum valor */ if ((req.body.posicao === '') || (req.body.tamanho === '') || (req.body.transparencia === '')) { res.send(500, parameters.errorMessage('O valor de algum parâmetro está vazio')); return; @@ -25,115 +21,85 @@ function init(req, res) { res.send(500, parameters.errorMessage('Parâmetros insuficientes ou inválidos')); return; } + + process(req, res); +}; - /* Checa se o arquivo de vídeo submetivo possui uma extensão válida */ - if (req.files.video !== undefined) { - if (parameters.checkVideo(req.files.video.name) === false) { - res.send(500, parameters.errorMessage('Vídeo enviado com extensão inválida')); - return; - } - - var video = { - 'name': req.files.video.name, - 'path': req.files.video.path - } - - processVideo(id, video, req, res); - - } else if (req.body.video_url !== undefined) { - http.get(req.body.video_url, function(response) { - - // Salva o arquivo em disco - response.pipe(fs.createWriteStream(id)); - - var video = { - 'name': req.body.video_url.substring(req.body.video_url.lastIndexOf('/') + 1), - 'path': id - } - - processVideo(id, video, req, res); - - }).on('error', function(e) { - error = 'Problema ao carregar video_url: ' + e.message; - - res.send(500, parameters.errorMessage(error)); - }); +function process(req, res) { + var id = uuid.v4(); + var folder = properties.uploads_folder + id; + var locals = {}; + + async.series([ + // Cria a pasta apropriada + function(callback) { + console.log("== Criando pasta " + folder); - } else { - res.send(500, parameters.errorMessage('Video deve ser enviado como parâmetro "video" ou como "video_url"')); - return; - } -}; + mkdirp(folder, function(err) { + var error; + if (err) { error = "Erro na criação da pasta com o id: " + id + "; " + err; } -function processVideo(id, video, req, res) { - /* Cria uma pasta cujo o nome é o ID atual */ - mkdirp(properties.uploads_folder + id, function(error) { - - if (error) { console.log(error); res.send(500, parameters.errorMessage('Erro na criação da pasta com o ID: ' + id)); return; } - - /* Move o vídeo submetido para a pasta com o seu ID correspondente */ - fs.rename(video.path, properties.uploads_folder + id + '/' + video.name, function(error) { - if (error) { console.log(error); res.send(500, parameters.errorMessage('Erro ao mover o vídeo submetido')); return; } - }); - - /* Cria a linha de comando */ - var command_line = 'vlibras_user/vlibras-core/./vlibras ' + parameters.getServiceType(req.body.servico) + ' uploads/' + id + '/' + - video.name + ' 1 ' + parameters.getPosition(req.body.posicao) + ' ' + parameters.getSize(req.body.tamanho) + ' ' + - parameters.getTransparency(req.body.transparencia) + ' ' + id + ' > /tmp/core_log 2>&1'; - - console.log(command_line); - - /* Executa a linha de comando */ - child = exec(command_line, function(err, stdout, stderr) { - // [stdout] = vlibras-core output - // console.log('Err: ' + err); - // console.log('STDOUT: ' + stdout); - // console.log('STDERR: ' + stderr); - }); - - if (req.body.callback === undefined) { - /* Listener que dispara quando a requisição ao core finaliza */ - child.on('close', function(code, signal){ - if (code !== 0) { - console.log('Erro código: ' + code); res.send(500, { 'error': 'Erro no Core', 'code': code }); return; - } - - res.send(200, { 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.flv' }); + callback(error); }); + }, + + // Baixa e move os arquivos para a pasta correta + function(callback) { + console.log("== Baixando os arquivos"); + + downloadAndMoveFiles(folder, req, locals, callback); + }, + + // Chama o core + function(callback) { + console.log("== Chamando o core"); + + // Faz a chamada ao core + try { + callCore(id, locals.video, locals.subtitle, req, res); + callback(); + } catch (err) { + callback(err); + } + } + ], function(err) { + // Se tiver erro + if (err) { + res.send(500, parameters.errorMessage(err)); - child.on('error', function(code, signal){ - res.send(500, parameters.errorMessage('Erro na chamada ao core')); - }); - } else { + return; + } + }); +} - child.on('close', function(code, signal){ - if (code !== 0) { - var path = url.parse(req.body.callback); - var data = querystring.stringify( { 'error': 'Erro no Core', 'code': code } ); - requests.postRequest(path, data); +function downloadAndMoveFiles(folder, req, locals, callback) { + async.parallel([ + // Download video + function(callback) { + files.downloadAndMoveVideo(folder, req, locals, callback); + } + ], function(err) { + console.log("=== Video baixado"); - return; - } + // Callback chamado depois de todas as tarefas + // Se tiver erro, vai passar para cima + callback(err); + }); +} - var path = url.parse(req.body.callback); - var data = querystring.stringify({ 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.flv' }); - requests.postRequest(path, data); - }); +function callCore(id, video, subtitle, req, res) { - /* Listener que dispara quando a requisição ao core da erro */ - child.on('error', function(code, signal){ - var path = url.parse(req.body.callback); - var data = querystring.stringify( { 'error': 'Erro na chamada ao core', 'code': code, 'id': id } ); + /* Cria a linha de comando */ + var command_line = 'vlibras_user/vlibras-core/./vlibras ' + parameters.getServiceType(req.body.servico) + ' ' + + video.path + ' 1 ' + parameters.getPosition(req.body.posicao) + ' ' + parameters.getSize(req.body.tamanho) + ' ' + + parameters.getTransparency(req.body.transparencia) + ' ' + id + ' > /tmp/core_log 2>&1'; - requests.postRequest(path, data); - }); + console.log("=== Core: " + command_line); - res.send(200, JSON.stringify({ 'id': id })); - } - }); -} + core.call(id, command_line, req, res); +}; module.exports.init = init; diff --git a/endpoints/video_legenda.js b/endpoints/video_legenda.js index 7bed2c9..089ebd9 100644 --- a/endpoints/video_legenda.js +++ b/endpoints/video_legenda.js @@ -1,18 +1,14 @@ var parameters = require('../helpers/parameters'); var properties = require('../helpers/properties'); -var requests = require('../helpers/requests'); +var files = require('../helpers/files'); +var core = require('../helpers/core'); -var exec = require('child_process').exec, child; -var querystring = require('querystring'); var uuid = require('node-uuid'); var mkdirp = require('mkdirp'); -var http = require('http'); -var url = require('url'); -var fs = require('fs'); +var async = require('async'); function init(req, res) { - - var id = uuid.v4(); + res.set("Content-Type", "application/json"); /* Verifica se os paramêtros [transparencia, texto] possuem algum valor */ if ((req.body.linguagem === '') || (req.body.posicao === '') || (req.body.tamanho === '') || (req.body.transparencia === '')) { @@ -25,92 +21,91 @@ function init(req, res) { res.send(500, parameters.errorMessage('Parâmetros insuficientes ou inválidos')); return; } - - /* Checa se o arquivo de vídeo submetivo possui uma extensão válida */ - if (parameters.checkVideo(req.files.video.name) === false) { - res.send(500, parameters.errorMessage('Vídeo com Extensão Inválida')); - return; - } - - /* Checa se o arquivo de legenda submetivo possui uma extensão válida */ - if (parameters.checkSubtitle(req.files.legenda.name) === false) { - res.send(500, parameters.errorMessage('Legenda com Extensão Inválida')); - return; - } + + process(req, res); +}; - /* Cria uma pasta cujo o nome é o ID atual */ - mkdirp(properties.uploads_folder + id, function(error) { +function process(req, res) { + var id = uuid.v4(); + var folder = properties.uploads_folder + id; + var locals = {}; - if (error) { console.log(error); return; } - - /* Move o vídeo submetido para a pasta com o seu ID correspondente */ - fs.rename(req.files.video.path, properties.uploads_folder + id + '/' + req.files.video.name, function(error) { - if (error) { console.log(error); res.send(500, parameters.errorMessage('Erro ao mover o vídeo submetido')); return; } - }); - - /* Move a legenda submetido para a pasta com o seu ID correspondente */ - fs.rename(req.files.legenda.path, properties.uploads_folder + id + '/' + req.files.legenda.name, function(error) { - if (error) { console.log(error); res.send(500, parameters.errorMessage('Erro ao mover a legenda submetido')); return; } - }); - - /* Cria a linha de comando */ - var command_line = 'vlibras_user/vlibras-core/./vlibras ' + parameters.getServiceType(req.body.servico) + ' uploads/' + id + '/' + - req.files.video.name + ' uploads/' + id + '/' + req.files.legenda.name + ' ' + parameters.getLanguage(req.body.linguagem) + - ' ' + parameters.getPosition(req.body.posicao) + ' ' + parameters.getSize(req.body.tamanho) + ' ' + - parameters.getTransparency(req.body.transparencia) + ' ' + id + ' > /tmp/core_log 2>&1'; - - console.log(command_line); - - /* Executa a linha de comando */ - child = exec(command_line, function(err, stdout, stderr) { - // [stdout] = vlibras-core output - // console.log('Err: ' + err); - // console.log('STDOUT: ' + stdout); - // console.log('STDERR: ' + stderr); - }); - - if (req.body.callback === undefined) { - /* Listener que dispara quando a requisição ao core finaliza */ - child.on('close', function(code, signal){ - if (code !== 0) { - console.log('Erro código: ' + code); res.send(500, { 'error': 'Erro no Core', 'code': code }); return; - } - - res.send(200, { 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.flv' }); - }); + async.series([ + // Cria a pasta apropriada + function(callback) { + console.log("== Criando pasta " + folder); + + mkdirp(folder, function(err) { + var error; + + if (err) { error = "Erro na criação da pasta com o id: " + id + "; " + err; } - child.on('error', function(code, signal){ - res.send(500, parameters.errorMessage('Erro na chamada ao core')); + callback(error); }); - } else { + }, + + // Baixa e move os arquivos para a pasta correta + function(callback) { + console.log("== Baixando os arquivos"); + + downloadAndMoveFiles(folder, req, locals, callback); + }, + + // Chama o core + function(callback) { + console.log("== Chamando o core"); + + // Faz a chamada ao core + try { + callCore(id, locals.video, locals.subtitle, req, res); + callback(); + } catch (err) { + callback(err); + } + } + ], function(err) { + // Se tiver erro + if (err) { + res.send(500, parameters.errorMessage(err)); - child.on('close', function(code, signal){ - if (code !== 0) { - var path = url.parse(req.body.callback); - var data = querystring.stringify( { 'error': 'Erro no Core', 'code': code } ); + return; + } + }); +} - requests.postRequest(path, data); - return; - } +function downloadAndMoveFiles(folder, req, locals, callback) { + async.parallel([ + // Download video + function(callback) { + files.downloadAndMoveVideo(folder, req, locals, callback); + }, - var path = url.parse(req.body.callback); - var data = querystring.stringify({ 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.flv' }); + // Download subtitle + function(callback) { + files.downloadAndMoveSubtitle(folder, req, locals, callback); + } + ], function(err) { + console.log("=== Legenda e video baixados"); - requests.postRequest(path, data); - }); + // Callback chamado depois de todas as tarefas + // Se tiver erro, vai passar para cima + callback(err); + }); +} - /* Listener que dispara quando a requisição ao core da erro */ - child.on('error', function(code, signal){ - var path = url.parse(req.body.callback); - var data = querystring.stringify( { 'error': 'Erro na chamada ao core', 'code': code, 'id': id } ); - requests.postRequest(path, data); - }); +function callCore(id, video, subtitle, req, res) { - res.send(200, JSON.stringify({ 'id': id })); - } - }); + /* Cria a linha de comando */ + var command_line = 'vlibras_user/vlibras-core/./vlibras ' + parameters.getServiceType(req.body.servico) + ' ' + + video.path + ' ' + subtitle.path + ' ' + parameters.getLanguage(req.body.linguagem) + + ' ' + parameters.getPosition(req.body.posicao) + ' ' + parameters.getSize(req.body.tamanho) + ' ' + + parameters.getTransparency(req.body.transparencia) + ' ' + id + ' > /tmp/core_log 2>&1'; + + console.log("=== Core: " + command_line); + + core.call(id, command_line, req, res); }; module.exports.init = init; diff --git a/helpers/core.js b/helpers/core.js new file mode 100644 index 0000000..953aa17 --- /dev/null +++ b/helpers/core.js @@ -0,0 +1,71 @@ +var requests = require('../helpers/requests'); + +var url = require('url'); +var http = require('http'); +var querystring = require('querystring'); +var exec = require('child_process').exec, child; + +function call(id, command_line, req, res) { + /* Executa a linha de comando */ + child = exec(command_line, function(err, stdout, stderr) { + // [stdout] = vlibras-core output + // console.log('Err: ' + err); + // console.log('STDOUT: ' + stdout); + // console.log('STDERR: ' + stderr); + }); + + // Se o callback não foi definido + if (req.body.callback === undefined) { + + // Se a chamada foi feita com sucesso + child.on('close', function(code, signal) { + + // Se o core executou com erro + if (code !== 0) { + throw "Erro no retorno do core. Código: " + code; + } + + // Se o core executou normal + res.send(200, { 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.flv' }); + }); + + // Se a chamada deu erro + child.on('error', function(code, signal) { + throw "Erro na chamada ao core"; + }); + + + // Se o callback foi definido + } else { + + // Se a chamada foi feita com sucesso + child.on('close', function(code, signal) { + + // Endereço do callback + var path = url.parse(req.body.callback); + + // Se o core executou com erro + if (code === 0) { + var data = querystring.stringify({ 'response' : 'http://' + properties.SERVER_IP + ':' + properties.port + '/' + id + '.mp4' }); + } else { + var data = querystring.stringify({ 'error': 'Erro no Core', 'code': code }); + } + + // Chama o callback + requests.postRequest(path, data); + }); + + // Se a chamada deu erro + child.on('error', function(code, signal) { + var path = url.parse(req.body.callback); + var data = querystring.stringify( { 'error': 'Erro na chamada ao core', 'code': code, 'id': id } ); + + requests.postRequest(path, data); + }); + + // Retorno da primeira requisição + res.send(200, JSON.stringify({ 'id': id })); + } +} + +module.exports.call = call; \ No newline at end of file diff --git a/helpers/files.js b/helpers/files.js new file mode 100644 index 0000000..afd833f --- /dev/null +++ b/helpers/files.js @@ -0,0 +1,141 @@ +var fs = require('fs'); +var http = require('http'); + +/* +* Função que processa o vídeo (seja baixando, seja pegando o vídeo enviado) +* Deve retornar um objeto contendo o nome e o caminho +*/ +function downloadAndMoveVideo(folder, req, locals, callback) { + + // Se enviou o arquivo na requisição + if (req.files.video !== undefined) { + + // Se a validação falhar + if (parameters.checkVideo(req.files.video.name) === false) { + var error = 'Vídeo enviado com extensão inválida'; + return callback(error); + } + + /* Move o vídeo submetido para a pasta com o seu ID correspondente */ + try { + fs.renameSync(req.files.video.path, folder + '/' + req.files.video.name); + } catch (err) { + callback("Erro ao mover o vídeo submetido: " + err); + } + + // Se não, retorna o vídeo enviado + locals.video = { + 'path': folder + '/' + req.files.video.name + } + + return callback(); + + // Se o arquivo não foi enviado, mas um video_url foi + } else if (req.body.video_url !== undefined) { + + // Requisição para baixar o vídeo + http.get(req.body.video_url, function(response) { + + // Se o vídeo não foi baixado com sucesso + if (response.statusCode !== 200) { + var error = 'Problema ao carregar video_url: status ' + response.statusCode; + return callback(error); + } + + // Nome do arquivo + var filename = req.body.video_url.substring(req.body.video_url.lastIndexOf('/') + 1); + var path = folder + '/' + filename; + + // Salva o arquivo em disco + response.pipe(fs.createWriteStream(path)); + + // Retorna o vídeo baixado + locals.video = { + 'path': path + } + + return callback(); + + // Se deu erro na requisição de baixar o vídeo + }).on('error', function(e) { + var error = 'Problema ao carregar video_url: ' + e.message; + return callback(error); + }); + + // Se nem o vídeo foi enviado e nem o video_url foi preenchido + } else { + var error = "Video deve ser enviado como parâmetro 'video' ou como 'video_url'"; + return callback(error); + } +} + +/* +* Função que processa a legenda (seja baixando, seja pegando o vídeo enviado) +* Deve retornar um objeto contendo o nome e o caminho +*/ +function downloadAndMoveSubtitle(folder, req, locals, callback) { + + // Se enviou o arquivo na requisição + if (req.files.legenda !== undefined) { + + // Se a validação falhar + if (parameters.checkSubtitle(req.files.legenda.name) === false) { + var error = 'Legenda enviado com extensão inválida'; + return callback(error); + } + + /* Move o vídeo submetido para a pasta com o seu ID correspondente */ + try { + fs.renameSync(req.files.legenda.path, folder + '/' + req.files.legenda.name); + } catch (err) { + callback("Erro ao mover a legenda submetida: " + err); + } + + // Se não, retorna o vídeo enviado + locals.subtitle = { + 'path': folder + '/' + req.files.legenda.name + } + + return callback(); + + // Se o arquivo não foi enviado, mas um legenda_url foi + } else if (req.body.legenda_url !== undefined) { + + // Requisição para baixar a legenda + http.get(req.body.legenda_url, function(response) { + + // Se a legenda não foi baixado com sucesso + if (response.statusCode !== 200) { + var error = 'Problema ao carregar legenda_url: status ' + response.statusCode; + return callback(error); + } + + // Nome do arquivo + var filename = req.body.legenda_url.substring(req.body.legenda_url.lastIndexOf('/') + 1); + var path = folder + '/' + filename; + + // Salva o arquivo em disco + response.pipe(fs.createWriteStream(path)); + + // Retorna o vídeo baixado + locals.subtitle = { + 'path': path + } + + return callback(); + + // Se deu erro na requisição de baixar a legenda + }).on('error', function(e) { + var error = 'Problema ao carregar legenda_url: ' + e.message; + return callback(error); + }); + + // Se nem a legenda foi enviada e nem a legenda_url foi preenchida + } else { + var error = "Legenda deve ser enviada como parâmetro 'legenda' ou como 'legenda_url'"; + return callback(error); + } +} + +module.exports.downloadAndMoveVideo = downloadAndMoveVideo; +module.exports.downloadAndMoveSubtitle = downloadAndMoveSubtitle; \ No newline at end of file diff --git a/helpers/parameters.js b/helpers/parameters.js index 7c54ea6..df89d14 100644 --- a/helpers/parameters.js +++ b/helpers/parameters.js @@ -172,7 +172,7 @@ function check_type(file, accepted_file_types) { }; function errorMessage(message) { - return { 'error': message } + return JSON.stringify({ 'error': message }) }; module.exports.getServiceType = getServiceType; diff --git a/helpers/requests.js b/helpers/requests.js index 424c3a0..a927ed2 100644 --- a/helpers/requests.js +++ b/helpers/requests.js @@ -14,20 +14,21 @@ function postRequest(path, data) { var requesting = http.request(options, function(res) { /* Debugging */ - /* - console.log('Callback response status: ' + res.statusCode); - console.log('Callback response headers: ' + JSON.stringify(res.headers)); + + console.log('== Chamando callback: ' + path.hostname) + console.log('=== Response status: ' + res.statusCode); + console.log('=== Response headers: ' + JSON.stringify(res.headers)); res.setEncoding('utf8'); res.on('data', function (chunk) { - console.log('Callback response body: ' + chunk); + console.log('=== Response body: ' + chunk); }); - */ + }); requesting.on('error', function (e) { - console.log("The callback URL can not be reachable"); + console.log("=== Não foi possível chamar a URL de callback"); }); requesting.write(data); diff --git a/package.json b/package.json index c103388..ccfed7b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "author": "LAViD", "license": "ISC", "dependencies": { + "async": "^0.9.0", "express": "~3.5.1", "mkdirp": "^0.5.0", "node-uuid": "^1.4.1" diff --git a/server.js b/server.js index f19163f..4be7a3f 100644 --- a/server.js +++ b/server.js @@ -7,8 +7,9 @@ var ep_video = require('./endpoints/video'); var ep_legenda = require('./endpoints/legenda'); var ep_video_legenda = require('./endpoints/video_legenda'); -var path = require('path'); var express = require('express'); +var path = require('path'); +var util = require('util'); var app = express(); app.use(express.static(path.join(__dirname, '/videos'))); @@ -18,7 +19,11 @@ app.get('/', function(req, res){ res.send(200, { 'status': 'server is running!' } ); }); -app.post('/api', function(req, res){ +app.post('/api', function(req, res) { + console.log("\n\n\n============================================="); + console.log("[" + new Date().toISOString() + "] Requisição do IP: " + req.ip); + console.log("== Parametros: " + util.inspect(req.body)); + /* Verifica se o paramêtro [servico] possui algum valor */ if (req.body.servico !== '') { /* Verifica qual é o Tipo de Serviço fornecido */ -- libgit2 0.21.2