diff --git a/client/src/components/Hero.js b/client/src/components/Hero.js
index a1cd4c8..2afa15b 100644
--- a/client/src/components/Hero.js
+++ b/client/src/components/Hero.js
@@ -37,7 +37,7 @@ class Hero extends Component {
live_tvGet Started
diff --git a/client/src/components/ImportLibrary.js b/client/src/components/ImportLibrary.js
index 0f81b46..20b3be5 100644
--- a/client/src/components/ImportLibrary.js
+++ b/client/src/components/ImportLibrary.js
@@ -1,20 +1,70 @@
import React, {Component} from 'react';
-import {BrowserRouter, Route} from 'react-router-dom';
+import PropTypes from 'prop-types';
+import CssBaseline from '@material-ui/core/CssBaseline';
+import Typography from '@material-ui/core/Typography';
+import {withStyles} from '@material-ui/core/styles';
import {connect} from 'react-redux';
-import * as actions from '../actions';
+import styles from './css';
+import axios from 'axios';
class ImportLibrary extends Component {
+ importPlexLibrary = async params => {
+ const res = await axios.get('/api/plex/import/all');
+ console.log(res);
+ return res;
+ };
+
render() {
+ const {classes} = this.props;
return (
-
Hello
+
+
+
+
+
+
+ PlexRex
+
+
+ Media recommendations based on your most watched Plex TV and
+ Movies.
+
+
+
+
+
+
+
+
);
}
}
+ImportLibrary.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
function mapStateToProps({auth}) {
return {auth};
}
-export default connect(mapStateToProps)(ImportLibrary);
+export default connect(mapStateToProps)(withStyles(styles)(ImportLibrary));
diff --git a/client/src/components/MediaList.js b/client/src/components/MediaList.js
new file mode 100644
index 0000000..4a47e8d
--- /dev/null
+++ b/client/src/components/MediaList.js
@@ -0,0 +1,46 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import {withStyles} from '@material-ui/core/styles';
+import {connect} from 'react-redux';
+import styles from './css';
+import axios from 'axios';
+
+class MediaList extends Component {
+ componentDidMount() {
+ this.getMostWatched();
+ }
+ getMostWatched = async params => {
+ const res = await axios.get('/api/recommend/most-watched');
+ console.log(res);
+ return res;
+ };
+
+ render() {
+ const {classes} = this.props;
+ return (
+
+ );
+ }
+}
+
+MediaList.propTypes = {
+ classes: PropTypes.object.isRequired,
+};
+
+function mapStateToProps({auth}) {
+ return {auth};
+}
+
+export default connect(mapStateToProps)(withStyles(styles)(MediaList));
diff --git a/client/src/components/Plex.js b/client/src/components/Plex.js
index a09ee74..f85b00c 100644
--- a/client/src/components/Plex.js
+++ b/client/src/components/Plex.js
@@ -1,9 +1,8 @@
import React, {Component} from 'react';
-import {BrowserRouter, Route} from 'react-router-dom';
import {connect} from 'react-redux';
-import * as actions from '../actions';
import PlexTokenForm from './PlexTokenForm';
import ImportLibrary from './ImportLibrary';
+import MediaList from './MediaList';
class Plex extends Component {
render() {
@@ -17,6 +16,7 @@ class Plex extends Component {
return (
+
);
}
diff --git a/client/src/components/PlexTokenForm.js b/client/src/components/PlexTokenForm.js
index ae15bf3..83cac1a 100644
--- a/client/src/components/PlexTokenForm.js
+++ b/client/src/components/PlexTokenForm.js
@@ -22,12 +22,6 @@ class PlexTokenForm extends React.Component {
return res;
};
- fetchSections = async params => {
- const res = await axios.get('/plex/library/sections');
- console.log(res);
- this.setState({section_data: res.data});
- };
-
render() {
const {classes} = this.props;
if (!this.props.auth) {
diff --git a/config/local.js b/config/local.js
index ff57cf9..9e1f03d 100644
--- a/config/local.js
+++ b/config/local.js
@@ -4,6 +4,7 @@ const localConfig = {
googleClientID: process.env.GOOGLE_CLIENT_ID,
googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,
cookieKey: process.env.COOKIE_KEY,
+ movieApiKey: process.env.MOVIE_API_KEY
};
export default localConfig;
diff --git a/config/production.js b/config/production.js
index 51e8346..4d5b328 100644
--- a/config/production.js
+++ b/config/production.js
@@ -4,6 +4,7 @@ const prodConfig = {
cookieKey: process.env.COOKIE_KEY,
port: process.env.PORT,
cookieKey: process.env.COOKIE_KEY,
+ movieApiKey: process.env.MOVIE_API_KEY,
};
export default prodConfig;
diff --git a/config/test.js b/config/test.js
index fab6e66..1013f74 100644
--- a/config/test.js
+++ b/config/test.js
@@ -4,6 +4,7 @@ const testConfig = {
googleClientID: process.env.GOOGLE_CLIENT_ID,
googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,
cookieKey: process.env.COOKIE_KEY,
+ movieApiKey: process.env.MOVIE_API_KEY,
};
export default testConfig;
diff --git a/package-lock.json b/package-lock.json
index 8a950cc..5827c4b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -599,12 +599,14 @@
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "optional": true
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "optional": true,
"requires": {
"is-extglob": "^1.0.0"
}
@@ -643,6 +645,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "optional": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
}
@@ -1686,8 +1689,7 @@
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
- "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
- "dev": true
+ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"cookies": {
"version": "0.7.3",
@@ -2512,8 +2514,7 @@
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
- "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
- "dev": true
+ "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"forwarded": {
"version": "0.1.2",
@@ -2570,7 +2571,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -2588,11 +2590,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2605,15 +2609,18 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -2716,7 +2723,8 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -2726,6 +2734,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -2738,17 +2747,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -2765,6 +2777,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -2837,7 +2850,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -2847,6 +2861,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -2922,7 +2937,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -2952,6 +2968,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -2969,6 +2986,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3007,11 +3025,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -3110,12 +3130,14 @@
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "optional": true
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "optional": true,
"requires": {
"is-extglob": "^1.0.0"
}
@@ -3920,6 +3942,11 @@
"invert-kv": "^2.0.0"
}
},
+ "limits.js": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/limits.js/-/limits.js-0.1.4.tgz",
+ "integrity": "sha1-2rIe8ioXDPoO8eoBpKe+yWRrXoI="
+ },
"lint-staged": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.3.tgz",
@@ -4457,6 +4484,15 @@
}
}
},
+ "moviedb-promise": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/moviedb-promise/-/moviedb-promise-1.3.2.tgz",
+ "integrity": "sha512-391/dwm9OI6ufHUC9w5B2JN+etPIFRG07Y9CWNHAYskmtGbGNR1n352DOTXQF9BYdsOFYL3H4Kh4M1N5e1PSoQ==",
+ "requires": {
+ "limits.js": "^0.1.4",
+ "superagent": "^3.8.3"
+ }
+ },
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -9408,7 +9444,8 @@
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "optional": true
},
"is-glob": {
"version": "2.0.1",
@@ -10690,7 +10727,6 @@
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
"integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
- "dev": true,
"requires": {
"component-emitter": "^1.2.0",
"cookiejar": "^2.1.0",
diff --git a/package.json b/package.json
index 7aca494..a34d603 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"http-proxy-middleware": "^0.19.1",
"lodash": "^4.17.11",
"morgan": "^1.9.1",
+ "moviedb-promise": "^1.3.2",
"onchange": "^5.2.0",
"passport": "^0.4.0",
"passport-google-oauth20": "^2.0.0",
diff --git a/server/controllers/recommend.controller.js b/server/controllers/recommend.controller.js
new file mode 100644
index 0000000..5bec42a
--- /dev/null
+++ b/server/controllers/recommend.controller.js
@@ -0,0 +1,8 @@
+import {Router} from 'express';
+import recommend from '../services/recommend';
+
+const router = Router();
+
+router.get('/most-watched', recommend.getMostWatched);
+
+export default router;
diff --git a/server/db/migrations/20190224045315-create-plex-library.js b/server/db/migrations/20190224045315-create-plex-library.js
index 3d4fb57..c4734cd 100644
--- a/server/db/migrations/20190224045315-create-plex-library.js
+++ b/server/db/migrations/20190224045315-create-plex-library.js
@@ -20,7 +20,7 @@ module.exports = {
rating_key: {
type: Sequelize.INTEGER,
},
- metadata_path: {
+ poster_path: {
type: Sequelize.STRING,
},
summary: {
diff --git a/server/db/models/plexlibrary.js b/server/db/models/plexlibrary.js
index 307440d..d45feb1 100644
--- a/server/db/models/plexlibrary.js
+++ b/server/db/models/plexlibrary.js
@@ -6,7 +6,7 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.STRING,
views: DataTypes.INTEGER,
rating_key: DataTypes.INTEGER,
- metadata_path: DataTypes.STRING,
+ poster_path: DataTypes.STRING,
summary: DataTypes.TEXT,
rating: DataTypes.FLOAT,
year: DataTypes.INTEGER,
diff --git a/server/index.js b/server/index.js
index c8e7d62..9c05c27 100644
--- a/server/index.js
+++ b/server/index.js
@@ -8,6 +8,7 @@ import keys from '../config';
import plex from './routes/plex.route';
import tdaw from './routes/tdaw.route';
import auth from './routes/auth.route';
+import recommend from './routes/recommend.route';
require('./services/auth/passport');
export default () => {
@@ -36,6 +37,7 @@ export default () => {
// Set up routes
server.use('/api/plex', plex);
server.use('/api/tdaw', tdaw);
+ server.use('/api/recommend', recommend);
server.use('/auth', auth);
server.use('/api/auth', auth);
diff --git a/server/routes/recommend.route.js b/server/routes/recommend.route.js
new file mode 100644
index 0000000..e34027c
--- /dev/null
+++ b/server/routes/recommend.route.js
@@ -0,0 +1,9 @@
+import recommendController from '../controllers/recommend.controller';
+
+const express = require('express');
+
+const router = express.Router();
+
+router.use(recommendController);
+
+export default router;
diff --git a/server/services/plex/importData.js b/server/services/plex/importData.js
index ef5e7b7..86520b8 100644
--- a/server/services/plex/importData.js
+++ b/server/services/plex/importData.js
@@ -1,20 +1,54 @@
import Promise from 'bluebird';
import plexApi from './plexApi';
import models from '../../db/models';
+import config from '../../../config';
+import MovieDb from 'moviedb-promise';
+import {Op} from 'sequelize';
+const mdb = new MovieDb(config.server.movieApiKey);
-const importSections = async () => {
+const importSections = async user => {
const sections = await plexApi.getSections();
- const dbSections = await createSections(sections);
+ const dbSections = await createSections(sections, user);
return dbSections;
};
-const createSections = sections => {
+const getTvPosters = async user => {
+ try {
+ console.log('Called Get Posters');
+ const mostWatched = await models.PlexLibrary.findAll({
+ where: {UserId: user.id, type: 'show', views: {[Op.gt]: 0}},
+ });
+
+ console.log(mostWatched);
+ const imageUrls = await mostWatched.map(async show => {
+ console.log('title', show.title);
+ const res = await mdb.searchTv({query: show.title});
+ console.log('request-movie', res.results[0].poster_path);
+ return models.PlexLibrary.update(
+ {
+ poster_path: res.results[0].poster_path,
+ },
+ {
+ where: {title: show.title},
+ },
+ );
+ });
+
+ console.log('mike--', imageUrls);
+ } catch (error) {
+ console.log(error);
+ return error.message;
+ }
+};
+
+const createSections = (sections, user) => {
return Promise.map(sections, section => {
return models.PlexSection.upsert(
{
title: section.title,
type: section.type,
key: section.key,
+ UserId: user.id,
},
{
where: {
@@ -30,10 +64,10 @@ const createSections = sections => {
});
};
-const importLibraries = async () => {
+const importLibraries = async user => {
const sections = await plexApi.getSections();
return Promise.map(sections, section => {
- return importLibrary(section.key);
+ return importLibrary(section.key, user);
});
};
@@ -41,7 +75,7 @@ const importMostWatched = async () => {
// const sectionKeys = await models.PlexSection.findAll().then(sections => {
// return sections.map(section => section.key.toString());
// });
- const sectionKeys = [1, 2, 3];
+ const sectionKeys = [1, 2];
return Promise.map(sectionKeys, sectionKey => {
return importMostWatchedData(sectionKey);
}).catch(err => {
@@ -55,12 +89,12 @@ const importMostWatchedData = async sectionKey => {
return mostWatchedDbData;
};
-const importLibrary = async sectionKey => {
- console.log('section-key', sectionKey);
+const importLibrary = async (sectionKey, user) => {
+ console.log('user--', user);
const libraryData = await plexApi.getLibraryDataBySection({
sectionKey,
});
- const dbLibraryData = await createLibrary(libraryData);
+ const dbLibraryData = await createLibrary(libraryData, user);
return dbLibraryData;
};
@@ -72,7 +106,7 @@ const updateLibrary = libraryData => {
type: data.type,
views: data.globalViewCount,
rating_key: data.ratingKey,
- metadata_path: data.key,
+ poster_path: data.key,
summary: data.summary,
rating: data.rating,
year: data.year,
@@ -89,11 +123,13 @@ const updateLibrary = libraryData => {
});
};
-const createLibrary = libraryData => {
+const createLibrary = (libraryData, user) => {
+ const userId = user.id;
return Promise.map(libraryData, sectionLibraryData => {
return models.PlexLibrary.upsert(
{
title: sectionLibraryData.title,
+ UserId: userId,
type: sectionLibraryData.type,
views: sectionLibraryData.views,
rating_key: sectionLibraryData.ratingKey,
@@ -112,4 +148,9 @@ const createLibrary = libraryData => {
}).catch(err => console.log(err));
};
-export default {importSections, importLibraries, importMostWatched};
+export default {
+ importSections,
+ importLibraries,
+ importMostWatched,
+ getTvPosters,
+};
diff --git a/server/services/plex/index.js b/server/services/plex/index.js
index bf34582..417cd7f 100644
--- a/server/services/plex/index.js
+++ b/server/services/plex/index.js
@@ -73,10 +73,12 @@ const importMostWatched = async (req, res) => {
};
const importAll = async (req, res) => {
- await importData.importSections();
- await importData.importLibraries();
- const data = await importData.importMostWatched();
- res.json(data);
+ await importData.importSections(req.user);
+ await importData.importLibraries(req.user);
+ await importData.importMostWatched(req.user);
+ const images = await importData.getTvPosters(req.user);
+
+ res.json(images);
};
export default {
diff --git a/server/services/recommend/index.js b/server/services/recommend/index.js
index e69de29..b5c68ae 100644
--- a/server/services/recommend/index.js
+++ b/server/services/recommend/index.js
@@ -0,0 +1,20 @@
+import models from '../../db/models';
+import helpers from '../helpers';
+import {Op} from 'sequelize';
+
+const getMostWatched = async (req, res) => {
+ try {
+ console.log('mike');
+ const mostWatched = await models.PlexLibrary.findAll({
+ where: {UserId: req.user.id, views: {[Op.gt]: 0}},
+ });
+ console.log('mostwatched', mostWatched);
+ res.json(mostWatched);
+ } catch (error) {
+ res.json(error.message);
+ }
+};
+
+export default {
+ getMostWatched,
+};
diff --git a/test/server/services/plex/importData.test.js b/test/server/services/plex/importData.test.js
index 77ad4f2..cb93571 100644
--- a/test/server/services/plex/importData.test.js
+++ b/test/server/services/plex/importData.test.js
@@ -3,7 +3,7 @@ import nock from 'nock';
import app from '../../../../index';
import importData from '../../../../server/services/plex/importData';
import models from '../../../../server/db/models';
-import { seed, truncate } from '../../../../server/db/scripts';
+import {seed, truncate} from '../../../../server/db/scripts';
import * as nocks from '../../../nocks';
describe('ImportData', () => {
@@ -71,7 +71,7 @@ describe('ImportData', () => {
data => data.dataValues.title === 'New Girl',
);
newGirl[0].dataValues.views.should.eq(74);
- newGirl[0].dataValues.metadata_path.should.eq(
+ newGirl[0].dataValues.poster_path.should.eq(
'/library/metadata/5485/children',
);
libraryMostWatched.should.be.length(56);