Merge branch 'master' of github.com:KevinMidboe/seasonedShows
This commit is contained in:
24
README.md
24
README.md
@@ -1,6 +1,8 @@
|
||||
# *Seasoned*: an intelligent organizer for your shows
|
||||
# 🌶 seasonedShows
|
||||
Your customly seasoned movie and show requester, downloader and organizer
|
||||
|
||||
*Seasoned* is a intelligent organizer for your tv show episodes. It is made to automate and simplify to process of renaming and moving newly downloaded tv show episodes following Plex file naming and placement.
|
||||
## About
|
||||
seasonedShows is a intelligent organizer for your tv show episodes. It is made to automate and simplify to process of renaming and moving newly downloaded tv show episodes following Plex file naming and placement.
|
||||
|
||||
## Architecture
|
||||
The flow of the system will first check for new folders in your tv shows directory, if a new file is found it's contents are analyzed, stored and tweets suggested changes to it's contents to use_admin.
|
||||
@@ -8,3 +10,21 @@ The flow of the system will first check for new folders in your tv shows directo
|
||||
Then there is a script for looking for replies on twitter by user_admin, if caanges are needed, it handles the changes specified and updates dtabbase.
|
||||
|
||||
After approval by user the files are modified and moved to folders in resptected area. If error occours, pasteee link if log is sent to user.
|
||||
|
||||
#### External
|
||||
+ Seasoned: request, discover and manage.
|
||||
+ Stray: Overview of downloaded episodes before they are organized.
|
||||
+ (+) Admin Panel: Overview of all stray episodes/movies.
|
||||
|
||||
#### Api
|
||||
+ All communication between public website to server.
|
||||
+ Plex: All querying to what is localy available in your plex library.
|
||||
+ Stray (seasoned) -> also calls services (moveStray) through api.
|
||||
+ Tmdb: Requesting information from tmdb.
|
||||
+ (+) Admin Panel: Use secure login and session tokens to handle logged in viewer.
|
||||
|
||||
#### Services
|
||||
+ Parse directories for new content.
|
||||
+ Extract and save in db information about stray item.
|
||||
+ Move a confirmed stray item.
|
||||
+ (+) Search for torrents matching new content.
|
||||
1
_config.yml
Normal file
1
_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-cayman
|
||||
@@ -1,102 +1,32 @@
|
||||
import React from 'react';
|
||||
import glamorous from 'glamorous';
|
||||
|
||||
// StyleComponents
|
||||
import mediaResultItem from './styledComponents/mediaResultItem.jsx';
|
||||
import movieStyle from './styles/movieObjectStyle.jsx';
|
||||
|
||||
class MovieObject {
|
||||
constructor(object) {
|
||||
this.id = object.id;
|
||||
this.title = object.title;
|
||||
this.year = object.year;
|
||||
this.type = object.type;
|
||||
// Check if object.poster != undefined
|
||||
this.poster = object.poster;
|
||||
this.matchedInPlex = object.matchedInPlex;
|
||||
this.overview = object.overview;
|
||||
this.summary = object.summary;
|
||||
}
|
||||
|
||||
requestExisting(movie) {
|
||||
console.log('Exists', movie);
|
||||
}
|
||||
|
||||
requestMovie(id) {
|
||||
fetch('https://apollo.kevinmidboe.com/api/v1/plex/request/' + id, {
|
||||
requestMovie() {
|
||||
// fetch('https://apollo.kevinmidboe.com/api/v1/plex/request/' + id, {
|
||||
fetch('http://localhost:31459/api/v1/plex/request/' + this.id + '?type='+this.type, {
|
||||
method: 'POST'
|
||||
});
|
||||
}
|
||||
|
||||
getElement() {
|
||||
// TODO move this to separate files.
|
||||
var resultItem = {
|
||||
maxWidth: '95%',
|
||||
margin: '0 auto',
|
||||
minHeight: '230px'
|
||||
}
|
||||
var movie_content = {
|
||||
marginLeft: '15px'
|
||||
}
|
||||
var resultTitle = {
|
||||
color: 'black',
|
||||
fontSize: '2em',
|
||||
}
|
||||
|
||||
var resultPoster = {
|
||||
float: 'left',
|
||||
zIndex: '3',
|
||||
position: 'relative',
|
||||
marginRight: '30px'
|
||||
}
|
||||
|
||||
var resultPosterImg = {
|
||||
border: '2px none',
|
||||
borderRadius: '2px',
|
||||
width: '150px'
|
||||
}
|
||||
|
||||
var buttons = {
|
||||
paddingTop: '20px'
|
||||
}
|
||||
|
||||
var requestButton = {
|
||||
color: '#e9a131',
|
||||
marginRight: '10px',
|
||||
background: 'white',
|
||||
border: '#e9a131 2px solid',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'center',
|
||||
padding: '10px',
|
||||
minWidth: '100px',
|
||||
float: 'left',
|
||||
fontSize: '13px',
|
||||
fontWeight: '800',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
|
||||
var tmdbButton = {
|
||||
color: '#00d17c',
|
||||
marginRight: '10px',
|
||||
background: 'white',
|
||||
border: '#00d17c 2px solid',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'center',
|
||||
padding: '10px',
|
||||
minWidth: '100px',
|
||||
float: 'left',
|
||||
fontSize: '13px',
|
||||
fontWeight: '800',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
|
||||
var row = {
|
||||
width: '100%'
|
||||
}
|
||||
|
||||
var itemDivider = {
|
||||
width: '90%',
|
||||
borderBottom: '1px solid grey',
|
||||
margin: '2rem auto'
|
||||
}
|
||||
|
||||
// TODO set the poster image async by updating the dom after this is returned
|
||||
if (this.poster == null || this.poster == undefined) {
|
||||
var posterPath = 'https://openclipart.org/image/2400px/svg_to_png/211479/Simple-Image-Not-Found-Icon.png'
|
||||
@@ -106,10 +36,10 @@ class MovieObject {
|
||||
var foundInPlex;
|
||||
if (this.matchedInPlex) {
|
||||
foundInPlex = <button onClick={() => {this.requestExisting(this)}}
|
||||
style={requestButton}><span>Request Anyway</span></button>;
|
||||
style={movieStyle.requestButton}><span>Request Anyway</span></button>;
|
||||
} else {
|
||||
foundInPlex = <button onClick={() => {this.requestMovie(this.id)}}
|
||||
style={requestButton}><span>+ Request</span></button>;
|
||||
foundInPlex = <button onClick={() => {this.requestMovie()}}
|
||||
style={movieStyle.requestButton}><span>+ Request</span></button>;
|
||||
}
|
||||
|
||||
var themoviedbLink = 'https://www.themoviedb.org/movie/' + this.id
|
||||
@@ -117,27 +47,29 @@ class MovieObject {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={resultItem} key={this.id}>
|
||||
<div style={resultPoster}>
|
||||
<img style={resultPosterImg} id='poster' src={posterPath}></img>
|
||||
<div style={movieStyle.resultItem} key={this.id}>
|
||||
<div style={movieStyle.resultPoster}>
|
||||
<img style={movieStyle.resultPosterImg} id='poster' src={posterPath}></img>
|
||||
</div>
|
||||
<div>
|
||||
<span style={resultTitle}>{this.title} ({this.year})</span>
|
||||
<span style={movieStyle.resultTitle}>{this.title} ({this.year})</span>
|
||||
<br></br>
|
||||
<span>{this.overview}</span>
|
||||
<span>{this.summary}</span>
|
||||
<br></br>
|
||||
|
||||
<span className='imdbLogo'>
|
||||
</span>
|
||||
|
||||
<div style={buttons}>
|
||||
<div style={movieStyle.buttons}>
|
||||
{foundInPlex}
|
||||
<a href={themoviedbLink}><button style={tmdbButton}><span>Info</span></button></a>
|
||||
<a href={themoviedbLink}>
|
||||
<button style={movieStyle.tmdbButton}><span>Info</span></button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={row}>
|
||||
<div style={itemDivider}></div>
|
||||
<div style={movieStyle.row}>
|
||||
<div style={movieStyle.itemDivider}></div>
|
||||
</div>
|
||||
</div>)
|
||||
|
||||
|
||||
@@ -2,67 +2,128 @@ import React from 'react';
|
||||
|
||||
import MovieObject from './MovieObject.jsx';
|
||||
|
||||
// TODO add option for searching multi, movies or tv shows
|
||||
// StyleComponents
|
||||
import searchStyle from './styles/searchRequestStyle.jsx';
|
||||
|
||||
import URI from 'urijs';
|
||||
|
||||
// TODO add option for searching multi, movies or tv shows
|
||||
class SearchRequest extends React.Component {
|
||||
constructor(props){
|
||||
constructor(props){
|
||||
super(props)
|
||||
// Constructor with states holding the search query and the element of reponse.
|
||||
this.state = {
|
||||
searchQuery: '',
|
||||
responseMovieList: null,
|
||||
movieFilter: true,
|
||||
tvshowFilter: false
|
||||
showFilter: false,
|
||||
discoverType: '',
|
||||
page: 1
|
||||
}
|
||||
|
||||
this.allowedDiscoverTypes = [
|
||||
'discover', 'popular', 'nowplaying', 'upcoming'
|
||||
]
|
||||
|
||||
// this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/';
|
||||
this.baseUrl = 'http://localhost:31459/api/v1/tmdb/';
|
||||
|
||||
this.URLs = {
|
||||
request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=',
|
||||
sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query='
|
||||
// request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?page='+this.state.page+'&query=',
|
||||
request: 'http://localhost:31459/api/v1/plex/request?page='+this.state.page+'&query=',
|
||||
// upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming',
|
||||
upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming',
|
||||
// sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query='
|
||||
sendRequest: 'http://localhost:31459/api/v1/plex/request?query='
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
componentDidMount(){
|
||||
var that = this;
|
||||
this.setState({responseMovieList: null})
|
||||
var that = this;
|
||||
// this.setState({responseMovieList: null})
|
||||
this.fetchDiscover('upcoming');
|
||||
}
|
||||
|
||||
// Handles all errors of the response of a fetch call
|
||||
handleErrors(response) {
|
||||
if (!response.ok) {
|
||||
throw Error(response.status);
|
||||
}
|
||||
return response;
|
||||
if (!response.ok) {
|
||||
throw Error(response.status);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
fetchDiscover(queryDiscoverType) {
|
||||
if (this.allowedDiscoverTypes.indexOf(queryDiscoverType) === -1)
|
||||
throw Error('Invalid discover type: ' + queryDiscoverType);
|
||||
|
||||
var uri = new URI(this.baseUrl);
|
||||
uri.segment(queryDiscoverType)
|
||||
uri = uri.setSearch('page', this.state.page);
|
||||
if (this.state.showFilter)
|
||||
uri = uri.addSearch('type', 'show');
|
||||
|
||||
console.log(uri)
|
||||
|
||||
this.setState({
|
||||
responseMovieList: 'Loading...'
|
||||
});
|
||||
|
||||
fetch(uri)
|
||||
// Check if the response is ok
|
||||
.then(response => this.handleErrors(response))
|
||||
.then(response => response.json()) // Convert to json object and pass to next then
|
||||
.then(data => { // Parse the data of the JSON response
|
||||
// If it is something here it updates the state variable with the HTML list of all
|
||||
// movie objects that where returned by the search request
|
||||
if (data.results.length > 0) {
|
||||
this.setState({
|
||||
responseMovieList: data.results.map(item => this.createMovieObjects(item))
|
||||
})
|
||||
}
|
||||
})
|
||||
// If the --------
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
responseMovieList: <h1>Not Found</h1>
|
||||
})
|
||||
|
||||
console.log('Error submit: ', error.toString());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
fetchQuery() {
|
||||
let url = this.URLs.request + this.state.searchQuery
|
||||
if (this.state.tvshowFilter) {
|
||||
if (this.state.showFilter) {
|
||||
url = url + '&type=tv'
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
// Check if the response is ok
|
||||
.then(response => this.handleErrors(response))
|
||||
.then(response => response.json()) // Convert to json object and pass to next then
|
||||
.then(data => { // Parse the data of the JSON response
|
||||
// If it is something here it updates the state variable with the HTML list of all
|
||||
// movie objects that where returned by the search request
|
||||
if (data.length > 0) {
|
||||
this.setState({
|
||||
responseMovieList: data.map(item => this.createMovieObjects(item))
|
||||
})
|
||||
}
|
||||
})
|
||||
// If the --------
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
responseMovieList: <h1>Not Found</h1>
|
||||
})
|
||||
fetch(url)
|
||||
// Check if the response is ok
|
||||
.then(response => this.handleErrors(response))
|
||||
.then(response => response.json()) // Convert to json object and pass to next then
|
||||
.then(data => { // Parse the data of the JSON response
|
||||
// If it is something here it updates the state variable with the HTML list of all
|
||||
// movie objects that where returned by the search request
|
||||
console.log(data)
|
||||
if (data.length > 0) {
|
||||
this.setState({
|
||||
responseMovieList: data.map(item => this.createMovieObjects(item))
|
||||
})
|
||||
}
|
||||
})
|
||||
// If the --------
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
this.setState({
|
||||
responseMovieList: <h1>Not Found</h1>
|
||||
})
|
||||
|
||||
console.log('Error submit: ', error.toString());
|
||||
});
|
||||
console.log('Error submit: ', error.toString());
|
||||
});
|
||||
}
|
||||
|
||||
// Updates the internal state of the query search field.
|
||||
@@ -93,186 +154,77 @@ class SearchRequest extends React.Component {
|
||||
})
|
||||
console.log(this.state.movieFilter);
|
||||
}
|
||||
else if (filterType == 'tvshows') {
|
||||
else if (filterType == 'shows') {
|
||||
this.setState({
|
||||
tvshowFilter: !this.state.tvshowFilter
|
||||
showFilter: !this.state.showFilter
|
||||
})
|
||||
console.log(this.state.tvshowFilter);
|
||||
console.log(this.state.showFilter);
|
||||
}
|
||||
}
|
||||
|
||||
pageBackwards() {
|
||||
if (this.state.page > 1) {
|
||||
console.log('backwards');
|
||||
this.state.page--;
|
||||
this.getUpcoming();
|
||||
}
|
||||
console.log(this.state.page)
|
||||
}
|
||||
|
||||
pageForwards() {
|
||||
this.state.page++;
|
||||
this.getUpcoming();
|
||||
console.log('forwards');
|
||||
console.log(this.state.page)
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
|
||||
var body = {
|
||||
fontFamily: "'Open Sans', sans-serif",
|
||||
backgroundColor: '#f7f7f7',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
minHeight: '100%',
|
||||
position: 'relative'
|
||||
}
|
||||
|
||||
var backgroundHeader = {
|
||||
width: '100%',
|
||||
minHeight: '400px',
|
||||
backgroundColor: '#011c23',
|
||||
zIndex: 1,
|
||||
position: 'absolute'
|
||||
}
|
||||
|
||||
|
||||
var requestWrapper = {
|
||||
top: '300px',
|
||||
width: '90%',
|
||||
maxWidth: '1200px',
|
||||
margin: 'auto',
|
||||
paddingTop: '20px',
|
||||
backgroundColor: 'white',
|
||||
position: 'relative',
|
||||
zIndex: '10',
|
||||
boxShadow: '0 2px 10px grey'
|
||||
}
|
||||
|
||||
var pageTitle = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
|
||||
var pageTitleSpan = {
|
||||
color: 'white',
|
||||
fontSize: '3em',
|
||||
marginTop: '4vh',
|
||||
marginBottom: '6vh'
|
||||
}
|
||||
|
||||
var box = {
|
||||
width: '90%',
|
||||
height: '50px',
|
||||
maxWidth: '1200px',
|
||||
margin: '0 auto'
|
||||
}
|
||||
|
||||
var container = {
|
||||
verticalAlign: 'middle',
|
||||
whiteSpace: 'nowrap',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
|
||||
var searchIcon = {
|
||||
position: 'absolute',
|
||||
marginLeft: '17px',
|
||||
marginTop: '17px',
|
||||
zIndex: '1',
|
||||
color: '#4f5b66'
|
||||
}
|
||||
|
||||
var searchBar = {
|
||||
width: '60%',
|
||||
minWidth: '120px',
|
||||
height: '50px',
|
||||
background: '#ffffff',
|
||||
border: 'none',
|
||||
fontSize: '10pt',
|
||||
float: 'left',
|
||||
color: '#63717f',
|
||||
paddingLeft: '45px',
|
||||
borderRadius: '5px',
|
||||
marginRight: '15px'
|
||||
}
|
||||
|
||||
var searchFilter = {
|
||||
color: 'white',
|
||||
fontSize: '1em',
|
||||
paddingTop: '12px',
|
||||
marginBottom: '12px',
|
||||
marginLeft: '10px',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
|
||||
var hvrUnderlineFromCenter = {
|
||||
color: 'white',
|
||||
fontSize: '1em',
|
||||
paddingTop: '12px',
|
||||
marginBottom: '12px',
|
||||
marginLeft: '10px',
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'middle',
|
||||
WebkitTransform: 'perspective(1px) translateZ(0)',
|
||||
transform: 'perspective(1px) translateZ(0)',
|
||||
boxShadow: '0 0 1px transparent',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
':before': {
|
||||
content: "",
|
||||
position: 'absolute',
|
||||
zIndex: '-1',
|
||||
left: '50%',
|
||||
right: '50%',
|
||||
bottom: '0',
|
||||
background: '#00d17c',
|
||||
height: '2px',
|
||||
WebkitTransitionProperty: 'left, right',
|
||||
transitionProperty: 'left, right',
|
||||
WebkitTransitionDuration: '0.3s',
|
||||
transitionDuration: '0.3s',
|
||||
WebkitTransitionTimingFunction: 'ease-out',
|
||||
transitionTimingFunction: 'ease-out'
|
||||
},
|
||||
':hover:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
'focus:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
'active:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
<div style={body}>
|
||||
<div className='backgroundHeader' style={backgroundHeader}>
|
||||
<div className='pageTitle' style={pageTitle}>
|
||||
<span style={pageTitleSpan}>Request new movies or tv shows</span>
|
||||
<div style={searchStyle.body}>
|
||||
<button onClick={() => {this.fetchDiscover('discover')}}>Discover</button>
|
||||
<button onClick={() => {this.fetchDiscover('popular')}}>Popular</button>
|
||||
<button onClick={() => {this.fetchDiscover('nowplaying')}}>Nowplaying</button>
|
||||
<button onClick={() => {this.fetchDiscover('upcoming')}}>Upcoming</button>
|
||||
|
||||
<div className='backgroundHeader' style={searchStyle.backgroundHeader}>
|
||||
<div className='pageTitle' style={searchStyle.pageTitle}>
|
||||
<span style={searchStyle.pageTitleSpan}>Request new movies or tv shows</span>
|
||||
</div>
|
||||
|
||||
<div className='box' style={box}>
|
||||
<div style={container}>
|
||||
<span style={searchIcon}><i className="fa fa-search"></i></span>
|
||||
<div className='box' style={searchStyle.box}>
|
||||
<div style={searchStyle.container}>
|
||||
<span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span>
|
||||
|
||||
<input style={searchBar} type="text" id="search" placeholder="Search for new content..."
|
||||
<input style={searchStyle.searchBar} type="text" id="search" placeholder="Search for new content..."
|
||||
onKeyPress={(event) => this._handleQueryKeyPress(event)}
|
||||
onChange={event => this.updateQueryState(event)}
|
||||
value={this.state.searchQuery}/>
|
||||
|
||||
<span style={searchFilter}
|
||||
<span style={searchStyle.searchFilter}
|
||||
className="search_category hvrUnderlineFromCenter"
|
||||
onClick={() => {this.toggleFilter('movies')}}
|
||||
id="category_active">Movies</span>
|
||||
<span style={searchFilter}
|
||||
<span style={searchStyle.searchFilter}
|
||||
className="search_category hvrUnderlineFromCenter"
|
||||
onClick={() => {this.toggleFilter('tvshows')}}
|
||||
onClick={() => {this.toggleFilter('shows')}}
|
||||
id="category_inactive">TV Shows</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='requestMovieList' ref='requestMovieList' style={requestWrapper}>
|
||||
<div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}>
|
||||
{this.state.responseMovieList}
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={() => {this.pageBackwards()}}>Back</button>
|
||||
<button onClick={() => {this.pageForwards()}}>Forward</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default SearchRequest;
|
||||
80
client/app/components/styles/movieObjectStyle.jsx
Normal file
80
client/app/components/styles/movieObjectStyle.jsx
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
export default {
|
||||
resultItem: {
|
||||
maxWidth: '95%',
|
||||
margin: '0 auto',
|
||||
minHeight: '230px'
|
||||
},
|
||||
|
||||
resultItem: {
|
||||
maxWidth: '95%',
|
||||
margin: '0 auto',
|
||||
minHeight: '230px'
|
||||
},
|
||||
|
||||
movie_content: {
|
||||
marginLeft: '15px'
|
||||
},
|
||||
|
||||
resultTitle: {
|
||||
color: 'black',
|
||||
fontSize: '2em',
|
||||
},
|
||||
|
||||
resultPoster: {
|
||||
float: 'left',
|
||||
zIndex: '3',
|
||||
position: 'relative',
|
||||
marginRight: '30px'
|
||||
},
|
||||
|
||||
resultPosterImg: {
|
||||
border: '2px none',
|
||||
borderRadius: '2px',
|
||||
width: '150px'
|
||||
},
|
||||
|
||||
buttons: {
|
||||
paddingTop: '20px'
|
||||
},
|
||||
|
||||
requestButton: {
|
||||
color: '#e9a131',
|
||||
marginRight: '10px',
|
||||
background: 'white',
|
||||
border: '#e9a131 2px solid',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'center',
|
||||
padding: '10px',
|
||||
minWidth: '100px',
|
||||
float: 'left',
|
||||
fontSize: '13px',
|
||||
fontWeight: '800',
|
||||
cursor: 'pointer'
|
||||
},
|
||||
|
||||
tmdbButton: {
|
||||
color: '#00d17c',
|
||||
marginRight: '10px',
|
||||
background: 'white',
|
||||
border: '#00d17c 2px solid',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'center',
|
||||
padding: '10px',
|
||||
minWidth: '100px',
|
||||
float: 'left',
|
||||
fontSize: '13px',
|
||||
fontWeight: '800',
|
||||
cursor: 'pointer'
|
||||
},
|
||||
|
||||
row: {
|
||||
width: '100%'
|
||||
},
|
||||
|
||||
itemDivider: {
|
||||
width: '90%',
|
||||
borderBottom: '1px solid grey',
|
||||
margin: '2rem auto'
|
||||
}
|
||||
}
|
||||
134
client/app/components/styles/searchRequestStyle.jsx
Normal file
134
client/app/components/styles/searchRequestStyle.jsx
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
export default {
|
||||
body: {
|
||||
fontFamily: "'Open Sans', sans-serif",
|
||||
backgroundColor: '#f7f7f7',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
minHeight: '100%',
|
||||
position: 'relative'
|
||||
},
|
||||
|
||||
backgroundHeader: {
|
||||
width: '100%',
|
||||
minHeight: '400px',
|
||||
backgroundColor: '#011c23',
|
||||
zIndex: 1,
|
||||
position: 'absolute'
|
||||
},
|
||||
|
||||
requestWrapper: {
|
||||
top: '300px',
|
||||
width: '90%',
|
||||
maxWidth: '1200px',
|
||||
margin: 'auto',
|
||||
paddingTop: '20px',
|
||||
backgroundColor: 'white',
|
||||
position: 'relative',
|
||||
zIndex: '10',
|
||||
boxShadow: '0 2px 10px grey'
|
||||
},
|
||||
|
||||
pageTitle: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
pageTitleSpan: {
|
||||
color: 'white',
|
||||
fontSize: '3em',
|
||||
marginTop: '4vh',
|
||||
marginBottom: '6vh'
|
||||
},
|
||||
|
||||
box: {
|
||||
width: '90%',
|
||||
height: '50px',
|
||||
maxWidth: '1200px',
|
||||
margin: '0 auto'
|
||||
},
|
||||
|
||||
container: {
|
||||
verticalAlign: 'middle',
|
||||
whiteSpace: 'nowrap',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
searchIcon: {
|
||||
position: 'absolute',
|
||||
marginLeft: '17px',
|
||||
marginTop: '17px',
|
||||
zIndex: '1',
|
||||
color: '#4f5b66'
|
||||
},
|
||||
|
||||
searchBar: {
|
||||
width: '60%',
|
||||
minWidth: '120px',
|
||||
height: '50px',
|
||||
background: '#ffffff',
|
||||
border: 'none',
|
||||
fontSize: '10pt',
|
||||
float: 'left',
|
||||
color: '#63717f',
|
||||
paddingLeft: '45px',
|
||||
borderRadius: '5px',
|
||||
marginRight: '15px'
|
||||
},
|
||||
|
||||
searchFilter: {
|
||||
color: 'white',
|
||||
fontSize: '1em',
|
||||
paddingTop: '12px',
|
||||
marginBottom: '12px',
|
||||
marginLeft: '10px',
|
||||
cursor: 'pointer'
|
||||
},
|
||||
|
||||
hvrUnderlineFromCenter: {
|
||||
color: 'white',
|
||||
fontSize: '1em',
|
||||
paddingTop: '12px',
|
||||
marginBottom: '12px',
|
||||
marginLeft: '10px',
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'middle',
|
||||
WebkitTransform: 'perspective(1px) translateZ(0)',
|
||||
transform: 'perspective(1px) translateZ(0)',
|
||||
boxShadow: '0 0 1px transparent',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
':before': {
|
||||
content: "",
|
||||
position: 'absolute',
|
||||
zIndex: '-1',
|
||||
left: '50%',
|
||||
right: '50%',
|
||||
bottom: '0',
|
||||
background: '#00d17c',
|
||||
height: '2px',
|
||||
WebkitTransitionProperty: 'left, right',
|
||||
transitionProperty: 'left, right',
|
||||
WebkitTransitionDuration: '0.3s',
|
||||
transitionDuration: '0.3s',
|
||||
WebkitTransitionTimingFunction: 'ease-out',
|
||||
transitionTimingFunction: 'ease-out'
|
||||
},
|
||||
':hover:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
'focus:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
'active:before': {
|
||||
left: 0,
|
||||
right: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"cross-env": "^3.1.3",
|
||||
"express": "~4.0.0",
|
||||
"mongoose": "^3.6.13",
|
||||
"moviedb": "^0.2.7",
|
||||
"moviedb": "^0.2.10",
|
||||
"node-cache": "^4.1.1",
|
||||
"nodemailer": "^4.0.1",
|
||||
"python-shell": "^0.4.0",
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
class MediaInfo {
|
||||
constructor(device, platform) {
|
||||
this.device = undefined;
|
||||
this.platform = undefined;
|
||||
this.ip = undefined;
|
||||
this.product = undefined;
|
||||
this.title = undefined;
|
||||
this.state = undefined;
|
||||
|
||||
constructor() {
|
||||
this.duration = undefined;
|
||||
this.height = undefined;
|
||||
this.width = undefined;
|
||||
this.bitrate = undefined;
|
||||
this.resolution = undefined;
|
||||
this.framerate = undefined;
|
||||
this.protocol = undefined;
|
||||
this.container = undefined;
|
||||
this.audioCodec = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ const convertStreamToUser = require('src/plex/stream/convertStreamToUser');
|
||||
const ConvertStreamToPlayback = require('src/plex/stream/convertStreamToPlayback');
|
||||
|
||||
function convertPlexToStream(plexStream) {
|
||||
const stream = convertPlexToSeasoned(plexStream);
|
||||
stream.mediaInfo = convertStreamToMediaInfo(plexStream.Media);
|
||||
const stream = convertPlexToSeasoned(plexStream)
|
||||
const plexStreamMedia = plexStream.Media[0]
|
||||
stream.mediaInfo = convertStreamToMediaInfo(plexStreamMedia);
|
||||
stream.player = convertStreamToPlayer(plexStream.Player);
|
||||
|
||||
stream.user = convertStreamToUser(plexStream.User);
|
||||
stream.playback = new ConvertStreamToPlayback(plexStream.Media.Part);
|
||||
stream.playback = new ConvertStreamToPlayback(plexStreamMedia.Part[0]);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ function convertStreamToMediaInfo(plexStream) {
|
||||
mediaInfo.duration = plexStream.duration;
|
||||
mediaInfo.height = plexStream.height;
|
||||
mediaInfo.width = plexStream.width;
|
||||
|
||||
if (plexStream.bitrate) {
|
||||
mediaInfo.bitrate = plexStream.bitrate;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class PlexRepository {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
throw new Error('Error handling plex playing. Error: ' + err);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,13 +67,16 @@ class RequestRepository {
|
||||
});
|
||||
}
|
||||
|
||||
sendRequest(identifier) {
|
||||
/**
|
||||
* Send request for given media id.
|
||||
* @param {identifier, type} the id of the media object and type of media must be defined
|
||||
* @returns {Promise} If nothing has gone wrong.
|
||||
*/
|
||||
sendRequest(identifier, type) {
|
||||
// TODO add to DB so can have a admin page
|
||||
// TODO try a cache hit on the movie item
|
||||
|
||||
tmdb.lookup(identifier).then(movie => {
|
||||
console.log(movie.title)
|
||||
|
||||
tmdb.lookup(identifier, type).then(movie => {
|
||||
|
||||
// create reusable transporter object using the default SMTP transport
|
||||
let transporter = nodemailer.createTransport({
|
||||
@@ -110,6 +113,7 @@ class RequestRepository {
|
||||
|
||||
})
|
||||
|
||||
// TODO add better response when done.
|
||||
return Promise.resolve();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@ class convertStreamToPlayback {
|
||||
this.width = plexStream.width;
|
||||
this.height = plexStream.height;
|
||||
this.decision = plexStream.decision;
|
||||
this.audioProfile = plexStream.audioProfile;
|
||||
this.videoProfile = plexStream.videoProfile;
|
||||
this.duration = plexStream.duration;
|
||||
this.container = plexStream.container;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const Movie = require('src/media_classes/movie');
|
||||
const Show = require('src/media_classes/show');
|
||||
|
||||
function convertTmdbToSeasoned(tmdbObject) {
|
||||
const mediaType = tmdbObject.media_type;
|
||||
function convertTmdbToSeasoned(tmdbObject, strictType=undefined) {
|
||||
const mediaType = strictType || tmdbObject.media_type;
|
||||
|
||||
// There are many diff types of content, we only want to look at movies and tv shows
|
||||
if (mediaType === 'movie') {
|
||||
@@ -16,6 +16,7 @@ function convertTmdbToSeasoned(tmdbObject) {
|
||||
|
||||
const movie = new Movie(title, year, mediaType);
|
||||
|
||||
movie.id = tmdbObject.id;
|
||||
movie.summary = tmdbObject.overview;
|
||||
movie.rating = tmdbObject.vote_average;
|
||||
movie.poster = tmdbObject.poster_path;
|
||||
@@ -27,11 +28,12 @@ function convertTmdbToSeasoned(tmdbObject) {
|
||||
|
||||
return movie;
|
||||
}
|
||||
else if (mediaType === 'tv') {
|
||||
else if (mediaType === 'tv' || mediaType === 'show') {
|
||||
const year = new Date(tmdbObject.first_air_date).getFullYear();
|
||||
|
||||
const show = new Show(tmdbObject.title, year, mediaType);
|
||||
const show = new Show(tmdbObject.name, year, 'show');
|
||||
|
||||
show.id = tmdbObject.id;
|
||||
show.summary = tmdbObject.overview;
|
||||
show.rating = tmdbObject.vote_average;
|
||||
show.poster = tmdbObject.poster_path;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
const moviedb = require('moviedb');
|
||||
const convertTmdbToSeasoned = require('src/tmdb/convertTmdbToSeasoned');
|
||||
var methodTypes = { 'movie': 'searchMovie', 'tv': 'searchTv', 'multi': 'searchMulti', 'movieInfo': 'movieInfo',
|
||||
'tvInfo': 'tvInfo' };
|
||||
var methodTypes = { 'movie': 'searchMovie', 'show': 'searchTv', 'multi': 'searchMulti', 'movieInfo': 'movieInfo',
|
||||
'tvInfo': 'tvInfo', 'upcomingMovies': 'miscUpcomingMovies', 'discoverMovie': 'discoverMovie',
|
||||
'discoverShow': 'discoverTv', 'popularMovies': 'miscPopularMovies', 'popularShows': 'miscPopularTvs',
|
||||
'nowPlayingMovies': 'miscNowPlayingMovies', 'nowAiringShows': 'tvOnTheAir', 'movieSimilar': 'movieSimilar',
|
||||
'showSimilar': 'tvSimilar' };
|
||||
|
||||
class TMDB {
|
||||
constructor(apiKey, tmdbLibrary) {
|
||||
@@ -9,7 +12,7 @@ class TMDB {
|
||||
}
|
||||
|
||||
search(text, page = 1, type = 'multi') {
|
||||
const query = { query: text, page };
|
||||
const query = { 'query': text, 'page': page };
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(type, query))
|
||||
.catch(() => { throw new Error('Could not search for movies.'); })
|
||||
@@ -26,27 +29,235 @@ class TMDB {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrive list of discover section of movies from TMDB.
|
||||
* @param {Page, type} the page number to specify in the request for discover,
|
||||
* and type for movie or show
|
||||
* @returns {Promise} dict with query results, current page and total_pages
|
||||
*/
|
||||
discover(page, type='movie') {
|
||||
// Sets the tmdb function type to the corresponding type from query
|
||||
var tmdbType;
|
||||
if (type === 'movie') {
|
||||
tmdbType = 'discoverMovie';
|
||||
} else if (type === 'show') {
|
||||
tmdbType = 'discoverShow';
|
||||
} else {
|
||||
// Throw error if invalid type from query
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
throw new Error('Invalid type declaration.')
|
||||
})
|
||||
}
|
||||
|
||||
// Build a query for tmdb with pagenumber
|
||||
const query = { 'page': page }
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(tmdbType, query))
|
||||
.catch(() => { throw new Error('Could not fetch discover.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
// Return a object that has the results and a variable for page, total_pages
|
||||
// and seasonedResponse
|
||||
var seasonedResponse = response.results.map((result) => {
|
||||
return convertTmdbToSeasoned(result, type); }
|
||||
);
|
||||
return { 'results': seasonedResponse,
|
||||
'page': response.page, 'total_pages': response.total_pages };
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
throw new Error('Error while parsing discover list.')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrive list of popular section of movies or shows from TMDB.
|
||||
* @param {Page, type} the page number to specify in the request for popular,
|
||||
* and type for movie or show
|
||||
* @returns {Promise} dict with query results, current page and total_pages
|
||||
*/
|
||||
// TODO add filter for language
|
||||
popular(page, type='movie') {
|
||||
// Sets the tmdb function type to the corresponding type from query
|
||||
var tmdbType;
|
||||
if (type === 'movie') {
|
||||
tmdbType = 'popularMovies';
|
||||
} else if (type === 'show') {
|
||||
tmdbType = 'popularShows';
|
||||
} else {
|
||||
// Throw error if invalid type from query
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
throw new Error('Invalid type declaration.')
|
||||
})
|
||||
}
|
||||
|
||||
// Build a query for tmdb with pagenumber
|
||||
const query = { 'page': page }
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(tmdbType, query))
|
||||
.catch(() => { throw new Error('Could not fetch popular.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
var seasonedResponse = response.results.map((result) => {
|
||||
return convertTmdbToSeasoned(result, type); }
|
||||
);
|
||||
// Return a object that has the results and a variable for page, total_pages
|
||||
// and seasonedResponse
|
||||
return { 'results': seasonedResponse,
|
||||
'page': response.page, 'total_pages': response.total_pages };
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
throw new Error('Error while parsing discover list.')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrive list of now playing/airing section of movies or shows from TMDB.
|
||||
* @param {Page, type} the page number to specify in the request for now playing/airing,
|
||||
* and type for movie or show
|
||||
* @returns {Promise} dict with query results, current page and total_pages
|
||||
*/
|
||||
// TODO add filter for language
|
||||
nowplaying(page, type='movie') {
|
||||
// Sets the tmdb function type to the corresponding type from query
|
||||
var tmdbType;
|
||||
if (type === 'movie') {
|
||||
tmdbType = 'nowPlayingMovies';
|
||||
} else if (type === 'show') {
|
||||
tmdbType = 'nowAiringShows';
|
||||
} else {
|
||||
// Throw error if invalid type from query
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
throw new Error('Invalid type declaration.')
|
||||
})
|
||||
}
|
||||
|
||||
// Build a query for tmdb with pagenumber
|
||||
const query = { 'page': page }
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(tmdbType, query))
|
||||
.catch(() => { throw new Error('Could not fetch popular.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
var seasonedResponse = response.results.map((result) => {
|
||||
return convertTmdbToSeasoned(result, type); }
|
||||
);
|
||||
// Return a object that has the results and a variable for page, total_pages
|
||||
// and seasonedResponse
|
||||
return { 'results': seasonedResponse,
|
||||
'page': response.page, 'total_pages': response.total_pages };
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
throw new Error('Error while parsing discover list.')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive list of upcmoing movies from TMDB.
|
||||
* @param {Page} the page number to specify in the request for upcoming movies
|
||||
* @returns {Promise} dict with query results, current page and total_pages
|
||||
*/
|
||||
// TODO add filter for language
|
||||
upcoming(page) {
|
||||
const query = { 'page': page }
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb('upcomingMovies', query))
|
||||
.catch(() => { throw new Error('Could not fetch upcoming movies.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
var seasonedResponse = response.results.map((result) => {
|
||||
return convertTmdbToSeasoned(result, 'movie'); }
|
||||
);
|
||||
// Return a object that has the results and a variable for page, total_pages
|
||||
// and seasonedResponse
|
||||
return { 'results': seasonedResponse,
|
||||
'page': response.page, 'total_pages': response.total_pages };
|
||||
} catch (parseError) {
|
||||
throw new Error('Error while parsing upcoming movies list.')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrive list of upcmoing movies from TMDB.
|
||||
* @param {Page} the page number to specify in the request for upcoming movies
|
||||
* @returns {Promise} dict with query results, current page and total_pages
|
||||
*/
|
||||
// TODO add filter for language
|
||||
similar(identifier, type) {
|
||||
var tmdbType;
|
||||
if (type === 'movie') {
|
||||
tmdbType = 'movieSimilar';
|
||||
} else if (type === 'show') {
|
||||
tmdbType = 'showSimilar';
|
||||
} else {
|
||||
// Throw error if invalid type from query
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
throw new Error('Invalid type declaration.')
|
||||
})
|
||||
}
|
||||
|
||||
const query = { id: identifier }
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(tmdbType, query))
|
||||
.catch(() => { throw new Error('Could not fetch upcoming movies.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
var seasonedResponse = response.results.map((result) => {
|
||||
return convertTmdbToSeasoned(result, type); }
|
||||
);
|
||||
// Return a object that has the results and a variable for page, total_pages
|
||||
// and seasonedResponse
|
||||
return { 'results': seasonedResponse,
|
||||
'page': response.page, 'total_pages': response.total_pages };
|
||||
} catch (parseError) {
|
||||
throw new Error('Error while parsing silimar media list.')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a specific movie by id from TMDB.
|
||||
* @param {Number} identifier of the movie you want to retrieve
|
||||
* @returns {Promise} succeeds if movie was found
|
||||
*/
|
||||
lookup(identifier, type = 'movie') {
|
||||
if (type === 'movie') { type = 'movieInfo'}
|
||||
else if (type === 'tv') { type = 'tvInfo'}
|
||||
lookup(identifier, queryType = 'movie') {
|
||||
var type;
|
||||
if (queryType === 'movie') { type = 'movieInfo'}
|
||||
else if (queryType === 'show') { type = 'tvInfo'}
|
||||
else {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
throw new Error('Invalid type declaration.')
|
||||
})
|
||||
}
|
||||
const query = { id: identifier };
|
||||
return Promise.resolve()
|
||||
.then(() => this.tmdb(type, query))
|
||||
.catch(() => { throw new Error('Could not find a movie with that id.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
return convertTmdbToSeasoned(response);
|
||||
} catch (parseError) {
|
||||
throw new Error('Could not parse movie.');
|
||||
}
|
||||
});
|
||||
.then(() => this.tmdb(type, query))
|
||||
.catch(() => { throw new Error('Could not find a movie with that id.'); })
|
||||
.then((response) => {
|
||||
try {
|
||||
var car = convertTmdbToSeasoned(response, queryType);
|
||||
console.log(car);
|
||||
return car;
|
||||
} catch (parseError) {
|
||||
throw new Error('Could not parse movie.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO ADD CACHE LOOKUP
|
||||
tmdb(method, argument) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = (error, reponse) => {
|
||||
@@ -58,6 +269,7 @@ class TMDB {
|
||||
|
||||
if (!argument) {
|
||||
this.tmdbLibrary[methodTypes[method]](callback);
|
||||
// this.tmdbLibrary['miscUpcomingMovies']
|
||||
} else {
|
||||
this.tmdbLibrary[methodTypes[method]](argument, callback);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ var allowedOrigins = ['https://kevinmidboe.com', 'http://localhost:8080']
|
||||
|
||||
|
||||
router.use(function(req, res, next) {
|
||||
console.log('Something is happening.');
|
||||
// TODO add logging of all incoming
|
||||
console.log('Request: ', req.originalUrl);
|
||||
var origin = req.headers.origin;
|
||||
if (allowedOrigins.indexOf(origin) > -1) {
|
||||
res.setHeader('Access-Control-Allow-Origin', origin);
|
||||
@@ -40,6 +41,12 @@ router.post('/v1/plex/request/:mediaId', require('./controllers/plex/submitReque
|
||||
router.get('/v1/plex/hook', require('./controllers/plex/hookDump.js'));
|
||||
|
||||
router.get('/v1/tmdb/search', require('./controllers/tmdb/searchMedia.js'));
|
||||
router.get('/v1/tmdb/discover', require('./controllers/tmdb/discoverMedia.js'));
|
||||
router.get('/v1/tmdb/popular', require('./controllers/tmdb/popularMedia.js'));
|
||||
router.get('/v1/tmdb/nowplaying', require('./controllers/tmdb/nowPlayingMedia.js'));
|
||||
router.get('/v1/tmdb/upcoming', require('./controllers/tmdb/getUpcoming.js'));
|
||||
|
||||
router.get('/v1/tmdb/similar/:mediaId', require('./controllers/tmdb/searchSimilar.js'));
|
||||
router.get('/v1/tmdb/:mediaId', require('./controllers/tmdb/readMedia.js'));
|
||||
|
||||
router.post('/v1/git/dump', require('./controllers/git/dumpHook.js'));
|
||||
|
||||
@@ -11,8 +11,9 @@ const requestRepository = new RequestRepository();
|
||||
function submitRequestController(req, res) {
|
||||
// This is the id that is the param of the url
|
||||
const id = req.params.mediaId;
|
||||
const type = req.query.type;
|
||||
|
||||
requestRepository.sendRequest(id)
|
||||
requestRepository.sendRequest(id, type)
|
||||
.then(() => {
|
||||
res.send({ success: true, message: 'Media item sucessfully requested!' });
|
||||
})
|
||||
|
||||
21
seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js
Normal file
21
seasoned_api/src/webserver/controllers/tmdb/discoverMedia.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const configuration = require('src/config/configuration').getInstance();
|
||||
const TMDB = require('src/tmdb/tmdb');
|
||||
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
|
||||
|
||||
/**
|
||||
* Controller: Retrieve a list of movies or shows in discover section in TMDB
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function discoverMediaController(req, res) {
|
||||
const { page, type } = req.query;
|
||||
tmdb.discover(page, type)
|
||||
.then((results) => {
|
||||
res.send(results);
|
||||
}).catch((error) => {
|
||||
res.status(404).send({ success: false, error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = discoverMediaController;
|
||||
21
seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js
Normal file
21
seasoned_api/src/webserver/controllers/tmdb/getUpcoming.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const configuration = require('src/config/configuration').getInstance();
|
||||
const TMDB = require('src/tmdb/tmdb');
|
||||
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
|
||||
|
||||
/**
|
||||
* Controller: Retrieve upcoming movies
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function getUpcomingController(req, res) {
|
||||
const { page } = req.query;
|
||||
tmdb.upcoming(page)
|
||||
.then((results) => {
|
||||
res.send(results);
|
||||
}).catch((error) => {
|
||||
res.status(404).send({ success: false, error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = getUpcomingController;
|
||||
@@ -0,0 +1,21 @@
|
||||
const configuration = require('src/config/configuration').getInstance();
|
||||
const TMDB = require('src/tmdb/tmdb');
|
||||
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
|
||||
|
||||
/**
|
||||
* Controller: Retrieve nowplaying movies / now airing shows
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function nowPlayingMediaController(req, res) {
|
||||
const { page, type } = req.query;
|
||||
tmdb.nowplaying(page, type)
|
||||
.then((results) => {
|
||||
res.send(results);
|
||||
}).catch((error) => {
|
||||
res.status(404).send({ success: false, error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = nowPlayingMediaController;
|
||||
21
seasoned_api/src/webserver/controllers/tmdb/popularMedia.js
Normal file
21
seasoned_api/src/webserver/controllers/tmdb/popularMedia.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const configuration = require('src/config/configuration').getInstance();
|
||||
const TMDB = require('src/tmdb/tmdb');
|
||||
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
|
||||
|
||||
/**
|
||||
* Controller: Retrieve information for a movie
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function popularMediaController(req, res) {
|
||||
const { page, type } = req.query;
|
||||
tmdb.popular(page, type)
|
||||
.then((results) => {
|
||||
res.send(results);
|
||||
}).catch((error) => {
|
||||
res.status(404).send({ success: false, error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = popularMediaController;
|
||||
@@ -14,7 +14,7 @@ function searchMoviesController(req, res) {
|
||||
Promise.resolve()
|
||||
.then(() => tmdb.search(query, page, type))
|
||||
.then((movies) => {
|
||||
if (movies.length > 0) {
|
||||
if (movies !== undefined || movies.length > 0) {
|
||||
res.send(movies);
|
||||
} else {
|
||||
res.status(404).send({ success: false, error: 'Search query did not return any results.'})
|
||||
|
||||
22
seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js
Normal file
22
seasoned_api/src/webserver/controllers/tmdb/searchSimilar.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const configuration = require('src/config/configuration').getInstance();
|
||||
const TMDB = require('src/tmdb/tmdb');
|
||||
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
|
||||
|
||||
/**
|
||||
* Controller: Retrieve similar movies or shows
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function similarMediaController(req, res) {
|
||||
const mediaId = req.params.mediaId;
|
||||
const { type } = req.query;
|
||||
tmdb.similar(mediaId, type)
|
||||
.then((results) => {
|
||||
res.send(results);
|
||||
}).catch((error) => {
|
||||
res.status(404).send({ success: false, error: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = similarMediaController;
|
||||
Reference in New Issue
Block a user