diff --git a/server/controllers/search.js b/server/controllers/search.js index 89808f0..052ae21 100644 --- a/server/controllers/search.js +++ b/server/controllers/search.js @@ -1,14 +1,146 @@ const fetch = require('node-fetch'); class SearchController { - constructor(searchTerm) { + constructor(searchTerm, language = 'en') { this.term = searchTerm; + this.lang = language; } get hasQuery() { return typeof this.term !== 'undefined' && this.term !== ''; } + searchInventaire() { + if (this.hasQuery) { + const request = fetch(`https://inventaire.io/api/entities?action=search&search=${encodeURIComponent(this.term)}&lang=${encodeURIComponent(this.lang)}`) + request.catch(exception => { + console.error(exception); + return { + error: exception, + message: 'An error occurred when trying to reach the Inventaire API.', + } + }); + const json = request.then(response => response.json()); + json.catch(exception => { + console.error(exception); + return { + error: exception, + message: 'An error occurred when trying read the response from Inventaire as JSON.', + } + }); + return json.then(responseJSON => { + const humans = responseJSON.humans.map(human => { + const hasLabels = typeof human.labels !== 'undefined'; + const hasDescriptions = typeof human.descriptions !== 'undefined'; + const hasImage = typeof human.image !== 'undefined'; + return { + name: ( + hasLabels && typeof human.labels[this.lang] !== 'undefined' + ? human.labels[this.lang] + : ( + hasLabels && Object.keys(human.labels).length > 0 + ? human.labels[Object.keys(human.labels)[0]] + : null + ) + ), + description: ( + hasDescriptions && typeof human.descriptions[this.lang] !== 'undefined' + ? human.descriptions[this.lang] + : ( + hasDescriptions && Object.keys(human.descriptions).length > 0 + ? human.descriptions[Object.keys(human.descriptions)[0]] + : null + ) + ), + link: ( + typeof human.uri !== 'undefined' + ? `https://inventaire.io/entity/${human.uri}` + : null + ), + image: ( + hasImage && typeof human.image.url !== 'undefined' + ? human.image + : null + ), + }; + }); + + const series = responseJSON.series.map(serie => { + const hasLabels = typeof serie.labels !== 'undefined'; + const hasDescriptions = typeof serie.descriptions !== 'undefined'; + return { + name: ( + hasLabels && typeof serie.labels[this.lang] !== 'undefined' + ? serie.labels[this.lang] + : ( + hasLabels && Object.keys(serie.labels).length > 0 + ? serie.labels[Object.keys(serie.labels)[0]] + : null + ) + ), + description: ( + hasDescriptions && typeof serie.descriptions[this.lang] !== 'undefined' + ? serie.descriptions[this.lang] + : ( + hasDescriptions && Object.keys(serie.descriptions).length > 0 + ? serie.descriptions[Object.keys(serie.descriptions)[0]] + : null + ) + ), + link: ( + typeof serie.uri !== 'undefined' + ? `https://inventaire.io/entity/${serie.uri}` + : null + ), + }; + }); + + const works = responseJSON.works.map(work => { + const hasLabels = typeof work.labels !== 'undefined'; + const hasDescriptions = typeof work.descriptions !== 'undefined'; + const hasImage = typeof work.image !== 'undefined'; + return { + name: ( + hasLabels && typeof work.labels[this.lang] !== 'undefined' + ? work.labels[this.lang] + : ( + hasLabels && Object.keys(work.labels).length > 0 + ? work.labels[Object.keys(work.labels)[0]] + : null + ) + ), + description: ( + hasDescriptions && typeof work.descriptions[this.lang] !== 'undefined' + ? work.descriptions[this.lang] + : ( + hasDescriptions && Object.keys(work.descriptions).length > 0 + ? work.descriptions[Object.keys(work.descriptions)[0]] + : null + ) + ), + link: ( + typeof work.uri !== 'undefined' + ? `https://inventaire.io/entity/${work.uri}` + : null + ), + image: ( + hasImage && typeof human.image.url !== 'undefined' + ? human.image + : null + ), + // Ratings and review count will be added here + }; + }); + + return { + humans, + series, + works, + } + }); + } + } + /** * Query a MediaWiki api.php instance with the given options */ diff --git a/server/index.js b/server/index.js index 8ce9c5a..fb5e6df 100644 --- a/server/index.js +++ b/server/index.js @@ -36,7 +36,7 @@ fastify.addHook('onRequest', (request, reply, done) => { fastify.register(require('./routes/public')); // fastify.register(require('./routes/home')); // fastify.register(require('./routes/account')); -// fastify.register(require('./routes/search')); +fastify.register(require('./routes/search')); // Start the server fastify.listen(fastify.siteConfig.port, function (err, address) { diff --git a/server/routes/search.js b/server/routes/search.js index 2f412c8..8b8e852 100644 --- a/server/routes/search.js +++ b/server/routes/search.js @@ -1,12 +1,12 @@ const SearchController = require('../controllers/search'); async function routes(fastify, options) { - fastify.get('/search', async (request, reply) => { + fastify.get('/api/search', async (request, reply) => { const searchTerm = typeof request.query.for !== 'undefined' ? request.query.for.trim() : ''; - const search = new SearchController(searchTerm); + const language = typeof request.query.lang !== 'undefined' ? request.query.lang.trim().split('-')[0] : undefined; // Get base language in cases like 'en-US' + const search = new SearchController(searchTerm, language); - const results = await search.searchOpenLibrary(); - reply.view('search.hbs', { results, searchTerm, arbitraryContent: request.isLoggedInUser ? JSON.stringify(fastify.jwt.decode(request.cookies.token)) : 'you are NOT logged in' }); + return await search.searchInventaire(); }); }