diff --git a/package.json b/package.json index 14526f5..f0a2bfd 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@types/sharp": "^0.28.0", "babel-polyfill": "^6.26.0", "express": "^4.17.1", + "fs-extra": "^9.1.0", "imghash": "^0.0.8", "mongoose": "^5.10.11", "react": "^17.0.1", diff --git a/src/server/interfaces/folder.interface.ts b/src/server/interfaces/folder.interface.ts index 61c3379..714ed11 100644 --- a/src/server/interfaces/folder.interface.ts +++ b/src/server/interfaces/folder.interface.ts @@ -22,6 +22,11 @@ export interface IFolderData { isLink: boolean; } +export interface IExplodedPathResponse { + exploded: Array; + fileName: string | Array; +} + export interface IComicBookCoverMetadata { name: string; path: string; diff --git a/src/server/route/routes/importComics.routes.ts b/src/server/route/routes/importComics.routes.ts index ea45483..461cda2 100644 --- a/src/server/route/routes/importComics.routes.ts +++ b/src/server/route/routes/importComics.routes.ts @@ -6,14 +6,15 @@ import { unzip, extractMetadataFromImage, unzipOne, + explodePath, } from "../../utils/fs.utils"; import { Request, Response } from "express"; router.route("/getComicCovers").get(async (req: Request, res: Response) => { const foo = await extractArchive({ - name: "Dante's Inferno 02 (2010) (noads) (Legion-CPS).cbr", + name: "Hellboy - The Chained Coffin and Others Ch3.cbr", extension: ".cbr", - containedIn: "comics/Dante's Inferno", + containedIn: "comics/Hellboy. The Chained Coffin and Others (1998) (of 1)", isFile: true, isLink: false, }); @@ -22,6 +23,7 @@ router.route("/getComicCovers").get(async (req: Request, res: Response) => { // ); // const foo = await unzipOne(); // const foo = await unzip("asd"); + // const foo = explodePath("Chapter Three/HELLBOY - The Chained Coffin - 069.jpg"); res.json({ jagan: "trupti", foo, diff --git a/src/server/utils/fs.utils.ts b/src/server/utils/fs.utils.ts index e8b751f..da6923e 100644 --- a/src/server/utils/fs.utils.ts +++ b/src/server/utils/fs.utils.ts @@ -2,10 +2,14 @@ import { default as unzipper } from "unzipper"; const sharp = require("sharp"); const unrarer = require("node-unrar-js"); const Walk = require("@root/walk"); +const mkdirp = require("mkdirp"); +const fse = require("fs-extra"); import fs from "fs"; import path from "path"; +import _ from "lodash"; import { logger } from "./logger.utils"; import { + IExplodedPathResponse, IExtractComicBookCoverErrorResponse, IExtractedComicBookCoverFile, IExtractionOptions, @@ -15,12 +19,13 @@ import { export const unrar = async ( extractionOptions: IExtractionOptions, ): Promise< - IExtractedComicBookCoverFile | IExtractComicBookCoverErrorResponse + | IExtractedComicBookCoverFile + | IExtractedComicBookCoverFile[] + | IExtractComicBookCoverErrorResponse > => { const comicCoversTargetPath = - extractionOptions.sourceFolder + - extractionOptions.targetComicCoversFolder + - "/"; + extractionOptions.sourceFolder + extractionOptions.targetComicCoversFolder; + const buf = Uint8Array.from( fs.readFileSync( extractionOptions.folderDetails.containedIn + @@ -63,34 +68,48 @@ export const unrar = async ( ); }); case "all": + const comicBookCoverFiles: IExtractedComicBookCoverFile[] = []; const files = extractor.extract({}); - const extractedFiles = [...files.files]; - console.log(extractedFiles); - // logger.info(`Attempting to write ${extractedFiles.fileHeader.name}`); + return new Promise(async (resolve, reject) => { + for (const file of extractedFiles) { + logger.info(`Attempting to write ${file.fileHeader.name}`); + const fileBuffer = file.extraction; + const pathFragments = explodePath(file.fileHeader.name); + const targetPath = + comicCoversTargetPath + "/" + pathFragments.exploded.join("/"); + fse.ensureDir(targetPath, (err) => { + if (err) { + console.log(err); + } else { + fs.writeFile( + targetPath + "/" + pathFragments.fileName, + fileBuffer, + (err) => { + if (err) { + logger.error(err); + reject(err); + } else { + logger.info( + `The file ${file.fileHeader.name} was saved to disk.`, + ); + } + }, + ); + comicBookCoverFiles.push({ + name: `${file.fileHeader.name}`, + path: targetPath, + fileSize: file.fileHeader.packSize, + }); + } + }); + } + console.log(comicBookCoverFiles); + resolve(comicBookCoverFiles); + }); - // return new Promise((resolve, reject) => { - // fs.writeFile( - // comicCoversTargetPath + extractedFiles.fileHeader.name, - // filesBuffer, - // (err) => { - // if (err) { - // logger.error("Failed to write file", err); - // reject(err); - // } else { - // logger.info( - // `The file ${extractedFile.fileHeader.name} was saved to disk.`, - // ); - // resolve({ - // name: `${extractedFile.fileHeader.name}`, - // path: comicCoversTargetPath, - // fileSize: extractedFile.fileHeader.packSize, - // }); - // } - // }, - // ); - // }); + // }); default: return { message: "File format not supported, yet.", @@ -206,3 +225,14 @@ export const walkFolder = async (folder: string): Promise => { }); return result; }; + +export const explodePath = (filePath: string): IExplodedPathResponse => { + const exploded = filePath.split("/"); + const fileName = _.remove(exploded, (item) => { + return _.indexOf(exploded, item) === exploded.length - 1; + }); + return { + exploded, + fileName, + }; +}; diff --git a/yarn.lock b/yarn.lock index 54ae2b4..79c9305 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2547,6 +2547,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -5450,6 +5455,16 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^2.0.0, fs-minipass@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -5805,7 +5820,7 @@ got@^8.3.1: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.10, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6: +graceful-fs@^4.1.10, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== @@ -7458,6 +7473,15 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -11940,6 +11964,11 @@ universalify@^0.1.2: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"