From abbc8b5591f4515e48a427069c55829147f7574e Mon Sep 17 00:00:00 2001 From: Robbie Antenesse Date: Tue, 4 Feb 2020 15:31:58 -0700 Subject: [PATCH] Split Inventaire book methods into sepate class --- .../{books.js => books/Inventaire.js} | 131 +++--------------- server/controllers/books/index.js | 98 +++++++++++++ server/controllers/search.js | 4 +- 3 files changed, 122 insertions(+), 111 deletions(-) rename server/controllers/{books.js => books/Inventaire.js} (56%) create mode 100644 server/controllers/books/index.js diff --git a/server/controllers/books.js b/server/controllers/books/Inventaire.js similarity index 56% rename from server/controllers/books.js rename to server/controllers/books/Inventaire.js index c1137e2..6d83dc8 100644 --- a/server/controllers/books.js +++ b/server/controllers/books/Inventaire.js @@ -1,70 +1,13 @@ const fetch = require('node-fetch'); -class BooksController { - constructor(bookSource, bookURI, language) { - this.source = bookSource; - this.inventaire = 'https://inventaire.io'; - this.openLibrary = 'https://openlibrary.org'; - this.bookBrainz = 'https://bookbrainz.org'; +class Inventaire { + constructor(bookURI, language) { + this.url = 'https://inventaire.io'; this.uri = bookURI; this.lang = language; } - getBookData() { - const bookData = this.getBookDataFromInventaire(); - const communityData = this.getCommunityData(); - - return { - ...bookData, - ...communityData, - } - } - - getCommunityData(maxReviews) { - if (process.NODE_ENV !== 'production') { - return this.getFakeData(maxReviews); - } - - return {}; - } - - getFakeData(maxReviews) { - const faker = require('faker'); - const numberOfReviews = Math.floor(Math.random() * 100); - const reviews = []; - for (let i = 0; i < numberOfReviews; i++) { - const reviewerName = Math.random() < 0.5 - ? faker.fake('{{name.firstName}} {{name.lastName}}') - : faker.fake('{{hacker.adjective}}{{hacker.noun}}'); - reviews.push({ - reviewer: { - name: reviewerName, - handle: faker.fake('@{{internet.userName}}@{{internet.domainName}}'), - }, - date: faker.date.past(), - rating: parseFloat((Math.random() * 5).toFixed(1)), - review: faker.lorem.paragraph(), - hearts: Math.floor(Math.random() * 1000), - }); - } - - const averageRating = parseFloat((reviews.reduce((total, review) => { - return total + review.rating; - }, 0) / numberOfReviews).toFixed(1)); - - reviews.sort((a, b) => { - if (a.hearts === b.hearts) return 0; - return a.hearts > b.hearts ? -1 : 1; - }); - - return { - averageRating, - numberOfReviews, - reviews: typeof maxReviews !== 'undefined' ? reviews.slice(0, maxReviews - 1) : reviews, - } - } - - handleQuickInventaireEntity(entityObject) { + handleQuickEntity(entityObject) { return { name: ( typeof entityObject.label !== 'undefined' @@ -78,7 +21,7 @@ class BooksController { ), link: ( typeof entityObject.uri !== 'undefined' - ? `${this.inventaire}/entity/${entityObject.uri}` + ? `${this.url}/entity/${entityObject.uri}` : null ), uri: ( @@ -91,7 +34,7 @@ class BooksController { ? entityObject.image.map(imageId => { return { uri: imageId.toString(), - url: `${this.inventaire}/img/entities/${imageId}`, + url: `${this.url}/img/entities/${imageId}`, } }) : [] @@ -99,7 +42,7 @@ class BooksController { }; } - handleInventaireEntity(entityObject) { + handleEntity(entityObject) { const hasLabels = typeof entityObject.labels !== 'undefined'; const hasDescriptions = typeof entityObject.descriptions !== 'undefined'; @@ -124,7 +67,7 @@ class BooksController { ), link: ( typeof entityObject.uri !== 'undefined' - ? `${this.inventaire}/entity/${entityObject.uri}` + ? `${this.url}/entity/${entityObject.uri}` : null ), uri: ( @@ -135,39 +78,9 @@ class BooksController { }; } - handleOpenLibraryEntity(entityObject) { - return { - name: ( - typeof entityObject.title_suggest !== 'undefined' - ? entityObject.title_suggest - : null - ), - description: ( - typeof entityObject.author_name !== 'undefined' - ? `${entityObject.type} by ${entityObject.author_name.map(name => name.trim()).join(', ')}` - : null - ), - link: ( - typeof entityObject.key !== 'undefined' - ? `${this.openLibrary}${entityObject.key}` - : null - ), - uri: ( - typeof entityObject.key !== 'undefined' - ? entityObject.key.substr(entityObject.key.lastIndexOf('/') + 1) - : null - ), - coverId: ( - typeof entityObject.cover_i !== 'undefined' - ? entityObject.cover_i.toString() - : false - ), - }; - } - - async getBookDataFromInventaire() { - if (this.uri) { - const request = fetch(`${this.inventaire}/api/entities?action=by-uris&uris=${encodeURIComponent(this.uri)}`) + async getBookData(uri) { + if (uri) { + const request = fetch(`${this.url}/api/entities?action=by-uris&uris=${encodeURIComponent(uri)}`) request.catch(exception => { console.error(exception); return { @@ -186,9 +99,9 @@ class BooksController { const bookData = await json; - if (typeof bookData.entities !== 'undefined' && typeof bookData.entities[this.uri] !== 'undefined') { - const bookData = this.handleInventaireEntity(bookData.entities[this.uri], this.lang); - bookData['covers'] = await this.getInventaireCovers(); + if (typeof bookData.entities !== 'undefined' && typeof bookData.entities[uri] !== 'undefined') { + const bookData = this.handleEntity(bookData.entities[uri], this.lang); + bookData['covers'] = await this.getCovers(); return bookData; } @@ -199,18 +112,18 @@ class BooksController { }; } - async getInventaireCovers() { - if (!this.uri) { + async getCovers(uri) { + if (!uri) { return Promise.resolve([]); } // Note: property `wdt:P629` is a given entity (uri)'s list of editions (ISBNs). - const editionsRequest = fetch(`${this.inventaire}/api/entities?action=reverse-claims&uri=${encodeURIComponent(this.uri)}&property=wdt:P629`) + const editionsRequest = fetch(`${this.url}/api/entities?action=reverse-claims&uri=${encodeURIComponent(uri)}&property=wdt:P629`) editionsRequest.catch(exception => { console.error(exception); return { error: exception, - message: `An error occurred when trying to reach the Inventaire API for URI ${this.uri}.`, + message: `An error occurred when trying to reach the Inventaire API for URI ${uri}.`, } }); @@ -230,12 +143,12 @@ class BooksController { return Promise.resolve([]); } - const isbnsRequest = fetch(`${this.inventaire}/api/entities?action=by-uris&uris=${encodeURIComponent(editionURIs)}`); + const isbnsRequest = fetch(`${this.url}/api/entities?action=by-uris&uris=${encodeURIComponent(editionURIs)}`); isbnsRequest.catch(exception => { console.error(exception); return { error: exception, - message: `An error occurred when trying to reach the Inventaire API for URI ${this.uri}.`, + message: `An error occurred when trying to reach the Inventaire API for URI ${uri}.`, } }); @@ -260,7 +173,7 @@ class BooksController { const entity = responseJSON.entities[key]; return { uri: entity.uri, - url: typeof entity.claims['invp:P2'] !== 'undefined' ? `${this.inventaire}/img/entities/${entity.claims['invp:P2'][0]}` : null, + url: typeof entity.claims['invp:P2'] !== 'undefined' ? `${this.url}/img/entities/${entity.claims['invp:P2'][0]}` : null, publishDate: typeof entity.claims['wdt:P577'] !== 'undefined' ? entity.claims['wdt:P577'][0] : null, } }); @@ -277,4 +190,4 @@ class BooksController { } } -module.exports = BooksController; \ No newline at end of file +module.exports = Inventaire; \ No newline at end of file diff --git a/server/controllers/books/index.js b/server/controllers/books/index.js new file mode 100644 index 0000000..c741932 --- /dev/null +++ b/server/controllers/books/index.js @@ -0,0 +1,98 @@ +const Inventaire = require('./Inventaire'); + +class BooksController { + constructor(bookSource, bookURI, language) { + this.source = bookSource; + this.Inventaire = new Inventaire(bookURI, language); + this.openLibrary = 'https://openlibrary.org'; + this.bookBrainz = 'https://bookbrainz.org'; + this.uri = bookURI; + this.lang = language; + } + + getBookData() { + const bookData = this.getBookDataFromInventaire(); + const communityData = this.getCommunityData(); + + return { + ...bookData, + ...communityData, + } + } + + getCommunityData(maxReviews) { + if (process.NODE_ENV !== 'production') { + return this.getFakeData(maxReviews); + } + + return {}; + } + + getFakeData(maxReviews) { + const faker = require('faker'); + const numberOfReviews = Math.floor(Math.random() * 100); + const reviews = []; + for (let i = 0; i < numberOfReviews; i++) { + const reviewerName = Math.random() < 0.5 + ? faker.fake('{{name.firstName}} {{name.lastName}}') + : faker.fake('{{hacker.adjective}}{{hacker.noun}}'); + reviews.push({ + reviewer: { + name: reviewerName, + handle: faker.fake('@{{internet.userName}}@{{internet.domainName}}'), + }, + date: faker.date.past(), + rating: parseFloat((Math.random() * 5).toFixed(1)), + review: faker.lorem.paragraph(), + hearts: Math.floor(Math.random() * 1000), + }); + } + + const averageRating = parseFloat((reviews.reduce((total, review) => { + return total + review.rating; + }, 0) / numberOfReviews).toFixed(1)); + + reviews.sort((a, b) => { + if (a.hearts === b.hearts) return 0; + return a.hearts > b.hearts ? -1 : 1; + }); + + return { + averageRating, + numberOfReviews, + reviews: typeof maxReviews !== 'undefined' ? reviews.slice(0, maxReviews - 1) : reviews, + } + } + + handleOpenLibraryEntity(entityObject) { + return { + name: ( + typeof entityObject.title_suggest !== 'undefined' + ? entityObject.title_suggest + : null + ), + description: ( + typeof entityObject.author_name !== 'undefined' + ? `${entityObject.type} by ${entityObject.author_name.map(name => name.trim()).join(', ')}` + : null + ), + link: ( + typeof entityObject.key !== 'undefined' + ? `${this.openLibrary}${entityObject.key}` + : null + ), + uri: ( + typeof entityObject.key !== 'undefined' + ? entityObject.key.substr(entityObject.key.lastIndexOf('/') + 1) + : null + ), + coverId: ( + typeof entityObject.cover_i !== 'undefined' + ? entityObject.cover_i.toString() + : false + ), + }; + } +} + +module.exports = BooksController; \ No newline at end of file diff --git a/server/controllers/search.js b/server/controllers/search.js index 1310d99..26a2384 100644 --- a/server/controllers/search.js +++ b/server/controllers/search.js @@ -34,7 +34,7 @@ class SearchController { const booksController = new BooksController('inventaire', undefined, this.lang); return responseJSON.results.map(work => { - const bookData = booksController.handleQuickInventaireEntity(work); + const bookData = booksController.Inventaire.handleQuickEntity(work); booksController.uri = bookData.uri; // Update booksController.uri for each book when fetching community data. const communityData = booksController.getCommunityData(5); @@ -68,7 +68,7 @@ class SearchController { return json.then(responseJSON => { const booksController = new BooksController('inventaire', undefined, this.lang); return responseJSON.works.map(work => { - const bookData = booksController.handleInventaireEntity(work); + const bookData = booksController.Inventaire.handleEntity(work); const communityData = booksController.getCommunityData(5); return {