🤼♀️ ES-powered issue detection feature
This commit is contained in:
14
package-lock.json
generated
14
package-lock.json
generated
@@ -46,7 +46,7 @@
|
|||||||
"node-unrar-js": "^1.0.2",
|
"node-unrar-js": "^1.0.2",
|
||||||
"sharp": "^0.28.3",
|
"sharp": "^0.28.3",
|
||||||
"socket.io": "^4.4.0",
|
"socket.io": "^4.4.0",
|
||||||
"threetwo-ui-typings": "^1.0.11",
|
"threetwo-ui-typings": "^1.0.12",
|
||||||
"through2": "^4.0.2",
|
"through2": "^4.0.2",
|
||||||
"unrar": "^0.2.0",
|
"unrar": "^0.2.0",
|
||||||
"xml2js": "^0.4.23"
|
"xml2js": "^0.4.23"
|
||||||
@@ -11247,9 +11247,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/threetwo-ui-typings": {
|
"node_modules/threetwo-ui-typings": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/threetwo-ui-typings/-/threetwo-ui-typings-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/threetwo-ui-typings/-/threetwo-ui-typings-1.0.12.tgz",
|
||||||
"integrity": "sha512-jRI1rUttoJDqsKFUPd4MM56NErftl2NSEo8MkeqllOtVf38Wy+wVvAT+OW6AoSguA5cLxSpOiA25c31FWjOvOw==",
|
"integrity": "sha512-lKADNpD2Oa3Wmf6tdZhaPSNfIFa0KtstsZLE0yalTjqKmtQZM7Ct2OnlCkH7aonDuVn+jgcRMwkcP9krCqa2fw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": "^4.3.2"
|
"typescript": "^4.3.2"
|
||||||
}
|
}
|
||||||
@@ -20540,9 +20540,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"threetwo-ui-typings": {
|
"threetwo-ui-typings": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/threetwo-ui-typings/-/threetwo-ui-typings-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/threetwo-ui-typings/-/threetwo-ui-typings-1.0.12.tgz",
|
||||||
"integrity": "sha512-jRI1rUttoJDqsKFUPd4MM56NErftl2NSEo8MkeqllOtVf38Wy+wVvAT+OW6AoSguA5cLxSpOiA25c31FWjOvOw==",
|
"integrity": "sha512-lKADNpD2Oa3Wmf6tdZhaPSNfIFa0KtstsZLE0yalTjqKmtQZM7Ct2OnlCkH7aonDuVn+jgcRMwkcP9krCqa2fw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"typescript": "^4.3.2"
|
"typescript": "^4.3.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ export default class ApiService extends Service {
|
|||||||
console.log("Client connected via websocket!");
|
console.log("Client connected via websocket!");
|
||||||
|
|
||||||
client.on("action", async (action) => {
|
client.on("action", async (action) => {
|
||||||
console.log("ACCCCCTION", action);
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "LS_IMPORT":
|
case "LS_IMPORT":
|
||||||
// 1. Send task to queue
|
// 1. Send task to queue
|
||||||
|
console.log(`Recieved ${action.type} event.`)
|
||||||
await this.broker.call(
|
await this.broker.call(
|
||||||
"import.newImport",
|
"import.newImport",
|
||||||
action.data,
|
action.data,
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ SOFTWARE.
|
|||||||
* Initial: 2022/01/28 Rishi Ghan
|
* Initial: 2022/01/28 Rishi Ghan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
import { isNil, isUndefined, map } from "lodash";
|
import { isNil, isUndefined, map } from "lodash";
|
||||||
import {
|
import {
|
||||||
@@ -395,7 +393,7 @@ export default class ImportService extends Service {
|
|||||||
{
|
{
|
||||||
$group: {
|
$group: {
|
||||||
_id: "$sourcedMetadata.comicvine.volume.id",
|
_id: "$sourcedMetadata.comicvine.volume.id",
|
||||||
comicObjectId : { $first: "$_id" },
|
comicObjectId: { $first: "$_id" },
|
||||||
volumeURI: {
|
volumeURI: {
|
||||||
$last: "$sourcedMetadata.comicvine.volume.api_detail_url",
|
$last: "$sourcedMetadata.comicvine.volume.api_detail_url",
|
||||||
},
|
},
|
||||||
@@ -416,17 +414,21 @@ export default class ImportService extends Service {
|
|||||||
volumesMetadata = map(volumes, async (volume) => {
|
volumesMetadata = map(volumes, async (volume) => {
|
||||||
console.log(volume);
|
console.log(volume);
|
||||||
if (!isNil(volume.volumeURI)) {
|
if (!isNil(volume.volumeURI)) {
|
||||||
const volumeMetadata = await ctx.call("comicvine.getVolumes", {
|
const volumeMetadata = await ctx.call(
|
||||||
volumeURI: volume.volumeURI,
|
"comicvine.getVolumes",
|
||||||
data: {
|
{
|
||||||
format: "json",
|
volumeURI: volume.volumeURI,
|
||||||
fieldList:
|
data: {
|
||||||
"id,name,deck,api_detail_url",
|
format: "json",
|
||||||
limit: "1",
|
fieldList:
|
||||||
offset: "0",
|
"id,name,deck,api_detail_url",
|
||||||
},
|
limit: "1",
|
||||||
});
|
offset: "0",
|
||||||
volumeMetadata["comicObjectId"] = volume.comicObjectId;
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
volumeMetadata["comicObjectId"] =
|
||||||
|
volume.comicObjectId;
|
||||||
return volumeMetadata;
|
return volumeMetadata;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -434,21 +436,23 @@ export default class ImportService extends Service {
|
|||||||
return Promise.all(volumesMetadata);
|
return Promise.all(volumesMetadata);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getIssuesForSeries: {
|
findIssuesForSeriesInLibrary: {
|
||||||
rest: "POST /getIssuesForSeries",
|
rest: "POST /findIssuesForSeriesInLibrary",
|
||||||
params: {},
|
params: {},
|
||||||
handler: async (ctx:Context<{ comicObjectID: string }>) => {
|
handler: async (
|
||||||
// 1. Query mongo to get issues for a given volume
|
ctx: Context<{ comicObjectID: string }>
|
||||||
|
) => {
|
||||||
|
// 1. Query mongo to get the comic document by its _id
|
||||||
const comicBookDetails: any = await this.broker.call(
|
const comicBookDetails: any = await this.broker.call(
|
||||||
"import.getComicBookById",
|
"import.getComicBookById",
|
||||||
{ id: ctx.params.comicObjectID }
|
{ id: ctx.params.comicObjectID }
|
||||||
);
|
);
|
||||||
|
|
||||||
// 2. Query CV and get metadata for them
|
// 2. Query CV and get metadata for them
|
||||||
comicBookDetails.sourcedMetadata.comicvine.volumeInformation.issues.map(
|
const foo =
|
||||||
async (issue: any, idx: any) => {
|
await comicBookDetails.sourcedMetadata.comicvine.volumeInformation.issues.map(
|
||||||
const issueMetadata: any =
|
async (issue: any, idx: any) => {
|
||||||
await axios.request({
|
const metadata: any = await axios.request({
|
||||||
url: `${issue.api_detail_url}?api_key=${process.env.COMICVINE_API_KEY}`,
|
url: `${issue.api_detail_url}?api_key=${process.env.COMICVINE_API_KEY}`,
|
||||||
params: {
|
params: {
|
||||||
resources: "issues",
|
resources: "issues",
|
||||||
@@ -459,29 +463,34 @@ export default class ImportService extends Service {
|
|||||||
"User-Agent": "ThreeTwo",
|
"User-Agent": "ThreeTwo",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const metadata =
|
const issueMetadata = metadata.data.results;
|
||||||
issueMetadata.data.results;
|
|
||||||
|
|
||||||
// 2a. Query Mongo with Elastic to see if a match exists for a given issue's name, and issue number
|
|
||||||
if (
|
|
||||||
!isUndefined(metadata.volume.name) &&
|
|
||||||
!isUndefined(metadata.issue_number)
|
|
||||||
) {
|
|
||||||
console.log("asdasd", metadata.volume.name);
|
|
||||||
await ctx.broker.call("libraryqueue.issuesForSeries", { queryObject: {
|
|
||||||
issueName:
|
|
||||||
metadata.volume
|
|
||||||
.name,
|
|
||||||
issueNumber:
|
|
||||||
metadata.issue_number,
|
|
||||||
}});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return issueMetadata.data.results;
|
// 2a. Enqueue the Elasticsearch job
|
||||||
}
|
if (
|
||||||
);
|
!isUndefined(issueMetadata.volume.name) &&
|
||||||
}
|
!isUndefined(issueMetadata.issue_number)
|
||||||
|
) {
|
||||||
|
await ctx.broker.call(
|
||||||
|
"libraryqueue.issuesForSeries",
|
||||||
|
{
|
||||||
|
queryObject: {
|
||||||
|
issueId: issue.id,
|
||||||
|
issueName:
|
||||||
|
issueMetadata.volume
|
||||||
|
.name,
|
||||||
|
issueNumber:
|
||||||
|
issueMetadata.issue_number,
|
||||||
|
issueMetadata,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 3. Just return the issues
|
||||||
|
return issueMetadata;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return Promise.all(foo);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
flushDB: {
|
flushDB: {
|
||||||
rest: "POST /flushDB",
|
rest: "POST /flushDB",
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { isNil, isUndefined } from "lodash";
|
import { extend, isNil, isUndefined } from "lodash";
|
||||||
import {
|
import {
|
||||||
Context,
|
Context,
|
||||||
Service,
|
Service,
|
||||||
@@ -101,20 +101,30 @@ export default class LibraryQueueService extends Service {
|
|||||||
async process(job: SandboxedJob) {
|
async process(job: SandboxedJob) {
|
||||||
try {
|
try {
|
||||||
console.log(
|
console.log(
|
||||||
"reached the issuematchinlibrary queue"
|
"Job recieved to find issue matches in library."
|
||||||
);
|
);
|
||||||
console.log(job.data);
|
|
||||||
const matchesInLibrary = await this.broker.call(
|
const matchesInLibrary = await this.broker.call(
|
||||||
"search.searchComic",
|
"search.searchComic",
|
||||||
{
|
{
|
||||||
queryObject: job.data.queryObject,
|
queryObject: job.data.queryObject,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log(
|
if (
|
||||||
`Matches in Library: ${matchesInLibrary}`
|
!isNil(matchesInLibrary) &&
|
||||||
);
|
!isUndefined(matchesInLibrary)
|
||||||
|
) {
|
||||||
|
console.log("Matches found in library:");
|
||||||
|
|
||||||
return Promise.all(matchesInLibrary);
|
const foo = extend(
|
||||||
|
{ issue: job.data.queryObject.issueMetadata },
|
||||||
|
{ matches: matchesInLibrary }
|
||||||
|
);
|
||||||
|
return foo;
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"No match was found for this issue in the library."
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -139,10 +149,14 @@ export default class LibraryQueueService extends Service {
|
|||||||
rest: "POST /findIssuesForSeries",
|
rest: "POST /findIssuesForSeries",
|
||||||
params: {},
|
params: {},
|
||||||
handler: async (
|
handler: async (
|
||||||
ctx: Context<{ queryObject: {
|
ctx: Context<{
|
||||||
issueName: string,
|
queryObject: {
|
||||||
issueNumber: string,
|
issueName: string;
|
||||||
} }>
|
issueNumber: string;
|
||||||
|
issueId: string;
|
||||||
|
issueMetadata: object;
|
||||||
|
};
|
||||||
|
}>
|
||||||
) => {
|
) => {
|
||||||
return await this.createJob(
|
return await this.createJob(
|
||||||
"issue.findMatchesInLibrary",
|
"issue.findMatchesInLibrary",
|
||||||
@@ -197,7 +211,7 @@ export default class LibraryQueueService extends Service {
|
|||||||
"completed",
|
"completed",
|
||||||
async (job, res) => {
|
async (job, res) => {
|
||||||
client.emit("action", {
|
client.emit("action", {
|
||||||
type: "LS_COVER_EXTRACTED",
|
type: "CV_ISSUES_FOR_VOLUME_IN_LIBRARY_SUCCESS",
|
||||||
result: res,
|
result: res,
|
||||||
});
|
});
|
||||||
console.info(
|
console.info(
|
||||||
|
|||||||
Reference in New Issue
Block a user