Commit bf34bf1e43a19651d5d75d9177066a161fa73338
1 parent
feb33337
Exists in
master
First code
Showing
17 changed files
with
1387 additions
and
1 deletions
Show diff stats
@@ -0,0 +1,71 @@ | @@ -0,0 +1,71 @@ | ||
1 | +SCRIPT_NAME := wikilibras-db-api | ||
2 | +SCRIPT_PATH := $(CURDIR)/${SCRIPT_NAME} | ||
3 | +SCRIPT_PATH_TMP := /tmp/${SCRIPT_NAME} | ||
4 | +SCRIPT_PATH_ETC := /etc/init.d/${SCRIPT_NAME} | ||
5 | +NPM := $(shell which npm) | ||
6 | + | ||
7 | +install: | ||
8 | + @ npm install | ||
9 | + @ sudo npm install -g supervisor | ||
10 | + | ||
11 | +autostart-enable: | ||
12 | + @ install -m 777 -p ${SCRIPT_PATH} ${SCRIPT_PATH_TMP} | ||
13 | + @ sed -i "s#<CURDIR>#$(CURDIR)#" ${SCRIPT_PATH_TMP} | ||
14 | + @ sed -i "s#<SCRIPT_NAME>#${SCRIPT_NAME}#" ${SCRIPT_PATH_TMP} | ||
15 | + @ sed -i "s#<NPM>#${NPM}#" ${SCRIPT_PATH_TMP} | ||
16 | + @ sudo install -m 755 -p ${SCRIPT_PATH_TMP} ${SCRIPT_PATH_ETC} | ||
17 | + @ sudo update-rc.d -f ${SCRIPT_NAME} remove | ||
18 | + @ sudo update-rc.d -f ${SCRIPT_NAME} defaults | ||
19 | + | ||
20 | +autostart-disable: | ||
21 | + @ sudo update-rc.d -f ${SCRIPT_NAME} remove | ||
22 | + @ sudo rm -f ${SCRIPT_PATH_ETC} | ||
23 | + | ||
24 | +clean: | ||
25 | + @ sudo chmod -R 777 ./public/users/ ./uploads/ | ||
26 | + @ find ./public/users/ -type d -empty -delete | ||
27 | + | ||
28 | +distclean: | ||
29 | + @ sudo rm -rf ./public/users/ ./uploads/ | ||
30 | + | ||
31 | +run: | ||
32 | + @ sudo ${NPM} start | ||
33 | + | ||
34 | +unistall: distclean | ||
35 | + @ rm -rf ./node_modules/ | ||
36 | + | ||
37 | +ROLENAME := wikilibras | ||
38 | +DATABASE := wikilibras | ||
39 | +PASSWORD := wikilibras123 | ||
40 | +DBFILEIN := wikilibras-db-api.sql | ||
41 | +DBOUTBAK := wikilibras-db-api-dump.sql | ||
42 | +VERBOSE := #-v | ||
43 | + | ||
44 | +create-db: .create-role .create-db .restore-db | ||
45 | +drop-db: .restart-db .drop-db .drop-role | ||
46 | + | ||
47 | +dump-db: | ||
48 | + @ sudo su postgres -c "PGPASSWORD='${PASSWORD}' pg_dump ${VERBOSE} -b --inserts ${ROLENAME};" > ${DBOUTBAK} | ||
49 | + | ||
50 | +.create-db: | ||
51 | + @ sudo su postgres -c "psql -c \"CREATE DATABASE ${DATABASE} OWNER ${ROLENAME};\"" | ||
52 | + | ||
53 | +.create-role: | ||
54 | + @ sudo su postgres -c "psql -c \"CREATE USER ${ROLENAME} WITH PASSWORD '${PASSWORD}';\"" | ||
55 | + | ||
56 | +.drop-db: | ||
57 | + @ sudo su postgres -c "psql -c \"DROP DATABASE ${DATABASE};\"" | ||
58 | + | ||
59 | +.drop-role: | ||
60 | + @ sudo su postgres -c "psql -c \"DROP USER ${ROLENAME};\"" | ||
61 | + | ||
62 | +populate-db: | ||
63 | + @ sudo su postgres -c "psql --set ON_ERROR_STOP=off -f ${DBOUTBAK} ${ROLENAME}" | ||
64 | + | ||
65 | +.restart-db: | ||
66 | + @ sudo service postgresql restart | ||
67 | + | ||
68 | +.restore-db: | ||
69 | + @ sudo su postgres -c "psql --set ON_ERROR_STOP=off -f ${DBFILEIN} ${ROLENAME}" | ||
70 | + | ||
71 | +.PHONY: autostart-enable autostart-disable clean distclean install run uninstall | ||
0 | \ No newline at end of file | 72 | \ No newline at end of file |
@@ -0,0 +1,94 @@ | @@ -0,0 +1,94 @@ | ||
1 | +var _ = require("lodash"); | ||
2 | +var async = require("async"); | ||
3 | +var bodyParser = require("body-parser"); | ||
4 | +var cookieParser = require("cookie-parser"); | ||
5 | +var express = require("express"); | ||
6 | +var favicon = require("serve-favicon"); | ||
7 | +var http = require("http"); | ||
8 | +var logger = require("morgan"); | ||
9 | +var multer = require("multer"); | ||
10 | +var path = require("path"); | ||
11 | +var util = require("util"); | ||
12 | +var files = require(path.join(__dirname, "helpers/files")); | ||
13 | +var routes = require(path.join(__dirname, "routes/index")); | ||
14 | +var users = require(path.join(__dirname, "routes/users")); | ||
15 | +var app = express(); | ||
16 | +var server = http.createServer(app); | ||
17 | + | ||
18 | +var upload = multer( | ||
19 | +{ | ||
20 | + dest: "uploads/" | ||
21 | +}); | ||
22 | + | ||
23 | +server.maxConnections = 5000; | ||
24 | + | ||
25 | +// static path | ||
26 | +app.use("/sinais", express.static(path.join(__dirname, "sinais"))); | ||
27 | +app.use("/avatar", express.static(path.join(__dirname, "avatar"))); | ||
28 | +app.use("/blender", express.static(path.join(__dirname, "blender"))); | ||
29 | +app.use("/public", express.static(path.join(__dirname, "public"))); | ||
30 | + | ||
31 | +// view engine setup | ||
32 | +app.set("views", path.join(__dirname, "views")); | ||
33 | +app.set("view engine", "pug"); | ||
34 | + | ||
35 | +// uncomment after placing your favicon in /public | ||
36 | +app.use(favicon(path.join(__dirname, "public", "img", "favicon.ico"))); | ||
37 | +app.use(logger("dev")); | ||
38 | +app.use(bodyParser.json({limit: "50mb"})); | ||
39 | +app.use(bodyParser.urlencoded( | ||
40 | +{ | ||
41 | + extended: true | ||
42 | +})); | ||
43 | + | ||
44 | +app.use(cookieParser()); | ||
45 | +app.use(function(req, res, next) | ||
46 | +{ | ||
47 | + res.header("Access-Control-Allow-Origin", "*"); | ||
48 | + res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE"); | ||
49 | + res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); | ||
50 | + next(); | ||
51 | +}); | ||
52 | + | ||
53 | +app.use("/", routes); | ||
54 | +app.use("/users", users); | ||
55 | + | ||
56 | +// catch 404 and forward to error handler | ||
57 | +app.use(function(req, res, next) | ||
58 | +{ | ||
59 | + var err = new Error("Not Found"); | ||
60 | + err.status = 404; | ||
61 | + next(err); | ||
62 | +}); | ||
63 | + | ||
64 | +// error handlers | ||
65 | + | ||
66 | +// development error handler | ||
67 | +// will print stacktrace | ||
68 | +if (app.get("env") === "development") | ||
69 | +{ | ||
70 | + app.use(function(err, req, res, next) | ||
71 | + { | ||
72 | + res.status(err.status || 500); | ||
73 | + res.render("error" | ||
74 | + , { | ||
75 | + message: err.message | ||
76 | + , error: err | ||
77 | + }); | ||
78 | + }); | ||
79 | +} | ||
80 | + | ||
81 | +// production error handler | ||
82 | +// no stacktraces leaked to user | ||
83 | +app.use(function(err, req, res, next) | ||
84 | +{ | ||
85 | + res.status(err.status || 500); | ||
86 | + res.render("error" | ||
87 | + , { | ||
88 | + message: err.message | ||
89 | + , error: | ||
90 | + {} | ||
91 | + }); | ||
92 | +}); | ||
93 | + | ||
94 | +module.exports = app; |
@@ -0,0 +1,90 @@ | @@ -0,0 +1,90 @@ | ||
1 | +#!/usr/bin/env node | ||
2 | + | ||
3 | +/** | ||
4 | + * Module dependencies. | ||
5 | + */ | ||
6 | + | ||
7 | +var app = require('../app'); | ||
8 | +var debug = require('debug')('wikilibrasdbapi:server'); | ||
9 | +var http = require('http'); | ||
10 | + | ||
11 | +/** | ||
12 | + * Get port from environment and store in Express. | ||
13 | + */ | ||
14 | + | ||
15 | +var port = normalizePort(process.env.PORT || '200'); | ||
16 | +app.set('port', port); | ||
17 | + | ||
18 | +/** | ||
19 | + * Create HTTP server. | ||
20 | + */ | ||
21 | + | ||
22 | +var server = http.createServer(app); | ||
23 | + | ||
24 | +/** | ||
25 | + * Listen on provided port, on all network interfaces. | ||
26 | + */ | ||
27 | + | ||
28 | +server.listen(port); | ||
29 | +server.on('error', onError); | ||
30 | +server.on('listening', onListening); | ||
31 | + | ||
32 | +/** | ||
33 | + * Normalize a port into a number, string, or false. | ||
34 | + */ | ||
35 | + | ||
36 | +function normalizePort(val) { | ||
37 | + var port = parseInt(val, 10); | ||
38 | + | ||
39 | + if (isNaN(port)) { | ||
40 | + // named pipe | ||
41 | + return val; | ||
42 | + } | ||
43 | + | ||
44 | + if (port >= 0) { | ||
45 | + // port number | ||
46 | + return port; | ||
47 | + } | ||
48 | + | ||
49 | + return false; | ||
50 | +} | ||
51 | + | ||
52 | +/** | ||
53 | + * Event listener for HTTP server "error" event. | ||
54 | + */ | ||
55 | + | ||
56 | +function onError(error) { | ||
57 | + if (error.syscall !== 'listen') { | ||
58 | + throw error; | ||
59 | + } | ||
60 | + | ||
61 | + var bind = typeof port === 'string' | ||
62 | + ? 'Pipe ' + port | ||
63 | + : 'Port ' + port; | ||
64 | + | ||
65 | + // handle specific listen errors with friendly messages | ||
66 | + switch (error.code) { | ||
67 | + case 'EACCES': | ||
68 | + console.error(bind + ' requires elevated privileges'); | ||
69 | + process.exit(1); | ||
70 | + break; | ||
71 | + case 'EADDRINUSE': | ||
72 | + console.error(bind + ' is already in use'); | ||
73 | + process.exit(1); | ||
74 | + break; | ||
75 | + default: | ||
76 | + throw error; | ||
77 | + } | ||
78 | +} | ||
79 | + | ||
80 | +/** | ||
81 | + * Event listener for HTTP server "listening" event. | ||
82 | + */ | ||
83 | + | ||
84 | +function onListening() { | ||
85 | + var addr = server.address(); | ||
86 | + var bind = typeof addr === 'string' | ||
87 | + ? 'pipe ' + addr | ||
88 | + : 'port ' + addr.port; | ||
89 | + debug('Listening on ' + bind); | ||
90 | +} |
@@ -0,0 +1,104 @@ | @@ -0,0 +1,104 @@ | ||
1 | +var parameters = require('../helpers/parameters'); | ||
2 | +var http = require('http'); | ||
3 | +var fs = require('fs'); | ||
4 | +var _ = require('lodash'); | ||
5 | + | ||
6 | +/* | ||
7 | +* Função que processa o vídeo (seja baixando, seja pegando o vídeo enviado) | ||
8 | +* Deve retornar um objeto contendo o nome e o caminho | ||
9 | +*/ | ||
10 | +function downloadAndMoveVideo(req, folder, callback) | ||
11 | +{ | ||
12 | + console.log(req.files[0].path + " " + req.files[0].originalname); | ||
13 | + // Se enviou o arquivo na requisição | ||
14 | + if (req.files[0].fieldname !== undefined) | ||
15 | + { | ||
16 | + // Se a validação falhar | ||
17 | + if (parameters.checkVideo(req.files[0].originalname) === false) | ||
18 | + { | ||
19 | + var error = 'Vídeo enviado com extensão inválida'; | ||
20 | + return callback(error); | ||
21 | + } | ||
22 | + /* Move o vídeo submetido para a pasta com o seu ID correspondente */ | ||
23 | + try | ||
24 | + { | ||
25 | + if (!_.isEmpty(req.body.wikilibras)) | ||
26 | + { | ||
27 | + fs.renameSync(req.files[0].path, 'avatar/' + req.files[0].originalname); | ||
28 | + fs.renameSync(req.files[1].path, 'blender/' + req.files[1].originalname); | ||
29 | + } | ||
30 | + else | ||
31 | + { | ||
32 | + fs.renameSync(req.files[0].path, 'uploads/' + req.files[0].originalname); | ||
33 | + } | ||
34 | + } | ||
35 | + catch (err) | ||
36 | + { | ||
37 | + console.log("Erro ao mover o vídeo submetido: " + err); | ||
38 | + callback("Erro ao mover o vídeo submetido: " + err); | ||
39 | + } | ||
40 | + return callback(); | ||
41 | + } // Se o arquivo não foi enviado, mas um video_url foi | ||
42 | + else if (req.body.video_url !== undefined) | ||
43 | + { | ||
44 | + // Requisição para baixar o vídeo | ||
45 | + http.get(req.body.video_url, function(response) | ||
46 | + { | ||
47 | + | ||
48 | + // Se o vídeo não foi baixado com sucesso | ||
49 | + if (response.statusCode !== 200) | ||
50 | + { | ||
51 | + var error = 'Problema ao carregar video_url: status ' + response.statusCode; | ||
52 | + return callback(error); | ||
53 | + } | ||
54 | + | ||
55 | + // Nome do arquivo | ||
56 | + var filename = req.body.video_url.substring(req.body.video_url.lastIndexOf('/') + 1); | ||
57 | + | ||
58 | + // Tira os parâmetros HTTP | ||
59 | + if (filename.lastIndexOf("?") !== -1) | ||
60 | + { | ||
61 | + filename = filename.substring(0, filename.lastIndexOf("?")); | ||
62 | + } | ||
63 | + | ||
64 | + var path = folder + '/' + filename; | ||
65 | + | ||
66 | + // Cria o stream para escrita | ||
67 | + var file = fs.createWriteStream(path); | ||
68 | + | ||
69 | + // Salva o arquivo em disco | ||
70 | + response.pipe(file); | ||
71 | + | ||
72 | + // Quando a escrita acabar | ||
73 | + file.on('finish', function() | ||
74 | + { | ||
75 | + // Fecha o arquivo | ||
76 | + file.close(function() | ||
77 | + { | ||
78 | + | ||
79 | + // Retorna o vídeo baixado | ||
80 | + locals.video = { | ||
81 | + 'path': path | ||
82 | + }; | ||
83 | + | ||
84 | + // Chama o callback para prosseguir execução | ||
85 | + callback(); | ||
86 | + }); | ||
87 | + }); | ||
88 | + | ||
89 | + // Se deu erro na requisição de baixar o vídeo | ||
90 | + }).on('error', function(e) { | ||
91 | + var error = 'Problema ao carregar video_url: ' + e.message; | ||
92 | + return callback(error); | ||
93 | + }); | ||
94 | + | ||
95 | + // Se nem o vídeo foi enviado e nem o video_url foi preenchido | ||
96 | + } | ||
97 | + else | ||
98 | + { | ||
99 | + var error = "Video deve ser enviado como parâmetro 'video' ou como 'video_url'"; | ||
100 | + return callback(error); | ||
101 | + } | ||
102 | +} | ||
103 | + | ||
104 | +module.exports.downloadAndMoveVideo = downloadAndMoveVideo; |
@@ -0,0 +1,182 @@ | @@ -0,0 +1,182 @@ | ||
1 | +function getServiceType(service_type) | ||
2 | +{ | ||
3 | + switch(service_type) | ||
4 | + { | ||
5 | + case 'video-legenda': return 2; break; | ||
6 | + case 'video': return 3; break; | ||
7 | + case 'texto': return 4; break; | ||
8 | + case 'ios': return 4; break; | ||
9 | + case 'legenda': return 5; break; | ||
10 | + case 'audio': return 6; break; | ||
11 | + } | ||
12 | +}; | ||
13 | + | ||
14 | +function getLanguage(language) | ||
15 | +{ | ||
16 | + switch(language) | ||
17 | + { | ||
18 | + case 'portugues': return 'portugues'; break; | ||
19 | + case 'glosa': return 'glosa'; break; | ||
20 | + } | ||
21 | +}; | ||
22 | + | ||
23 | +function getPosition(position) | ||
24 | +{ | ||
25 | + switch(position) | ||
26 | + { | ||
27 | + case 'superior-esquerdo': return 'top_left'; break; | ||
28 | + case 'superior-direito': return 'top_right'; break; | ||
29 | + case 'inferior-direito': return 'bottom_right'; break; | ||
30 | + case 'inferior-esquerdo': return 'bottom_left'; break; | ||
31 | + } | ||
32 | +}; | ||
33 | + | ||
34 | +function getSize(size) | ||
35 | +{ | ||
36 | + switch(size) | ||
37 | + { | ||
38 | + case 'pequeno': return 1; break; | ||
39 | + case 'medio': return 2; break; | ||
40 | + case 'grande': return 3; break; | ||
41 | + } | ||
42 | +}; | ||
43 | + | ||
44 | +function getTransparency(transparency) | ||
45 | +{ | ||
46 | + switch(transparency) | ||
47 | + { | ||
48 | + case 'opaco': return 'opaque'; break; | ||
49 | + case 'transparente': return 'transp'; break; | ||
50 | + } | ||
51 | +}; | ||
52 | + | ||
53 | +function getSize(size) | ||
54 | +{ | ||
55 | + switch(size) | ||
56 | + { | ||
57 | + case 'pequeno': return 'small'; break; | ||
58 | + case 'medio': return 'medium'; break; | ||
59 | + case 'grande': return 'large'; break; | ||
60 | + } | ||
61 | +}; | ||
62 | + | ||
63 | +function checkServiceType(service_type) | ||
64 | +{ | ||
65 | + var t_types = ['video', 'texto']; | ||
66 | + for (var i = 0; i < t_types.length; i++) | ||
67 | + { | ||
68 | + if (service_type === t_types[i]) | ||
69 | + { | ||
70 | + return true; | ||
71 | + } | ||
72 | + } | ||
73 | + return false; | ||
74 | +}; | ||
75 | + | ||
76 | +function checkLanguage(language) | ||
77 | +{ | ||
78 | + var t_types = ['portugues', 'glosa']; | ||
79 | + for (var i = 0; i < t_types.length; i++) | ||
80 | + { | ||
81 | + if (language === t_types[i]) | ||
82 | + { | ||
83 | + return true; | ||
84 | + } | ||
85 | + } | ||
86 | + return false; | ||
87 | +}; | ||
88 | + | ||
89 | +function checkPosition(position) | ||
90 | +{ | ||
91 | + var t_types = ['superior-esquerdo', 'superior-direito', 'inferior-esquerdo', 'inferior-direito']; | ||
92 | + for (var i = 0; i < t_types.length; i++) | ||
93 | + { | ||
94 | + if (position === t_types[i]) | ||
95 | + { | ||
96 | + return true; | ||
97 | + } | ||
98 | + } | ||
99 | + return false; | ||
100 | +}; | ||
101 | + | ||
102 | +function checkSize(size) | ||
103 | +{ | ||
104 | + var t_types = ['pequeno', 'medio', 'grande']; | ||
105 | + for (var i = 0; i < t_types.length; i++) | ||
106 | + { | ||
107 | + if (size === t_types[i]) | ||
108 | + { | ||
109 | + return true; | ||
110 | + } | ||
111 | + } | ||
112 | + return false; | ||
113 | +}; | ||
114 | + | ||
115 | +function checkTransparency(transparency) | ||
116 | +{ | ||
117 | + var t_types = ['opaco', 'transparente']; | ||
118 | + for (var i = 0; i < t_types.length; i++) | ||
119 | + { | ||
120 | + if (transparency === t_types[i]) | ||
121 | + { | ||
122 | + return true; | ||
123 | + } | ||
124 | + } | ||
125 | + return false; | ||
126 | +}; | ||
127 | + | ||
128 | +function checkVideo(file) { | ||
129 | + var accepted_file_types = ['flv', 'ts', 'avi', 'mp4', 'mov', 'webm', 'wmv', 'mkv', 'srt']; | ||
130 | + return check_type(file, accepted_file_types); | ||
131 | +}; | ||
132 | + | ||
133 | +function checkSubtitle(file) | ||
134 | +{ | ||
135 | + var accepted_file_types = ['srt']; | ||
136 | + return check_type(file, accepted_file_types); | ||
137 | +}; | ||
138 | + | ||
139 | +function checkAudio(file) | ||
140 | +{ | ||
141 | + var accepted_file_types = ['mp3', 'wav', 'aac', 'flac', 'ogg', 'wma']; | ||
142 | + return check_type(file, accepted_file_types); | ||
143 | +}; | ||
144 | + | ||
145 | +function check_type(file, accepted_file_types) | ||
146 | +{ | ||
147 | + var ext = file.substring(file.lastIndexOf('.') + 1).toLowerCase(); | ||
148 | + var isValidFile = false; | ||
149 | + for (var i = 0; i < accepted_file_types.length; i++) | ||
150 | + { | ||
151 | + if (ext == accepted_file_types[i]) | ||
152 | + { | ||
153 | + isValidFile = true; | ||
154 | + break; | ||
155 | + } | ||
156 | + } | ||
157 | + if (!isValidFile) | ||
158 | + { | ||
159 | + file.value = null; | ||
160 | + } | ||
161 | + return isValidFile; | ||
162 | +}; | ||
163 | + | ||
164 | +function errorMessage(message) | ||
165 | +{ | ||
166 | + return JSON.stringify({ 'error': message }) | ||
167 | +}; | ||
168 | + | ||
169 | +module.exports.getServiceType = getServiceType; | ||
170 | +module.exports.getLanguage = getLanguage; | ||
171 | +module.exports.getPosition = getPosition; | ||
172 | +module.exports.getSize = getSize; | ||
173 | +module.exports.getTransparency = getTransparency; | ||
174 | +module.exports.checkServiceType = checkServiceType; | ||
175 | +module.exports.checkLanguage = checkLanguage; | ||
176 | +module.exports.checkPosition = checkPosition; | ||
177 | +module.exports.checkSize = checkSize; | ||
178 | +module.exports.checkTransparency = checkTransparency; | ||
179 | +module.exports.checkVideo = checkVideo; | ||
180 | +module.exports.checkSubtitle = checkSubtitle; | ||
181 | +module.exports.checkAudio = checkAudio; | ||
182 | +module.exports.errorMessage = errorMessage; |
inicial.txt
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -Repositorio wikilibrasdbapi Criado |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +{ | ||
2 | + "name": "Wikilibras-DBAPI", | ||
3 | + "description": "", | ||
4 | + "version": "1.0.0", | ||
5 | + "private": true, | ||
6 | + "scripts": | ||
7 | + { | ||
8 | + "start": "supervisor ./bin/www" | ||
9 | + }, | ||
10 | + "dependencies": | ||
11 | + { | ||
12 | + "bluebird": "~3.4.6", | ||
13 | + "body-parser": "~1.13.2", | ||
14 | + "cookie-parser": "~1.3.5", | ||
15 | + "debug": "~2.2.0", | ||
16 | + "express": "~4.13.1", | ||
17 | + "lodash": "~4.15.0", | ||
18 | + "mkdirp": "~0.5.1", | ||
19 | + "morgan": "~1.6.1", | ||
20 | + "multer": "~1.2.0", | ||
21 | + "pg": "^4.4.6", | ||
22 | + "pg-promise": "~5.3.3", | ||
23 | + "pug": "~2.0.0-beta6", | ||
24 | + "serve-favicon": "~2.3.0" | ||
25 | + } | ||
26 | +} |
No preview for this file type
@@ -0,0 +1,645 @@ | @@ -0,0 +1,645 @@ | ||
1 | +var express = require("express"); | ||
2 | +var promise = require("bluebird"); // or any other Promise/A+ compatible library; | ||
3 | +var _ = require("lodash"); | ||
4 | +var pgp = require("pg-promise")({promiseLib: promise}); // overriding the default (ES6 Promise); | ||
5 | +var db = pgp("postgres://wikilibras:wikilibras123@localhost:5432/wikilibras"); | ||
6 | +var parameters = require("../helpers/parameters"); | ||
7 | +var async = require("async"); | ||
8 | +var files = require("../helpers/files.js"); | ||
9 | +var fs = require('fs'); | ||
10 | +var path = require("path"); | ||
11 | +var util = require("util"); | ||
12 | +var mkdirp = require("mkdirp"); | ||
13 | +var multer = require("multer"); | ||
14 | +var upload = multer({dest: "uploads/"}); | ||
15 | +var users = path.join(__dirname, "../public/users"); | ||
16 | +var sys = require("util"); | ||
17 | +var exec = require("child_process").exec; | ||
18 | +var child = null; | ||
19 | +var router = express.Router(); | ||
20 | + | ||
21 | +// GET home page | ||
22 | +router.get("/", function(req, res, next) | ||
23 | +{ | ||
24 | + res.render("index" | ||
25 | + , { | ||
26 | + title: "Wikilibras-DB API", | ||
27 | + version: "1.0.0" | ||
28 | + }); | ||
29 | +}); | ||
30 | + | ||
31 | +router.get("/countvideo", function(req, res, next) | ||
32 | +{ | ||
33 | + var response = {}; | ||
34 | + db.query('SELECT COUNT(*) FROM sinal;') | ||
35 | + .then(function(result) | ||
36 | + { | ||
37 | + // response.status = true; | ||
38 | + // response.message = ""; | ||
39 | + // response.data = result; | ||
40 | + // TODO uncomment lines above, remove the line below and | ||
41 | + response = [parseInt(result[0].count)]; | ||
42 | + res.status(203); | ||
43 | + }) | ||
44 | + .catch(function(error) | ||
45 | + { | ||
46 | + response.status = false; | ||
47 | + response.message = ""; | ||
48 | + response.data = error; | ||
49 | + res.status(500); | ||
50 | + }) | ||
51 | + .finally(function() | ||
52 | + { | ||
53 | + res.send(response); | ||
54 | + pgp.end(); | ||
55 | + }); | ||
56 | +}); | ||
57 | + | ||
58 | +router.get("/listselos", function(req, res, next) | ||
59 | +{ | ||
60 | + var response = {}; | ||
61 | + db.query('SELECT "nomeSelo", "idSelo" FROM "tipoSelo";') | ||
62 | + .then(function(result) | ||
63 | + { | ||
64 | + // response.status = true; | ||
65 | + // response.data = result; | ||
66 | + response = result; | ||
67 | + res.status(203); | ||
68 | + }) | ||
69 | + .catch(function(error) | ||
70 | + { | ||
71 | + response.status = false; | ||
72 | + response.error = error; | ||
73 | + res.status(500); | ||
74 | + }) | ||
75 | + .finally(function() | ||
76 | + { | ||
77 | + res.send(response); | ||
78 | + pgp.end(); | ||
79 | + }); | ||
80 | +}); | ||
81 | + | ||
82 | +router.get("/countuservideos", function(req, res, next) | ||
83 | +{ | ||
84 | + var response = {}; | ||
85 | + var limit = 10; | ||
86 | + if (!_.isEmpty(req.query.limit)) | ||
87 | + { | ||
88 | + var _limit = parseInt(req.query.limit); | ||
89 | + if ((0 <= _limit) && (_limit <= 1000)) | ||
90 | + { | ||
91 | + limit = _limit; | ||
92 | + } | ||
93 | + } | ||
94 | + var query = 'SELECT DISTINCT' + | ||
95 | + ' usuario as username,' + | ||
96 | + ' "idUsuario" as email,' + | ||
97 | + ' CAST(COUNT(*) as INTEGER) as videos' + | ||
98 | + ' FROM sinal' + | ||
99 | + ' GROUP BY usuario, "idUsuario"' + | ||
100 | + ' ORDER BY videos DESC, usuario' + | ||
101 | + ' LIMIT ' + limit + ';'; | ||
102 | + db.query(query) | ||
103 | + .then(function(result) | ||
104 | + { | ||
105 | + // response.status = true; | ||
106 | + // response.data = result; | ||
107 | + response = result; | ||
108 | + res.status(203); | ||
109 | + }) | ||
110 | + .catch(function(error) | ||
111 | + { | ||
112 | + response.status = false; | ||
113 | + response.error = error; | ||
114 | + console.log(error); | ||
115 | + res.status(500); | ||
116 | + }) | ||
117 | + .finally(function() | ||
118 | + { | ||
119 | + res.send(response); | ||
120 | + pgp.end(); | ||
121 | + }); | ||
122 | +}); | ||
123 | + | ||
124 | +router.get("/listall", function(req, res, next) | ||
125 | +{ | ||
126 | + var response = {}; | ||
127 | + // 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"') | ||
128 | + db.query('SELECT s."data", s."usuario", s."idSinal", s."idSelo", s."nome", s."classe", s."frase", s."estado", s."cidade", s."file" FROM "sinal" s, "tipoSelo" ts WHERE s."idSelo" = ts."idSelo"') | ||
129 | + .then(function(result) | ||
130 | + { | ||
131 | + response = result; | ||
132 | + res.status(203); | ||
133 | + }) | ||
134 | + .catch(function(error) | ||
135 | + { | ||
136 | + response = error; | ||
137 | + res.status(500); | ||
138 | + }) | ||
139 | + .finally(function() | ||
140 | + { | ||
141 | + res.send(response); | ||
142 | + pgp.end(); | ||
143 | + }); | ||
144 | +}); | ||
145 | + | ||
146 | +/* | ||
147 | +// only for test | ||
148 | +router.get("/populate", function(req, res, next) | ||
149 | +{ | ||
150 | + var response = {}; | ||
151 | + exec("sudo su postgres -c 'psql --set ON_ERROR_STOP=off -f ../wikilibras-db-api-dump.sql wikilibras'", | ||
152 | + function(error, stdout, stderr) | ||
153 | + { | ||
154 | + if (error) | ||
155 | + { | ||
156 | + response.status = false; | ||
157 | + response.message = "Error while populate"; | ||
158 | + console.log(stdout); | ||
159 | + res.status = 500; | ||
160 | + } | ||
161 | + else if (stderr.length > 0) | ||
162 | + { | ||
163 | + response.status = false; | ||
164 | + response.message = "The Database already been populated"; | ||
165 | + console.log(stderr); | ||
166 | + res.status = 304; | ||
167 | + } | ||
168 | + else | ||
169 | + { | ||
170 | + response.status = true; | ||
171 | + response.message = "The Database has been populated"; | ||
172 | + res.status = 201; | ||
173 | + } | ||
174 | + res.send(response); | ||
175 | + }); | ||
176 | +}); | ||
177 | +*/ | ||
178 | + | ||
179 | +router.get("/reset", function(req, res, next) | ||
180 | +{ | ||
181 | + var response = {}; | ||
182 | + db.query('TRUNCATE TABLE sinal, selo; ALTER SEQUENCE sequence RESTART WITH 1;') | ||
183 | + .then(function(result) | ||
184 | + { | ||
185 | + response.status = true; | ||
186 | + response.message = "The database has been truncated"; | ||
187 | + res.status(203); | ||
188 | + }) | ||
189 | + .catch(function(error) | ||
190 | + { | ||
191 | + response.status = false; | ||
192 | + response.message = "The database cannot be truncated"; | ||
193 | + response.error = error; | ||
194 | + res.status(500); | ||
195 | + }) | ||
196 | + .finally(function() | ||
197 | + { | ||
198 | + res.send(response); | ||
199 | + pgp.end(); | ||
200 | + // console.log(JSON.stringify(response, null, 4)); | ||
201 | + }); | ||
202 | +}); | ||
203 | + | ||
204 | +router.get("/version", function(req, res, next) | ||
205 | +{ | ||
206 | + var response = []; | ||
207 | + db.query('SELECT MAX(version) FROM sinal;') | ||
208 | + .then(function(result) | ||
209 | + { | ||
210 | + response = { "version": result[0].max }; | ||
211 | + }) | ||
212 | + .catch(function(error) | ||
213 | + { | ||
214 | + response = error; | ||
215 | + }) | ||
216 | + .finally(function() | ||
217 | + { | ||
218 | + pgp.end(); | ||
219 | + res.status(203).send(response); | ||
220 | + }); | ||
221 | +}); | ||
222 | + | ||
223 | +router.get("/sinais", function(req, res, next) | ||
224 | +{ | ||
225 | + var results = []; | ||
226 | + if ((!_.isEmpty(req.param("selo"))) && (!_.isEmpty(req.param("version")))) | ||
227 | + { | ||
228 | + 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.param("selo"), req.param("version")]) | ||
229 | + .then(function(result) | ||
230 | + { | ||
231 | + res.status(203).send(result); | ||
232 | + }) | ||
233 | + .catch(function(error) | ||
234 | + { | ||
235 | + // error; | ||
236 | + }) | ||
237 | + .finally(function() | ||
238 | + { | ||
239 | + pgp.end(); | ||
240 | + }); | ||
241 | + } | ||
242 | + else | ||
243 | + { | ||
244 | + if (!_.isEmpty(req.param("version"))) | ||
245 | + { | ||
246 | + db.query("select nome, data, file, avatar, blender version FROM sinal WHERE version = $1", req.param("version")) | ||
247 | + .then(function(result) | ||
248 | + { | ||
249 | + res.status(203).send(result); | ||
250 | + }) | ||
251 | + .catch(function(error) | ||
252 | + { | ||
253 | + // error; | ||
254 | + }) | ||
255 | + .finally(function() | ||
256 | + { | ||
257 | + pgp.end(); | ||
258 | + }); | ||
259 | + } | ||
260 | + if (!_.isEmpty(req.param("selo"))) | ||
261 | + { | ||
262 | + 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.param("selo")) | ||
263 | + | ||
264 | + .then(function(result) | ||
265 | + { | ||
266 | + res.status(203).send(result); | ||
267 | + }) | ||
268 | + .catch(function(error) | ||
269 | + { | ||
270 | + // error; | ||
271 | + }) | ||
272 | + .finally(function() | ||
273 | + { | ||
274 | + pgp.end(); | ||
275 | + }); | ||
276 | + } | ||
277 | + } | ||
278 | +}); | ||
279 | + | ||
280 | +router.post('/gsinal', function(req, res, next) | ||
281 | +{ | ||
282 | + console.log("\n\n\n============================================="); | ||
283 | + console.log("[" + new Date().toISOString() + "] Requisição do IP: " + req.ip); | ||
284 | + console.log("== Parametros: " + util.inspect(req.body)); | ||
285 | + console.log("== Body: " + JSON.stringify(req.headers)); | ||
286 | + db.query('UPDATE sinal SET "idSelo" = ($1), version = version + 1 WHERE nome = ($2)', [req.body.selo, req.body.nome]) | ||
287 | + .then(function(data) | ||
288 | + { | ||
289 | + res.status(203).send('Sinal ' + req.body.nome + ' atualizado com sucesso [without archive]'); | ||
290 | + }) | ||
291 | + .catch(function(error) | ||
292 | + { | ||
293 | + console.log("Erro " + error); | ||
294 | + }); | ||
295 | +}); | ||
296 | + | ||
297 | +/* | ||
298 | +router.post('/addsinal', upload.array('video', 2), function(req, res, next) | ||
299 | +{ | ||
300 | + console.log("\n\n\n============================================="); | ||
301 | + console.log("[" + new Date().toISOString() + "]"); | ||
302 | + console.log("From: " + req.ip); | ||
303 | + // console.log("Files: " + req.files[0]); | ||
304 | + // console.log("headers: " + JSON.stringify(req.headers)); | ||
305 | + console.log("body: " + JSON.stringify(req.body)); | ||
306 | + | ||
307 | + if (req.method === "OPTIONS") | ||
308 | + { | ||
309 | + res.header('Access-Control-Allow-Origin', req.headers.origin); | ||
310 | + } | ||
311 | + else | ||
312 | + { | ||
313 | + res.header('Access-Control-Allow-Origin', '*'); | ||
314 | + } | ||
315 | + | ||
316 | + if (_.isEmpty(req.body.nome)) | ||
317 | + { | ||
318 | + res.send(500, 'O valor do parâmetro nome está vazio'); | ||
319 | + return; | ||
320 | + } | ||
321 | + async.series([ | ||
322 | + function(callback) | ||
323 | + { | ||
324 | + console.log("\t >> ORDEM 1"); | ||
325 | + if (_.isEmpty(req.body.wikilibras)) | ||
326 | + { | ||
327 | + console.log("Movendo arquivo para conversão..."); | ||
328 | + files.downloadAndMoveVideo(req, 'sinais', callback); | ||
329 | + } | ||
330 | + else | ||
331 | + { | ||
332 | + files.downloadAndMoveVideo(req, 'wikilibras', callback); | ||
333 | + } | ||
334 | + }, | ||
335 | + function(callback) | ||
336 | + { | ||
337 | + console.log("\t >> ORDEM 2"); | ||
338 | + if (_.isEmpty(req.body.wikilibras)) | ||
339 | + { | ||
340 | + console.log("Convertendo para .webm..."); | ||
341 | + 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) | ||
342 | + { | ||
343 | + console.log('stdout: ' + stdout); | ||
344 | + console.log('stderr: ' + stderr); | ||
345 | + if (error !== null) | ||
346 | + { | ||
347 | + console.log('exec error: ' + error); | ||
348 | + } | ||
349 | + }); | ||
350 | + | ||
351 | + child.on('exit', function() | ||
352 | + { | ||
353 | + setTimeout(function() | ||
354 | + { | ||
355 | + console.log("Conversão para webm concluída."); | ||
356 | + callback(null, 1); | ||
357 | + }, 500); | ||
358 | + }); | ||
359 | + } | ||
360 | + else | ||
361 | + { | ||
362 | + callback(); | ||
363 | + } | ||
364 | + }, | ||
365 | + function(callback) | ||
366 | + { | ||
367 | + console.log("== Alterando o db"); | ||
368 | + db.query('SELECT "idSelo" FROM "sinal" WHERE nome = $1', req.body.nome) | ||
369 | + .then(function(result) | ||
370 | + { | ||
371 | + var d = new Date(); | ||
372 | + if (Object.keys(result).length > 0) | ||
373 | + { | ||
374 | + if (!_.isEmpty(req.body.overwrite)) | ||
375 | + { | ||
376 | + if (!_.isEmpty(req.body.wikilibras)) | ||
377 | + { | ||
378 | + db.query('UPDATE sinal SET avatar = ($1), blender = ($2) WHERE nome = ($3)', [req.files[0].originalname, req.files[1].originalname, req.body.nome]) | ||
379 | + .then(function(data) | ||
380 | + { | ||
381 | + res.send(200, 'Sinal ' + req.body.nome + ' atualizado com sucesso [with avatar/blender].'); | ||
382 | + }) | ||
383 | + .catch(function(error) | ||
384 | + { | ||
385 | + console.log("Erro " + error); | ||
386 | + }); | ||
387 | + } | ||
388 | + if (!_.isEmpty(req.files)) | ||
389 | + { | ||
390 | + 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]) | ||
391 | + .then(function(data) | ||
392 | + { | ||
393 | + res.status(200).send('Sinal ' + req.body.nome + ' atualizado com sucesso [with archive].'); | ||
394 | + }) | ||
395 | + .catch(function(error) | ||
396 | + { | ||
397 | + console.log("Erro " + error); | ||
398 | + }); | ||
399 | + } | ||
400 | + else | ||
401 | + { | ||
402 | + db.query('UPDATE sinal SET "idSelo" = ($1) WHERE nome = ($2)', [req.body.selo, req.body.nome]) | ||
403 | + .then(function(data) | ||
404 | + { | ||
405 | + res.status(200).send('Sinal ' + req.body.nome + ' atualizado com sucesso [without archive].'); | ||
406 | + }) | ||
407 | + .catch(function(error) | ||
408 | + { | ||
409 | + console.log("Erro " + error); | ||
410 | + }); | ||
411 | + } | ||
412 | + } | ||
413 | + else | ||
414 | + { | ||
415 | + res.status(500).send('Sinal já cadastrado no sistema'); | ||
416 | + } | ||
417 | + } | ||
418 | + else | ||
419 | + { | ||
420 | + if (_.isEmpty(req.body.selo)) | ||
421 | + { | ||
422 | + req.body.selo = 7; | ||
423 | + } | ||
424 | + 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']) | ||
425 | + .then(function(data) | ||
426 | + { | ||
427 | + res.status(200).send('Sinal ' + req.body.nome + ' adicionado com sucesso.'); | ||
428 | + }) | ||
429 | + .catch(function(error) | ||
430 | + { | ||
431 | + console.log("Erro " + error); | ||
432 | + }); | ||
433 | + } | ||
434 | + }) | ||
435 | + .catch(function(error) | ||
436 | + { | ||
437 | + console.log(error); | ||
438 | + }) | ||
439 | + .finally(function() | ||
440 | + { | ||
441 | + pgp.end(); | ||
442 | + }); | ||
443 | + } | ||
444 | + , ], function(err) | ||
445 | + { | ||
446 | + if (err) | ||
447 | + { | ||
448 | + res.send(500, "Error"); | ||
449 | + return; | ||
450 | + } | ||
451 | + }); | ||
452 | +}); | ||
453 | +*/ | ||
454 | + | ||
455 | +router.post('/addsinal', upload.array('video', 2), function(req, res, next) | ||
456 | +{ | ||
457 | + // console.log("[" + new Date().toISOString() + "]"); | ||
458 | + // console.log("From: " + req.ip); | ||
459 | + // console.log("Files: " + JSON.stringify(req.files[0], null, 4)); | ||
460 | + // console.log("headers: " + JSON.stringify(req.headers, null, 4)); | ||
461 | + // console.log("body: " + JSON.stringify(req.body, null, 4)); | ||
462 | + if (req.method === "OPTIONS") | ||
463 | + { | ||
464 | + res.header('Access-Control-Allow-Origin', req.headers.origin); | ||
465 | + } | ||
466 | + else | ||
467 | + { | ||
468 | + res.header('Access-Control-Allow-Origin', '*'); | ||
469 | + } | ||
470 | + if (req.files.length < 1) | ||
471 | + { | ||
472 | + res.status(500).send("ERROR: O campo 'video' não contém nenhum arquivo do sinal"); | ||
473 | + return; | ||
474 | + } | ||
475 | + var directory = users; | ||
476 | + var login = req.body["login"]; | ||
477 | + var estado = req.body["estado"]; | ||
478 | + var classe = req.body["classe-gramatical"]; | ||
479 | + var nome = req.body["nome"]; | ||
480 | + var cidade = req.body["cidade"]; | ||
481 | + var frase = req.body["frases"]; | ||
482 | + var selo = req.body["selo"]; | ||
483 | + var filesize = req.files[0].size; | ||
484 | + var input = req.files[0].path; | ||
485 | + var videoref = ""; | ||
486 | + var output = ""; | ||
487 | + var maxfilesize = 25; // MB | ||
488 | + if (filesize > (maxfilesize * 1048576)) | ||
489 | + { | ||
490 | + res.status(500).send("O tamanho do arquivo deve ter no máximo " + maxfilesize + " MB"); | ||
491 | + return; | ||
492 | + } | ||
493 | + if (_.isEmpty(nome)) | ||
494 | + { | ||
495 | + res.status(500).send("ERROR: O campo 'nome' não foi encontrado"); | ||
496 | + return; | ||
497 | + } | ||
498 | + else | ||
499 | + { | ||
500 | + nome = nome.trim().toUpperCase(); | ||
501 | + videoref = nome + "_REF.webm"; | ||
502 | + } | ||
503 | + if (_.isEmpty(selo)) | ||
504 | + { | ||
505 | + selo = 7; | ||
506 | + } | ||
507 | + if (_.isEmpty(login)) | ||
508 | + { | ||
509 | + console.log("WARNING: O campo 'login' não foi encontrado"); | ||
510 | + } | ||
511 | + else | ||
512 | + { | ||
513 | + directory = path.join(directory, login); | ||
514 | + } | ||
515 | + if (_.isEmpty(estado)) | ||
516 | + { | ||
517 | + console.log("WARNING: O campo 'estado' não foi encontrado"); | ||
518 | + } | ||
519 | + else | ||
520 | + { | ||
521 | + directory = path.join(directory, estado); | ||
522 | + } | ||
523 | + if (_.isEmpty(classe)) | ||
524 | + { | ||
525 | + console.log("WARNING: O campo 'classe' não foi encontrado"); | ||
526 | + } | ||
527 | + else | ||
528 | + { | ||
529 | + directory = path.join(directory, classe); | ||
530 | + } | ||
531 | + if (!fs.existsSync(directory)) | ||
532 | + { | ||
533 | + console.log("Criando diretorio: " + directory); | ||
534 | + mkdirp(directory, function (err) | ||
535 | + { | ||
536 | + if (err) | ||
537 | + { | ||
538 | + console.error(err); | ||
539 | + res.status(500).send(err); | ||
540 | + return; | ||
541 | + } | ||
542 | + else | ||
543 | + { | ||
544 | + console.log("Diretório criado com sucesso!"); | ||
545 | + } | ||
546 | + }); | ||
547 | + } | ||
548 | + output = path.join(directory, videoref); | ||
549 | + async.series([ | ||
550 | + // Converter para formato webm | ||
551 | + function(callback) | ||
552 | + { | ||
553 | + console.log("Convertendo para webm..."); | ||
554 | + child = exec("avconv -y -v error -i \"" + input + "\" -acodec libvorbis -vcodec libvpx -an \"" + output + "\"", | ||
555 | + function(error, stdout, stderr) | ||
556 | + { | ||
557 | + if (error || (stderr.length > 0)) | ||
558 | + { | ||
559 | + var log = "O arquivo de vídeo é inválido, ou ocorreu um erro durante a conversão\nDetalhes: " + stdout + stderr; | ||
560 | + log = log.trim(); | ||
561 | + res.status(500).send(log.trim()); | ||
562 | + callback(true, log); | ||
563 | + } | ||
564 | + else | ||
565 | + { | ||
566 | + res.status(200); | ||
567 | + return 0; | ||
568 | + } | ||
569 | + }); | ||
570 | + child.on("exit", function(code) | ||
571 | + { | ||
572 | + setTimeout(function() | ||
573 | + { | ||
574 | + if (code === 0) | ||
575 | + { | ||
576 | + console.log("Conversão concluída"); | ||
577 | + callback(null, 1); | ||
578 | + } | ||
579 | + else | ||
580 | + { | ||
581 | + callback(true, new Error("Erro durante conversão")); | ||
582 | + } | ||
583 | + }, 500); | ||
584 | + }); | ||
585 | + }, | ||
586 | + function(callback) | ||
587 | + { | ||
588 | + console.log("Verificando se este sinal já existe"); | ||
589 | + db.query('SELECT "idSinal" FROM "sinal" WHERE usuario = ($1) AND estado = ($2) AND classe = ($3) AND nome = ($4)', [login, estado, classe, nome]) | ||
590 | + .then(function(result) | ||
591 | + { | ||
592 | + var d = new Date(); | ||
593 | + var date = d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate(); | ||
594 | + if (Object.keys(result).length > 0) | ||
595 | + { | ||
596 | + var idSinal = result[0].idSinal; | ||
597 | + console.log("Existe, atualizando o sinal[" + idSinal + "]: '" + nome + "'"); | ||
598 | + 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]) | ||
599 | + .then(function(data) | ||
600 | + { | ||
601 | + res.status(200).send("Sinal atualizado"); | ||
602 | + }) | ||
603 | + .catch(function(error) | ||
604 | + { | ||
605 | + var message = "Erro ao atualizar sinal '" + nome + "'\n" + error; | ||
606 | + console.log(message); | ||
607 | + res.status(500).send(message); | ||
608 | + }); | ||
609 | + } | ||
610 | + else | ||
611 | + { | ||
612 | + console.log("Não existe, inserindo o sinal: '" + nome + "'"); | ||
613 | + 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]) | ||
614 | + .then(function(data) | ||
615 | + { | ||
616 | + var message = "Sinal[" + data.idSinal + "]: '" + nome + "', inserido com sucesso"; | ||
617 | + console.log(message); | ||
618 | + res.status(200).send(message); | ||
619 | + }) | ||
620 | + .catch(function(error) | ||
621 | + { | ||
622 | + res.status(500).send(error); | ||
623 | + }); | ||
624 | + } | ||
625 | + }) | ||
626 | + .catch(function(error) | ||
627 | + { | ||
628 | + console.log(error); | ||
629 | + }) | ||
630 | + .finally(function() | ||
631 | + { | ||
632 | + pgp.end(); | ||
633 | + }); | ||
634 | + } | ||
635 | + ], | ||
636 | + function(err, results) | ||
637 | + { | ||
638 | + if (err) | ||
639 | + { | ||
640 | + console.log(results[0]); | ||
641 | + } | ||
642 | + }); | ||
643 | +}); | ||
644 | + | ||
645 | +module.exports = router; |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +#!/bin/sh | ||
2 | + | ||
3 | +### BEGIN INIT INFO | ||
4 | +# Provides: <SCRIPT_NAME> | ||
5 | +# Required-Start: $all | ||
6 | +# Required-Stop: $all | ||
7 | +# Default-Start: 2 3 4 5 | ||
8 | +# Default-Stop: 0 1 6 | ||
9 | +# Short-Description: Service provided <SCRIPT_NAME> | ||
10 | +# Description: Enable service provided <SCRIPT_NAME> API at boot | ||
11 | +### END INIT INFO | ||
12 | + | ||
13 | +set -e | ||
14 | + | ||
15 | +export PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" | ||
16 | + | ||
17 | +CWD="<CURDIR>" | ||
18 | + | ||
19 | +case "$1" in | ||
20 | + start) | ||
21 | + cd "$CWD" | ||
22 | + "<NPM>" start& | ||
23 | + ;; | ||
24 | + *) | ||
25 | + echo "Usage: /etc/init.d/<SCRIPT_NAME> {start}" | ||
26 | + exit 1 | ||
27 | + ;; | ||
28 | +esac | ||
29 | + | ||
30 | +exit 0 |
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +SET statement_timeout = 0; | ||
2 | +SET lock_timeout = 0; | ||
3 | +SET client_encoding = 'UTF8'; | ||
4 | +SET standard_conforming_strings = on; | ||
5 | +SET check_function_bodies = false; | ||
6 | +SET client_min_messages = warning; | ||
7 | + | ||
8 | +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; | ||
9 | + | ||
10 | +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; | ||
11 | + | ||
12 | +SET search_path = public, pg_catalog; | ||
13 | + | ||
14 | +SET default_tablespace = ''; | ||
15 | + | ||
16 | +SET default_with_oids = false; | ||
17 | + | ||
18 | +CREATE TABLE selo ( | ||
19 | + "idSelo" integer NOT NULL, | ||
20 | + "idSinal" integer, | ||
21 | + data character varying(30), | ||
22 | + estado character varying(30), | ||
23 | + cidade character varying(30) | ||
24 | +); | ||
25 | + | ||
26 | +ALTER TABLE public.selo OWNER TO wikilibras; | ||
27 | + | ||
28 | +CREATE SEQUENCE sequence | ||
29 | + START WITH 1 | ||
30 | + INCREMENT BY 1 | ||
31 | + NO MINVALUE | ||
32 | + NO MAXVALUE | ||
33 | + CACHE 1; | ||
34 | + | ||
35 | +ALTER TABLE public.sequence OWNER TO wikilibras; | ||
36 | + | ||
37 | +CREATE TABLE sinal ( | ||
38 | + data character varying(30), | ||
39 | + -- TODO create table users | ||
40 | + "idUsuario" integer, | ||
41 | + usuario character varying(30), | ||
42 | + version integer DEFAULT 0, | ||
43 | + "idSinal" integer DEFAULT nextval('sequence'::regclass) NOT NULL, | ||
44 | + "idSelo" integer, | ||
45 | + nome character varying(30), | ||
46 | + classe character varying(30), | ||
47 | + frase character varying(100), | ||
48 | + estado character varying(30), | ||
49 | + cidade character varying(30), | ||
50 | + file character varying(100), | ||
51 | + blender character varying(100), | ||
52 | + avatar character varying(100) | ||
53 | +); | ||
54 | + | ||
55 | +ALTER TABLE public.sinal OWNER TO wikilibras; | ||
56 | + | ||
57 | +CREATE TABLE "tipoSelo" ( | ||
58 | + "nomeSelo" character varying(40), | ||
59 | + "idSelo" integer DEFAULT nextval('sequence'::regclass) NOT NULL | ||
60 | +); | ||
61 | + | ||
62 | +ALTER TABLE public."tipoSelo" OWNER TO wikilibras; | ||
63 | + | ||
64 | +SELECT pg_catalog.setval('sequence', 1, false); | ||
65 | + | ||
66 | +INSERT INTO "tipoSelo" VALUES ('wikilibras', 1); | ||
67 | +INSERT INTO "tipoSelo" VALUES ('especialista', 2); | ||
68 | +INSERT INTO "tipoSelo" VALUES ('invalido_wikilibras', 3); | ||
69 | +INSERT INTO "tipoSelo" VALUES ('invalido_especialista', 4); | ||
70 | +INSERT INTO "tipoSelo" VALUES ('animadores', 5); | ||
71 | +INSERT INTO "tipoSelo" VALUES ('invalido_animadores', 6); | ||
72 | +INSERT INTO "tipoSelo" VALUES ('null', 7); | ||
73 | + | ||
74 | +ALTER TABLE ONLY sinal | ||
75 | + ADD CONSTRAINT "idSinal" PRIMARY KEY ("idSinal"); | ||
76 | + | ||
77 | +ALTER TABLE ONLY "tipoSelo" | ||
78 | + ADD CONSTRAINT "tipoSelo_pkey" PRIMARY KEY ("idSelo"); | ||
79 | + | ||
80 | +ALTER TABLE ONLY selo | ||
81 | + ADD CONSTRAINT "selo_idSelo_fkey" FOREIGN KEY ("idSelo") REFERENCES "tipoSelo"("idSelo"); | ||
82 | + | ||
83 | +ALTER TABLE ONLY selo | ||
84 | + ADD CONSTRAINT "selo_idSinal_fkey" FOREIGN KEY ("idSinal") REFERENCES sinal("idSinal"); | ||
85 | + | ||
86 | +REVOKE ALL ON SCHEMA public FROM PUBLIC; | ||
87 | +REVOKE ALL ON SCHEMA public FROM postgres; | ||
88 | +GRANT ALL ON SCHEMA public TO postgres; | ||
89 | +GRANT ALL ON SCHEMA public TO PUBLIC; |