broke 'serve' and 'show' functions into separate controller files

This commit is contained in:
bill bittner 2017-07-19 14:11:47 -07:00
parent a6788886fd
commit 2bda35968f
12 changed files with 376 additions and 433 deletions

View file

@ -3,152 +3,10 @@ const db = require('../models');
const logger = require('winston'); const logger = require('winston');
const getAllFreePublicClaims = require('../helpers/functions/getAllFreePublicClaims.js'); const getAllFreePublicClaims = require('../helpers/functions/getAllFreePublicClaims.js');
const isFreePublicClaim = require('../helpers/functions/isFreePublicClaim.js'); const isFreePublicClaim = require('../helpers/functions/isFreePublicClaim.js');
const { getShortUrlByClaimId, getClaimIdByShortUrl } = require('../helpers/libraries/serveHelpers.js'); const serveHelpers = require('../helpers/libraries/serveHelpers.js');
function updateFileIfNeeded (uri, localOutpoint, localHeight) {
logger.debug(`Initiating resolve to check outpoint for ${uri}`);
// 1. resolve claim
lbryApi
.resolveUri(uri)
.then(result => {
// check to make sure the result is a claim
if (!result.claim) {
logger.debug('resolve did not return a claim');
return;
}
// logger.debug('resolved result:', result);
const resolvedOutpoint = `${result.claim.txid}:${result.claim.nout}`;
const resolvedHeight = result.claim.height;
const resolvedAddress = result.claim.address;
logger.debug('database outpoint:', localOutpoint);
logger.debug('resolved outpoint:', resolvedOutpoint);
// 2. if the outpoint's match, no further work needed
if (localOutpoint === resolvedOutpoint) {
logger.debug('local outpoint matched');
// 2. if the outpoints don't match, check the height
} else if (localHeight > resolvedHeight) {
logger.debug('local height was greater than resolved height');
// 2. get the resolved claim
} else {
logger.debug(`local outpoint did not match for ${uri}. Initiating update.`);
getClaimAndUpdate(uri, resolvedAddress, resolvedHeight);
}
})
.catch(error => {
logger.error(error);
});
}
function getClaimAndUpdate (uri, address, height) {
// 1. get the claim
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
logger.debug(' Get returned outpoint: ', outpoint);
// 2. update the entry in db
db.File
.update({
outpoint,
height, // note: height is coming from the 'resolve', not 'get'.
address, // note: address is coming from the 'resolve', not 'get'.
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
}, {
where: {
name,
claimId: claim_id,
},
})
.then(result => {
logger.debug('successfully updated mysql record', result);
})
.catch(error => {
logger.error('sequelize error', error);
});
})
.catch(error => {
logger.error(`error while getting claim for ${uri} >> `, error);
});
}
function getClaimAndHandleResponse (uri, address, height, resolve, reject) {
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
// create entry in the db
logger.silly(`creating "${name}" record in File db`);
db.File
.create({
name,
claimId : claim_id,
address, // note: comes from parent 'resolve,' not this 'get' call
outpoint,
height, // note: comes from parent 'resolve,' not this 'get' call
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
})
.then(result => {
logger.debug('successfully created mysql record');
})
.catch(error => {
logger.error('sequelize create error', error);
});
// resolve the request
resolve({
name,
claimId : claim_id,
fileName: file_name,
filePath: download_path,
fileType: mime_type,
});
})
.catch(error => {
reject(error);
});
}
function getClaimAndReturnResponse (uri, address, height) {
const deferred = new Promise((resolve, reject) => {
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
// create entry in the db
logger.silly(`Creating new File record`);
db.File
.create({
name,
claimId : claim_id,
address, // note: passed as an arguent, not from this 'get' call
outpoint,
height, // note: passed as an arguent, not from this 'get' call
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
})
.then(result => {
logger.debug('Successfully created File record');
resolve(result); // note: result.dataValues ?
})
.catch(error => {
logger.debug('db.File.create error');
reject(error);
});
})
.catch(error => {
logger.debug('lbryApi.getClaim error');
reject(error);
});
});
return deferred;
}
module.exports = { module.exports = {
getClaimByName (claimName) { serveClaimByName (claimName) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
// 1. get the top free, public claims // 1. get the top free, public claims
getAllFreePublicClaims(claimName) getAllFreePublicClaims(claimName)
@ -172,11 +30,11 @@ module.exports = {
// serve the file // serve the file
resolve(claim.dataValues); resolve(claim.dataValues);
// trigger update if needed // trigger update if needed
updateFileIfNeeded(uri, claim.dataValues.outpoint, claim.dataValues.height); serveHelpers.updateFileIfNeeded(uri, claim.dataValues.outpoint, claim.dataValues.height);
// 3. otherwise use daemon to retrieve it // 3. otherwise use daemon to retrieve it
} else { } else {
// get the claim and serve it // get the claim and serve it
getClaimAndHandleResponse(uri, address, height, resolve, reject); serveHelpers.getClaimAndHandleResponse(uri, address, height, resolve, reject);
} }
}) })
.catch(error => { .catch(error => {
@ -189,8 +47,8 @@ module.exports = {
}); });
return deferred; return deferred;
}, },
getClaimByClaimId (name, claimId) { serveClaimByClaimId (name, claimId) {
logger.debug(`Getting claim name: ${name} by claimid: ${claimId}`); logger.debug(`serving claim "${name}" with claimid "${claimId}"`);
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
// 1. check locally for the claim // 1. check locally for the claim
const uri = `${name}#${claimId}`; const uri = `${name}#${claimId}`;
@ -201,37 +59,25 @@ module.exports = {
if (result) { if (result) {
logger.debug('local result found'); logger.debug('local result found');
// return the data for the file to be served // return the data for the file to be served
getShortUrlByClaimId(name, claimId) resolve(result.dataValues);
.then(shortUrl => { serveHelpers.updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint);
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
// update the file, as needed
updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint);
// 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created // 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created
} else { } else {
logger.debug('no local result found'); logger.debug('no local result found');
lbryApi lbryApi
.resolveUri(uri) .resolveUri(uri)
.then(result => { .then(result => {
logger.debug('resolve returned successfully');
if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
// get claim and serve // get claim and serve
getClaimAndReturnResponse(uri, result.claim.address, result.claim.height) serveHelpers
.getClaimAndReturnResponse(uri, result.claim.address, result.claim.height)
.then(result => { .then(result => {
logger.debug('get request returned'); resolve(result.dataValues);
getShortUrlByClaimId(name, claimId)
.then(shortUrl => {
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
}) })
.catch(error => reject(error)); .catch(error => reject(error));
} else { } else {
logger.debug('Resolve did not return a free, public claim'); logger.debug('Resolve did not return a free, public claim');
resolve(null, null); resolve(null);
} }
}) })
.catch(error => { .catch(error => {
@ -244,12 +90,13 @@ module.exports = {
}); });
return deferred; return deferred;
}, },
getClaimByShortUrl (name, shortUrl) { serveClaimByShortUrl (name, shortUrl) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
let uri; let uri;
let claimId; let claimId;
// 1. validate the claim id & retrieve the full claim id if needed // 1. validate the claim id & retrieve the full claim id if needed
getClaimIdByShortUrl(name, shortUrl) serveHelpers
.getClaimIdByShortUrl(name, shortUrl)
.then(result => { .then(result => {
// 2. check locally for the claim // 2. check locally for the claim
uri = `${name}#${result}`; uri = `${name}#${result}`;
@ -260,10 +107,9 @@ module.exports = {
// 3. if a match is found locally, serve that claim // 3. if a match is found locally, serve that claim
if (result) { if (result) {
// return the data for the file to be served // return the data for the file to be served
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues); resolve(result.dataValues);
// update the file, as needed // update the file, as needed
updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint); serveHelpers.updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint);
// 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created // 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created
} else { } else {
lbryApi lbryApi
@ -271,16 +117,15 @@ module.exports = {
.then(result => { .then(result => {
if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
// get claim and serve // get claim and serve
getClaimAndReturnResponse(uri, result.claim.address, result.claim.height) serveHelpers
.getClaimAndReturnResponse(uri, result.claim.address, result.claim.height)
.then(result => { .then(result => {
logger.debug('returned');
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues); resolve(result.dataValues);
}) })
.catch(error => reject(error)); .catch(error => reject(error));
} else { } else {
logger.debug('Resolve did not return a free, public claim'); logger.debug('Resolve did not return a free, public claim');
resolve(null, null); resolve(null);
} }
}) })
.catch(error => reject(error)); .catch(error => reject(error));
@ -290,7 +135,4 @@ module.exports = {
}); });
return deferred; return deferred;
}, },
getAllClaims (claimName) {
return getAllFreePublicClaims(claimName);
},
}; };

