151 lines
5.0 KiB
JavaScript
Executable File
151 lines
5.0 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
const express = require("express"),
|
|
config = require("config"),
|
|
crypto = require("crypto"),
|
|
Promise = require("bluebird");
|
|
|
|
let photoDB;
|
|
|
|
require("../db/photos").then(function(db) {
|
|
photoDB = db;
|
|
});
|
|
|
|
const router = express.Router();
|
|
const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/";
|
|
|
|
router.put("/:id", function(req, res/*, next*/) {
|
|
if (!req.user.maintainer) {
|
|
return res.status(401).send("Unauthorized to modify photos.");
|
|
}
|
|
|
|
return res.status(400).send("Invalid request");
|
|
});
|
|
|
|
router.delete("/:id?", function(req, res/*, next*/) {
|
|
if (!req.user.maintainer) {
|
|
return res.status(401).send("Unauthorized to delete photos.");
|
|
}
|
|
|
|
return res.status(400).send("Invalid request");
|
|
});
|
|
|
|
function getFacesForPhoto(id) {
|
|
/* Get the set of faces in this photo */
|
|
return photoDB.sequelize.query(
|
|
"SELECT * FROM faces WHERE photoId=:id AND faceConfidence>0.9", {
|
|
replacements: {
|
|
id: id,
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
}).then((faces) => {
|
|
/* For each face in the photo, get the related faces */
|
|
return photoDB.sequelize.query(
|
|
"SELECT relatedFaces.photoId AS photoId,fd.face1Id,fd.face2Id,fd.distance,relatedFaces.faceConfidence " +
|
|
"FROM (SELECT id,photoId,faceConfidence FROM faces WHERE faces.faceConfidence>=0.9 AND faces.id IN (:ids)) AS faces " +
|
|
"INNER JOIN faces AS relatedFaces ON relatedFaces.faceConfidence>=0.9 AND relatedFaces.id IN (fd.face1Id,fd.face2Id) " +
|
|
"INNER JOIN facedistances AS fd ON fd.distance<=0.5 " +
|
|
" AND (fd.face1Id=faces.id OR fd.face2Id=faces.id) " +
|
|
"WHERE (faces.id=fd.face1Id OR faces.id=fd.face2Id) " +
|
|
"ORDER BY fd.distance ASC", {
|
|
replacements: {
|
|
ids: faces.map(face => face.id),
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
}).then((relatedFaces) => {
|
|
faces.forEach((face) => {
|
|
face.relatedFaces = relatedFaces.filter((related) => {
|
|
return (related.photoId != id && (related.face1Id == face.id || related.face2Id == face.id));
|
|
}).map((related) => {
|
|
return {
|
|
distance: related.distance,
|
|
faceConfidence: related.faceConfidence,
|
|
photoId: related.photoId,
|
|
faceId: related.face1Id != face.id ? related.face1Id : related.face2Id
|
|
}
|
|
});
|
|
});
|
|
return faces;
|
|
});
|
|
});
|
|
}
|
|
|
|
router.get("/:id?", (req, res) => {
|
|
let id;
|
|
if (req.params.id) {
|
|
id = parseInt(req.params.id);
|
|
if (id != req.params.id) {
|
|
return res.status(400).send({ message: "Usage /[id]"});
|
|
}
|
|
}
|
|
|
|
let promise;
|
|
if (id) {
|
|
promise = photoDB.sequelize.query(
|
|
"SELECT * FROM faces WHERE id=:id", {
|
|
replacements: {
|
|
id: id
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
});
|
|
} else {
|
|
promise = photoDB.sequelize.query(
|
|
"SELECT COUNT(id) AS count FROM faces WHERE faceConfidence>=0.9 AND identityId IS NULL", {
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
}).then((results) => {
|
|
const random = Math.floor(Math.random() * results[0].count);
|
|
return photoDB.sequelize.query(
|
|
"SELECT * FROM faces WHERE faceConfidence>=0.9 AND identityId IS NULL ORDER BY id LIMIT :index,1", {
|
|
replacements: {
|
|
index: random
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
});
|
|
});
|
|
}
|
|
|
|
return promise.then((faces) => {
|
|
console.log("Looking up " + faces.map(face => face.id).join(","));
|
|
return photoDB.sequelize.query(
|
|
"SELECT relatedFaces.photoId AS photoId,fd.face1Id,fd.face2Id,fd.distance,relatedFaces.faceConfidence " +
|
|
"FROM (SELECT id,photoId,faceConfidence FROM faces WHERE faces.id IN (:ids)) AS faces " +
|
|
"INNER JOIN faces AS relatedFaces ON relatedFaces.identityId IS NULL AND relatedFaces.faceConfidence>=0.9 AND relatedFaces.id IN (fd.face1Id,fd.face2Id) " +
|
|
"INNER JOIN facedistances AS fd ON fd.distance<=0.5 " +
|
|
" AND (fd.face1Id=faces.id OR fd.face2Id=faces.id) " +
|
|
"WHERE (faces.id=fd.face1Id OR faces.id=fd.face2Id) " +
|
|
"ORDER BY fd.distance ASC",{
|
|
replacements: {
|
|
ids: faces.map(face => face.id)
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
}).then((relatedFaces) => {
|
|
faces.forEach((face) => {
|
|
face.relatedFaces = relatedFaces.filter((related) => {
|
|
return (related.photoId != faces[0].photoId && (related.face1Id == face.id || related.face2Id == face.id));
|
|
}).map((related) => {
|
|
return {
|
|
distance: related.distance,
|
|
faceConfidence: related.faceConfidence,
|
|
photoId: related.photoId,
|
|
faceId: related.face1Id != face.id ? related.face1Id : related.face2Id
|
|
}
|
|
});
|
|
});
|
|
return faces;
|
|
});
|
|
}).then((results) => {
|
|
return res.status(200).json(results);
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
return res.status(500).send("Error processing request.");
|
|
});
|
|
});
|
|
|
|
module.exports = router;
|