Merge pull request #492 from lbryio/465-social-share-with-extensions
465 social share with extensions
This commit is contained in:
commit
536dfc9ccd
14 changed files with 141 additions and 80 deletions
|
@ -101,9 +101,9 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) {
|
|||
defaultThumbnail = _ref3.defaultThumbnail;
|
||||
var claimData = asset.claimData;
|
||||
var contentType = claimData.contentType;
|
||||
var embedUrl = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name);
|
||||
var videoEmbedUrl = "".concat(siteHost, "/video-embed/").concat(claimData.name, "/").concat(claimData.claimId);
|
||||
var showUrl = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name);
|
||||
var source = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name, ".").concat(claimData.fileExt);
|
||||
var source = "".concat(siteHost, "/asset/").concat(claimData.name, "/").concat(claimData.claimId);
|
||||
var ogTitle = claimData.title || claimData.name;
|
||||
var ogDescription = claimData.description || defaultDescription;
|
||||
var ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail);
|
||||
|
@ -154,7 +154,7 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) {
|
|||
});
|
||||
metaTags.push({
|
||||
property: 'og:type',
|
||||
content: 'video'
|
||||
content: 'video.other'
|
||||
});
|
||||
metaTags.push({
|
||||
property: 'twitter:card',
|
||||
|
@ -162,7 +162,7 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) {
|
|||
});
|
||||
metaTags.push({
|
||||
property: 'twitter:player',
|
||||
content: embedUrl
|
||||
content: videoEmbedUrl
|
||||
});
|
||||
metaTags.push({
|
||||
property: 'twitter:player:width',
|
||||
|
|
|
@ -46,9 +46,9 @@ const createChannelMetaTags = ({siteHost, siteTitle, siteTwitter, channel}) => {
|
|||
const createAssetMetaTags = ({siteHost, siteTitle, siteTwitter, asset, defaultDescription, defaultThumbnail}) => {
|
||||
const { claimData } = asset;
|
||||
const { contentType } = claimData;
|
||||
const embedUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`;
|
||||
const videoEmbedUrl = `${siteHost}/video-embed/${claimData.name}/${claimData.claimId}`;
|
||||
const showUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`;
|
||||
const source = `${siteHost}/${claimData.claimId}/${claimData.name}.${claimData.fileExt}`;
|
||||
const source = `${siteHost}/asset/${claimData.name}/${claimData.claimId}`;
|
||||
const ogTitle = claimData.title || claimData.name;
|
||||
const ogDescription = claimData.description || defaultDescription;
|
||||
const ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail);
|
||||
|
@ -68,9 +68,9 @@ const createAssetMetaTags = ({siteHost, siteTitle, siteTwitter, asset, defaultDe
|
|||
metaTags.push({property: 'og:video:type', content: contentType});
|
||||
metaTags.push({property: 'og:image', content: ogThumbnail});
|
||||
metaTags.push({property: 'og:image:type', content: ogThumbnailContentType});
|
||||
metaTags.push({property: 'og:type', content: 'video'});
|
||||
metaTags.push({property: 'og:type', content: 'video.other'});
|
||||
metaTags.push({property: 'twitter:card', content: 'player'});
|
||||
metaTags.push({property: 'twitter:player', content: embedUrl});
|
||||
metaTags.push({property: 'twitter:player', content: videoEmbedUrl});
|
||||
metaTags.push({property: 'twitter:player:width', content: 600});
|
||||
metaTags.push({property: 'twitter:text:player_width', content: 600});
|
||||
metaTags.push({property: 'twitter:player:height', content: 337});
|
||||
|
|
9
server/controllers/assets/constants/request_types.js
Normal file
9
server/controllers/assets/constants/request_types.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
const EMBED = 'EMBED';
|
||||
const BROWSER = 'BROWSER';
|
||||
const SOCIAL = 'SOCIAL';
|
||||
|
||||
module.exports = {
|
||||
EMBED,
|
||||
BROWSER,
|
||||
SOCIAL,
|
||||
};
|
17
server/controllers/assets/serveAsset/index.js
Normal file
17
server/controllers/assets/serveAsset/index.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
const { sendGAServeEvent } = require('../../../utils/googleAnalytics');
|
||||
const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js');
|
||||
|
||||
/*
|
||||
|
||||
route to serve an asset directly
|
||||
|
||||
*/
|
||||
|
||||
const serveAsset = ({ headers, ip, originalUrl, params: { claimName, claimId } }, res) => {
|
||||
// send google analytics
|
||||
sendGAServeEvent(headers, ip, originalUrl);
|
||||
// get the claim Id and then serve the asset
|
||||
getClaimIdAndServeAsset(null, null, claimName, claimId, originalUrl, ip, res);
|
||||
};
|
||||
|
||||
module.exports = serveAsset;
|
|
@ -3,11 +3,10 @@ const handleShowRender = require('../../../render/build/handleShowRender.js');
|
|||
|
||||
const lbryUri = require('../utils/lbryUri.js');
|
||||
|
||||
const determineResponseType = require('../utils/determineResponseType.js');
|
||||
const determineRequestType = require('../utils/determineRequestType.js');
|
||||
const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js');
|
||||
const logRequestData = require('../utils/logRequestData.js');
|
||||
|
||||
const SERVE = 'SERVE';
|
||||
const { EMBED } = require('../constants/request_types.js');
|
||||
|
||||
/*
|
||||
|
||||
|
@ -15,7 +14,7 @@ const SERVE = 'SERVE';
|
|||
|
||||
*/
|
||||
|
||||
const serverAssetByClaim = (req, res) => {
|
||||
const serveByClaim = (req, res) => {
|
||||
const { headers, ip, originalUrl, params } = req;
|
||||
// decide if this is a show request
|
||||
let hasFileExtension;
|
||||
|
@ -24,13 +23,11 @@ const serverAssetByClaim = (req, res) => {
|
|||
} catch (error) {
|
||||
return res.status(400).json({success: false, message: error.message});
|
||||
}
|
||||
let responseType = determineResponseType(hasFileExtension, headers);
|
||||
if (responseType !== SERVE) {
|
||||
// determine request type
|
||||
let requestType = determineRequestType(hasFileExtension, headers);
|
||||
if (requestType !== EMBED) {
|
||||
return handleShowRender(req, res);
|
||||
}
|
||||
// handle serve request
|
||||
// send google analytics
|
||||
sendGAServeEvent(headers, ip, originalUrl);
|
||||
// parse the claim
|
||||
let claimName;
|
||||
try {
|
||||
|
@ -38,10 +35,10 @@ const serverAssetByClaim = (req, res) => {
|
|||
} catch (error) {
|
||||
return res.status(400).json({success: false, message: error.message});
|
||||
}
|
||||
// log the request data for debugging
|
||||
logRequestData(responseType, claimName, null, null);
|
||||
// send google analytics
|
||||
sendGAServeEvent(headers, ip, originalUrl);
|
||||
// get the claim Id and then serve the asset
|
||||
getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);
|
||||
};
|
||||
|
||||
module.exports = serverAssetByClaim;
|
||||
module.exports = serveByClaim;
|
||||
|
|
|
@ -3,12 +3,11 @@ const handleShowRender = require('../../../render/build/handleShowRender.js');
|
|||
|
||||
const lbryUri = require('../utils/lbryUri.js');
|
||||
|
||||
const determineResponseType = require('../utils/determineResponseType.js');
|
||||
const determineRequestType = require('../utils/determineRequestType.js');
|
||||
const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js');
|
||||
const flipClaimNameAndId = require('../utils/flipClaimNameAndId.js');
|
||||
const logRequestData = require('../utils/logRequestData.js');
|
||||
|
||||
const SERVE = 'SERVE';
|
||||
const { EMBED } = require('../constants/request_types.js');
|
||||
|
||||
/*
|
||||
|
||||
|
@ -16,22 +15,20 @@ const SERVE = 'SERVE';
|
|||
|
||||
*/
|
||||
|
||||
const serverAssetByIdentifierAndClaim = (req, res) => {
|
||||
const serverByIdentifierAndClaim = (req, res) => {
|
||||
const { headers, ip, originalUrl, params } = req;
|
||||
// decide if this is a show request
|
||||
// parse request
|
||||
let hasFileExtension;
|
||||
try {
|
||||
({ hasFileExtension } = lbryUri.parseModifier(params.claim));
|
||||
} catch (error) {
|
||||
return res.status(400).json({success: false, message: error.message});
|
||||
}
|
||||
let responseType = determineResponseType(hasFileExtension, headers);
|
||||
if (responseType !== SERVE) {
|
||||
// determine request type
|
||||
let requestType = determineRequestType(hasFileExtension, headers);
|
||||
if (requestType !== EMBED) {
|
||||
return handleShowRender(req, res);
|
||||
}
|
||||
// handle serve request
|
||||
// send google analytics
|
||||
sendGAServeEvent(headers, ip, originalUrl);
|
||||
// parse the claim
|
||||
let claimName;
|
||||
try {
|
||||
|
@ -50,10 +47,10 @@ const serverAssetByIdentifierAndClaim = (req, res) => {
|
|||
if (!isChannel) {
|
||||
[claimId, claimName] = flipClaimNameAndId(claimId, claimName);
|
||||
}
|
||||
// log the request data for debugging
|
||||
logRequestData(responseType, claimName, channelName, claimId);
|
||||
// send google analytics
|
||||
sendGAServeEvent(headers, ip, originalUrl);
|
||||
// get the claim Id and then serve the asset
|
||||
getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);
|
||||
};
|
||||
|
||||
module.exports = serverAssetByIdentifierAndClaim;
|
||||
module.exports = serverByIdentifierAndClaim;
|
||||
|
|
54
server/controllers/assets/utils/determineRequestType.js
Normal file
54
server/controllers/assets/utils/determineRequestType.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
const logger = require('winston');
|
||||
const { EMBED, BROWSER, SOCIAL } = require('../constants/request_types.js');
|
||||
|
||||
function headersMatchesSocialBotList (headers) {
|
||||
const userAgent = headers['user-agent'];
|
||||
const socialBotList = {
|
||||
'facebookexternalhit': 1,
|
||||
'Twitterbot' : 1,
|
||||
};
|
||||
return socialBotList[userAgent];
|
||||
}
|
||||
|
||||
function clientAcceptsHtml ({accept}) {
|
||||
return accept && accept.match(/text\/html/);
|
||||
};
|
||||
|
||||
function requestIsFromBrowser (headers) {
|
||||
return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);
|
||||
};
|
||||
|
||||
function clientWantsAsset ({accept, range}) {
|
||||
const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/);
|
||||
const videoIsWanted = accept && range;
|
||||
return imageIsWanted || videoIsWanted;
|
||||
};
|
||||
|
||||
const determineRequestType = (hasFileExtension, headers) => {
|
||||
let responseType;
|
||||
logger.debug('headers:', headers);
|
||||
// return early with 'show' if headers match the list
|
||||
if (headersMatchesSocialBotList(headers)) {
|
||||
return SOCIAL;
|
||||
}
|
||||
// if request is not from a social bot...
|
||||
if (hasFileExtension) {
|
||||
// assume embed,
|
||||
responseType = EMBED;
|
||||
// but change to browser if client accepts html.
|
||||
if (clientAcceptsHtml(headers)) {
|
||||
responseType = BROWSER;
|
||||
}
|
||||
// if request does not have file extentsion...
|
||||
} else {
|
||||
// assume browser,
|
||||
responseType = BROWSER;
|
||||
// but change to embed if someone embeded a show url...
|
||||
if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) {
|
||||
responseType = EMBED;
|
||||
}
|
||||
}
|
||||
return responseType;
|
||||
};
|
||||
|
||||
module.exports = determineRequestType;
|
|
@ -1,37 +0,0 @@
|
|||
const logger = require('winston');
|
||||
|
||||
const SERVE = 'SERVE';
|
||||
const SHOW = 'SHOW';
|
||||
|
||||
function clientAcceptsHtml ({accept}) {
|
||||
return accept && accept.match(/text\/html/);
|
||||
};
|
||||
|
||||
function requestIsFromBrowser (headers) {
|
||||
return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);
|
||||
};
|
||||
|
||||
function clientWantsAsset ({accept, range}) {
|
||||
const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/);
|
||||
const videoIsWanted = accept && range;
|
||||
return imageIsWanted || videoIsWanted;
|
||||
};
|
||||
|
||||
const determineResponseType = (hasFileExtension, headers) => {
|
||||
let responseType;
|
||||
if (hasFileExtension) {
|
||||
responseType = SERVE; // assume a serve request if file extension is present
|
||||
if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request
|
||||
responseType = SHOW;
|
||||
}
|
||||
} else {
|
||||
responseType = SHOW;
|
||||
if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url
|
||||
logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');
|
||||
responseType = SERVE;
|
||||
}
|
||||
}
|
||||
return responseType;
|
||||
};
|
||||
|
||||
module.exports = determineResponseType;
|
|
@ -17,6 +17,7 @@ const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId
|
|||
getClaimId(channelName, channelClaimId, claimName, claimId)
|
||||
.then(fullClaimId => {
|
||||
claimId = fullClaimId;
|
||||
logger.debug('FULL CLAIM ID:', fullClaimId);
|
||||
return db.Blocked.isNotBlocked(fullClaimId, claimName);
|
||||
})
|
||||
.then(() => {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const { details: { host } } = require('@config/siteConfig');
|
||||
|
||||
const sendEmbedPage = ({ params }, res) => {
|
||||
const sendVideoEmbedPage = ({ params }, res) => {
|
||||
const claimId = params.claimId;
|
||||
const name = params.name;
|
||||
// get and render the content
|
||||
res.status(200).render('embed', { layout: 'embed', host, claimId, name });
|
||||
};
|
||||
|
||||
module.exports = sendEmbedPage;
|
||||
module.exports = sendVideoEmbedPage;
|
|
@ -29,7 +29,7 @@ module.exports = (app) => {
|
|||
app.get('/api/claim/data/:claimName/:claimId', claimData);
|
||||
app.get('/api/claim/get/:name/:claimId', claimGet);
|
||||
app.get('/api/claim/list/:name', claimList);
|
||||
app.post('/api/claim/long-id', claimLongId);
|
||||
app.post('/api/claim/long-id', claimLongId); // should be a get
|
||||
app.post('/api/claim/publish', multipartMiddleware, claimPublish);
|
||||
app.get('/api/claim/resolve/:name/:claimId', claimResolve);
|
||||
app.get('/api/claim/short-id/:longId/:name', claimShortId);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
const serveAssetByClaim = require('../../controllers/assets/serveByClaim');
|
||||
const serveAssetByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim');
|
||||
const serveByClaim = require('../../controllers/assets/serveByClaim');
|
||||
const serveByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim');
|
||||
const serveAsset = require('../../controllers/assets/serveAsset');
|
||||
|
||||
module.exports = (app, db) => {
|
||||
app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);
|
||||
app.get('/:claim', serveAssetByClaim);
|
||||
module.exports = (app) => {
|
||||
app.get('/asset/:claimName/:claimId/', serveAsset);
|
||||
app.get('/:identifier/:claim', serveByIdentifierAndClaim);
|
||||
app.get('/:claim', serveByClaim);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const handlePageRequest = require('../../controllers/pages/sendReactApp');
|
||||
const handleEmbedRequest = require('../../controllers/pages/sendEmbedPage');
|
||||
const handleVideoEmbedRequest = require('../../controllers/pages/sendVideoEmbedPage');
|
||||
const redirect = require('../../controllers/utils/redirect');
|
||||
|
||||
module.exports = (app) => {
|
||||
|
@ -10,5 +10,5 @@ module.exports = (app) => {
|
|||
app.get('/popular', handlePageRequest);
|
||||
app.get('/new', handlePageRequest);
|
||||
app.get('/multisite', handlePageRequest);
|
||||
app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)
|
||||
app.get('/video-embed/:name/:claimId', handleVideoEmbedRequest); // for twitter
|
||||
};
|
||||
|
|
21
test/test.html
Normal file
21
test/test.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<img src="https://media.giphy.com/media/vwEHGjx71HSytx5mY8/giphy-facebook_s.jpg" alt="test embed"/>
|
||||
<p>no identifier, no ending</p>
|
||||
<img src="https://dev1.spee.ch/typingcat" alt="no identifier, no ending"/>
|
||||
<p>no identifier, yes ending</p>
|
||||
<img src="https://dev1.spee.ch/typingcat.gif" alt="no identifier, yes ending"/>
|
||||
<p>yes identifier, no ending</p>
|
||||
<img src="https://dev1.spee.ch/8/typingcat" alt="yes identifier, no ending"/>
|
||||
<p>yes identifier, yes ending</p>
|
||||
<img src="https://dev1.spee.ch/8/typingcat.gif" alt="yes identifier, yes ending"/>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue