🔼 Bumped moleculer to 0.14.23

This commit is contained in:
2022-08-18 00:29:25 -07:00
parent b0a7e42461
commit d2c171ab5e
8 changed files with 550 additions and 608 deletions

View File

@@ -20,76 +20,68 @@ export default class ImageTransformation extends Service {
schema: ServiceSchema<{}> = { name: "imagetransformation" }
) {
super(broker);
this.parseServiceSchema(
Service.mergeSchemas(
{
name: "imagetransformation",
mixins: [],
settings: {
// Available fields in the responses
fields: ["_id", "name", "quantity", "price"],
this.parseServiceSchema({
name: "imagetransformation",
mixins: [],
settings: {
// Available fields in the responses
fields: ["_id", "name", "quantity", "price"],
// Validator for the `create` & `insert` actions.
entityValidator: {
name: "string|min:3",
price: "number|positive",
},
},
hooks: {},
actions: {
resize: {
rest: "POST /resizeImage",
params: {},
async handler(
ctx: Context<{
imageFile: string | Buffer;
newWidth: number;
newHeight: number;
outputPath: string;
}>
) {
const resizeResult = await resizeImage(
ctx.params.imageFile,
ctx.params.outputPath,
ctx.params.newWidth,
ctx.params.newHeight
);
return { resizeOperationStatus: resizeResult };
},
},
analyze: {
rest: "POST /analyze",
params: {},
handler: async (
ctx: Context<{ imageFilePath: string }>
) => {
const url = new URL(ctx.params.imageFilePath);
const pathName = url.pathname;
const decodedImageFileURI = decodeURI(pathName);
const finalImagePath = path.resolve(
"." + decodedImageFileURI
);
const analyzedData = await analyze(
finalImagePath
);
const colorHistogramData =
await getColorHistogramData(
finalImagePath,
false
);
return {
analyzedData,
colorHistogramData,
};
},
},
},
methods: {},
// Validator for the `create` & `insert` actions.
entityValidator: {
name: "string|min:3",
price: "number|positive",
},
schema
)
);
},
hooks: {},
actions: {
resize: {
rest: "POST /resizeImage",
params: {},
async handler(
ctx: Context<{
imageFile: string | Buffer;
newWidth: number;
newHeight: number;
outputPath: string;
}>
) {
const resizeResult = await resizeImage(
ctx.params.imageFile,
ctx.params.outputPath,
ctx.params.newWidth,
ctx.params.newHeight
);
return { resizeOperationStatus: resizeResult };
},
},
analyze: {
rest: "POST /analyze",
params: {},
handler: async (
ctx: Context<{ imageFilePath: string }>
) => {
const url = new URL(ctx.params.imageFilePath);
const pathName = url.pathname;
const decodedImageFileURI = decodeURI(pathName);
const finalImagePath = path.resolve(
"." + decodedImageFileURI
);
const analyzedData = await analyze(finalImagePath);
const colorHistogramData = await getColorHistogramData(
finalImagePath,
false
);
return {
analyzedData,
colorHistogramData,
};
},
},
},
methods: {},
});
}
}

View File

