Merge pull request #14 from billbitt/master

replacing live-coded spee.ch with @billbitt js version
This commit is contained in:
Bill Bittner 2017-05-24 11:09:06 -07:00 committed by GitHub
commit c2ff396058
19 changed files with 579 additions and 209 deletions

2
.gitignore vendored
View file

@ -1 +1 @@
.idea/
node_modules

View file

@ -1,85 +0,0 @@
<?php
if (!defined('ROOT_PAGE')) { die('not allowed'); }
class LBRY
{
public static function api($function, array $params = [])
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:5279/lbryapi');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['method' => $function, 'params' => $params]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$serverOutput = curl_exec($ch);
curl_close($ch);
if ($serverOutput)
{
$responseData = json_decode($serverOutput, true);
if (isset($responseData['error']))
{
throw new Exception($responseData['error']['message'] ?? 'Something unknown went wrong');
}
if (isset($responseData['result']))
{
return $responseData['result'];
}
throw new Exception('Received unknown response format.');
}
}
public static function publishPublicClaim($name, $tmpFileName)
{
$filePath = '/home/lbry/publishes/newupload-' . random_int(1, PHP_INT_MAX);
move_uploaded_file($tmpFileName, $filePath);
$apiResult = LBRY::api('publish', [
'name' => $name,
'bid' => 1,
'file_path' => $filePath,
'description' => 'An image published from spee.ch',
'author' => 'https://spee.ch',
'language' => 'en',
'license' => 'Public Domain',
'nsfw' => 0,
'title' => 'Image published from spee.ch'
]);
return isset($apiResult['claim_id']);
}
public static function findTopPublicFreeClaim($name)
{
$claims = LBRY::api('claim_list', ['name' => $name]);
if (!$claims || !isset($claims['claims']))
{
return null;
}
$freePublicClaims = array_filter($claims['claims'], function($claim) {
$metadata = json_decode($claim['value'], true);
return
//TODO: Expand these checks AND verify it is an image claim!
($metadata['license'] == "Public Domain" || stripos($metadata['license'], 'Creative Commons') !== false) &&
!isset($metadata['fee']);
});
if (count($freePublicClaims) > 1)
{
usort($freePublicClaims, function($claimA, $claimB) {
if ($claimA['amount'] == $claimB['amount'])
{
return $claimA['height'] < $claimB['height'] ? -1 : 1;
}
return $claimA['amount'] > $claimB['amount'] ? -1 : 1;
});
}
return reset($freePublicClaims);
}
}

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 LBRY
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.

View file

