diff --git a/helpers/lbryApi.js b/helpers/lbryApi.js index 6170d83e..a9314401 100644 --- a/helpers/lbryApi.js +++ b/helpers/lbryApi.js @@ -1,10 +1,7 @@ -// load dependencies var path = require('path'); var axios = require('axios'); -// helper function to filter an array of claims for only free, public claims function filterForFreePublicClaims(claimsListArray){ - //console.log(">> filterForFreePublicClaims, claimsListArray:", claimsListArray); if (!claimsListArray) { return null; }; @@ -14,7 +11,7 @@ function filterForFreePublicClaims(claimsListArray){ }); return freePublicClaims; } -// helper function to decide if a claim is free and public + function isFreePublicClaim(claim){ console.log(">> isFreePublicClaim, claim:", claim); if ((claim.value.stream.metadata.license === 'Public Domain' || claim.value.stream.metadata.license === 'Creative Commons') && @@ -24,7 +21,7 @@ function isFreePublicClaim(claim){ return false; } } -// helper function to order a set of claims + function orderTopClaims(claimsListArray){ console.log(">> orderTopClaims, claimsListArray:"); claimsListArray.sort(function(claimA, claimB){ @@ -46,8 +43,8 @@ function getClaimWithUri(uri, resolve, reject){ ).then(function (getUriResponse) { console.log(">> 'get claim' success..."); //check to make sure the daemon didn't just time out - if (getUriResponse.data.result.error === "Timeout"){ - reject("get request to lbry daemon timed out"); + if (getUriResponse.data.result.error){ + reject(getUriResponse.data.result.error); } console.log(">> response data:", getUriResponse.data); console.log(">> dl path =", getUriResponse.data.result.download_path) @@ -57,9 +54,9 @@ function getClaimWithUri(uri, resolve, reject){ */ resolve(getUriResponse.data.result.download_path); }).catch(function(getUriError){ - console.log(">> 'get' error:", getUriError.response.data); + console.log(">> 'get' error."); // reject the promise with an error message - reject(getUriError.response.data.error.message); + reject(getUriError); return; }); } @@ -82,16 +79,10 @@ module.exports = { console.log(">> 'publish' success"); // return the claim we got resolve(response.data); - return; }).catch(function(error){ // receive response from LBRY console.log(">> 'publish' error"); - if (error.response.data.error){ - reject(error.response.data.error); - } else { - reject(error); - } - return; + reject(error); }) }) return deferred; @@ -134,16 +125,8 @@ module.exports = { getClaimWithUri(freePublicClaimUri, resolve, reject); }) .catch(function(error){ - console.log(">> 'claim_list' error:", error); - // reject the promise with an approriate message - if (error.code === "ECONNREFUSED"){ - reject("Connection refused. The daemon may not be running.") - } else if (error.response.data.error) { - reject(error.response.data.error); - } else { - reject(error); - }; - return; + console.log(">> 'claim_list' error."); + reject(error); }); }); // 3. return the promise @@ -200,14 +183,8 @@ module.exports = { */ resolve(orderedPublicClaims); }).catch(function(error){ - console.log(">> 'claim_list' error:", error); - if (error.code === "ECONNREFUSED"){ - reject("Connection refused. The daemon may not be running.") - } else if (error.response.data.error) { - reject(error.response.data.error); - } else { - reject(error); - }; + console.log(">> 'claim_list' error"); + reject(error); }) }); return deferred; diff --git a/helpers/queueApi.js b/helpers/queueApi.js deleted file mode 100644 index 6f8c5fef..00000000 --- a/helpers/queueApi.js +++ /dev/null @@ -1,22 +0,0 @@ -// require amqp library -var amqp = require('amqplib/callback_api'); - -module.exports = { - addNewTaskToQueue: function(task){ - // connect to RabbitMQ server - amqp.connect('amqp://localhost', function(err, conn) { - // create a channel - conn.createChannel(function(err, ch) { - var q = 'task_queue2'; // declaring a que is idempotent (it will only be created if it doesnt already exist) - var msg = task || "request received with no task!"; - // declare a queue - ch.assertQueue(q, {durable: true}); - // publish a message to the queue - ch.sendToQueue(q, new Buffer.from(msg), {persistent: true}); - console.log(` [x] Sent '${msg}' to ${q}`); - }); - // close the connection and exit - setTimeout(function() {conn.close() }, 500); - }); - } -} \ No newline at end of file diff --git a/helpers/routeHelpers.js b/helpers/routeHelpers.js new file mode 100644 index 00000000..6aa294c4 --- /dev/null +++ b/helpers/routeHelpers.js @@ -0,0 +1,15 @@ +var path = require('path'); + +module.exports = { + handleRequestError: function(error, res) { + if ((error === "NO_CLAIMS") || (error === "NO_FREE_PUBLIC_CLAIMS")){ + res.status(307).sendFile(path.join(__dirname, '../public', 'noClaims.html')); + } else if (error.response){ + res.status(error.response.status).send(error.response.data.error.message); + } else if (error.code === "ECONNREFUSED") { + res.status(400).send("Connection refused. The daemon may not be running."); + } else { + res.status(400).send(error.toString()); + }; + } +} diff --git a/helpers/socketHelpers.js b/helpers/socketHelpers.js new file mode 100644 index 00000000..0a4f41fe --- /dev/null +++ b/helpers/socketHelpers.js @@ -0,0 +1,57 @@ +var fs = require('fs'); +var lbryApi = require('../helpers/lbryApi.js'); + +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.1, + "metadata": { + "description": name + " published via spee.ch", + "title": name, + "author": "spee.ch", + "language": "en", + "license": license, + "nsfw": (nsfw.toLowerCase() === "true") + } + }; + 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) { + // update the client + socket.emit("publish-status", "Your image is being published (this might take a second)..."); + // create the publish object + var publishParams = createPublishParams(name, filepath, license, nsfw); + // get a promise to publish + lbryApi.publishClaim(publishParams) + .then(function(data){ + console.log("publish promise success. Tx info:", data) + socket.emit("publish-complete", {name: name, result: data.result}); + deleteTemporaryFile(filepath); + }) + .catch(function(error){ + console.log("error:", error); + socket.emit("publish-failure", handlePublishError(error)); + deleteTemporaryFile(filepath); + }); + } +} \ No newline at end of file diff --git a/package.json b/package.json index a3ef74fd..2300bd02 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,8 @@ }, "homepage": "https://github.com/billbitt/spee.ch-backend#readme", "dependencies": { - "amqplib": "^0.5.1", "axios": "^0.16.1", "body-parser": "^1.17.1", - "connect-multiparty": "^2.0.0", "express": "^4.15.2", "nodemon": "^1.11.0", "socket.io": "^2.0.1", diff --git a/public/assets/css/style.css b/public/assets/css/style.css new file mode 100644 index 00000000..e69de29b diff --git a/public/favicon.ico b/public/assets/img/favicon.ico similarity index 100% rename from public/favicon.ico rename to public/assets/img/favicon.ico diff --git a/public/claimPlus.html b/public/claimPlus.html deleted file mode 100644 index 678eedd9..00000000 --- a/public/claimPlus.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - Spee.ch Claim - - -
-

