forked from fredrik/nodejs-multipart-form-upload
-
Notifications
You must be signed in to change notification settings - Fork 3
/
server.js
288 lines (263 loc) · 8.39 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
var bunyan = require('bunyan');
var fs = require('fs');
var exec = require('child_process').exec;
var path = require('path');
var http = require('http');
var formidable = require('./lib/formidable');
var paperboy = require('./lib/paperboy');
var log = bunyan.createLogger({
name: 'nodejs-sphinx'
});
var PUBLIC = path.join(path.dirname(__filename), 'public');
var devmode = false;
var port = 8126;
if (devmode) {
port = 8124;
}
var statuses = {};
var progresses = {};
var metadata = {};
var child;
function puts(error) {
log.error(error);
};
function logsAndFlagsFresh(error, uuid, stdout, stderr) {
log.error(error);
var setFresh = function() {
statuses[uuid] = "transcription fresh";
log.info("\nProcessed uuid: " + uuid + " set to: " + statuses[uuid] + "\n\n");
}
return setFresh;
};
function handleError(err, req, res) {
log.error('Error processing upload', err);
res.writeHead(500, {
'Content-Type': 'application/json'
});
res.write(JSON.stringify({
message: err.message,
status: 500
}));
res.end();
}
function handleUpload(req, res) {
var uuid = match[1];
uuid = uuid.replace(/.mp3/, "");
uuid = uuid.replace(/.srt/, "");
uuid = uuid.replace(/_client/, "");
uuid = uuid.replace(/_server/, "");
log.info("Receiving transcription request: " + uuid);
var form = new formidable.IncomingForm();
form.uploadDir = './data';
form.keepExtensions = true;
// keep track of progress.
form.addListener('progress', function(recvd, expected) {
progress = (recvd / expected * 100).toFixed(2);
progresses[uuid] = progress;
});
form.parse(req, function(error, fields, files) {
var path = files['file']['path'],
filename = files['file']['filename'] || 'temp',
mime = files['file']['mime'];
log.info({
filename: filename,
path: path
}, 'Users file: ' + filename + ':filename\nIs server file: ' + path + ':path\n');
/*
* Rename to original name (sanitize, although it shoudl already be sanitized by the android client.)
*/
var safeFilename = filename.replace(/[^\w\.]/g, "_");
safeFilename = safeFilename.replace(/[;:|@&*/\\]/g, "_");
//safeFilename=safeFilename.replace(/_client\./,".");
safeFilename = safeFilename.replace(/\.mp3/, ".amr");
var tempdir = "../nodejs-pocketsphinxtemp/";
fs.mkdirSync(tempdir);
fs.renameSync(path, tempdir + safeFilename);
safeFilenameServer = safeFilename.replace(/_client/, "_server");
var subtitleregex = new RegExp('(.+).srt');
var matchsubtitle = subtitleregex.exec(filename);
res.writeHead(200, {
'content-type': 'text/html'
});
if (matchsubtitle) {
if (statuses[uuid] === "dictation recieved") {
res.write("Transcription machine is thinking...\n");
} else {
res.write("Server is Processing.\n");
}
res.write(filename + ':filename\n' + path + ':path\n');
//not using closure to set fresh, instead, running sphinx every time the user uploads the srt of the same uuid. this lets the user control the transcription more.
if (statuses[uuid] === "dictation received" || statuses[uuid] === "transcription nothing fresh") {
var runTranscription = function(uuid) {
var uuidchange = uuid; //local variable bound by closure
exec("sh audio2text.sh " + safeFilename.replace(/_client\.srt/, ""), puts);
var setFresh = function() {
statuses[uuidchange] = "transcription fresh";
log.info("Processed uuid: " + uuidchange + " set to: " + statuses[uuidchange]);
}
//http://stackoverflow.com/questions/111102/how-do-javascript-closures-work
return setFresh;
}
var resultFresh = runTranscription(uuid);
setTimeout(resultFresh, 30000); //this is running before exec finishes.
}
/*
* copy the file to the response, if the status was dictation received
* and we just got the client .srt, then thi should copy the client .srt
* with the timecode from audio2text saying that the transcription
* will apear below when it is ready
*
* other wise if the transcription is fresh it will provide
* the transcription
*/
fs.readFile(tempdir + safeFilenameServer, "binary", function(err, file) {
if (err) {
//res.sendHeader(500, {"Content-Type": "text/plain"});
log.info("There was an err reading the file" + err + "\nReturning nothing to the user\n");
//res.write("The machine transcription hasn't returned any hypotheses yet.\n");
//log.info("The machine transcription hasn't returned any hypotheses yet.\n");
} else {
log.info("\nReturning the machine transcription to the user.\n");
log.info("___________________________+++_____________________\n");
res.write(file, "binary");
res.end();
log.info(file);
log.info("___________________________+++_____________________\n");
exec("date", puts);
log.info("Returned above transcription to user.\n");
}
});
statuses[uuid] = "transcription nothing fresh"
log.info("Server's transcription was returned to client. ");
} else {
//if the user just sent an mp3/amr
res.write("Dictation sent for transcription.\n");
res.write(filename + ':filename\n' + path + ':path\n');
res.end();
statuses[uuid] = "dictation received";
}
exec("date", puts);
log.info("Finished upload processing.");
});
}
function handleUpdate(req, res) {
uuid = match[1];
var form = new formidable.IncomingForm();
form.addListener('field', function(name, value) {
log.info("fresh metadata for " + uuid + ": " + name + " => " + value + "\n")
metadata[uuid] = metadata[uuid] || {};
metadata[uuid][name] = value;
});
form.parse(req, function(error, fields, files) {
res.writeHead(200, {
'content-type': 'application/json'
});
res.write(JSON.stringify({
'metadata': metadata[uuid]
}));
log.info(metadata[uuid], 'Done parsing form');
res.end();
});
}
function handleStatus(req, res) {
uuid = match[1];
uuid = uuid.replace(/.mp3/, "");
uuid = uuid.replace(/.srt/, "");
uuid = uuid.replace(/_client/, "");
uuid = uuid.replace(/_server/, "");
res.writeHead(200, {
'content-type': 'application/json'
});
res.write(JSON.stringify({
'status': statuses[uuid]
}));
res.end();
exec("date", puts);
log.info({
'status': statuses[uuid]
}, uuid + "\nReplied to status request: ");
log.info("\n\n");
}
function handleProgress(req, res) {
uuid = match[1];
res.writeHead(200, {
'content-type': 'application/json'
});
res.write(JSON.stringify({
'progress': progresses[uuid]
}));
res.end();
}
function handleStatic(req, res) {
// let paperboy handle any static content.
paperboy
.deliver(PUBLIC, req, res)
.after(function(statCode) {
log.info('Served Request: ' + statCode + ' ' + req.url)
})
.otherwise(function() {
res.writeHead(404, {
'Content-Type': 'text/plain'
});
res.write('Not Found');
res.end();
});
}
var server = http.createServer(function(req, res) {
/*TODO check for API key and non banned install id in this regex */
regex = new RegExp('/upload/(.+)');
match = regex.exec(req.url);
if (match && req.method.toLowerCase() == 'post') {
try {
handleUpload(req, res);
} catch (err) {
handleError(err, req, res);
}
return;
}
// (update) metadata
regex = new RegExp('/update/(.+)');
match = regex.exec(req.url);
if (match && req.method.toLowerCase() == 'post') {
try {
handleUpdate(req, res);
} catch (err) {
handleError(err, req, res);
}
return;
}
// respond to status queries
regex = new RegExp('/status/(.+)');
match = regex.exec(req.url);
if (match) {
try {
handleStatus(req, res);
} catch (err) {
handleError(err, req, res);
}
return;
}
// respond to progress queries.
regex = new RegExp('/progress/(.+)');
match = regex.exec(req.url);
if (match) {
try {
handleProgress(req, res);
} catch (err) {
handleError(err, req, res);
}
return;
}
handleStatic(req, res);
})
if (!module.parent) {
server.listen(port);
log.info('ready at http://localhost:' + port + '/')
} else {
module.exports = {
server: server,
statuses: statuses,
progresses: progresses,
metadata: metadata,
};
}