View file

@ -0,0 +1,159 @@
const lbryApi = require('../helpers/libraries/lbryApi.js');
const db = require('../models');
const logger = require('winston');
const getAllFreePublicClaims = require('../helpers/functions/getAllFreePublicClaims.js');
const isFreePublicClaim = require('../helpers/functions/isFreePublicClaim.js');
const serveHelpers = require('../helpers/libraries/serveHelpers.js');
module.exports = {
showClaimByName (claimName) {
const deferred = new Promise((resolve, reject) => {
// 1. get the top free, public claims
getAllFreePublicClaims(claimName)
.then(freePublicClaimList => {
// check to make sure some claims were found
if (!freePublicClaimList) {
resolve(null);
return;
}
const name = freePublicClaimList[0].name;
const claimId = freePublicClaimList[0].claim_id;
const uri = `${name}#${claimId}`;
const height = freePublicClaimList[0].height;
const address = freePublicClaimList[0].address;
// 2. check to see if the file is available locally
db.File
.findOne({ where: { name, claimId } })
.then(result => {
// 3. if a matching record is found locally, serve it
if (result) {
// return the data for the file to be served
serveHelpers.getShortUrlByClaimId(name, claimId)
.then(shortUrl => {
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
// trigger update if needed
serveHelpers.updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.height);
// 3. otherwise use daemon to retrieve it
} else {
// get the claim and serve it
serveHelpers.getClaimAndHandleResponse(uri, address, height, resolve, reject);
}
})
.catch(error => {
reject(error);
});
})
.catch(error => {
reject(error);
});
});
return deferred;
},
showClaimByClaimId (name, claimId) {
logger.debug(`Getting claim name: ${name} by claimid: ${claimId}`);
const deferred = new Promise((resolve, reject) => {
// 1. check locally for the claim
const uri = `${name}#${claimId}`;
db.File
.findOne({ where: { name, claimId } })
.then(result => {
// 3. if a match is found locally, serve that claim
if (result) {
logger.debug('local result found');
// return the data for the file to be served
serveHelpers.getShortUrlByClaimId(name, claimId)
.then(shortUrl => {
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
// update the file, as needed
serveHelpers.updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint);
// 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created
} else {
logger.debug('no local result found');
lbryApi
.resolveUri(uri)
.then(result => {
logger.debug('resolve returned successfully');
if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
// get claim and serve
serveHelpers.getClaimAndReturnResponse(uri, result.claim.address, result.claim.height)
.then(result => {
logger.debug('get request returned');
serveHelpers.getShortUrlByClaimId(name, claimId)
.then(shortUrl => {
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
})
.catch(error => reject(error));
} else {
logger.debug('Resolve did not return a free, public claim');
resolve(null, null);
}
})
.catch(error => {
logger.debug('resolve returned an error');
reject(error);
});
}
})
.catch(error => reject(error));
});
return deferred;
},
showClaimByShortUrl (name, shortUrl) {
const deferred = new Promise((resolve, reject) => {
let uri;
let claimId;
// 1. validate the claim id & retrieve the full claim id if needed
serveHelpers.getClaimIdByShortUrl(name, shortUrl)
.then(result => {
// 2. check locally for the claim
uri = `${name}#${result}`;
claimId = result;
return db.File.findOne({ where: { name, claimId } });
})
.then(result => {
// 3. if a match is found locally, serve that claim
if (result) {
// return the data for the file to be served
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
// update the file, as needed
serveHelpers.updateFileIfNeeded(uri, result.dataValues.outpoint, result.dataValues.outpoint);
// 3. if a match was not found locally, use the daemon to retrieve the claim & return the db data once it is created
} else {
lbryApi
.resolveUri(uri)
.then(result => {
if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
// get claim and serve
serveHelpers.getClaimAndReturnResponse(uri, result.claim.address, result.claim.height)
.then(result => {
logger.debug('returned');
result.dataValues['shortUrl'] = shortUrl;
resolve(result.dataValues);
})
.catch(error => reject(error));
} else {
logger.debug('Resolve did not return a free, public claim');
resolve(null, null);
}
})
.catch(error => reject(error));
}
})
.catch(error => reject(error));
});
return deferred;
},
showAllClaims (claimName) {
return getAllFreePublicClaims(claimName);
},
};

View file

@ -91,11 +91,9 @@ module.exports = {
params: { uri }, params: { uri },
}) })
.then(({ data }) => { .then(({ data }) => {
logger.debug('resolved successfully', data); if (data.result[uri].error) { // check for errors
// check for errors
if (data.result[uri].error) {
reject(data.result[uri].error); reject(data.result[uri].error);
} else { } else { // if no errors, resolve
resolve(data.result[uri]); resolve(data.result[uri]);
} }
}) })