spee.ch

-

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

-

Status:

-

Your image is being retrieved

-
- - - - diff --git a/public/eagle.jpg b/public/eagle.jpg deleted file mode 100644 index cb736738..00000000 Binary files a/public/eagle.jpg and /dev/null differ diff --git a/public/index.html b/public/index.html index 579fc672..775aed4c 100644 --- a/public/index.html +++ b/public/index.html @@ -5,91 +5,128 @@ Spee.ch +

spee.ch

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

-

Examples:

- -

Publish Your Own

-
-
- -
- Image preview... -
- Name: -
- License: -
- NSFW: -
- -
-

-
- -

Help Wanted!

-

If you would like to help make spee.ch amazing, join our slack channel.

-

We are currently in need of a designer to help with styling spee.ch's front end, but all help is welcome!

- -

Help

-

Site Navigation

- -

API

-

Note: these are being used for testing durring spee.ch development and may not be maintained

- - +
+

Examples:

+ +
+
+

Publish Your Own

+
+
+ +
+ Image preview... +
+ Name: +
+ License: +
+ NSFW: +
+ +
+
+
+
+

Help Wanted!

+

If you would like to help make spee.ch amazing, join our slack channel.

+

We are currently in need of a designer to help with styling spee.ch's front end, but all help is welcome!

+
+
+

Documentation

+

Site Navigation

+ +

API

+

Note: these are being used for testing durring spee.ch development and may not be maintained

+ +
+
+

Links

+ github + lbry + slack +
+
+

Bugs

