Short urls 2 #93
14 changed files with 498 additions and 443 deletions
|
@ -3,151 +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 { validateClaimId } = require('../helpers/libraries/serveHelpers.js');
|
const serveHelpers = require('../helpers/libraries/serveHelpers.js');
|
||||||
|
|
||||||
function updateFileIfNeeded (uri, claimName, claimId, localOutpoint, localHeight) {
|
|
||||||
logger.debug(`Initiating resolve to check outpoint for ${claimName}:${claimId}.`);
|
|
||||||
// 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.error('sequelize create error', error);
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(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)
|
||||||
|
@ -171,15 +30,14 @@ module.exports = {
|
||||||
// serve the file
|
// serve the file
|
||||||
resolve(claim.dataValues);
|
resolve(claim.dataValues);
|
||||||
// trigger update if needed
|
// trigger update if needed
|
||||||
updateFileIfNeeded(uri, name, claimId, 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 => {
|
||||||
logger.error('sequelize error', error);
|
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -189,54 +47,92 @@ module.exports = {
|
||||||
});
|
});
|
||||||
return deferred;
|
return deferred;
|
||||||
},
|
},
|
||||||
getClaimByClaimId (name, claimId) {
|
serveClaimByClaimId (name, claimId) {
|
||||||
|
logger.debug(`serving claim "${name}" with 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
|
||||||
|
resolve(result.dataValues);
|
||||||
|
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 => {
|
||||||
|
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 => {
|
||||||
|
resolve(result.dataValues);
|
||||||
|
})
|
||||||
|
.catch(error => reject(error));
|
||||||
|
} else {
|
||||||
|
logger.debug('Resolve did not return a free, public claim');
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
logger.debug('resolve returned an error');
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => reject(error));
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
serveClaimByShortUrl (name, shortUrl) {
|
||||||
const deferred = new Promise((resolve, reject) => {
|
const deferred = new Promise((resolve, reject) => {
|
||||||
let uri;
|
let uri;
|
||||||
|
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
|
||||||
validateClaimId(name, claimId)
|
serveHelpers
|
||||||
.then(validClaimId => {
|
.getClaimIdByShortUrl(name, shortUrl)
|
||||||
|
.then(result => {
|
||||||
// 2. check locally for the claim
|
// 2. check locally for the claim
|
||||||
logger.debug('valid claim id:', validClaimId);
|
uri = `${name}#${result}`;
|
||||||
uri = `${name}#${validClaimId}`;
|
claimId = result;
|
||||||
return db.File.findOne({ where: { name, claimId: validClaimId } });
|
return db.File.findOne({ where: { name, claimId } });
|
||||||
})
|
})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
// 3. if a match is found locally, serve that claim
|
// 3. if a match is found locally, serve that claim
|
||||||
if (result) {
|
if (result) {
|
||||||
logger.debug('Result found in File table:', result.dataValues);
|
|
||||||
// return the data for the file to be served
|
// return the data for the file to be served
|
||||||
resolve(result.dataValues);
|
resolve(result.dataValues);
|
||||||
// update the file, as needed
|
// update the file, as needed
|
||||||
updateFileIfNeeded(uri, name, claimId, 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 {
|
||||||
logger.debug('No result found in File table');
|
|
||||||
lbryApi
|
lbryApi
|
||||||
.resolveUri(uri)
|
.resolveUri(uri)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (!result.claim) { // check to make sure the result is a claim
|
if (result.claim && isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
|
||||||
logger.debug('resolve did not return a claim');
|
|
||||||
resolve(null);
|
|
||||||
}
|
|
||||||
if (isFreePublicClaim(result.claim)) { // check to see if the claim is free & public
|
|
||||||
// get claim and serve
|
// get claim and serve
|
||||||
resolve(getClaimAndReturnResponse(uri, result.claim.address, result.claim.height));
|
serveHelpers
|
||||||
|
.getClaimAndReturnResponse(uri, result.claim.address, result.claim.height)
|
||||||
|
.then(result => {
|
||||||
|
resolve(result.dataValues);
|
||||||
|
})
|
||||||
|
.catch(error => reject(error));
|
||||||
} else {
|
} else {
|
||||||
|
logger.debug('Resolve did not return a free, public claim');
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => reject(error));
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => reject(error));
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return deferred;
|
return deferred;
|
||||||
},
|
},
|
||||||
getAllClaims (claimName) {
|
|
||||||
return getAllFreePublicClaims(claimName);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
159
controllers/showController.js
Normal file
159
controllers/showController.js
Normal 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);
|
||||||
|
},
|
||||||
|
};
|
|
@ -10,11 +10,10 @@ module.exports = {
|
||||||
if (result && (typeof result !== 'string')) {
|
if (result && (typeof result !== 'string')) {
|
||||||
result = result.toString();
|
result = result.toString();
|
||||||
}
|
}
|
||||||
// // make sure the ip address(es) are a string
|
// make sure the ip address(es) are a string
|
||||||
if (ipAddress && (typeof ipAddress !== 'string')) {
|
if (ipAddress && (typeof ipAddress !== 'string')) {
|
||||||
ipAddress = ipAddress.toString();
|
ipAddress = ipAddress.toString();
|
||||||
}
|
}
|
||||||
logger.silly(name, claimId);
|
|
||||||
db.File
|
db.File
|
||||||
.findOne({where: { name, claimId }})
|
.findOne({where: { name, claimId }})
|
||||||
.then(file => {
|
.then(file => {
|
||||||
|
@ -25,7 +24,6 @@ module.exports = {
|
||||||
} else {
|
} else {
|
||||||
FileId = null;
|
FileId = null;
|
||||||
}
|
}
|
||||||
logger.silly('file id:', FileId);
|
|
||||||
return db.Request
|
return db.Request
|
||||||
.create({
|
.create({
|
||||||
action,
|
action,
|
||||||
|
|
|
@ -59,6 +59,7 @@ module.exports = {
|
||||||
resolve(data.result);
|
resolve(data.result);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
logger.debug("axios.post 'get' error");
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -90,12 +91,11 @@ module.exports = {
|
||||||
params: { uri },
|
params: { uri },
|
||||||
})
|
})
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
// check for errors
|
if (data.result[uri].error) { // check for errors
|
||||||
if (data.result[uri].error) {
|
|
||||||
reject(data.result[uri].error);
|
reject(data.result[uri].error);
|
||||||
return;
|
} else { // if no errors, resolve
|
||||||
}
|
|
||||||
resolve(data.result[uri]);
|
resolve(data.result[uri]);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
reject(error);
|
reject(error);
|
||||||
|
|
|
@ -1,5 +1,74 @@
|
||||||
const logger = require('winston');
|
const logger = require('winston');
|
||||||
const db = require('../../models');
|
const db = require('../../models');
|
||||||
|
const lbryApi = require('./lbryApi');
|
||||||
|
|
||||||
|
function determineShortUrl (claimId, claimList) {
|
||||||
|
logger.debug('determining short url based on claim id and claim list');
|
||||||
|
const thisClaim = claimList.filter(claim => { // find this claim in the list & store it
|
||||||
|
return claim.claim_id === claimId;
|
||||||
|
})[0];
|
||||||
|
claimList = claimList.filter(claim => { // remove this claim from the claim list
|
||||||
|
return claim.claim_id !== claimId;
|
||||||
|
});
|
||||||
|
if (claimList.length === 0) { // if there are no other claims, return the first letter of the claim id
|
||||||
|
return claimId.substring(0, 1);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
||||||
serveFile ({ fileName, fileType, filePath }, res) {
|
serveFile ({ fileName, fileType, filePath }, res) {
|
||||||
|
@ -29,39 +98,157 @@ module.exports = {
|
||||||
// send the file
|
// send the file
|
||||||
res.status(200).sendFile(filePath, options);
|
res.status(200).sendFile(filePath, options);
|
||||||
},
|
},
|
||||||
validateClaimId (name, claimId) {
|
getClaimIdByShortUrl (name, shortUrl) {
|
||||||
const deferred = new Promise((resolve, reject) => {
|
const deferred = new Promise((resolve, reject) => {
|
||||||
logger.debug('claim id length:', claimId.length);
|
lbryApi.getClaimsList(name)
|
||||||
// make sure the claim id is 40 characters
|
.then(({ claims }) => {
|
||||||
if (claimId.length === 40) {
|
const regex = new RegExp(`^${shortUrl}`);
|
||||||
logger.debug('Claim Id length is valid.');
|
logger.debug('regex:', regex);
|
||||||
resolve(claimId);
|
const filteredClaimsList = claims.filter(claim => {
|
||||||
// if the claim id is shorter than 40, check the db for the full claim id
|
return regex.test(claim.claim_id);
|
||||||
} else if (claimId.length === 1) {
|
});
|
||||||
logger.debug(`Finding claim id for "${name}" "${claimId}"`);
|
logger.debug('filtered claims list', filteredClaimsList);
|
||||||
db.File
|
switch (filteredClaimsList.length) {
|
||||||
.findOne({
|
case 0:
|
||||||
where: {
|
reject(new Error('That is an invalid short url'));
|
||||||
name,
|
break;
|
||||||
claimId: { $like: `${claimId}%` },
|
case 1:
|
||||||
},
|
resolve(filteredClaimsList[0].claim_id);
|
||||||
})
|
break;
|
||||||
.then(file => {
|
default:
|
||||||
// if no results were found, throw an error
|
const sortedClaimsList = filteredClaimsList.sort((a, b) => {
|
||||||
if (!file) {
|
return a.height > b.height;
|
||||||
reject(new Error('That is not a valid short URL.'));
|
});
|
||||||
|
resolve(sortedClaimsList[0].claim_id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// if a result was found, resolve with the full claim id
|
|
||||||
logger.debug('Full claim id:', file.dataValues.claimId);
|
|
||||||
resolve(file.dataValues.claimId);
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
logger.error('The Claim Id was neither 40 nor 1 character in length');
|
return deferred;
|
||||||
reject(new Error('That Claim Id is not valid.'));
|
},
|
||||||
|
getShortUrlByClaimId (name, claimId) {
|
||||||
|
const deferred = new Promise((resolve, reject) => {
|
||||||
|
// get a list of all the claims
|
||||||
|
lbryApi.getClaimsList(name)
|
||||||
|
// find the smallest possible unique url for this claim
|
||||||
|
.then(({ claims }) => {
|
||||||
|
const shortUrl = determineShortUrl(claimId, claims);
|
||||||
|
resolve(shortUrl);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
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;
|
return deferred;
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -78,7 +78,6 @@ module.exports = (app, hostedContentPath) => {
|
||||||
res.status(400).send(error.message);
|
res.status(400).send(error.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the publish parameters
|
// prepare the publish parameters
|
||||||
const fileName = file.name;
|
const fileName = file.name;
|
||||||
const filePath = file.path;
|
const filePath = file.path;
|
||||||
|
|
|
@ -1,25 +1,38 @@
|
||||||
const logger = require('winston');
|
const { serveClaimByName, serveClaimByClaimId, serveClaimByShortUrl } = require('../controllers/serveController.js');
|
||||||
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');
|
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
||||||
const { serveFile } = require('../helpers/libraries/serveHelpers.js');
|
const { serveFile } = require('../helpers/libraries/serveHelpers.js');
|
||||||
|
|
||||||
|
function retrieveAssetInfo (name, claimId) {
|
||||||
|
const deferred = new Promise((resolve, reject) => {
|
||||||
|
// if claim id is full 40 chars, retrieve the shortest possible url
|
||||||
|
if (claimId.length === 40) {
|
||||||
|
resolve(serveClaimByClaimId(name, claimId));
|
||||||
|
// if the claim id is shorter than 40, retrieve the full claim id & shortest possible url
|
||||||
|
} else if (claimId.length < 40) {
|
||||||
|
resolve(serveClaimByShortUrl(name, claimId));
|
||||||
|
} else {
|
||||||
|
reject(new Error('That Claim Id is longer than 40 characters.'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
// route to serve a specific asset
|
// 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) => {
|
||||||
// google analytics
|
// google analytics
|
||||||
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
sendGoogleAnalytics('serve', headers, ip, originalUrl);
|
||||||
// begin image-serve processes
|
// begin image-serve processes
|
||||||
getClaimByClaimId(params.name, params.claim_id)
|
retrieveAssetInfo(params.name, params.claim_id)
|
||||||
.then(fileInfo => {
|
.then((fileInfo) => {
|
||||||
logger.debug('file info:', 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;
|
||||||
}
|
}
|
||||||
// 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');
|
||||||
|
@ -42,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) {
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
|
||||||
const { getClaimByClaimId, 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 retrieveAssetInfo (name, claimId) {
|
||||||
|
const deferred = new Promise((resolve, reject) => {
|
||||||
|
// if claim id is full 40 chars, retrieve the shortest possible url
|
||||||
|
if (claimId.length === 40) {
|
||||||
|
resolve(showClaimByClaimId(name, claimId));
|
||||||
|
// if the claim id is shorter than 40, retrieve the full claim id & shortest possible url
|
||||||
|
} else if (claimId.length < 40) {
|
||||||
|
resolve(showClaimByShortUrl(name, claimId));
|
||||||
|
} else {
|
||||||
|
reject(new Error('That Claim Id is longer than 40 characters.'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
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) => {
|
||||||
|
@ -34,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');
|
||||||
|
@ -65,8 +68,9 @@ 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
|
||||||
getClaimByClaimId(params.name, params.claim_id)
|
retrieveAssetInfo(params.name, params.claim_id)
|
||||||
.then(fileInfo => {
|
.then((fileInfo) => {
|
||||||
|
console.log('SHORT URL:', fileInfo.shortUrl);
|
||||||
// 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');
|
||||||
|
@ -77,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) {
|
||||||
|
@ -95,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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
|
|
@ -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}}/{{firstCharacter fileInfo.claimId}}">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}}/{{firstCharacter fileInfo.claimId}}" 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}}/{{firstCharacter fileInfo.claimId}}">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}}/{{firstCharacter fileInfo.claimId}}"/>
|
<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">
|
||||||
|
|
|
@ -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>
|
|
|
@ -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>
|
|
Loading…
Reference in a new issue
Technically two claims could have the same height, though this is rather unlikely.