Merge pull request #14 from KevinMidboe/client_feature

Client feature
This commit is contained in:
2017-07-16 11:19:15 +02:00
committed by GitHub
9 changed files with 187 additions and 45 deletions

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ node_modules
*.pyc *.pyc
npm-debug.log npm-debug.log
webpage/js/env_variables.js webpage/js/env_variables.js
client/dist
src/webserver/access.log

View File

@@ -7,15 +7,18 @@ class MovieObject {
this.year = object.year; this.year = object.year;
// Check if object.poster != undefined // Check if object.poster != undefined
this.poster = object.poster; this.poster = object.poster;
this.matchedInPlex = object.matchedInPlex this.matchedInPlex = object.matchedInPlex;
this.overview = object.overview;
} }
requestExisting(id) { requestExisting(movie) {
console.log('Exists', id) console.log('Exists', movie)
} }
requestMovie(id) { requestMovie(id) {
console.log(id); fetch('http://localhost:31459/api/v1/plex/request/' + id, {
method: 'POST'
})
} }
getElement() { getElement() {
@@ -30,11 +33,13 @@ class MovieObject {
returnList.push(<img src={posterPath}></img>); returnList.push(<img src={posterPath}></img>);
if (this.matchedInPlex) { if (this.matchedInPlex) {
returnList.push(<button onClick={() => this.requestExisting(this.id)}>Request anyway</button>) returnList.push(<button onClick={() => this.requestExisting(this)}>Request anyway</button>)
} else { } else {
returnList.push(<button onClick={() => this.requestMovie(this.id)}>Request</button>) returnList.push(<button onClick={() => this.requestMovie(this)}>Request</button>)
} }
returnList.push(<span>{this.overview}</span>);
returnList.push(<br></br>); returnList.push(<br></br>);
return returnList; return returnList;
} }

View File

@@ -2,72 +2,101 @@ import React from 'react';
import MovieObject from './MovieObject.jsx'; import MovieObject from './MovieObject.jsx';
// TODO add option for searching multi, movies or tv shows
class SearchRequest extends React.Component { class SearchRequest extends React.Component {
constructor(props){ constructor(props){
super(props) super(props)
// Constructor with states holding the search query and the element of reponse.
this.state = { this.state = {
searchQuery: '', searchQuery: '',
items: [] responseMovieList: null
}
this.URLs = {
request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=',
sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query='
} }
} }
componentDidMount(){ componentDidMount(){
var that = this; var that = this;
fetch("https://apollo.kevinmidboe.com/api/v1/plex/request?query=interstellar") this.setState({responseMovieList: null})
.then(response => response.json())
.then(data => this.setState({
items: data
})
).catch(err => console.error('Error load: ', err.toString()));
} }
_handleKeyPress(e) { // Handles all errors of the response of a fetch call
handleErrors(response) {
if (!response.ok) {
throw Error(response.status);
}
return response;
}
fetchQuery() {
let url = this.URLs.request + this.state.searchQuery
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>
})
console.log('Error submit: ', error.toString());
});
}
// Updates the internal state of the query search field.
updateQueryState(event){
this.setState({
searchQuery: event.target.value
});
}
// For checking if the enter key was pressed in the search field.
_handleQueryKeyPress(e) {
if (e.key === 'Enter') { if (e.key === 'Enter') {
this.fetchQuery(); this.fetchQuery();
} }
} }
fetchQuery() { // When called passes the variable to MovieObject and calls it's interal function for
var query = 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=' + this.state.searchQuery; // generating the wanted HTML
createMovieObjects(item) {
fetch(query) let movie = new MovieObject(item);
.then(response => response.json()) return movie.getElement();
.then(data => this.setState({
items: data
})
).catch(err => console.error('Error submit: ', err.toString()));
} }
printMovies(item) {
if (item != undefined) {
let a = new MovieObject(item);
return a.getElement();
}
}
handleChange(event){
this.setState({
searchQuery: event.target.value
});
}
render(){ render(){
return( return(
<div> <div>
<input <input
type="text" type="text"
onKeyPress={(event) => this._handleKeyPress(event)} onKeyPress={(event) => this._handleQueryKeyPress(event)}
onChange={event => this.handleChange(event)} onChange={event => this.updateQueryState(event)}
value={this.state.searchQuery} value={this.state.searchQuery}
/> />
<button onClick={() => this.fetchQuery()}>Search</button> <button onClick={() => this.fetchQuery()}>Search</button>
<br></br> <br></br>
{this.state.searchQuery}
<br></br> <br></br>
<span id='requestMovieList' ref='requestMovieList'>
{this.state.items.map((item) => this.printMovies(item))} {this.state.responseMovieList}
</span>
</div> </div>
) )
} }

View File

