screenspook/server/app.js
2012-07-04 16:19:52 +02:00

165 lines
5.3 KiB
JavaScript

/**
* Module dependencies.
*/
var express = require('express'),
cradle = require('cradle'),
crypto = require('crypto'),
dbDesign = require('./dbDesign'),
conn = new(cradle.Connection)();
db = conn.database('screenspook'),
dbActions = require('./dbActions').create(db),
app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// init database.
db.save('_design/screenspook', dbDesign);
// upload a screenshot and check whether it is equal to the currently accepted.
app.post('/screenshot', function(req, res){
var screenshotId = req.body.screenshotId,
hash = crypto.createHash('SHA1');
hash.update(req.body.encodedFile, 'utf8'),
screenshotHash = hash.digest('hex'),
screenshotKey = 'blob_' + screenshotHash;
console.log('got screenshot with hash '+ screenshotKey + ' for screenshotId ' + screenshotId);
/* ensure that the BLOB is contained in the db. */
db.get(screenshotKey, function(err, doc) {
if (err || !doc) {
console.log('saving screenshot to database.');
db.save(screenshotKey, {
type : 'blob',
encodedFile : req.body.encodedFile
});
} else {
console.log('screenshot already in database.');
}
});
// get currently accepted screenshot
db.view('screenspook/accepted', { key : screenshotId }, function(err, doc) {
if (!err && doc.length === 1 && doc[0].value.blob === screenshotKey) {
console.log('currently accepted screenshot equals submitted screenshot');
dbActions.deleteCurrentlyPendingFor(screenshotId, function(err, doc) {
// TODO we do not store the blob again, but probably we want to audit this success.
res.send({accepted:true});
});
} else {
dbActions.deleteCurrentlyPendingFor(screenshotId, function(err, doc) {
db.save({
type : 'shot',
date : new Date(),
screenshotId : screenshotId,
blob : screenshotKey,
status : 'pending'
}, function(err, dbRes) {
if (err) {
console.log('error while saving screenshot: ' + err);
res.send(err);
} else {
res.send({accepted:false});
}
});
});
}
});
});
app.get('/accepted/:screenshotId', function(req, res) {
console.log('get accepted for "' + req.params.screenshotId + '"');
db.view('screenspook/accepted', { key : req.params.screenshotId }, function(err, doc) {
if (err) {
res.send(err);
} else {
if (doc.length === 1) {
res.send(doc[0].value);
}
}
});
});
// get the specified blob
app.get('/blob/:id', function(req, res) {
db.get(req.params.id, function(err, dbRes) {
if (err) {
res.send(err);
} else {
decodedImage = new Buffer(dbRes.encodedFile, 'base64');
res.write(decodedImage);
res.end();
}
});
});
// accept a screenshot (all other screenshots for the screenshotId will be marked invalid).
app.get('/accept/:id', function(req, res) {
db.get(req.params.id, function(err, dbRes) {
if (err) {
res.send(err);
} else {
screenshotId = dbRes.screenshotId;
// get currently accepted screenshot
db.view('screenspook/acceptedIds', { key : screenshotId }, function(err, doc) {
if (!err) {
if (doc.length === 1) {
db.merge(doc[0].id, {status:'historic'}, function(err, dbRes) {
//res.send(err);
});
}
}
// set new screenshot accepted
db.merge(req.params.id, {status:'accepted'}, function(err, dbRes) {
if (err) {
res.send(err);
} else {
res.send({ok:true});
}
});
});
}
});
});
app.get('/overview', function(req, res) {
db.view('screenspook/accepted', function(err, acceptedShots) {
db.view('screenspook/pending', function(err, pendingShots) {
var mapValue = function(item) {
return item;
};
var acceptedShotsValues = acceptedShots.map(mapValue);
var pendingShotsValues = pendingShots.map(mapValue);
res.send({
acceptedShots : acceptedShotsValues,
pendingShots : pendingShotsValues
});
});
});
});
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});