diff --git a/api/index.js b/api/index.js index a322b6e..e262ca7 100644 --- a/api/index.js +++ b/api/index.js @@ -1,6 +1,4 @@ -const router = require('express').Router(); -// const config = require('../config-handler'); - -router.use("/v/1.0", require('./v1')); +const router = require("express").Router(); +router.use("/v/1.0", require("./v1")); module.exports = router; \ No newline at end of file diff --git a/api/v1/errorClass.js b/api/v1/errorClass.js index c76de8e..2c4db01 100644 --- a/api/v1/errorClass.js +++ b/api/v1/errorClass.js @@ -1,5 +1,5 @@ module.exports = class ApiError extends Error { - constructor(message, details={}, ...args) { + constructor(message, details = {}, ...args) { super(message, ...args); this.message = message; this.details = details; diff --git a/api/v1/index.js b/api/v1/index.js index 998fafe..76ece4a 100644 --- a/api/v1/index.js +++ b/api/v1/index.js @@ -1,46 +1,56 @@ -const router = require('express').Router(); -const response = require('./response-wrapper'); +const router = require("express").Router(); +const response = require("./response-wrapper"); // const config = require('../../config-handler'); // Парсинг куки //router.use(require('cookie-parser')()); // Загрузка музыки при помощи спец. метода -function muzicLoad (req, res) { - res.setHeader('Content-Type', 'audio/mpeg'); - global.database.muzic.get((err, data) => { - data = data[0]?.data; - if (err) { - res.send(Buffer.from([])); - } - else { - res.send(!data ? Buffer.from([]) : data); - } - }, { where : { id : !Number.isInteger(+req.query.id) ? 0 : +req.query.id } }); +function muzicLoad(req, res) { + res.setHeader("Content-Type", "audio/mpeg"); + global.database.muzic.get( + (err, data) => { + data = data[0]?.data; + if (err) { + res.send(Buffer.from([])); + } else { + res.send(!data ? Buffer.from([]) : data); + } + }, + { where: { id: !Number.isInteger(+req.query.id) ? 0 : +req.query.id } }, + ); } // Подгрузка с файла -router.use('/:method_name', async (req, res, next, ...etc) => { - if (req.params.method_name === 'muzic') { +router.use("/:method_name", async (req, res, next, ...etc) => { + if (req.params.method_name === "muzic") { muzicLoad(req, res); return; } - + try { const methodFunct = require(`./methods/${req.params.method_name}`); response(methodFunct, req, res); - } - catch (e) { + } catch (e) { if (e.message.includes("Cannot find module")) { - const ApiError = require('./errorClass'); - res.status(400).sendModed(await response((req, res) => { - throw new ApiError("METHOD_NOT_FOUNDED"); - }, req, res)); - } - else { - response(async () => { - throw e; - }, req, res); + const ApiError = require("./errorClass"); + res.status(400).sendModed( + await response( + (req, res) => { + throw new ApiError("METHOD_NOT_FOUNDED"); + }, + req, + res, + ), + ); + } else { + response( + async () => { + throw e; + }, + req, + res, + ); } } }); diff --git a/api/v1/methods/create-item.js b/api/v1/methods/create-item.js index 6c66d18..15e31cb 100644 --- a/api/v1/methods/create-item.js +++ b/api/v1/methods/create-item.js @@ -1,73 +1,87 @@ -const ApiError = require('../errorClass'); -const config = require('../../../config-handler'); +const ApiError = require("../errorClass"); +const config = require("../../../config-handler"); -async function isAuthorExists (authorId) { +async function isAuthorExists(authorId) { if (!authorId) return false; - return (await global.database.authors.promiseMode().get({ where : { id : authorId } })).length !== 0; + return ( + ( + await global.database.authors + .promiseMode() + .get({ where: { id: authorId } }) + ).length !== 0 + ); } -async function checkSyntaxArgs (req, res) { +async function checkSyntaxArgs(req, res) { return !!( - ( // Проверка поля type. - ['author', 'muzic'].indexOf(req.json?.type) !== -1 - ) && - ( // Проверка поля name. - typeof req.json.name === 'string' && req.json.name.length >= 2 && ( - req.json.type === 'muzic' ? true : config().authors_blacklist.filter((blacklisted) => { - return req.json.name.toLowerCase().includes(blacklisted.toLowerCase()); - }).length === 0 - ) - ) && - ( // Дополнительные поля для muzic - req.json.type === 'muzic' ? !!( // Для `muzic` - ( // Проверка поля author_id. - await isAuthorExists(req.json.author_id) - ) && - ( // Проверка поля data. (Передаётся либо ничего, либо строка с base64) - req.json.data === undefined ? true : ( - typeof req.json.data === 'string' + // Проверка поля type. + ["author", "muzic"].indexOf(req.json?.type) !== -1 && // Проверка поля name. + typeof req.json.name === "string" && + req.json.name.length >= 2 && + (req.json.type === "muzic" + ? true + : config().authors_blacklist.filter((blacklisted) => { + return req.json.name + .toLowerCase() + .includes(blacklisted.toLowerCase()); + }).length === 0) && // Дополнительные поля для muzic + (req.json.type === "muzic" + ? !!( + // Для `muzic` + ( + // Проверка поля author_id. + (await isAuthorExists(req.json.author_id)) && // Проверка поля data. (Передаётся либо ничего, либо строка с base64) + (req.json.data === undefined + ? true + : typeof req.json.data === "string") ) - ) - ) : true - ) - ) + ) + : true) + ); } module.exports = async (req, res) => { if (req.json === undefined) { // console.log(req.headers); throw new ApiError("METHOD_MUST_BE_POST_JSON", { - request_method : req.method, - 'content-type' : !req.headers['content-type'] ? null : req.headers['content-type'] + request_method: req.method, + "content-type": !req.headers["content-type"] + ? null + : req.headers["content-type"], }); } - if (!await checkSyntaxArgs(req, res)) { + if (!(await checkSyntaxArgs(req, res))) { throw new ApiError("INVALID_OR_UNSYNTAX_PARAMS", { - request_method : req.method, - params : { - type : req.json?.type === undefined ? null : req.json.type, - name : req.json?.name === undefined ? null : req.json.name, - ...(req.json?.type === 'muzic' ? ({ - author_id : req.json?.author_id === undefined ? null : req.json?.author_id, - data : req.json?.data === undefined ? null : req.json.data, - }) : ({})) - } + request_method: req.method, + params: { + type: req.json?.type === undefined ? null : req.json.type, + name: req.json?.name === undefined ? null : req.json.name, + ...(req.json?.type === "muzic" + ? { + author_id: + req.json?.author_id === undefined ? null : req.json?.author_id, + data: req.json?.data === undefined ? null : req.json.data, + } + : {}), + }, }); } - if (req.json.type === 'author') { + if (req.json.type === "author") { let result = await global.database.authors.promiseMode().add({ - name : req.json.name, - time : Math.round(new Date().getTime() / 1000) + name: req.json.name, + time: Math.round(new Date().getTime() / 1000), }); return result.dataValues.id; - } - else { + } else { let result = await global.database.muzic.promiseMode().add({ - name : req.json.name, - author_id : req.json.author_id, - data : req.json.data === undefined ? undefined : Buffer.from(req.json.data, 'base64'), - time : Math.round(new Date().getTime() / 1000) + name: req.json.name, + author_id: req.json.author_id, + data: + req.json.data === undefined + ? undefined + : Buffer.from(req.json.data, "base64"), + time: Math.round(new Date().getTime() / 1000), }); return result.dataValues.id; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/api/v1/methods/edit-item.js b/api/v1/methods/edit-item.js index 796a814..3790da5 100644 --- a/api/v1/methods/edit-item.js +++ b/api/v1/methods/edit-item.js @@ -1,84 +1,90 @@ -const ApiError = require('../errorClass'); +const ApiError = require("../errorClass"); -async function isAuthorExists (id) { +async function isAuthorExists(id) { if (!id || !Number.isInteger(id)) return false; - return (await global.database.authors.promiseMode().get({ where : { id } })).length !== 0; + return ( + (await global.database.authors.promiseMode().get({ where: { id } })) + .length !== 0 + ); } -async function isMuzicExists (id) { +async function isMuzicExists(id) { if (!id || !Number.isInteger(id)) return false; - let result = (await global.database.muzic.promiseMode().get({ where : { id } })).length !== 0; - console.log('isMuzicExists', result); + let result = + (await global.database.muzic.promiseMode().get({ where: { id } })) + .length !== 0; + console.log("isMuzicExists", result); return result; } -async function checkSyntaxArgs (req, res) { +async function checkSyntaxArgs(req, res) { return !!( - ( // Проверка поля type - ['author', 'muzic'].includes(req.json.type) - ) && - ( // Проверка поля name - req.json.name === undefined ? true : (typeof req.json.name === 'string' && req.json.name.length >= 2) - ) && - ( // Проверка id - req.json.type === 'author' ? await isAuthorExists(req.json.id) : await isMuzicExists(req.json.id) - ) && - ( // Проверка при type=muzic - req.json.type === 'muzic' ? ( - ( // Проверка поля author_id - req.json.author_id === undefined ? true : await isAuthorExists(req.json.author_id) - ) && - ( // Проверка поля data. (Передаётся либо ничего, либо строка с base64) - req.json.data === undefined ? true : ( - typeof req.json.data === 'string' - ) - ) - ) : true - ) - ) + // Проверка поля type + ["author", "muzic"].includes(req.json.type) && // Проверка поля name + (req.json.name === undefined + ? true + : typeof req.json.name === "string" && req.json.name.length >= 2) && // Проверка id + (req.json.type === "author" + ? await isAuthorExists(req.json.id) + : await isMuzicExists(req.json.id)) && // Проверка при type=muzic + (req.json.type === "muzic" + ? // Проверка поля author_id + (req.json.author_id === undefined + ? true + : await isAuthorExists(req.json.author_id)) && // Проверка поля data. (Передаётся либо ничего, либо строка с base64) + (req.json.data === undefined ? true : typeof req.json.data === "string") + : true) + ); } module.exports = async (req, res) => { - if (req.method !== 'POST') { + if (req.method !== "POST") { throw new ApiError("METHOD_MUST_BE_POST_JSON", { - request_method : req.method + request_method: req.method, }); } console.log(await checkSyntaxArgs(req, res)); - if (!await checkSyntaxArgs(req, res)) { + if (!(await checkSyntaxArgs(req, res))) { throw new ApiError("INVALID_OR_UNSYNTAX_PARAMS", { - request_method : req.method, - params : { - id : req.json.id === undefined ? null : req.json.id, - type : req.json.type === undefined ? null : req.json.type, - name : req.json.name === undefined ? null : req.json.name, - ...(req.json.type === 'muzic' ? { - author_id : req.json.author_id, - data : req.json.data - } : {}) - } + request_method: req.method, + params: { + id: req.json.id === undefined ? null : req.json.id, + type: req.json.type === undefined ? null : req.json.type, + name: req.json.name === undefined ? null : req.json.name, + ...(req.json.type === "muzic" + ? { + author_id: req.json.author_id, + data: req.json.data, + } + : {}), + }, }); } - - if (req.json.type === 'author') { - await global.database.authors.promiseMode().edit({ - name : req.json.name - }, { - where : { - id : req.json.id - } - }); + + if (req.json.type === "author") { + await global.database.authors.promiseMode().edit( + { + name: req.json.name, + }, + { + where: { + id: req.json.id, + }, + }, + ); + } else { + await global.database.muzic.promiseMode().edit( + { + name: req.json.name, + author_id: req.json.author_id, + data: !req.json.data ? undefined : Buffer.from(req.json.data, "base64"), + }, + { + where: { + id: req.json.id, + }, + }, + ); } - else { - await global.database.muzic.promiseMode().edit({ - name : req.json.name, - author_id : req.json.author_id, - data : !req.json.data ? undefined : Buffer.from(req.json.data, "base64") - }, { - where : { - id : req.json.id - } - }); - } - return 'ok'; -} \ No newline at end of file + return "ok"; +}; \ No newline at end of file diff --git a/api/v1/methods/get-authors.js b/api/v1/methods/get-authors.js index cef65f8..1f55801 100644 --- a/api/v1/methods/get-authors.js +++ b/api/v1/methods/get-authors.js @@ -1,79 +1,81 @@ -const ApiError = require('../errorClass'); +const ApiError = require("../errorClass"); -async function checkSyntaxArgs (req, res) { +async function checkSyntaxArgs(req, res) { return !!( - ( // Проверка поля offset - req.query.id === undefined ? true : Number.isInteger(+req.query.offset) - ) && - ( // Проверка поля offset - req.query.offset === undefined ? true : Number.isInteger(+req.query.offset) - ) && - ( // Проверка поля count - req.query.count === undefined ? true : Number.isInteger(+req.query.count) - ) && - ( // Проверка поля min_date - req.query.min_date === undefined ? true : Number.isInteger(+req.query.min_date) - ) && - ( // Проверка поля max_date - req.query.max_date === undefined ? true : Number.isInteger(+req.query.max_date) - ) && - ( // Проверка поля q. (Ключевые слова для поиска) - true // (Проверки нет, query всегда строка, необязательный параметр) - ) - ) + // Проверка поля offset + (req.query.id === undefined ? true : Number.isInteger(+req.query.offset)) && // Проверка поля offset + (req.query.offset === undefined + ? true + : Number.isInteger(+req.query.offset)) && // Проверка поля count + (req.query.count === undefined + ? true + : Number.isInteger(+req.query.count)) && // Проверка поля min_date + (req.query.min_date === undefined + ? true + : Number.isInteger(+req.query.min_date)) && // Проверка поля max_date + (req.query.max_date === undefined + ? true + : Number.isInteger(+req.query.max_date)) && // Проверка поля q. (Ключевые слова для поиска) + true // (Проверки нет, query всегда строка, необязательный параметр) + ); } module.exports = async (req, res) => { - if (req.method !== 'GET') { + if (req.method !== "GET") { throw new ApiError("METHOD_MUST_BE_GET", { - request_method : req.method + request_method: req.method, }); } - if (!await checkSyntaxArgs(req, res)) { + if (!(await checkSyntaxArgs(req, res))) { throw new ApiError("INVALID_OR_UNSYNTAX_PARAMS", { - request_method : req.method, - params : { - id : req.query?.id === undefined ? null : req.query.id, - q : req.query?.q === undefined ? null : req.query.q, - offset : req.query?.offset === undefined ? null : req.query.offset, - count : req.query?.count === undefined ? null : req.query.count, - min_date : req.query?.min_date === undefined ? null : req.query.min_date, - max_date : req.query?.max_date === undefined ? null : req.query.max_date - } + request_method: req.method, + params: { + id: req.query?.id === undefined ? null : req.query.id, + q: req.query?.q === undefined ? null : req.query.q, + offset: req.query?.offset === undefined ? null : req.query.offset, + count: req.query?.count === undefined ? null : req.query.count, + min_date: req.query?.min_date === undefined ? null : req.query.min_date, + max_date: req.query?.max_date === undefined ? null : req.query.max_date, + }, }); } - - + const offset = req.query.offset === undefined ? 0 : +req.query.offset; - const countFromNull = req.query.count === undefined ? undefined : offset + (+req.query.count); - - let result = (await global.database.authors.promiseMode().get( - req.query.id === undefined ? {} : { - id : +req.query.id - } - )).map(i => ({ - id : i.id, - name : i.name, - date : i.time + const countFromNull = + req.query.count === undefined ? undefined : offset + +req.query.count; + + let result = ( + await global.database.authors.promiseMode().get( + req.query.id === undefined + ? {} + : { + id: +req.query.id, + }, + ) + ).map((i) => ({ + id: i.id, + name: i.name, + date: i.time, })); // Если просят выборку по времени if (req.query.min_date || req.query.max_date) { const minDate = req.query.min_date === undefined ? 0 : +req.query.min_date; - const maxDate = req.query.max_date === undefined ? 1e+32 : +req.query.max_date; - + const maxDate = + req.query.max_date === undefined ? 1e32 : +req.query.max_date; + result = result.filter((res) => minDate <= res.date && res.date <= maxDate); } - + if (req.query?.q !== undefined) { - result = result.filter(i => { + result = result.filter((i) => { const search = req.query.q.toLowerCase(); return i.name.toLowerCase().includes(search); }); } - + result = result.slice(offset, countFromNull); return { - count : result.length, - items : result + count: result.length, + items: result, }; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/api/v1/methods/get-muzic.js b/api/v1/methods/get-muzic.js index e77f30a..43a9998 100644 --- a/api/v1/methods/get-muzic.js +++ b/api/v1/methods/get-muzic.js @@ -1,110 +1,142 @@ -const ApiError = require('../errorClass'); +const ApiError = require("../errorClass"); -async function isAuthorExists (authorId) { +async function isAuthorExists(authorId) { if (!authorId) return false; - return (await global.database.authors.promiseMode().get({ where : { id : authorId } })).length !== 0; + return ( + ( + await global.database.authors + .promiseMode() + .get({ where: { id: authorId } }) + ).length !== 0 + ); } -async function isAuthorsExists (authorsId) { +async function isAuthorsExists(authorsId) { if (!Array.isArray(authorsId)) return false; - const authors = (await global.database.authors.promiseMode().get()).map(i => i.id); - return authorsId.map(authorId => authors.includes(authorId)); + const authors = (await global.database.authors.promiseMode().get()).map( + (i) => i.id, + ); + return authorsId.map((authorId) => authors.includes(authorId)); } -async function checkSyntaxArgs (req, res) { +async function checkSyntaxArgs(req, res) { return !!( - ( // Проверка поля author. - req.query.author === undefined ? true : await isAuthorExists(+req.query.author) - ) && - ( // Проверка поля authors. - req.query.authors === undefined ? true : await isAuthorsExists(req.query.authors.split(',').map(i => +i)) - ) && - ( // Проверка поля offset - req.query.offset === undefined ? true : Number.isInteger(+req.query.offset) - ) && - ( // Проверка поля count - req.query.count === undefined ? true : Number.isInteger(+req.query.count) - ) && - ( // Проверка поля min_date - req.query.min_date === undefined ? true : Number.isInteger(+req.query.min_date) - ) && - ( // Проверка поля max_date - req.query.max_date === undefined ? true : Number.isInteger(+req.query.max_date) - ) && - ( // Проверка поля q. (Ключевые слова для поиска) - true // (Проверки нет, query всегда строка, необязательный параметр) - ) && - ( // Проверка поля searchByAuthor (Флаг для 'q'. 0 - отключить) - true // (Проверки нет, query всегда строка, необязательный параметр) - ) && - ( // Проверка поля searchByName (Флаг для 'q'. 0 - отключить) - true // (Проверки нет, query всегда строка, необязательный параметр) - ) - ) + // Проверка поля author. + (req.query.author === undefined + ? true + : await isAuthorExists(+req.query.author)) && // Проверка поля authors. + (req.query.authors === undefined + ? true + : await isAuthorsExists(req.query.authors.split(",").map((i) => +i))) && // Проверка поля offset + (req.query.offset === undefined + ? true + : Number.isInteger(+req.query.offset)) && // Проверка поля count + (req.query.count === undefined + ? true + : Number.isInteger(+req.query.count)) && // Проверка поля min_date + (req.query.min_date === undefined + ? true + : Number.isInteger(+req.query.min_date)) && // Проверка поля max_date + (req.query.max_date === undefined + ? true + : Number.isInteger(+req.query.max_date)) && // Проверка поля q. (Ключевые слова для поиска) + true && // (Проверки нет, query всегда строка, необязательный параметр) // Проверка поля searchByAuthor (Флаг для 'q'. 0 - отключить) + true && // (Проверки нет, query всегда строка, необязательный параметр) // Проверка поля searchByName (Флаг для 'q'. 0 - отключить) + true // (Проверки нет, query всегда строка, необязательный параметр) + ); } module.exports = async (req, res) => { - if (req.method !== 'GET') { + if (req.method !== "GET") { throw new ApiError("METHOD_MUST_BE_GET", { - request_method : req.method + request_method: req.method, }); } - if (!await checkSyntaxArgs(req, res)) { + if (!(await checkSyntaxArgs(req, res))) { throw new ApiError("INVALID_OR_UNSYNTAX_PARAMS", { - request_method : req.method, - params : { - author : req.query?.author === undefined ? null : req.query.author, - authors : req.query?.authors === undefined ? null : req.query.authors, - q : req.query?.q === undefined ? null : req.query.q, - offset : req.query?.offset === undefined ? null : req.query.offset, - count : req.query?.count === undefined ? null : req.query.count, - searchByAuthor : req.query?.searchByAuthor === undefined ? null : req.query.searchByAuthor, - searchByName : req.query?.searchByName === undefined ? null : req.query.searchByName, - min_date : req.query?.min_date === undefined ? null : req.query.min_date, - max_date : req.query?.max_date === undefined ? null : req.query.max_date - } + request_method: req.method, + params: { + author: req.query?.author === undefined ? null : req.query.author, + authors: req.query?.authors === undefined ? null : req.query.authors, + q: req.query?.q === undefined ? null : req.query.q, + offset: req.query?.offset === undefined ? null : req.query.offset, + count: req.query?.count === undefined ? null : req.query.count, + searchByAuthor: + req.query?.searchByAuthor === undefined + ? null + : req.query.searchByAuthor, + searchByName: + req.query?.searchByName === undefined ? null : req.query.searchByName, + min_date: req.query?.min_date === undefined ? null : req.query.min_date, + max_date: req.query?.max_date === undefined ? null : req.query.max_date, + }, }); } - + // Оптимизация: флаг searchByAuthor выставится на 0, если была запрошена выборка по музыке определённого автора // Тем самым, мы ускоряем время ответа, поскольку мы не перебираем массив searchedAuthors с целью поиска совпадений - let searchByAuthor = req.query.author === undefined ? req.query.searchByAuthor : '0'; - + let searchByAuthor = + req.query.author === undefined ? req.query.searchByAuthor : "0"; + const offset = req.query.offset === undefined ? 0 : +req.query.offset; - const countFromNull = req.query.count === undefined ? undefined : offset + (+req.query.count); - - let result = (await global.database.muzic.promiseMode().get(req.query?.author === undefined - ? {} : { where: { - author_id : +req.query.author - }})).map(i => ({ id : i.id, name : i.name, author_id : i.author_id, is_data_exists : i.data !== null, date : i.time })); + const countFromNull = + req.query.count === undefined ? undefined : offset + +req.query.count; + + let result = ( + await global.database.muzic.promiseMode().get( + req.query?.author === undefined + ? {} + : { + where: { + author_id: +req.query.author, + }, + }, + ) + ).map((i) => ({ + id: i.id, + name: i.name, + author_id: i.author_id, + is_data_exists: i.data !== null, + date: i.time, + })); // Если просят выборку по authors if (req.query.authors) { - let authors = req.query.authors.split(',').map(author => +author); - result = result.filter(res => authors.includes(res.author_id)); + let authors = req.query.authors.split(",").map((author) => +author); + result = result.filter((res) => authors.includes(res.author_id)); } // Если просят выборку по времени if (req.query.min_date || req.query.max_date) { const minDate = req.query.min_date === undefined ? 0 : +req.query.min_date; - const maxDate = req.query.max_date === undefined ? 1e+32 : +req.query.max_date; - + const maxDate = + req.query.max_date === undefined ? 1e32 : +req.query.max_date; + result = result.filter((res) => minDate <= res.date && res.date <= maxDate); } - + if (req.query?.q !== undefined) { let authors = await global.database.authors.promiseMode().get(); - let searchedAuthors = result.map(i => { + let searchedAuthors = result.map((i) => { let author_id = i.author_id; - return authors.filter(a => a.id === author_id)[0]; + return authors.filter((a) => a.id === author_id)[0]; }); - result = result.filter(i => { + result = result.filter((i) => { const search = req.query.q.toLowerCase(); - return (req.query.searchByName !== '0' && i.name.toLowerCase().includes(search)) || - !!(searchByAuthor !== '0' && searchedAuthors.filter(a => a.id === i.author_id)[0]?.name.toLowerCase().includes(search)); + return ( + (req.query.searchByName !== "0" && + i.name.toLowerCase().includes(search)) || + !!( + searchByAuthor !== "0" && + searchedAuthors + .filter((a) => a.id === i.author_id)[0] + ?.name.toLowerCase() + .includes(search) + ) + ); }); } result = result.slice(offset, countFromNull); return { - count : result.length, - items : result + count: result.length, + items: result, }; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/api/v1/methods/remove-item.js b/api/v1/methods/remove-item.js index 212b17c..b0c288a 100644 --- a/api/v1/methods/remove-item.js +++ b/api/v1/methods/remove-item.js @@ -1,63 +1,72 @@ -const ApiError = require('../errorClass'); -const config = require('../../../config-handler'); +const ApiError = require("../errorClass"); +const config = require("../../../config-handler"); -async function isAuthorExists (authorId) { +async function isAuthorExists(authorId) { if (!authorId) return false; - return (await global.database.authors.promiseMode().get({ where : { id : authorId } })).length !== 0; + return ( + ( + await global.database.authors + .promiseMode() + .get({ where: { id: authorId } }) + ).length !== 0 + ); } -async function checkSyntaxArgs (req, res) { +async function checkSyntaxArgs(req, res) { return !!( - ( // Проверка поля type. - ['author', 'muzic'].indexOf(req.json?.type) !== -1 - ) && - ( // Проверка поля id. - Number.isInteger(req.json.id) && req.json.type === 'author' ? await isAuthorExists(req.json.id) : true - ) - ) + // Проверка поля type. + ["author", "muzic"].indexOf(req.json?.type) !== -1 && // Проверка поля id. + (Number.isInteger(req.json.id) && req.json.type === "author" + ? await isAuthorExists(req.json.id) + : true) + ); } module.exports = async (req, res) => { if (req.json === undefined) { // console.log(req.headers); throw new ApiError("METHOD_MUST_BE_POST_JSON", { - request_method : req.method, - 'content-type' : !req.headers['content-type'] ? null : req.headers['content-type'] + request_method: req.method, + "content-type": !req.headers["content-type"] + ? null + : req.headers["content-type"], }); } - if (!await checkSyntaxArgs(req, res)) { + if (!(await checkSyntaxArgs(req, res))) { throw new ApiError("INVALID_OR_UNSYNTAX_PARAMS", { - request_method : req.method, - params : { - type : req.json?.type === undefined ? null : req.json.type, - name : req.json?.name === undefined ? null : req.json.name, - ...(req.json?.type === 'muzic' ? ({ - author_id : req.json?.author_id === undefined ? null : req.json?.author_id, - data : req.json?.data === undefined ? null : req.json.data, - }) : ({})) - } + request_method: req.method, + params: { + type: req.json?.type === undefined ? null : req.json.type, + name: req.json?.name === undefined ? null : req.json.name, + ...(req.json?.type === "muzic" + ? { + author_id: + req.json?.author_id === undefined ? null : req.json?.author_id, + data: req.json?.data === undefined ? null : req.json.data, + } + : {}), + }, }); } - if (req.json.type === 'author') { + if (req.json.type === "author") { // Удаляем всю музыку этого исполнителя await global.database.muzic.promiseMode().remove({ where: { - author_id: req.json.id - } + author_id: req.json.id, + }, }); // Удаляем исполнителя await global.database.authors.promiseMode().remove({ where: { - id: req.json.id - } + id: req.json.id, + }, }); - } - else { + } else { await global.database.muzic.promiseMode().remove({ where: { - id: req.json.id - } + id: req.json.id, + }, }); } - return 'ok'; -} \ No newline at end of file + return "ok"; +}; \ No newline at end of file diff --git a/api/v1/response-wrapper.js b/api/v1/response-wrapper.js index 2e01970..c40a381 100644 --- a/api/v1/response-wrapper.js +++ b/api/v1/response-wrapper.js @@ -1,54 +1,61 @@ -const fs = require('fs'); -const config = require('../../config-handler'); +const fs = require("fs"); +const config = require("../../config-handler"); const unknownError = (err) => { - const stackId = (new Date()).getTime(); + const stackId = new Date().getTime(); let errorLoggingFolder = config().error_logs_folder; - errorLoggingFolder = !['/', '\\'].includes(errorLoggingFolder.at(-1)) ? errorLoggingFolder + '/' : errorLoggingFolder; - fs.writeFileSync(`${errorLoggingFolder}error_${stackId}.log`, `ERROR: + errorLoggingFolder = !["/", "\\"].includes(errorLoggingFolder.at(-1)) + ? errorLoggingFolder + "/" + : errorLoggingFolder; + fs.writeFileSync( + `${errorLoggingFolder}error_${stackId}.log`, + `ERROR: Date: ${new Date()} Name: ${err.name} Message: ${err.message} Stack: -${err.stack}`); - +${err.stack}`, + ); + return { - error : 'UNKNOWN_ERROR', - details : { - trace_id : stackId - } + error: "UNKNOWN_ERROR", + details: { + trace_id: stackId, + }, }; -} +}; -const unknownResponseFormat = 'UNKNOWN_RESPONSE_FORMAT'; +const unknownResponseFormat = "UNKNOWN_RESPONSE_FORMAT"; -async function handlingError (funct, success, error) { +async function handlingError(funct, success, error) { try { success(await funct()); - } - catch (e) { + } catch (e) { // console.log('error', e); - error(e.name === 'ApiError' ? { - error : e.message, - details : e.details - } : unknownError(e)); + error( + e.name === "ApiError" + ? { + error: e.message, + details: e.details, + } + : unknownError(e), + ); } } module.exports = async (method, req, res) => { - if (req.query.response_format === 'json') { + if (req.query.response_format === "json") { handlingError( - async () => ({ response : await method(req, res) }), + async () => ({ response: await method(req, res) }), async (data) => { res.sendModed(data); }, async (errBody) => { res.errorModeOn(); res.status(400).sendModed(errBody); - } + }, ); - } - else { + } else { res.status(400).sendModed(unknownResponseFormat); } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/config-handler.js b/config-handler.js index 3914f58..464d901 100644 --- a/config-handler.js +++ b/config-handler.js @@ -1,6 +1,8 @@ -const fs = require('fs'); +const fs = require("fs"); module.exports = () => { - const config = JSON.parse(fs.readFileSync("./config.json", { encoding : 'utf-8' })); + const config = JSON.parse( + fs.readFileSync("./config.json", { encoding: "utf-8" }), + ); // Проверить конфиг на целостность return config; -} \ No newline at end of file +}; diff --git a/database.js b/database.js index 30e73f3..448d1fb 100644 --- a/database.js +++ b/database.js @@ -1,118 +1,136 @@ -const { Sequelize, DataTypes } = require('sequelize'); +const { Sequelize, DataTypes } = require("sequelize"); class Table { - constructor (model) { + constructor(model) { this.model = model; } - - promiseMode () { + + promiseMode() { return new TablePromise(this.model); } - - get (cb, condition = null) { - this.model.findAll({...(!condition ? {} : condition), raw: true }) - .then(data => cb(null, data)).catch(err => cb(err, null)); + + get(cb, condition = null) { + this.model + .findAll({ ...(!condition ? {} : condition), raw: true }) + .then((data) => cb(null, data)) + .catch((err) => cb(err, null)); } - - add (item, cb) { - this.model.create(item).then(i => cb(null, i)) - .catch(err => cb(err, null)); + + add(item, cb) { + this.model + .create(item) + .then((i) => cb(null, i)) + .catch((err) => cb(err, null)); } - - remove (condition, cb) { - this.model.destroy(condition).then(i => cb(null, i)) - .catch(err => cb(err, null)); + + remove(condition, cb) { + this.model + .destroy(condition) + .then((i) => cb(null, i)) + .catch((err) => cb(err, null)); } - - edit (data, condition, cb) { - this.model.update(data, condition).then(i => cb(null, i)) - .catch(err => cb(err, null)); + + edit(data, condition, cb) { + this.model + .update(data, condition) + .then((i) => cb(null, i)) + .catch((err) => cb(err, null)); } } class TablePromise extends Table { - async get (condition) { - return await this.model.findAll({...(!condition ? {} : condition), raw: true }); + async get(condition) { + return await this.model.findAll({ + ...(!condition ? {} : condition), + raw: true, + }); } - - async add (item) { + + async add(item) { //setTimeout(() => this.model.findAll(), 0); return await this.model.create(item); } - - async remove (condition) { + + async remove(condition) { return await this.model.destroy(condition); } - - async edit (data, condition) { + + async edit(data, condition) { return await this.model.update(data, condition); } } class Database { - constructor ( - address, - port, - username, - password, - database - ) { - this.sequelize = new Sequelize(`postgres://${username}:${password}@${address}:${port}/${database}`); - this.sequelize.authenticate().then(() => { - this.authors = new Table( - this.sequelize.define('authors', { - id: { - type: DataTypes.INTEGER, - primaryKey: true, - autoIncrement: true, - allowNull: false - }, - name: { - type: DataTypes.TEXT, - allowNull: false - }, - time : { - type: DataTypes.INTEGER, - allowNull: false - } - }, { - freezeTableName: true, - timestamps: false - }) - ); - this.muzic = new Table( - this.sequelize.define('muzic', { - id: { - type: DataTypes.INTEGER, - primaryKey: true, - autoIncrement: true, - allowNull: false - }, - name: { - type: DataTypes.TEXT, - allowNull: false - }, - author_id: { - type: DataTypes.INTEGER, - allowNull: false - }, - data: { - type: DataTypes.BLOB('long') - }, - time : { - type: DataTypes.INTEGER, - allowNull: false - } - }, { - freezeTableName: true, - timestamps: false - }) - ); - console.log('Database successful connected!') - }, (err) => { - throw err; - }) + constructor(address, port, username, password, database) { + this.sequelize = new Sequelize( + `postgres://${username}:${password}@${address}:${port}/${database}`, + ); + this.sequelize.authenticate().then( + () => { + this.authors = new Table( + this.sequelize.define( + "authors", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + }, + time: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + freezeTableName: true, + timestamps: false, + }, + ), + ); + this.muzic = new Table( + this.sequelize.define( + "muzic", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + allowNull: false, + }, + name: { + type: DataTypes.TEXT, + allowNull: false, + }, + author_id: { + type: DataTypes.INTEGER, + allowNull: false, + }, + data: { + type: DataTypes.BLOB("long"), + }, + time: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + freezeTableName: true, + timestamps: false, + }, + ), + ); + console.log("Database successful connected!"); + }, + (err) => { + throw err; + }, + ); } } -module.exports = { Database } \ No newline at end of file +module.exports = { Database }; diff --git a/logger.js b/logger.js index 87c572f..b92da74 100644 --- a/logger.js +++ b/logger.js @@ -1,35 +1,40 @@ -const config = require('./config-handler'); -const fs = require('fs'); +const config = require("./config-handler"); +const fs = require("fs"); -function log (date, req, ip, res) { - const requestBody = !req.byteBody.toString('utf-8') ? '' : ` +function log(date, req, ip, res) { + const requestBody = !req.byteBody.toString("utf-8") + ? "" + : ` ~~~~~~~~~~~~~~ [REQUEST BODY] ~~~~~~~~~~~~~~ -${req.byteBody.toString('utf-8')}`; +${req.byteBody.toString("utf-8")}`; let action = `HTTP ${req.httpVersion} ${req.method} ${req.originalUrl} ~~~~~~~~~ [HEADERS] ~~~~~~~~~ -${Object.entries(req.headers).map(([header, value]) => header + ": " + value).join('\n')}${requestBody}`; - let response = !res.isError ? '' : `\n----------------\nError raised:\n----------------\n${JSON.stringify(res.responseData)}`; +${Object.entries(req.headers) + .map(([header, value]) => header + ": " + value) + .join("\n")}${requestBody}`; + let response = !res.isError + ? "" + : `\n----------------\nError raised:\n----------------\n${JSON.stringify( + res.responseData, + )}`; //console.log(`================================\nREPORT\n================================\n\nIP: ${ip}\n----------------\nACTION:\n----------------\n${action}${response}`); let loggerFolder = config().logger_folder; - loggerFolder = !['/', '\\'].includes(loggerFolder.at(-1)) ? loggerFolder + '/' : loggerFolder; - + loggerFolder = !["/", "\\"].includes(loggerFolder.at(-1)) + ? loggerFolder + "/" + : loggerFolder; + fs.writeFileSync( `${loggerFolder}${date.getTime()}.log`, - `================================\nREPORT\n================================\n\nIP: ${ip}\n----------------\nACTION:\n----------------\n${action}${response}` + `================================\nREPORT\n================================\n\nIP: ${ip}\n----------------\nACTION:\n----------------\n${action}${response}`, ); } module.exports = async (req, res, next) => { // console.log('ip', req.ip); - log( - new Date(), - req, - req.ip, - res - ); + log(new Date(), req, req.ip, res); next(); }; \ No newline at end of file diff --git a/server.js b/server.js index 11089d2..04d87d6 100644 --- a/server.js +++ b/server.js @@ -1,10 +1,10 @@ "use strict"; -const express = require('express'); -const bodyHand = require('body'); -const config = require('./config-handler'); -const http = require('http'); -const { Database } = require('./database'); +const express = require("express"); +const bodyHand = require("body"); +const config = require("./config-handler"); +const http = require("http"); +const { Database } = require("./database"); const app = express(); @@ -13,74 +13,80 @@ global.database = new Database( config().database.port, config().database.username, config().database.password, - config().database.database + config().database.database, ); http.ServerResponse.prototype.errorModeOn = function () { this.isError = true; -} +}; http.ServerResponse.prototype.bindNext = function (next) { this.next = next; -} +}; -http.ServerResponse.prototype.sendModed = function (sendData) { // Модифицируем res.send +http.ServerResponse.prototype.sendModed = function (sendData) { + // Модифицируем res.send if (sendData !== undefined && config().logger_mode) { this.responseData = sendData; - require('./logger')(this.req, this, this.next); + require("./logger")(this.req, this, this.next); } this.send(sendData); -} +}; app.use((req, res, next) => { res.bindNext(next); next(); }); -app.use((req, res, next) => { // Для добавления оригинального тела запроса - const body = bodyHand(req, res, { - limit: 9999999999, - cache: false, - encoding: 'base64' - }, (err, body) => { - if (!err) { - req.byteBody = Buffer.from(body, 'base64'); - - // Запись в req.json при json - if ( - !!req.headers && - req.headers['content-type']?.includes('json') - ) { - try { - req.json = JSON.parse(req.byteBody.toString('utf8')); +app.use((req, res, next) => { + // Для добавления оригинального тела запроса + const body = bodyHand( + req, + res, + { + limit: 9999999999, + cache: false, + encoding: "base64", + }, + (err, body) => { + if (!err) { + req.byteBody = Buffer.from(body, "base64"); + + // Запись в req.json при json + if (!!req.headers && req.headers["content-type"]?.includes("json")) { + try { + req.json = JSON.parse(req.byteBody.toString("utf8")); + } catch (_e) {} } - catch (_e) {} } - } - next(); - }); + next(); + }, + ); }); -app.use("/api", async (rq, rs, next) => next(), require('./api')); +app.use("/api", async (rq, rs, next) => next(), require("./api")); // Подключение через HTTPS let server; if (!config().ssl.enabled) { server = app; -} -else { - const https = require('https'); - server = https.createServer({ - cert : fs.readFileSync(config().ssl['public'], 'utf-8'), - key : fs.readFileSync(config().ssl['private'], 'utf-8') - }, app); +} else { + const https = require("https"); + server = https.createServer( + { + cert: fs.readFileSync(config().ssl["public"], "utf-8"), + key: fs.readFileSync(config().ssl["private"], "utf-8"), + }, + app, + ); } server.listen(config().port, config().address, async (err) => { if (err) { throw err; + } else { + console.log( + `Kodex Muzic catalog runned at ${config().address}:${config().port}`, + ); } - else { - console.log(`Kodex Muzic catalog runned at ${config().address}:${config().port}`); - } -}); \ No newline at end of file +});