From fa0ed357529649f0b44ec1dd2786532b7814b816 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 20 Feb 2024 23:29:03 +0200 Subject: [PATCH] server-ts: Port services/image --- src/becca/becca-interface.ts | 2 +- src/routes/api/attachments.js | 2 +- src/routes/api/clipper.js | 2 +- src/routes/api/image.js | 2 +- src/routes/api/sender.js | 2 +- src/routes/routes.js | 2 +- src/services/{image.js => image.ts} | 45 +++++++++++++++-------------- src/services/import/enex.js | 2 +- src/services/import/single.js | 2 +- src/services/notes.ts | 4 +-- src/types.d.ts | 5 ++++ 11 files changed, 39 insertions(+), 31 deletions(-) rename src/services/{image.js => image.ts} (81%) diff --git a/src/becca/becca-interface.ts b/src/becca/becca-interface.ts index 4c8218797..a4e837366 100644 --- a/src/becca/becca-interface.ts +++ b/src/becca/becca-interface.ts @@ -95,7 +95,7 @@ class Becca { return this.notes[noteId]; } - getNoteOrThrow(noteId: string): BNote | null { + getNoteOrThrow(noteId: string): BNote { const note = this.notes[noteId]; if (!note) { throw new NotFoundError(`Note '${noteId}' doesn't exist.`); diff --git a/src/routes/api/attachments.js b/src/routes/api/attachments.js index 09bf09376..4cb782cb2 100644 --- a/src/routes/api/attachments.js +++ b/src/routes/api/attachments.js @@ -1,7 +1,7 @@ const becca = require('../../becca/becca'); const blobService = require('../../services/blob'); const ValidationError = require('../../errors/validation_error'); -const imageService = require("../../services/image.js"); +const imageService = require("../../services/image"); function getAttachmentBlob(req) { const preview = req.query.preview === 'true'; diff --git a/src/routes/api/clipper.js b/src/routes/api/clipper.js index 54532a039..74cd4d8a7 100644 --- a/src/routes/api/clipper.js +++ b/src/routes/api/clipper.js @@ -5,7 +5,7 @@ const cloneService = require('../../services/cloning'); const noteService = require('../../services/notes'); const dateNoteService = require('../../services/date_notes'); const dateUtils = require('../../services/date_utils'); -const imageService = require('../../services/image.js'); +const imageService = require('../../services/image'); const appInfo = require('../../services/app_info'); const ws = require('../../services/ws'); const log = require('../../services/log'); diff --git a/src/routes/api/image.js b/src/routes/api/image.js index d1c702bc7..32bce601b 100644 --- a/src/routes/api/image.js +++ b/src/routes/api/image.js @@ -1,6 +1,6 @@ "use strict"; -const imageService = require('../../services/image.js'); +const imageService = require('../../services/image'); const becca = require('../../becca/becca'); const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; const fs = require('fs'); diff --git a/src/routes/api/sender.js b/src/routes/api/sender.js index 3c405ecc1..7ceeba74d 100644 --- a/src/routes/api/sender.js +++ b/src/routes/api/sender.js @@ -1,7 +1,7 @@ "use strict"; const imageType = require('image-type'); -const imageService = require('../../services/image.js'); +const imageService = require('../../services/image'); const noteService = require('../../services/notes'); const {sanitizeAttributeName} = require('../../services/sanitize_attribute_name'); const specialNotesService = require('../../services/special_notes.js'); diff --git a/src/routes/routes.js b/src/routes/routes.js index 430c2bb25..3c920264c 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -41,7 +41,7 @@ const importRoute = require('./api/import.js'); const setupApiRoute = require('./api/setup.js'); const sqlRoute = require('./api/sql'); const databaseRoute = require('./api/database.js'); -const imageRoute = require('./api/image.js'); +const imageRoute = require('./api/image'); const attributesRoute = require('./api/attributes'); const scriptRoute = require('./api/script.js'); const senderRoute = require('./api/sender.js'); diff --git a/src/services/image.js b/src/services/image.ts similarity index 81% rename from src/services/image.js rename to src/services/image.ts index 26c2fbdd3..046a28bec 100644 --- a/src/services/image.js +++ b/src/services/image.ts @@ -1,19 +1,19 @@ "use strict"; -const becca = require('../becca/becca'); -const log = require('./log'); -const protectedSessionService = require('./protected_session'); -const noteService = require('./notes'); -const optionService = require('./options'); -const sql = require('./sql'); -const jimp = require('jimp'); -const imageType = require('image-type'); -const sanitizeFilename = require('sanitize-filename'); -const isSvg = require('is-svg'); -const isAnimated = require('is-animated'); -const htmlSanitizer = require('./html_sanitizer'); +import becca = require('../becca/becca'); +import log = require('./log'); +import protectedSessionService = require('./protected_session'); +import noteService = require('./notes'); +import optionService = require('./options'); +import sql = require('./sql'); +import jimp = require('jimp'); +import imageType = require('image-type'); +import sanitizeFilename = require('sanitize-filename'); +import isSvg = require('is-svg'); +import isAnimated = require('is-animated'); +import htmlSanitizer = require('./html_sanitizer'); -async function processImage(uploadBuffer, originalName, shrinkImageSwitch) { +async function processImage(uploadBuffer: Buffer, originalName: string, shrinkImageSwitch: boolean) { const compressImages = optionService.getOptionBool("compressImages"); const origImageFormat = getImageType(uploadBuffer); @@ -44,7 +44,7 @@ async function processImage(uploadBuffer, originalName, shrinkImageSwitch) { }; } -function getImageType(buffer) { +function getImageType(buffer: Buffer) { if (isSvg(buffer)) { return { ext: 'svg' @@ -57,18 +57,19 @@ function getImageType(buffer) { } } -function getImageMimeFromExtension(ext) { +function getImageMimeFromExtension(ext: string) { ext = ext.toLowerCase(); return `image/${ext === 'svg' ? 'svg+xml' : ext}`; } -function updateImage(noteId, uploadBuffer, originalName) { +function updateImage(noteId: string, uploadBuffer: Buffer, originalName: string) { log.info(`Updating image ${noteId}: ${originalName}`); originalName = htmlSanitizer.sanitize(originalName); const note = becca.getNote(noteId); + if (!note) { throw new Error("Unable to find note."); } note.saveRevision(); @@ -85,7 +86,7 @@ function updateImage(noteId, uploadBuffer, originalName) { }); } -function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSwitch, trimFilename = false) { +function saveImage(parentNoteId: string, uploadBuffer: Buffer, originalName: string, shrinkImageSwitch: boolean, trimFilename = false) { log.info(`Saving image ${originalName} into parent ${parentNoteId}`); if (trimFilename && originalName.length > 40) { @@ -95,6 +96,7 @@ function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSwitch, const fileName = sanitizeFilename(originalName); const parentNote = becca.getNote(parentNoteId); + if (!parentNote) { throw new Error("Unable to find parent note."); } const {note} = noteService.createNewNote({ parentNoteId, @@ -131,7 +133,7 @@ function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSwitch, }; } -function saveImageToAttachment(noteId, uploadBuffer, originalName, shrinkImageSwitch, trimFilename = false) { +function saveImageToAttachment(noteId: string, uploadBuffer: Buffer, originalName: string, shrinkImageSwitch: boolean, trimFilename = false) { log.info(`Saving image '${originalName}' as attachment into note '${noteId}'`); if (trimFilename && originalName.length > 40) { @@ -163,6 +165,7 @@ function saveImageToAttachment(noteId, uploadBuffer, originalName, shrinkImageSw processImage(uploadBuffer, originalName, shrinkImageSwitch).then(({buffer, imageFormat}) => { sql.transactional(() => { // re-read, might be changed in the meantime + if (!attachment.attachmentId) { throw new Error("Missing attachment ID."); } attachment = becca.getAttachmentOrThrow(attachment.attachmentId); attachment.mime = getImageMimeFromExtension(imageFormat.ext); @@ -179,7 +182,7 @@ function saveImageToAttachment(noteId, uploadBuffer, originalName, shrinkImageSw return attachment; } -async function shrinkImage(buffer, originalName) { +async function shrinkImage(buffer: Buffer, originalName: string) { let jpegQuality = optionService.getOptionInt('imageJpegQuality', 0); if (jpegQuality < 10 || jpegQuality > 100) { @@ -190,7 +193,7 @@ async function shrinkImage(buffer, originalName) { try { finalImageBuffer = await resize(buffer, jpegQuality); } - catch (e) { + catch (e: any) { log.error(`Failed to resize image '${originalName}', stack: ${e.stack}`); finalImageBuffer = buffer; @@ -205,7 +208,7 @@ async function shrinkImage(buffer, originalName) { return finalImageBuffer; } -async function resize(buffer, quality) { +async function resize(buffer: Buffer, quality: number) { const imageMaxWidthHeight = optionService.getOptionInt('imageMaxWidthHeight'); const start = Date.now(); diff --git a/src/services/import/enex.js b/src/services/import/enex.js index c8379b951..74ae5b243 100644 --- a/src/services/import/enex.js +++ b/src/services/import/enex.js @@ -5,7 +5,7 @@ const log = require('../log'); const utils = require('../utils'); const sql = require('../sql'); const noteService = require('../notes'); -const imageService = require('../image.js'); +const imageService = require('../image'); const protectedSessionService = require('../protected_session'); const htmlSanitizer = require('../html_sanitizer'); const {sanitizeAttributeName} = require('../sanitize_attribute_name'); diff --git a/src/services/import/single.js b/src/services/import/single.js index ec7aa735d..bebacee09 100644 --- a/src/services/import/single.js +++ b/src/services/import/single.js @@ -1,7 +1,7 @@ "use strict"; const noteService = require('../../services/notes'); -const imageService = require('../../services/image.js'); +const imageService = require('../../services/image'); const protectedSessionService = require('../protected_session'); const markdownService = require('./markdown.js'); const mimeService = require('./mime.js'); diff --git a/src/services/notes.ts b/src/services/notes.ts index 4f177c58f..48af3f775 100644 --- a/src/services/notes.ts +++ b/src/services/notes.ts @@ -506,7 +506,7 @@ async function downloadImage(noteId: string, imageUrl: string) { const parsedUrl = url.parse(unescapedUrl); const title = path.basename(parsedUrl.pathname || ""); - const imageService = require('../services/image.js'); + const imageService = require('../services/image'); const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, title, true, true); imageUrlToAttachmentIdMapping[imageUrl] = attachment.attachmentId; @@ -539,7 +539,7 @@ function downloadImages(noteId: string, content: string) { const imageBase64 = url.substr(inlineImageMatch[0].length); const imageBuffer = Buffer.from(imageBase64, 'base64'); - const imageService = require('../services/image.js'); + const imageService = require('../services/image'); const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true); const encodedTitle = encodeURIComponent(attachment.title); diff --git a/src/types.d.ts b/src/types.d.ts index 166372891..9fe04a204 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -24,4 +24,9 @@ declare module 'joplin-turndown-plugin-gfm' { function gfm(service: TurndownService): void; } export = gfm; +} + +declare module 'is-animated' { + function isAnimated(buffer: Buffer): boolean; + export = isAnimated; } \ No newline at end of file