Development #287

Merged
bones7242 merged 58 commits from development into master 2017-12-11 20:53:02 +01:00
17 changed files with 374 additions and 388 deletions
Showing only changes of commit cda9efa800 - Show all commits

View file

@ -1,105 +1,8 @@
const lbryApi = require('../helpers/lbryApi.js');
const db = require('../models');
const logger = require('winston');
const { serveFile, showFile, showFileLite } = require('../helpers/serveHelpers.js');
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
const SERVE = 'SERVE';
const SHOW = 'SHOW';
const SHOWLITE = 'SHOWLITE';
const DEFAULT_THUMBNAIL = 'https://spee.ch/assets/img/video_thumb_default.png';
const NO_CHANNEL = 'NO_CHANNEL';
const NO_CLAIM = 'NO_CLAIM';
function checkForLocalAssetByClaimId (claimId, name) {
logger.debug(`checkForLocalAssetsByClaimId(${claimId}, ${name}`);
return new Promise((resolve, reject) => {
db.File
.findOne({where: { name, claimId }})
.then(result => {
if (result) {
resolve(result.dataValues);
} else {
resolve(null);
}
})
.catch(error => {
reject(error);
});
});
}
function addGetResultsToFileRecord (fileInfo, getResult) {
fileInfo.fileName = getResult.file_name;
fileInfo.filePath = getResult.download_path;
fileInfo.fileType = getResult.mime_type;
return fileInfo;
}
function createFileRecord ({ name, claimId, outpoint, height, address, nsfw }) {
return {
name,
claimId,
outpoint,
height,
address,
fileName: '',
filePath: '',
fileType: '',
nsfw,
};
}
function getAssetByLongClaimId (fullClaimId, name) {
logger.debug('...getting asset by claim Id...');
return new Promise((resolve, reject) => {
// 1. check locally for claim
checkForLocalAssetByClaimId(fullClaimId, name)
.then(dataValues => {
// if a result was found, return early with the result
if (dataValues) {
logger.debug('found a local file for this name and claimId');
resolve(dataValues);
return;
}
logger.debug('no local file found for this name and claimId');
// 2. if no local claim, resolve and get the claim
db.Claim
.resolveClaim(name, fullClaimId)
.then(resolveResult => {
// if no result, return early (claim doesn't exist or isn't free)
if (!resolveResult) {
resolve(NO_CLAIM);
return;
}
logger.debug('resolve result >> ', resolveResult.dataValues);
let fileRecord = {};
// get the claim
lbryApi.getClaim(`${name}#${fullClaimId}`)
.then(getResult => {
logger.debug('getResult >>', getResult);
fileRecord = createFileRecord(resolveResult);
fileRecord = addGetResultsToFileRecord(fileRecord, getResult);
// insert a record in the File table & Update Claim table
return db.File.create(fileRecord);
})
.then(() => {
logger.debug('File record successfully updated');
resolve(fileRecord);
})
.catch(error => {
reject(error);
});
})
.catch(error => {
reject(error);
});
})
.catch(error => {
reject(error);
});
});
}
function chooseThumbnail (claimInfo, defaultThumbnail) {
if (!claimInfo.thumbnail || claimInfo.thumbnail.trim() === '') {
@ -109,42 +12,38 @@ function chooseThumbnail (claimInfo, defaultThumbnail) {
}
module.exports = {
getAssetByClaim (claimName, claimId) {
logger.debug(`getAssetByClaim(${claimName}, ${claimId})`);
return new Promise((resolve, reject) => {
db.Claim.getLongClaimId(claimName, claimId) // 1. get the long claim id
.then(result => { // 2. get the asset using the long claim id
logger.debug('long claim id ===', result);
if (result === NO_CLAIM) {
logger.debug('resolving NO_CLAIM');
resolve(NO_CLAIM);
return;
getClaimId (channelName, channelId, name, claimId) {
if (channelName) {
return module.exports.getClaimIdByChannel(channelName, channelId, name);
} else {
return module.exports.getClaimIdByClaim(name, claimId);
}
resolve(getAssetByLongClaimId(result, claimName));
},
getClaimIdByClaim (claimName, claimId) {
logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`);
return new Promise((resolve, reject) => {
db.Claim.getLongClaimId(claimName, claimId) // get the long claim id
.then(result => {
resolve(result); // resolves with NO_CLAIM or valid claim id
})
.catch(error => {
reject(error);
});
});
},
getAssetByChannel (channelName, channelId, claimName) {
logger.debug('getting asset by channel');
getClaimIdByChannel (channelName, channelId, claimName) {
logger.debug(`getClaimIdByChannel(${channelName}, ${channelId}, ${claimName})`);
return new Promise((resolve, reject) => {
db.Certificate.getLongChannelId(channelName, channelId) // 1. get the long channel id
.then(result => { // 2. get the long claim Id
.then(result => {
if (result === NO_CHANNEL) {
resolve(NO_CHANNEL);
resolve(result); // resolves NO_CHANNEL
return;
}
return db.Claim.getClaimIdByLongChannelId(result, claimName);
return db.Claim.getClaimIdByLongChannelId(result, claimName); // 2. get the long claim id
})
.then(result => { // 3. get the asset using the long claim id
logger.debug('asset claim id =', result);
if (result === NO_CHANNEL || result === NO_CLAIM) {
resolve(result);
return;
}
resolve(getAssetByLongClaimId(result, claimName));
.then(result => {
resolve(result); // resolves with NO_CLAIM or valid claim id
})
.catch(error => {
reject(error);
@ -172,7 +71,7 @@ module.exports = {
})
.then(result => { // 4. add extra data not available from Claim table
if (result === NO_CHANNEL) {
resolve(NO_CHANNEL);
resolve(result);
return;
}
if (result) {
@ -197,57 +96,23 @@ module.exports = {
});
});
},
serveOrShowAsset (fileInfo, extension, method, headers, originalUrl, ip, res) {
// add file extension to the file info
if (extension === 'gifv') {
fileInfo['fileExt'] = 'gifv';
} else {
fileInfo['fileExt'] = fileInfo.fileName.substring(fileInfo.fileName.lastIndexOf('.') + 1);
getLocalFileRecord (claimId, name) {
return db.File.findOne({where: {claimId, name}})
.then(file => {
if (!file) {
return null;
}
// add a record to the stats table
postToStats(method, originalUrl, ip, fileInfo.name, fileInfo.claimId, 'success');
// serve or show
switch (method) {
case SERVE:
serveFile(fileInfo, res);
sendGoogleAnalytics(method, headers, ip, originalUrl);
return fileInfo;
case SHOWLITE:
return db.Claim.resolveClaim(fileInfo.name, fileInfo.claimId)
.then(claimRecord => {
fileInfo['title'] = claimRecord.title;
fileInfo['description'] = claimRecord.description;
showFileLite(fileInfo, res);
return fileInfo;
})
.catch(error => {
logger.error('throwing serverOrShowAsset SHOWLITE error...');
throw error;
return file.dataValues;
});
case SHOW:
return db.Claim
.getShortClaimIdFromLongClaimId(fileInfo.claimId, fileInfo.name)
.then(shortId => {
fileInfo['shortId'] = shortId;
return db.Claim.resolveClaim(fileInfo.name, fileInfo.claimId);
})
.then(resolveResult => {
logger.debug('resolve result >>', resolveResult.dataValues);
fileInfo['thumbnail'] = chooseThumbnail(resolveResult, DEFAULT_THUMBNAIL);
fileInfo['title'] = resolveResult.title;
fileInfo['description'] = resolveResult.description;
if (resolveResult.certificateId) { fileInfo['certificateId'] = resolveResult.certificateId };
if (resolveResult.channelName) { fileInfo['channelName'] = resolveResult.channelName };
showFile(fileInfo, res);
return fileInfo;
})
.catch(error => {
logger.error('throwing serverOrShowAsset SHOW error...');
throw error;
});
default:
logger.error('I did not recognize that method');
break;
},
getClaimRecord (claimId, name) {
return db.Claim.findOne({where: {claimId, name}})
.then(claim => {
if (!claim) {
throw new Error('no record found in Claim table');
}
claim.dataValues.thumbnail = chooseThumbnail(claim.dataValues.thumbnail, DEFAULT_THUMBNAIL);
return claim.dataValues;
});
},
};

View file

@ -13,10 +13,10 @@ module.exports = {
return new Handlebars.SafeString(gaCode);
},
addOpenGraph (title, mimeType, showUrl, source, description, thumbnail) {
if (title === null || title.trim() === '') {
if (!title || title.trim() === '') {
title = 'Spee.ch';
}
if (description === null || description.trim() === '') {
if (!description || description.trim() === '') {
description = 'Open-source, decentralized image and video sharing.';
}
const ogTitle = `<meta property="og:title" content="${title}" >`;

View file

@ -1,6 +1,10 @@
const logger = require('winston');
const SERVE = 'SERVE';
const SHOW = 'SHOW';
const SHOWLITE = 'SHOWLITE';
// const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
function createOpenGraphInfo ({ fileType, claimId, name, fileName, fileExt }) {
function createOpenGraphInfo ({ claimId, name, fileExt }) {
return {
embedUrl : `https://spee.ch/embed/${claimId}/${name}`,
showUrl : `https://spee.ch/${claimId}/${name}`,
@ -10,36 +14,50 @@ function createOpenGraphInfo ({ fileType, claimId, name, fileName, fileExt }) {
}
module.exports = {
serveFile ({ fileName, fileType, filePath }, res) {
logger.verbose(`serving file ${fileName}`);
// set default options
let options = {
headers: {
'X-Content-Type-Options': 'nosniff',
'Content-Type' : fileType,
},
};
// adjust default options as needed
switch (fileType) {
case 'image/jpeg':
case 'image/gif':
case 'image/png':
case 'video/mp4':
break;
serveOrShowAsset (method, fileInfo, claimInfo, shortId, res) {
// add file extension to the file info
claimInfo['fileExt'] = fileInfo.fileName.substring(fileInfo.fileName.lastIndexOf('.') + 1);
// serve or show
switch (method) {
case SERVE:
module.exports.serveFile(fileInfo, claimInfo, shortId, res);
return fileInfo;
case SHOWLITE:
module.exports.showFileLite(fileInfo, claimInfo, shortId, res);
return fileInfo;
case SHOW:
module.exports.showFile(fileInfo, claimInfo, shortId, res);
return fileInfo;
default:
logger.warn('sending file with unknown type as .jpeg');
options['headers']['Content-Type'] = 'image/jpeg';
logger.error('I did not recognize that method');
break;
}
},
serveFile ({ filePath }, { claimId, name, contentType }, shortId, res) {
logger.verbose(`serving ${name}#${claimId}`);
// set response options
const headerContentType = contentType || 'image/jpeg';
const options = {
headers: {
'X-Content-Type-Options': 'nosniff',
'Content-Type' : headerContentType,
},
};
// send the file
if (filePath) {
res.status(200).sendFile(filePath, options);
} else {
// 'get' the file
// send the file
res.status(307).redirect(`/api/get/${name}/${claimId}`);
}
},
showFile (fileInfo, res) {
const openGraphInfo = createOpenGraphInfo(fileInfo);
res.status(200).render('show', { layout: 'show', fileInfo, openGraphInfo });
showFile (fileInfo, claimInfo, shortId, res) {
const openGraphInfo = createOpenGraphInfo(claimInfo);
res.status(200).render('show', { layout: 'show', claimInfo, shortId, openGraphInfo });
},
showFileLite (fileInfo, res) {
const openGraphInfo = createOpenGraphInfo(fileInfo);
res.status(200).render('showLite', { layout: 'showlite', fileInfo, openGraphInfo });
showFileLite (fileInfo, claimInfo, shortId, res) {
const openGraphInfo = createOpenGraphInfo(claimInfo);
res.status(200).render('showLite', { layout: 'showlite', claimInfo, shortId, openGraphInfo });
},
};

View file

@ -171,10 +171,32 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
});
};
Certificate.validateLongChannelId = function (name, claimId) {
return new Promise((resolve, reject) => {
this.findOne({
where: {name, claimId},
})
.then(result => {
switch (result.length) {
case 0:
return resolve(NO_CHANNEL);
case 1:
return resolve(result[0]);
default:
logger.warn(`more than one entry matches that name (${name}) and certificate Id (${claimId})`);
return resolve(result[0]);
}
})
.catch(error => {
reject(error);
});
});
};
Certificate.getLongChannelId = function (channelName, channelId) {
logger.debug(`getLongChannelId(${channelName}, ${channelId})`);
if (channelId && (channelId.length === 40)) { // if a full channel id is provided
return new Promise((resolve, reject) => resolve(channelId));
return this.validateLongChannelId(channelName, channelId);
} else if (channelId && channelId.length < 40) { // if a short channel id is provided
return this.getLongChannelIdFromShortChannelId(channelName, channelId);
} else {

View file

@ -274,10 +274,34 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
});
};
Claim.validateLongClaimId = function (name, claimId) {
return new Promise((resolve, reject) => {
this.findOne({
where: {name, claimId},
})
.then(result => {
// logger.debug('validateLongClaimId result:', result.dataValues);
logger.debug('validateLongClaimId result.length:', result.dataValues.length);
switch (result.dataValues.length) {
case 0:
return resolve(NO_CLAIM);
case 1:
return resolve(claimId);
default:
logger.warn(`more than one entry matches that name (${name}) and claimID (${claimId})`);
return resolve(claimId);
}
})
.catch(error => {
reject(error);
});
});
};
Claim.getLongClaimId = function (claimName, claimId) {
logger.debug(`getLongClaimId(${claimName}, ${claimId})`);
if (claimId && (claimId.length === 40)) { // if a full claim id is provided
return new Promise((resolve, reject) => resolve(claimId));
return this.validateLongClaimId(claimName, claimId);
} else if (claimId && claimId.length < 40) {
return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided
} else {

View file

@ -10,6 +10,77 @@ const errorHandlers = require('../helpers/errorHandlers.js');
const { postToStats } = require('../controllers/statsController.js');
const { authenticateOrSkip } = require('../auth/authentication.js');
function addGetResultsToFileRecord (fileInfo, getResult) {
fileInfo.fileName = getResult.file_name;
fileInfo.filePath = getResult.download_path;
return fileInfo;
}
function createFileRecord ({ name, claimId, outpoint, height, address, nsfw, contentType }) {
return {
name,
claimId,
outpoint,
height,
address,
fileName: '',
filePath: '',
fileType: contentType,
nsfw,
};
}
// function getAssetByLongClaimId (fullClaimId, name) {
// logger.debug('...getting asset by claim Id...');
// return new Promise((resolve, reject) => {
// // 1. check locally for claim
// checkForLocalAssetByClaimId(fullClaimId, name)
// .then(dataValues => {
// // if a result was found, return early with the result
// if (dataValues) {
// logger.debug('found a local file for this name and claimId');
// resolve(dataValues);
// return;
// }
// logger.debug('no local file found for this name and claimId');
// // 2. if no local claim, resolve and get the claim
// db.Claim
// .resolveClaim(name, fullClaimId)
// .then(resolveResult => {
// // if no result, return early (claim doesn't exist or isn't free)
// if (!resolveResult) {
// resolve(NO_CLAIM);
// return;
// }
// logger.debug('resolve result >> ', resolveResult.dataValues);
// let fileRecord = {};
// // get the claim
// lbryApi.getClaim(`${name}#${fullClaimId}`)
// .then(getResult => {
// logger.debug('getResult >>', getResult);
// fileRecord = createFileRecord(resolveResult);
// fileRecord = addGetResultsToFileRecord(fileRecord, getResult);
// // insert a record in the File table & Update Claim table
// return db.File.create(fileRecord);
// })
// .then(() => {
// logger.debug('File record successfully updated');
// resolve(fileRecord);
// })
// .catch(error => {
// reject(error);
// });
// })
// .catch(error => {
// reject(error);
// });
// })
// .catch(error => {
// reject(error);
// });
// });
// }
module.exports = (app) => {
// route to run a claim_list request on the daemon
app.get('/api/claim_list/:name', ({ ip, originalUrl, params }, res) => {
@ -27,9 +98,26 @@ module.exports = (app) => {
if (!params.name || !params.claimId) {
res.status(400).json({success: false, message: 'provide a claimId and/or a name'});
}
getClaim(`${params.name}#${params.claimId}`)
.then(result => {
res.status(200).json({status: 'success', message: result});
let fileRecord;
// 1. resolve the claim
db.Claim.resolveClaim(params.name, params.claimId)
.then(resolveResult => {
if (!resolveResult) {
throw new Error('No matching uri found in Claim table');
}
fileRecord = createFileRecord(resolveResult);
// 2. get the claim
return getClaim(`${params.name}#${params.claimId}`);
})
.then(getResult => {
res.status(200).json({status: 'success', message: getResult});
logger.debug('response was sent to the client');
fileRecord = addGetResultsToFileRecord(fileRecord, getResult);
// 3. insert a record for the claim into the File table
return db.File.create(fileRecord);
})
.then(() => {
logger.debug('File record successfully created');
})
.catch(error => {
errorHandlers.handleApiError('get', originalUrl, ip, error, res);

View file

@ -1,12 +1,14 @@
const logger = require('winston');
const { getAssetByClaim, getChannelContents, getAssetByChannel, serveOrShowAsset } = require('../controllers/serveController.js');
const { getClaimId, getChannelContents, getLocalFileRecord, getClaimRecord } = require('../controllers/serveController.js');
const { serveOrShowAsset } = require('../helpers/serveHelpers.js');
const { handleRequestError } = require('../helpers/errorHandlers.js');
const db = require('../models');
const SERVE = 'SERVE';
const SHOW = 'SHOW';
const SHOWLITE = 'SHOWLITE';
const CHANNEL = 'CHANNEL';
const CLAIM = 'CLAIM';
// const CHANNEL = 'CHANNEL';
// const CLAIM = 'CLAIM';
const CLAIM_ID_CHAR = ':';
const CHANNEL_CHAR = '@';
const CLAIMS_PER_PAGE = 10;
@ -25,17 +27,6 @@ function isValidShortIdOrClaimId (input) {
return (isValidClaimId(input) || isValidShortId(input));
}
function getAsset (claimType, channelName, channelId, name, claimId) {
switch (claimType) {
case CHANNEL:
return getAssetByChannel(channelName, channelId, name);
case CLAIM:
return getAssetByClaim(name, claimId);
default:
return new Error('that claim type was not found');
}
}
function getPage (query) {
if (query.p) {
return parseInt(query.p);
@ -86,7 +77,6 @@ module.exports = (app) => {
app.get('/:identifier/:name', ({ headers, ip, originalUrl, params }, res) => {
let identifier = params.identifier;
let name = params.name;
let claimOrChannel;
let channelName = null;
let claimId = null;
let channelId = null;
@ -123,7 +113,6 @@ module.exports = (app) => {
// parse identifier for whether it is a channel, short url, or claim_id
if (identifier.charAt(0) === '@') {
channelName = identifier;
claimOrChannel = CHANNEL;
const channelIdIndex = channelName.indexOf(CLAIM_ID_CHAR);
if (channelIdIndex !== -1) {
channelId = channelName.substring(channelIdIndex + 1);
@ -133,13 +122,11 @@ module.exports = (app) => {
} else {
claimId = identifier;
logger.debug('claim id =', claimId);
claimOrChannel = CLAIM;
}
// 1. retrieve the asset and information
getAsset(claimOrChannel, channelName, channelId, name, claimId)
// 2. serve or show
// get the claim id
getClaimId(channelName, channelId, name, claimId)
.then(result => {
logger.debug('getAsset result:', result);
logger.debug('getClaimId result:', result);
if (result === NO_CLAIM) {
res.status(200).render('noClaim');
return;
@ -147,7 +134,15 @@ module.exports = (app) => {
res.status(200).render('noChannel');
return;
}
return serveOrShowAsset(result, fileExtension, method, headers, originalUrl, ip, res);
// check for local file info and resolve the claim
return Promise.all([getLocalFileRecord(result, name), getClaimRecord(result, name), db.Claim.getShortClaimIdFromLongClaimId(result, name)]);
})
.then(([fileInfo, claimInfo, shortClaimId]) => {
logger.debug(`file record:`, fileInfo);
logger.debug('claim record:', claimInfo);
logger.debug('short url:', shortClaimId);
// serve or show
return serveOrShowAsset(method, fileInfo, claimInfo, shortClaimId, res);
})
// 3. update the file
.then(fileInfoForUpdate => {
@ -229,18 +224,28 @@ module.exports = (app) => {
}
logger.debug('claim name = ', name);
logger.debug('method =', method);
// 1. retrieve the asset and information
getAsset(CLAIM, null, null, name, null)
// 2. respond to the request
// get the claim id
getClaimId(null, null, name, null)
.then(result => {
logger.debug('getAsset result', result);
logger.debug('getClaimId result:', result);
if (result === NO_CLAIM) {
res.status(200).render('noClaim');
} else {
return serveOrShowAsset(result, fileExtension, method, headers, originalUrl, ip, res);
return;
} else if (result === NO_CHANNEL) {
res.status(200).render('noChannel');
return;
}
// check for local file info and resolve the claim
return Promise.all([getLocalFileRecord(result, name), getClaimRecord(result, name), db.Claim.getShortClaimIdFromLongClaimId(result, name)]);
})
// 3. update the database
.then(([fileInfo, claimInfo, shortClaimId]) => {
logger.debug(`fileInfo:`, fileInfo);
logger.debug('claimInfo:', claimInfo);
logger.debug('shortClaimId:', shortClaimId);
// serve or show
return serveOrShowAsset(method, fileInfo, claimInfo, shortClaimId, res);
})
// 3. update the file
.then(fileInfoForUpdate => {
// if needed, this is where we would update the file
})

View file

@ -9,9 +9,9 @@
<link rel="stylesheet" href="/assets/css/general.css" type="text/css">
<link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">
<meta property="fb:app_id" content="1371961932852223">
{{#unless fileInfo.nsfw}}
{{{addTwitterCard fileInfo.fileType openGraphInfo.source openGraphInfo.embedUrl openGraphInfo.directFileUrl}}}
{{{addOpenGraph fileInfo.title fileInfo.fileType openGraphInfo.showUrl openGraphInfo.source fileInfo.description fileInfo.thumbnail}}}
{{#unless claimInfo.nsfw}}
{{{addTwitterCard claimInfo.contentType openGraphInfo.source openGraphInfo.embedUrl openGraphInfo.directFileUrl}}}
{{{addOpenGraph claimInfo.title claimInfo.contentType openGraphInfo.showUrl openGraphInfo.source claimInfo.description claimInfo.thumbnail}}}
{{/unless}}
<!--google font-->
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">

View file

@ -9,9 +9,9 @@
<link rel="stylesheet" href="/assets/css/general.css" type="text/css">
<link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">
<meta property="fb:app_id" content="1371961932852223">
{{#unless fileInfo.nsfw}}
{{{addTwitterCard fileInfo.fileType openGraphInfo.source openGraphInfo.embedUrl openGraphInfo.directFileUrl}}}
{{{addOpenGraph fileInfo.title fileInfo.fileType openGraphInfo.showUrl openGraphInfo.source fileInfo.description fileInfo.thumbnail}}}
{{#unless claimInfo.nsfw}}
{{{addTwitterCard claimInfo.contentType openGraphInfo.source openGraphInfo.embedUrl openGraphInfo.directFileUrl}}}
{{{addOpenGraph claimInfo.title claimInfo.contentType openGraphInfo.showUrl openGraphInfo.source claimInfo.description claimInfo.thumbnail}}}
{{/unless}}
<!-- google analytics -->
{{ googleAnalytics }}

View file

@ -1,14 +1,13 @@
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
{{#ifConditional fileInfo.fileExt '===' 'gifv'}}
{{#ifConditional claimInfo.contentType '===' 'video/mp4'}}
{{#ifConditional claimInfo.fileExt '===' 'gifv'}}
<video class="gifv-show" autoplay loop muted>
<source src="/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}">
<source src="/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}">
{{!--fallback--}}
Your browser does not support the <code>video</code> element.
</video>
{{else}}
<video id="video-player" class="video-show video" controls poster="{{fileInfo.thumbnail}}">
<source src="/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}">
<video id="video-player" class="video-show video" controls poster="{{claimInfo.thumbnail}}">
<source src="/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}">
{{!--fallback--}}
Your browser does not support the <code>video</code> element.
</video>
@ -23,7 +22,63 @@
</script>
{{/ifConditional}}
{{else}}
<a href="/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}">
<img class="image-show" src="/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}" />
<a href="/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}">
<img class="image-show" src="/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}" />
</a>
{{/ifConditional}}
<div id="asset-holder">
<div id="search-message" hidden="true">
<p>We're currently combing the blockchain for your asset!</p>
</div>
<div id="failure-message" hidden="true">
<p>Hmmm, looks like no peers have your content. How anti-social!</p>
</div>
<div id="asset" hidden="true">
</div>
</div>
<script type="text/javascript">
const getAssetFunctions = {
showAsset: function () {
const searchMessage = document.getElementById('search-message');
const asset = document.getElementById('asset');
searchMessage.hidden = true;
asset.hidden = false;
},
showFailureMessage: function (msg) {
console.log(msg);
const searchMessage = document.getElementById('search-message');
const failureMessage = document.getElementById('failure-message');
searchMessage.hidden = true;
failureMessage.hidden = false;
},
displayAsset: function(contentType, source) {
},
getAsset: function(claimName, claimId) {
console.log(`getting ${claimName}#${claimId}}`)
var uri = `/api/get/${claimName}/${claimId}`;
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log('get returned successfully', xhr.response);
this.showAsset();
} else {
console.log('get failed:', xhr.response);
}
} else {
console.log('xhr.readyState', xhr.readyState);
this.showFailureMessage(xhr.readyState.message);
}
};
// Initiate a multipart/form-data upload
xhr.send();
},
}
</script>

View file

@ -1,28 +1,28 @@
{{#if fileInfo.channelName}}
{{#if claimInfo.channelName}}
<div class="row row--padded row--wide row--no-top">
<div class="column column--2 column--med-10">
<span class="text">Channel:</span>
</div><div class="column column--8 column--med-10">
<span class="text"><a href="/{{fileInfo.channelName}}:{{fileInfo.certificateId}}">{{fileInfo.channelName}}</a></span>
<span class="text"><a href="/{{claimInfo.channelName}}:{{claimInfo.certificateId}}">{{claimInfo.channelName}}</a></span>
</div>
</div>
{{/if}}
{{#if fileInfo.description}}
{{#if claimInfo.description}}
<div class="row row--padded row--wide row--no-top">
<span class="text">{{fileInfo.description}}</span>
<span class="text">{{claimInfo.description}}</span>
</div>
{{/if}}
<div class="row row--wide">
<div id="show-short-link">
<div class="column column--2 column--med-10">
<a class="link--primary" href="/{{fileInfo.shortId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}"><span class="text">Link:</span></a>
<a class="link--primary" href="/{{shortId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}"><span class="text">Link:</span></a>
</div><div class="column column--8 column--med-10">
<div class="row row--short row--wide">
<div class="column column--7">
<div class="input-error" id="input-error-copy-short-link" hidden="true"></div>
<input type="text" id="short-link" class="input-disabled input-text--full-width" readonly spellcheck="false" value="https://spee.ch/{{fileInfo.shortId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}" onclick="select()"/>
<input type="text" id="short-link" class="input-disabled input-text--full-width" readonly spellcheck="false" value="https://spee.ch/{{shortId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}" onclick="select()"/>
</div><div class="column column--1"></div><div class="column column--2">
<button class="button--primary" data-elementtocopy="short-link" onclick="copyToClipboard(event)">copy</button>
</div>
@ -36,10 +36,10 @@
<div class="row row--short row--wide">
<div class="column column--7">
<div class="input-error" id="input-error-copy-embed-text" hidden="true"></div>
{{#ifConditional fileInfo.fileType '===' 'video/mp4'}}
<input type="text" id="embed-text" class="input-disabled input-text--full-width" readonly onclick="select()" spellcheck="false" value='&lt;video width="100%" controls poster="{{fileInfo.thumbnail}}" src="https://spee.ch/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}"/>&lt;/video>'/>
{{#ifConditional claimInfo.contentType '===' 'video/mp4'}}
<input type="text" id="embed-text" class="input-disabled input-text--full-width" readonly onclick="select()" spellcheck="false" value='&lt;video width="100%" controls poster="{{claimInfo.thumbnail}}" src="https://spee.ch/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}"/>&lt;/video>'/>
{{else}}
<input type="text" id="embed-text" class="input-disabled input-text--full-width" readonly onclick="select()" spellcheck="false" value='&lt;img src="https://spee.ch/{{fileInfo.claimId}}/{{fileInfo.name}}.{{fileInfo.fileExt}}"/>'/>
<input type="text" id="embed-text" class="input-disabled input-text--full-width" readonly onclick="select()" spellcheck="false" value='&lt;img src="https://spee.ch/{{claimInfo.claimId}}/{{claimInfo.name}}.{{claimInfo.fileExt}}"/>'/>
{{/ifConditional}}
</div><div class="column column--1"></div><div class="column column--2">
<button class="button--primary" data-elementtocopy="embed-text" onclick="copyToClipboard(event)">copy</button>
@ -55,10 +55,10 @@
<span class="text">Share:</span>
</div><div class="column column--7 column--med-10">
<div class="row row--short row--wide flex-container--row flex-container--space-between-bottom flex-container--wrap">
<a class="link--primary" target="_blank" href="https://twitter.com/intent/tweet?text=https://spee.ch/{{fileInfo.shortId}}/{{fileInfo.name}}">twitter</a>
<a class="link--primary" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://spee.ch/{{fileInfo.shortId}}/{{fileInfo.name}}">facebook</a>
<a class="link--primary" target="_blank" href="http://tumblr.com/widgets/share/tool?canonicalUrl=https://spee.ch/{{fileInfo.shortId}}/{{fileInfo.name}}">tumblr</a>
<a class="link--primary" target="_blank" href="https://www.reddit.com/submit?url=https://spee.ch/{{fileInfo.shortId}}/{{fileInfo.name}}&title={{fileInfo.name}}">reddit</a>
<a class="link--primary" target="_blank" href="https://twitter.com/intent/tweet?text=https://spee.ch/{{shortId}}/{{claimInfo.name}}">twitter</a>
<a class="link--primary" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://spee.ch/{{shortId}}/{{claimInfo.name}}">facebook</a>
<a class="link--primary" target="_blank" href="http://tumblr.com/widgets/share/tool?canonicalUrl=https://spee.ch/{{shortId}}/{{claimInfo.name}}">tumblr</a>
<a class="link--primary" target="_blank" href="https://www.reddit.com/submit?url=https://spee.ch/{{shortId}}/{{claimInfo.name}}&title={{claimInfo.name}}">reddit</a>
</div>
</div>
</div>
@ -73,29 +73,29 @@
<div class="column column--2 column--med-10">
<span class="text">Name:</span>
</div><div class="column column--8 column--med-10">
{{fileInfo.name}}
{{claimInfo.name}}
</div>
</div>
<div id="show-claim-id">
<div class="column column--2 column--med-10">
<span class="text">Claim Id:</span>
</div><div class="column column--8 column--med-10">
{{fileInfo.claimId}}
{{claimInfo.claimId}}
</div>
</div>
<div id="show-claim-id">
<div class="column column--2 column--med-10">
<span class="text">File Name:</span>
</div><div class="column column--8 column--med-10">
{{fileInfo.fileName}}
{{claimInfo.fileName}}
</div>
</div>
<div id="show-claim-id">
<div class="column column--2 column--med-10">
<span class="text">File Type:</span>
</div><div class="column column--8 column--med-10">
{{#if fileInfo.fileType}}
{{fileInfo.fileType}}
{{#if claimInfo.contentType}}
{{claimInfo.contentType}}
{{else}}
unknown
{{/if}}

View file

@ -1,91 +0,0 @@
<div id="asset-holder">
<div id="peer-info">
<p id="peer-search-placeholder">Searching for peers for this asset...</p>
<p id="peer-search-success" hidden="true">Number of peers with content:<span id="peer-number">?</span></p>
<p id="peer-search-failure" hidden="true">Unfortunately, no peers could be located with that asset</p>
</div>
<div id="asset">
<div id="video-display" hidden="true">
</div>
<div id="gifv-display" hidden="true">
</div>
<div id="gif-display" hidden="true">
</div>
<div id="static-image-display" hidden="true">
</div>
</div>
</div>
<script type="text/javascript">
const getAssetFunctions = {
showPeerListSuccess: function (numberOfPeers) {
const peerSearchPlaceholder = document.getElementById('peer-search-placeholder');
const peerSearchSuccess = document.getElementById('peer-search-success');
const peerSearchNumber = document.getElementById('peer-search-number');
peerSearchPlaceholder.hidden = true;
peerSearchSuccess.hidden = false;
peerSearchNumber.innerText = numberOfPeers;
},
showPeerListFailure: function () {
const peerSearchPlaceholder = document.getElementById('peer-search-placeholder');
const peerSearchFailure = document.getElementById('peer-search-failure');
peerSearchPlaceholder.hidden = true;
peerSearchFailure.hidden = false;
},
showAsset: function (claimName, claimId) {
},
showFailureMessage: function (msg) {
console.log(msg);
},
getAsset: function(claimName, claimId) {
console.log(`getting ${claimName}#${claimId}}`)
var uri = `/api/get/${claimName}/${claimId}`;
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log('get returned successfully')
this.showAsset(claimName, claimId);
} else {
console.log('get failed:', xhr.response);
}
} else {
console.log('xhr.readyState', xhr.readyState);
this.showFailureMessage(xhr.readyState.message);
}
};
// Initiate a multipart/form-data upload
xhr.send();
},
getPeerList: function(claimName, claimId) {
var uri = `/api/peer_list/${claimName}/${claimId}`;
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log('peer list retrieved:', JSON.parse(xhr.response).message);
this.showPeerListSuccess(JSON.parse(xhr.response).message);
this.getAsset(claimName, claimId);
} else {
console.log(xhr.response);
console.log('unfortunately no peers could be found');
this.showPeerListFailure(JSON.parse(xhr.response).message);
}
} else {
console.log('xhr.readyState', xhr.readyState);
}
};
// Initiate a multipart/form-data upload
xhr.send();
}
}
getAssetFunctions.getPeerList({{fileInfo.claimName}}, {{fileInfo.claimId}})
</script>

View file

@ -1,12 +1,12 @@
<div class="row row--tall row--padded">
<div class="column column--10">
<!-- title -->
<span class="text--large">{{fileInfo.title}}</span>
<span class="text--large">{{claimInfo.title}}</span>
</div>
<div class="column column--5 column--sml-10 align-content-top">
<!-- asset -->
<div class="row row--padded">
{{> getAsset}}
{{> asset}}
</div>
</div><div class="column column--5 column--sml-10 align-content-top">
<!-- details -->

View file

@ -1,7 +1,7 @@
<div class="row row--tall row--padded">
<div class="column column--10">
<!-- title -->
<span class="text--large">{{fileInfo.title}}</span>
<span class="text--large">{{claimInfo.title}}</span>
</div>
<div class="column column--5 column--sml-10 align-content-top">
<!-- asset -->

View file

@ -1,2 +0,0 @@
{{> getAsset }}
<a class="link--primary fine-print" href="/{{fileInfo.claimId}}/{{fileInfo.name}}">hosted via spee&lt;h</a>

View file

@ -0,0 +1,2 @@
{{> asset }}
<a class="link--primary fine-print" href="/{{claimInfo.claimId}}/{{claimInfo.name}}">hosted via spee&lt;h</a>

View file

@ -1,2 +1,2 @@
{{> asset }}
<a class="link--primary fine-print" href="/{{fileInfo.claimId}}/{{fileInfo.name}}">hosted via spee&lt;h</a>
<a class="link--primary fine-print" href="/{{claimInfo.claimId}}/{{claimInfo.name}}">hosted via spee&lt;h</a>