const settings = require('../data/settings.json'); const MovieDB = require('moviedb')(settings.tmdbApiKey); const _ = require('lodash'); const GENRE_TRANSLATIONS = settings.genre.translations; const GENRE_WEIGHTS = settings.genre.weights; const GENRE_COMBINATIONS = settings.genre.combinations; const searchQuery = name => { let parts = name.match(/(.+?)(\s\((\d{4})\))$/); let query = (parts && parts.length > 0) ? parts[1] : name; let year = (parts && parts.length > 2) ? parts[3] : false; return { query:query, year:year }; }; const searchFilter = (data, year = false) => { if (!year) return data; return data.filter(d => d.release_date.toString().includes(year.toString())); }; const searchMovie = name => { const { query, year } = searchQuery(name); return new Promise((resolve, reject) => { MovieDB.searchMovie({ query: query }, (err, res) => { if (err) reject(err); resolve(searchFilter(res.results,year)); }); }); }; const searchTv = name => { const { query, year } = searchQuery(name); return new Promise((resolve, reject) => { MovieDB.searchMovie({ query: query }, (err, res) => { if (err) reject(err); resolve(searchFilter(res.results,year)); }); }); }; const infoMovie = id => { return new Promise((resolve, reject) => { MovieDB.movieInfo({ id: id }, (err, res) => { if (err) reject(err); resolve(res); }); }); }; const infoTv = id => { return new Promise((resolve, reject) => { MovieDB.tvInfo({ id: id }, (err, res) => { if (err) reject(err); resolve(res); }); }); }; const genreTranslate = (data = {}) => { let genres = Object.keys(data); let translations = Object.keys(GENRE_TRANSLATIONS); for (let i=0, l=translations.length; i { let genres = info && info.genres ? info.genres.map(g => g.name) : []; for (let i = 0, l = genres.length; i < l; i++) { let genre = genres[i]; if (!data) data = {}; if (!data[genre]) data[genre] = 0; data[genre] = data[genre] + 1; } genreTranslate(data); }; const genreSorted = data => { if (!data) return []; let keys = Object.keys(data); let values = Object.values(data); // get a distinctset of values let distinctValues = [...new Set(values)]; // sort the keys based on current values let sorted = keys.sort((a, b) => data[b] - data[a]); // only one key ... return if (keys.length === 1) return sorted; // we have more than 1 distinct value if (distinctValues.length > 1) return sorted; // we have one entry and all genere are equally weighted ... apply boosting let genreWeightKeys = Object.keys(GENRE_WEIGHTS); // get the key list for (let i=0, l=genreWeightKeys.length; i data[b] - data[a]); }; const genrePrimary = data => { if (!data) return 'Unknown'; let sorted = genreSorted(data); return sorted[0]; }; const genreMovie = async (name, list = false) => { let results = await searchMovie(name); let genres = {}; for (let i = 0, l = results.length; i < l; i++) { let result = results[i]; let info = await infoMovie(result.id); genreTally(genres, info); } return (list) ? genreSorted(genres) : genrePrimary(genres); }; const genreTv = async (name, list = false) => { let results = await searchTv(name); let genres = {}; for (let i = 0, l = results.length; i < l; i++) { let result = results[i]; let info = await infoTv(result.id); genreTally(genres, info); } return (list) ? genreSorted(genres) : genrePrimary(genres); }; const search = async (name, type = 'movie') => { if (!name) return new Error('nothing to search'); switch (type) { case 'tv': return await searchTv(name); case 'movie': return await searchMovie(name); default: return new Error('invalid type specified'); } }; const info = async (id, type = 'movie') => { if (!id) return new Error('no id specified'); switch (type) { case 'tv': return await infoTv(id); case 'movie': return await infoMovie(id); default: return new Error('invalid type specified'); } }; const genre = async (name, type = 'movie') => { if (!name) return new Error('nothing to search'); switch (type) { case 'tv': return await genreTv(name); case 'movie': return await genreMovie(name); default: return new Error('invalid type specified'); } }; const genres = async (name, type = 'movie') => { if (!name) return new Error('nothing to search'); switch (type) { case 'tv': return await genreTv(name, true); case 'movie': return await genreMovie(name, true); default: return new Error('invalid type specified'); } }; module.exports = { search, info, genre, genres, };