commit
2c2ae7a348
24 changed files with 540 additions and 266 deletions
|
@ -195,4 +195,7 @@ module.exports = {
|
||||||
});
|
});
|
||||||
return deferred;
|
return deferred;
|
||||||
},
|
},
|
||||||
|
getAllClaims (claimName) {
|
||||||
|
return getAllFreePublicClaims(claimName);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
const getAllFreePublicClaims = require('../helpers/functions/getAllFreePublicClaims.js');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllClaims (claimName) {
|
|
||||||
return getAllFreePublicClaims(claimName);
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -3,16 +3,19 @@ const { postToStats } = require('../../controllers/statsController.js');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
handleRequestError (action, originalUrl, ip, error, res) {
|
handleRequestError (action, originalUrl, ip, error, res) {
|
||||||
logger.error('Request Error >>', error.message);
|
logger.error('Request Error >>', error);
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
postToStats(action, originalUrl, ip, error.response.data.error.messsage);
|
postToStats(action, originalUrl, ip, error.response.data.error.messsage);
|
||||||
res.status(error.response.status).send(error.response.data.error.message);
|
res.status(error.response.status).send(error.response.data.error.message);
|
||||||
} else if (error.code === 'ECONNREFUSED') {
|
} else if (error.code === 'ECONNREFUSED') {
|
||||||
postToStats(action, originalUrl, ip, 'Connection refused. The daemon may not be running.');
|
postToStats(action, originalUrl, ip, 'Connection refused. The daemon may not be running.');
|
||||||
res.status(503).send('Connection refused. The daemon may not be running.');
|
res.status(503).send('Connection refused. The daemon may not be running.');
|
||||||
} else {
|
} else if (error.message) {
|
||||||
postToStats(action, originalUrl, ip, error);
|
postToStats(action, originalUrl, ip, error);
|
||||||
res.status(400).send(error.message);
|
res.status(400).send(error.message);
|
||||||
|
} else {
|
||||||
|
postToStats(action, originalUrl, ip, error);
|
||||||
|
res.status(400).send(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handlePublishError (error) {
|
handlePublishError (error) {
|
||||||
|
|
|
@ -14,19 +14,17 @@
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
float: left;
|
float: left;
|
||||||
width: 75%;
|
width: 65%;
|
||||||
margin-right: 1%;
|
|
||||||
padding-right: 1%;
|
|
||||||
border-right: 1px lightgrey solid;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
float: left;
|
float: right;
|
||||||
width: 22%;
|
width: 33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
|
@ -43,7 +41,6 @@ footer {
|
||||||
.panel {
|
.panel {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-left, .col-right {
|
.col-left, .col-right {
|
||||||
|
@ -64,7 +61,8 @@ footer {
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
|
|
||||||
a {
|
a, a:visited {
|
||||||
|
color: blue;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -73,11 +71,16 @@ h1 {
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
|
margin-top: 1em;
|
||||||
border-top: 1px #999 solid;
|
border-top: 1px #999 solid;
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subheader {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +108,10 @@ table {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrap-words {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1250px) {
|
@media (max-width: 1250px) {
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
|
@ -12,12 +12,53 @@
|
||||||
margin: 2px 5px 2px 5px;
|
margin: 2px 5px 2px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* show routes */
|
||||||
|
.show-asset {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-asset-lite {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel.links {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.link {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.copy-button {
|
||||||
|
padding: 4px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-table {
|
||||||
|
font-size: small;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata-row {
|
||||||
|
border-bottom: 1px solid lightgrey;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-column {
|
||||||
|
width: 30%;
|
||||||
|
font-weight: bold;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
/* learn more */
|
/* learn more */
|
||||||
.learn-more {
|
.learn-more {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
border-top: 1px lightgrey solid;
|
border-top: 1px solid lightgrey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* examples */
|
/* examples */
|
||||||
|
@ -30,16 +71,17 @@
|
||||||
|
|
||||||
.example-image, .example-code {
|
.example-image, .example-code {
|
||||||
float: left;
|
float: left;
|
||||||
margin: 5px 15px 5px 0px;
|
margin: 2%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example-image {
|
.example-image {
|
||||||
width: 20%;
|
width: 21%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example-code {
|
.example-code {
|
||||||
padding: 2em;
|
float: right;
|
||||||
width: 60%;
|
padding: 4%;
|
||||||
|
width: 62%;
|
||||||
background-color: lightgrey;
|
background-color: lightgrey;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: #666;
|
color: #666;
|
||||||
|
@ -82,6 +124,7 @@
|
||||||
|
|
||||||
#image-preview {
|
#image-preview {
|
||||||
display: none;
|
display: none;
|
||||||
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* meme */
|
/* meme */
|
||||||
|
@ -115,6 +158,10 @@ canvas {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.show-asset-lite {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 475px) {
|
@media (max-width: 475px) {
|
||||||
|
|
|
@ -3,81 +3,6 @@ var socket = io();
|
||||||
var uploader = new SocketIOFileUpload(socket);
|
var uploader = new SocketIOFileUpload(socket);
|
||||||
var stagedFiles = null;
|
var stagedFiles = null;
|
||||||
|
|
||||||
/* helper functions */
|
|
||||||
// create a progress animation
|
|
||||||
function createProgressBar(element, size){
|
|
||||||
var x = 1;
|
|
||||||
var adder = 1;
|
|
||||||
function addOne(){
|
|
||||||
var bars = '<p>|';
|
|
||||||
for (var i = 0; i < x; i++){ bars += ' | '; }
|
|
||||||
bars += '</p>';
|
|
||||||
element.innerHTML = bars;
|
|
||||||
if (x === size){
|
|
||||||
adder = -1;
|
|
||||||
} else if ( x === 0){
|
|
||||||
adder = 1;
|
|
||||||
}
|
|
||||||
x += adder;
|
|
||||||
};
|
|
||||||
setInterval(addOne, 300);
|
|
||||||
}
|
|
||||||
// preview file and stage the image for upload
|
|
||||||
function previewAndStageFile(selectedFile){
|
|
||||||
var preview = document.getElementById('image-preview');
|
|
||||||
var dropzone = document.getElementById('drop-zone');
|
|
||||||
var previewReader = new FileReader();
|
|
||||||
var nameInput = document.getElementById('publish-name');
|
|
||||||
|
|
||||||
preview.style.display = 'block';
|
|
||||||
dropzone.style.display = 'none';
|
|
||||||
|
|
||||||
previewReader.onloadend = function () {
|
|
||||||
preview.src = previewReader.result;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (selectedFile) {
|
|
||||||
previewReader.readAsDataURL(selectedFile); // reads the data and sets the img src
|
|
||||||
if (nameInput.value === "") {
|
|
||||||
nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.'));
|
|
||||||
}
|
|
||||||
stagedFiles = [selectedFile]; // stores the selected file for upload
|
|
||||||
} else {
|
|
||||||
preview.src = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update the publish status
|
|
||||||
function updatePublishStatus(msg){
|
|
||||||
document.getElementById('publish-status').innerHTML = msg;
|
|
||||||
}
|
|
||||||
// process the drop-zone drop
|
|
||||||
function drop_handler(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
// if dropped items aren't files, reject them
|
|
||||||
var dt = ev.dataTransfer;
|
|
||||||
if (dt.items) {
|
|
||||||
if (dt.items[0].kind == 'file') {
|
|
||||||
var droppedFile = dt.items[0].getAsFile();
|
|
||||||
previewAndStageFile(droppedFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// prevent the browser's default drag behavior
|
|
||||||
function dragover_handler(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
}
|
|
||||||
// remove all of the drag data
|
|
||||||
function dragend_handler(ev) {
|
|
||||||
var dt = ev.dataTransfer;
|
|
||||||
if (dt.items) {
|
|
||||||
for (var i = 0; i < dt.items.length; i++) {
|
|
||||||
dt.items.remove(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ev.dataTransfer.clearData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* configure the submit button */
|
/* configure the submit button */
|
||||||
document.getElementById('publish-submit').addEventListener('click', function(event){
|
document.getElementById('publish-submit').addEventListener('click', function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -132,6 +57,12 @@ document.getElementById('publish-submit').addEventListener('click', function(eve
|
||||||
})
|
})
|
||||||
|
|
||||||
/* socketio-file-upload listeners */
|
/* socketio-file-upload listeners */
|
||||||
|
uploader.maxFileSize = 5000000;
|
||||||
|
uploader.addEventListener("error", function(data){
|
||||||
|
if (data.code === 1) {
|
||||||
|
alert("Sorry, uploading is limitted to 5 megabytes.");
|
||||||
|
}
|
||||||
|
});
|
||||||
uploader.addEventListener('start', function(event){
|
uploader.addEventListener('start', function(event){
|
||||||
var name = document.getElementById('publish-name').value;
|
var name = document.getElementById('publish-name').value;
|
||||||
var license = document.getElementById('publish-license').value;
|
var license = document.getElementById('publish-license').value;
|
||||||
|
@ -161,33 +92,16 @@ socket.on('publish-status', function(msg){
|
||||||
updatePublishStatus(msg);
|
updatePublishStatus(msg);
|
||||||
});
|
});
|
||||||
socket.on('publish-failure', function(msg){
|
socket.on('publish-failure', function(msg){
|
||||||
document.getElementById('publish-active-area').innerHTML = '<p>' + JSON.stringify(msg) + '</p><p> --(✖╭╮✖)→ </p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
document.getElementById('publish-active-area').innerHTML = '<p> --(✖╭╮✖)→ </p><p>' + JSON.stringify(msg) + '</p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('publish-complete', function(msg){
|
socket.on('publish-complete', function(msg){
|
||||||
var publishResults;
|
var publishResults;
|
||||||
var directUrl = '/' + msg.name + '/' + msg.result.claim_id;
|
var showUrl = '/show/' + msg.name + '/' + msg.result.claim_id;
|
||||||
// build new publish area
|
// build new publish area
|
||||||
publishResults = '<p>Your publish is complete! View it here:</p>';
|
publishResults = '<p>Your publish is complete! You are being redirected to it now.</p>';
|
||||||
publishResults += '<p><a target="_blank" href="' + directUrl + '">spee.ch' + directUrl + '</a></p>';
|
publishResults += '<p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>';
|
||||||
publishResults += '<p><button class="copy-button">Copy to clipboard</button></p>';
|
|
||||||
publishResults += '<p><a target="_blank" href="https://explorer.lbry.io/#!/transaction/' + msg.result.txid + '">View the transaction details</a></p>';
|
|
||||||
publishResults += '<a href="/"><button>Reload</button></a></p>';
|
|
||||||
// update publish area
|
// update publish area
|
||||||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||||
// update the link holder
|
window.location.href = showUrl;
|
||||||
document.getElementById('direct-link-holder').innerText = 'https://spee.ch' + directUrl;
|
|
||||||
// enable copy-to-clipboard
|
|
||||||
var copyBtn = document.querySelector('.copy-button');
|
|
||||||
copyBtn.addEventListener('click', function(event) {
|
|
||||||
// select the text
|
|
||||||
var text = document.getElementById('direct-link-holder');
|
|
||||||
text.select();
|
|
||||||
try {
|
|
||||||
var successful = document.execCommand('copy');
|
|
||||||
var msg = successful ? 'successful' : 'unsuccessful';
|
|
||||||
} catch (err) {
|
|
||||||
alert('Oops, unable to copy');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
|
@ -15,4 +15,43 @@ function toggleSection(event){
|
||||||
masterElement.innerText = "[open]";
|
masterElement.innerText = "[open]";
|
||||||
masterElement.dataset.open = "false";
|
masterElement.dataset.open = "false";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a progress animation
|
||||||
|
function createProgressBar(element, size){
|
||||||
|
var x = 1;
|
||||||
|
var adder = 1;
|
||||||
|
function addOne(){
|
||||||
|
var bars = '<p>|';
|
||||||
|
for (var i = 0; i < x; i++){ bars += ' | '; }
|
||||||
|
bars += '</p>';
|
||||||
|
element.innerHTML = bars;
|
||||||
|
if (x === size){
|
||||||
|
adder = -1;
|
||||||
|
} else if ( x === 0){
|
||||||
|
adder = 1;
|
||||||
|
}
|
||||||
|
x += adder;
|
||||||
|
};
|
||||||
|
setInterval(addOne, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dataURItoBlob(dataURI) {
|
||||||
|
// convert base64/URLEncoded data component to raw binary data held in a string
|
||||||
|
var byteString;
|
||||||
|
if (dataURI.split(',')[0].indexOf('base64') >= 0)
|
||||||
|
byteString = atob(dataURI.split(',')[1]);
|
||||||
|
else
|
||||||
|
byteString = unescape(dataURI.split(',')[1]);
|
||||||
|
|
||||||
|
// separate out the mime component
|
||||||
|
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||||
|
|
||||||
|
// write the bytes of the string to a typed array
|
||||||
|
var ia = new Uint8Array(byteString.length);
|
||||||
|
for (var i = 0; i < byteString.length; i++) {
|
||||||
|
ia[i] = byteString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Blob([ia], {type:mimeString});
|
||||||
}
|
}
|
|
@ -7,97 +7,6 @@ var license = 'Creative Commons';
|
||||||
var nsfw = false;
|
var nsfw = false;
|
||||||
var nameInput = document.getElementById("publish-name");
|
var nameInput = document.getElementById("publish-name");
|
||||||
|
|
||||||
function dataURItoBlob(dataURI) {
|
|
||||||
// convert base64/URLEncoded data component to raw binary data held in a string
|
|
||||||
var byteString;
|
|
||||||
if (dataURI.split(',')[0].indexOf('base64') >= 0)
|
|
||||||
byteString = atob(dataURI.split(',')[1]);
|
|
||||||
else
|
|
||||||
byteString = unescape(dataURI.split(',')[1]);
|
|
||||||
|
|
||||||
// separate out the mime component
|
|
||||||
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
|
||||||
|
|
||||||
// write the bytes of the string to a typed array
|
|
||||||
var ia = new Uint8Array(byteString.length);
|
|
||||||
for (var i = 0; i < byteString.length; i++) {
|
|
||||||
ia[i] = byteString.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Blob([ia], {type:mimeString});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startPublish() {
|
|
||||||
//download the image
|
|
||||||
var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js
|
|
||||||
var blob = dataURItoBlob(dataUrl)
|
|
||||||
var fileName = nameInput.value + ".jpg"; //note: need to dynamically grab type
|
|
||||||
var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()});
|
|
||||||
stageAndPublish(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* helper functions */
|
|
||||||
// create a progress animation
|
|
||||||
function createProgressBar(element, size){
|
|
||||||
var x = 1;
|
|
||||||
var adder = 1;
|
|
||||||
function addOne(){
|
|
||||||
var bars = '<p>|';
|
|
||||||
for (var i = 0; i < x; i++){ bars += ' | '; }
|
|
||||||
bars += '</p>';
|
|
||||||
element.innerHTML = bars;
|
|
||||||
if (x === size){
|
|
||||||
adder = -1;
|
|
||||||
} else if ( x === 0){
|
|
||||||
adder = 1;
|
|
||||||
}
|
|
||||||
x += adder;
|
|
||||||
};
|
|
||||||
setInterval(addOne, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stageAndPublish(file) {
|
|
||||||
var name = nameInput.value;
|
|
||||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
|
||||||
// validate 'name'
|
|
||||||
if (invalidCharacters) {
|
|
||||||
alert(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
|
||||||
return;
|
|
||||||
} else if (name.length < 1) {
|
|
||||||
alert("You must enter a name for your claim");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// stage files
|
|
||||||
stagedFiles = [file]; // stores the selected file for
|
|
||||||
// make sure a file was selected
|
|
||||||
if (stagedFiles) {
|
|
||||||
// make sure only 1 file was selected
|
|
||||||
if (stagedFiles.length < 1) {
|
|
||||||
alert("A file is needed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// make sure the content type is acceptable
|
|
||||||
switch (stagedFiles[0].type) {
|
|
||||||
case "image/png":
|
|
||||||
case "image/jpeg":
|
|
||||||
case "image/gif":
|
|
||||||
case "video/mp4":
|
|
||||||
uploader.submitFiles(stagedFiles);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
alert("Only .png, .jpeg, .gif, and .mp4 files are currently supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert("Please select a file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the publish status
|
|
||||||
function updatePublishStatus(msg){
|
|
||||||
document.getElementById('publish-status').innerHTML = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* socketio-file-upload listeners */
|
/* socketio-file-upload listeners */
|
||||||
uploader.addEventListener('start', function(event){
|
uploader.addEventListener('start', function(event){
|
||||||
event.file.meta.name = nameInput.value;
|
event.file.meta.name = nameInput.value;
|
||||||
|
|
107
public/assets/js/publishFunctions.js
Normal file
107
public/assets/js/publishFunctions.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
// update the publish status
|
||||||
|
function updatePublishStatus(msg){
|
||||||
|
document.getElementById('publish-status').innerHTML = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* regular publish helper functions */
|
||||||
|
|
||||||
|
function previewAndStageFile(selectedFile){
|
||||||
|
var preview = document.getElementById('image-preview');
|
||||||
|
var dropzone = document.getElementById('drop-zone');
|
||||||
|
var previewReader = new FileReader();
|
||||||
|
var nameInput = document.getElementById('publish-name');
|
||||||
|
|
||||||
|
preview.style.display = 'block';
|
||||||
|
dropzone.style.display = 'none';
|
||||||
|
|
||||||
|
previewReader.onloadend = function () {
|
||||||
|
preview.src = previewReader.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedFile) {
|
||||||
|
previewReader.readAsDataURL(selectedFile); // reads the data and sets the img src
|
||||||
|
if (nameInput.value === "") {
|
||||||
|
nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.'));
|
||||||
|
}
|
||||||
|
stagedFiles = [selectedFile]; // stores the selected file for upload
|
||||||
|
} else {
|
||||||
|
preview.src = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* drop zone function s*/
|
||||||
|
|
||||||
|
function drop_handler(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
// if dropped items aren't files, reject them
|
||||||
|
var dt = ev.dataTransfer;
|
||||||
|
if (dt.items) {
|
||||||
|
if (dt.items[0].kind == 'file') {
|
||||||
|
var droppedFile = dt.items[0].getAsFile();
|
||||||
|
previewAndStageFile(droppedFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragover_handler(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragend_handler(ev) {
|
||||||
|
var dt = ev.dataTransfer;
|
||||||
|
if (dt.items) {
|
||||||
|
for (var i = 0; i < dt.items.length; i++) {
|
||||||
|
dt.items.remove(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ev.dataTransfer.clearData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* meme publish functions */
|
||||||
|
|
||||||
|
function startPublish() {
|
||||||
|
//download the image
|
||||||
|
var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js
|
||||||
|
var blob = dataURItoBlob(dataUrl)
|
||||||
|
var fileName = nameInput.value + ".jpg"; //note: need to dynamically grab type
|
||||||
|
var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()});
|
||||||
|
stageAndPublish(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
function stageAndPublish(file) {
|
||||||
|
var name = nameInput.value;
|
||||||
|
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||||
|
// validate 'name'
|
||||||
|
if (invalidCharacters) {
|
||||||
|
alert(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
||||||
|
return;
|
||||||
|
} else if (name.length < 1) {
|
||||||
|
alert("You must enter a name for your claim");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// stage files
|
||||||
|
stagedFiles = [file]; // stores the selected file for
|
||||||
|
// make sure a file was selected
|
||||||
|
if (stagedFiles) {
|
||||||
|
// make sure only 1 file was selected
|
||||||
|
if (stagedFiles.length < 1) {
|
||||||
|
alert("A file is needed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// make sure the content type is acceptable
|
||||||
|
switch (stagedFiles[0].type) {
|
||||||
|
case "image/png":
|
||||||
|
case "image/jpeg":
|
||||||
|
case "image/gif":
|
||||||
|
case "video/mp4":
|
||||||
|
uploader.submitFiles(stagedFiles);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
alert("Only .png, .jpeg, .gif, and .mp4 files are currently supported");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Please select a file");
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,9 @@ const { postToStats, sendGoogleAnalytics } = require('../controllers/statsContro
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
// route to run a claim_list request on the daemon
|
// route to run a claim_list request on the daemon
|
||||||
app.get('/api/claim_list/:name', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/claim_list/:name', ({ headers, ip, originalUrl, params }, res) => {
|
||||||
// google analytics
|
// google analytics
|
||||||
sendGoogleAnalytics('serve', ip, originalUrl);
|
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
||||||
// log
|
|
||||||
logger.verbose(`GET request on ${originalUrl} from ${ip}`);
|
|
||||||
// serve the content
|
// serve the content
|
||||||
lbryApi
|
lbryApi
|
||||||
.getClaimsList(params.name)
|
.getClaimsList(params.name)
|
||||||
|
@ -27,8 +25,6 @@ module.exports = app => {
|
||||||
});
|
});
|
||||||
// route to check whether spee.ch has published to a claim
|
// route to check whether spee.ch has published to a claim
|
||||||
app.get('/api/isClaimAvailable/:name', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/isClaimAvailable/:name', ({ ip, originalUrl, params }, res) => {
|
||||||
// log
|
|
||||||
logger.verbose(`GET request on ${originalUrl} from ${ip}`);
|
|
||||||
// send response
|
// send response
|
||||||
publishController
|
publishController
|
||||||
.checkNameAvailability(params.name)
|
.checkNameAvailability(params.name)
|
||||||
|
@ -45,11 +41,9 @@ module.exports = app => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to run a resolve request on the daemon
|
// route to run a resolve request on the daemon
|
||||||
app.get('/api/resolve/:uri', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/resolve/:uri', ({ headers, ip, originalUrl, params }, res) => {
|
||||||
// google analytics
|
// google analytics
|
||||||
sendGoogleAnalytics('serve', ip, originalUrl);
|
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
||||||
// log
|
|
||||||
logger.verbose(`GET request on ${originalUrl} from ${ip}`);
|
|
||||||
// serve content
|
// serve content
|
||||||
lbryApi
|
lbryApi
|
||||||
.resolveUri(params.uri)
|
.resolveUri(params.uri)
|
||||||
|
@ -62,18 +56,22 @@ module.exports = app => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to run a publish request on the daemon
|
// route to run a publish request on the daemon
|
||||||
app.post('/api/publish', multipartMiddleware, ({ body, files, ip, originalUrl }, res) => {
|
app.post('/api/publish', multipartMiddleware, ({ body, files, headers, ip, originalUrl }, res) => {
|
||||||
// google analytics
|
// google analytics
|
||||||
sendGoogleAnalytics('publish', ip, originalUrl);
|
sendGoogleAnalytics('publish', headers, ip, originalUrl);
|
||||||
// log
|
|
||||||
logger.verbose(`POST request on ${originalUrl} from ${ip}`);
|
|
||||||
// validate that a file was provided
|
// validate that a file was provided
|
||||||
const file = files.speech || files.null;
|
const file = files.speech || files.null;
|
||||||
|
logger.debug(file);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
postToStats('publish', originalUrl, ip, 'Error: file');
|
postToStats('publish', originalUrl, ip, 'Error: file');
|
||||||
res.status(400).send('Error: No file was submitted or the key used was incorrect. Files posted through this route must use a key of "speech" or null');
|
res.status(400).send('Error: No file was submitted or the key used was incorrect. Files posted through this route must use a key of "speech" or null');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// check if the size is 5 mb or less
|
||||||
|
if (file.size > 5000000) {
|
||||||
|
res.status(400).send('Error: only files of 5 megabytes or less are allowed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
// validate name
|
// validate name
|
||||||
const name = body.name || file.name.substring(0, file.name.indexOf('.'));
|
const name = body.name || file.name.substring(0, file.name.indexOf('.'));
|
||||||
const invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
const invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||||
|
|
|
@ -4,15 +4,12 @@ const { postToStats } = require('../controllers/statsController.js');
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
// route for the home page
|
// route for the home page
|
||||||
app.get('/', ({ headers, ip, originalUrl }, res) => {
|
app.get('/', ({ headers, ip, originalUrl }, res) => {
|
||||||
// logging
|
|
||||||
logger.verbose(`GET request on ${originalUrl} from ${ip}`);
|
|
||||||
// send response
|
// send response
|
||||||
res.status(200).render('index');
|
res.status(200).render('index');
|
||||||
});
|
});
|
||||||
// a catch-all route if someone visits a page that does not exist
|
// a catch-all route if someone visits a page that does not exist
|
||||||
app.use('*', ({ originalUrl, ip }, res) => {
|
app.use('*', ({ originalUrl, ip }, res) => {
|
||||||
// logging
|
logger.error(`404 on ${originalUrl}`);
|
||||||
logger.error(`Get request on ${originalUrl} from ${ip} which was a 404`);
|
|
||||||
// post to stats
|
// post to stats
|
||||||
postToStats('show', originalUrl, ip, 'Error: 404');
|
postToStats('show', originalUrl, ip, 'Error: 404');
|
||||||
// send response
|
// send response
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
|
||||||
const serveController = require('../controllers/serveController.js');
|
|
||||||
const logger = require('winston');
|
const logger = require('winston');
|
||||||
|
const { getClaimByClaimId, getClaimByName } = require('../controllers/serveController.js');
|
||||||
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
||||||
|
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
||||||
|
|
||||||
function serveFile ({ fileName, fileType, filePath }, res) {
|
function serveFile ({ fileName, fileType, filePath }, res) {
|
||||||
logger.info(`serving file ${fileName}`);
|
logger.info(`serving file ${fileName}`);
|
||||||
// set default options
|
// set default options
|
||||||
const options = {
|
let options = {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Content-Type-Options': 'nosniff',
|
'X-Content-Type-Options': 'nosniff',
|
||||||
'Content-Type' : fileType,
|
'Content-Type' : fileType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// adjust default options as needed
|
// adjust default options as needed
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
switch (fileType) {
|
switch (fileType) {
|
||||||
case 'image/jpeg':
|
case 'image/jpeg':
|
||||||
break;
|
break;
|
||||||
|
@ -24,7 +23,7 @@ function serveFile ({ fileName, fileType, filePath }, res) {
|
||||||
case 'video/mp4':
|
case 'video/mp4':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn('sending unknown file type as .jpeg');
|
logger.warn('sending file with unknown type as .jpeg');
|
||||||
options['headers']['Content-Type'] = 'image/jpeg';
|
options['headers']['Content-Type'] = 'image/jpeg';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -35,44 +34,54 @@ function serveFile ({ fileName, fileType, filePath }, res) {
|
||||||
function sendAnalyticsAndLog (headers, ip, originalUrl) {
|
function sendAnalyticsAndLog (headers, ip, originalUrl) {
|
||||||
// google analytics
|
// google analytics
|
||||||
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
||||||
// logging
|
|
||||||
logger.verbose(`GET request on ${originalUrl} from ${ip}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
// route to fetch one free public claim
|
// route to serve a specific asset
|
||||||
app.get('/:name/:claim_id', ({ headers, ip, originalUrl, params }, res) => {
|
app.get('/:name/:claim_id', ({ headers, ip, originalUrl, params }, res) => {
|
||||||
sendAnalyticsAndLog(headers, ip, originalUrl);
|
sendAnalyticsAndLog(headers, ip, originalUrl);
|
||||||
// begin image-serve processes
|
// begin image-serve processes
|
||||||
serveController
|
getClaimByClaimId(params.name, params.claim_id)
|
||||||
.getClaimByClaimId(params.name, params.claim_id)
|
|
||||||
.then(fileInfo => {
|
.then(fileInfo => {
|
||||||
// check to make sure a file was found
|
// check to make sure a file was found
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
res.status(307).render('noClaims');
|
res.status(307).render('noClaims');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
postToStats('serve', originalUrl, ip, 'success');
|
// serve the file or the show route
|
||||||
serveFile(fileInfo, res);
|
const mimetypes = headers['accept'].split(',');
|
||||||
|
if (mimetypes.includes('text/html')) {
|
||||||
|
postToStats('show', originalUrl, ip, 'success');
|
||||||
|
res.status(200).render('showLite', { fileInfo });
|
||||||
|
} else {
|
||||||
|
postToStats('serve', originalUrl, ip, 'success');
|
||||||
|
serveFile(fileInfo, res);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to fetch one free public claim
|
// route to serve the winning claim
|
||||||
app.get('/:name', ({ headers, ip, originalUrl, params }, res) => {
|
app.get('/:name', ({ headers, ip, originalUrl, params }, res) => {
|
||||||
sendAnalyticsAndLog(headers, ip, originalUrl);
|
sendAnalyticsAndLog(headers, ip, originalUrl);
|
||||||
// begin image-serve processes
|
// begin image-serve processes
|
||||||
serveController
|
getClaimByName(params.name)
|
||||||
.getClaimByName(params.name)
|
|
||||||
.then(fileInfo => {
|
.then(fileInfo => {
|
||||||
// check to make sure a file was found
|
// check to make sure a file was found
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
res.status(307).render('noClaims');
|
res.status(307).render('noClaims');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
postToStats('serve', originalUrl, ip, 'success');
|
// serve the file or the show route
|
||||||
serveFile(fileInfo, res);
|
const mimetypes = headers['accept'].split(',');
|
||||||
|
if (mimetypes.includes('text/html')) {
|
||||||
|
postToStats('show', originalUrl, ip, 'success');
|
||||||
|
res.status(200).render('showLite', { fileInfo });
|
||||||
|
} else {
|
||||||
|
postToStats('serve', originalUrl, ip, 'success');
|
||||||
|
serveFile(fileInfo, res);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
const logger = require('winston');
|
|
||||||
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
||||||
const { getAllClaims } = require('../controllers/showController.js');
|
const { getClaimByClaimId, getClaimByName, getAllClaims } = require('../controllers/serveController.js');
|
||||||
const { getStatsSummary, postToStats } = require('../controllers/statsController.js');
|
const { getStatsSummary, postToStats } = require('../controllers/statsController.js');
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
// route to show 'about' page for spee.ch
|
// route to show 'about' page for spee.ch
|
||||||
app.get('/about', ({ ip, originalUrl }, res) => {
|
app.get('/about', ({ ip, originalUrl }, res) => {
|
||||||
logger.verbose(`POST request on ${originalUrl} from ${ip}`);
|
|
||||||
// get and render the content
|
// get and render the content
|
||||||
res.status(200).render('about');
|
res.status(200).render('about');
|
||||||
});
|
});
|
||||||
// route to show the meme-fodder meme maker
|
// route to show the meme-fodder meme maker
|
||||||
app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => {
|
app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => {
|
||||||
logger.verbose(`POST request on ${originalUrl} from ${ip}`);
|
|
||||||
// get and render the content
|
// get and render the content
|
||||||
getAllClaims('meme-fodder')
|
getAllClaims('meme-fodder')
|
||||||
.then(orderedFreePublicClaims => {
|
.then(orderedFreePublicClaims => {
|
||||||
|
@ -25,7 +22,6 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
// route to show statistics for spee.ch
|
// route to show statistics for spee.ch
|
||||||
app.get('/stats', ({ ip, originalUrl }, res) => {
|
app.get('/stats', ({ ip, originalUrl }, res) => {
|
||||||
logger.verbose(`POST request on ${originalUrl} from ${ip}`);
|
|
||||||
// get and render the content
|
// get and render the content
|
||||||
getStatsSummary()
|
getStatsSummary()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
|
@ -38,7 +34,6 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
// route to display all free public claims at a given name
|
// route to display all free public claims at a given name
|
||||||
app.get('/:name/all', ({ ip, originalUrl, params }, res) => {
|
app.get('/:name/all', ({ ip, originalUrl, params }, res) => {
|
||||||
logger.verbose(`POST request on ${originalUrl} from ${ip}`);
|
|
||||||
// get and render the content
|
// get and render the content
|
||||||
getAllClaims(params.name)
|
getAllClaims(params.name)
|
||||||
.then(orderedFreePublicClaims => {
|
.then(orderedFreePublicClaims => {
|
||||||
|
@ -53,4 +48,40 @@ module.exports = (app) => {
|
||||||
errorHandlers.handleRequestError('show', originalUrl, ip, error, res);
|
errorHandlers.handleRequestError('show', originalUrl, ip, error, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// route to show a specific asset
|
||||||
|
app.get('/show/:name/:claim_id', ({ ip, originalUrl, params }, res) => {
|
||||||
|
// begin image-serve processes
|
||||||
|
getClaimByClaimId(params.name, params.claim_id)
|
||||||
|
.then(fileInfo => {
|
||||||
|
// check to make sure a file was found
|
||||||
|
if (!fileInfo) {
|
||||||
|
res.status(307).render('noClaims');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// serve the file or the show route
|
||||||
|
postToStats('show', originalUrl, ip, 'success');
|
||||||
|
res.status(200).render('show', { fileInfo });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// route to show the winning free, public claim
|
||||||
|
app.get('/show/:name', ({ ip, originalUrl, params }, res) => {
|
||||||
|
// get and render the content
|
||||||
|
getClaimByName(params.name)
|
||||||
|
.then(fileInfo => {
|
||||||
|
// check to make sure a file was found
|
||||||
|
if (!fileInfo) {
|
||||||
|
res.status(307).render('noClaims');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// serve the show route
|
||||||
|
postToStats('show', originalUrl, ip, 'success');
|
||||||
|
res.status(200).render('show', { fileInfo });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
const logger = require('winston');
|
const logger = require('winston');
|
||||||
|
const fs = require('fs');
|
||||||
const publishController = require('../controllers/publishController.js');
|
const publishController = require('../controllers/publishController.js');
|
||||||
const publishHelpers = require('../helpers/libraries/publishHelpers.js');
|
const publishHelpers = require('../helpers/libraries/publishHelpers.js');
|
||||||
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
||||||
const { postToStats } = require('../controllers/statsController.js');
|
const { postToStats } = require('../controllers/statsController.js');
|
||||||
|
|
||||||
module.exports = (app, siofu, hostedContentPath) => {
|
module.exports = (app, siofu, hostedContentPath) => {
|
||||||
const http = require('http').Server(app);
|
const http = require('http');
|
||||||
const io = require('socket.io')(http);
|
const server = http.Server(app);
|
||||||
|
const io = require('socket.io')(server);
|
||||||
|
|
||||||
io.on('connection', socket => {
|
io.on('connection', socket => {
|
||||||
logger.silly('a user connected via sockets');
|
logger.silly('a user connected via sockets');
|
||||||
|
@ -55,11 +57,47 @@ module.exports = (app, siofu, hostedContentPath) => {
|
||||||
// to-do: remove the file if not done automatically
|
// to-do: remove the file if not done automatically
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// handle asset requests
|
||||||
|
socket.on('asset-request', filePath => {
|
||||||
|
logger.debug('received a request for the following file', filePath);
|
||||||
|
fs.readFile(filePath, (err, assetBuffer) => {
|
||||||
|
if (err) {
|
||||||
|
logger.error('fs.readFile error', err);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
// set the data
|
||||||
|
const fileExtension = filePath.substring(filePath.lastIndexOf('.'));
|
||||||
|
let data = {
|
||||||
|
type : null,
|
||||||
|
buffer: assetBuffer.toString('base64'),
|
||||||
|
};
|
||||||
|
switch (fileExtension) {
|
||||||
|
case '.jpeg' || '.jpg':
|
||||||
|
data['type'] = 'image/jpeg';
|
||||||
|
break;
|
||||||
|
case '.gif':
|
||||||
|
data['type'] = 'image/gif';
|
||||||
|
break;
|
||||||
|
case '.png':
|
||||||
|
data['type'] = 'image/png';
|
||||||
|
break;
|
||||||
|
case '.mp4':
|
||||||
|
data['type'] = 'video/mp4';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
data['type'] = 'image/jpeg';
|
||||||
|
logger.warn('showing file with unknown type as jpeg');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// send the asset
|
||||||
|
socket.emit('asset-transfer', data);
|
||||||
|
});
|
||||||
|
});
|
||||||
// handle disconnect
|
// handle disconnect
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
logger.silly('a user disconnected via sockets');
|
logger.silly('a user disconnected via sockets');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return http;
|
return server;
|
||||||
};
|
};
|
||||||
|
|
30
server.js
30
server.js
|
@ -29,6 +29,10 @@ app.enable('trust proxy'); // trust the proxy to get ip address for us
|
||||||
app.use(bodyParser.json()); // for parsing application/json
|
app.use(bodyParser.json()); // for parsing application/json
|
||||||
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
|
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
|
||||||
app.use(siofu.router);
|
app.use(siofu.router);
|
||||||
|
app.use((req, res, next) => { // logging middleware
|
||||||
|
winston.verbose(`Request on ${req.originalUrl} from ${req.ip}`);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
// configure handlebars & register it with Express app
|
// configure handlebars & register it with Express app
|
||||||
const hbs = expressHandlebars.create({
|
const hbs = expressHandlebars.create({
|
||||||
|
@ -49,6 +53,28 @@ const hbs = expressHandlebars.create({
|
||||||
</script>`
|
</script>`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
ifConditional (varOne, operator, varTwo, options) {
|
||||||
|
switch (operator) {
|
||||||
|
case '===':
|
||||||
|
return (varOne === varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '!==':
|
||||||
|
return (varOne !== varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '<':
|
||||||
|
return (varOne < varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '<=':
|
||||||
|
return (varOne <= varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '>':
|
||||||
|
return (varOne > varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '>=':
|
||||||
|
return (varOne >= varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '&&':
|
||||||
|
return (varOne && varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '||':
|
||||||
|
return (varOne || varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
default:
|
||||||
|
return options.inverse(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
app.engine('handlebars', hbs.engine);
|
app.engine('handlebars', hbs.engine);
|
||||||
|
@ -61,13 +87,13 @@ require('./routes/serve-routes.js')(app);
|
||||||
require('./routes/home-routes.js')(app);
|
require('./routes/home-routes.js')(app);
|
||||||
|
|
||||||
// require socket.io routes
|
// require socket.io routes
|
||||||
const http = require('./routes/sockets-routes.js')(app, siofu, hostedContentPath);
|
const server = require('./routes/sockets-routes.js')(app, siofu, hostedContentPath);
|
||||||
|
|
||||||
// sync sequelize
|
// sync sequelize
|
||||||
// wrap the server in socket.io to intercept incoming sockets requests
|
// wrap the server in socket.io to intercept incoming sockets requests
|
||||||
// start server
|
// start server
|
||||||
db.sequelize.sync().then(() => {
|
db.sequelize.sync().then(() => {
|
||||||
http.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
winston.info('Trusting proxy?', app.get('trust proxy'));
|
winston.info('Trusting proxy?', app.get('trust proxy'));
|
||||||
winston.info(`Server is listening on PORT ${PORT}`);
|
winston.info(`Server is listening on PORT ${PORT}`);
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,4 +9,5 @@
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
<script src="/siofu/client.js"></script>
|
<script src="/siofu/client.js"></script>
|
||||||
|
|
||||||
|
<script src="/assets/js/publishFunctions.js"></script>
|
||||||
<script src="/assets/js/claimPublish.js"></script>
|
<script src="/assets/js/claimPublish.js"></script>
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<link rel="stylesheet" href="/assets/css/componentStyle.css" type="text/css">
|
<link rel="stylesheet" href="/assets/css/componentStyle.css" type="text/css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{{ body }}}
|
|
||||||
<script src="/assets/js/generalFunctions.js"></script>
|
<script src="/assets/js/generalFunctions.js"></script>
|
||||||
|
{{{ body }}}
|
||||||
<!-- google analytics -->
|
<!-- google analytics -->
|
||||||
{{ googleAnalytics }}
|
{{ googleAnalytics }}
|
||||||
</body>
|
</body>
|
||||||
|
|
35
views/partials/asset.handlebars
Normal file
35
views/partials/asset.handlebars
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<div class="panel">
|
||||||
|
<div id="asset-placeholder" data-filepath="{{{fileInfo.filePath}}}">
|
||||||
|
<p> loading... </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var socket = io();
|
||||||
|
var filePath = document.getElementById('asset-placeholder').dataset.filepath;
|
||||||
|
if (filePath) {
|
||||||
|
// send request for the file
|
||||||
|
socket.emit('asset-request', filePath);
|
||||||
|
// update the html
|
||||||
|
document.getElementById('asset-placeholder').innerHTML = '<p>Loading...</p><div id="progress-bar"></div>';
|
||||||
|
// start a progress animation
|
||||||
|
createProgressBar(document.getElementById('progress-bar'), 12);
|
||||||
|
}
|
||||||
|
// wait for the file to be sent
|
||||||
|
socket.on('asset-transfer', function(data) {
|
||||||
|
switch (data.type) {
|
||||||
|
case 'image/jpeg':
|
||||||
|
case 'image/gif':
|
||||||
|
case 'image/png':
|
||||||
|
const base64Image = 'data:' + data.type + ';base64,' + data.buffer;
|
||||||
|
document.getElementById("asset-placeholder").innerHTML = '<img class="show-asset" src="' + base64Image + '"/>';
|
||||||
|
break;
|
||||||
|
case 'video/mp4':
|
||||||
|
const base64video = 'data:' + data.type + ';base64,' + data.buffer;
|
||||||
|
document.getElementById("asset-placeholder").innerHTML = '<video class="show-asset" controls> <source src="' + base64video + '"></video>';
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
68
views/partials/assetInfo.handlebars
Normal file
68
views/partials/assetInfo.handlebars
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<div class="panel">
|
||||||
|
<h2>Name</h2>
|
||||||
|
<p>{{fileInfo.name}}</>
|
||||||
|
</div>
|
||||||
|
<div class="panel links">
|
||||||
|
<h2 class="subheader">Links</h2>
|
||||||
|
<a href="/{{fileInfo.name}}/{{fileInfo.claimId}}">Direct Link</a>
|
||||||
|
<input type="text" id="direct-link" class="link" readonly="true" spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
|
||||||
|
<button class="copy-button" data-elementtocopy="direct-link" onclick="copyToClipboard(event)">copy</button>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
Embed HTML
|
||||||
|
<br/>
|
||||||
|
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
|
||||||
|
<input type="text" id="embed-text" class="link" readonly="true" spellcheck="false" value='<video controls><source src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" /></video>'/>
|
||||||
|
{{else}}
|
||||||
|
<input type="text" id="embed-text" class="link" readonly="true" spellcheck="false" value='<img src="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}" />'/>
|
||||||
|
{{/ifConditional}}
|
||||||
|
<button class="copy-button" data-elementtocopy="embed-text" onclick="copyToClipboard(event)">copy</button>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<a href="/show/{{fileInfo.name}}/{{fileInfo.claimId}}">Details</a>
|
||||||
|
</br>
|
||||||
|
<input type="text" id="show-link" class="link" readonly="true" spellcheck="false" value="https://spee.ch/show/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
|
||||||
|
<button class="copy-button" data-elementtocopy="show-link" onclick="copyToClipboard(event)">copy</button>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
<div class="panel">
|
||||||
|
<h2 class="subheader">Metadata</h2>
|
||||||
|
<table class="metadata-table" style="table-layout: fixed">
|
||||||
|
<tr class="metadata-row">
|
||||||
|
<td class="left-column">Name</td>
|
||||||
|
<td>{{fileInfo.name}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="metadata-row">
|
||||||
|
<td class="left-column">Claim Id</td>
|
||||||
|
<td>{{fileInfo.claimId}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="metadata-row">
|
||||||
|
<td class="left-column">File Name</td>
|
||||||
|
<td>{{fileInfo.fileName}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="left-column">fileType</td>
|
||||||
|
<td>{{#if fileInfo.fileType}}
|
||||||
|
{{fileInfo.fileType}}
|
||||||
|
{{else}}
|
||||||
|
unknown
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type ="text/javascript">
|
||||||
|
// update the link holder
|
||||||
|
function copyToClipboard(event){
|
||||||
|
var elementToCopy = event.target.dataset.elementtocopy;
|
||||||
|
var element = document.getElementById(elementToCopy);
|
||||||
|
element.select();
|
||||||
|
try {
|
||||||
|
var successful = document.execCommand('copy');
|
||||||
|
} catch (err) {
|
||||||
|
alert('Oops, unable to copy');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -9,13 +9,23 @@
|
||||||
</ul>
|
</ul>
|
||||||
<code>https://spee.ch/:name</code>
|
<code>https://spee.ch/:name</code>
|
||||||
<ul>
|
<ul>
|
||||||
<li >Serves the newest file with the largest bid at a claim</li>
|
<li >Serves the winning free, public claim at this name</li>
|
||||||
<li >E.g. <a href="/doitlive">spee.ch/doitlive</a></li>
|
<li >E.g. <a href="/doitlive">spee.ch/doitlive</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<code>https://spee.ch/show/:name</code>
|
||||||
|
<ul>
|
||||||
|
<li >Serves the winning claim at this name with additional details</li>
|
||||||
|
<li >E.g. <a href="/show/doitlive">spee.ch/show/doitlive</a></li>
|
||||||
|
</ul>
|
||||||
<code>https://spee.ch/:name/:claim_id</code>
|
<code>https://spee.ch/:name/:claim_id</code>
|
||||||
<ul>
|
<ul>
|
||||||
<li >Serves a specific file at a claim</li>
|
<li >Serves a specific claim</li>
|
||||||
<li >E.g. <a href="/doitlive/c496c8c55ed79816fec39e36a78645aa4458edb5">spee.ch/doitlive/c496c8c55ed79816fec39e36a78645aa4458edb5</a></li>
|
<li >E.g. <a href="/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0">spee.ch/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0</a></li>
|
||||||
|
</ul>
|
||||||
|
<code>https://spee.ch/show/:name/:claim_id</code>
|
||||||
|
<ul>
|
||||||
|
<li >Serves a specific claim with additional details</li>
|
||||||
|
<li >E.g. <a href="/show/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0">spee.ch/show/doitlive/ca3023187e901df9e9aabd95d6ae09b6cc69b3f0</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<code>https://spee.ch/:name/all</code>
|
<code>https://spee.ch/:name/all</code>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -13,9 +13,5 @@
|
||||||
<a href="/doitlive"><img class="example-image" src="/doitlive"/></a>
|
<a href="/doitlive"><img class="example-image" src="/doitlive"/></a>
|
||||||
<div class="example-code"><img src="https://spee.ch/doitlive"/></div>
|
<div class="example-code"><img src="https://spee.ch/doitlive"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="example">
|
|
||||||
<h4>Use spee.ch to view all the assets at a LBRY claim:</h4>
|
|
||||||
<a href="/doitlive/all">spee.ch/doitlive/all</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="learn-more stop-float">
|
<div class="learn-more stop-float">
|
||||||
<p><i>Spee.ch is an open-source project. We would love it if you <a href="https://github.com/lbryio/spee.ch/issues">contributed</a> to the existing site, or <a href="https://github.com/lbryio/spee.ch">forked it</a> and made your own!</i></p>
|
<p><i>Spee.ch is an open-source project. You should <a href="https://github.com/lbryio/spee.ch/issues">contribute</a> on github, or <a href="https://github.com/lbryio/spee.ch">fork it</a> and make your own!</i></p>
|
||||||
<p><a href="/about">Learn more about spee.ch</a></p>
|
<p><a href="/about">Learn more about spee.ch</a></p>
|
||||||
</div>
|
</div>
|
10
views/show.handlebars
Normal file
10
views/show.handlebars
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="wrapper">
|
||||||
|
{{> topBar}}
|
||||||
|
<div class="main">
|
||||||
|
{{> asset}}
|
||||||
|
</div>
|
||||||
|
<div class="sidebar">
|
||||||
|
{{> assetInfo}}
|
||||||
|
</div>
|
||||||
|
{{> footer}}
|
||||||
|
</div>
|
33
views/showLite.handlebars
Normal file
33
views/showLite.handlebars
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<div id="asset-placeholder" data-filepath="{{{fileInfo.filePath}}}">
|
||||||
|
<p> loading... </p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var socket = io();
|
||||||
|
var filePath = document.getElementById('asset-placeholder').dataset.filepath;
|
||||||
|
if (filePath) {
|
||||||
|
// send request for the file
|
||||||
|
socket.emit('asset-request', filePath);
|
||||||
|
// update the html
|
||||||
|
document.getElementById('asset-placeholder').innerHTML = '<p>Loading...</p><div id="progress-bar"></div>';
|
||||||
|
// start a progress animation
|
||||||
|
createProgressBar(document.getElementById('progress-bar'), 12);
|
||||||
|
}
|
||||||
|
// wait for the file to be sent
|
||||||
|
socket.on('asset-transfer', function(data) {
|
||||||
|
switch (data.type) {
|
||||||
|
case 'image/jpeg':
|
||||||
|
case 'image/gif':
|
||||||
|
case 'image/png':
|
||||||
|
const base64Image = 'data:' + data.type + ';base64,' + data.buffer;
|
||||||
|
document.getElementById("asset-placeholder").innerHTML = '<img class="show-asset-lite" src="' + base64Image + '"/>';
|
||||||
|
break;
|
||||||
|
case 'video/mp4':
|
||||||
|
const base64video = 'data:' + data.type + ';base64,' + data.buffer;
|
||||||
|
document.getElementById("asset-placeholder").innerHTML = '<video class="show-asset-lite" controls> <source src="' + base64video + '"></video>';
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Reference in a new issue