diff --git a/README.MD b/README.MD index 945654e..76b6ed3 100644 --- a/README.MD +++ b/README.MD @@ -23,6 +23,12 @@ npm install express-session --save npm install whiskers --save ``` +Dependencies + +```bash +$apt-get install ffmpeg +``` + Codacs which don't work H.265 diff --git a/configManager.js b/configManager.js index 4db79a3..df2500e 100644 --- a/configManager.js +++ b/configManager.js @@ -16,6 +16,11 @@ module.exports= }, getRootDirectory: function() + { + return "/home/jeff/public/Shows/Rick And Morty/Season 1"; + }, + + getPublicDirectory: function() { return "/home/jeff/work/aaSchool/Algo/online Lectures/"; }, diff --git a/html/error.html b/html/error.html new file mode 100644 index 0000000..678c3ef --- /dev/null +++ b/html/error.html @@ -0,0 +1,11 @@ +
+
+

{errorMessage}

+
+ Page not found +

+
+
+ {>login} +
+
diff --git a/html/home.html b/html/home.html index 4f5e8fd..aa1beab 100644 --- a/html/home.html +++ b/html/home.html @@ -1,19 +1,24 @@
-
-
-

Profile

-
-
-

Welcome {username}.

-
-
-
- -
+ {if loggedIn} +
+ +
+

Profile

+
+
+

Welcome {username}.


- +
+
+ +
+
+
+
-
+ {else} + {>login} + {/if}
\ No newline at end of file diff --git a/html/mainTemplate.html b/html/mainTemplate.html index c26cb1f..a128c5f 100644 --- a/html/mainTemplate.html +++ b/html/mainTemplate.html @@ -1,12 +1,7 @@ {>header}
- {if loggedIn} - {>main} - {else} - {>login} - {/if} - + {>main}
{>footer} \ No newline at end of file diff --git a/html/videos.html b/html/videos.html index dac14f0..6ef6dcf 100644 --- a/html/videos.html +++ b/html/videos.html @@ -8,11 +8,25 @@
- {for video in videos} -
+ {for video in private} +
-

{video.name}

+

{video.name}

+
+
+ + Icon for {video.name} + +
+
+
+ {/for} + {for video in public} +
+
+
+

{video.name}

diff --git a/package.json b/package.json new file mode 100644 index 0000000..d568e42 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "HomeBrewPlex", + "version": "0.1.0", + "description": "Light weight alternative for Plex", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jrtechs/HomeBrewPlex.git" + }, + "author": "Jeffery Russell", + "license": "MPL 2.0", + "bugs": { + "url": "https://github.com/jrtechs/HomeBrewPlex/issues" + }, + "homepage": "https://github.com/jrtechs/HomeBrewPlex#readme", + "dependencies": { + "download-file": "^0.1.5", + "express-session": "^1.15.6", + "fs": "0.0.2", + "path": "^0.12.7", + "url": "^0.11.0", + "whiskers": "^0.4.0" + } +} diff --git a/routes/icon.js b/routes/icon.js index dc86d20..4053872 100644 --- a/routes/icon.js +++ b/routes/icon.js @@ -4,6 +4,8 @@ const utils = require("../utils"); const fs = require('fs'); +const videoManager = require('../videoManager'); + function isPublicVideo(videoURL) { return false; @@ -18,24 +20,23 @@ routes.get('/', (request, result) => const splitArray = videoID.split('/'); const name = splitArray[splitArray.length -1] + ".png"; - console.log(name); - var file=""; - if(!isPublicVideo(videoID)) + if(!videoManager.isPublicVideo(videoID)) { if(utils.checkPrivilege(request) >= utils.PRIVILEGE.MEMBER) { - file = fs.readFileSync("./img/private/" + name); + file = fs.readFileSync("./icon/private/" + name); } else { + utils.printError(result, "You need to be logged in"); throw "Not logged in"; } } else { - file = fs.readFileSync("./img/public/" + name); + file = fs.readFileSync("./icon/public/" + name); } result.writeHead(200, {'Content-Type': 'image/png', @@ -45,10 +46,7 @@ routes.get('/', (request, result) => } catch(error) { - result.writeHead(404, {'Content-Type': 'text/html', - 'Vary': 'Accept-Encoding'}); - result.write("Nada"); - result.end(); + utils.printError(result, "Invalid Icon"); } }); diff --git a/routes/index.js b/routes/index.js index a18abd0..4d37cb6 100644 --- a/routes/index.js +++ b/routes/index.js @@ -30,4 +30,10 @@ routes.get('/', (request, result) => utils.renderHTML(request, result, "home.html", getHomePageInformation) }); + +routes.get('*', (request, result) => +{ + utils.printError(result, "Page not found."); +}); + module.exports = routes; \ No newline at end of file diff --git a/routes/user/addUser.js b/routes/user/addUser.js index 8f35a09..0f0e28a 100644 --- a/routes/user/addUser.js +++ b/routes/user/addUser.js @@ -17,8 +17,7 @@ routes.post('/', (request, result) => } else { - result.status(401); - result.send('None shall pass'); + utils.printError(result, "You need to be logged in"); } }); diff --git a/routes/user/edituser.js b/routes/user/edituser.js index 5ae4c28..3146ae9 100644 --- a/routes/user/edituser.js +++ b/routes/user/edituser.js @@ -17,8 +17,7 @@ routes.post('/', (request, result) => } else { - result.status(401); - result.send('None shall pass'); + utils.printError(result, "You need to be logged in"); } }); diff --git a/routes/user/index.js b/routes/user/index.js index 106801e..64b5ea4 100644 --- a/routes/user/index.js +++ b/routes/user/index.js @@ -40,7 +40,15 @@ function getUserInformation(templateContext, request) routes.get('/', (request, result) => { - utils.renderHTML(request, result, "users.html", getUserInformation); + if(utils.checkPrivilege(request) >= utils.PRIVILEGE.MEMBER) + { + utils.renderHTML(request, result, "users.html", getUserInformation); + } + else + { + utils.printError(result, "You need to be logged in"); + } + }); module.exports = routes; \ No newline at end of file diff --git a/routes/user/removeuser.js b/routes/user/removeuser.js index c04a2ed..69cb961 100644 --- a/routes/user/removeuser.js +++ b/routes/user/removeuser.js @@ -13,8 +13,7 @@ routes.post('/', (request, result) => } else { - result.status(401); - result.send('None shall pass'); + utils.printError(result, "You need to be logged in"); } }); diff --git a/routes/user/revokeAPI.js b/routes/user/revokeAPI.js index 02b50e5..956d205 100644 --- a/routes/user/revokeAPI.js +++ b/routes/user/revokeAPI.js @@ -16,6 +16,10 @@ routes.post('/', (request, result) => userUtils.revokeAPI(request.session.username); request.session.API = userUtils.getAPIKEY(request.session.username); } + else + { + utils.printError(result, "You need to be logged in"); + } result.redirect('/user'); }); diff --git a/routes/user/updateUser.js b/routes/user/updateUser.js index fa177f4..19dc356 100644 --- a/routes/user/updateUser.js +++ b/routes/user/updateUser.js @@ -14,8 +14,7 @@ routes.post('/', (request, result) => } else { - result.status(401); - result.send('None shall pass'); + utils.printError(result, "You need to be logged in"); } }); diff --git a/routes/video.js b/routes/video.js index 45190b8..fbb323b 100644 --- a/routes/video.js +++ b/routes/video.js @@ -8,14 +8,19 @@ const configManager = require("../configManager"); const fs = require('fs'); +const videoManager = require("../videoManager"); + routes.get('/', (request, result) => { + var videoID = request.query.v; + if(utils.checkPrivilege(request) >= utils.PRIVILEGE.MEMBER || - userUtils.isValidAPI(request.query.api)) + userUtils.isValidAPI(request.query.api) || + videoManager.isPublicVideo(videoID)) { const rootDir = configManager.getRootDirectory(); - var videoID = request.query.v; + const path = rootDir + videoID; const stat = fs.statSync(path); const fileSize = stat.size; @@ -55,9 +60,7 @@ routes.get('/', (request, result) => } else { - console.log("invalid attempt to view video"); - result.status(401); - result.send('None shall pass'); + utils.printError(result, "You need to be logged in"); } }); diff --git a/routes/videos.js b/routes/videos.js index 15094d4..f863e1b 100644 --- a/routes/videos.js +++ b/routes/videos.js @@ -2,52 +2,25 @@ const routes = require('express').Router(); const utils = require("../utils"); -const recursive = require('../recursiveTraversal'); +const videoManager = require("../videoManager"); -const configManager = require("../configManager"); - -const filepreview = require('filepreview'); - -const fs = require('fs'); - -var videos = null; function getVideosTemplateInformation(templateContext, request) { - if(videos === null) + var promises = []; + + if(utils.checkPrivilege(request) >= utils.PRIVILEGE.MEMBER) { - const rootDir = configManager.getRootDirectory(); - videos = []; - return new Promise(function(resolve, reject) - { - recursive(rootDir, function (err, files) - { - console.log(files); - files.forEach(file => - { - var splitArray = file.split('/'); - var name = splitArray[splitArray.length -1]; - const icon = 'img/private/' + name + ".png"; - if (!fs.existsSync(icon)) - { - filepreview.generate(file, icon, function(error) { - if (error) { - return console.log(error); - } - console.log('File preview is located ' + icon); - }); - } - videos.push({name: file.replace(rootDir, ''), length: "n/a"}); - }); - templateContext.videos = videos; - resolve(); - }); - }) + promises.push(videoManager.getVideosForTemplate(templateContext, "private")); } else { - templateContext.videos = videos; + templateContext["private"] = []; } + + promises.push(videoManager.getVideosForTemplate(templateContext, "public")); + + return Promise.all(promises); } routes.get('/', (request, result) => diff --git a/routes/watch.js b/routes/watch.js index f88b15a..626adb8 100644 --- a/routes/watch.js +++ b/routes/watch.js @@ -4,16 +4,32 @@ const utils = require("../utils"); const configManager = require("../configManager"); +const videoManager = require("../videoManager"); + function getVideoTemplateInfo(templateContext, request) { templateContext.api = request.session.API; templateContext.serverURL = configManager.getServerURL(); templateContext.videoURL = request.query.v.split(" ").join("%20"); + + if(utils.checkPrivilege(request) === utils.PRIVILEGE.NOBODY + && !videoManager.isPublicVideo(request.query.v)) + { + throw "Video either doesn't exist or you need to log in."; + } } routes.get('/', (request, result) => { - utils.renderHTML(request, result, "watch.html", getVideoTemplateInfo) + try + { + utils.renderHTML(request, result, "watch.html", getVideoTemplateInfo) + } + catch(error) + { + utils.printError(result, error); + } + }); module.exports = routes; \ No newline at end of file diff --git a/server.js b/server.js index c72dfdb..58e1792 100644 --- a/server.js +++ b/server.js @@ -11,20 +11,21 @@ const app = express(); /**Initializes sessions for login */ app.use(session( { secret: configLoader.getConfiguration().sessionSecret, - cookie: { maxAge: 6000000 } - } + cookie: { maxAge: 6000000 }} )); app.use(express.urlencoded()); //for easy retrieval of post and get data app.use(express.json()); -const routes = require('./routes'); -app.use('/', routes); - app.use(express.static('css')); app.use(express.static('js')); app.use(express.static('img')); +const routes = require('./routes'); +app.use('/', routes); + + + app.listen(configLoader.getConfiguration().port, () => console.log(`App listening on port ${configLoader.getConfiguration().port}!`) ); \ No newline at end of file diff --git a/utils.js b/utils.js index 860a2bf..bd7866c 100644 --- a/utils.js +++ b/utils.js @@ -28,15 +28,16 @@ module.exports = templateContext.loggedIn = true; if(module.exports.checkPrivilege(request) === PRIVILEGE.ADMIN) templateContext.admin = true; - if(templateDependencyFunction !== null) - prom.push(templateDependencyFunction(templateContext, request)); - prom.push(fetchInTemplate(templateContext, "main","./html/" + templateFile)); } else { prom.push(fetchInTemplate(templateContext, "login","./html/login.html")); } + if(templateDependencyFunction !== null) + prom.push(templateDependencyFunction(templateContext, request)); + prom.push(fetchInTemplate(templateContext, "main","./html/" + templateFile)); + Promise.all(prom).then(function(content) { result.write(whiskers.render(content[0], templateContext)); @@ -59,5 +60,24 @@ module.exports = else if(request.session.admin === true) return module.exports.PRIVILEGE.ADMIN; return module.exports.RIVILEGE.MEMBER; + }, + + printError: function(result, errorMessage) + { + var templateContext = Object(); + var prom = []; + + prom.push(fileIO.getFile("./html/mainTemplate.html")); + prom.push(fetchInTemplate(templateContext, "header", "./html/header.html")); + prom.push(fetchInTemplate(templateContext, "footer", "./html/footer.html")); + prom.push(fetchInTemplate(templateContext, "main", "./html/error.html")); + prom.push(fetchInTemplate(templateContext, "login","./html/login.html")); + templateContext.errorMessage = errorMessage; + + Promise.all(prom).then(function(content) + { + result.write(whiskers.render(content[0], templateContext)); + result.end(); + }); } }; \ No newline at end of file diff --git a/videoManager.js b/videoManager.js new file mode 100644 index 0000000..37cf0b3 --- /dev/null +++ b/videoManager.js @@ -0,0 +1,125 @@ +const configManager = require('./configManager'); + +const recursive = require('./recursiveTraversal'); + +const filepreview = require('filepreview'); + +const fs = require('fs'); + +var privateVideos = null; + +var publicVideos = null; + +module.exports = + { + indexVideos: function(rootDir, videos, templateKey) + { + return new Promise(function(resolve, reject) + { + recursive(rootDir, function (err, files) + { + files.forEach(file => + { + var splitArray = file.split('/'); + var name = splitArray[splitArray.length -1]; + const icon = './icon/' + templateKey + '/' + name + ".png"; + if (!fs.existsSync(icon)) + { + var options = { + width: 200, + quality: 50, + previewTime: '00:05:00.000' + }; + + filepreview.generate(file, icon, options,function(error) { + if (error) { + return console.log(error); + } + console.log('File preview is located ' + icon); + }); + } + videos.push({name: file.replace(rootDir, '')}); + }); + resolve(); + }); + }).catch(function(error) + { + //console.log(error); + }) + }, + + getVideosForTemplate: function(templateContext, templateKey) + { + return new Promise(function(resolve, reject) + { + var videos, rootDir; + if(templateKey === "public") + { + videos = publicVideos; + rootDir = configManager.getPublicDirectory(); + } + else + { + videos = privateVideos; + rootDir = configManager.getRootDirectory(); + } + + if(videos === null) + { + videos = []; + module.exports.indexVideos(rootDir, videos, templateKey) + .then(function() + { + templateContext[templateKey] = videos; + if(templateKey === "public") + publicVideos = videos; + else + privateVideos = videos; + resolve(); + }) + } + else + { + templateContext[templateKey] = videos; + resolve(); + } + }) + }, + + isPublicVideo: function(videoName) + { + if(publicVideos == null) + { + publicVideos = []; + rootDir = configManager.getPublicDirectory(); + module.exports.indexVideos(rootDir, publicVideos, "public").then(function() + { + for(var i = 0; i < publicVideos.length; i++) + { + const splitArray = publicVideos[i].name.split('/'); + const name = splitArray[splitArray.length -1]; + + if(name === videoName) + { + return true; + } + } + return false; + }); + } + else + { + for(var i = 0; i < publicVideos.length; i++) + { + const splitArray = publicVideos[i].name.split('/'); + const name = splitArray[splitArray.length -1]; + + if(name === videoName) + { + return true; + } + } + return false; + } + } + }; \ No newline at end of file