View file

@ -1,21 +1,73 @@
const logger = require('winston'); const logger = require('winston');
// const db = require('../../models'); const db = require('../../models');
const { getClaimsList } = require('./lbryApi'); const lbryApi = require('./lbryApi');
function determineShortUrl (claimId, claimList) { function determineShortUrl (claimId, claimList) {
let shortUrl = claimId.substring(0, 1); logger.debug('determining short url based on claim id and claim list');
let i = 1; const thisClaim = claimList.filter(claim => { // find this claim in the list & store it
claimList = claimList.filter(claim => { // filter out this exact claim id return claim.claim_id === claimId;
})[0];
claimList = claimList.filter(claim => { // remove this claim from the claim list
return claim.claim_id !== claimId; return claim.claim_id !== claimId;
}); });
while (claimList.length !== 0) { // filter out matching claims until none or left if (claimList.length === 0) { // if there are no other claims, return the first letter of the claim id
shortUrl = claimId.substring(0, i); return claimId.substring(0, 1);
claimList = claimList.filter(claim => { } else {
return (claim.claim_id.substring(0, i) === shortUrl); let i = 0;
const claimListCopy = claimList;
while (claimList.length !== 0) { // filter out matching claims
i++;
claimList = claimList.filter(claim => {
return (claim.claim_id.substring(0, i) === claimId.substring(0, i));
});
}
i -= 1;
const lastMatch = claimId.substring(0, i);
const matchingClaims = claimListCopy.filter(claim => {
return (claim.claim_id.substring(0, i) === lastMatch);
}); });
i++; for (let j = 0; j < matchingClaims.length; j++) {
if (matchingClaims[j].height < thisClaim.height) {
return claimId.substring(0, i + 1);
}
}
return claimId.substring(0, i);
} }
return (shortUrl); }
function getClaimAndUpdate (uri, address, height) {
// 1. get the claim
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
logger.debug(' Get returned outpoint: ', outpoint);
// 2. update the entry in db
db.File
.update({
outpoint,
height, // note: height is coming from the 'resolve', not 'get'.
address, // note: address is coming from the 'resolve', not 'get'.
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
}, {
where: {
name,
claimId: claim_id,
},
})
.then(result => {
logger.debug('successfully updated mysql record', result);
})
.catch(error => {
logger.error('sequelize error', error);
});
})
.catch(error => {
logger.error(`error while getting claim for ${uri} >> `, error);
});
} }
module.exports = { module.exports = {
@ -48,7 +100,7 @@ module.exports = {
}, },
getClaimIdByShortUrl (name, shortUrl) { getClaimIdByShortUrl (name, shortUrl) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
getClaimsList(name) lbryApi.getClaimsList(name)
.then(({ claims }) => { .then(({ claims }) => {
const regex = new RegExp(`^${shortUrl}`); const regex = new RegExp(`^${shortUrl}`);
logger.debug('regex:', regex); logger.debug('regex:', regex);
@ -80,7 +132,7 @@ module.exports = {
getShortUrlByClaimId (name, claimId) { getShortUrlByClaimId (name, claimId) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
// get a list of all the claims // get a list of all the claims
getClaimsList(name) lbryApi.getClaimsList(name)
// find the smallest possible unique url for this claim // find the smallest possible unique url for this claim
.then(({ claims }) => { .then(({ claims }) => {
const shortUrl = determineShortUrl(claimId, claims); const shortUrl = determineShortUrl(claimId, claims);
@ -95,4 +147,109 @@ module.exports = {
determineShortUrl (claimId, claimList) { determineShortUrl (claimId, claimList) {
return determineShortUrl(claimId, claimList); return determineShortUrl(claimId, claimList);
}, },
updateFileIfNeeded (uri, localOutpoint, localHeight) {
logger.debug(`Initiating resolve to check outpoint for ${uri}`);
// 1. resolve claim
lbryApi
.resolveUri(uri)
.then(result => {
// check to make sure the result is a claim
if (!result.claim) {
logger.debug('resolve did not return a claim');
return;
}
// logger.debug('resolved result:', result);
const resolvedOutpoint = `${result.claim.txid}:${result.claim.nout}`;
const resolvedHeight = result.claim.height;
const resolvedAddress = result.claim.address;
logger.debug('database outpoint:', localOutpoint);
logger.debug('resolved outpoint:', resolvedOutpoint);
// 2. if the outpoint's match, no further work needed
if (localOutpoint === resolvedOutpoint) {
logger.debug('local outpoint matched');
// 2. if the outpoints don't match, check the height
} else if (localHeight > resolvedHeight) {
logger.debug('local height was greater than resolved height');
// 2. get the resolved claim
} else {
logger.debug(`local outpoint did not match for ${uri}. Initiating update.`);
getClaimAndUpdate(uri, resolvedAddress, resolvedHeight);
}
})
.catch(error => {
logger.error(error);
});
},
getClaimAndHandleResponse (uri, address, height, resolve, reject) {
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
// create entry in the db
logger.silly(`creating "${name}" record in File db`);
db.File
.create({
name,
claimId : claim_id,
address, // note: comes from parent 'resolve,' not this 'get' call
outpoint,
height, // note: comes from parent 'resolve,' not this 'get' call
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
})
.then(result => {
logger.debug('successfully created mysql record');
})
.catch(error => {
logger.error('sequelize create error', error);
});
// resolve the request
resolve({
name,
claimId : claim_id,
fileName: file_name,
filePath: download_path,
fileType: mime_type,
});
})
.catch(error => {
reject(error);
});
},
getClaimAndReturnResponse (uri, address, height) {
const deferred = new Promise((resolve, reject) => {
lbryApi
.getClaim(uri)
.then(({ name, claim_id, outpoint, file_name, download_path, mime_type, metadata }) => {
// create entry in the db
logger.silly(`Creating new File record`);
db.File
.create({
name,
claimId : claim_id,
address, // note: passed as an arguent, not from this 'get' call
outpoint,
height, // note: passed as an arguent, not from this 'get' call
fileName: file_name,
filePath: download_path,
fileType: mime_type,
nsfw : metadata.stream.metadata.nsfw,
})
.then(result => {
logger.debug('Successfully created File record');
resolve(result); // note: result.dataValues ?
})
.catch(error => {
logger.debug('db.File.create error');
reject(error);
});
})
.catch(error => {
logger.debug('lbryApi.getClaim error');
reject(error);
});
});
return deferred;
},
}; };

View file

@ -1,96 +0,0 @@
var canvas = document.getElementById('meme-canvas');
var img = document.getElementById('start-image');
var canvasWidth;
var canvasHeight;
var fontSize = 28;
var topText = document.getElementById('top-text');
var bottomText = document.getElementById('bottom-text');
var ctx = canvas.getContext('2d');
// create the canvas
img.onload = function() {
// get dimensions of the start img
canvasWidth = img.width;
canvasHeight = img.height;
// hide start image
img.hidden = true;
// size the canvas
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// draw the starting meme
drawMeme()
}
function newCanvas(image){
// hide start image
img = image;
// get dimensions of the start img
canvasHeight = canvasWidth * (img.height / img.width);
// size the canvas
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// draw the meme
drawMeme()
}
// if the text changes, re-draw the meme
topText.addEventListener('keyup', drawMeme);
bottomText.addEventListener('keyup', drawMeme);
// draw the image and draw the text over it
function drawMeme() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight);
ctx.lineWidth = 4;
ctx.font = fontSize + 'px sans-serif';
ctx.strokeStyle = 'black';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
var text1 = topText.value;
text1 = text1.toUpperCase();
x = canvasWidth / 2;
y = 5;
wrapText(ctx, text1, x, y, canvasWidth, fontSize, false);
ctx.textBaseline = 'bottom';
var text2 = bottomText.value;
text2 = text2.toUpperCase();
y = canvasHeight - 5;
wrapText(ctx, text2, x, y, canvasHeight, fontSize, true);
}
function wrapText(context, text, x, y, maxWidth, lineHeight, fromBottom) {
var pushMethod = (fromBottom)?'unshift':'push';
lineHeight = (fromBottom)?-lineHeight:lineHeight;
var lines = [];
var y = y;
var line ='';
var words = text.split(' ');
for (var i = 0; i < words.length; i++) {
var testLine = line + ' ' + words[i];
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth) {
lines[pushMethod](line);
line = words[i] + ' ';
} else {
line = testLine;
}
}
lines[pushMethod](line);
for (var k in lines ) {
context.strokeText(lines[k], x, y + lineHeight * k);
context.fillText(lines[k], x, y + lineHeight * k);
}
}

View file

@ -1,50 +0,0 @@
// define variables
var socket = io();
var uploader = new SocketIOFileUpload(socket);
var stagedFiles = null;
var license = 'Creative Commons';
var nsfw = false;
var nameInput = document.getElementById("publish-name");
/* socketio-file-upload listeners */
uploader.addEventListener('start', function(event){
event.file.meta.name = nameInput.value;
event.file.meta.license = license;
event.file.meta.nsfw = nsfw;
event.file.meta.type = stagedFiles[0].type;
// re-set the html in the publish area
document.getElementById('publish-active-area').innerHTML = '<div id="publish-status"></div><div id="progress-bar"></div>';
// start a progress animation
createProgressBar(document.getElementById('progress-bar'), 12);
// google analytics
ga('send', {
hitType: 'event',
eventCategory: 'publish',
eventAction: nameInput.value
});
});
uploader.addEventListener('progress', function(event){
var percent = event.bytesLoaded / event.file.size * 100;
updatePublishStatus('File is ' + percent.toFixed(2) + '% loaded to the server');
});
/* socket.io message listeners */
socket.on('publish-status', function(msg){
updatePublishStatus(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>';
});
socket.on('publish-complete', function(msg){
var publishResults;
var directUrl = '/' + msg.name + '/' + msg.result.claim_id;
// build new publish area
publishResults = '<p>Your publish is complete! View it here:</p>';
publishResults += '<p><a target="_blank" href="' + directUrl + '">spee.ch' + directUrl + '</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="/meme-fodder/play"><button>Reload</button></a></p>';
// update publish area
document.getElementById('publish-active-area').innerHTML = publishResults;
});

View file

@ -1,16 +1,16 @@
const { getClaimByClaimId, getClaimByShortUrl, getClaimByName } = require('../controllers/serveController.js'); const { serveClaimByName, serveClaimByClaimId, serveClaimByShortUrl } = 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'); const errorHandlers = require('../helpers/libraries/errorHandlers.js');
const { serveFile } = require('../helpers/libraries/serveHelpers.js'); const { serveFile } = require('../helpers/libraries/serveHelpers.js');
function validateClaimId (name, claimId) { function retrieveAssetInfo (name, claimId) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
// if claim id is full 40 chars, retrieve the shortest possible url // if claim id is full 40 chars, retrieve the shortest possible url
if (claimId.length === 40) { if (claimId.length === 40) {
resolve(getClaimByClaimId(name, claimId)); resolve(serveClaimByClaimId(name, claimId));
// if the claim id is shorter than 40, retrieve the full claim id & shortest possible url // if the claim id is shorter than 40, retrieve the full claim id & shortest possible url
} else if (claimId.length < 40) { } else if (claimId.length < 40) {
resolve(getClaimByShortUrl(name, claimId)); resolve(serveClaimByShortUrl(name, claimId));
} else { } else {
reject(new Error('That Claim Id is longer than 40 characters.')); reject(new Error('That Claim Id is longer than 40 characters.'));
} }
@ -24,7 +24,7 @@ module.exports = (app) => {
// google analytics // google analytics
sendGoogleAnalytics('serve', headers, ip, originalUrl); sendGoogleAnalytics('serve', headers, ip, originalUrl);
// begin image-serve processes // begin image-serve processes
validateClaimId(params.name, params.claim_id) retrieveAssetInfo(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) {
@ -32,7 +32,7 @@ module.exports = (app) => {
return; return;
} }
// serve the file or the show route // serve the file or the show route
if (headers['accept']) { // note: added b/c some requests errored out due to no accept param in header if (headers['accept']) {
const mimetypes = headers['accept'].split(','); const mimetypes = headers['accept'].split(',');
if (mimetypes.includes('text/html')) { if (mimetypes.includes('text/html')) {
postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success'); postToStats('show', originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success');
@ -55,7 +55,7 @@ module.exports = (app) => {
// google analytics // google analytics
sendGoogleAnalytics('serve', headers, ip, originalUrl); sendGoogleAnalytics('serve', headers, ip, originalUrl);
// begin image-serve processes // begin image-serve processes
getClaimByName(params.name) serveClaimByName(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) {

View file

@ -1,15 +1,15 @@
const errorHandlers = require('../helpers/libraries/errorHandlers.js'); const errorHandlers = require('../helpers/libraries/errorHandlers.js');
const { getClaimByClaimId, getClaimByShortUrl, getClaimByName, getAllClaims } = require('../controllers/serveController.js'); const { showClaimByName, showClaimByClaimId, showClaimByShortUrl, showAllClaims } = require('../controllers/showController.js');
const { postToStats, getStatsSummary, getTrendingClaims } = require('../controllers/statsController.js'); const { postToStats, getStatsSummary, getTrendingClaims } = require('../controllers/statsController.js');
function validateClaimId (name, claimId) { function retrieveAssetInfo (name, claimId) {
const deferred = new Promise((resolve, reject) => { const deferred = new Promise((resolve, reject) => {
// if claim id is full 40 chars, retrieve the shortest possible url // if claim id is full 40 chars, retrieve the shortest possible url
if (claimId.length === 40) { if (claimId.length === 40) {
resolve(getClaimByClaimId(name, claimId)); resolve(showClaimByClaimId(name, claimId));
// if the claim id is shorter than 40, retrieve the full claim id & shortest possible url // if the claim id is shorter than 40, retrieve the full claim id & shortest possible url
} else if (claimId.length < 40) { } else if (claimId.length < 40) {
resolve(getClaimByShortUrl(name, claimId)); resolve(showClaimByShortUrl(name, claimId));
} else { } else {
reject(new Error('That Claim Id is longer than 40 characters.')); reject(new Error('That Claim Id is longer than 40 characters.'));
} }
@ -49,22 +49,10 @@ module.exports = (app) => {
errorHandlers.handleRequestError(error, res); errorHandlers.handleRequestError(error, res);
}); });
}); });
// route to show the meme-fodder meme maker
app.get('/meme-fodder/play', ({ ip, originalUrl }, res) => {
// get and render the content
getAllClaims('meme-fodder')
.then(orderedFreePublicClaims => {
postToStats('show', originalUrl, ip, null, null, 'success');
res.status(200).render('memeFodder', { claims: orderedFreePublicClaims });
})
.catch(error => {
errorHandlers.handleRequestError('show', originalUrl, ip, error, res);
});
});
// 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) => {
// get and render the content // get and render the content
getAllClaims(params.name) showAllClaims(params.name)
.then(orderedFreePublicClaims => { .then(orderedFreePublicClaims => {
if (!orderedFreePublicClaims) { if (!orderedFreePublicClaims) {
res.status(307).render('noClaims'); res.status(307).render('noClaims');
@ -80,7 +68,7 @@ module.exports = (app) => {
// route to show a specific asset // route to show a specific asset
app.get('/show/:name/:claim_id', ({ ip, originalUrl, params }, res) => { app.get('/show/:name/:claim_id', ({ ip, originalUrl, params }, res) => {
// begin image-serve processes // begin image-serve processes
validateClaimId(params.name, params.claim_id) retrieveAssetInfo(params.name, params.claim_id)
.then((fileInfo) => { .then((fileInfo) => {
console.log('SHORT URL:', fileInfo.shortUrl); console.log('SHORT URL:', fileInfo.shortUrl);
// check to make sure a file was found // check to make sure a file was found
@ -93,13 +81,13 @@ module.exports = (app) => {
res.status(200).render('show', { fileInfo }); res.status(200).render('show', { fileInfo });
}) })
.catch(error => { .catch(error => {
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res); errorHandlers.handleRequestError('show', originalUrl, ip, error, res);
}); });
}); });
// route to show the winning free, public claim // route to show the winning free, public claim
app.get('/show/:name', ({ ip, originalUrl, params }, res) => { app.get('/show/:name', ({ ip, originalUrl, params }, res) => {
// get and render the content // get and render the content
getClaimByName(params.name) showClaimByName(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) {
@ -111,7 +99,7 @@ module.exports = (app) => {
res.status(200).render('show', { fileInfo }); res.status(200).render('show', { fileInfo });
}) })
.catch(error => { .catch(error => {
errorHandlers.handleRequestError('serve', originalUrl, ip, error, res); errorHandlers.handleRequestError('show', originalUrl, ip, error, res);
}); });
}); });
}; };

View file

@ -1,15 +0,0 @@
<div class="wrapper">
{{> topBar}}
<div class="full">
{{> memeFodderMaker}}
{{> memeFodderResults}}
</div>
{{> footer}}
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="/siofu/client.js"></script>
<script src="/assets/js/generalFunctions.js"></script>
<script src="/assets/js/memeFodder-draw.js"></script>
<script src="/assets/js/memeFodder-publish.js"></script>

View file

@ -6,19 +6,21 @@
<h2 class="subheader">Links</h2> <h2 class="subheader">Links</h2>
{{!--short direct link to asset--}} {{!--short direct link to asset--}}
<div class="share-option"> <div class="share-option">
<a href="/{{fileInfo.name}}/{{fileInfo.shortUrl}}">Direct Link</a> <a href="/{{fileInfo.name}}/{{fileInfo.shortUrl}}">Permanent Short Link</a>
<div class="input-error" id="input-error-copy-direct-link" hidden="true"></div> (most convenient)
<div class="input-error" id="input-error-copy-short-link" hidden="true"></div>
<br/> <br/>
<input type="text" id="direct-link" class="link" readonly spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.shortUrl}}" onclick="select()"/> <input type="text" id="short-link" class="link" readonly spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.shortUrl}}" onclick="select()"/>
<button class="copy-button" data-elementtocopy="direct-link" onclick="copyToClipboard(event)">copy</button> <button class="copy-button" data-elementtocopy="short-link" onclick="copyToClipboard(event)">copy</button>
</div> </div>
{{!-- link to show route for asset--}} {{!-- link to show route for asset--}}
<div class="share-option"> <div class="share-option">
<a href="/show/{{fileInfo.name}}/{{fileInfo.shortUrl}}">Details Link</a> <a href="/{{fileInfo.name}}/{{fileInfo.claimId}}">Permanent Long Link</a>
<div class="input-error" id="input-error-copy-show-link" hidden="true"></div> (fastest service)
<div class="input-error" id="input-error-copy-long-link" hidden="true"></div>
</br> </br>
<input type="text" id="show-link" class="link" readonly onclick="select()" spellcheck="false" value="https://spee.ch/show/{{fileInfo.name}}/{{fileInfo.shortUrl}}"/> <input type="text" id="long-link" class="link" readonly onclick="select()" spellcheck="false" value="https://spee.ch/{{fileInfo.name}}/{{fileInfo.claimId}}"/>
<button class="copy-button" data-elementtocopy="show-link" onclick="copyToClipboard(event)">copy</button> <button class="copy-button" data-elementtocopy="long-link" onclick="copyToClipboard(event)">copy</button>
</div> </div>
{{!-- html text for embedding asset--}} {{!-- html text for embedding asset--}}
<div class="share-option"> <div class="share-option">

View file

@ -1,31 +0,0 @@
<div class="panel" id="meme-fodder-maker">
<div>
<h2>#LBRYMemeFodder</h2>
<h3>Congratulations, you found the /meme-fodder game!</h3>
<p>Create a meme based on the current <i>lbry://meme-fodder</i> claims using the tool below.</p>
</div>
<div class="col-left">
<canvas id="meme-canvas">
If you can see this, the meme generator is not supported by your browser.
</canvas>
<img id="start-image" src="/meme-fodder" alt="a picture to make your meme with"/>
</div>
<div class="col-right">
<textarea id="direct-link-holder" hidden="true">No URL yet</textarea>
<div id="publish-active-area">
<p>
<label>Meme:</label><br/>
<input id="top-text" type="text" value="Hello" /><br/>
<input id="bottom-text" type="text" value="world!" /><br/>
</p>
<p>
<label for="publish-name">Claim Name:</label></br>
<input id="publish-name" type="text" placeholder="Your claim name" />
</p>
<p>
<button onclick="startPublish()">Save and Publish</button>
</p>
</div>
</div>
<p class="stop-float">Got a masterpiece? <a href="https://twitter.com/hashtag/LBRYMemeFodder" target="_blank">Share it with the community</a> and see what they think!</p>
</div>

View file

@ -1,11 +0,0 @@
<div class="stop-float panel">
<h2>Recent Meme Fodder</h2>
<div class="row">
<p>Below are the free, public images published to <a href="lbry://meme-fodder">lbry://meme-fodder</a>. Want to put a different image on the chopping block? Go publish it!</p>
</div>
<div class="row">
{{#each claims}}
<img class="asset-small" src="/{{this.name}}/{{this.claim_id}}" onclick="newCanvas(this)"/>
{{/each}}
</div>
</div>