var express = require("express"); var promise = require("bluebird"); // or any other Promise/A+ compatible library; var _ = require("lodash"); var pgp = require("pg-promise")({promiseLib: promise}); // overriding the default (ES6 Promise); var db = pgp("postgres://wikilibras:wikilibras123@localhost:5432/wikilibras"); var parameters = require("../helpers/parameters"); var async = require("async"); var files = require("../helpers/files.js"); var fs = require('fs'); var path = require("path"); var util = require("util"); var mkdirp = require("mkdirp"); var multer = require("multer"); var upload = multer({dest: "uploads/"}); var users = path.join(__dirname, "../public/users"); var sys = require("util"); var exec = require("child_process").exec; var child = null; var router = express.Router(); // GET home page router.get("/", function(req, res, next) { res.render("index" , { title: "Wikilibras-DB API", version: "1.0.0" }); }); router.get("/countvideo", function(req, res, next) { var response = {}; db.query('SELECT COUNT(*) FROM sinal;') .then(function(result) { // response.status = true; // response.message = ""; // response.data = result; // TODO uncomment lines above, remove the line below and response = [parseInt(result[0].count)]; res.status(203); }) .catch(function(error) { response.status = false; response.message = ""; response.data = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); router.get("/listselos", function(req, res, next) { var response = {}; db.query('SELECT "nomeSelo", "idSelo" FROM "tipoSelo";') .then(function(result) { // response.status = true; // response.data = result; response = result; res.status(203); }) .catch(function(error) { response.status = false; response.error = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); router.get("/countuservideos", function(req, res, next) { var response = {}; var limit = 10; if (!_.isEmpty(req.query.limit)) { var _limit = parseInt(req.query.limit); if ((0 <= _limit) && (_limit <= 1000)) { limit = _limit; } } var query = 'SELECT DISTINCT' + ' usuario as username,' + ' "idUsuario" as email,' + ' CAST(COUNT(*) as INTEGER) as videos' + ' FROM sinal' + ' GROUP BY usuario, "idUsuario"' + ' ORDER BY videos DESC, usuario' + ' LIMIT ' + limit + ';'; db.query(query) .then(function(result) { // response.status = true; // response.data = result; response = result; res.status(203); }) .catch(function(error) { response.status = false; response.error = error; console.log(error); res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); router.get("/listall", function(req, res, next) { var response = {}; // db.query('SELECT s."nome", s."data", s.cidade, s.estado, s.file, s.avatar, s.blender, ts."nomeSelo", s."version" FROM "sinal" s, "tipoSelo" ts WHERE s."idSelo" = ts."idSelo"') db.query('SELECT s."data", s."usuario", s."idSinal", s.idtask, s."idSelo", ts."nomeSelo", s."version", s."nome", s."classe", s."frase", s."estado", s."cidade", s."file", s."avatar", s."blender" FROM "sinal" s INNER JOIN "tipoSelo" ts ON (s."idSelo" = ts."idSelo")') .then(function(result) { response = result; res.status(203); }) .catch(function(error) { response = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); /** * Atualiza o campo selo com base no idSinal ou idTask */ router.put("/updateselo", function(req, res, next) { var response = {}; var idTask = req.body["idtask"]; var idSinal = req.body["idsinal"]; var selo = req.body["selo"]; console.log(JSON.stringify(req.body, null, 4)); var query = ""; if (_.isEmpty(selo)) { res.status(500); response.status = false; response.error = "O campo 'selo' é obrigatório"; return res.send(response); } else { query += 'UPDATE "sinal" SET "idSelo" = ' + parseInt(selo) + ' WHERE '; } if (_.isEmpty(idTask) && _.isEmpty(idSinal)) { res.status(500); response.status = false; response.error = "O campo 'idtask' ou 'idsinal' está ausente"; return res.send(response); } if (!_.isEmpty(idTask)) { query += 'idtask = ' + parseInt(idTask); } if (!_.isEmpty(idTask) && !_.isEmpty(idSinal)) { query += " AND "; } if (!_.isEmpty(idSinal)) { query += '"idSinal" = ' + parseInt(idSinal); } query += ' RETURNING "nome", "idSinal", idtask, "idSelo";'; db.query(query) .then(function(result) { if (Object.keys(result).length > 0) { response.status = true; } else { response.status = false; } response.data = result; res.status(200); }) .catch(function(error) { response.status = false; response.error = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); /** * Atualiza o campo 'idtask' com base no idSinal */ router.get("/updatetask", function(req, res, next) { var response = {}; var idTask = req.query["idtask"]; var idSinal = req.query["idsinal"]; if (_.isEmpty(idTask)) { res.status(500); response.status = false; response.error = "O campo 'idtask' é obrigatório"; res.send(response); return; } else { idTask = parseInt(idTask); } if (_.isEmpty(idSinal)) { res.status(500); response.status = false; response.error = "O campo 'idsinal' é obrigatório"; res.send(response); return; } else { idSinal = parseInt(idSinal); } db.query('UPDATE "sinal" SET version = version + 1, idtask = ($1) WHERE "idSinal" = ($2) RETURNING "idSinal", idtask;', [idTask, idSinal]) .then(function(result) { if (Object.keys(result).length > 0) { response.status = true; response.data = result; } else { response.status = false; response.data = "ERROR: 'idSinal' = " + idSinal + " Não encontrado"; } res.status(200); }) .catch(function(error) { response.status = false; response.error = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); /** * Retorna lista de sinais inseridos pelo formulário e * os que que tiveram o selo alterado */ router.get("/newtasks", function(req, res, next) { var response = {}; var selo = req.query["selo"]; var query = 'SELECT s."idSinal", s."nome", s."idSelo", ts."nomeSelo", s."usuario", s."estado", s."classe", s."file", s."avatar", s."blender" FROM "sinal" s INNER JOIN "tipoSelo" ts ON (s."idSelo" = ts."idSelo") WHERE s."version" = 0 '; if (!_.isEmpty(selo)) { query += ' AND s."idSelo" = ' + parseInt(selo); } query += ';'; db.query(query) .then(function(result) { response.status = true; response.count = result.length; response.data = result; res.status(200); }) .catch(function(error) { response.status = false; response.error = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); }); }); /* // only for test router.get("/populate", function(req, res, next) { var response = {}; exec("sudo su postgres -c 'psql --set ON_ERROR_STOP=off -f ../wikilibras-db-api-dump.sql wikilibras'", function(error, stdout, stderr) { if (error) { response.status = false; response.message = "Error while populate"; console.log(stdout); res.status = 500; } else if (stderr.length > 0) { response.status = false; response.message = "The Database already been populated"; console.log(stderr); res.status = 304; } else { response.status = true; response.message = "The Database has been populated"; res.status = 201; } res.send(response); }); }); */ router.get("/reset", function(req, res, next) { var response = {}; db.query('TRUNCATE TABLE sinal, selo; ALTER SEQUENCE sequence RESTART WITH 1;') .then(function(result) { response.status = true; response.message = "The database has been truncated"; res.status(203); }) .catch(function(error) { response.status = false; response.message = "The database cannot be truncated"; response.error = error; res.status(500); }) .finally(function() { res.send(response); pgp.end(); // console.log(JSON.stringify(response, null, 4)); }); }); router.get("/resettasks", function(req, res, next) { const pg = require("pg"); const connectionString = "postgres://pybossa:tester@localhost:5432/pybossa"; const results = []; const data = { text: req.body.text, complete: false }; pg.connect(connectionString, function(err, client, done) { if (err) { done(); console.log(err); return res.status(500).json({ success: false, data: err }); } const query = client.query('TRUNCATE "task" CASCADE; ALTER SEQUENCE task_id_seq RESTART WITH 1'); query.on('row', function(row) { results.push(row); }); query.on('end', function() { done(); return res.json({ success: true, data: results }); }); }); }); router.get("/version", function(req, res, next) { var response = []; db.query('SELECT MAX(version) FROM sinal;') .then(function(result) { response = { "version": result[0].max }; }) .catch(function(error) { response = error; }) .finally(function() { pgp.end(); res.status(200).send(response); }); }); router.get("/sinais", function(req, res, next) { var results = []; if ((!_.isEmpty(req.query("selo"))) && (!_.isEmpty(req.query("version")))) { db.query('SELECT s."nome", s."data", s.cidade, s."version", s.estado, s.file, s.avatar, s.blender, ts."nomeSelo" FROM "sinal" s, "tipoSelo" ts WHERE s."idSelo" = ts."idSelo" AND ts."nomeSelo" = $1 AND s."version" = $2', [req.query("selo"), req.query("version")]) .then(function(result) { res.status(203).send(result); }) .catch(function(error) { // error; }) .finally(function() { pgp.end(); }); } else { if (!_.isEmpty(req.query("version"))) { db.query("select nome, data, file, avatar, blender version FROM sinal WHERE version = $1", req.query("version")) .then(function(result) { res.status(203).send(result); }) .catch(function(error) { // error; }) .finally(function() { pgp.end(); }); } if (!_.isEmpty(req.query("selo"))) { db.query('SELECT s."nome", s."data", s.cidade, s.estado, s.file, s.avatar, s.blender, ts."nomeSelo", s.version FROM "sinal" s, "tipoSelo" ts WHERE s."idSelo" = ts."idSelo" AND ts."nomeSelo" = $1', req.query("selo")) .then(function(result) { res.status(203).send(result); }) .catch(function(error) { // error; }) .finally(function() { pgp.end(); }); } } }); router.post('/gsinal', function(req, res, next) { console.log("\n\n\n============================================="); console.log("[" + new Date().toISOString() + "] Requisição do IP: " + req.ip); console.log("== Parametros: " + util.inspect(req.body)); console.log("== Body: " + JSON.stringify(req.headers)); db.query('UPDATE sinal SET "idSelo" = ($1), version = version + 1 WHERE nome = ($2)', [req.body.selo, req.body.nome]) .then(function(data) { res.status(203).send('Sinal ' + req.body.nome + ' atualizado com sucesso [without archive]'); }) .catch(function(error) { console.log("Erro " + error); }); }); /* router.post('/addsinal', upload.array('video', 2), function(req, res, next) { console.log("\n\n\n============================================="); console.log("[" + new Date().toISOString() + "]"); console.log("From: " + req.ip); // console.log("Files: " + req.files[0]); // console.log("headers: " + JSON.stringify(req.headers)); console.log("body: " + JSON.stringify(req.body)); if (req.method === "OPTIONS") { res.header('Access-Control-Allow-Origin', req.headers.origin); } else { res.header('Access-Control-Allow-Origin', '*'); } if (_.isEmpty(req.body.nome)) { res.send(500, 'O valor do parâmetro nome está vazio'); return; } async.series([ function(callback) { console.log("\t >> ORDEM 1"); if (_.isEmpty(req.body.wikilibras)) { console.log("Movendo arquivo para conversão..."); files.downloadAndMoveVideo(req, 'sinais', callback); } else { files.downloadAndMoveVideo(req, 'wikilibras', callback); } }, function(callback) { console.log("\t >> ORDEM 2"); if (_.isEmpty(req.body.wikilibras)) { console.log("Convertendo para .webm..."); child = exec('avconv -v error -i uploads/' + req.files[0].originalname + ' -acodec libvorbis -vcodec libvpx -an sinais/' + req.files[0].originalname.slice(0, -4) + '.webm -y', function(error, stdout, stderr) { console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); if (error !== null) { console.log('exec error: ' + error); } }); child.on('exit', function() { setTimeout(function() { console.log("Conversão para webm concluída."); callback(null, 1); }, 500); }); } else { callback(); } }, function(callback) { console.log("== Alterando o db"); db.query('SELECT "idSelo" FROM "sinal" WHERE nome = $1', req.body.nome) .then(function(result) { var d = new Date(); if (Object.keys(result).length > 0) { if (!_.isEmpty(req.body.overwrite)) { if (!_.isEmpty(req.body.wikilibras)) { db.query('UPDATE sinal SET avatar = ($1), blender = ($2) WHERE nome = ($3)', [req.files[0].originalname, req.files[1].originalname, req.body.nome]) .then(function(data) { res.send(200, 'Sinal ' + req.body.nome + ' atualizado com sucesso [with avatar/blender].'); }) .catch(function(error) { console.log("Erro " + error); }); } if (!_.isEmpty(req.files)) { db.query('UPDATE sinal SET "idSelo" = ($1), version = version + 1, file = ($2) WHERE nome = ($3)', [req.body.selo, req.files[0].originalname, req.body.nome]) .then(function(data) { res.status(200).send('Sinal ' + req.body.nome + ' atualizado com sucesso [with archive].'); }) .catch(function(error) { console.log("Erro " + error); }); } else { db.query('UPDATE sinal SET "idSelo" = ($1) WHERE nome = ($2)', [req.body.selo, req.body.nome]) .then(function(data) { res.status(200).send('Sinal ' + req.body.nome + ' atualizado com sucesso [without archive].'); }) .catch(function(error) { console.log("Erro " + error); }); } } else { res.status(500).send('Sinal já cadastrado no sistema'); } } else { if (_.isEmpty(req.body.selo)) { req.body.selo = 7; } db.one('insert into sinal (usuario, nome, "idSelo", data, version, estado, cidade, file) values ($1, $2, $3, $4, $5, $6, $7, $8) returning "idSinal"', [req.body.login, req.body.nome, req.body.selo, d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate(), 1, req.body.estado, req.body.cidade, req.files[0].originalname.slice(0, -4) + '.webm']) .then(function(data) { res.status(200).send('Sinal ' + req.body.nome + ' adicionado com sucesso.'); }) .catch(function(error) { console.log("Erro " + error); }); } }) .catch(function(error) { console.log(error); }) .finally(function() { pgp.end(); }); } , ], function(err) { if (err) { res.send(500, "Error"); return; } }); }); */ router.post('/updatesinal', upload.array('video', 2), function(req, res, next) { // console.log("[" + new Date().toISOString() + "]"); // console.log("From: " + req.ip); // console.log("Files: " + JSON.stringify(req.files[0], null, 4)); // console.log("headers: " + JSON.stringify(req.headers, null, 4)); // console.log("body: " + JSON.stringify(req.body, null, 4)); if (req.method === "OPTIONS") { res.header('Access-Control-Allow-Origin', req.headers.origin); } else { res.header('Access-Control-Allow-Origin', '*'); } if (req.files.length < 2) { return res.status(500).send("ERROR: O campo 'video' deve conter dois arquivos (video, blend)"); } var response = {}; var directory = users; var nome = req.body["nome"]; var selo = req.body["selo"]; var idTask = req.body["idtask"]; var blend = req.files[1]; var video = req.files[0]; var maxblendsize = 25; // MB var maxvideosize = 25; // MB if (_.isEmpty(nome) || _.isEmpty(idTask)) { response.status = false; response.error = "Os campos 'nome' e 'idtask' são obrigatórios"; return res.status(500).send(response); } else { nome = nome.trim().toUpperCase(); } if (video.size > (maxvideosize * 1048576)) { response.status = false; response.error = "O tamanho do video deve ter no máximo " + maxvideosize + " MB"; return res.status(500).send(response); } if (blend.size > (maxblendsize * 1048576)) { response.status = false; response.error = "O tamanho do blend deve ter no máximo " + maxblendsize + " MB"; return res.status(500).send(response); } if (_.isEmpty(selo) || 1 < selo || selo > 7) { selo = 1; } db.query('SELECT "idSinal", usuario, estado, classe FROM "sinal" WHERE nome = ($1) AND idtask = ($2)', [nome, idTask]) .then(function(result) { if (Object.keys(result).length > 0) { var idSinal = result[0]["idSinal"]; var login = result[0]["usuario"]; var estado = result[0]["estado"]; var classe = result[0]["classe"]; var videoname = nome + ".webm"; var blendname = nome + ".blend"; if (login !== null) { directory = path.join(directory, login); } if (estado !== null) { directory = path.join(directory, estado); } if (classe !== null) { directory = path.join(directory, classe); } if (!fs.existsSync(directory)) { console.log("Criando diretorio: " + directory); mkdirp(directory, function (err) { if (err) { console.error(err); res.status(500).send(err); return; } else { console.log("Diretório criado com sucesso!"); } }); } db.query('UPDATE sinal SET "idSelo" = ($1), version = ($2), avatar = ($3), blender = ($4) WHERE "idSinal" = ($5)', [selo, 0, videoname, blendname, idSinal]) .then(function(data) { videopath = path.join(directory, videoname); blendpath = path.join(directory, blendname); fs.rename(video.path, videopath); fs.rename(blend.path, blendpath); var message = "Sinal atualizado: '" + nome + "'"; console.log(message); res.status(200).send(message); }) .catch(function(error) { var message = "Erro ao atualizar sinal '" + nome + "'\n" + error; console.log(message); res.status(500).send(message); }); } else { var message = "Não foi encontrado nenhum 'idtask' = '" + idTask + "' com sinal = " + nome; res.status(500).send(message); } }) .catch(function(error) { console.log(error); }) .finally(function() { pgp.end(); }); }); router.post('/addsinal', upload.array('video', 2), function(req, res, next) { // console.log("[" + new Date().toISOString() + "]"); // console.log("From: " + req.ip); // console.log("Files: " + JSON.stringify(req.files[0], null, 4)); // console.log("headers: " + JSON.stringify(req.headers, null, 4)); // console.log("body: " + JSON.stringify(req.body, null, 4)); if (req.method === "OPTIONS") { res.header('Access-Control-Allow-Origin', req.headers.origin); } else { res.header('Access-Control-Allow-Origin', '*'); } if (req.files.length < 1) { return res.status(500).send("ERROR: O campo 'video' não contém nenhum arquivo do sinal"); } var directory = users; var login = req.body["login"]; var estado = req.body["estado"]; var classe = req.body["classe-gramatical"]; var nome = req.body["nome"]; var cidade = req.body["cidade"]; var frase = req.body["frases"]; var selo = req.body["selo"]; var filesize = req.files[0].size; var input = req.files[0].path; var videoref = ""; var output = ""; var maxfilesize = 25; // MB if (filesize > (maxfilesize * 1048576)) { return res.status(500).send("O tamanho do arquivo deve ter no máximo " + maxfilesize + " MB"); } if (_.isEmpty(nome)) { return res.status(500).send("ERROR: O campo 'nome' não foi encontrado"); } else { nome = nome.trim().toUpperCase(); videoref = nome + "_REF.webm"; } if (_.isEmpty(selo)) { selo = 7; } if (_.isEmpty(login)) { console.log("WARNING: O campo 'login' não foi encontrado"); } else { directory = path.join(directory, login); } if (_.isEmpty(estado)) { console.log("WARNING: O campo 'estado' não foi encontrado"); } else { directory = path.join(directory, estado); } if (_.isEmpty(classe)) { console.log("WARNING: O campo 'classe' não foi encontrado"); } else { directory = path.join(directory, classe); } output = path.join(directory, videoref); async.series([ function (callback) { if (fs.existsSync(directory)) { callback(null, 1); } else { console.log("Criando diretorio: " + directory); mkdirp(directory, function (err) { if (err) { console.error(err); return res.status(500).send(err); } else { console.log("Diretório criado com sucesso!"); callback(null, 1); } }); } }, // Converter para formato webm function(callback) { console.log("Convertendo sinal '" + nome + "' para webm..."); child = exec("avconv -y -v error -i \"" + input + "\" -acodec libvorbis -vcodec libvpx -an \"" + output + "\"", function(error, stdout, stderr) { if (error || (stderr.length > 0)) { var log = "O arquivo de vídeo é inválido, ou ocorreu um erro durante a conversão\nDetalhes: " + stdout + stderr; log = log.trim(); res.status(500); callback(true, log); } else { res.status(200); return 0; } }); child.on("exit", function(code) { setTimeout(function() { if (code === 0) { console.log("Conversão concluída"); callback(null, 1); } else { callback(true, new Error("Erro durante conversão")); } }, 500); }); }, function(callback) { console.log("Verificando se este sinal já existe"); db.query('SELECT "idSinal" FROM "sinal" WHERE usuario = ($1) AND estado = ($2) AND classe = ($3) AND nome = ($4)', [login, estado, classe, nome]) .then(function(result) { var d = new Date(); var date = d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate(); if (Object.keys(result).length > 0) { var idSinal = result[0].idSinal; console.log("Existe, atualizando o sinal[" + idSinal + "]: '" + nome + "'"); db.query('UPDATE sinal SET "idSelo" = ($1), version = ($2), data = ($3), cidade = ($4), frase = ($5), file = ($6) WHERE "idSinal" = ($7)', [7, 0, date, cidade, frase, videoref, idSinal]) .then(function(data) { res.status(200).send("Sinal atualizado"); }) .catch(function(error) { var message = "Erro ao atualizar sinal '" + nome + "'\n" + error; console.log(message); res.status(500).send(message); }); } else { console.log("Não existe, inserindo sinal: '" + nome + "'"); db.one('INSERT INTO sinal (usuario, nome, classe, "idSelo", data, version, estado, cidade, frase, file) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "idSinal"', [login, nome, classe, selo, date, 0, estado, cidade, frase, videoref]) .then(function(data) { var message = "Sinal[" + data.idSinal + "]: '" + nome + "', inserido com sucesso!"; console.log(message); res.status(200).send(message); }) .catch(function(error) { res.status(500).send(error); }); } }) .catch(function(error) { console.log(error); }) .finally(function() { pgp.end(); }); } ], function(err, results) { if (err) { console.log(results[0]); } }); }); module.exports = router;