UNPKG

flexbiz-server

Version:

Flexible Server

39 lines (38 loc) 18.9 kB
const model=global.getModel("file"),app=global.getModel("app"),path=require("path"),fs=require("fs"),controller=require("../../controllers/controller"),ffmpeg=require("fluent-ffmpeg"),ffmpegInstaller=require("@ffmpeg-installer/ffmpeg");ffmpeg.setFfmpegPath(ffmpegInstaller.path); const sharp=require("sharp"),watermark=require("dynamic-watermark"),permission=require("../../libs/permission"),async=require("async"),JSZip=require("jszip"),{onAfterCommit}=require("../../libs/sessionContext"),{createWorker,createScheduler}=require("tesseract.js"),{getDir,getPathFile}=require("../../libs/utils"),{processAndStoreFileWorker}=require("../../libs/vectorService"),tesseractScheduler=createScheduler();let isTesseractReady=!1; async function initTesseract(){try{const $worker$$=await createWorker("vie+eng");tesseractScheduler.addWorker($worker$$);isTesseractReady=!0}catch($error$$){}}initTesseract(); const hasPermission=async($email$$,$file$$)=>new Promise($resolve$$=>{permission.hasRight($file$$.id_app,$email$$,"file","view",async function($error$$,$permission$$){if(!$permission$$)return $resolve$$(!1);$resolve$$(!0)},{data:$file$$,obj:$file$$,notNeedRight:!$file$$.id_link&&!$file$$.id_folder||$file$$.shared})}),convertVideo=async($fileInput$$,$fileOutput$$)=>new Promise(($resolve$$,$reject$$)=>{ffmpeg($fileInput$$,{timeout:432E3}).addOptions("-profile:v baseline;-level 3.0;-start_number 0;-hls_time 10;-hls_list_size 0;-f hls".split(";")).output($fileOutput$$).on("error", function($err$$){$reject$$($err$$.message)}).on("end",()=>{$resolve$$($fileOutput$$)}).run()}),createThumnail=async($fileInput$$,$fileOutput$$,$THUMBNAIL_DIR$$)=>{Logger.info("[file] t\u1ea1o thumbnail",{fileInput:$fileInput$$,fileOutput:$fileOutput$$,THUMBNAIL_DIR:$THUMBNAIL_DIR$$});return new Promise(($resolve$$,$reject$$)=>{ffmpeg($fileInput$$,{timeout:432E3}).on("end",function(){Logger.info("Thumbnail generated successfully!");$resolve$$()}).on("error",function($err$$,$stdout$$,$stderr$$){Logger.error("Error generating thumbnail:", $err$$.message);$stdout$$&&Logger.error("FFmpeg stdout:",$stdout$$);$stderr$$&&Logger.error("FFmpeg stderr:",$stderr$$);$reject$$(Error("Failed to generate thumbnail: "+$err$$.message))}).screenshots({count:1,timemarks:["00:00:01"],filename:$fileOutput$$,folder:$THUMBNAIL_DIR$$,size:"320x?"})})},setWaterMark4Image=async($app_info$$,$file_name$$,$extension_root$$,$recache$$)=>{let $file_name_watermark$$=`${$file_name$$}.watermark.${$extension_root$$}.webp`;if(!$app_info$$.logo_watermark)return $file_name$$; if(!$recache$$&&fs.existsSync($file_name_watermark$$))return $file_name_watermark$$;$extension_root$$=configs.paths.images;$extension_root$$||($extension_root$$=__dirname,$extension_root$$=path.dirname($extension_root$$),$extension_root$$=path.dirname($extension_root$$),$extension_root$$=path.join($extension_root$$,"images"));let $file_logo$$=path.join($extension_root$$,$app_info$$.logo_watermark.split("getfile/")[1]);return fs.existsSync($file_logo$$)?new Promise($resolve$$=>{sharp($file_name$$, {failOnError:!1}).metadata().then($value$$=>{const $watermark_size$$=$value$$.width*10/100;watermark.embed({type:"image",source:$file_name$$,logo:$file_logo$$,destination:$file_name_watermark$$,position:{logoX:$value$$.width-$watermark_size$$-10,logoY:10,logoHeight:$watermark_size$$,logoWidth:$watermark_size$$}},function($status$$){$status$$.status===1?$resolve$$($file_name_watermark$$):(Logger.info("status set watermark",$status$$),$resolve$$($file_name$$))})}).catch($error$$=>{Logger.info($error$$); return $resolve$$($file_name$$)})}):(Logger.info("file logo watermark is not exists",$file_logo$$),$file_name$$)},configResizeImage=async($_size_file_name_resize$$,$file_name$$,$extension$$,$recache$$)=>{let $size$$,$cache$$;if($_size_file_name_resize$$)switch($_size_file_name_resize$$.toString().toUpperCase()){case "64":case "X":$size$$=64;$cache$$=!0;break;case "256":$size$$=256;$cache$$=!0;break;case "S":case "320":$size$$=320;$cache$$=!0;break;case "512":case "M":$size$$=512;$cache$$=!0;break; case "1024":case "L":$size$$=1024;$cache$$=!0;break;case "1080":case "XL":case "FULLHD":$size$$=1080;$cache$$=!0;break;case "1440":case "2K":$size$$=1440;$cache$$=!0;break;case "FULL":break;default:try{$size$$=Number($_size_file_name_resize$$);if(isNaN($size$$)||!$size$$)$size$$=1080;$cache$$=!0}catch($e$$){Logger.info("size param must be X or S or M or L or 2K or FULLHD or a number")}}return $size$$?($_size_file_name_resize$$=`${$file_name$$}.${$size$$}.${$extension$$}.webp`,!$recache$$&&fs.existsSync($_size_file_name_resize$$)? {file_name_resize:$_size_file_name_resize$$,exist:!0}:{cache:$cache$$,size:$size$$,file_name_resize:$_size_file_name_resize$$}):{file_name_resize:$file_name$$}}; module.exports=function($router$$){const $contr$$=new controller($router$$,model,"file",{sort:{date_created:-1},onView:($user$$,$items$$,$next$$)=>{async.map($items$$,($item$$,$callback$$)=>{setImmediate(async()=>{$item$$.file&&(delete $item$$.file.encoding,delete $item$$.file.mimetype,delete $item$$.file.path,$item$$.id_app&&configs.api_url&&($item$$.download_link=`${configs.api_url||""}/api/${$item$$.id_app}/file/download/${$item$$._id.toString()}`));$callback$$(null,$items$$)})},()=>{$next$$(null, $items$$)})},onDeleting:async($user$$,$item$$,$next$$)=>{await global.getModel("filechunk").deleteMany({id_app:$item$$.id_app,file_id:$item$$._id.toString()});$next$$(null,$item$$)}});$contr$$.creating=async function($file_name$jscomp$2_input_user$$,$obj$$,$fn$$){var $extension$jscomp$2_root$$=($obj$$?.file?.extension||"").toLowerCase();if($obj$$.file&&$obj$$.read_image&&$obj$$.file.name&&$obj$$.file.extension&&!$obj$$.file.url&&($file_name$jscomp$2_input_user$$=$obj$$.file.name,["png","jpg","jpeg"].indexOf($extension$jscomp$2_root$$)>= 0)){($extension$jscomp$2_root$$=configs.paths.uploads)||($extension$jscomp$2_root$$=path.join(path.dirname(path.dirname(__dirname)),"uploads"));$file_name$jscomp$2_input_user$$=path.join($extension$jscomp$2_root$$,$file_name$jscomp$2_input_user$$);try{if(await fs.promises.access($file_name$jscomp$2_input_user$$,fs.constants.F_OK),isTesseractReady){var $folder_imageBuffer$$=await sharp($file_name$jscomp$2_input_user$$).greyscale().normalize().linear(1.5,0).sharpen().toBuffer();const $ret$$=await tesseractScheduler.addJob("recognize", $folder_imageBuffer$$);$obj$$.text_from_image=$ret$$.data.text}}catch($error$$){Logger.error("Read text from image error:",$error$$.message,$file_name$jscomp$2_input_user$$)}}$obj$$.id_folder&&global.mongoose.Types.ObjectId.isValid($obj$$.id_folder)&&($folder_imageBuffer$$=await global.getModel("folder").findOne({_id:$obj$$.id_folder}))&&($obj$$.update_right=$folder_imageBuffer$$.update_right,$obj$$.delete_right=$folder_imageBuffer$$.delete_right,$obj$$.visible_to=$folder_imageBuffer$$.visible_to, $obj$$.visible_to_users=$folder_imageBuffer$$.visible_to_users,$obj$$.visible_to_usergroups=$folder_imageBuffer$$.visible_to_usergroups);$fn$$(null,$obj$$)};$contr$$.created=async function($user$$,$obj$$,$fn$$){onAfterCommit(async()=>{if($obj$$.file&&$obj$$.file.name&&$obj$$.file.extension){var $file_name$$=$obj$$.file.name,$extension$jscomp$3_input$jscomp$1_root$$=$obj$$.file.extension.toLowerCase();if(["mp4","mov","avi"].indexOf($extension$jscomp$3_input$jscomp$1_root$$)>=0){$extension$jscomp$3_input$jscomp$1_root$$= getDir("uploads");$extension$jscomp$3_input$jscomp$1_root$$=path.join($extension$jscomp$3_input$jscomp$1_root$$,$file_name$$);let $output$$=getDir("videos");$output$$=path.join($output$$,$obj$$._id.toString());fs.existsSync($output$$)||fs.mkdirSync($output$$);$output$$=path.join($output$$,$file_name$$);convertVideo($extension$jscomp$3_input$jscomp$1_root$$,$output$$).catch($e$$=>{Logger.error("Can't convert video. Error:",$e$$)});$file_name$$=getDir("videos");$file_name$$=path.join($file_name$$,$obj$$._id.toString()); fs.existsSync($file_name$$)||fs.mkdirSync($file_name$$);try{await createThumnail($extension$jscomp$3_input$jscomp$1_root$$,"thumbnail.png",$file_name$$),$obj$$.file.thumbnail="thumbnail.png",await global.getModel("file").updateOne({_id:$obj$$._id},{file:$obj$$.file})}catch($e$$){Logger.error("[file] l\u1ed7i t\u1ea1o thumbnail cho viedeo",$e$$.message)}}}else Logger.info("file not exists",$obj$$)});onAfterCommit(async()=>{try{await processAndStoreFileWorker($obj$$)}catch($e$$){Logger.error("[ls-file] err:", $e$$)}});$fn$$(null,$obj$$)};$contr$$.route(function($router$$){$router$$.route("/:id_app/file/create-vector").post(async function($req$$,$res$$){if(!$req$$.user.current_app_info.appAdmin)return $res$$.status(400).send({error:"Ch\u1ec9 admin c\u1ee7a c\u00f4ng ty m\u1edbi c\u00f3 th\u1ec3 th\u1ef1c hi\u1ec7n thao t\u00e1c n\u00e0y"});const $condition$$=($req$$.body||{}).condition||{};$condition$$.id_app=$req$$.params.id_app;(await model.find($condition$$).lean()).forEach(async $file$$=>{try{await processAndStoreFileWorker($file$$), Logger.warn("[ls-file] \u0111\u00e3 x\u1eed l\u00fd xong file",$file$$.file)}catch($e$$){Logger.error("[ls-file] \u0111\u00e3 c\u00f3 l\u1ed7i khi x\u1eed l\u00fd file",$file$$.file,$e$$)}});$res$$.send({message:"Ch\u01b0\u01a1ng tr\u00ecnh \u0111ang th\u1ef1c hi\u1ec7n"})});$router$$.route("/:id_app/file/zip").post(async function($req$$,$res$$){try{var $i_ids$$=($req$$.body||{}).ids;if(!$i_ids$$||$i_ids$$.length===0)return $res$$.status(400).send({error:"Kh\u00f4ng c\u00f3 danh s\u00e1ch c\u00e1c id file c\u1ea7n zip"}); if($i_ids$$.find($id$$=>!global.mongoose.Types.ObjectId.isValid($id$$)))return $res$$.status(400).send({error:"C\u00f3 m\u1ed9t ho\u1eb7c nhi\u1ec1u id file kh\u00f4ng h\u1ee3p l\u1ec7"});let $files$$=await model.find({id_app:$req$$.user.current_id_app,_id:{$in:$i_ids$$}}).lean();$files$$=$files$$.filter($f$$=>!$f$$.file?.url);if($files$$.length===0)return $res$$.status(404).send({error:"Kh\u00f4ng c\u00f3 file n\u00e0o \u0111\u01b0\u1ee3c t\u00ecm th\u1ea5y"});if((await Promise.all($files$$.map($file$$=> hasPermission($req$$.user.email,$file$$)))).find($p$$=>!$p$$))return $res$$.status(400).send({error:"M\u1ed9t ho\u1eb7c nhi\u1ec1u file b\u1ea1n kh\u00f4ng c\u00f3 quy\u1ec1n truy c\u1eadp"});let $pathFiles$$=$files$$.map($file$$=>getPathFile($file$$));if($pathFiles$$.find($f$$=>!fs.existsSync($f$$)))return $res$$.status(404).send({error:"C\u00f3 m\u1ed9t ho\u1eb7c nhi\u1ec1u file kh\u00f4ng t\u1ed3n t\u1ea1i"});const $zip$$=new JSZip;for($i_ids$$=0;$i_ids$$<$pathFiles$$.length;$i_ids$$++){const $filePath$$= $pathFiles$$[$i_ids$$],$fileName$$=path.basename($filePath$$),$fileData$$=fs.readFileSync($filePath$$);$zip$$.file($fileName$$,$fileData$$)}$res$$.setHeader("Content-Type","application/zip");$res$$.setHeader("Content-Disposition",`attachment; filename="files_${Date.now()}.zip"`);$zip$$.generateNodeStream({type:"nodebuffer",streamFiles:!0}).pipe($res$$)}catch($err$$){Logger.error($err$$),$res$$.status(500).send({error:"L\u1ed7i khi t\u1ea1o file zip",detail:$err$$.message})}});$router$$.route("/:id_app/file/download/:id").get(function($req$$, $res$$){let $id$$=$req$$.params.id.split("-")[0];if(!global.mongoose.Types.ObjectId.isValid($id$$))return $res$$.status(400).send({error:"File ID kh\u00f4ng h\u1ee3p l\u1ec7"});let $size$$=($req$$.query.size||$req$$.query.resize||"FULLHD").toUpperCase(),$isFullSize$$=$size$$==="FULL";app.findOne({_id:$req$$.user.current_id_app}).lean().then(function($app_info$$){if(!$app_info$$)return $res$$.status(400).send("Kh\u00f4ng th\u1ec3 t\u1ea3i file n\u00e0y. Th\u00f4ng tin c\u00f4ng ty kh\u00f4ng t\u1ed3n t\u1ea1i"); model.findOne({_id:$id$$}).lean().then(async $rs$$=>{$rs$$&&$rs$$.file?permission.hasRight($rs$$.id_app,$req$$.user.email,$contr$$.module,"view",async function($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$,$originalName_outputFileName_permission$$){if(!$originalName_outputFileName_permission$$)return $res$$.status(403).send({error:$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$||"B\u1ea1n kh\u00f4ng c\u00f3 quy\u1ec1n truy c\u1eadp file n\u00e0y"}); if($rs$$.file.url)return $res$$.redirect($rs$$.file.url);var $_new_file_file_name$$=getPathFile($rs$$);$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$=$rs$$.file.extension.toLowerCase();if(fs.existsSync($_new_file_file_name$$))if($req$$.query.recache?$res$$.setHeader("Cache-Control","no-cache, no-store, must-revalidate"):$res$$.setHeader("Cache-Control","public, max-age=2592000"),"png jpg jpeg webp tiff heif avif gif jp2 jxl".split(" ").indexOf($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$)>= 0){$originalName_outputFileName_permission$$=$rs$$.file.originalname||`image.${$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$}`;$_new_file_file_name$$=await setWaterMark4Image($app_info$$,$_new_file_file_name$$,$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$,$req$$.query.recache);if($isFullSize$$)return $res$$.type($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$),$res$$.setHeader("Content-Disposition", `${$req$$.query.action==="download"?"attachment":"inline"}; filename*=UTF-8''${encodeURIComponent($originalName_outputFileName_permission$$)}`),$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$=fs.createReadStream($_new_file_file_name$$),$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.on("error",$err$$=>{Logger.error("Error streaming full image:",$err$$);$res$$.headersSent||$res$$.status(500).send("L\u1ed7i khi \u0111\u1ecdc file \u1ea3nh g\u1ed1c")}), $error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.pipe($res$$);$originalName_outputFileName_permission$$=`${$originalName_outputFileName_permission$$.substring(0,$originalName_outputFileName_permission$$.lastIndexOf("."))||$originalName_outputFileName_permission$$}.webp`;$res$$.setHeader("Content-Type","image/webp");$res$$.setHeader("Content-Disposition",`${$req$$.query.action==="download"?"attachment":"inline"}; filename*=UTF-8''${encodeURIComponent($originalName_outputFileName_permission$$)}`); let $_resize_conf$$=await configResizeImage($size$$,$_new_file_file_name$$,$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$,$req$$.query.recache);if($_resize_conf$$.exist)return $error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$=sharp($_resize_conf$$.file_name_resize,{failOnError:!1}),$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.on("error",$err$$=>{Logger.error("Stream error (cached file):",$err$$); $res$$.headersSent||$res$$.status(500).send("L\u1ed7i khi \u0111\u1ecdc file \u1ea3nh")}),$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.pipe($res$$);let $_gm$$=sharp($_new_file_file_name$$,{failOnError:!1});($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$=await $_gm$$.metadata())&&$_resize_conf$$.size&&$_resize_conf$$.size<$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.width&&$_resize_conf$$.size< $error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.height&&($_gm$$=$_gm$$.resize({width:$_resize_conf$$.size}).rotate());$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$&&$error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$.format!="webp"&&($_gm$$=$_gm$$.webp({lossless:!1,quality:70,nearLossless:!0}));$_gm$$.on("error",$err$$=>{Logger.error("Sharp processing error:",$err$$);$res$$.headersSent||$res$$.status(500).send("L\u1ed7i khi x\u1eed l\u00fd h\u00ecnh \u1ea3nh")}); $_resize_conf$$.cache&&setImmediate(()=>{$_gm$$.clone().toFile($_resize_conf$$.file_name_resize,$error$$=>{if($error$$)return Logger.error("save resize image:",$error$$.message);Logger.info("cache file",$_resize_conf$$.file_name_resize)})});$_gm$$.pipe($res$$)}else $req$$.query.thumbnail==1&&$rs$$.file.thumbnail?($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$=path.join(getDir("videos"),$rs$$._id.toString(),$rs$$.file.thumbnail),$res$$.download($error$jscomp$6_extension$jscomp$4_file_thumbnail_orgin_file_size_stream_stream$$, $rs$$.file.thumbnail)):$res$$.download($_new_file_file_name$$,$rs$$.file.originalname);else $res$$.status(400).send({error:"File n\u00e0y kh\u00f4ng t\u1ed3n t\u1ea1i"})},{data:$rs$$,obj:$rs$$,notNeedRight:!$rs$$.id_link&&!$rs$$.id_folder||$rs$$.shared}):$res$$.status(400).send({error:"Kh\u00f4ng t\u00ecm th\u1ea5y file n\u00e0y"})}).catch($e$$=>{$res$$.status(400).send($e$$)})}).catch($e$$=>{$res$$.status(400).send($e$$)})});$router$$.route("/:id_app/file/stream/:id/:file").get(function($req$$,$res$$){let $id$$= $req$$.params.id.split("-")[0];if(!global.mongoose.Types.ObjectId.isValid($id$$))return $res$$.status(400).send({error:"File ID kh\u00f4ng h\u1ee3p l\u1ec7"});app.findOne({_id:$req$$.user.current_id_app}).lean().then(function($app_info$$){if(!$app_info$$)return $res$$.status(400).send("Kh\u00f4ng th\u1ec3 stream file n\u00e0y. Th\u00f4ng tin c\u00f4ng ty kh\u00f4ng ch\u00ednh x\u00e1c");model.findOne({_id:$id$$}).lean().then(async $rs$$=>{$rs$$&&$rs$$.file?permission.hasRight($rs$$.id_app,$req$$.user.email, $contr$$.module,"view",async function($error$jscomp$8_file_name$jscomp$5_output$$,$file$jscomp$4_permission$jscomp$3_root$$){if(!$file$jscomp$4_permission$jscomp$3_root$$)return $res$$.status(403).send({error:$error$jscomp$8_file_name$jscomp$5_output$$||"B\u1ea1n kh\u00f4ng c\u00f3 quy\u1ec1n truy c\u1eadp file n\u00e0y"});if($rs$$.file.url)return $res$$.redirect($rs$$.file.url);$error$jscomp$8_file_name$jscomp$5_output$$=$rs$$.file.name;$file$jscomp$4_permission$jscomp$3_root$$=$req$$.params.file; $file$jscomp$4_permission$jscomp$3_root$$.endsWith(".ts")&&($error$jscomp$8_file_name$jscomp$5_output$$=$file$jscomp$4_permission$jscomp$3_root$$);$file$jscomp$4_permission$jscomp$3_root$$=getDir("videos");$error$jscomp$8_file_name$jscomp$5_output$$=path.join($file$jscomp$4_permission$jscomp$3_root$$,$rs$$._id.toString(),$error$jscomp$8_file_name$jscomp$5_output$$);if(fs.existsSync($error$jscomp$8_file_name$jscomp$5_output$$)){const $readStream$$=fs.createReadStream($error$jscomp$8_file_name$jscomp$5_output$$); $readStream$$.on("open",function(){$readStream$$.pipe($res$$)});$readStream$$.on("error",function($err$$){$res$$.end($err$$)})}else $res$$.status(400).send("File n\u00e0y kh\u00f4ng t\u1ed3n t\u1ea1i")},{data:$rs$$,obj:$rs$$,notNeedRight:!$rs$$.id_link&&!$rs$$.id_folder||$rs$$.shared}):$res$$.status(400).send("Kh\u00f4ng t\u00ecm th\u1ea5y file n\u00e0y")}).catch($e$$=>{$res$$.status(400).send($e$$)})}).catch($e$$=>{$res$$.status(400).send($e$$)})})})};