@ -1,6 +1,44 @@
# spee.ch
spee.ch is a simple but powerful image hosting service on top of the LBRY protocol.
# spee.ch (js)
this is a clone of spee.ch with a javascript backend
It was built in real-time on March 29th, 2017.
## how to use this repository
* start lbry
* install the [`lbry`](https://github.com/lbryio/lbry) daemon
* start the `lbry` daemon
* start RabbitMQ (this will handle the queue for background processing)
* install & run [RabbitMQ](https://www.rabbitmq.com/#getstarted)
* clone this repo
* run `npm install`
* from your terminal, run `npm start`
* to run hot, run `nodemon server.js`
* start at least one worker by running `node worker.js`
* visit [localhost:3000](http://localhost:3000) and enjoy!
You can watch the video and learn more from [https://spee.ch](https://spee.ch)
## site navigation
* spee.ch.
* To publish a file, navigate to the homepage.
* spee.ch/<the name of the claim>
* To view the file with the largest bid at a claim.
* E.g. spee.ch/doitlive.
* spee.ch/< the name of the claim >/< the claim_id >
* To view a specific file at a claim
* E.g. spee.ch/doitlive/c496c8c55ed79816fec39e36a78645aa4458edb5
* spee.ch/<the name of the claim>/all
* To view a batch of files at a claim
* E.g. spee.ch/doitlive/all
## development to-do's
* discover/explore functionality for home page
* display a list of claims at /:name/all
* fetching: a temporary page while the request is being made (with a loading bar?)
* publishing: a temporary page while the request is being handled by the server (with a loading bar?)
* publishing: after publishing, take the user to a temp page with the tx info and status of the tx (then redirect when the tx is complete)
## API
Note: these are being used for testing durring spee.ch development and may not be maintained
* A GET request to spee.ch/claim_list/<the name of the claim>
* Will return the claim_list for the claim in json format.
* E.g. spee.ch/claim_list/doitlive

173
helpers/lbryApi.js Normal file
View file

@ -0,0 +1,173 @@
// 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;
};
var freePublicClaims = claimsListArray.filter(function(claim){
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;
}
// 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') &&
(!claim.value.stream.metadata.fee || claim.value.stream.metadata.fee.amount === 0)) {
return true;
} else {
return false;
}
}
// helper function to order a set of claims
function orderTopClaims(claimsListArray){
console.log(">> orderTopClaims, claimsListArray:");
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 = {
publishClaim: function(publishObject){
axios.post('http://localhost:5279/lbryapi', publishObject)
.then(function (response) {
// receive resonse from LBRY
// if successfull, (1) delete file (2) send response to the client
console.log(">> 'publish' success...");
console.log(">> 'publish' response.data:", response.data);
console.log(" [x] Done");
// return the claim we got
//res.status(200).send(JSON.stringify({msg: "you succsessfully published!", txData: response.data}));
}).catch(function(error){
// receive response from LBRY
// if not successfull, (1) delete file and (2) send response to the client
console.log(">> 'publish' error.response.data:", error.response.data);
console.log(" [x] Done");
//res.status(500).send(JSON.stringify({msg: "your file was not published", err: error.response.data.error.message}));
})
},
serveClaimBasedOnNameOnly: function(claimName, res){
// make a call to the daemon to get the claims list
axios.post('http://localhost:5279/lbryapi', {
method: "claim_list",
params: {
name: claimName
}
}
).then(function (response) {
console.log(">> Claim_list success");
console.log(">> Number of claims:", response.data.result.claims.length)
// return early if no claims were found
if (response.data.result.claims.length === 0){
res.status(200).sendFile(path.join(__dirname, '../public', 'noClaims.html'));
return;
}
// filter the claims to return free, public claims
var freePublicClaims = filterForFreePublicClaims(response.data.result.claims);
// return early if no free, public claims were found
if (!freePublicClaims || (freePublicClaims.length === 0)){
res.status(200).sendFile(path.join(__dirname, '../public', 'noClaims.html'));
return;
}
// order the claims
var orderedPublcClaims = orderTopClaims(freePublicClaims);
// create the uri for the first (selected) claim
console.log(">> ordered free public claims", orderedPublcClaims);
var freePublicClaimUri = "lbry://" + orderedPublcClaims[0].name + "#" + orderedPublcClaims[0].claim_id;
console.log(">> your free public claim uri:", freePublicClaimUri);
// fetch the image to display
axios.post('http://localhost:5279/lbryapi', {
method: "get",
params: {
uri: freePublicClaimUri
}
}
).then(function (getResponse) {
console.log(">> 'get claim' success...");
console.log(">> response data:", getResponse.data);
console.log(">> dl path =", getResponse.data.result.download_path)
// return the claim we got
res.status(200).sendFile(getResponse.data.result.download_path);
}).catch(function(getError){
console.log(">> /c/ 'get' error:", getError.response.data);
res.status(500).send(JSON.stringify({msg: "An error occurred while fetching the free, public claim by URI.", err: getError.response.data.error.message}));
})
}).catch(function(error){
console.log(">> /c/ error:", error.response.data);
res.status(500).send(JSON.stringify({msg: "An error occurred while getting the claim list.", err: error.response.data.error.message}));
})
},
serveClaimBasedOnUri: function(uri, res){
/*
to do: need to pass the URI through a test (use 'resolve') to see if it is free and public. Right now it is jumping straight to 'get'ing and serving the asset.
*/
console.log(">> your uri:", uri);
// fetch the image to display
axios.post('http://localhost:5279/lbryapi', { // to do: abstract this code to a function that can be shared
method: "get",
params: {
uri: uri
}
}
).then(function (getResponse) {
console.log(">> 'get claim' success...");
console.log(">> response data:", getResponse.data);
console.log(">> dl path =", getResponse.data.result.download_path)
/*
to do: make sure the file has completed downloading before serving back the file
*/
// return the claim we got
res.status(200).sendFile(getResponse.data.result.download_path);
/* delete the file after a certain amount of time? */
}).catch(function(error){
console.log(">> /c/ 'get' error:", error.response.data);
res.status(500).send(JSON.stringify({msg: "an error occurred", err: error.response.data.error.message}));
})
},
serveAllClaims: function(claimName, res){
// make a call to the daemon to get the claims list
axios.post('http://localhost:5279/lbryapi', {
method: "claim_list",
params: {
name: claimName
}
}
).then(function (response) {
console.log(">> Claim_list success");
console.log(">> Number of claims:", response.data.result.claims.length)
// return early if no claims were found
if (response.data.result.claims.length === 0){
res.status(200).sendFile(path.join(__dirname, '../public', 'noClaims.html'));
return;
}
// filter the claims to return free, public claims
var freePublicClaims = filterForFreePublicClaims(response.data.result.claims);
// return early if no free, public claims were found
if (!freePublicClaims || (freePublicClaims.length === 0)){
res.status(200).sendFile(path.join(__dirname, '../public', 'noClaims.html'));
return;
}
console.log(">> Number of free public claims:", freePublicClaims.length);
// order the claims
var orderedPublicClaims = orderTopClaims(freePublicClaims);
// serve the response
res.status(200).send(orderedPublicClaims); //to do: rather than returning json, serve a page of all these claims
}).catch(function(error){
console.log(">> /c/ error:", error.response.data);
// serve the response
res.status(500).send(JSON.stringify({msg: "An error occurred while finding the claim list.", err: error.response.data.error.message}));
})
}
}

22
helpers/queueApi.js Normal file
View file

@ -0,0 +1,22 @@
// 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);
});
}
}