@@ -21,120 +21,108 @@ export default class OpdsService extends Service {
schema: ServiceSchema<{}> = { name: "opds" }
) {
super(broker);
this.parseServiceSchema(
Service.mergeSchemas(
{
name: "opds",
mixins: [],
settings: {
port: process.env.PORT || 3001,
},
hooks: {},
actions: {
serve: {
rest: "POST /serve",
handler: async (ctx) => {
return buildAsync(
initMain({
title: `title`,
subtitle: `subtitle`,
icon: "/favicon.ico",
}),
[
async (feed: Feed) => {
feed.id =
"urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2";
feed.books = feed.books || [];
await FastGlob(
[
"*.cbr",
"*.cbz",
"*.cb7",
"*.cba",
"*.cbt",
],
{
cwd: COMICS_DIRECTORY,
}
).each((file, idx) => {
const ext = extname(file);
const title = basename(
file,
ext
);
const href = encodeURI(
`/comics/${file}`
);
const type =
lookup(ext) ||
"application/octet-stream";
const entry =
Entry.deserialize<Entry>({
title,
id: idx.toString(),
links: [
{
rel: EnumLinkRel.ACQUISITION,
href,
type,
} as Link,
],
});
if (
!isUndefined(feed) &&
!isUndefined(feed.books)
) {
feed.books.push(entry);
}
});
return feed;
},
]
).then((feed) => {
ctx.meta.$responseHeaders = {
"Content-Type": " application/xml",
};
let data;
xml2js.parseString(
feed.toXML(),
(err, result) => {
result.feed.link = {
$: {
rel: "self",
href: "/opds-catalogs/root.xml",
type: "application/atom+xml;profile=opds-catalog;kind=navigation",
},
_: "",
};
const builder = new xml2js.Builder({
xmldec: {
version: "1.0",
encoding: "UTF-8",
standalone: false,
},
});
data = builder.buildObject(result, {
renderOpts: {
pretty: true,
indent: " ",
newline: "\n",
allowEmpty: true,
},
});
this.parseServiceSchema({
name: "opds",
mixins: [],
settings: {
port: process.env.PORT || 3001,
},
hooks: {},
actions: {
serve: {
rest: "POST /serve",
handler: async (ctx) => {
return buildAsync(
initMain({
title: `title`,
subtitle: `subtitle`,
icon: "/favicon.ico",
}),
[
async (feed: Feed) => {
feed.id =
"urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2";
feed.books = feed.books || [];
await FastGlob(
[
"*.cbr",
"*.cbz",
"*.cb7",
"*.cba",
"*.cbt",
],
{
cwd: COMICS_DIRECTORY,
}
);
return data;
).each((file, idx) => {
const ext = extname(file);
const title = basename(file, ext);
const href = encodeURI(
`/comics/${file}`
);
const type =
lookup(ext) ||
"application/octet-stream";
const entry = Entry.deserialize<Entry>({
title,
id: idx.toString(),
links: [
{
rel: EnumLinkRel.ACQUISITION,
href,
type,
} as Link,
],
});
if (
!isUndefined(feed) &&
!isUndefined(feed.books)
) {
feed.books.push(entry);
}
});
return feed;
},
]
).then((feed) => {
ctx.meta.$responseHeaders = {
"Content-Type": " application/xml",
};
let data;
xml2js.parseString(feed.toXML(), (err, result) => {
result.feed.link = {
$: {
rel: "self",
href: "/opds-catalogs/root.xml",
type: "application/atom+xml;profile=opds-catalog;kind=navigation",
},
_: "",
};
const builder = new xml2js.Builder({
xmldec: {
version: "1.0",
encoding: "UTF-8",
standalone: false,
},
});
},
},
data = builder.buildObject(result, {
renderOpts: {
pretty: true,
indent: " ",
newline: "\n",
allowEmpty: true,
},
});
});
return data;
});
},
methods: {},
},
schema
)
);
},
methods: {},
});
}
}
}

View File

@@ -20,166 +20,157 @@ export default class SettingsService extends Service {
schema: ServiceSchema<{}> = { name: "search" }
) {
super(broker);
this.parseServiceSchema(
Service.mergeSchemas(
{
name: "search",
mixins: [DbMixin("comics", Comic)],
hooks: {},
actions: {
searchComic: {
rest: "POST /searchComic",
params: {},
timeout: 400000,
async handler(
ctx: Context<{
queryObjects: [];
elasticSearchQueries: [
{
elasticSearchQuery: object;
}
];
}>
) {
const flattenedQueryArray = flatten(
ctx.params.elasticSearchQueries
);
let queries = flattenedQueryArray
.map((item) => JSON.stringify(item))
.join("\n");
queries += "\n";
const { body } = await eSClient.msearch({
body: queries,
});
body.responses.forEach((match) => {
console.log(match.hits);
});
return body.responses;
},
},
issue: {
rest: "POST /searchIssue",
params: {},
handler: async (
ctx: Context<{
query: {
volumeName: string;
issueNumber: string;
};
pagination: {
size: number;
from: number;
};
type: string;
}>
) => {
try {
console.log(ctx.params);
const { query, pagination } = ctx.params;
let eSQuery = {};
switch (ctx.params.type) {
case "all":
Object.assign(eSQuery, {
match_all: {},
});
break;
case "volumeName":
Object.assign(eSQuery, {
multi_match: {
fields: [
"rawFileDetails.name",
"sourcedMetadata.locg.name",
"sourcedMetadata.comicvine.name",
"sourcedMetadata.comicvine.volumeInformation.name",
],
query: query.volumeName,
},
});
break;
case "wanted":
Object.assign(eSQuery, {
bool: {
must: {
term: {
"acquisition.source.wanted":
true,
},
},
},
});
break;
case "volumes":
Object.assign(eSQuery, {
exists: {
field: "sourcedMetadata.comicvine.volumeInformation",
},
});
break;
}
console.log(
"Searching ElasticSearch index with this query -> "
);
console.log(
JSON.stringify(eSQuery, null, 2)
);
const result = await eSClient.search(
{
index: "comics",
body: {
query: eSQuery,
},
...pagination,
},
{ hydrate: true }
);
return result;
} catch (error) {
return new Errors.MoleculerClientError(
"Failed to return data",
404,
"ElasticSearch error",
error
);
this.parseServiceSchema({
name: "search",
mixins: [DbMixin("comics", Comic)],
hooks: {},
actions: {
searchComic: {
rest: "POST /searchComic",
params: {},
timeout: 400000,
async handler(
ctx: Context<{
queryObjects: [];
elasticSearchQueries: [
{
elasticSearchQuery: object;
}
},
},
groupIssuesByBundles: {
rest: "GET /groupIssuesByBundles",
params: {},
handler: async (
ctx: Context<{ bundleIds: [] }>
) => {
// params: array of bundle IDs
if (!isNil(ctx.params.bundleIds)) {
return await Comic.find({
"acquisition.directconnect.downloads": {
$elemMatch: {
bundleId: {
$in: ctx.params.bundleIds,
];
}>
) {
const flattenedQueryArray = flatten(
ctx.params.elasticSearchQueries
);
let queries = flattenedQueryArray
.map((item) => JSON.stringify(item))
.join("\n");
queries += "\n";
const { body } = await eSClient.msearch({
body: queries,
});
body.responses.forEach((match) => {
console.log(match.hits);
});
return body.responses;
},
},
issue: {
rest: "POST /searchIssue",
params: {},
handler: async (
ctx: Context<{
query: {
volumeName: string;
issueNumber: string;
};
pagination: {
size: number;
from: number;
};
type: string;
}>
) => {
try {
console.log(ctx.params);
const { query, pagination } = ctx.params;
let eSQuery = {};
switch (ctx.params.type) {
case "all":
Object.assign(eSQuery, {
match_all: {},
});
break;
case "volumeName":
Object.assign(eSQuery, {
multi_match: {
fields: [
"rawFileDetails.name",
"sourcedMetadata.locg.name",
"sourcedMetadata.comicvine.name",
"sourcedMetadata.comicvine.volumeInformation.name",
],
query: query.volumeName,
},
});
break;
case "wanted":
Object.assign(eSQuery, {
bool: {
must: {
term: {
"acquisition.source.wanted":
true,
},
},
},
});
}
},
},
deleteElasticSearchIndices: {
rest: "GET /deleteElasticSearchIndices",
params: {},
handler: async (ctx: Context<{}>) => {
return await eSClient.indices.delete({
break;
case "volumes":
Object.assign(eSQuery, {
exists: {
field: "sourcedMetadata.comicvine.volumeInformation",
},
});
break;
}
console.log(
"Searching ElasticSearch index with this query -> "
);
console.log(JSON.stringify(eSQuery, null, 2));
const result = await eSClient.search(
{
index: "comics",
});
},
},
body: {
query: eSQuery,
},
...pagination,
},
{ hydrate: true }
);
return result;
} catch (error) {
return new Errors.MoleculerClientError(
"Failed to return data",
404,
"ElasticSearch error",
error
);
}
},
methods: {},
},
schema
)
);
groupIssuesByBundles: {
rest: "GET /groupIssuesByBundles",
params: {},
handler: async (ctx: Context<{ bundleIds: [] }>) => {
// params: array of bundle IDs
if (!isNil(ctx.params.bundleIds)) {
return await Comic.find({
"acquisition.directconnect.downloads": {
$elemMatch: {
bundleId: {
$in: ctx.params.bundleIds,
},
},
},
});
}
},
},
deleteElasticSearchIndices: {
rest: "GET /deleteElasticSearchIndices",
params: {},
handler: async (ctx: Context<{}>) => {
return await eSClient.indices.delete({
index: "comics",
});
},
},
},
methods: {},
});
}
}

View File

@@ -18,91 +18,79 @@ export default class SettingsService extends Service {
schema: ServiceSchema<{}> = { name: "settings" }
) {
super(broker);
this.parseServiceSchema(
Service.mergeSchemas(
{
name: "settings",
mixins: [DbMixin("settings", Settings)],
settings: {},
hooks: {},
actions: {
getSettings: {
rest: "GET /getAllSettings",
params: {},
async handler(
ctx: Context<{ settingsKey: string }>
) {
const settings = await Settings.find({});
if (isEmpty(settings)) {
return {};
}
console.log(settings[0]);
return settings[0];
},
},
saveSettings: {
rest: "POST /saveSettings",
params: {},
async handler(
ctx: Context<{
settingsPayload: {
host: object;
airDCPPUserSettings: object;
hubs: [];
};
settingsObjectId: string;
}>
) {
console.log("varan bhat", ctx.params);
const { host, airDCPPUserSettings, hubs } =
ctx.params.settingsPayload;
let query = {
host,
airDCPPUserSettings,
hubs,
};
const keysToUpdate = pickBy(query, identity);
let updateQuery = {};
map(Object.keys(keysToUpdate), (key) => {
updateQuery[`directConnect.client.${key}`] =
query[key];
});
const options = {
upsert: true,
new: true,
setDefaultsOnInsert: true,
};
const filter = {
_id: new ObjectId(
ctx.params.settingsObjectId
),
};
const result = Settings.findOneAndUpdate(
filter,
{ $set: updateQuery },
options
);
return result;
},
},
deleteSettings: {
rest: "POST /deleteSettings",
params: {},
async handler(ctx: Context<{}>) {
return await Settings.remove(
{},
(result) => result
);
},
},
this.parseServiceSchema({
name: "settings",
mixins: [DbMixin("settings", Settings)],
settings: {},
hooks: {},
actions: {
getSettings: {
rest: "GET /getAllSettings",
params: {},
async handler(ctx: Context<{ settingsKey: string }>) {
const settings = await Settings.find({});
if (isEmpty(settings)) {
return {};
}
console.log(settings[0]);
return settings[0];
},
methods: {},
},
schema
)
);
saveSettings: {
rest: "POST /saveSettings",
params: {},
async handler(
ctx: Context<{
settingsPayload: {
host: object;
airDCPPUserSettings: object;
hubs: [];
};
settingsObjectId: string;
}>
) {
console.log("varan bhat", ctx.params);
const { host, airDCPPUserSettings, hubs } =
ctx.params.settingsPayload;
let query = {
host,
airDCPPUserSettings,
hubs,
};
const keysToUpdate = pickBy(query, identity);
let updateQuery = {};
map(Object.keys(keysToUpdate), (key) => {
updateQuery[`directConnect.client.${key}`] =
query[key];
});
const options = {
upsert: true,
new: true,
setDefaultsOnInsert: true,
};
const filter = {
_id: new ObjectId(ctx.params.settingsObjectId),
};
const result = Settings.findOneAndUpdate(
filter,
{ $set: updateQuery },
options
);
return result;
},
},
deleteSettings: {
rest: "POST /deleteSettings",
params: {},
async handler(ctx: Context<{}>) {
return await Settings.remove({}, (result) => result);
},
},
},
methods: {},
});
}
}

View File

@@ -12,70 +12,71 @@ export default class SocketService extends Service {
schema: ServiceSchema<{}> = { name: "socket" }
) {
super(broker);
this.parseServiceSchema(
Service.mergeSchemas(
{
name: "socket",
mixins: [SocketIOService],
settings: {
port: process.env.PORT || 3001,
io: {
namespaces: {
"/": {
events: {
call: {
// whitelist: ["math.*", "say.*", "accounts.*", "rooms.*", "io.*"],
},
action: async (data, ack) => {
// write your handler function here.
switch (data.type) {
case "LS_IMPORT":
console.log(
`Recieved ${data.type} event.`
);
// 1. Send task to queue
await this.broker.call(
"library.newImport",
data.data,
{}
);
break;
case "LS_TOGGLE_IMPORT_QUEUE":
await this.broker.call(
"importqueue.toggleImportQueue",
data.data,
{}
);
break;
case "LS_SINGLE_IMPORT":
console.info("AirDC++ finished a download -> ")
console.log(data);
await this.broker.call("library.importDownloadedFileToLibrary", data.data, {});
break;
}
},
},
this.parseServiceSchema({
name: "socket",
mixins: [SocketIOService],
settings: {
port: process.env.PORT || 3001,
io: {
namespaces: {
"/": {
events: {
call: {
// whitelist: ["math.*", "say.*", "accounts.*", "rooms.*", "io.*"],
},
action: async (data, ack) => {
// write your handler function here.
switch (data.type) {
case "LS_IMPORT":
console.log(
`Recieved ${data.type} event.`
);
// 1. Send task to queue
await this.broker.call(
"library.newImport",
data.data,
{}
);
break;
case "LS_TOGGLE_IMPORT_QUEUE":
await this.broker.call(
"importqueue.toggleImportQueue",
data.data,
{}
);
break;
case "LS_SINGLE_IMPORT":
console.info(
"AirDC++ finished a download -> "
);
console.log(data);
await this.broker.call(
"library.importDownloadedFileToLibrary",
data.data,
{}
);
break;
}
},
},
options: {
adapter: redisAdapter({
host: redisURL.hostname,
port: 6379,
}),
},
},
},
hooks: {},
actions: {},
methods: {},
async started() {
this.io.on("connection", (data) =>
console.log("socket.io server initialized.")
);
options: {
adapter: redisAdapter({
host: redisURL.hostname,
port: 6379,
}),
},
},
schema
)
);
},
hooks: {},
actions: {},
methods: {},
async started() {
this.io.on("connection", (data) =>
console.log("socket.io server initialized.")
);
},
});
}
}