2018-01-05 23:54:02 -05:00
"use strict" ;
2024-07-18 21:35:17 +03:00
import imageService from "../../services/image.js" ;
import becca from "../../becca/becca.js" ;
2024-07-18 21:37:45 +03:00
import fs from "fs" ;
2025-01-09 18:36:24 +02:00
import type { Request , Response } from "express" ;
2025-01-13 23:18:10 +02:00
import type BNote from "../../becca/entities/bnote.js" ;
import type BRevision from "../../becca/entities/brevision.js" ;
2024-07-23 19:14:33 +03:00
import { RESOURCE_DIR } from "../../services/resource_dir.js" ;
2018-01-05 23:54:02 -05:00
2024-04-06 21:21:22 +03:00
function returnImageFromNote ( req : Request , res : Response ) {
2021-05-02 11:23:58 +02:00
const image = becca . getNote ( req . params . noteId ) ;
2018-01-05 23:54:02 -05:00
2023-10-02 15:24:40 +02:00
return returnImageInt ( image , res ) ;
}
2024-04-06 21:21:22 +03:00
function returnImageFromRevision ( req : Request , res : Response ) {
2023-10-02 15:24:40 +02:00
const image = becca . getRevision ( req . params . revisionId ) ;
return returnImageInt ( image , res ) ;
}
2024-04-06 21:21:22 +03:00
function returnImageInt ( image : BNote | BRevision | null , res : Response ) {
2018-01-05 23:54:02 -05:00
if ( ! image ) {
2025-01-09 18:07:02 +02:00
res . set ( "Content-Type" , "image/png" ) ;
2024-07-23 19:14:33 +03:00
return res . send ( fs . readFileSync ( ` ${ RESOURCE_DIR } /db/image-deleted.png ` ) ) ;
2025-01-09 18:07:02 +02:00
} else if ( ! [ "image" , "canvas" , "mermaid" , "mindMap" ] . includes ( image . type ) ) {
2018-11-08 10:30:35 +01:00
return res . sendStatus ( 400 ) ;
}
2020-03-25 18:21:55 +01:00
2025-01-09 18:07:02 +02:00
if ( image . type === "canvas" ) {
renderSvgAttachment ( image , res , "canvas-export.svg" ) ;
} else if ( image . type === "mermaid" ) {
renderSvgAttachment ( image , res , "mermaid-export.svg" ) ;
2024-09-01 22:36:50 +03:00
} else if ( image . type === "mindMap" ) {
2025-01-09 18:07:02 +02:00
renderSvgAttachment ( image , res , "mindmap-export.svg" ) ;
2022-04-11 11:56:36 +02:00
} else {
2025-01-09 18:07:02 +02:00
res . set ( "Content-Type" , image . mime ) ;
2022-04-11 11:56:36 +02:00
res . set ( "Cache-Control" , "no-cache, no-store, must-revalidate" ) ;
res . send ( image . getContent ( ) ) ;
}
2018-03-30 17:07:41 -04:00
}
2018-01-05 23:54:02 -05:00
2024-04-06 21:21:22 +03:00
function renderSvgAttachment ( image : BNote | BRevision , res : Response , attachmentName : string ) {
2025-01-09 18:07:02 +02:00
let svg : string | Buffer = "<svg/>" ;
2023-10-21 00:23:16 +02:00
const attachment = image . getAttachmentByTitle ( attachmentName ) ;
2024-07-16 22:29:00 +03:00
if ( attachment ) {
2024-07-18 19:29:34 +03:00
svg = attachment . getContent ( ) ;
2023-10-21 00:23:16 +02:00
} else {
// backwards compatibility, before attachments, the SVG was stored in the main note content as a separate key
const contentSvg = image . getJsonContentSafely ( ) ? . svg ;
if ( contentSvg ) {
2024-07-16 22:29:00 +03:00
svg = contentSvg ;
2023-10-21 00:23:16 +02:00
}
}
2025-01-09 18:07:02 +02:00
res . set ( "Content-Type" , "image/svg+xml" ) ;
2023-10-21 00:23:16 +02:00
res . set ( "Cache-Control" , "no-cache, no-store, must-revalidate" ) ;
res . send ( svg ) ;
}
2024-04-06 21:21:22 +03:00
function returnAttachedImage ( req : Request , res : Response ) {
2023-03-16 18:34:39 +01:00
const attachment = becca . getAttachment ( req . params . attachmentId ) ;
2023-04-17 22:40:53 +02:00
if ( ! attachment ) {
2025-01-09 18:07:02 +02:00
res . set ( "Content-Type" , "image/png" ) ;
2024-07-23 19:14:33 +03:00
return res . send ( fs . readFileSync ( ` ${ RESOURCE_DIR } /db/image-deleted.png ` ) ) ;
2023-03-16 18:34:39 +01:00
}
if ( ! [ "image" ] . includes ( attachment . role ) ) {
2025-01-09 18:07:02 +02:00
return res . setHeader ( "Content-Type" , "text/plain" ) . status ( 400 ) . send ( ` Attachment ' ${ attachment . attachmentId } ' has role ' ${ attachment . role } ', but 'image' was expected. ` ) ;
2023-03-16 18:34:39 +01:00
}
2025-01-09 18:07:02 +02:00
res . set ( "Content-Type" , attachment . mime ) ;
2023-03-16 18:34:39 +01:00
res . set ( "Cache-Control" , "no-cache, no-store, must-revalidate" ) ;
res . send ( attachment . getContent ( ) ) ;
}
2024-12-10 22:35:23 +02:00
function updateImage ( req : Request ) {
2025-01-09 18:07:02 +02:00
const { noteId } = req . params ;
const { file } = req ;
2019-11-08 22:34:30 +01:00
2023-05-08 00:02:08 +02:00
const note = becca . getNoteOrThrow ( noteId ) ;
2019-11-08 22:34:30 +01:00
2024-04-07 16:56:45 +03:00
if ( ! file ) {
return {
uploaded : false ,
message : ` Missing image data. `
} ;
}
2020-06-28 23:10:45 +02:00
if ( ! [ "image/png" , "image/jpeg" , "image/gif" , "image/webp" , "image/svg+xml" ] . includes ( file . mimetype ) ) {
2019-11-08 22:34:30 +01:00
return {
uploaded : false ,
2022-12-21 15:19:05 +01:00
message : ` Unknown image type: ${ file . mimetype } `
2019-11-08 22:34:30 +01:00
} ;
}
2024-04-07 14:29:08 +03:00
if ( typeof file . buffer === "string" ) {
return {
uploaded : false ,
message : "Invalid image content."
} ;
}
2024-12-22 15:42:15 +02:00
2020-06-20 12:31:38 +02:00
imageService . updateImage ( noteId , file . buffer , file . originalname ) ;
2019-11-08 22:34:30 +01:00
return { uploaded : true } ;
}
2024-07-18 21:47:30 +03:00
export default {
2023-10-02 15:24:40 +02:00
returnImageFromNote ,
returnImageFromRevision ,
2023-03-16 18:34:39 +01:00
returnAttachedImage ,
2019-11-08 22:34:30 +01:00
updateImage
2020-06-20 12:31:38 +02:00
} ;