| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const express = require('express'); | 
					
						
							|  |  |  | const router = express.Router(); | 
					
						
							|  |  |  | const sql = require('../../services/sql'); | 
					
						
							|  |  |  | const auth = require('../../services/auth'); | 
					
						
							|  |  |  | const utils = require('../../services/utils'); | 
					
						
							| 
									
										
										
										
											2018-01-06 15:56:00 -05:00
										 |  |  | const sync_table = require('../../services/sync_table'); | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  | const multer = require('multer')(); | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  | const imagemin = require('imagemin'); | 
					
						
							|  |  |  | const imageminMozJpeg = require('imagemin-mozjpeg'); | 
					
						
							| 
									
										
										
										
											2018-01-06 13:53:02 -05:00
										 |  |  | const imageminPngQuant = require('imagemin-pngquant'); | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  | const jimp = require('jimp'); | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | router.get('/:imageId/:filename', auth.checkApiAuth, async (req, res, next) => { | 
					
						
							|  |  |  |     const image = await sql.getFirst("SELECT * FROM images WHERE image_id = ?", [req.params.imageId]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!image) { | 
					
						
							|  |  |  |         return res.status(404).send({}); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res.set('Content-Type', 'image/' + image.format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res.send(image.data); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  | router.post('', auth.checkApiAuth, multer.single('upload'), async (req, res, next) => { | 
					
						
							| 
									
										
										
										
											2018-01-06 15:56:00 -05:00
										 |  |  |     const sourceId = req.headers.source_id; | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  |     const noteId = req.query.noteId; | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  |     const file = req.file; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  |     const note = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!note) { | 
					
						
							|  |  |  |         return req.status(404).send(`Note ${noteId} doesn't exist.`); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!file.mimetype.startsWith("image/")) { | 
					
						
							|  |  |  |         return req.send("Unknown image type: " + file.mimetype); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const now = utils.nowDate(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  |     const resizedImage = await resize(file.buffer); | 
					
						
							|  |  |  |     const optimizedImage = await optimize(resizedImage); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  |     const imageId = utils.newImageId(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 15:56:00 -05:00
										 |  |  |     await sql.doInTransaction(async () => { | 
					
						
							|  |  |  |         await sql.insert("images", { | 
					
						
							|  |  |  |             image_id: imageId, | 
					
						
							|  |  |  |             format: file.mimetype.substr(6), | 
					
						
							|  |  |  |             name: file.originalname, | 
					
						
							|  |  |  |             checksum: utils.hash(optimizedImage), | 
					
						
							|  |  |  |             data: optimizedImage, | 
					
						
							|  |  |  |             is_deleted: 0, | 
					
						
							|  |  |  |             date_modified: now, | 
					
						
							|  |  |  |             date_created: now | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await sync_table.addImageSync(imageId, sourceId); | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const noteImageId = utils.newNoteImageId(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await sql.insert("notes_image", { | 
					
						
							|  |  |  |             note_image_id: noteImageId, | 
					
						
							|  |  |  |             note_id: noteId, | 
					
						
							|  |  |  |             image_id: imageId, | 
					
						
							|  |  |  |             is_deleted: 0, | 
					
						
							|  |  |  |             date_modified: now, | 
					
						
							|  |  |  |             date_created: now | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await sync_table.addNoteImageSync(noteImageId, sourceId); | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res.send({ | 
					
						
							|  |  |  |         uploaded: true, | 
					
						
							| 
									
										
										
										
											2018-01-06 21:49:02 -05:00
										 |  |  |         url: `/api/images/${imageId}/${file.originalname}` | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  | const MAX_SIZE = 1000; | 
					
						
							| 
									
										
										
										
											2018-01-06 13:53:02 -05:00
										 |  |  | const MAX_BYTE_SIZE = 200000; // images should have under 100 KBs
 | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | async function resize(buffer) { | 
					
						
							|  |  |  |     const image = await jimp.read(buffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (image.bitmap.width > image.bitmap.height && image.bitmap.width > MAX_SIZE) { | 
					
						
							|  |  |  |         image.resize(MAX_SIZE, jimp.AUTO); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (image.bitmap.height > MAX_SIZE) { | 
					
						
							|  |  |  |         image.resize(jimp.AUTO, MAX_SIZE); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-06 13:53:02 -05:00
										 |  |  |     else if (buffer.byteLength <= MAX_BYTE_SIZE) { | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  |         return buffer; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // we do resizing with max quality which will be trimmed during optimization step next
 | 
					
						
							|  |  |  |     image.quality(100); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // getBuffer doesn't support promises so this workaround
 | 
					
						
							|  |  |  |     return await new Promise((resolve, reject) => image.getBuffer(jimp.MIME_JPEG, (err, data) => { | 
					
						
							|  |  |  |         if (err) { | 
					
						
							|  |  |  |             reject(err); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             resolve(data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     })); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function optimize(buffer) { | 
					
						
							|  |  |  |     return await imagemin.buffer(buffer, { | 
					
						
							|  |  |  |         plugins: [ | 
					
						
							| 
									
										
										
										
											2018-01-06 13:53:02 -05:00
										 |  |  |             // imageminMozJpeg({
 | 
					
						
							|  |  |  |             //     quality: 50
 | 
					
						
							|  |  |  |             // }),
 | 
					
						
							|  |  |  |             imageminPngQuant({ | 
					
						
							|  |  |  |                 quality: "0-70" | 
					
						
							| 
									
										
										
										
											2018-01-06 12:38:25 -05:00
										 |  |  |             }) | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 23:54:02 -05:00
										 |  |  | module.exports = router; |