@@ -1757,11 +1757,11 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@2, inherits@2.0.3, inherits@~2.0.0, inherits@~2.0.1: inherits@2, inherits@2.0.3, inherits@~2.0.0:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
inherits@2.0.1, inherits@^2.0.1: inherits@2.0.1, inherits@^2.0.1, inherits@~2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"

57
seasonMover.py Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-07-11 19:16:23
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-07-11 19:16:23
import fire, re, os
class seasonMover(object):
''' Moving multiple files to multiple folders with
identifer '''
workingDir = os.getcwd()
def create(self, name, interval):
pass
def move(self, fileSyntax, folderName):
episodeRange = self.findInterval(fileSyntax)
self.motherMover(fileSyntax, folderName, episodeRange)
def findInterval(self, item):
if (re.search(r'\((.*)\)', item) is None):
raise ValueError('Need to declare an identifier e.g. (1..3) in: \n\t' + item)
start = int(re.search('\((\d+)\.\.', item).group(1))
end = int(re.search('\.\.(\d+)\)', item).group(1))
return list(range(start, end+1))
def removeUploadSign(self, file):
match = re.search('-[a-zA-Z\[\]\-]*.[a-z]{3}', file)
if match:
uploader = match.group(0)[:-4]
return re.sub(uploader, '', file)
return file
def motherMover(self, fileSyntax, folderName, episodeRange):
# Call for sub of fileList
# TODO check if range is same as folderContent
for episode in episodeRange:
leadingZeroNumber = "%02d" % episode
fileName = re.sub(r'\((.*)\)', leadingZeroNumber, fileSyntax)
oldPath = os.path.join(self.workingDir,fileName)
newFolder = os.path.join(self.workingDir, folderName + leadingZeroNumber)
newPath = os.path.join(newFolder, self.removeUploadSign(fileName))
os.makedirs(newFolder)
os.rename(oldPath, newPath)
# print(newFolder)
# print(oldPath + ' --> ' + newPath)
if __name__ == '__main__':
fire.Fire(seasonMover)

View File

@@ -8,6 +8,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');
var pythonShell = require('python-shell');
class RequestRepository { class RequestRepository {
searchRequest(query, page, type) { searchRequest(query, page, type) {
@@ -55,6 +57,30 @@ class RequestRepository {
}); });
} }
sendRequest(identifier) {
// TODO try a cache hit on the movie item
console.log(identifier)
tmdb.lookup(identifier).then(movie => {
console.log(movie.title)
var options = {
args: [movie.title, movie.year, movie.poster]
}
pythonShell.run('sendRequest.py', options, function (err, results) {
if (err) throw err;
// TODO Add error handling!! RequestRepository.ERROR
// results is an array consisting of messages collected during execution
console.log('results: %j', results)
})
return true;
})
}
} }
module.exports = RequestRepository; module.exports = RequestRepository;

View File

@@ -36,7 +36,7 @@ router.get('/v1/plex/search', require('./controllers/plex/searchMedia.js'));
router.get('/v1/plex/playing', require('./controllers/plex/plexPlaying.js')); router.get('/v1/plex/playing', require('./controllers/plex/plexPlaying.js'));
router.get('/v1/plex/request', require('./controllers/plex/searchRequest.js')); router.get('/v1/plex/request', require('./controllers/plex/searchRequest.js'));
router.get('/v1/plex/request/:mediaId', require('./controllers/plex/readRequest.js')); router.get('/v1/plex/request/:mediaId', require('./controllers/plex/readRequest.js'));
// router.post('/v1/plex/request/:mediaId', require('./controllers/plex/submitRequest.js')); router.post('/v1/plex/request/:mediaId', require('./controllers/plex/submitRequest.js'));
router.get('/v1/plex/hook', require('./controllers/plex/hookDump.js')); router.get('/v1/plex/hook', require('./controllers/plex/hookDump.js'));
router.get('/v1/tmdb/search', require('./controllers/tmdb/searchMedia.js')); router.get('/v1/tmdb/search', require('./controllers/tmdb/searchMedia.js'));

View File

@@ -0,0 +1,24 @@
const RequestRepository = require('src/plex/requestRepository.js');
const requestRepository = new RequestRepository();
/**
* Controller: POST a media id to be donwloaded
* @param {Request} req http request variable
* @param {Response} res
* @returns {Callback}
*/
function submitRequestController(req, res) {
// This is the id that is the param of the url
const id = req.params.mediaId;
requestRepository.sendRequest(id)
.then(() => {
res.send({ success: true, message: 'Media item sucessfully requested!' });
})
.catch((error) => {
res.status(500).send({ success: false, error: error.message });
});
}
module.exports = submitRequestController;

View File

@@ -1,4 +1,3 @@
const configuration = require('src/config/configuration').getInstance();
const StrayRepository = require('src/seasoned/strayRepository'); const StrayRepository = require('src/seasoned/strayRepository');
const strayRepository = new StrayRepository(); const strayRepository = new StrayRepository();