+

Spee.ch is young and under continuous development so it will have bugs. Please leave an issue on our github if you experience a problem or have suggestions.

+
 .w. +
(o|o) +
  `'` +
diff --git a/routes/api-routes.js b/routes/api-routes.js index 67bbed41..235caa86 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -1,11 +1,7 @@ -// require dependencies var path = require('path'); var axios = require('axios'); -var multipart = require('connect-multiparty'); -var multipartMiddleware = multipart(); -// import helpers + var lbryApi = require('../helpers/lbryApi.js'); -var queueApi = require('../helpers/queueApi.js'); module.exports = function(app){ // route to return claim list in json diff --git a/routes/html-routes.js b/routes/html-routes.js index 6253e54f..b8e01c09 100644 --- a/routes/html-routes.js +++ b/routes/html-routes.js @@ -1,41 +1,26 @@ -// load dependencies var path = require('path'); -var multipart = require('connect-multiparty'); -var multipartMiddleware = multipart(); -// load helpers +var routeHelpers = require('../helpers/routeHelpers.js'); var lbryApi = require('../helpers/lbryApi.js'); -var queueApi = require('../helpers/queueApi.js'); -// routes to export module.exports = function(app){ // route to fetch one free public claim app.get("/favicon.ico", function(req, res){ console.log(" >> GET request on favicon.ico"); - res.sendFile(path.join(__dirname, '../public', 'favicon.ico')); + res.sendFile(path.join(__dirname, '../public/assets/img', 'favicon.ico')); }); // route to fetch one free public claim app.get("/:name/all", function(req, res){ - var name = req.params.name; - console.log(">> GET request on /" + name + " (all)"); + console.log(">> GET request on /" + req.params.name + " (all)"); // create promise - var promise = lbryApi.getAllClaims(name); - // handle the promise resolve - promise.then(function(orderedFreePublicClaims){ - console.log("/name/all promise success.") + lbryApi.getAllClaims(req.params.name) + .then(function(orderedFreePublicClaims){ + console.log("/:name/all success.") res.status(200).send(orderedFreePublicClaims); return; }) - // handle the promise rejection .catch(function(error){ - console.log("/name/all/ promise error:", error); - // handle the error - if ((error === "NO_CLAIMS") || (error === "NO_FREE_PUBLIC_CLAIMS")){ - res.status(307).sendFile(path.join(__dirname, '../public', 'noClaims.html')); - return; - } else { - res.status(400).send(error); - return; - }; + console.log("/:name/all error:", error); + routeHelpers.handleRequestError(error, res); }) }); // route to fetch one free public claim @@ -43,56 +28,33 @@ module.exports = function(app){ var uri = req.params.name + "#" + req.params.claim_id; console.log(">> GET request on /" + uri); // create promise - var promise = lbryApi.getClaimBasedOnUri(uri); - // handle the promise resolve - promise.then(function(filePath){ - console.log("/name/claim_id promise success - filepath:", filePath) + lbryApi.getClaimBasedOnUri(uri) + .then(function(filePath){ + console.log("/:name/:claim_id success."); res.status(200).sendFile(filePath); - return; }) - // handle the promise rejection .catch(function(error){ - console.log("/name/claim_id/ promise error:", error) - // handle the error - if (error === "Invalid URI") { - res.status(400).sendFile(path.join(__dirname, '../public', 'invalidUri.html')); - return; - } else { - res.status(400).send(error); - return; - }; + console.log("/:name/:claim_id error.") + routeHelpers.handleRequestError(error, res); }); }); - // route to fetch one free public claim app.get("/:name", function(req, res){ - var name = req.params.name; - console.log(">> GET request on /" + name); + console.log(">> GET request on /" + req.params.name); // create promise - var promise = lbryApi.getClaimBasedOnNameOnly(name); - // handle the promise resolve - promise.then(function(filePath){ - console.log("/name promise success - filepath:", filePath) + lbryApi.getClaimBasedOnNameOnly(req.params.name) + .then(function(filePath){ + console.log("/:name success.") res.status(200).sendFile(filePath); - return; - }) - // handle the promise rejection - .catch(function(error){ - console.log("/name/ promise error:", error); - // handle the error - if ((error === "NO_CLAIMS") || (error === "NO_FREE_PUBLIC_CLAIMS")){ - res.status(307).sendFile(path.join(__dirname, '../public', 'noClaims.html')); - return; - }; - res.status(400).send(error); + }).catch(function(error){ + console.log("/:name error."); + routeHelpers.handleRequestError(error, res); }); }); - // route for the home page app.get("/", function(req, res){ res.status(200).sendFile(path.join(__dirname, '../public', 'index.html')); }); - // a catch-all route if someone visits a page that does not exist app.use("*", function(req, res){ res.status(404).sendFile(path.join(__dirname, '../public', 'fourOhfour.html')); diff --git a/routes/sockets-routes.js b/routes/sockets-routes.js index edd1d4a9..76ac399e 100644 --- a/routes/sockets-routes.js +++ b/routes/sockets-routes.js @@ -1,61 +1,16 @@ module.exports = function(app) { var http = require('http').Server(app); var io = require('socket.io')(http); - var fs = require('fs'); var path = require('path'); - var lbryApi = require('../helpers/lbryApi.js'); - var queueApi = require('../helpers/queueApi.js'); var siofu = require("socketio-file-upload"); - - // functions to create a publishing object - function createPublishParams(name, filepath, license, nsfw){ - var publishParams = { - "name": name, - "file_path": filepath, - "bid": 0.1, - "metadata": { - "description": name + " published via spee.ch", - "title": name, - "author": "spee.ch", - "language": "en", - "license": license, - "nsfw": (nsfw.toLowerCase() === "true") - } - }; - return publishParams; - } - // publish an image to lbry - function publish(name, filepath, license, nsfw, socket){ - // update the client - socket.emit("publish-status", "Your image is being published (this might take a second)..."); - // create the publish object - var publishParams = createPublishParams(name, filepath, license, nsfw); - // get a promise to publish - var promise = lbryApi.publishClaim(publishParams); - // handle promise - promise.then(function(data){ - console.log("publish promise success. Tx info:", data) - socket.emit("publish-complete", data); - /* - note: remember to delete the local file - */ - }) - .catch(function(error){ - console.log("error:", error); - socket.emit("publish-status", "publish failed"); - /* - note: remember to delete the local file - */ - }); - }; + var socketHelpers = require('../helpers/socketHelpers.js'); io.on('connection', function(socket){ console.log('a user connected'); - // listener for uploader + // attach upload listeners var uploader = new siofu(); uploader.dir = path.join(__dirname, '../../Uploads'); uploader.listen(socket); - // attach upload listeners uploader.on("error", function(event){ console.log("an error occured while uploading", event.error); socket.emit("publish-status", event.error) @@ -64,12 +19,11 @@ module.exports = function(app) { console.log("saved " + event.file.name); if (event.file.success){ socket.emit("publish-status", "file upload successfully completed"); - publish(event.file.meta.name, event.file.pathName, event.file.meta.license,event.file.meta.nsfw, socket) + socketHelpers.publish(event.file.meta.name, event.file.pathName, event.file.meta.license,event.file.meta.nsfw, socket) } else { - socket.emit("publish-status", "file saved, but with errors") + socket.emit("publish-failure", "file uploaded, but with errors") }; }); - // handle disconnect socket.on('disconnect', function(){ console.log('user disconnected'); diff --git a/worker.js b/worker.js deleted file mode 100644 index dd7b179d..00000000 --- a/worker.js +++ /dev/null @@ -1,31 +0,0 @@ -// load dependencies -var amqp = require('amqplib/callback_api'); -// load helpers -var lbryApi = require('./helpers/lbryApi'); -// open a connection and a channel -amqp.connect('amqp://localhost', function(err, conn) { - // open a channel - conn.createChannel(function(err, ch) { - var q = 'task_queue2'; - // declare the cue (in case the publisher hasn't made it yet) - ch.assertQueue(q, {durable: true}); - // tell the queue to only assign one task at a time to this worker - ch.prefetch(1); - // listen for messages & pass callback for what to do with the msgs - console.log(" [x] Waiting for messages in %s. To exit press ctrl+c", q); - ch.consume(q, function(msg) { - var task = JSON.parse(msg.content.toString()); - console.log(` [o] Received a ${task.type} task`); - // initiate the task - switch(task.type) { - case 'publish': - console.log(" [-] publishing:", task.data); - lbryApi.publishClaim(task.data); - break; - default: - console.log(" [-] that task type is not recognized"); - console.log(" [x] Done"); - } - }, {noAck: true}); - }); -}); \ No newline at end of file