diff --git a/config/custom-environment-variables.json b/config/custom-environment-variables.json index 1a2f8501..cb9b9aa3 100644 --- a/config/custom-environment-variables.json +++ b/config/custom-environment-variables.json @@ -1,5 +1,8 @@ { "WalletConfig": { "lbryAddress": "LBRY_WALLET_ADDRESS" + }, + "Database": { + "MySqlConnectionUri": "MYSQL_CONNECTION_STRING" } } \ No newline at end of file diff --git a/config/default.json b/config/default.json index 17c51244..5691ff63 100644 --- a/config/default.json +++ b/config/default.json @@ -4,5 +4,9 @@ }, "AnalyticsConfig":{ "googleId": "none" + }, + "Database": { + "MySqlConnectionUri": "none", + "PublishUploadPath": "none" } } \ No newline at end of file diff --git a/config/development.json b/config/development.json index c1bac572..a673979c 100644 --- a/config/development.json +++ b/config/development.json @@ -4,5 +4,9 @@ }, "AnalyticsConfig":{ "googleId": "UA-100747990-1" + }, + "Database": { + "MySqlConnectionUri": "none", + "PublishUploadPath": "C:\\lbry\\speech\\hosted_content" } } \ No newline at end of file diff --git a/config/production.json b/config/production.json index 95f72955..4f815ce7 100644 --- a/config/production.json +++ b/config/production.json @@ -4,5 +4,9 @@ }, "AnalyticsConfig":{ "googleId": "UA-60403362-2" + }, + "Database": { + "MySqlConnectionUri": "none", + "PublishUploadPath": "~/Downloads/" } } \ No newline at end of file diff --git a/config/test.json b/config/test.json new file mode 100644 index 00000000..8d0379c2 --- /dev/null +++ b/config/test.json @@ -0,0 +1,12 @@ +{ + "WalletConfig": { + "lbryAddress": "none" + }, + "AnalyticsConfig":{ + "googleId": "UA-100747990-1" + }, + "Database": { + "MySqlConnectionUri": "none", + "PublishUploadPath": "~/Downloads/" + } +} \ No newline at end of file diff --git a/controllers/publishController.js b/controllers/publishController.js new file mode 100644 index 00000000..9bf8f5e4 --- /dev/null +++ b/controllers/publishController.js @@ -0,0 +1,57 @@ +var fs = require('fs'); +var lbryApi = require('../helpers/libraries/lbryApi.js'); +var config = require('config'); +var errorHandlers = require("../helpers/libraries/errorHandlers.js"); + +var walledAddress = config.get('WalletConfig.lbryAddress'); + +function createPublishParams(claim, filePath, license, nsfw) { + console.log("nsfw:", nsfw, typeof nsfw); + var publishParams = { + "name": claim, + "file_path": filePath, + "bid": 0.01, + "metadata": { + "description": claim + " published via spee.ch", + "title": claim, + "author": "spee.ch", + "language": "en", + "license": license, + "nsfw": (nsfw.toLowerCase() === "on") + }, + "claim_address": walledAddress, + "change_address": walledAddress + }; + return publishParams; +} + +function deleteTemporaryFile(filePath) { + fs.unlink(filePath, function(err) { + if (err) throw err; + console.log('successfully deleted ' + filePath); + }); +} + +module.exports = { + publish: function(claim, fileName, filePath, fileType, license, nsfw, socket, visitor) { + // update the client + socket.emit("publish-status", "Your image is being published (this might take a second)..."); + // send to analytics + visitor.event("Publish Route", "Publish Request", filePath).send(); + // create the publish object + var publishParams = createPublishParams(claim, filePath, license, nsfw); + // get a promise to publish + lbryApi.publishClaim(publishParams, fileName, fileType) + .then(function(result){ + visitor.event("Publish Route", "Publish Success", filePath).send(); + console.log("publish promise success. Tx info:", result) + socket.emit("publish-complete", {name: claim, result: result}); + }) + .catch(function(error){ + visitor.event("Publish Route", "Publish Failure", filePath).send(); + console.log("error:", error); + socket.emit("publish-failure", errorHandlers.handlePublishError(error)); + deleteTemporaryFile(filePath); + }); + } +} \ No newline at end of file diff --git a/controllers/serveController.js b/controllers/serveController.js new file mode 100644 index 00000000..324cfd6c --- /dev/null +++ b/controllers/serveController.js @@ -0,0 +1,102 @@ +var lbryApi = require('../helpers/libraries/lbryApi.js'); +var db = require("../models"); + +var getAllFreePublicClaims = require("../helpers/functions/getAllFreePublicClaims.js"); +var isFreePublicClaim = require("../helpers/functions/isFreePublicClaim.js"); + +function getClaimAndHandleResponse(claimUri, resolve, reject){ + lbryApi.getClaim(claimUri) + .then(function(result){ + resolve({ + file_name: result.file_name, + file_path: result.download_path, + file_type: result.mime_type + }); + }).catch(function(error){ + reject(error) + }); +} + +module.exports = { + getClaimByName: function(claimName){ + var deferred = new Promise(function (resolve, reject){ + console.log(">> lbryHelpers >> getClaim BasedOnNameOnly:", claimName); + // get all free public claims + getAllFreePublicClaims(claimName) + .then(function(freePublicClaimList){ + console.log(">> Decided on public claim id:", freePublicClaimList[0].claim_id); + var freePublicClaimOutpoint = freePublicClaimList[0].txid + ":" + freePublicClaimList[0].nout; + var freePublicClaimUri = freePublicClaimList[0].name + "#" + freePublicClaimList[0].claim_id; + // check to see if the file is available locally + db.File.findOne({where: { claim_id: freePublicClaimList[0].claim_id }}) + .then(function(claim){ + // if a found locally... + if (claim){ + console.log(">> A matching claim_id was found locally"); + // if the outpoint's match return it + if (claim.dataValues.outpoint === freePublicClaimOutpoint){ + console.log(">> Local outpoint matched"); + resolve(claim.dataValues); + // if the outpoint's don't match, fetch updated claim + } else { + console.log(">> local outpoint did not match"); + getClaimAndHandleResponse(freePublicClaimUri, resolve, reject); + } + // ... otherwise use daemon to retrieve it + } else { + // 'get' the claim + getClaimAndHandleResponse(freePublicClaimUri, resolve, reject) + } + }).catch(function(error){ + reject(error); + }); + }).catch(function(error){ + reject(error); + }); + }); + return deferred; + }, + getClaimByClaimId: function(claimName, claimId){ + var deferred = new Promise(function (resolve, reject){ + var uri = claimName + "#" + claimId; + console.log(">> lbryHelpers >> getClaimBasedOnUri:", uri); + // resolve the Uri + lbryApi.resolveUri(uri) // note: use 'spread' and make parallel with db.File.findOne() + .then(function(result){ // note should just be 'result' returned. + // get the outpoint + var resolvedOutpoint = result[uri].claim.txid + ":" + result[uri].claim.nout; + // check locally for the claim + db.File.findOne({where: { claim_id: claimId }}) + .then(function(claim){ + // if a found locally... + if (claim){ + console.log(">> A matching claim_id was found locally"); + // if the outpoint's match return it + if (claim.dataValues.outpoint === resolvedOutpoint){ + console.log(">> Local outpoint matched"); + resolve(claim.dataValues); + // if the outpoint's don't match, fetch updated claim + } else { + console.log(">> Local outpoint did not match"); + getClaimAndHandleResponse(uri, resolve, reject); + } + // ... otherwise use daemon to retrieve it + } else { + // check to make sure it is free and public (note: no need for another resolve?) + if (isFreePublicClaim(result[uri].claim)){ + // 'get' the claim + getClaimAndHandleResponse(uri, resolve, reject); + } else { + reject("NO_FREE_PUBLIC_CLAIMS"); + } + } + }).catch(function(error){ + reject(error) + }); + }).catch(function(error){ + reject(error); + }); + }); + return deferred; + } +} diff --git a/controllers/showController.js b/controllers/showController.js new file mode 100644 index 00000000..78adc0f9 --- /dev/null +++ b/controllers/showController.js @@ -0,0 +1,7 @@ +var getAllFreePublicClaims = require("../helpers/functions/getAllFreePublicClaims.js"); + +module.exports = { + getAllClaims: function(claimName){ + return getAllFreePublicClaims(claimName); + } +} \ No newline at end of file diff --git a/helpers/functions/getAllFreePublicClaims.js b/helpers/functions/getAllFreePublicClaims.js new file mode 100644 index 00000000..f9e1f0d6 --- /dev/null +++ b/helpers/functions/getAllFreePublicClaims.js @@ -0,0 +1,61 @@ +var isFreePublicClaim = require("./isFreePublicClaim.js"); +var lbryApi = require('../libraries/lbryApi.js'); + +function filterForFreePublicClaims(claimsListArray){ + //console.log("claims list:", claimsListArray) + if (!claimsListArray) { + return null; + }; + var freePublicClaims = claimsListArray.filter(function(claim){ + if (!claim.value){ + return false; + } + return (isFreePublicClaim(claim)); + }); + return freePublicClaims; +} + +function orderTopClaims(claimsListArray){ + console.log(">> orderTopClaims"); + claimsListArray.sort(function(claimA, claimB){ + if (claimA.amount === claimB.amount){ + return (claimA.height > claimB.height); + } else { + return (claimA.amount < claimB.amount); + } + }) + return claimsListArray; +} + +module.exports = function(claimName){ + var deferred = new Promise(function(resolve, reject){ + // make a call to the daemon to get the claims list + lbryApi.getClaimsList(claimName) + .then(function(result){ + var claimsList = result.claims; + console.log(">> Number of claims:", claimsList.length) + // return early if no claims were found + if (claimsList.length === 0){ + reject("NO_CLAIMS"); + console.log("exiting due to lack of claims"); + return; + } + // filter the claims to return only free, public claims + var freePublicClaims = filterForFreePublicClaims(claimsList); + // return early if no free, public claims were found + if (!freePublicClaims || (freePublicClaims.length === 0)){ + reject("NO_FREE_PUBLIC_CLAIMS"); + console.log("exiting due to lack of free or public claims"); + return; + } + // order the claims + var orderedPublicClaims = orderTopClaims(freePublicClaims); + // resolve the promise + resolve(orderedPublicClaims); + }).catch(function(error){ + console.log(">> 'claim_list' error"); + reject(error); + }); + }); + return deferred; +} \ No newline at end of file diff --git a/helpers/functions/isFreePublicClaim.js b/helpers/functions/isFreePublicClaim.js new file mode 100644 index 00000000..5103635e --- /dev/null +++ b/helpers/functions/isFreePublicClaim.js @@ -0,0 +1,11 @@ + +module.exports = function(claim){ + console.log(">> check: isFreePublicClaim?"); + if (((claim.value.stream.metadata.license.indexOf("Public Domain") != -1 ) || (claim.value.stream.metadata.license.indexOf("Creative Commons") != -1 )) + && + (!claim.value.stream.metadata.fee || claim.value.stream.metadata.fee.amount === 0)) { + return true; + } else { + return false; + } +}; \ No newline at end of file diff --git a/helpers/lbryHelpers.js b/helpers/lbryHelpers.js deleted file mode 100644 index b4fb8d21..00000000 --- a/helpers/lbryHelpers.js +++ /dev/null @@ -1,134 +0,0 @@ -var path = require('path'); -var axios = require('axios'); -var lbryApi = require('./lbryApi'); - -function filterForFreePublicClaims(claimsListArray){ - //console.log("claims list:", claimsListArray) - if (!claimsListArray) { - return null; - }; - var freePublicClaims = claimsListArray.filter(function(claim){ - if (!claim.value){ - return false; - } - return (((claim.value.stream.metadata.license.indexOf('Public Domain') != -1) || (claim.value.stream.metadata.license.indexOf('Creative Commons') != -1)) && - (!claim.value.stream.metadata.fee || claim.value.stream.metadata.fee === 0)); - }); - return freePublicClaims; -} - -function isFreePublicClaim(claim){ - console.log(">> isFreePublicClaim? claim:", claim); - if ((claim.value.stream.metadata.license === 'Public Domain' || claim.value.stream.metadata.license === 'Creative Commons') && - (!claim.value.stream.metadata.fee || claim.value.stream.metadata.fee.amount === 0)) { - return true; - } else { - return false; - } -} - -function orderTopClaims(claimsListArray){ - console.log(">> orderTopClaims"); - claimsListArray.sort(function(claimA, claimB){ - if (claimA.amount === claimB.amount){ - return (claimA.height > claimB.height); - } else { - return (claimA.amount < claimB.amount); - } - }) - return claimsListArray; -} - -function getAllFreePublicClaims(claimName){ - var deferred = new Promise(function(resolve, reject){ - // make a call to the daemon to get the claims list - lbryApi.getClaimsList(claimName) - .then(function(data){ - var claimsList = data.result.claims; - console.log(">> Number of claims:", claimsList.length) - // return early if no claims were found - if (claimsList.length === 0){ - reject("NO_CLAIMS"); - console.log("exiting due to lack of claims"); - return; - } - // filter the claims to return only free, public claims - var freePublicClaims = filterForFreePublicClaims(claimsList); - // return early if no free, public claims were found - if (!freePublicClaims || (freePublicClaims.length === 0)){ - reject("NO_FREE_PUBLIC_CLAIMS"); - console.log("exiting due to lack of free or public claims"); - return; - } - // order the claims - var orderedPublicClaims = orderTopClaims(freePublicClaims); - // resolve the promise - resolve(orderedPublicClaims); - }).catch(function(error){ - console.log(">> 'claim_list' error"); - reject(error); - }); - }); - return deferred; -} - -module.exports = { - getClaimBasedOnNameOnly: function(claimName){ - var deferred = new Promise(function (resolve, reject){ - console.log(">> lbryHelpers >> getClaim BasedOnNameOnly:", claimName); - // promise to get all free public claims - getAllFreePublicClaims(claimName) - .then(function(freePublicClaimList){ - var freePublicClaimUri = freePublicClaimList[0].name + "#" + freePublicClaimList[0].claim_id; - console.log(">> successfully received free public claim URI:", freePublicClaimUri); - // promise to get the chosen uri - lbryApi.getClaim(freePublicClaimUri) - .then(function(data){ - resolve({ - fileName: data.result.file_name, - directory: data.result.download_directory, - contentType: data.result.metadata.stream.source.contentType - }); - }).catch(function(error){ - reject(error) - }); - }).catch(function(error){ - reject(error); - }); - }); - return deferred; - }, - getClaimBasedOnUri: function(uri){ - var deferred = new Promise(function (resolve, reject){ - console.log(">> lbryHelpers >> getClaimBasedOnUri:", uri); - // resolve the claim - lbryApi.resolveUri(uri) - .then(function(resolvedUri){ - //console.log("result >>", resolvedUri) - // check to make sure it is free and public - if (isFreePublicClaim(resolvedUri.result[uri].claim)){ - // promise to get the chosen uri - lbryApi.getClaim(uri) - .then(function(data){ - resolve({ - fileName: data.result.file_name, - directory: data.result.download_directory, - contentType: data.result.metadata.stream.source.contentType - }); - }).catch(function(error){ - reject(error) - }); - } else { - reject("NO_FREE_PUBLIC_CLAIMS"); - } - }).catch(function(error){ - reject(error) - }); - - }); - return deferred; - }, - getAllClaims: function(claimName){ // note: work in progress - return getAllFreePublicClaims(claimName); - } -} diff --git a/helpers/routeHelpers.js b/helpers/libraries/errorHandlers.js similarity index 64% rename from helpers/routeHelpers.js rename to helpers/libraries/errorHandlers.js index f3f43814..031e1ebc 100644 --- a/helpers/routeHelpers.js +++ b/helpers/libraries/errorHandlers.js @@ -1,5 +1,3 @@ -var path = require('path'); - module.exports = { handleRequestError: function(error, res) { if ((error === "NO_CLAIMS") || (error === "NO_FREE_PUBLIC_CLAIMS")){ @@ -11,5 +9,14 @@ module.exports = { } else { res.status(400).send(error.toString()); }; - } + }, + handlePublishError: function(error) { + if (error.code === "ECONNREFUSED"){ + return "Connection refused. The daemon may not be running."; + } else if (error.response.data.error) { + return error.response.data.error; + } else { + return error; + }; +} } diff --git a/helpers/lbryApi.js b/helpers/libraries/lbryApi.js similarity index 57% rename from helpers/lbryApi.js rename to helpers/libraries/lbryApi.js index 79d2ce08..82466a51 100644 --- a/helpers/lbryApi.js +++ b/helpers/libraries/lbryApi.js @@ -1,15 +1,28 @@ var axios = require('axios'); +var db = require("../../models"); module.exports = { - publishClaim: function(publishParams){ + publishClaim: function(publishParams, fileName, fileType){ var deferred = new Promise(function(resolve, reject){ console.log(">> lbryApi >> publishClaim:", publishParams); axios.post('http://localhost:5279/lbryapi', { "method": "publish", "params": publishParams }).then(function (response) { - console.log(">> 'publish' success"); - resolve(response.data); + console.log(">> 'publish' success", response); + var result = response.data.result; + db.File.create({ + name: publishParams.name, + claim_id: result.claim_id, + outpoint: result.txid + ":" + result.nout, + file_name: fileName, + file_path: publishParams.file_path, + file_type: fileType, + nsfw: publishParams.metadata.nsfw, + }).catch(function(error){ + console.log('An error occurred when writing to the MySQL database:', error); + }); + resolve(result); }).catch(function(error){ console.log(">> 'publish' error"); reject(error); @@ -23,22 +36,32 @@ module.exports = { axios.post('http://localhost:5279/lbryapi', { "method": "get", "params": { "uri": uri, "timeout": 20} - }).then(function (getResponse) { + }).then(function (response) { console.log(">> 'get' success"); - //check to make sure the daemon didn't just time out (or otherwise send an error that appears to be a success response) - if (getResponse.data.result.error){ - reject(getResponse.data.result.error); + //check to make sure the daemon didn't just time out + if (response.data.result.error){ + reject(response.data.result.error); } - // resolve the promise with the download path for the claim we got /* note: put in a check to make sure we do not resolve until the download is actually complete (response.data.completed === true) */ - resolve(getResponse.data); - }).catch(function(getUriError){ + // save a record of the file to the Files table + var result = response.data.result + db.File.create({ + name: result.name, + claim_id: result.claim_id, + outpoint: result.outpoint, + file_name: result.file_name, + file_path: result.download_path, + file_type: result.mime_type, + nsfw: result.metadata.stream.metadata.nsfw, + }).catch(function(error){ + console.log('An error occurred when writing to the MySQL database:', error); + }); + resolve(result); + }).catch(function(error){ console.log(">> 'get' error"); - // reject the promise with an error message - reject(getUriError); - return; + reject(error); }); }); return deferred; @@ -51,7 +74,7 @@ module.exports = { params: { name: claimName } }).then(function (response) { console.log(">> 'claim_list' success"); - resolve(response.data); + resolve(response.data.result); }).catch(function(error){ console.log(">> 'claim_list' error"); reject(error); @@ -67,7 +90,7 @@ module.exports = { "params": { "uri": uri} }).then(function(response){ console.log(">> 'resolve' success"); - resolve(response.data); + resolve(response.data.result); }).catch(function(error){ console.log(">> 'resolve' error"); reject(error); diff --git a/helpers/socketHelpers.js b/helpers/socketHelpers.js deleted file mode 100644 index 59688edd..00000000 --- a/helpers/socketHelpers.js +++ /dev/null @@ -1,65 +0,0 @@ -var fs = require('fs'); -var lbryApi = require('../helpers/lbryApi.js'); -var config = require('config'); - -var walledAddress = config.get('WalletConfig.lbryAddress'); - -function handlePublishError(error) { - if (error.code === "ECONNREFUSED"){ - return "Connection refused. The daemon may not be running."; - } else if (error.response.data.error) { - return error.response.data.error; - } else { - return error; - }; -} - -function createPublishParams(name, filepath, license, nsfw) { - var publishParams = { - "name": name, - "file_path": filepath, - "bid": 0.01, - "metadata": { - "description": name + " published via spee.ch", - "title": name, - "author": "spee.ch", - "language": "en", - "license": license, - "nsfw": (nsfw.toLowerCase() === "true") - }, - "claim_address": walledAddress, - "change_address": walledAddress //requires daemon 0.12.2rc1 or above - }; - return publishParams; -} - -function deleteTemporaryFile(filepath) { - fs.unlink(filepath, function(err) { - if (err) throw err; - console.log('successfully deleted ' + filepath); - }); -} - -module.exports = { - publish: function(name, filepath, license, nsfw, socket, visitor) { - // update the client - socket.emit("publish-status", "Your image is being published (this might take a second)..."); - visitor.event("Publish Route", "Publish Request", filepath).send(); - // create the publish object - var publishParams = createPublishParams(name, filepath, license, nsfw); - // get a promise to publish - lbryApi.publishClaim(publishParams) - .then(function(data){ - visitor.event("Publish Route", "Publish Success", filepath).send(); - console.log("publish promise success. Tx info:", data) - socket.emit("publish-complete", {name: name, result: data.result}); - deleteTemporaryFile(filepath); - }) - .catch(function(error){ - visitor.event("Publish Route", "Publish Failure", filepath).send(); - console.log("error:", error); - socket.emit("publish-failure", handlePublishError(error)); - deleteTemporaryFile(filepath); - }); - } -} \ No newline at end of file diff --git a/models/file.js b/models/file.js new file mode 100644 index 00000000..3e696558 --- /dev/null +++ b/models/file.js @@ -0,0 +1,35 @@ +module.exports = function(sequelize, DataTypes){ + var File = sequelize.define("File", { + name: { + type: DataTypes.STRING, + allowNull: false + }, + claim_id: { + type: DataTypes.STRING, + allowNull: false + }, + outpoint: { + type: DataTypes.STRING, + allowNull: false + }, + file_name: { + type: DataTypes.STRING, + allowNull: false + }, + file_path: { + type: DataTypes.STRING, + allowNull: false + }, + file_type: { + type: DataTypes.STRING, + }, + nsfw: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + } + }, { + freezeTableName: true + }); + return File; +} \ No newline at end of file diff --git a/models/index.js b/models/index.js new file mode 100644 index 00000000..7d1ffe47 --- /dev/null +++ b/models/index.js @@ -0,0 +1,41 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var Sequelize = require('sequelize'); +var basename = path.basename(module.filename); +var config = require('config'); +var db = {}; + +var connectionUri = config.get('Database.MySqlConnectionUri'); +var sequelize = new Sequelize(connectionUri); + +sequelize + .authenticate() + .then(() => { + console.log('Connection has been established successfully.'); + }) + .catch(err => { + console.error('Unable to connect to the database:', err); + }); + +fs + .readdirSync(__dirname) + .filter(function(file) { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(function(file) { + var model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach(function(modelName) { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/package.json b/package.json index ddc14060..0b28aec9 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,9 @@ "config": "^1.26.1", "express": "^4.15.2", "express-handlebars": "^3.0.0", + "mysql2": "^1.3.5", "nodemon": "^1.11.0", + "sequelize": "^4.1.0", "socket.io": "^2.0.1", "socketio-file-upload": "^0.6.0", "universal-analytics": "^0.4.13" diff --git a/routes/api-routes.js b/routes/api-routes.js index 5eb306a0..449f5b50 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -1,15 +1,17 @@ +var errorHandlers = require("../helpers/libraries/errorHandlers.js"); +var lbryApi = require("../helpers/libraries/lbryApi.js"); -module.exports = function(app, routeHelpers, lbryApi){ +module.exports = function(app){ // route to run a claim_list request on the daemon app.get("/api/claim_list/:claim", function(req, res){ lbryApi.getClaimsList(req.params.claim) - .then(function(orderedFreePublicImages){ + .then(function(claimsList){ console.log("/api/claim_list/:claim success."); - res.status(200).json(orderedFreePublicImages); + res.status(200).json(claimsList); }) .catch(function(error){ console.log("/api/claim_list/:name error:", error); - routeHelpers.handleRequestError(error, res); + errorHandlers.handleRequestError(error, res); }); }); // route to run a resolve request on the daemon @@ -19,7 +21,7 @@ module.exports = function(app, routeHelpers, lbryApi){ console.log("/api/resolve/:claim success."); res.status(200).json(resolvedUri); }).catch(function(error){ - routeHelpers.handleRequestError(error, res); + errorHandlers.handleRequestError(error, res); }); }); diff --git a/routes/serve-routes.js b/routes/serve-routes.js index ed50f446..933121d9 100644 --- a/routes/serve-routes.js +++ b/routes/serve-routes.js @@ -1,14 +1,16 @@ +var errorHandlers = require("../helpers/libraries/errorHandlers.js"); +var serveController = require("../controllers/serveController.js"); + function serveFile(fileInfo, res){ // set default options var options = { - root: fileInfo.directory, headers: { "X-Content-Type-Options": "nosniff", - "Content-Type": fileInfo.contentType + "Content-Type": fileInfo.file_type } }; // adjust default options as needed - switch (fileInfo.contentType){ + switch (fileInfo.file_type){ case "image/jpeg": break; case "image/gif": @@ -23,37 +25,39 @@ function serveFile(fileInfo, res){ break; } // send file - res.status(200).sendFile(fileInfo.fileName, options); + res.status(200).sendFile(fileInfo.file_path, options); } -module.exports = function(app, routeHelpers, lbryHelpers, ua, googleAnalyticsId){ +module.exports = function(app, ua, googleAnalyticsId){ // route to fetch one free public claim app.get("/:name/:claim_id", function(req, res){ - ua(googleAnalyticsId, {https: true}).event("Serve Route", "/name/claimId", req.params.name + "/" + req.params.claim_id).send(); - var uri = req.params.name + "#" + req.params.claim_id; - console.log(">> GET request on /" + uri); - // create promise - lbryHelpers.getClaimBasedOnUri(uri) + var routeString = req.params.name + "/" + req.params.claim_id; + // google analytics + ua(googleAnalyticsId, {https: true}).event("Serve Route", "/name/claimId", routeString).send(); + // begin image-serve processes + console.log(">> GET request on /" + routeString); + serveController.getClaimByClaimId(req.params.name, req.params.claim_id) .then(function(fileInfo){ - console.log("/:name/:claim_id success.", fileInfo.fileName); + console.log("/:name/:claim_id success.", fileInfo.file_name); serveFile(fileInfo, res); }).catch(function(error){ console.log("/:name/:claim_id error:", error) - routeHelpers.handleRequestError(error, res); + errorHandlers.handleRequestError(error, res); }); }); // route to fetch one free public claim app.get("/:name", function(req, res){ + // google analytics ua(googleAnalyticsId, {https: true}).event("Serve Route", "/name", req.params.name).send(); + // begin image-serve processes console.log(">> GET request on /" + req.params.name); - // create promise - lbryHelpers.getClaimBasedOnNameOnly(req.params.name) + serveController.getClaimByName(req.params.name) .then(function(fileInfo){ - console.log("/:name success.", fileInfo.fileName); + console.log("/:name success.", fileInfo.file_name); serveFile(fileInfo, res); }).catch(function(error){ console.log("/:name error:", error); - routeHelpers.handleRequestError(error, res); + errorHandlers.handleRequestError(error, res); }); }); } \ No newline at end of file diff --git a/routes/show-routes.js b/routes/show-routes.js index 2a809d62..a705271a 100644 --- a/routes/show-routes.js +++ b/routes/show-routes.js @@ -1,11 +1,14 @@ +var errorHandlers = require("../helpers/libraries/errorHandlers.js"); +var showController = require("../controllers/showController.js"); -module.exports = function(app, routeHelpers, lbryHelpers, ua, googleAnalyticsId){ - // route to fetch all free public claims +module.exports = function(app, ua, googleAnalyticsId){ + // route to fetch all free public claims app.get("/:name/all", function(req, res){ console.log(">> GET request on /" + req.params.name + "/all"); + // google analytics ua(googleAnalyticsId, {https: true}).event("Show Routes", "/name/all", req.params.name + "/all").send(); - // create promise - lbryHelpers.getAllClaims(req.params.name) + // fetch all free public claims + showController.getAllClaims(req.params.name) .then(function(orderedFreePublicClaims){ console.log("/:name/all success."); res.status(200).render('allClaims', { claims: orderedFreePublicClaims }); @@ -13,7 +16,7 @@ module.exports = function(app, routeHelpers, lbryHelpers, ua, googleAnalyticsId) }) .catch(function(error){ console.log("/:name/all error:", error); - routeHelpers.handleRequestError(error, res); + errorHandlers.handleRequestError(error, res); }) }); } diff --git a/routes/sockets-routes.js b/routes/sockets-routes.js index 570268d6..4a476f02 100644 --- a/routes/sockets-routes.js +++ b/routes/sockets-routes.js @@ -1,4 +1,6 @@ -module.exports = function(app, path, siofu, socketHelpers, ua, googleAnalyticsId) { +var publishController = require('../controllers/publishController.js'); + +module.exports = function(app, siofu, hostedContentPath, ua, googleAnalyticsId) { var http = require('http').Server(app); var io = require('socket.io')(http); @@ -8,9 +10,10 @@ module.exports = function(app, path, siofu, socketHelpers, ua, googleAnalyticsId var visitor = ua(googleAnalyticsId, {https: true}); // attach upload listeners var uploader = new siofu(); - uploader.dir = path.join(__dirname, '../../Uploads'); + uploader.dir = hostedContentPath; uploader.listen(socket); uploader.on("start", function(event){ + // server side test to make sure file is not a bad file type if (/\.exe$/.test(event.file.name)) { uploader.abort(event.file.id, socket); } @@ -20,12 +23,13 @@ module.exports = function(app, path, siofu, socketHelpers, ua, googleAnalyticsId socket.emit("publish-status", event.error) }); uploader.on("saved", function(event){ - console.log("saved " + event.file.name); + console.log("uploaded ", event.file.name); if (event.file.success){ socket.emit("publish-status", "file upload successfully completed"); - socketHelpers.publish(event.file.meta.name, event.file.pathName, event.file.meta.license, event.file.meta.nsfw, socket, visitor) + publishController.publish(event.file.meta.name, event.file.name, event.file.pathName, event.file.meta.type, event.file.meta.license, event.file.meta.nsfw, socket, visitor) } else { socket.emit("publish-failure", "file uploaded, but with errors") + // to-do: remove the file }; }); // handle disconnect diff --git a/server.js b/server.js index c27b7fed..c56bbadd 100644 --- a/server.js +++ b/server.js @@ -9,18 +9,15 @@ var axios = require('axios'); var config = require('config'); var ua = require('universal-analytics'); -var socketHelpers = require('./helpers/socketHelpers.js'); -var routeHelpers = require('./helpers/routeHelpers.js'); -var lbryApi = require('./helpers/lbryApi.js'); -var lbryHelpers = require('./helpers/lbryHelpers.js'); - var googleAnalyticsId = config.get('AnalyticsConfig.googleId'); +var hostedContentPath = config.get('Database.PublishUploadPath'); // set port var PORT = 3000; - // initialize express app var app = express(); +//require our models for syncing +var db = require("./models"); // make express look in the public directory for assets (css/js/img) app.use(express.static(__dirname + '/public')); @@ -52,15 +49,21 @@ app.engine('handlebars', hbs.engine); app.set('view engine', 'handlebars'); // require express routes -require("./routes/api-routes.js")(app, routeHelpers, lbryApi); -require("./routes/show-routes.js")(app, routeHelpers, lbryHelpers, ua, googleAnalyticsId); -require("./routes/serve-routes.js")(app, routeHelpers, lbryHelpers, ua, googleAnalyticsId); +require("./routes/api-routes.js")(app); +require("./routes/show-routes.js")(app, ua, googleAnalyticsId); +require("./routes/serve-routes.js")(app, ua, googleAnalyticsId); require("./routes/home-routes.js")(app); -// wrap the server in socket.io to intercept incoming sockets requests -var http = require("./routes/sockets-routes.js")(app, path, siofu, socketHelpers, ua, googleAnalyticsId); +// require socket.io routes +var http = require("./routes/sockets-routes.js")(app, siofu, hostedContentPath, ua, googleAnalyticsId); +// sync sequelize +// wrap the server in socket.io to intercept incoming sockets requests // start server -http.listen(PORT, function() { - console.log("Listening on PORT " + PORT); +db.sequelize.sync({}) +.then(function(){ + http.listen(PORT, function() { + console.log("Listening on PORT " + PORT); + }); }); + diff --git a/views/allClaims.handlebars b/views/allClaims.handlebars index 28abbad4..75b5eb20 100644 --- a/views/allClaims.handlebars +++ b/views/allClaims.handlebars @@ -8,7 +8,7 @@

claim_id: {{this.claim_id}}

-

direct link here

+

direct link here

author: {{this.value.stream.metadata.author}}

description: {{this.value.stream.metadata.description}}

license: {{this.value.stream.metadata.license}}

diff --git a/views/index.handlebars b/views/index.handlebars index 57a4f439..ea81218f 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -132,6 +132,7 @@ event.file.meta.name = name; event.file.meta.license = license; event.file.meta.nsfw = nsfw; + event.file.meta.type = stagedFiles[0].type; // re-set the html in the publish area document.getElementById('publish-active-area').innerHTML = '
'; // start a progress animation diff --git a/views/partials/documentation.handlebars b/views/partials/documentation.handlebars index 217649a6..a7d8243a 100644 --- a/views/partials/documentation.handlebars +++ b/views/partials/documentation.handlebars @@ -1,6 +1,6 @@
-
+

Site Navigation

diff --git a/views/partials/examples.handlebars b/views/partials/examples.handlebars index 43acd663..3535d957 100644 --- a/views/partials/examples.handlebars +++ b/views/partials/examples.handlebars @@ -1,6 +1,6 @@
-
+

Examples

diff --git a/views/partials/publish.handlebars b/views/partials/publish.handlebars index a6c40fde..e99aedbb 100644 --- a/views/partials/publish.handlebars +++ b/views/partials/publish.handlebars @@ -1,6 +1,6 @@
-
+

Publish Your Own

diff --git a/views/partials/topBar.handlebars b/views/partials/topBar.handlebars index 3d406f09..27cd80ab 100644 --- a/views/partials/topBar.handlebars +++ b/views/partials/topBar.handlebars @@ -1,10 +1,21 @@
-
+
-

Spee.ch

+
+
+ +
+
+

Spee.ch

+
+
+
+
+

Spee.ch is a single-serving site that reads and publishes images to and from the LBRY blockchain.

+
+
-

Spee.ch is a single-serving site that reads and publishes images to and from the LBRY blockchain.

\ No newline at end of file