View file

@ -1,39 +0,0 @@
<?php
if (!defined('ROOT_PAGE')) { die('not allowed'); }
$claim = LBRY::findTopPublicFreeClaim($name);
if ($claim)
{
$getResult = LBRY::api('get', ['name' => $name, 'claim_id' => $claim['claim_id']]);
if (isset($getResult['completed']) && $getResult['completed'] && isset($getResult['download_path']))
{
$path = $getResult['download_path'];
// $validType = isset($getResult['content_type']) && in_array($getResult['content_type'], ['image/jpeg', 'image/png']);
header('Content-type: image/jpeg');
header('Content-length: ' . filesize($path));
readfile($getResult['download_path']);
}
elseif (isset($getResult['written_bytes']))
{
echo 'This image is on it\'s way...<br/>';
echo 'Received: ' . $getResult['written_bytes'] . " / " . $getResult['total_bytes'] . ' bytes';
}
else
{
echo 'There seems to be a valid claim, but are having trouble retrieving the content.';
}
}
elseif (isset($_GET['new']) && $_GET['new'])
{
echo 'Your image is on the way. It can take a few minutes to reach the blockchain and be public. You can refresh this page to check the progress.';
}
else
{
echo 'No valid claim for this name. Make one!';
include './publish.php';
}
exit(0);

View file

@ -1,45 +0,0 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
define('ROOT_PAGE', 1);
require_once './LBRY.class.php';
$urlParts = parse_url($_SERVER['REQUEST_URI']);
$name = ltrim($urlParts['path'], '/');
if ($name)
{
include './image.php';
exit(0);
}
if (isset($_POST['publish']) && isset($_POST['name']) && isset($_FILES['file']))
{
$success = LBRY::publishPublicClaim($_POST['name'], $_FILES['file']['tmp_name']);
if ($success)
{
header('Location: /' . $_POST['name'] . '?new=1');
}
else
{
echo '<p>Something went wrong publishing your content. We are only somewhat sorry.</p>';
}
exit(0);
}
?>
<!DOCTYPE html>
<h1><img src="https://spee.ch/speechlogo" alt="spee.ch logo" style="max-height: 36px; vertical-align: middle; max-width: 36px;" />spee.ch</h1>
<p>spee.ch is a single-serving site that reads and publishes images to and from the <a href="https://lbry.io">LBRY</a> blockchain.</p>
<p>Examples:</p>
<ul>
<?php foreach(['thailand', 'doitlive', 'coconuts', 'cow-air-balloon'] as $sampleName): ?>
<li><a href="/<?php echo $sampleName ?>">spee.ch/<?php echo $sampleName ?></a></li>
<?php endforeach ?>
</ul>
<h3>Publish Your Own</h3>
<?php include './publish.php' ?>
<h3>About This Site</h3>
<p>It was built live in a little over 2 hours on March 29th, 2017. You can watch the video here:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/C9LCapt_OYw" frameborder="0" allowfullscreen></iframe>

