From 267386ec94ab74a7a0fc044be3abfd7ec4857c07 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Tue, 11 May 2021 09:58:14 -0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=82=EF=B8=8F=20Pruned=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/actions/fileops.actions.tsx | 2 - src/client/workers/extractCovers.worker.ts | 6 +- src/server/index.ts | 2 - src/server/utils/fs.utils.ts | 331 --------------------- 4 files changed, 2 insertions(+), 339 deletions(-) delete mode 100644 src/server/utils/fs.utils.ts diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index 25937be..70e68d5 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -1,8 +1,6 @@ import axios from "axios"; import fetch, { Response } from "node-fetch"; import { - IExtractComicBookCoverErrorResponse, - IExtractedComicBookCoverFile, IExtractionOptions, IFolderData, } from "../../server/interfaces/folder.interface"; diff --git a/src/client/workers/extractCovers.worker.ts b/src/client/workers/extractCovers.worker.ts index 14abebd..9668ec9 100644 --- a/src/client/workers/extractCovers.worker.ts +++ b/src/client/workers/extractCovers.worker.ts @@ -4,12 +4,10 @@ import { } from "../actions/fileops.actions"; import { IExtractedComicBookCoverFile } from "../../server/interfaces/folder.interface"; const ndjsonStream = require("can-ndjson-stream"); -import fetch from "node-fetch"; -import { API_BASE_URI } from "../constants/endpoints"; export const greet = async ( path: string, -): Promise => { +): Promise => { const targetOptions = { sourceFolder: path, extractTarget: "cover", @@ -32,7 +30,7 @@ export const greet = async ( ); const reader = await ndjsonStream(fetchedResource.body).getReader(); - reader.read().then(function process({ done, value }) { + return reader.read().then(function process({ done, value }) { if (done) { console.log("done"); return; diff --git a/src/server/index.ts b/src/server/index.ts index 66b3867..52d8928 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,7 +1,6 @@ import express, { Request, Response, Router, Express } from "express"; import bodyParser from "body-parser"; import router from "./route"; -import { default as paginate } from "express-paginate"; // call express const app: Express = express(); // define our app using express @@ -9,7 +8,6 @@ const app: Express = express(); // define our app using express // configure app to use bodyParser for // Getting data from body of requests app.use(bodyParser.json()); -app.use(paginate.middleware(10, 50)); app.use(bodyParser.urlencoded({ extended: true })); diff --git a/src/server/utils/fs.utils.ts b/src/server/utils/fs.utils.ts deleted file mode 100644 index 509da4c..0000000 --- a/src/server/utils/fs.utils.ts +++ /dev/null @@ -1,331 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2021 Rishi Ghan - * - The MIT License (MIT) - -Copyright (c) 2021 Rishi Ghan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -/* - * Revision History: - * Initial: 2021/05/04 Rishi Ghan - */ - -const sharp = require("sharp"); -const unrarer = require("node-unrar-js"); -const Walk = require("@root/walk"); -const fse = require("fs-extra"); - -import { default as unzipper } from "unzipper"; -import _ from "lodash"; -import { createReadStream, createWriteStream } from "fs"; -const { writeFile, readFile } = require("fs").promises; -import path from "path"; -import { each, isEmpty, map, remove, indexOf } from "lodash"; -import { logger } from "./logger.utils"; -import { - IExplodedPathResponse, - IExtractComicBookCoverErrorResponse, - IExtractedComicBookCoverFile, - IExtractionOptions, - IFolderData, -} from "../interfaces/folder.interface"; - -export const unrar = async ( - extractionOptions: IExtractionOptions, - walkedFolder: IFolderData, -): Promise< - | IExtractedComicBookCoverFile - | IExtractedComicBookCoverFile[] - | IExtractComicBookCoverErrorResponse -> => { - const paths = constructPaths(extractionOptions, walkedFolder); - const directoryOptions = { - mode: 0o2775, - }; - const fileBuffer = await readFile(paths.inputFilePath).catch((err) => - console.error("Failed to read file", err), - ); - try { - await fse.ensureDir(paths.targetPath, directoryOptions); - logger.info(`${paths.targetPath} was created.`); - } catch (error) { - logger.error(`${error}: Couldn't create directory.`); - } - - const extractor = await unrarer.createExtractorFromData({ data: fileBuffer }); - - switch (extractionOptions.extractTarget) { - case "cover": - return new Promise(async (resolve, reject) => { - try { - let fileNameToExtract = ""; - const list = extractor.getFileList(); - const fileHeaders = [...list.fileHeaders]; - each(fileHeaders, async (fileHeader) => { - const fileName = explodePath(fileHeader.name).fileName; - if ( - fileName !== "" && - fileHeader.flags.directory === false && - isEmpty(fileNameToExtract) - ) { - logger.info(`Attempting to write ${fileHeader.name}`); - fileNameToExtract = fileHeader.name; - const file = extractor.extract({ files: [fileHeader.name] }); - const extractedFile = [...file.files][0]; - const fileArrayBuffer = extractedFile.extraction; - await writeFile( - paths.targetPath + "/" + fileName, - fileArrayBuffer, - ); - resolve({ - name: `${fileName}`, - path: paths.targetPath, - fileSize: fileHeader.packSize, - }); - } - }); - } catch (error) { - logger.error(`${error}: Couldn't write file.`); - reject(error); - } - }); - - case "all": - return new Promise(async (resolve, reject) => { - try { - const files = extractor.extract({}); - const extractedFiles = [...files.files]; - const comicBookCoverFiles: IExtractedComicBookCoverFile[] = []; - for (const file of extractedFiles) { - logger.info(`Attempting to write ${file.fileHeader.name}`); - const fileBuffer = file.extraction; - const fileName = explodePath(file.fileHeader.name).fileName; - - if (fileName !== "" && file.fileHeader.flags.directory === false) { - await writeFile(paths.targetPath + "/" + fileName, fileBuffer); - } - comicBookCoverFiles.push({ - name: `${file.fileHeader.name}`, - path: paths.targetPath, - fileSize: file.fileHeader.packSize, - }); - } - resolve(_.flatten(comicBookCoverFiles)); - } catch (error) { - resolve({ - message: `${error}`, - errorCode: "500", - data: walkedFolder.name, - }); - } - }); - - default: - return { - message: "File format not supported, yet.", - errorCode: "90", - data: "asda", - }; - } -}; - -export const unzip = async ( - extractionOptions: IExtractionOptions, - walkedFolder: IFolderData, -): Promise< - | IExtractedComicBookCoverFile[] - | IExtractedComicBookCoverFile - | IExtractComicBookCoverErrorResponse -> => { - const directoryOptions = { - mode: 0o2775, - }; - const paths = constructPaths(extractionOptions, walkedFolder); - - try { - await fse.ensureDir(paths.targetPath, directoryOptions); - logger.info(`${paths.targetPath} was created or already exists.`); - } catch (error) { - logger.error(`${error} Couldn't create directory.`); - } - - const extractedFiles: IExtractedComicBookCoverFile[] = []; - const zip = createReadStream(paths.inputFilePath).pipe( - unzipper.Parse({ forceStream: true }), - ); - for await (const entry of zip) { - const fileName = explodePath(entry.path).fileName; - const size = entry.vars.uncompressedSize; - if ( - extractedFiles.length === 1 && - extractionOptions.extractTarget === "cover" - ) { - break; - } - if (fileName !== "" && entry.type !== "Directory") { - logger.info(`Attempting to write ${fileName}`); - entry.pipe(createWriteStream(paths.targetPath + "/" + fileName)); - extractedFiles.push({ - name: fileName, - fileSize: size, - path: paths.targetPath, - }); - } - entry.autodrain(); - } - - return new Promise(async (resolve, reject) => { - logger.info(""); - resolve(_.flatten(extractedFiles)); - }); -}; - -export const extractArchive = async ( - extractionOptions: IExtractionOptions, - walkedFolder: IFolderData, -): Promise< - | IExtractedComicBookCoverFile - | IExtractedComicBookCoverFile[] - | IExtractComicBookCoverErrorResponse -> => { - switch (walkedFolder.extension) { - case ".cbz": - return await unzip(extractionOptions, walkedFolder); - case ".cbr": - return await unrar(extractionOptions, walkedFolder); - default: - return { - message: "File format not supported, yet.", - errorCode: "90", - data: `${extractionOptions}`, - }; - } -}; - -export const getCovers = async ( - options: IExtractionOptions, - walkedFolders: Array, -): Promise< - | IExtractedComicBookCoverFile - | IExtractComicBookCoverErrorResponse - | IExtractedComicBookCoverFile[] - | ( - | IExtractedComicBookCoverFile - | IExtractComicBookCoverErrorResponse - | IExtractedComicBookCoverFile[] - )[] - | IExtractComicBookCoverErrorResponse -> => { - switch (options.extractionMode) { - case "bulk": - const extractedDataPromises = map(walkedFolders, async (folder) => { - return await extractArchive(options, folder); - }); - return Promise.all(extractedDataPromises).then((data) => _.flatten(data)); - case "single": - return await extractArchive(options, walkedFolders[0]); - default: - logger.error("Unknown extraction mode selected."); - return { - message: "Unknown extraction mode selected.", - errorCode: "90", - data: `${options}`, - }; - } -}; - -export const walkFolder = async (folder: string): Promise => { - const result: IFolderData[] = []; - let walkResult: IFolderData = { - name: "", - extension: "", - containedIn: "", - isFile: false, - isLink: true, - }; - - const walk = Walk.create({ sort: filterOutDotFiles }); - await walk(folder, async (err, pathname, dirent) => { - if (err) { - logger.error("Failed to lstat directory", { error: err }); - return false; - } - if ([".cbz", ".cbr"].includes(path.extname(dirent.name))) { - walkResult = { - name: path.basename(dirent.name, path.extname(dirent.name)), - extension: path.extname(dirent.name), - containedIn: path.dirname(pathname), - isFile: dirent.isFile(), - isLink: dirent.isSymbolicLink(), - }; - logger.info( - `Scanned ${dirent.name} contained in ${path.dirname(pathname)}`, - ); - result.push(walkResult); - } - }); - return result; -}; - -export const explodePath = (filePath: string): IExplodedPathResponse => { - const exploded = filePath.split("/"); - const fileName = remove(exploded, (item) => { - return indexOf(exploded, item) === exploded.length - 1; - }).join(""); - - return { - exploded, - fileName, - }; -}; - -const constructPaths = ( - extractionOptions: IExtractionOptions, - walkedFolder: IFolderData, -) => { - return { - targetPath: - extractionOptions.targetExtractionFolder + "/" + walkedFolder.name, - inputFilePath: - walkedFolder.containedIn + - "/" + - walkedFolder.name + - walkedFolder.extension, - }; -}; - -export const extractMetadataFromImage = async ( - imageFilePath: string, -): Promise => { - const image = await sharp(imageFilePath) - .metadata() - .then(function (metadata) { - return metadata; - }); - return image; -}; - -const filterOutDotFiles = (entities) => { - return entities.filter((ent) => !ent.name.startsWith(".")); -};