🔧 Adding methods for comicinfo.xml detection/extraction
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -70,3 +70,4 @@ userdata/
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
erl_crash.dump
|
erl_crash.dump
|
||||||
temp
|
temp
|
||||||
|
test
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import { ServiceBroker } from "moleculer";
|
|
||||||
import DbService from "moleculer-db";
|
|
||||||
import {DbMixin} from "../../../mixins/db.mixin";
|
|
||||||
|
|
||||||
describe("Test DB mixin", () => {
|
|
||||||
|
|
||||||
describe("Test schema generator", () => {
|
|
||||||
const broker = new ServiceBroker({ logger: false, cacher: "Memory" });
|
|
||||||
|
|
||||||
beforeAll(() => broker.start());
|
|
||||||
afterAll(() => broker.stop());
|
|
||||||
|
|
||||||
it("check schema properties", async () => {
|
|
||||||
const schema = new DbMixin("my-collection").start();
|
|
||||||
|
|
||||||
expect(schema.mixins).toEqual([DbService]);
|
|
||||||
// @ts-ignore
|
|
||||||
expect(schema.adapter).toBeInstanceOf(DbService.MemoryAdapter);
|
|
||||||
expect(schema.started).toBeDefined();
|
|
||||||
expect(schema.events["cache.clean.my-collection"]).toBeInstanceOf(Function);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("check cache event handler", async () => {
|
|
||||||
jest.spyOn(broker.cacher, "clean");
|
|
||||||
|
|
||||||
const schema = new DbMixin("my-collection").start();
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await schema.events["cache.clean.my-collection"].call({ broker, fullName: "my-service" });
|
|
||||||
|
|
||||||
expect(broker.cacher.clean).toBeCalledTimes(1);
|
|
||||||
expect(broker.cacher.clean).toBeCalledWith("my-service.*");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Check service started handler", () => {
|
|
||||||
|
|
||||||
it("should not call seedDB method", async () => {
|
|
||||||
const schema = new DbMixin("my-collection").start();
|
|
||||||
|
|
||||||
schema.adapter.count = jest.fn(async () => 10);
|
|
||||||
const seedDBFn = jest.fn();
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await schema.started.call({ broker, logger: broker.logger, adapter: schema.adapter, seedDB: seedDBFn });
|
|
||||||
|
|
||||||
expect(schema.adapter.count).toBeCalledTimes(1);
|
|
||||||
expect(schema.adapter.count).toBeCalledWith();
|
|
||||||
|
|
||||||
expect(seedDBFn).toBeCalledTimes(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should call seedDB method", async () => {
|
|
||||||
const schema = new DbMixin("my-collection").start();
|
|
||||||
|
|
||||||
schema.adapter.count = jest.fn(async () => 0);
|
|
||||||
const seedDBFn = jest.fn();
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await schema.started.call({ broker, logger: broker.logger, adapter: schema.adapter, seedDB: seedDBFn });
|
|
||||||
|
|
||||||
expect(schema.adapter.count).toBeCalledTimes(2);
|
|
||||||
expect(schema.adapter.count).toBeCalledWith();
|
|
||||||
|
|
||||||
expect(seedDBFn).toBeCalledTimes(1);
|
|
||||||
expect(seedDBFn).toBeCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should broadcast a cache clear event", async () => {
|
|
||||||
const schema = new DbMixin("my-collection").start();
|
|
||||||
|
|
||||||
const ctx = {
|
|
||||||
broadcast: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await schema.methods.entityChanged(null, null, ctx);
|
|
||||||
|
|
||||||
expect(ctx.broadcast).toBeCalledTimes(1);
|
|
||||||
expect(ctx.broadcast).toBeCalledWith("cache.clean.my-collection");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import { Errors, ServiceBroker} from "moleculer";
|
|
||||||
import TestService from "../../../services/greeter.service";
|
|
||||||
|
|
||||||
describe("Test 'greeter' service", () => {
|
|
||||||
const broker = new ServiceBroker({ logger: false });
|
|
||||||
broker.createService(TestService);
|
|
||||||
|
|
||||||
beforeAll(() => broker.start());
|
|
||||||
afterAll(() => broker.stop());
|
|
||||||
|
|
||||||
describe("Test 'greeter.hello' action", () => {
|
|
||||||
|
|
||||||
it("should return with 'Hello Moleculer'", async () => {
|
|
||||||
const res = await broker.call("greeter.hello");
|
|
||||||
expect(res).toBe("Hello Moleculer");
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test 'greeter.welcome' action", () => {
|
|
||||||
|
|
||||||
it("should return with 'Welcome'", async () => {
|
|
||||||
const res = await broker.call("greeter.welcome", { name: "Adam" });
|
|
||||||
expect(res).toBe("Welcome, Adam");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should reject an ValidationError", async () => {
|
|
||||||
expect.assertions(1);
|
|
||||||
try {
|
|
||||||
await broker.call("greeter.welcome");
|
|
||||||
} catch (err) {
|
|
||||||
expect(err).toBeInstanceOf(Errors.ValidationError);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -44,13 +44,13 @@ import {
|
|||||||
|
|
||||||
import { constructPaths, explodePath, walkFolder } from "../utils/file.utils";
|
import { constructPaths, explodePath, walkFolder } from "../utils/file.utils";
|
||||||
import { resizeImage } from "./imagetransformation.utils";
|
import { resizeImage } from "./imagetransformation.utils";
|
||||||
import { isNil } from "lodash";
|
import { isNil, isUndefined } from "lodash";
|
||||||
|
import { convertXMLToJSON } from "./xml.utils";
|
||||||
const sevenZip = require("7zip-min");
|
const sevenZip = require("7zip-min");
|
||||||
const unrar = require("node-unrar-js");
|
const unrar = require("node-unrar-js");
|
||||||
const { Calibre } = require("node-calibre");
|
const { Calibre } = require("node-calibre");
|
||||||
import { USERDATA_DIRECTORY, COMICS_DIRECTORY } from "../constants/directories";
|
import { USERDATA_DIRECTORY, COMICS_DIRECTORY } from "../constants/directories";
|
||||||
|
|
||||||
|
|
||||||
export const extractCoverFromFile2 = async (
|
export const extractCoverFromFile2 = async (
|
||||||
fileObject: any
|
fileObject: any
|
||||||
): Promise<IExtractedComicBookCoverFile> => {
|
): Promise<IExtractedComicBookCoverFile> => {
|
||||||
@@ -63,44 +63,46 @@ export const extractCoverFromFile2 = async (
|
|||||||
// 1. Check for process.env.COMICS_DIRECTORY and process.env.USERDATA_DIRECTORY
|
// 1. Check for process.env.COMICS_DIRECTORY and process.env.USERDATA_DIRECTORY
|
||||||
if (!isNil(USERDATA_DIRECTORY)) {
|
if (!isNil(USERDATA_DIRECTORY)) {
|
||||||
// 2. Create the directory to which the cover image will be extracted
|
// 2. Create the directory to which the cover image will be extracted
|
||||||
console.info("Attempting to create target directory for cover extraction...");
|
console.info(
|
||||||
|
"Attempting to create target directory for cover extraction..."
|
||||||
|
);
|
||||||
const directoryOptions = {
|
const directoryOptions = {
|
||||||
mode: 0o2775,
|
mode: 0o2775,
|
||||||
};
|
};
|
||||||
|
const extension = path.extname(filePath);
|
||||||
const fileNameWithExtension = path.basename(filePath);
|
const fileNameWithExtension = path.basename(filePath);
|
||||||
const fileNameWithoutExtension = path.basename(filePath, path.extname(filePath));
|
const fileNameWithoutExtension = path.basename(
|
||||||
|
filePath,
|
||||||
|
path.extname(filePath)
|
||||||
|
);
|
||||||
const targetDirectory = `${USERDATA_DIRECTORY}/covers/${fileNameWithoutExtension}`;
|
const targetDirectory = `${USERDATA_DIRECTORY}/covers/${fileNameWithoutExtension}`;
|
||||||
|
|
||||||
await fse.ensureDir(targetDirectory, directoryOptions);
|
await fse.ensureDir(targetDirectory, directoryOptions);
|
||||||
console.info(`%s was created.`, targetDirectory);
|
console.info(`%s was created.`, targetDirectory);
|
||||||
|
|
||||||
|
// 2.1 look for comicinfo.xml
|
||||||
|
extractFileFromArchive(filePath, targetDirectory, extension);
|
||||||
|
|
||||||
// 3. extract the cover
|
// 3. extract the cover
|
||||||
console.info(`Starting cover extraction...`);
|
console.info(`Starting cover extraction...`);
|
||||||
let result: string;
|
let result: string;
|
||||||
const targetCoverImageFilePath = path.resolve(
|
const targetCoverImageFilePath = path.resolve(
|
||||||
targetDirectory +
|
targetDirectory + "/" + fileNameWithoutExtension + "_cover.jpg"
|
||||||
"/" +
|
|
||||||
fileNameWithoutExtension +
|
|
||||||
"_cover.jpg"
|
|
||||||
);
|
);
|
||||||
const ebookMetaPath = process.env.CALIBRE_EBOOK_META_PATH
|
const ebookMetaPath = process.env.CALIBRE_EBOOK_META_PATH
|
||||||
? `${process.env.CALIBRE_EBOOK_META_PATH}`
|
? `${process.env.CALIBRE_EBOOK_META_PATH}`
|
||||||
: `ebook-meta`;
|
: `ebook-meta`;
|
||||||
result = await calibre.run(
|
result = await calibre.run(ebookMetaPath, [filePath], {
|
||||||
ebookMetaPath,
|
|
||||||
[filePath],
|
|
||||||
{
|
|
||||||
getCover: targetCoverImageFilePath,
|
getCover: targetCoverImageFilePath,
|
||||||
}
|
});
|
||||||
|
console.info(
|
||||||
|
`ebook-meta ran with the following result: %o`,
|
||||||
|
result
|
||||||
);
|
);
|
||||||
console.info(`ebook-meta ran with the following result: %o`, result)
|
|
||||||
|
|
||||||
// 4. create rendition path
|
// 4. create rendition path
|
||||||
const renditionPath =
|
const renditionPath =
|
||||||
targetDirectory+
|
targetDirectory + "/" + fileNameWithoutExtension + "_275px.jpg";
|
||||||
"/" +
|
|
||||||
fileNameWithoutExtension +
|
|
||||||
"_275px.jpg";
|
|
||||||
|
|
||||||
// 5. resize image
|
// 5. resize image
|
||||||
await resizeImage(
|
await resizeImage(
|
||||||
@@ -112,7 +114,7 @@ export const extractCoverFromFile2 = async (
|
|||||||
name: fileNameWithoutExtension,
|
name: fileNameWithoutExtension,
|
||||||
filePath,
|
filePath,
|
||||||
fileSize,
|
fileSize,
|
||||||
extension: path.extname(filePath),
|
extension,
|
||||||
cover: {
|
cover: {
|
||||||
filePath: path.relative(process.cwd(), renditionPath),
|
filePath: path.relative(process.cwd(), renditionPath),
|
||||||
},
|
},
|
||||||
@@ -170,3 +172,69 @@ export const unrarArchive = async (
|
|||||||
console.info(`${error}`);
|
console.info(`${error}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const extractFileFromRar = async (
|
||||||
|
filePath: string,
|
||||||
|
fileToExtract: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
// Read the archive file into a typedArray
|
||||||
|
const fileBuffer = await fse
|
||||||
|
.readFile(filePath)
|
||||||
|
.catch((err) => console.error("Failed to read file", err));
|
||||||
|
const extractor = await unrar.createExtractorFromData({
|
||||||
|
data: fileBuffer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const list = extractor.getFileList();
|
||||||
|
const listArcHeader = list.arcHeader; // archive header
|
||||||
|
const fileHeaders = [...list.fileHeaders]; // load the file headers
|
||||||
|
|
||||||
|
const extracted = extractor.extract({ files: ["ComicInfo.xml"] });
|
||||||
|
const files = [...extracted.files]; //load the files
|
||||||
|
console.log("asdas", files[0]);
|
||||||
|
if(!isUndefined(files[0])) {
|
||||||
|
const trin = String.fromCharCode.apply(null, files[0].extraction)
|
||||||
|
const foo = await convertXMLToJSON(trin);
|
||||||
|
console.log(foo);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const extractFileFromZip = async (
|
||||||
|
filePath: string,
|
||||||
|
outputDirectory: string
|
||||||
|
) => {
|
||||||
|
const foo = sevenZip.cmd(
|
||||||
|
["e", path.resolve(filePath), outputDirectory, "*.xml"],
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return foo;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const extractFileFromArchive = async (
|
||||||
|
filePath: string,
|
||||||
|
outputDirectory: string,
|
||||||
|
extension: string
|
||||||
|
) => {
|
||||||
|
console.log(extension);
|
||||||
|
switch (extension) {
|
||||||
|
case ".cbz":
|
||||||
|
console.log("cbz");
|
||||||
|
extractFileFromZip(filePath, outputDirectory);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".cbr":
|
||||||
|
console.log("cbr");
|
||||||
|
extractFileFromRar(filePath, outputDirectory);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.log("error na rao");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ export const convertXMLToJSON = (xmlPayload) => {
|
|||||||
trim: true,
|
trim: true,
|
||||||
normalizeTags: true,
|
normalizeTags: true,
|
||||||
});
|
});
|
||||||
const xml = fs.readFileSync(__dirname + "/comicinfo.xml", "utf8");
|
|
||||||
return parser
|
return parser
|
||||||
.parseStringPromise(xml)
|
.parseStringPromise(xmlPayload)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
return result;
|
return result;
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user