33
package.json Normal file
View file

@ -0,0 +1,33 @@
{
"name": "spee.ch-backend",
"version": "0.0.1",
"description": "a back end for spee.ch",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/billbitt/spee.ch-backend.git"
},
"keywords": [
"spee.ch",
"lbry",
"blockchain"
],
"author": "@billbitt @vxn",
"license": "MIT",
"bugs": {
"url": "https://github.com/billbitt/spee.ch-backend/issues"
},
"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"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

14
public/fourOhfour.html Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Four Oh Four</title>
</head>
<body>
<h1>spee.ch</h1>
<h3>404: Not Found</h3>
<p>That page does not exist. Return <a href="/">home</a>.</p>
</body>
</html>

106
public/index.html Normal file
View file

@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Spee.ch</title>
</head>
<body>
<h1>spee.ch</h1>
<p>spee.ch is a single-serving site that reads and publishes images to and from the <a href="https://lbry.io">LBRY</a> blockchain.</p>
<h3>Examples:</h3>
<ul>
<li><a href="/coconuts">spee.ch/coconuts</a></li>
<li><a href="/test">spee.ch/test</a></li>
<li><a href="/doitlive">spee.ch/doitlive</a></li>
<li><a href="/doitlive/all">spee.ch/doitlive/all</a></li>
<li><a href="/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0">spee.ch/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0</a></li>
</ul>
<h3>Publish Your Own</h3>
<form id="publish-form" action="/publish" method="post" enctype="multipart/form-data">
<input type="file" name="file" accept="video/*,image/*" onchange="previewFile()" enctype="multipart/form-data"/>
<br/>
<img src="" height="200" alt="Image preview..."/>
<br/>
Title: <input type="text" name="title" value="title"/>
<br/>
Description: <input type="text" name="description" value="description"/>
<br/>
Author: <input type="text" name="author" value="author"/>
<br/>
Language: <input type="text" name="language" value="en"/>
<br/>
License: <select type="text" name="license" value="license">
<option value="Creative Commons">Creative Commons</option>
<option value="Public Domain">Public Domain</option>
</select>
<br/>
NSFW: <select type="text" name="nsfw" value="nsfw">
<option value="true">True</option>
<option value="false">False</option>
</select>
<br/>
<button type="submit">Submit</button>
</form>
<h3>Help</h3>
<h4>Site Navigation</h4>
<ul>
<li><strong><a href="/">spee.ch</a></strong>.
<ul>
<li>To publish a file, navigate to the homepage.</li>
</ul>
</li>
<li><strong>spee.ch/&ltthe name of the claim&gt</strong>
<ul>
<li>To view the file with the largest bid at a claim.</li>
<li>E.g. <a href="/doitlive">spee.ch/doitlive</a>.</li>
</ul>
</li>
<li><strong>spee.ch/&lt the name of the claim &gt/&lt the claim_id &gt</strong>
<ul>
<li>To view a specific file at a claim</li>
<li>E.g. <a href="/doitlive/c496c8c55ed79816fec39e36a78645aa4458edb5">spee.ch/doitlive/c496c8c55ed79816fec39e36a78645aa4458edb5</a></li>
</ul>
</li>
<li><strong>spee.ch/&ltthe name of the claim&gt/all</strong>
<ul>
<li>To view a batch of files at a claim</li>
<li>E.g. <a href="/doitlive/all">spee.ch/doitlive/all</a></li>
</ul>
</li>
</ul>
<h4>API</h4>
<p>Note: these are being used for testing durring spee.ch development and may not be maintained</p>
<ul>
<li>A GET request to <strong>spee.ch/claim_list/&ltthe name of the claim&gt</strong>
<ul>
<li>Will return the claim_list for the claim in json format. </li>
<li>E.g. <a href="/claim_list/doitlive">spee.ch/claim_list/doitlive</a></li>
</ul>
</li>
</ul>
<script>
function previewFile(){
var preview = document.querySelector('img'); //selects the query named img
var file = document.querySelector('input[type=file]').files[0]; //sames as here
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file); //reads the data as a URL
} else {
preview.src = "";
}
}
previewFile(); //calls the function named previewFile()
</script>
</body>
</html>

