Merge pull request #32 from lbryio/mysql
mysql - record and check state of local files
This commit is contained in:
commit
fcbb844b3e
28 changed files with 469 additions and 267 deletions
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"WalletConfig": {
|
||||
"lbryAddress": "LBRY_WALLET_ADDRESS"
|
||||
},
|
||||
"Database": {
|
||||
"MySqlConnectionUri": "MYSQL_CONNECTION_STRING"
|
||||
}
|
||||
}
|
|
@ -4,5 +4,9 @@
|
|||
},
|
||||
"AnalyticsConfig":{
|
||||
"googleId": "none"
|
||||
},
|
||||
"Database": {
|
||||
"MySqlConnectionUri": "none",
|
||||
"PublishUploadPath": "none"
|
||||
}
|
||||
}
|
|
@ -4,5 +4,9 @@
|
|||
},
|
||||
"AnalyticsConfig":{
|
||||
"googleId": "UA-100747990-1"
|
||||
},
|
||||
"Database": {
|
||||
"MySqlConnectionUri": "none",
|
||||
"PublishUploadPath": "C:\\lbry\\speech\\hosted_content"
|
||||
}
|
||||
}
|
|
@ -4,5 +4,9 @@
|
|||
},
|
||||
"AnalyticsConfig":{
|
||||
"googleId": "UA-60403362-2"
|
||||
},
|
||||
"Database": {
|
||||
"MySqlConnectionUri": "none",
|
||||
"PublishUploadPath": "~/Downloads/"
|
||||
}
|
||||
}
|
12
config/test.json
Normal file
12
config/test.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"WalletConfig": {
|
||||
"lbryAddress": "none"
|
||||
},
|
||||
"AnalyticsConfig":{
|
||||
"googleId": "UA-100747990-1"
|
||||
},
|
||||
"Database": {
|
||||
"MySqlConnectionUri": "none",
|
||||
"PublishUploadPath": "~/Downloads/"
|
||||
}
|
||||
}
|
57
controllers/publishController.js
Normal file
57
controllers/publishController.js
Normal file
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
102
controllers/serveController.js
Normal file
102
controllers/serveController.js
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
7
controllers/showController.js
Normal file
7
controllers/showController.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
var getAllFreePublicClaims = require("../helpers/functions/getAllFreePublicClaims.js");
|
||||
|
||||
module.exports = {
|
||||
getAllClaims: function(claimName){
|
||||
return getAllFreePublicClaims(claimName);
|
||||
}
|
||||
}
|
61
helpers/functions/getAllFreePublicClaims.js
Normal file
61
helpers/functions/getAllFreePublicClaims.js
Normal file
|
@ -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;
|
||||
}
|
11
helpers/functions/isFreePublicClaim.js
Normal file
11
helpers/functions/isFreePublicClaim.js
Normal file
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
35
models/file.js
Normal file
35
models/file.js
Normal file
|
@ -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;
|
||||
}
|
41
models/index.js
Normal file
41
models/index.js
Normal file
|
@ -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;
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
29
server.js
29
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);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<img class="all-claims-img" src="https://spee.ch/{{this.name}}/{{this.claim_id}}" />
|
||||
<div class="card card-block">
|
||||
<p>claim_id: {{this.claim_id}}</p>
|
||||
<p>direct link <a href="https://spee.ch/{{this.name}}/{{this.claim_id}}">here</a></p>
|
||||
<p>direct link <a href="/{{this.name}}/{{this.claim_id}}">here</a></p>
|
||||
<p>author: {{this.value.stream.metadata.author}}</p>
|
||||
<p>description: {{this.value.stream.metadata.description}}</p>
|
||||
<p>license: {{this.value.stream.metadata.license}}</p>
|
||||
|
|
|
@ -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 = '<div id="publish-status"></div><div id="progress-bar"></div>';
|
||||
// start a progress animation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="col-md-12">
|
||||
<div class="card" id="documentation">
|
||||
<div class="card-title card-block default-color-dark white-text">
|
||||
<div class="card-title card-block grey lighten-1 white-text">
|
||||
<h2>Site Navigation</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="col-md-12">
|
||||
<div class="card" id="examples">
|
||||
<div class="card-title card-block default-color-dark white-text">
|
||||
<div class="card-title card-block grey lighten-1 white-text">
|
||||
<h2>Examples</h2>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="col-md-12">
|
||||
<div class="card" id="publish">
|
||||
<div class="card-title card-block default-color-dark white-text">
|
||||
<div class="card-title card-block grey lighten-1 white-text">
|
||||
<h2>Publish Your Own</h2>
|
||||
</div>
|
||||
<div class="card-block" id="publish-active-area">
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card card-block default-color-dark white-text">
|
||||
<div class="card card-block grey white-text">
|
||||
<div class="card-title">
|
||||
<h1><a class="white-text" href="/">Spee.ch</a></h1>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<img src="/speech/900227fe5c778eb2a6424d923af806c669ea3a3c"/>
|
||||
</div>
|
||||
<div class="col-md-10 align-self-center">
|
||||
<h1><a class="white-text" href="/">Spee.ch</a></h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p>Spee.ch is a single-serving site that reads and publishes images to and from the <a class="white-text" href="https://lbry.io">LBRY</a> blockchain.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Spee.ch is a single-serving site that reads and publishes images to and from the <a class="white-text" href="https://lbry.io">LBRY</a> blockchain.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue