diff --git a/database/dump.js b/database/dump.js index dfc40b3..382ec9b 100644 --- a/database/dump.js +++ b/database/dump.js @@ -4,21 +4,21 @@ const SavedBlogs = require("../modules/blogs/models/SavedBlogs"); const Login = require("../modules/logins/models/login"); const User = require("../modules/users/models/user"); -User.hasMany(Login, { +User.User.hasMany(Login, { foreignKey:{ allowNull: false, unique: true } }); -Login.belongsTo(User); +Login.belongsTo(User.User); -User.hasMany(Blogs, { +User.User.hasMany(Blogs, { foreignKey:{ allowNull: false, unique: false } }); -Blogs.belongsTo(User); +Blogs.belongsTo(User.User); Categories.hasMany(Blogs, { foreignKey:{ @@ -36,19 +36,60 @@ Blogs.hasMany(SavedBlogs, { }); SavedBlogs.belongsTo(Blogs); -User.hasMany(SavedBlogs, { +User.User.hasMany(SavedBlogs, { foreignKey:{ allowNull: false, unique: false } }); -SavedBlogs.belongsTo(User); +SavedBlogs.belongsTo(User.User); + +User.Education.hasMany(User.User, { + foreignKey:{ + allowNull: true, + unique: false + } +}); +User.User.belongsTo(User.Education); + +User.Gender.hasMany(User.User, { + foreignKey:{ + allowNull: true, + unique: false + } +}); +User.User.belongsTo(User.Gender); exports.createTesting = async function(){ const resultLogins = await Login.findAll(); if(resultLogins.length == 0){ + + await User.Education.bulkCreate([{ + id: 1, + title: "İlkokul" + },{ + id: 2, + title: "Ortaokul" + },{ + id: 3, + title: "Lise" + },{ + id: 4, + title: "Önlisans" + },{ + id: 5, + title: "Lisans" + }]); + + await User.Gender.bulkCreate([{ + id: 1, + title: "Erkek" + },{ + id: 2, + title: "Kadın" + }]) - await User.bulkCreate([{ + await User.User.bulkCreate([{ id: 1, first_name: "Batuhan", second_name: "Coşkun", @@ -78,16 +119,25 @@ exports.createTesting = async function(){ await Categories.bulkCreate([{ id: 1, - title: "Teknoloji" + title: "Profil" },{ id: 2, - title: "Siyaset" + title: "Teknoloji" },{ id: 3, - title: "Sağlık" + title: "Siyaset" },{ id: 4, + title: "Sağlık" + },{ + id: 5, title: "Felsefe" + },{ + id: 6, + title: "Doğa" + },{ + id: 7, + title: "Gıda" }]); await Blogs.bulkCreate([{ diff --git a/index.js b/index.js index 9cfdc36..938730b 100644 --- a/index.js +++ b/index.js @@ -42,10 +42,12 @@ app.use(session({ const moduleLogin = require("./modules/logins/index"); const moduleBlog = require("./modules/blogs/app"); const moduleUser = require("./modules/users/app"); +const moduleStream = require("./modules/streams/app"); app.use(moduleLogin); app.use(moduleBlog); app.use(moduleUser); +app.use(moduleStream); // DATABASES const DatabaseDump = require("./database/dump"); diff --git a/modules/blogs/app.js b/modules/blogs/app.js index 3cbf7f6..c2c8cdf 100644 --- a/modules/blogs/app.js +++ b/modules/blogs/app.js @@ -7,8 +7,8 @@ const routerPost = require("./routes/post"); const routerPage = require("./routes/page"); // USES +app.use(routerPage); app.use(routerGet); app.use(routerPost); -app.use(routerPage); module.exports = app; \ No newline at end of file diff --git a/modules/blogs/middlewares/post.js b/modules/blogs/middlewares/post.js index dafe60c..5f04158 100644 --- a/modules/blogs/middlewares/post.js +++ b/modules/blogs/middlewares/post.js @@ -22,11 +22,24 @@ exports.createSaved = async function({blogId, userId}){ const checkQuery = await getSaved({blogId: blogId, userId: userId}); if(!checkQuery){ - return await SavedBlogs.create({ + const result = await SavedBlogs.create({ blogId: blogId, - userId: userId - }); + userId: userId, + statu: true + }).then(get => {return (get) ? true : false}); + return {Status: "Success", data: result} + }else if(checkQuery){ + const result = await SavedBlogs.update( + {statu: !checkQuery.statu}, + { + where:{ + blogId: blogId, + userId: userId + } + } + ).then(get => {return (get) && !checkQuery.statu}); + return {Status: "Success", data: result}; }else{ - return false; + return {Status: "Failed"}; }; }; \ No newline at end of file diff --git a/modules/blogs/middlewares/query.js b/modules/blogs/middlewares/query.js index 49fc856..dff8770 100644 --- a/modules/blogs/middlewares/query.js +++ b/modules/blogs/middlewares/query.js @@ -1,28 +1,46 @@ -const User = require("../../users/models/user"); +const User = require("../../users/models/user").User; const Blogs = require("../models/Blogs"); const Categories = require("../models/Categories"); const SavedBlogs = require("../models/SavedBlogs"); -exports.getBlogs = async function(){ +exports.getBlogs = async function({myUserId}){ + console.log(myUserId, 456); return await Blogs.findAll({ - include: [User, Categories], - order: [["createdAt", "DESC"]] - }); -}; - -exports.getBlogsWithUsername = async function({username}){ - return await Blogs.findAll({ - include:[Categories, { - model: User, + include: [User, Categories, { + model: SavedBlogs, where: { - username: username - } + userId: myUserId + }, + required: false }], order: [["createdAt", "DESC"]] }); }; -exports.getBlogsWithCategory = async function({categoryId, categoryTitle}){ +exports.getBlogsWithUsername = async function({username, category, myUserId}){ + return await Blogs.findAll({ + include:[(category) ? { + model: Categories, + where: { + title: category + } + } : Categories, { + model: User, + where: { + username: username + } + },{ + model: SavedBlogs, + where: { + userId: myUserId + }, + required: false + }], + order: [["createdAt", "DESC"]] + }); +}; + +exports.getBlogsWithCategory = async function({categoryId, categoryTitle, myUserId}){ return await Blogs.findAll({ include: [User, Categories, { model: Categories, @@ -31,6 +49,12 @@ exports.getBlogsWithCategory = async function({categoryId, categoryTitle}){ }, (categoryTitle) && { title: categoryTitle }] + },{ + model: SavedBlogs, + where: { + userId: myUserId + }, + required: false }], order: [["createdAt", "DESC"]] }); diff --git a/modules/blogs/models/SavedBlogs.js b/modules/blogs/models/SavedBlogs.js index 30bf6aa..98f8f04 100644 --- a/modules/blogs/models/SavedBlogs.js +++ b/modules/blogs/models/SavedBlogs.js @@ -1,3 +1,10 @@ +const { DataTypes } = require("sequelize"); const Database = require("../../../database/db"); -module.exports = Database.define("savedBlogs",{}); \ No newline at end of file +module.exports = Database.define("savedBlogs",{ + statu: { + type: DataTypes.BOOLEAN, + allowNull: false, + unique: false + } +}); \ No newline at end of file diff --git a/modules/blogs/routes/get.js b/modules/blogs/routes/get.js index 366e469..b161024 100644 --- a/modules/blogs/routes/get.js +++ b/modules/blogs/routes/get.js @@ -5,16 +5,25 @@ const Categories = require("../models/Categories"); const router = express(); router.get("/get/blogs/all", auth, async function (req, res) { - res.json(await getBlogs()); + res.json(await getBlogs({myUserId: req.session.user.id})); }); router.get("/get/blogs/:cate", auth, async function(req, res) { - res.json(await getBlogsWithCategory({categoryId: req.params.cate})); + res.json(await getBlogsWithCategory({categoryId: req.params.cate, myUserId: req.session.user.id})); }); router.get("/get/blogs/user/:username", auth, async function (req, res) { res.json(await getBlogsWithUsername({ - username: req.params.username + username: req.params.username, + myUserId: req.session.user.id + })); +}); + +router.get("/get/blogs/user/:username/:category", auth, async function (req, res) { + res.json(await getBlogsWithUsername({ + username: req.params.username, + category: req.params.category, + myUserId: req.session.user.id })); }); diff --git a/modules/blogs/routes/page.js b/modules/blogs/routes/page.js index b4a956f..f89c958 100644 --- a/modules/blogs/routes/page.js +++ b/modules/blogs/routes/page.js @@ -7,14 +7,14 @@ const router = express(); router.get("/page/blogs", auth, async function(req, res) { res.json({ categories: await Categories.findAll(), - blogs: await getBlogs() + blogs: await getBlogs({myUserId: req.session.user.id}) }); }); router.get("/page/blogs/:cate", auth, async function(req, res) { res.json({ categories: await Categories.findAll(), - blogs: await getBlogsWithCategory({categoryTitle: req.params.cate}), + blogs: await getBlogsWithCategory({categoryTitle: req.params.cate, myUserId: req.session.user.id}), currentCategory: await getCategoryWithParams({categoryTitle: req.params.cate}) }); }); diff --git a/modules/blogs/routes/post.js b/modules/blogs/routes/post.js index 67a9a3b..c747c93 100644 --- a/modules/blogs/routes/post.js +++ b/modules/blogs/routes/post.js @@ -19,7 +19,7 @@ router.post("/post/blogs/create", auth, async function(req, res) { router.post("/post/blogs/save", auth, async function(req, res) { const result = await createSaved({userId: req.session.user.id, blogId: req.body.blogId}); - return (result) && res.json({Status: "Success"}); + return res.json(result); }); module.exports = router; \ No newline at end of file diff --git a/modules/logins/index.js b/modules/logins/index.js index 6fb7ccc..550dabe 100644 --- a/modules/logins/index.js +++ b/modules/logins/index.js @@ -3,7 +3,9 @@ const app = express(); //Routes const routesHome = require("./routes/home"); +const routesPost = require("./routes/post"); app.use(routesHome); +app.use(routesPost); module.exports = app; \ No newline at end of file diff --git a/modules/logins/middlewares/auth.js b/modules/logins/middlewares/auth.js index e02573e..fcc8850 100644 --- a/modules/logins/middlewares/auth.js +++ b/modules/logins/middlewares/auth.js @@ -1,8 +1,12 @@ module.exports = (req, res, next) => { - if(req.session.isAuth === true){ - next(); - }else{ + try { + if(req.session.isAuth === true){ + next(); + }else{ + res.json({Status: "Failed"}); + next(); + } + } catch (error) { res.json({Status: "Failed"}); - next(); - } + }; }; \ No newline at end of file diff --git a/modules/logins/middlewares/proccess.js b/modules/logins/middlewares/proccess.js new file mode 100644 index 0000000..a7b4cfc --- /dev/null +++ b/modules/logins/middlewares/proccess.js @@ -0,0 +1,21 @@ +const Login = require("../models/login") +const { checkPassword } = require("./query") + +exports.updatePassword = async function({oldPass, newPass, myUserId}) { + const check = await checkPassword({password: oldPass, myUserId: myUserId}); + if(check.data === true){ + const result = await Login.update( + {password: newPass}, + { + where: { + userId: myUserId + } + } + ).then(get => { + return (get) ? true : false; + }); + return {Status: "Success", data: result}; + }else{ + return {Status: "Failed"}; + }; +}; \ No newline at end of file diff --git a/modules/logins/middlewares/query.js b/modules/logins/middlewares/query.js index ca7eec8..db6b17c 100644 --- a/modules/logins/middlewares/query.js +++ b/modules/logins/middlewares/query.js @@ -1,5 +1,5 @@ const Login = require("../models/login"); -const User = require("../../users/models/user"); +const User = require("../../users/models/user").User; exports.getLogin = async function({password, email = null, username = null}){ const result = await Login.findOne({ @@ -9,5 +9,17 @@ exports.getLogin = async function({password, email = null, username = null}){ }, include: User }); + console.log(result, 546) return result; +}; + +exports.checkPassword = async function({password, myUserId}){ + const result = await Login.findOne({ + where:{ + userId: myUserId, + password: password + } + }).then(res => {return (res) ? true : false}); + + return {Status: "Success", data: result}; }; \ No newline at end of file diff --git a/modules/logins/routes/home.js b/modules/logins/routes/home.js index 2b5dc36..e6504ae 100644 --- a/modules/logins/routes/home.js +++ b/modules/logins/routes/home.js @@ -35,8 +35,9 @@ router.post('/login', async (req, res) => { router.get('/logout', auth, async (req, res) => { req.session.destroy(); - res.clearCookie('connect.sid'); - res.redirect(data.serverOptions.frontEnd.url + "/login"); -}) + res.json({ + redirect: "/login" + }); +}); module.exports = router; \ No newline at end of file diff --git a/modules/logins/routes/post.js b/modules/logins/routes/post.js new file mode 100644 index 0000000..4389f7f --- /dev/null +++ b/modules/logins/routes/post.js @@ -0,0 +1,18 @@ +const express = require("express"); +const auth = require("../middlewares/auth"); +const { updatePassword } = require("../middlewares/proccess"); +const router = express(); + +router.post("/post/login/change/password", auth, async function(req, res){ + if(req.body.newPass === req.body.reNewPass){ + const result = await updatePassword({oldPass: req.body.oldPass, newPass: req.body.newPass, myUserId: req.session.user.id}); + if(result){ + res.redirect("/logout"); + } + // res.json({...result, redirect: "/login"}); + }else{ + res.json({Status: "Failed"}); + }; +}); + +module.exports = router; \ No newline at end of file diff --git a/modules/streams/app.js b/modules/streams/app.js new file mode 100644 index 0000000..f1e4594 --- /dev/null +++ b/modules/streams/app.js @@ -0,0 +1,13 @@ +const express = require("express"); +const app = express(); +const path = require("path"); + +app.use(express.static(path.join(__dirname,'public'))); + +// ROUTES +const routeMusiks = require("./routes/musiks"); + +// APPS +app.use(routeMusiks); + +module.exports = app; \ No newline at end of file diff --git a/modules/streams/public/musiks/musik.mp3 b/modules/streams/public/musiks/musik.mp3 new file mode 100644 index 0000000..6016323 Binary files /dev/null and b/modules/streams/public/musiks/musik.mp3 differ diff --git a/modules/streams/routes/musiks.js b/modules/streams/routes/musiks.js new file mode 100644 index 0000000..b3ecf1b --- /dev/null +++ b/modules/streams/routes/musiks.js @@ -0,0 +1,9 @@ +const express = require("express"); +const router = express(); +const ms = require("mediaserver"); + +router.get("/musiks/musik.mp3", function(req, res){ + ms.pipe(req, res, "/musik.mp3"); +}); + +module.exports = router; \ No newline at end of file diff --git a/modules/users/app.js b/modules/users/app.js index b813837..e722a22 100644 --- a/modules/users/app.js +++ b/modules/users/app.js @@ -3,8 +3,10 @@ const app = express(); //MODULES const routeUsers = require("./routes/home"); +const routeSetting = require("./routes/setting"); //USES app.use(routeUsers); +app.use(routeSetting); module.exports = app; \ No newline at end of file diff --git a/modules/users/middlewares/check.js b/modules/users/middlewares/check.js new file mode 100644 index 0000000..792ed76 --- /dev/null +++ b/modules/users/middlewares/check.js @@ -0,0 +1,77 @@ +const { User } = require("../models/user"); +const { getDatabaseColumns } = require("./proccess"); + +exports.postSettings = async function({data, userId}){ + const user = await User.findOne({where:{id: userId}}); + + const dataset = { + name: { + title: "first_name", + isNull: false + }, + surname: { + title: "second_name", + isNull: false + }, + username: { + title: "username", + isNull: false + }, + about: { + title: "about", + isNull: true + }, + private: {title: "private", isNull: false}, + relation: {title: "relation", isNull: true}, + education: {title: "educationId", isNull: true}, + gender: {title: "genderId", isNull: true} + }; + + const returnData = new Object(); + + Object.keys(dataset).forEach(get => { + if(Object.keys(data).includes(get)){ + returnData[get] = false; + }else{ + returnData[get] = true; + }; + }); + + for (let key in data){ + const value = (data[key]).trim(); + + const databaseKey = dataset[key].title; + const databaseVal = user[databaseKey]; + + console.log(key) + if(databaseVal != value){ + if( + (dataset[key].isNull === true && [null, undefined, ""].includes(value)) || + (![null, undefined, ""].includes(value)) + ){ + try { + console.log(key) + await User.update( + {[databaseKey]: value}, + { + where:{ + id: userId + } + } + ).then(res => { + if(res){ + returnData[key] = true; + }; + }); + } catch (error) { + console.log(54) + returnData[key] = false; + }; + } + console.log(databaseVal, value, databaseKey) + }else{ + returnData[key] = true; + }; + }; + return returnData; +}; \ No newline at end of file diff --git a/modules/users/middlewares/proccess.js b/modules/users/middlewares/proccess.js new file mode 100644 index 0000000..1b5da19 --- /dev/null +++ b/modules/users/middlewares/proccess.js @@ -0,0 +1,7 @@ +exports.getDatabaseColumns = async function({Model}){ + const columns = new Array(); + for(let key in await Model.rawAttributes){ + columns.push(key); + }; + return columns; +}; \ No newline at end of file diff --git a/modules/users/middlewares/query.js b/modules/users/middlewares/query.js index f1bc6ae..9338072 100644 --- a/modules/users/middlewares/query.js +++ b/modules/users/middlewares/query.js @@ -1,13 +1,25 @@ -const User = require("../models/user") +const { Gender, Education } = require("../models/user"); + +const User = require("../models/user").User; exports.getUsers = async function(){ return await User.findAll(); }; +exports.getUserWithId = async function({userId}) { + return await User.findOne({ + where:{ + id: userId + }, + include: [Gender, Education] + }); +} + exports.getUserWithUsername = async function({username}){ return await User.findOne({ where:{ username: username - } + }, + include: [Gender, Education] }); }; \ No newline at end of file diff --git a/modules/users/models/user.js b/modules/users/models/user.js index 92f5d15..704ca43 100644 --- a/modules/users/models/user.js +++ b/modules/users/models/user.js @@ -16,7 +16,42 @@ const User = Database.define("users", { type: DataTypes.CHAR(30), allowNull: false, unique: true + }, + about: { + type: DataTypes.CHAR(255), + allowNull: true, + unique: false + }, + private: { + type: DataTypes.BOOLEAN, + allowNull: false, + unique: false, + defaultValue: false + }, + relation: { + type: DataTypes.BOOLEAN, + allowNull: true, + unique: false, + defaultValue: null } -}) +}); -module.exports = User; \ No newline at end of file +const Education = Database.define("educations", { + title: { + type: DataTypes.CHAR(30), + allowNull: false, + unique: true + } +}); + +const Gender = Database.define("genders", { + title: { + type: DataTypes.CHAR(10), + allowNull: false, + unique: true + } +}); + + + +module.exports = {User, Education, Gender}; \ No newline at end of file diff --git a/modules/users/routes/home.js b/modules/users/routes/home.js index 805d2e9..c8b5cd2 100644 --- a/modules/users/routes/home.js +++ b/modules/users/routes/home.js @@ -1,6 +1,6 @@ const express = require("express"); const auth = require("../../logins/middlewares/auth"); -const { getUsers, getUserWithUsername } = require("../middlewares/query"); +const { getUsers, getUserWithUsername, getUserWithId } = require("../middlewares/query"); const router = express(); router.get("/get/peoples", auth, async (req, res) => { @@ -8,13 +8,20 @@ router.get("/get/peoples", auth, async (req, res) => { }); router.get("/get/user/my", auth, async (req, res) => { - res.json({ - username: req.session.user.username - }); + try { + res.json({ + user: await getUserWithId({userId: req.session.user.id}) + }); + } catch (error) { + }; }); router.get("/get/user/:username", async (req, res) => { - res.json(await getUserWithUsername({username: req.params.username})) -}) + const user = await getUserWithUsername({username: req.params.username}); + res.json({ + user: user, + isMy: user.id === req.session.user.id + }); +}); module.exports = router; \ No newline at end of file diff --git a/modules/users/routes/setting.js b/modules/users/routes/setting.js new file mode 100644 index 0000000..5a389c3 --- /dev/null +++ b/modules/users/routes/setting.js @@ -0,0 +1,27 @@ +const express = require("express"); +const auth = require("../../logins/middlewares/auth"); +const { Education, Gender } = require("../models/user"); +const { getUserWithUsername, getUserWithId } = require("../middlewares/query"); +const { postSettings } = require("../middlewares/check"); +const router = express(); + +router.get("/profile/settings/profile", auth, async function(req, res) { + console.log(45653, req.session.user); + res.json({ + data:{ + education: await Education.findAll(), + genders: await Gender.findAll(), + user: await getUserWithId({userId: req.session.user.id}) + }, + Status: "Success" + }); +}); + +router.post("/profile/settings", auth, async function(req, res) { + res.json({ + data: postSettings({data: req.body, userId: req.session.user.id}), + Status: "Success" + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 58c4dad..c3c0b33 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -861,6 +861,14 @@ "node": ">= 0.6" } }, + "node_modules/mediaserver": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/mediaserver/-/mediaserver-0.1.1.tgz", + "integrity": "sha512-+Gpdjzxp8n3v4lUnvLzepimasnrjHdjNVqcvD/U9nhUkuYNkUp3AbenHoePBEFheqS/WL5j9Mk0V4tjAHLnIpw==", + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", diff --git a/node_modules/mediaserver/Changelog.md b/node_modules/mediaserver/Changelog.md new file mode 100755 index 0000000..2aa6882 --- /dev/null +++ b/node_modules/mediaserver/Changelog.md @@ -0,0 +1,40 @@ +0.1.1 +* clean up the file stream on response end/close/finish (#10) + +0.1.0 +* Desktop safari media streaming fix + +0.0.9 +* minor stability improvements + +0.0.8 +* don't cache on'noCache + +0.0.7 +* consistent mime type from extension +* mp4 added to exts list + +0.0.6 +* code style update +* minor improvements and stability updates +* streaming fix for chrome + +0.0.4 - 0.0.5 +* event support for extension streaming + +0.0.3 + +* exports.mediaTypes proxies the media types +* mediaserver now serves other file types (html, css, js etc) +* cross domain headers added +* pipe returns true/false based on the success (do not close the response if it wasn't successful) + +0.0.2 + +* direct flow support +* cross browser tests made + + +0.0.1 + +* initial version diff --git a/node_modules/mediaserver/LICENSE b/node_modules/mediaserver/LICENSE new file mode 100755 index 0000000..da1eddc --- /dev/null +++ b/node_modules/mediaserver/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Oguz Bastemur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/mediaserver/Readme.md b/node_modules/mediaserver/Readme.md new file mode 100755 index 0000000..cfac3de --- /dev/null +++ b/node_modules/mediaserver/Readme.md @@ -0,0 +1,50 @@ +#### Media & static asset streaming module for node.js http(s) server + +#### Compatibility +(Tested on IE 6+, FF, Chrome, Mobile Safari - IE/Edge - Chrome and Brave) + +#### Installation +```npm install mediaserver``` + +#### Application Sample +Visit `sample` folder for sample application. + +#### Sample Usage +``` +var http = require('http'), + ms = require('mediaserver'); + +http.createServer(function (req, res) { + + ms.pipe(req, res, "music.mp3"); + +}).listen(1337, '127.0.0.1'); +``` + +from the client side + +``` + +``` + +#### express +``` +app.get('/music.mp3', function(req, res){ + ms.pipe(req, res, "/music.mp3"); +}); +``` + +#### API + +`.noCache` (true/false) enable/disable caching `file stat` results (default enabled) + +`.mediaTypes` Dictionary of media types and their corresponding media identifiers (i.e. "mp4" => "video/mpeg") + +`.pipe(request, response, path, extension or media identifier)` pipe a file from file system to browser + + +#### LICENSE +MIT diff --git a/node_modules/mediaserver/index.js b/node_modules/mediaserver/index.js new file mode 100755 index 0000000..cc5e781 --- /dev/null +++ b/node_modules/mediaserver/index.js @@ -0,0 +1,185 @@ +/** + * mediaserver module for node.js + * + * MIT license, Oguz Bastemur 2014-2018 + */ + +var fs = require('fs'), + exts = require('./libs/exts'), + pathModule = require('path'); + +var pipe_extensions = {}; +var pipe_extension_id = 0; + +var shared = {}; +var fileInfo = function (path) { + if (path) { + if (!exports.noCache && shared[path]) { + return shared[path]; + } + else { + if (!fs.existsSync(path)) { + return null; + } + var stat = fs.statSync(path); + if (!exports.noCache) + shared[path] = stat.size; + + return stat.size; + } + } + return 0; +}; + +// set this to true for development mode +exports.noCache = false; +exports.mediaTypes = exts; + +var getRange = function (req, total) { + var range = [0, total, 0]; + var rinfo = req.headers ? req.headers.range : null; + + if (rinfo) { + var rloc = rinfo.indexOf('bytes='); + if (rloc >= 0) { + var ranges = rinfo.substr(rloc + 6).split('-'); + try { + range[0] = parseInt(ranges[0]); + if (ranges[1] && ranges[1].length) { + range[1] = parseInt(ranges[1]); + range[1] = range[1] < 16 ? 16 : range[1]; + } + } catch (e) {} + } + + if (range[1] == total) + range[1]--; + + range[2] = total; + } + + return range; +}; + + +var isString = function (str) { + if (!str) return false; + return (typeof str == 'string' || str instanceof String); +}; + + +exports.pipe = function (req, res, path, type, opt_cb) { + if (!isString(path)) { + throw new TypeError("path must be a string value"); + } + + var total = fileInfo(path); + + if (total == null) { + res.end(path + " not found"); + return false; + } + + var range = getRange(req, total); + + var ext = pathModule.extname(path).toLowerCase(); + if (!type && ext && ext.length) { + type = exts[ext]; + } + + if (type && type.length && type[0] == '.') { + ext = type; + type = exts[type]; + } + + if (!type || !type.length) { + res.write("Media format not found for " + pathModule.basename(path)); + } else { + var file = fs.createReadStream(path, {start: range[0], end: range[1]}); + + var cleanupFileStream = function() { + file.close(); + } + + // the event emitted seems to change based on version of node.js + // 'close' is fired as of v6.11.5 + res.on('close', cleanupFileStream); // https://stackoverflow.com/a/9021242 + res.on('end', cleanupFileStream); // https://stackoverflow.com/a/16897986 + res.on('finish', cleanupFileStream); // https://stackoverflow.com/a/14093091 - https://stackoverflow.com/a/38057516 + + if (!ext.length || !pipe_extensions[ext]) { + var header = { + 'Content-Length': range[1], + 'Content-Type': type, + 'Access-Control-Allow-Origin': req.headers.origin || "*", + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', + 'Access-Control-Allow-Headers': 'POST, GET, OPTIONS' + }; + + if (range[2]) { + header['Accept-Ranges'] = 'bytes'; + header['Content-Range'] = 'bytes ' + range[0] + '-' + range[1] + '/' + total; + header['Content-Length'] = range[2]; + + res.writeHead(206, header); + } else { + res.writeHead(200, header); + } + + file.pipe(res); + file.on('close', function () { + res.end(0); + if (opt_cb && typeof opt_cb == 'function') { + opt_cb(path); + } + }); + } else { + var _exts = pipe_extensions[ext]; + res.writeHead(200, + { + 'Content-Type': type, + 'Access-Control-Allow-Origin': req.headers.origin || "*", + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', + 'Access-Control-Allow-Headers': 'POST, GET, OPTIONS' + }); + for (var o in _exts) { + _exts[o](file, req, res, function () { + if (!res.__ended) { + res.__ended = true; + res.end(0); + } + }); + } + } + + return true; + } + + return false; +}; + +exports.on = function (ext, m) { + if (!pipe_extensions[ext]) { + pipe_extensions[ext] = []; + } + + m.pipe_extension_id = pipe_extension_id++; + m.pipe_extension = ext; + + pipe_extensions[ext].push(m); +}; + +exports.removeEvent = function (method) { + if (!method || !method.pipe_extension || !method.pipe_extension_id) { + return; + } + + if (pipe_extensions[method.pipe_extension]) { + var exts = pipe_extensions[method.pipe_extension]; + for (var i = 0, ln = exts.length; i < ln; i++) { + if (exts[i].pipe_extension_id == method.pipe_extension_id) { + pipe_extensions[method.pipe_extension] = exts.splice(i, 1); + } + } + } +}; diff --git a/node_modules/mediaserver/libs/exts.js b/node_modules/mediaserver/libs/exts.js new file mode 100755 index 0000000..85541dd --- /dev/null +++ b/node_modules/mediaserver/libs/exts.js @@ -0,0 +1,166 @@ +/** + * mediaserver module for JXcore and Node.JS + * + * MIT license, Oguz Bastemur 2014 + * + * + * media extensions + */ + +// ref : http://www.webmaster-toolkit.com/mime-types.shtml +exports = module.exports = { + + // plain formats + ".html": "text/html", + ".css": "text/css", + ".js": "text/javascript", + ".txt": "text/plain", + + // custom + ".pdf": "application/octet-stream", + ".woff": "application/octet-stream", + ".ttf": "application/octet-stream", + ".svg": "application/octet-stream", + ".otf": "application/octet-stream", + ".eot": "application/octet-stream", + + // compressed formats + ".zip": "application/octet-stream", + ".rar": "application/octet-stream", + ".7z": "application/octet-stream", + ".gz": "application/octet-stream", + ".tar": "application/octet-stream", + + // media formats + ".afl": "video/animaflex", + ".ai": "application/postscript", + ".aif": "audio/aiff", + ".aifc": "audio/aiff", + ".aiff": "audio/aiff", + ".aip": "text/x-audiosoft-intra", + ".art": "image/x-jg", + ".asf": "video/x-ms-asf", + ".asm": "text/x-asm", + ".asx": "video/x-ms-asf", + ".au": "audio/basic", + ".avi": "video/avi", + ".avs": "video/avs-video", + ".bm": "image/bmp", + ".bmp": "image/bmp", + ".dif": "video/x-dv", + ".dl": "video/dl", + ".dv": "video/x-dv", + ".dwg": "image/vnd.dwg", + ".dxf": "image/vnd.dwg", + ".fli": "video/fli", + ".flo": "image/florian", + ".flac": "audio/flac", + ".fmf": "video/x-atomic3d-feature", + ".fpx": "image/vnd.fpx", + ".funk": "audio/make", + ".g3": "image/g3fax", + ".gif": "image/gif", + ".gl": "video/gl", + ".gsd": "audio/x-gsm", + ".gsm": "audio/x-gsm", + ".isu": "video/x-isvideo", + ".it": "audio/it", + ".jam": "audio/x-jam", + ".jfif": "image/jpeg", + ".jfif-tbnl": "image/jpeg", + ".jpe": "image/jpeg", + ".jpeg": "image/jpeg", + ".jpg": "image/jpeg", + ".jps": "image/x-jps", + ".jut": "image/jutvision", + ".kar": "audio/midi", + ".la": "audio/nspaudio", + ".lam": "audio/x-liveaudio", + ".lma": "audio/x-nspaudio", + ".m1v": "video/mpeg", + ".m2a": "audio/mpeg", + ".m2v": "video/mpeg", + ".m3u": "audio/x-mpequrl", + ".mcf": "image/vasa", + ".mid": "audio/midi", + ".midi": "audio/midi", + ".mjf": "audio/x-vnd.audioexplosion.mjuicemediafile", + ".mjpg": "video/x-motion-jpeg", + ".mod": "audio/mod", + ".moov": "video/quicktime", + ".mov": "video/quicktime", + ".movie": "video/x-sgi-movie", + ".mp2": "video/mpeg", + ".mp3": "audio/mpeg", + ".mpa": "audio/mpeg", + ".mpe": "video/mpeg", + ".mpeg": "video/mpeg", + ".mp4": "video/mpeg", + ".mpg": "video/mpeg", + ".mpga": "audio/mpeg", + ".mv": "video/x-sgi-movie", + ".my": "audio/make", + ".nap": "image/naplps", + ".naplps": "image/naplps", + ".nif": "image/x-niff", + ".niff": "image/x-niff", + ".ogg": "audio/ogg", + ".pbm": "image/x-portable-bitmap", + ".pct": "image/x-pict", + ".pcx": "image/x-pcx", + ".pfunk": "audio/make", + ".pgm": "image/x-portable-greymap", + ".pic": "image/pict", + ".pict": "image/pict", + ".pm": "image/x-xpixmap", + ".png": "image/png", + ".pnm": "image/x-portable-anymap", + ".ppm": "image/x-portable-pixmap", + ".qcp": "audio/vnd.qcelp", + ".qif": "image/x-quicktime", + ".qt": "video/quicktime", + ".qtc": "video/x-qtc", + ".qti": "image/x-quicktime", + ".qtif": "image/x-quicktime", + ".ra": "audio/x-realaudio", + ".ram": "audio/x-pn-realaudio", + ".ras": "image/cmu-raster", + ".rast": "image/cmu-raster", + ".rf": "image/vnd.rn-realflash", + ".rgb": "image/x-rgb", + ".rm": "audio/x-pn-realaudio", + ".rmi": "audio/mid", + ".rmm": "audio/x-pn-realaudio", + ".rmp": "audio/x-pn-realaudio", + ".rp": "image/vnd.rn-realpix", + ".rpm": "audio/x-pn-realaudio-plugin", + ".rv": "video/vnd.rn-realvideo", + ".s3m": "audio/s3m", + ".scm": "video/x-scm", + ".sid": "audio/x-psid", + ".snd": "audio/x-adpcm", + ".svf": "image/vnd.dwg", + ".tif": "image/tiff", + ".tiff": "image/tiff", + ".tsi": "audio/tsp-audio", + ".tsp": "audio/tsplayer", + ".vdo": "video/vdo", + ".viv": "video/vivo", + ".vivo": "video/vivo", + ".voc": "audio/voc", + ".vos": "video/vosaic", + ".vox": "audio/voxware", + ".vqe": "audio/x-twinvq-plugin", + ".vqf": "audio/x-twinvq", + ".vql": "audio/x-twinvq-plugin", + ".wav": "audio/wav", + ".wbmp": "image/vnd.wap.wbmp", + ".xbm": "image/xbm", + ".xdr": "video/x-amt-demorun", + ".xif": "image/vnd.xiff", + ".xm": "audio/xm", + ".xmz": "xgl/movie", + ".xpm": "image/xpm", + ".x-png": "image/png", + ".xsr": "video/x-amt-showrun" +}; \ No newline at end of file diff --git a/node_modules/mediaserver/package.json b/node_modules/mediaserver/package.json new file mode 100755 index 0000000..56d3d44 --- /dev/null +++ b/node_modules/mediaserver/package.json @@ -0,0 +1,19 @@ +{ + "name": "mediaserver", + "description": "Media & static asset streaming for http(s) server", + "version": "0.1.1", + "author": { + "name": "Oguz Bastemur", + "email": "obastemur@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/obastemur/mediaserver" + }, + "engines": { + "node": ">= 0.10.0" + }, + "license": "MIT", + "homepage": "https://github.com/obastemur/mediaserver", + "readmeFilename": "Readme.md" +} diff --git a/node_modules/mediaserver/sample/app.js b/node_modules/mediaserver/sample/app.js new file mode 100755 index 0000000..fe274f4 --- /dev/null +++ b/node_modules/mediaserver/sample/app.js @@ -0,0 +1,21 @@ +var http = require('http'), + ms = require('../index'); + +var path = require('path'); + +http.createServer(function (req, res) { + + var _path; + if(req.url == "/" || req.url == "/index.html"){ + _path = "/index.html"; + } else if (req.url == "/birds.ogg") { + _path = "/birds.ogg"; + } else { + res.write("Target Not Found!" ); + res.end(); + return; + } + + ms.pipe(req, res, path.join(__dirname, _path), path.extname(_path)); + +}).listen(1337, '127.0.0.1'); \ No newline at end of file diff --git a/node_modules/mediaserver/sample/birds.ogg b/node_modules/mediaserver/sample/birds.ogg new file mode 100755 index 0000000..221d06e Binary files /dev/null and b/node_modules/mediaserver/sample/birds.ogg differ diff --git a/node_modules/mediaserver/sample/index.html b/node_modules/mediaserver/sample/index.html new file mode 100755 index 0000000..375fe48 --- /dev/null +++ b/node_modules/mediaserver/sample/index.html @@ -0,0 +1,14 @@ + + +
+ +