14
public/noClaims.html Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>No Claims</title>
</head>
<body>
<h1>spee.ch</h1>
<h3>No Claims</h3>
<p>There are no free, public images at that claim. You should publish one at <a href="/">spee.ch</a>.</p>
</body>
</html>

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Publishing Asset</title>
</head>
<body>
<h1>spee.ch</h1>
<h3>Publishing Asset</h3>
<p>Your asset is being published by a handy background worker. You can return to <a href="/">spee.ch</a> and your asset should be published to your claim shortly.</p>
</body>
</html>

View file

@ -1,14 +0,0 @@
<form method="POST" action="/" enctype="multipart/form-data">
<div>
<input type="file" name="file" />
</div>
<?php if (isset($name) && $name != ''): ?>
<input type="hidden" name="name" value="<?php echo $name ?>" />
<?php else: ?>
<div>
lbry://<input type="text" name="name" />
</div>
<?php endif ?>
<input type="submit" name="publish" value="Go" />
<p>Publishing can take a few moments. Please be patient.</p>
</form>

29
routes/api-routes.js Normal file
View file

@ -0,0 +1,29 @@
// 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
app.get("/claim_list/:claim", function(req, res){
var claim = req.params.claim;
// make a call to the daemon
axios.post('http://localhost:5279/lbryapi', {
method: "claim_list",
params: {
name: claim
}
}
).then(function (response) {
console.log("success");
res.send(response.data);
}).catch(function(error){
console.log(error.data);
res.send(error.data);
})
});
}

80
routes/html-routes.js Normal file
View file

@ -0,0 +1,80 @@
// load dependencies
var path = require('path');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
// load helpers
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'));
});
// route to publish a new claim
app.post("/publish", multipartMiddleware, function(req, res){
// receive the request
console.log(" >> POST request on /publish");
//console.log(">> req.files:", req.files)
console.log(" >> req.body:", req.body)
// build the data needed to publish the file
var publishObject = {
"method":"publish",
"params": {
"name": req.body.title,
"file_path": req.files.file.path,
"bid": 0.1,
"metadata": {
"description": req.body.description,
"title": req.body.title,
"author": req.body.author,
"language": req.body.language,
"license": req.body.license,
"nsfw": req.body.nsfw.value
}
}
};
//console.log(">> publishObject:", publishObject)
// post the task to the que
queueApi.addNewTaskToQueue(JSON.stringify({
type: 'publish',
data: publishObject
}));
// respond to the client that the task has been queued
res.status(200).sendFile(path.join(__dirname, '../public', 'publishingClaim.html'));
});
// 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)");
lbryApi.serveAllClaims(name, res);
});
// route to fetch one free public claim
app.get("/:name/:claim_id", function(req, res){
var uri = "lbry://" + req.params.name + "#" + req.params.claim_id;
console.log(">> GET request on /" + uri);
lbryApi.serveClaimBasedOnUri(uri, 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)
// publish a message to the cue
// queueApi.addNewTaskToQueue("return claim for " + req.params.name + " ...")
// retrieve the claim
lbryApi.serveClaimBasedOnNameOnly(name, res);
});
// route for the home page
app.get("/", function(req, res){
res.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.sendFile(path.join(__dirname, '../public', 'fourOhfour.html'));
});
}

20
server.js Normal file
View file

@ -0,0 +1,20 @@
// load dependencies
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
// set port
var PORT = 80;
// initialize express
var app = express();
// make express look in the public directory for assets (css/js/img)
app.use(express.static(__dirname + '/public'));
// configure epress
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
// require in routes
require("./routes/api-routes.js")(app);
require("./routes/html-routes.js")(app);
// start server
app.listen(PORT, function() {
console.log("Listening on PORT " + PORT);
});

31
worker.js Normal file
View file

@ -0,0 +1,31 @@
// 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});
});
});