Merge pull request #33 from KevinMidboe/update/frontend_logic
Update/frontend logic
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -11,3 +11,4 @@ client/dist | |||||||
| src/webserver/access.log | src/webserver/access.log | ||||||
| conf/development.json | conf/development.json | ||||||
| yarn-error.log | yarn-error.log | ||||||
|  | */yarn.lock | ||||||
|   | |||||||
| @@ -1,8 +1,12 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
|  |  | ||||||
|  | import Notifications, {notify} from 'react-notify-toast'; | ||||||
|  |  | ||||||
| // StyleComponents | // StyleComponents | ||||||
| import movieStyle from './styles/movieObjectStyle.jsx'; | import movieStyle from './styles/movieObjectStyle.jsx'; | ||||||
|  |  | ||||||
|  | var MediaQuery = require('react-responsive'); | ||||||
|  |  | ||||||
| class MovieObject { | class MovieObject { | ||||||
| 	constructor(object) { | 	constructor(object) { | ||||||
| 		this.id = object.id; | 		this.id = object.id; | ||||||
| @@ -10,7 +14,9 @@ class MovieObject { | |||||||
| 		this.year = object.year; | 		this.year = object.year; | ||||||
| 		this.type = object.type; | 		this.type = object.type; | ||||||
| 		// Check if object.poster != undefined | 		// Check if object.poster != undefined | ||||||
|  | 		this.rating = object.rating; | ||||||
| 		this.poster = object.poster; | 		this.poster = object.poster; | ||||||
|  | 		this.background = object.background; | ||||||
| 		this.matchedInPlex = object.matchedInPlex; | 		this.matchedInPlex = object.matchedInPlex; | ||||||
| 		this.summary = object.summary; | 		this.summary = object.summary; | ||||||
| 	} | 	} | ||||||
| @@ -20,10 +26,12 @@ class MovieObject { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	requestMovie() { | 	requestMovie() { | ||||||
| 		// fetch('https://apollo.kevinmidboe.com/api/v1/plex/request/' + id, { | 		// fetch('http://localhost:31459/api/v1/plex/request/' + this.id + '?type='+this.type, { | ||||||
| 		fetch('http://localhost:31459/api/v1/plex/request/' + this.id + '?type='+this.type, { | 		fetch('https://apollo.kevinmidboe.com/api/v1/plex/request/' + this.id + '?type='+this.type, { | ||||||
| 		  method: 'POST' | 		  method: 'POST' | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  | 		notify.show(this.title + ' requested!', 'success', 3000); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	getElement() { | 	getElement() { | ||||||
| @@ -31,8 +39,10 @@ class MovieObject { | |||||||
| 		if (this.poster == null || this.poster == undefined) { | 		if (this.poster == null || this.poster == undefined) { | ||||||
| 			var posterPath = 'https://openclipart.org/image/2400px/svg_to_png/211479/Simple-Image-Not-Found-Icon.png' | 			var posterPath = 'https://openclipart.org/image/2400px/svg_to_png/211479/Simple-Image-Not-Found-Icon.png' | ||||||
| 		} else { | 		} else { | ||||||
| 			var posterPath = 'https://image.tmdb.org/t/p/w154' + this.poster; | 			var posterPath = 'https://image.tmdb.org/t/p/w300' + this.poster; | ||||||
| 		} | 		} | ||||||
|  | 		var backgroundPath = 'https://image.tmdb.org/t/p/w640_and_h360_bestv2/' + this.background; | ||||||
|  |  | ||||||
| 		var foundInPlex; | 		var foundInPlex; | ||||||
| 		if (this.matchedInPlex) { | 		if (this.matchedInPlex) { | ||||||
| 			foundInPlex = <button onClick={() => {this.requestExisting(this)}}  | 			foundInPlex = <button onClick={() => {this.requestExisting(this)}}  | ||||||
| @@ -47,15 +57,31 @@ class MovieObject { | |||||||
|  |  | ||||||
| 		return ( | 		return ( | ||||||
| 		<div> | 		<div> | ||||||
|  | 		 	<Notifications /> | ||||||
| 			<div style={movieStyle.resultItem} key={this.id}> | 			<div style={movieStyle.resultItem} key={this.id}> | ||||||
|  | 				<MediaQuery minWidth={600}> | ||||||
| 				<div style={movieStyle.resultPoster}> | 				<div style={movieStyle.resultPoster}> | ||||||
| 					<img style={movieStyle.resultPosterImg} id='poster' src={posterPath}></img> | 					<img style={movieStyle.resultPosterImg} id='poster' src={posterPath}></img> | ||||||
| 				</div> | 				</div> | ||||||
|  | 				</MediaQuery> | ||||||
| 				<div> | 				<div> | ||||||
| 					<span style={movieStyle.resultTitle}>{this.title} ({this.year})</span> | 					<MediaQuery minWidth={600}> | ||||||
|  | 						<span style={movieStyle.resultTitleLarge}>{this.title}</span> | ||||||
| 						<br></br> | 						<br></br> | ||||||
| 						<span>{this.summary}</span> | 						<span style={movieStyle.yearRatingLarge}>Released: { this.year } | Rating: {this.rating}</span> | ||||||
| 						<br></br> | 						<br></br> | ||||||
|  | 						<span style={movieStyle.summary}>{this.summary}</span> | ||||||
|  | 						<br></br> | ||||||
|  | 					</MediaQuery> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 					<MediaQuery maxWidth={600}> | ||||||
|  | 						<img src={ backgroundPath } style={movieStyle.background}></img> | ||||||
|  | 						<span style={movieStyle.resultTitleSmall}>{this.title}</span> | ||||||
|  | 						<br></br> | ||||||
|  | 						<span style={movieStyle.yearRatingSmall}>Released: {this.year} | Rating: {this.rating}</span> | ||||||
|  | 					</MediaQuery> | ||||||
|  |  | ||||||
|  |  | ||||||
| 					<span className='imdbLogo'> | 					<span className='imdbLogo'> | ||||||
| 					</span> | 					</span> | ||||||
| @@ -68,6 +94,9 @@ class MovieObject { | |||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
|  | 			<MediaQuery maxWidth={600}> | ||||||
|  | 				<br></br> | ||||||
|  | 			</MediaQuery> | ||||||
| 			<div style={movieStyle.row}> | 			<div style={movieStyle.row}> | ||||||
| 				<div style={movieStyle.itemDivider}></div> | 				<div style={movieStyle.itemDivider}></div> | ||||||
| 			</div> | 			</div> | ||||||
|   | |||||||
| @@ -4,8 +4,12 @@ import MovieObject from './MovieObject.jsx'; | |||||||
|  |  | ||||||
| // StyleComponents | // StyleComponents | ||||||
| import searchStyle from './styles/searchRequestStyle.jsx'; | import searchStyle from './styles/searchRequestStyle.jsx'; | ||||||
|  | import movieStyle from './styles/movieObjectStyle.jsx'; | ||||||
|  |  | ||||||
| import URI from 'urijs'; | import URI from 'urijs'; | ||||||
|  | import InfiniteScroll from 'react-infinite-scroller'; | ||||||
|  |  | ||||||
|  | var MediaQuery = require('react-responsive'); | ||||||
|  |  | ||||||
| // TODO add option for searching multi, movies or tv shows | // TODO add option for searching multi, movies or tv shows | ||||||
| class SearchRequest extends React.Component { | class SearchRequest extends React.Component { | ||||||
| @@ -13,24 +17,28 @@ class SearchRequest extends React.Component { | |||||||
|     super(props) |     super(props) | ||||||
|     // Constructor with states holding the search query and the element of reponse. |     // Constructor with states holding the search query and the element of reponse. | ||||||
|     this.state = { |     this.state = { | ||||||
|  |       lastApiCallURI: '', | ||||||
|       searchQuery: '', |       searchQuery: '', | ||||||
|       responseMovieList: null, |       responseMovieList: null, | ||||||
|       movieFilter: true, |       movieFilter: false, | ||||||
|       showFilter: false, |       showFilter: false, | ||||||
|       discoverType: '', |       discoverType: '', | ||||||
|       page: 1 |       page: 1, | ||||||
|  |       resultHeader: '', | ||||||
|  |       loadResults: false, | ||||||
|  |       scrollHasMore: true | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this.allowedDiscoverTypes = [ |     this.allowedListTypes = [ | ||||||
|         'discover', 'popular', 'nowplaying', 'upcoming' |         'discover', 'popular', 'nowplaying', 'upcoming' | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb'; |     this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb/'; | ||||||
|     // this.baseUrl = 'http://localhost:31459/api/v1/tmdb/'; |     // this.baseUrl = 'http://localhost:31459/api/v1/tmdb/'; | ||||||
|  |  | ||||||
|     this.URLs = { |     this.URLs = { | ||||||
|       request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?page='+this.state.page+'&query=', |       searchRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request', | ||||||
|       // request: 'http://localhost:31459/api/v1/plex/request?page='+this.state.page+'&query=', |       // searchRequest: 'http://localhost:31459/api/v1/plex/request', | ||||||
|       upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming', |       upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming', | ||||||
|       // upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming', |       // upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming', | ||||||
|       sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=' |       sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=' | ||||||
| @@ -42,89 +50,225 @@ class SearchRequest extends React.Component { | |||||||
|   componentDidMount(){ |   componentDidMount(){ | ||||||
|     var that = this; |     var that = this; | ||||||
|     // this.setState({responseMovieList: null}) |     // this.setState({responseMovieList: null}) | ||||||
|     this.fetchDiscover('upcoming'); |     this.resetPageNumber(); | ||||||
|  |     this.state.loadResults = true; | ||||||
|  |     this.fetchTmdbList('upcoming'); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|     // Handles all errors of the response of a fetch call |     // Handles all errors of the response of a fetch call | ||||||
|     handleErrors(response) { |     handleErrors(response) { | ||||||
|     if (!response.ok) { |         if (!response.ok) | ||||||
|             throw Error(response.status); |             throw Error(response.status); | ||||||
|  |         return response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     handleQueryError(response) { | ||||||
|  |         if (!response.ok) { | ||||||
|  |             if (response.status === 404) { | ||||||
|  |                 this.setState({ | ||||||
|  |                     responseMovieList: <h1>Nothing found for search query: { this.findQueryInURI(uri) }</h1> | ||||||
|  |                 }) | ||||||
|  |             } | ||||||
|  |             console.log('handleQueryError: ', error); | ||||||
|         } |         } | ||||||
|         return response; |         return response; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Unpacks the query value of a uri | ||||||
|  |     findQueryValueInURI(uri) { | ||||||
|  |         let uriSearchValues = uri.query(true); | ||||||
|  |         let queryValue = uriSearchValues['query'] | ||||||
|  |  | ||||||
|   fetchDiscover(queryDiscoverType) { |         return queryValue; | ||||||
|     if (this.allowedDiscoverTypes.indexOf(queryDiscoverType) === -1) |     } | ||||||
|         throw Error('Invalid discover type: ' + queryDiscoverType); |  | ||||||
|  |  | ||||||
|     var uri = new URI(this.baseUrl); |     // Unpacks the page value of a uri | ||||||
|     uri.segment(queryDiscoverType) |     findPageValueInURI(uri) { | ||||||
|     uri = uri.setSearch('page', this.state.page); |         let uriSearchValues = uri.query(true); | ||||||
|     if (this.state.showFilter) |         let queryValue = uriSearchValues['page'] | ||||||
|         uri = uri.addSearch('type', 'show'); |  | ||||||
|  |  | ||||||
|     console.log(uri) |         return queryValue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     resetPageNumber() { | ||||||
|  |         this.state.page = 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     writeLoading() { | ||||||
|         this.setState({ |         this.setState({ | ||||||
|             responseMovieList: 'Loading...' |             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()); |     // Test this by calling missing endpoint or 404 query and see what code | ||||||
|  |     // and filter the error message based on the code. | ||||||
|  |     // Calls a uri and returns the response as json | ||||||
|  |     callURI(uri) { | ||||||
|  |         return fetch(uri) | ||||||
|  |         .then(response => { return response }) | ||||||
|  |         .catch(error => { | ||||||
|  |             throw Error('Something went wrong while fetching URI.'); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Saves the input string as a h1 element in responseMovieList state | ||||||
|   fetchQuery() { |     fillResponseMovieListWithError(msg) { | ||||||
|     let url = this.URLs.request + this.state.searchQuery |         this.setState({ | ||||||
|     if (this.state.showFilter) { |             responseMovieList: <h1>{ msg }</h1> | ||||||
|       url = url + '&type=tv' |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   fetch(url) |  | ||||||
|     // Check if the response is ok |     // Here we first call api for a search with the input uri, handle any errors | ||||||
|     .then(response => this.handleErrors(response)) |     // and fill the reponseData from api into the state of reponseMovieList as movieObjects | ||||||
|     .then(response => response.json()) // Convert to json object and pass to next then |     callSearchFillMovieList(uri) { | ||||||
|     .then(data => {  // Parse the data of the JSON response |         // Write loading animation | ||||||
|       // If it is something here it updates the state variable with the HTML list of all  |         // this.writeLoading(); | ||||||
|       // movie objects that where returned by the search request |          | ||||||
|       if (data.results.length > 0) { |         Promise.resolve() | ||||||
|  |         .then(() => this.callURI(uri)) | ||||||
|  |         .then(response => { | ||||||
|  |             // If we get a error code for the request | ||||||
|  |             if (!response.ok) { | ||||||
|  |                 if (response.status === 404) { | ||||||
|  |                     if (this.findPageValueInURI(new URI(response.url)) > 1) { | ||||||
|  |                         this.state.scrollHasMore = false; | ||||||
|  |                         console.log(this.state.scrollHasMore) | ||||||
|  |                         return null | ||||||
|  |                         let returnMessage = 'this is the return mesasge than will never be delivered' | ||||||
|  |                         let theSecondReturnMsg = 'this is the second return messag ethat will NEVE be delivered' | ||||||
|  |                     } | ||||||
|  |                     else {                     | ||||||
|  |  | ||||||
|  |                         let errorMsg = 'Nothing found for the search query: ' + this.findQueryValueInURI(uri); | ||||||
|  |                         this.fillResponseMovieListWithError(errorMsg) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     let errorMsg = 'Error fetching query from server ' + this.response.status; | ||||||
|  |                     this.fillResponseMovieListWithError(errorMsg)  | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Convert to json and update the state of responseMovieList with the results of the api call | ||||||
|  |             // mapped as a movieObject. | ||||||
|  |             response.json() | ||||||
|  |             .then(responseData => { | ||||||
|  |                 if (this.state.page === 1) { | ||||||
|                     this.setState({ |                     this.setState({ | ||||||
|           responseMovieList: data.results.map(item => this.createMovieObjects(item)) |                         responseMovieList: responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)), | ||||||
|  |                         lastApiCallURI: uri  // Save the value of the last sucessfull api call | ||||||
|  |                     }) | ||||||
|  |                 } else { | ||||||
|  |                     let responseMovieObjects = responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)); | ||||||
|  |                     let growingReponseMovieObjectList = this.state.responseMovieList.concat(responseMovieObjects); | ||||||
|  |                     this.setState({ | ||||||
|  |                         responseMovieList: growingReponseMovieObjectList, | ||||||
|  |                         lastApiCallURI: uri  // Save the value of the last sucessfull api call | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|     // If the -------- |             .catch((error) => { | ||||||
|     .catch(error => { |                 console.log('CallSearchFillMovieList: ', error) | ||||||
|       console.log(error) |  | ||||||
|       this.setState({ |  | ||||||
|         responseMovieList: <h1>Not Found</h1> |  | ||||||
|             }) |             }) | ||||||
|  |         }) | ||||||
|  |         .catch(() => { | ||||||
|  |             throw Error('Something went wrong when fetching query.') | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|       console.log('Error submit: ', error.toString()); |     callListFillMovieList(uri) { | ||||||
|  |         // Write loading animation | ||||||
|  |         // this.writeLoading(); | ||||||
|  |          | ||||||
|  |         Promise.resolve() | ||||||
|  |         .then(() => this.callURI(uri)) | ||||||
|  |         .then(response => { | ||||||
|  |             // If we get a error code for the request | ||||||
|  |             if (!response.ok) { | ||||||
|  |                 if (response.status === 404) { | ||||||
|  |                     let errorMsg = 'List not found'; | ||||||
|  |                     this.fillResponseMovieListWithError(errorMsg) | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     let errorMsg = 'Error fetching list from server ' + this.response.status; | ||||||
|  |                     this.fillResponseMovieListWithError(errorMsg)  | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Convert to json and update the state of responseMovieList with the results of the api call | ||||||
|  |             // mapped as a movieObject. | ||||||
|  |             response.json() | ||||||
|  |             .then(responseData => { | ||||||
|  |                 if (this.state.page === 1) { | ||||||
|  |                     this.setState({ | ||||||
|  |                         responseMovieList: responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)), | ||||||
|  |                         lastApiCallURI: uri  // Save the value of the last sucessfull api call | ||||||
|  |                     }) | ||||||
|  |                 } else { | ||||||
|  |                     let responseMovieObjects = responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)); | ||||||
|  |                     let growingReponseMovieObjectList = this.state.responseMovieList.concat(responseMovieObjects); | ||||||
|  |                     this.setState({ | ||||||
|  |                         responseMovieList: growingReponseMovieObjectList, | ||||||
|  |                         lastApiCallURI: uri  // Save the value of the last sucessfull api call | ||||||
|  |                     }) | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |         }) | ||||||
|  |         .catch(() => { | ||||||
|  |             throw Error('Something went wrong when fetching query.') | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     searchSeasonedRequest() { | ||||||
|  |         this.state.resultHeader = 'Search result for: ' + this.state.searchQuery; | ||||||
|  |  | ||||||
|  |         // Build uri with the url for searching requests | ||||||
|  |         var uri = new URI(this.URLs.searchRequest); | ||||||
|  |         // Add input of search query and page count to the uri payload | ||||||
|  |         uri = uri.search({ 'query': this.state.searchQuery, 'page': this.state.page }); | ||||||
|  |          | ||||||
|  |         if (this.state.showFilter) | ||||||
|  |             uri = uri.addSearch('type', 'show'); | ||||||
|  |         else  | ||||||
|  |             if (this.state.movieFilter) | ||||||
|  |                 uri = uri.addSearch('type', 'movie') | ||||||
|  |  | ||||||
|  |         // Send uri to call and fill the response list with movie/show objects | ||||||
|  |         this.callSearchFillMovieList(uri); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fetchTmdbList(tmdbListType) { | ||||||
|  |         console.log(tmdbListType) | ||||||
|  |         // Check if it is a whitelisted list, this should be replaced with checking if the return call is 500 | ||||||
|  |         if (this.allowedListTypes.indexOf(tmdbListType) === -1) | ||||||
|  |             throw Error('Invalid discover type: ' + tmdbListType); | ||||||
|  |  | ||||||
|  |         this.state.responseMovieList = [] | ||||||
|  |         // Captialize the first letter of and save the discoverQueryType to resultHeader state.  | ||||||
|  |         this.state.resultHeader = tmdbListType.toLowerCase().replace(/\b[a-z]/g, function(letter) { | ||||||
|  |             return letter.toUpperCase(); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         // Build uri with the url for searching requests | ||||||
|  |         var uri = new URI(this.baseUrl); | ||||||
|  |         uri.segment(tmdbListType); | ||||||
|  |         // Add input of search query and page count to the uri payload | ||||||
|  |         uri = uri.search({ 'page': this.state.page }); | ||||||
|  |          | ||||||
|  |         if (this.state.showFilter) | ||||||
|  |             uri = uri.addSearch('type', 'show'); | ||||||
|  |  | ||||||
|  |         // Send uri to call and fill the response list with movie/show objects | ||||||
|  |         this.callListFillMovieList(uri); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   // Updates the internal state of the query search field. |   // Updates the internal state of the query search field. | ||||||
|   updateQueryState(event){ |   updateQueryState(event){ | ||||||
|     this.setState({ |     this.setState({ | ||||||
| @@ -135,7 +279,10 @@ class SearchRequest extends React.Component { | |||||||
|   // For checking if the enter key was pressed in the search field. |   // For checking if the enter key was pressed in the search field. | ||||||
|   _handleQueryKeyPress(e) { |   _handleQueryKeyPress(e) { | ||||||
|     if (e.key === 'Enter') { |     if (e.key === 'Enter') { | ||||||
|       this.fetchQuery(); |         // this.fetchQuery(); | ||||||
|  |         // Reset page number for a new search | ||||||
|  |         this.resetPageNumber(); | ||||||
|  |         this.searchSeasonedRequest(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -163,63 +310,135 @@ class SearchRequest extends React.Component { | |||||||
|  |  | ||||||
|     pageBackwards() { |     pageBackwards() { | ||||||
|         if (this.state.page > 1) { |         if (this.state.page > 1) { | ||||||
|       console.log('backwards'); |             let pageNumber = this.state.page - 1; | ||||||
|       this.state.page--; |             let uri = this.state.lastApiCallURI; | ||||||
|       this.getUpcoming(); |              | ||||||
|  |             // Augment the page number of the uri with a callback | ||||||
|  |             uri.search(function(data) { | ||||||
|  |                 data.page = pageNumber; | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             // Call the api with the new uri | ||||||
|  |             this.callSearchFillMovieList(uri); | ||||||
|  |             // Update state of our page number after the call is done | ||||||
|  |             this.state.page = pageNumber; | ||||||
|             } |             } | ||||||
|     console.log(this.state.page) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO need to get total page number and save in a state to not overflow | ||||||
|     pageForwards() { |     pageForwards() { | ||||||
|     this.state.page++; |         // Wrap this in the check | ||||||
|     this.getUpcoming(); |         let pageNumber = this.state.page + 1; | ||||||
|     console.log('forwards'); |         let uri = this.state.lastApiCallURI; | ||||||
|     console.log(this.state.page) |          | ||||||
|  |         // Augment the page number of the uri with a callback | ||||||
|  |         uri.search(function(data) { | ||||||
|  |             data.page = pageNumber; | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Call the api with the new uri | ||||||
|  |         this.callSearchFillMovieList(uri); | ||||||
|  |         // Update state of our page number after the call is done | ||||||
|  |         this.state.page = pageNumber; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     movieToggle() { | ||||||
|  |         if (this.state.movieFilter)  | ||||||
|  |             return <span style={searchStyle.searchFilterActive} | ||||||
|  |                 className="search_category hvrUnderlineFromCenter"  | ||||||
|  |                 onClick={() => {this.toggleFilter('movies')}} | ||||||
|  |                 id="category_active">Movies</span> | ||||||
|  |         else | ||||||
|  |             return <span style={searchStyle.searchFilterNotActive} | ||||||
|  |                 className="search_category hvrUnderlineFromCenter"  | ||||||
|  |                 onClick={() => {this.toggleFilter('movies')}} | ||||||
|  |                 id="category_active">Movies</span> | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     showToggle() { | ||||||
|  |         if (this.state.showFilter)  | ||||||
|  |             return <span style={searchStyle.searchFilterActive} | ||||||
|  |                 className="search_category hvrUnderlineFromCenter"  | ||||||
|  |                 onClick={() => {this.toggleFilter('shows')}} | ||||||
|  |                 id="category_active">TV Shows</span> | ||||||
|  |         else | ||||||
|  |             return <span style={searchStyle.searchFilterNotActive} | ||||||
|  |                 className="search_category hvrUnderlineFromCenter"  | ||||||
|  |                 onClick={() => {this.toggleFilter('shows')}} | ||||||
|  |                 id="category_active">TV Shows</span> | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|   render(){ |   render(){ | ||||||
|     return( |     const loader = <div className="loader">Loading ...<br></br></div>; | ||||||
|      <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}> |  | ||||||
|  |     return( | ||||||
|  |          <InfiniteScroll | ||||||
|  |                 pageStart={0} | ||||||
|  |                 loadMore={this.pageForwards.bind(this)} | ||||||
|  |                 hasMore={this.state.scrollHasMore} | ||||||
|  |                 loader={loader} | ||||||
|  |                 initialLoad={this.state.loadResults}> | ||||||
|  |  | ||||||
|  |                 <MediaQuery minWidth={600}> | ||||||
|  |                     <div style={searchStyle.body}> | ||||||
|  |                         <div className='backgroundHeader' style={searchStyle.backgroundLargeHeader}> | ||||||
|                             <div className='pageTitle' style={searchStyle.pageTitle}> |                             <div className='pageTitle' style={searchStyle.pageTitle}> | ||||||
|               <span style={searchStyle.pageTitleSpan}>Request new movies or tv shows</span> |                                 <span style={searchStyle.pageTitleLargeSpan}>Request new content</span> | ||||||
|                             </div> |                             </div> | ||||||
|                              |                              | ||||||
|                             <div className='box' style={searchStyle.box}> |                             <div className='box' style={searchStyle.box}> | ||||||
|               <div style={searchStyle.container}> |                                 <div style={searchStyle.searchLargeContainer}> | ||||||
|                                     <span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span> |                                     <span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span> | ||||||
|  |  | ||||||
|                 <input style={searchStyle.searchBar} type="text" id="search" placeholder="Search for new content..."  |                                     <input style={searchStyle.searchLargeBar} type="text" id="search" placeholder="Search for new content..."  | ||||||
|                                     onKeyPress={(event) => this._handleQueryKeyPress(event)} |                                     onKeyPress={(event) => this._handleQueryKeyPress(event)} | ||||||
|                                     onChange={event => this.updateQueryState(event)} |                                     onChange={event => this.updateQueryState(event)} | ||||||
|                                     value={this.state.searchQuery}/> |                                     value={this.state.searchQuery}/> | ||||||
|  |  | ||||||
|                 <span style={searchStyle.searchFilter} |  | ||||||
|                   className="search_category hvrUnderlineFromCenter"  |  | ||||||
|                   onClick={() => {this.toggleFilter('movies')}} |  | ||||||
|                   id="category_active">Movies</span> |  | ||||||
|                 <span style={searchStyle.searchFilter}  |  | ||||||
|                   className="search_category hvrUnderlineFromCenter"  |  | ||||||
|                   onClick={() => {this.toggleFilter('shows')}} |  | ||||||
|                   id="category_inactive">TV Shows</span> |  | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|  |  | ||||||
|                         <div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}> |                         <div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}> | ||||||
|  |                             <span style={searchStyle.resultLargeHeader}>{this.state.resultHeader}</span> | ||||||
|  |                             <br></br><br></br> | ||||||
|  |                              | ||||||
|                             {this.state.responseMovieList}      |                             {this.state.responseMovieList}      | ||||||
|                         </div> |                         </div> | ||||||
|           <div> |                     </div> | ||||||
|             <button onClick={() => {this.pageBackwards()}}>Back</button> |                 </MediaQuery> | ||||||
|             <button onClick={() => {this.pageForwards()}}>Forward</button> |  | ||||||
|  |                 <MediaQuery maxWidth={600}> | ||||||
|  |                      <div style={searchStyle.body}> | ||||||
|  |                         <div className='backgroundHeader' style={searchStyle.backgroundSmallHeader}> | ||||||
|  |                             <div className='pageTitle' style={searchStyle.pageTitle}> | ||||||
|  |                                 <span style={searchStyle.pageTitleSmallSpan}>Request new content</span> | ||||||
|  |                             </div> | ||||||
|  |                              | ||||||
|  |                             <div className='box' style={searchStyle.box}> | ||||||
|  |                                 <div style={searchStyle.searchSmallContainer}> | ||||||
|  |                                     <span style={searchStyle.searchIcon}><i className="fa fa-search"></i></span> | ||||||
|  |  | ||||||
|  |                                     <input style={searchStyle.searchSmallBar} type="text" id="search" placeholder="Search for new content..."  | ||||||
|  |                                     onKeyPress={(event) => this._handleQueryKeyPress(event)} | ||||||
|  |                                     onChange={event => this.updateQueryState(event)} | ||||||
|  |                                     value={this.state.searchQuery}/> | ||||||
|  |  | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|  |                         </div> | ||||||
|  |  | ||||||
|  |                         <div id='requestMovieList' ref='requestMovieList' style={searchStyle.requestWrapper}> | ||||||
|  |                             <span style={searchStyle.resultSmallHeader}>{this.state.resultHeader}</span> | ||||||
|  |                             <br></br><br></br> | ||||||
|  |  | ||||||
|  |                             {this.state.responseMovieList}      | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </MediaQuery> | ||||||
|  |             </InfiniteScroll> | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,21 +6,24 @@ export default { | |||||||
| 		minHeight: '230px' | 		minHeight: '230px' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	resultItem: { |  | ||||||
| 		maxWidth: '95%', |  | ||||||
| 		margin: '0 auto', |  | ||||||
| 		minHeight: '230px' |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	movie_content: { | 	movie_content: { | ||||||
| 		marginLeft: '15px' | 		marginLeft: '15px' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	resultTitle: { | 	resultTitleLarge: { | ||||||
| 		color: 'black', | 		color: 'black', | ||||||
| 		fontSize: '2em', | 		fontSize: '2em', | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	resultTitleSmall: { | ||||||
|  | 		color: 'black', | ||||||
|  | 		fontSize: '22px', | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	yearRatingLarge: { | ||||||
|  | 		fontSize: '0.8em' | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	resultPoster: { | 	resultPoster: { | ||||||
| 		float: 'left', | 		float: 'left', | ||||||
| 		zIndex: '3', | 		zIndex: '3', | ||||||
| @@ -28,12 +31,30 @@ export default { | |||||||
| 		marginRight: '30px' | 		marginRight: '30px' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	background: { | ||||||
|  | 		width: '100%' | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	yearRatingSmall: { | ||||||
|  | 		marginTop: '5px', | ||||||
|  | 		fontSize: '0.8em' | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	resultPosterImg: { | 	resultPosterImg: { | ||||||
| 		border: '2px none', | 		border: '2px none', | ||||||
| 	    borderRadius: '2px', | 	    borderRadius: '2px', | ||||||
| 	    width: '150px' | 	    width: '150px' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	cornerRibbon: { | ||||||
|  | 		position: 'absolute', | ||||||
|  | 		width: '450px', | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	summary: { | ||||||
|  | 		fontSize: '15px', | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	buttons: { | 	buttons: { | ||||||
| 		paddingTop: '20px' | 		paddingTop: '20px' | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
| @@ -6,23 +6,29 @@ export default { | |||||||
|       margin: 0, |       margin: 0, | ||||||
|       padding: 0, |       padding: 0, | ||||||
|       minHeight: '100%', |       minHeight: '100%', | ||||||
|       position: 'relative' |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     backgroundHeader: { |     backgroundLargeHeader: { | ||||||
|       width: '100%', |       width: '100%', | ||||||
|       minHeight: '400px', |       minHeight: '400px', | ||||||
|       backgroundColor: '#011c23', |       backgroundColor: '#011c23', | ||||||
|       zIndex: 1, |       zIndex: 1, | ||||||
|       position: 'absolute' |       marginBottom: '-100px' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |   backgroundSmallHeader: { | ||||||
|  |       width: '100%', | ||||||
|  |       minHeight: '300px', | ||||||
|  |       backgroundColor: '#011c23', | ||||||
|  |       zIndex: 1, | ||||||
|  |       marginBottom: '-100px' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     requestWrapper: { |     requestWrapper: { | ||||||
|       top: '300px', |  | ||||||
|       width: '90%', |       width: '90%', | ||||||
|       maxWidth: '1200px', |       maxWidth: '1200px', | ||||||
|       margin: 'auto', |       margin: 'auto', | ||||||
|       paddingTop: '20px', |       // paddingTop: '20px', | ||||||
|       backgroundColor: 'white', |       backgroundColor: 'white', | ||||||
|       position: 'relative', |       position: 'relative', | ||||||
|       zIndex: '10', |       zIndex: '10', | ||||||
| @@ -32,42 +38,46 @@ export default { | |||||||
|     pageTitle: { |     pageTitle: { | ||||||
|       display: 'flex', |       display: 'flex', | ||||||
|       alignItems: 'center', |       alignItems: 'center', | ||||||
|       justifyContent: 'center' |       justifyContent: 'center', | ||||||
|  |       textAlign: 'center' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     pageTitleSpan: { |     pageTitleLargeSpan: { | ||||||
|       color: 'white', |       color: 'white', | ||||||
|       fontSize: '3em', |       fontSize: '3em', | ||||||
|       marginTop: '4vh', |       marginTop: '4vh', | ||||||
|       marginBottom: '6vh' |       marginBottom: '6vh' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     box: { |     pageTitleSmallSpan: { | ||||||
|       width: '90%', |       color: 'white', | ||||||
|       height: '50px', |       fontSize: '2em', | ||||||
|       maxWidth: '1200px', |       marginTop: '3vh', | ||||||
|       margin: '0 auto' |       marginBottom: '3vh' | ||||||
|     },     |     },     | ||||||
|  |  | ||||||
|     container: { |     box: { | ||||||
|       verticalAlign: 'middle', |       height: '50px', | ||||||
|       whiteSpace: 'nowrap', |     }, | ||||||
|       position: 'relative', |  | ||||||
|       display: 'flex', |     searchLargeContainer: { | ||||||
|       justifyContent: 'center' |       margin: '0 25%', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     searchSmallContainer: { | ||||||
|  |       margin: '0 10%', | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     searchIcon: { |     searchIcon: { | ||||||
|       position: 'absolute', |       position: 'absolute', | ||||||
|       marginLeft: '17px', |       fontSize: '1.2em', | ||||||
|       marginTop: '17px', |       marginTop: '12px', | ||||||
|       zIndex: '1', |       marginLeft: '-13px', | ||||||
|       color: '#4f5b66' |       color: '#4f5b66' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     searchBar: { |     searchLargeBar: { | ||||||
|       width: '60%', |       width: '100%', | ||||||
|       minWidth: '120px', |  | ||||||
|       height: '50px', |       height: '50px', | ||||||
|       background: '#ffffff', |       background: '#ffffff', | ||||||
|       border: 'none', |       border: 'none', | ||||||
| @@ -75,19 +85,78 @@ export default { | |||||||
|       float: 'left', |       float: 'left', | ||||||
|       color: '#63717f', |       color: '#63717f', | ||||||
|       paddingLeft: '45px', |       paddingLeft: '45px', | ||||||
|  |       marginLeft: '-25px', | ||||||
|       borderRadius: '5px', |       borderRadius: '5px', | ||||||
|       marginRight: '15px' |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     searchFilter: { |     searchSmallBar: { | ||||||
|       color: 'white', |       width: '100%', | ||||||
|  |       height: '50px', | ||||||
|  |       background: '#ffffff', | ||||||
|  |       border: 'none', | ||||||
|  |       fontSize: '13pt', | ||||||
|  |       float: 'left', | ||||||
|  |       color: '#63717f', | ||||||
|  |       paddingLeft: '45px', | ||||||
|  |       marginLeft: '-25px', | ||||||
|  |       borderRadius: '5px', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     searchFilterActive: { | ||||||
|  |       color: '#00d17c', | ||||||
|       fontSize: '1em', |       fontSize: '1em', | ||||||
|       paddingTop: '12px', |  | ||||||
|       marginBottom: '12px', |  | ||||||
|       marginLeft: '10px', |       marginLeft: '10px', | ||||||
|       cursor: 'pointer' |       cursor: 'pointer' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     searchFilterNotActive: { | ||||||
|  |       color: 'white', | ||||||
|  |       fontSize: '1em', | ||||||
|  |       marginLeft: '10px', | ||||||
|  |       cursor: 'pointer' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     filter: { | ||||||
|  |       color: 'white', | ||||||
|  |       paddingLeft: '40px', | ||||||
|  |       width: '60%', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     resultLargeHeader: { | ||||||
|  |       paddingLeft: '30px', | ||||||
|  |       color: 'black', | ||||||
|  |       fontSize: '2em', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     resultSmallHeader: { | ||||||
|  |       paddingLeft: '30px', | ||||||
|  |       color: 'black', | ||||||
|  |       fontSize: '1.7em', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     row: { | ||||||
|  |       width: '100%' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     itemDivider: { | ||||||
|  |       width: '90%', | ||||||
|  |       borderBottom: '1px solid grey', | ||||||
|  |       margin: '1rem auto' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     pageNavigationBar: { | ||||||
|  |       width: '100%', | ||||||
|  |       display: 'flex', | ||||||
|  |       alignItems: 'center', | ||||||
|  |       justifyContent: 'center' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     pageNavigationButton: { | ||||||
|  |       margin: '0 auto', | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     hvrUnderlineFromCenter: { |     hvrUnderlineFromCenter: { | ||||||
|       color: 'white', |       color: 'white', | ||||||
|       fontSize: '1em', |       fontSize: '1em', | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <meta charset="utf-8"> |     <meta charset="utf-8"> | ||||||
|     <link href="https://fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet"> |     <link href="https://fonts.googleapis.com/css?family=Open+Sans:300" rel="stylesheet"> | ||||||
|     <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"> |     <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"> | ||||||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|     <title>seasoned Shows</title> |     <title>seasoned Shows</title> | ||||||
|   </head> |   </head> | ||||||
|   <body style='margin: 0'> |   <body style='margin: 0'> | ||||||
|   | |||||||
| @@ -13,7 +13,12 @@ | |||||||
|     "html-webpack-plugin": "^2.28.0", |     "html-webpack-plugin": "^2.28.0", | ||||||
|     "path": "^0.12.7", |     "path": "^0.12.7", | ||||||
|     "react": "^15.6.1", |     "react": "^15.6.1", | ||||||
|  |     "react-burger-menu": "^2.1.6", | ||||||
|     "react-dom": "^15.5.4", |     "react-dom": "^15.5.4", | ||||||
|  |     "react-infinite-scroller": "^1.0.15", | ||||||
|  |     "react-notify-toast": "^0.3.2", | ||||||
|  |     "react-responsive": "^1.3.4", | ||||||
|  |     "urijs": "^1.18.12", | ||||||
|     "webfontloader": "^1.6.28", |     "webfontloader": "^1.6.28", | ||||||
|     "webpack": "^3.5.5", |     "webpack": "^3.5.5", | ||||||
|     "webpack-dev-server": "^2.4.5" |     "webpack-dev-server": "^2.4.5" | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ class mailTemplate { | |||||||
| 	 | 	 | ||||||
| 	constructor(mediaItem) { | 	constructor(mediaItem) { | ||||||
| 		this.mediaItem = mediaItem; | 		this.mediaItem = mediaItem; | ||||||
| 		this.posterURL = 'https://image.tmdb.org/t/p/w600/'; | 		this.posterURL = 'https://image.tmdb.org/t/p/w600'; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	toText() { | 	toText() { | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ const tmdb = new TMDB(configuration.get('tmdb', 'apiKey')); | |||||||
| var Promise = require('bluebird'); | var Promise = require('bluebird'); | ||||||
| var rp = require('request-promise'); | var rp = require('request-promise'); | ||||||
|  |  | ||||||
|  | const establishedDatabase = require('src/database/database'); | ||||||
|  |  | ||||||
| const MailTemplate = require('src/plex/mailTemplate') | const MailTemplate = require('src/plex/mailTemplate') | ||||||
|  |  | ||||||
| var pythonShell = require('python-shell'); | var pythonShell = require('python-shell'); | ||||||
| @@ -15,6 +17,13 @@ const nodemailer = require('nodemailer'); | |||||||
|  |  | ||||||
| class RequestRepository { | class RequestRepository { | ||||||
|  |  | ||||||
|  | 	constructor(database) { | ||||||
|  | 		this.database = database || establishedDatabase; | ||||||
|  | 		this.queries = { | ||||||
|  | 			'insertRequest': "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, CURRENT_DATE)" | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	searchRequest(query, page, type) { | 	searchRequest(query, page, type) { | ||||||
| 		// TODO get from cache | 		// TODO get from cache | ||||||
| 		// STRIP METADATA THAT IS NOT ALLOWED | 		// STRIP METADATA THAT IS NOT ALLOWED | ||||||
| @@ -99,23 +108,31 @@ class RequestRepository { | |||||||
| 	* @param {identifier, type} the id of the media object and type of media must be defined | 	* @param {identifier, type} the id of the media object and type of media must be defined | ||||||
| 	* @returns {Promise} If nothing has gone wrong. | 	* @returns {Promise} If nothing has gone wrong. | ||||||
| 	*/  | 	*/  | ||||||
| 	sendRequest(identifier, type) { | 	sendRequest(identifier, type, ip) { | ||||||
| 		// TODO add to DB so can have a admin page | 		// TODO add to DB so can have a admin page | ||||||
| 		// TODO try a cache hit on the movie item | 		// TODO try a cache hit on the movie item | ||||||
|  |  | ||||||
| 		tmdb.lookup(identifier, type).then(movie => { | 		tmdb.lookup(identifier, type).then(movie => { | ||||||
|  |  | ||||||
|  | 			// Add request to database | ||||||
|  | 			this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster, 'NULL', ip]) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 			//  | ||||||
|  |  | ||||||
|  |  | ||||||
| 			// create reusable transporter object using the default SMTP transport | 			// create reusable transporter object using the default SMTP transport | ||||||
| 			let transporter = nodemailer.createTransport({ | 			let transporter = nodemailer.createTransport({ | ||||||
| 			    host: configuration.get('mail', 'host'), | 				service: 'gmail', | ||||||
| 			    port: 26, |  | ||||||
| 			    ignoreTLS: true, |  | ||||||
| 			    tls :{rejectUnauthorized: false}, |  | ||||||
| 			    secure: false, // secure:true for port 465, secure:false for port 587 |  | ||||||
| 			    auth: { | 			    auth: { | ||||||
| 			        user: configuration.get('mail', 'user'), | 			        user: configuration.get('mail', 'user_pi'), | ||||||
| 			        pass: configuration.get('mail', 'password') | 			        pass: configuration.get('mail', 'password_pi') | ||||||
| 			    } | 			    } | ||||||
|  | 			    // host: configuration.get('mail', 'host'), | ||||||
|  | 			    // port: 26, | ||||||
|  | 			    // ignoreTLS: true, | ||||||
|  | 			    // tls :{rejectUnauthorized: false}, | ||||||
|  | 			    // secure: false, // secure:true for port 465, secure:false for port 587 | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
| 			const mailTemplate = new MailTemplate(movie) | 			const mailTemplate = new MailTemplate(movie) | ||||||
| @@ -123,7 +140,7 @@ class RequestRepository { | |||||||
| 			// setup email data with unicode symbols | 			// setup email data with unicode symbols | ||||||
| 			let mailOptions = { | 			let mailOptions = { | ||||||
| 				// TODO get the mail adr from global location (easy to add) | 				// TODO get the mail adr from global location (easy to add) | ||||||
| 			    from: 'MovieRequester <support@kevinmidboe.com>', // sender address | 			    from: 'MovieRequester <pi.midboe@gmail.com>', // sender address | ||||||
| 			    to: 'kevin.midboe@gmail.com', // list of receivers | 			    to: 'kevin.midboe@gmail.com', // list of receivers | ||||||
| 			    subject: 'Download request', // Subject line | 			    subject: 'Download request', // Subject line | ||||||
| 			    text: mailTemplate.toText(), | 			    text: mailTemplate.toText(), | ||||||
|   | |||||||
| @@ -2,10 +2,13 @@ const Movie = require('src/media_classes/movie'); | |||||||
| const Show = require('src/media_classes/show'); | const Show = require('src/media_classes/show'); | ||||||
|  |  | ||||||
| function convertTmdbToSeasoned(tmdbObject, strictType=undefined) { | function convertTmdbToSeasoned(tmdbObject, strictType=undefined) { | ||||||
| 	if (strictType === undefined) | 	// TODO create a default fallback class to set the when falls to else as both are undefined | ||||||
|  | 	if (tmdbObject.media_type !== undefined) | ||||||
| 		var mediaType = tmdbObject.media_type; | 		var mediaType = tmdbObject.media_type; | ||||||
| 	else | 	else if (strictType !== undefined) | ||||||
| 		var mediaType = strictType; | 		var mediaType = strictType; | ||||||
|  | 	else | ||||||
|  | 		var mediaType = 'movie'; | ||||||
|  |  | ||||||
| 	// There are many diff types of content, we only want to look at movies and tv shows | 	// There are many diff types of content, we only want to look at movies and tv shows | ||||||
| 	if (mediaType === 'movie') { | 	if (mediaType === 'movie') { | ||||||
|   | |||||||
| @@ -22,15 +22,16 @@ class TMDB { | |||||||
| 		return Promise.resolve() | 		return Promise.resolve() | ||||||
| 		 .then(() => this.tmdb(type, query))  // Search the tmdb api | 		 .then(() => this.tmdb(type, query))  // Search the tmdb api | ||||||
| 		 .catch(() => { throw new Error('Could not search for movies.'); })  // If any error at all when fetching | 		 .catch(() => { throw new Error('Could not search for movies.'); })  // If any error at all when fetching | ||||||
| 		 .then((reponse) => { | 		 .then((response) => { | ||||||
| 		 	try { | 		 	try { | ||||||
| 		 		// We want to filter because there are movies really low rated that are not interesting to us.  | 		 		// We want to filter because there are movies really low rated that are not interesting to us.  | ||||||
| 		 		let filteredTmdbItems = reponse.results.filter(function(tmdbResultItem) { | 		 		let filteredTmdbItems = response.results.filter(function(tmdbResultItem) { | ||||||
| 		 			return ((tmdbResultItem.vote_count >= 80 || tmdbResultItem.popularity > 18) && (tmdbResultItem.release_date !== undefined || tmdbResultItem.first_air_date !== undefined)) | 		 			return ((tmdbResultItem.vote_count >= 80 || tmdbResultItem.popularity > 18) && (tmdbResultItem.release_date !== undefined || tmdbResultItem.first_air_date !== undefined)) | ||||||
| 		 		}) | 		 		}) | ||||||
|  |  | ||||||
| 		 		// Here we convert the filtered result from the tmdb api to seaonsed objects | 		 		// Here we convert the filtered result from the tmdb api to seaonsed objects | ||||||
| 		 		let seasonedItems = filteredTmdbItems.map((tmdbItem) => { | 		 		let seasonedItems = filteredTmdbItems.map((tmdbItem) => { | ||||||
|  |  | ||||||
| 					if (type === 'movie') | 					if (type === 'movie') | ||||||
| 						return convertTmdbToSeasoned(tmdbItem, 'movie'); | 						return convertTmdbToSeasoned(tmdbItem, 'movie'); | ||||||
| 					else if (type === 'show') | 					else if (type === 'show') | ||||||
| @@ -40,7 +41,7 @@ class TMDB { | |||||||
| 		 		}); | 		 		}); | ||||||
| 		 		 | 		 		 | ||||||
| 		 		// TODO add page number if results are larger than 20 | 		 		// TODO add page number if results are larger than 20 | ||||||
| 		 		return { 'results': seasonedItems, 'number_of_items_on_page': seasonedItems, | 		 		return { 'results': seasonedItems, 'number_of_items_on_page': seasonedItems.length, | ||||||
| 						'page': 1, 'total_pages': 1 }; | 						'page': 1, 'total_pages': 1 }; | ||||||
|  |  | ||||||
| 		 	} catch (parseError) { | 		 	} catch (parseError) { | ||||||
|   | |||||||
| @@ -12,8 +12,9 @@ function submitRequestController(req, res) { | |||||||
| 	// This is the id that is the param of the url | 	// This is the id that is the param of the url | ||||||
| 	const id = req.params.mediaId; | 	const id = req.params.mediaId; | ||||||
| 	const type = req.query.type; | 	const type = req.query.type; | ||||||
|  | 	var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; | ||||||
|  |  | ||||||
| 	requestRepository.sendRequest(id, type) | 	requestRepository.sendRequest(id, type, ip) | ||||||
| 	.then(() => { | 	.then(() => { | ||||||
| 		res.send({ success: true, message: 'Media item sucessfully requested!' }); | 		res.send({ success: true, message: 'Media item sucessfully requested!' }); | ||||||
| 	}) | 	}) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user