diff --git a/client/build/components/AssetPreview/index.js b/client/build/components/AssetPreview/index.js index 994b75ce..1d044764 100644 --- a/client/build/components/AssetPreview/index.js +++ b/client/build/components/AssetPreview/index.js @@ -19,10 +19,10 @@ var AssetPreview = function AssetPreview(_ref) { fileExt = _ref$claimData.fileExt, contentType = _ref$claimData.contentType, thumbnail = _ref$claimData.thumbnail; - var directSourceLink = "asset/".concat(name, "/").concat(claimId); - var showUrlLink = "/".concat(claimId, "/").concat(name); + var embedUrl = "/".concat(claimId, "/").concat(name, ".").concat(fileExt); + var showUrl = "/".concat(claimId, "/").concat(name); return _react.default.createElement(_reactRouterDom.Link, { - to: showUrlLink + to: showUrl }, function () { switch (contentType) { case 'image/jpeg': @@ -31,7 +31,7 @@ var AssetPreview = function AssetPreview(_ref) { case 'image/gif': return _react.default.createElement("img", { className: 'asset-preview-image', - src: directSourceLink, + src: embedUrl, alt: name }); diff --git a/client/build/containers/AssetDisplay/view.js b/client/build/containers/AssetDisplay/view.js index c0d1f013..d8e5620c 100644 --- a/client/build/containers/AssetDisplay/view.js +++ b/client/build/containers/AssetDisplay/view.js @@ -60,6 +60,7 @@ function (_React$Component) { contentType = _this$props$asset$cla2.contentType, fileExt = _this$props$asset$cla2.fileExt, thumbnail = _this$props$asset$cla2.thumbnail; + var sourceUrl = "/".concat(claimId, "/").concat(name, ".").concat(fileExt); return _react.default.createElement("div", { className: 'asset-display' }, status === _asset_display_states.LOCAL_CHECK && _react.default.createElement("div", null, _react.default.createElement("p", null, "Checking to see if Spee.ch has your asset locally...")), status === _asset_display_states.UNAVAILABLE && _react.default.createElement("div", null, _react.default.createElement("p", null, "Sit tight, we're searching the LBRY blockchain for your asset!"), _react.default.createElement(_ProgressBar.default, { @@ -82,7 +83,7 @@ function (_React$Component) { case 'image/gif': return _react.default.createElement("img", { className: "asset-image", - src: "/asset/".concat(name, "/").concat(claimId), + src: sourceUrl, alt: name }); @@ -92,11 +93,11 @@ function (_React$Component) { controls: true, poster: thumbnail }, _react.default.createElement("source", { - src: "/asset/".concat(name, "/").concat(claimId) + src: sourceUrl }), _react.default.createElement("p", null, "Your browser does not support the ", _react.default.createElement("code", null, "video"), " element.")); default: - return _react.default.createElement("p", null, "Unsupported file type"); + return _react.default.createElement("p", null, "Unsupported content type"); } }()); } diff --git a/client/build/containers/AssetInfo/view.js b/client/build/containers/AssetInfo/view.js index 55eefee1..8a968a42 100644 --- a/client/build/containers/AssetInfo/view.js +++ b/client/build/containers/AssetInfo/view.js @@ -89,7 +89,7 @@ function (_React$Component) { }), content: _react.default.createElement(_ClickToCopy.default, { id: 'short-link', - value: "".concat(host, "/").concat(shortId, "/").concat(name, ".").concat(fileExt) + value: "".concat(host, "/").concat(shortId, "/").concat(name) }) })), _react.default.createElement(_Row.default, null, _react.default.createElement(_RowLabeled.default, { label: _react.default.createElement(_Label.default, { @@ -102,9 +102,9 @@ function (_React$Component) { id: 'embed-text-image', value: "") })) - })), _react.default.createElement(_Row.default, null, _react.default.createElement(_SpaceBetween.default, null, _react.default.createElement(_reactRouterDom.Link, { + })), _react.default.createElement(_Row.default, null, _react.default.createElement(_SpaceBetween.default, null, _react.default.createElement("a", { className: "link--primary", - to: "/".concat(shortId, "/").concat(name, ".").concat(fileExt) + href: "".concat(host, "/").concat(claimId, "/").concat(name, ".").concat(fileExt) }, "Direct Link"), _react.default.createElement("a", { className: 'link--primary', href: "".concat(host, "/").concat(claimId, "/").concat(name, ".").concat(fileExt), diff --git a/client/build/containers/SEO/index.js b/client/build/containers/SEO/index.js index 68ed79ed..bbd3c41e 100644 --- a/client/build/containers/SEO/index.js +++ b/client/build/containers/SEO/index.js @@ -11,24 +11,6 @@ var _view = _interopRequireDefault(require("./view")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -var mapStateToProps = function mapStateToProps(_ref) { - var site = _ref.site; - var defaultDescription = site.defaultDescription, - defaultThumbnail = site.defaultThumbnail, - siteDescription = site.description, - siteHost = site.host, - siteTitle = site.title, - siteTwitter = site.twitter; - return { - defaultDescription: defaultDescription, - defaultThumbnail: defaultThumbnail, - siteDescription: siteDescription, - siteHost: siteHost, - siteTitle: siteTitle, - siteTwitter: siteTwitter - }; -}; - -var _default = (0, _reactRedux.connect)(mapStateToProps, null)(_view.default); +var _default = (0, _reactRedux.connect)(null, null)(_view.default); exports.default = _default; \ No newline at end of file diff --git a/client/build/containers/SEO/view.js b/client/build/containers/SEO/view.js index 659abd7f..16b25365 100644 --- a/client/build/containers/SEO/view.js +++ b/client/build/containers/SEO/view.js @@ -11,11 +11,11 @@ var _reactHelmet = _interopRequireDefault(require("react-helmet")); var _propTypes = _interopRequireDefault(require("prop-types")); -var _pageTitle = require("../../utils/pageTitle"); +var _createPageTitle = _interopRequireDefault(require("../../utils/createPageTitle")); -var _metaTags = require("../../utils/metaTags"); +var _createMetaTags = _interopRequireDefault(require("../../utils/createMetaTags")); -var _canonicalLink = require("../../utils/canonicalLink"); +var _createCanonicalLink = _interopRequireDefault(require("../../utils/createCanonicalLink")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -49,33 +49,19 @@ function (_React$Component) { _createClass(SEO, [{ key: "render", value: function render() { - // props from state + // props from parent var _this$props = this.props, - defaultDescription = _this$props.defaultDescription, - defaultThumbnail = _this$props.defaultThumbnail, - siteDescription = _this$props.siteDescription, - siteHost = _this$props.siteHost, - siteTitle = _this$props.siteTitle, - siteTwitter = _this$props.siteTwitter; // props from parent - - var _this$props2 = this.props, - asset = _this$props2.asset, - channel = _this$props2.channel, - pageUri = _this$props2.pageUri; + asset = _this$props.asset, + channel = _this$props.channel, + pageUri = _this$props.pageUri; var pageTitle = this.props.pageTitle; // create page title, tags, and canonical link - pageTitle = (0, _pageTitle.createPageTitle)(siteTitle, pageTitle); - var metaTags = (0, _metaTags.createMetaTags)({ - siteDescription: siteDescription, - siteHost: siteHost, - siteTitle: siteTitle, - siteTwitter: siteTwitter, + pageTitle = (0, _createPageTitle.default)(pageTitle); + var metaTags = (0, _createMetaTags.default)({ asset: asset, - channel: channel, - defaultDescription: defaultDescription, - defaultThumbnail: defaultThumbnail + channel: channel }); - var canonicalLink = (0, _canonicalLink.createCanonicalLink)(asset, channel, pageUri, siteHost); // render results + var canonicalLink = (0, _createCanonicalLink.default)(asset, channel, pageUri); // render results return _react.default.createElement(_reactHelmet.default, { title: pageTitle, diff --git a/client/build/utils/createAssetMetaTags.js b/client/build/utils/createAssetMetaTags.js new file mode 100644 index 00000000..3fb2720f --- /dev/null +++ b/client/build/utils/createAssetMetaTags.js @@ -0,0 +1,105 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _siteConfig = _interopRequireDefault(require("@config/siteConfig.json")); + +var _determineContentTypeFromExtension = _interopRequireDefault(require("./determineContentTypeFromExtension")); + +var _createMetaTagsArray = _interopRequireDefault(require("./createMetaTagsArray")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _siteConfig$details = _siteConfig.default.details, + host = _siteConfig$details.host, + siteTitle = _siteConfig$details.title, + twitter = _siteConfig$details.twitter, + _siteConfig$assetDefa = _siteConfig.default.assetDefaults, + defaultDescription = _siteConfig$assetDefa.description, + defaultThumbnail = _siteConfig$assetDefa.thumbnail; +var VIDEO = 'VIDEO'; +var IMAGE = 'IMAGE'; +var GIF = 'GIF'; + +var determineMediaType = function determineMediaType(contentType) { + switch (contentType) { + case 'image/jpg': + case 'image/jpeg': + case 'image/png': + return IMAGE; + + case 'image/gif': + return GIF; + + case 'video/mp4': + case 'video/webm': + return VIDEO; + + default: + return ''; + } +}; + +var createAssetMetaTags = function createAssetMetaTags(asset) { + var claimData = asset.claimData; + var contentType = claimData.contentType; + var showUrl = "".concat(host, "/").concat(claimData.claimId, "/").concat(claimData.name); + var serveUrl = "".concat(host, "/").concat(claimData.claimId, "/").concat(claimData.name, ".").concat(claimData.fileExt); + var ogTitle = claimData.title || claimData.name; + var ogDescription = claimData.description || defaultDescription; + var ogThumbnailContentType = (0, _determineContentTypeFromExtension.default)(claimData.thumbnail); + var ogThumbnail = claimData.thumbnail || defaultThumbnail; // {property: 'og:title'] = ogTitle}, + + var metaTags = { + 'og:title': ogTitle, + 'twitter:title': ogTitle, + 'og:description': ogDescription, + 'twitter:description': ogDescription, + 'og:url': showUrl, + 'og:site_name': siteTitle, + 'twitter:site': twitter, + 'fb:app_id': '1371961932852223' + }; + + if (determineMediaType(contentType) === VIDEO) { + var videoEmbedUrl = "".concat(host, "/video-embed/").concat(claimData.name, "/").concat(claimData.claimId); // card type tags + + metaTags['og:type'] = 'video.other'; + metaTags['twitter:card'] = 'player'; + metaTags['twitter:player'] = videoEmbedUrl; + metaTags['twitter:player:width'] = 600; + metaTags['twitter:text:player_width'] = 600; + metaTags['twitter:player:height'] = 350; + metaTags['twitter:player:stream'] = serveUrl; + metaTags['twitter:player:stream:content_type'] = contentType; // video tags + + metaTags['og:video'] = serveUrl; + metaTags['og:video:secure_url'] = serveUrl; + metaTags['og:video:type'] = contentType; // image tags + + metaTags['og:image'] = ogThumbnail; + metaTags['og:image:width'] = 600; + metaTags['og:image:height'] = 315; + metaTags['og:image:type'] = ogThumbnailContentType; + metaTags['twitter:image'] = ogThumbnail; + } else { + // card type tags + metaTags['og:type'] = 'article'; + metaTags['twitter:card'] = 'summary_large_image'; // image tags + + metaTags['og:image'] = serveUrl; + metaTags['og:image'] = serveUrl; + metaTags['og:image:width'] = 600; + metaTags['og:image:height'] = 315; + metaTags['og:image:type'] = contentType; + metaTags['twitter:image'] = serveUrl; + } + + return (0, _createMetaTagsArray.default)(metaTags); +}; + +var _default = createAssetMetaTags; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createBasicMetaTags.js b/client/build/utils/createBasicMetaTags.js new file mode 100644 index 00000000..0160e74a --- /dev/null +++ b/client/build/utils/createBasicMetaTags.js @@ -0,0 +1,51 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _siteConfig = _interopRequireDefault(require("@config/siteConfig.json")); + +var _determineContentTypeFromExtension = _interopRequireDefault(require("./determineContentTypeFromExtension.js")); + +var _createMetaTagsArray = _interopRequireDefault(require("./createMetaTagsArray")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _siteConfig$details = _siteConfig.default.details, + description = _siteConfig$details.description, + host = _siteConfig$details.host, + title = _siteConfig$details.title, + twitter = _siteConfig$details.twitter, + thumbnail = _siteConfig.default.assetDefaults.thumbnail; + +var createBasicMetaTags = function createBasicMetaTags() { + var metaTags = { + // page details + 'og:title': title, + 'twitter:title': title, + 'og:description': description, + 'twitter:description': description, + // url + 'og:url': host, + // site id + 'og:site_name': title, + 'twitter:site': twitter, + 'fb:app_id': '1371961932852223', + // card type + 'og:type': 'article', + 'twitter:card': 'summary_large_image', + // image + 'og:image': thumbnail, + 'og:image:width': 600, + 'og:image:height': 315, + 'og:image:type': (0, _determineContentTypeFromExtension.default)(thumbnail), + 'twitter:image': thumbnail, + 'twitter:image:alt': 'Spee.ch Logo' + }; + return (0, _createMetaTagsArray.default)(metaTags); +}; + +var _default = createBasicMetaTags; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createCanonicalLink.js b/client/build/utils/createCanonicalLink.js new file mode 100644 index 00000000..281a68e4 --- /dev/null +++ b/client/build/utils/createCanonicalLink.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _siteConfig = _interopRequireDefault(require("@config/siteConfig.json")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var host = _siteConfig.default.details.host; + +var createBasicCanonicalLink = function createBasicCanonicalLink(page) { + return "".concat(host, "/").concat(page); +}; + +var createAssetCanonicalLink = function createAssetCanonicalLink(asset) { + var channelName, certificateId, name, claimId; + + if (asset.claimData) { + var _asset$claimData = asset.claimData; + channelName = _asset$claimData.channelName; + certificateId = _asset$claimData.certificateId; + name = _asset$claimData.name; + claimId = _asset$claimData.claimId; + } + + if (channelName) { + return "".concat(host, "/").concat(channelName, ":").concat(certificateId, "/").concat(name); + } + + return "".concat(host, "/").concat(claimId, "/").concat(name); +}; + +var createChannelCanonicalLink = function createChannelCanonicalLink(channel) { + var name = channel.name, + longId = channel.longId; + return "".concat(host, "/").concat(name, ":").concat(longId); +}; + +var createCanonicalLink = function createCanonicalLink(asset, channel, page) { + if (asset) { + return createAssetCanonicalLink(asset); + } + + if (channel) { + return createChannelCanonicalLink(channel); + } + + return createBasicCanonicalLink(page); +}; + +var _default = createCanonicalLink; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createChannelMetaTags.js b/client/build/utils/createChannelMetaTags.js new file mode 100644 index 00000000..9abc6902 --- /dev/null +++ b/client/build/utils/createChannelMetaTags.js @@ -0,0 +1,53 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.createChannelMetaTags = void 0; + +var _siteConfig = _interopRequireDefault(require("@config/siteConfig.json")); + +var _determineContentTypeFromExtension = _interopRequireDefault(require("./determineContentTypeFromExtension")); + +var _createMetaTagsArray = _interopRequireDefault(require("./createMetaTagsArray")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _siteConfig$details = _siteConfig.default.details, + host = _siteConfig$details.host, + siteTitle = _siteConfig$details.title, + twitter = _siteConfig$details.twitter, + defaultThumbnail = _siteConfig.default.assetDefaults.thumbnail; + +var createChannelMetaTags = function createChannelMetaTags(channel) { + var name = channel.name, + longId = channel.longId; + var metaTags = { + // page detail tags + 'og:title': "".concat(name, " on ").concat(siteTitle), + 'twitter:title': "".concat(name, " on ").concat(siteTitle), + 'og:description': "".concat(name, ", a channel on ").concat(siteTitle), + 'twitter:description': "".concat(name, ", a channel on ").concat(siteTitle), + // url + 'og:url': "".concat(host, "/").concat(name, ":").concat(longId), + // site info + 'og:site_name': siteTitle, + 'twitter:site': twitter, + 'fb:app_id': '1371961932852223', + // card type tags + 'og:type': 'article', + 'twitter:card': 'summary_large_image', + // image tags + 'og:image': defaultThumbnail, + 'og:image:width': 600, + 'og:image:height': 315, + 'og:image:type': (0, _determineContentTypeFromExtension.default)(defaultThumbnail), + 'twitter:image': defaultThumbnail, + 'twitter:image:alt': 'Spee.ch Logo' + }; + return (0, _createMetaTagsArray.default)(metaTags); +}; + +exports.createChannelMetaTags = createChannelMetaTags; +var _default = createChannelMetaTags; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createMetaTags.js b/client/build/utils/createMetaTags.js new file mode 100644 index 00000000..98c33201 --- /dev/null +++ b/client/build/utils/createMetaTags.js @@ -0,0 +1,32 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _createAssetMetaTags = _interopRequireDefault(require("./createAssetMetaTags")); + +var _createChannelMetaTags = _interopRequireDefault(require("./createChannelMetaTags.js")); + +var _createBasicMetaTags = _interopRequireDefault(require("./createBasicMetaTags.js")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var createMetaTags = function createMetaTags(_ref) { + var asset = _ref.asset, + channel = _ref.channel; + + if (asset) { + return (0, _createAssetMetaTags.default)(asset); + } + + if (channel) { + return (0, _createChannelMetaTags.default)(channel); + } + + return (0, _createBasicMetaTags.default)(); +}; + +var _default = createMetaTags; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createMetaTagsArray.js b/client/build/utils/createMetaTagsArray.js new file mode 100644 index 00000000..21fa19ef --- /dev/null +++ b/client/build/utils/createMetaTagsArray.js @@ -0,0 +1,24 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var createMetaTagsArray = function createMetaTagsArray(metaTagsObject) { + var metaTagsArray = []; + + for (var key in metaTagsObject) { + if (metaTagsObject.hasOwnProperty(key)) { + metaTagsArray.push({ + property: key, + content: metaTagsObject[key] + }); + } + } + + return metaTagsArray; +}; + +var _default = createMetaTagsArray; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/createPageTitle.js b/client/build/utils/createPageTitle.js new file mode 100644 index 00000000..72577c0e --- /dev/null +++ b/client/build/utils/createPageTitle.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _siteConfig = _interopRequireDefault(require("@config/siteConfig.json")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var siteTitle = _siteConfig.default.details.title; + +var createPageTitle = function createPageTitle(pageTitle) { + if (!pageTitle) { + return "".concat(siteTitle); + } + + return "".concat(siteTitle, " - ").concat(pageTitle); +}; + +var _default = createPageTitle; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/determineContentTypeFromExtension.js b/client/build/utils/determineContentTypeFromExtension.js new file mode 100644 index 00000000..ecaa987e --- /dev/null +++ b/client/build/utils/determineContentTypeFromExtension.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var determineContentTypeFromExtension = function determineContentTypeFromExtension(thumbnail) { + if (thumbnail) { + var fileExt = thumbnail.substring(thumbnail.lastIndexOf('.')); + + switch (fileExt) { + case 'jpeg': + case 'jpg': + return 'image/jpg'; + + case 'png': + return 'image/png'; + + case 'gif': + return 'image/gif'; + + case 'mp4': + return 'video/mp4'; + + default: + return ''; + } + } + + return ''; +}; + +var _default = determineContentTypeFromExtension; +exports.default = _default; \ No newline at end of file diff --git a/client/build/utils/metaTags.js b/client/build/utils/metaTags.js index 418710f7..383a32f0 100644 --- a/client/build/utils/metaTags.js +++ b/client/build/utils/metaTags.js @@ -5,270 +5,25 @@ Object.defineProperty(exports, "__esModule", { }); exports.createMetaTags = void 0; -var determineOgThumbnailContentType = function determineOgThumbnailContentType(thumbnail) { - if (thumbnail) { - var fileExt = thumbnail.substring(thumbnail.lastIndexOf('.')); +var createAssetMetaTags = require('createAssetMetaTags.js'); - switch (fileExt) { - case 'jpeg': - case 'jpg': - return 'image/jpeg'; +var createChannelMetaTags = require('createChannelMetaTags.js'); - case 'png': - return 'image/png'; +var createBasicMetaTags = require('createBasicMetaTags.js'); - case 'gif': - return 'image/gif'; - - case 'mp4': - return 'video/mp4'; - - default: - return 'image/jpeg'; - } - } - - return ''; -}; - -var createBasicMetaTags = function createBasicMetaTags(_ref) { - var siteHost = _ref.siteHost, - siteDescription = _ref.siteDescription, - siteTitle = _ref.siteTitle, - siteTwitter = _ref.siteTwitter, - defaultThumbnail = _ref.defaultThumbnail; - return [{ - property: 'og:title', - content: siteTitle - }, { - property: 'twitter:title', - content: siteTitle - }, { - property: 'og:url', - content: siteHost - }, { - property: 'og:site_name', - content: siteTitle - }, { - property: 'og:description', - content: siteDescription - }, { - property: 'twitter:description', - content: siteDescription - }, { - property: 'twitter:site', - content: siteTwitter - }, { - property: 'twitter:card', - content: 'summary_large_image' - }, { - property: 'og:image', - content: defaultThumbnail - }, { - property: 'twitter:image', - content: defaultThumbnail - }, { - property: 'og:image:type', - content: 'image/jpeg' - }]; -}; - -var createChannelMetaTags = function createChannelMetaTags(_ref2) { - var siteHost = _ref2.siteHost, - siteTitle = _ref2.siteTitle, - siteTwitter = _ref2.siteTwitter, - channel = _ref2.channel; - var name = channel.name, - longId = channel.longId; - return [{ - property: 'og:title', - content: "".concat(name, " on ").concat(siteTitle) - }, { - property: 'twitter:title', - content: "".concat(name, " on ").concat(siteTitle) - }, { - property: 'og:url', - content: "".concat(siteHost, "/").concat(name, ":").concat(longId) - }, { - property: 'og:site_name', - content: siteTitle - }, { - property: 'og:description', - content: "".concat(name, ", a channel on ").concat(siteTitle) - }, { - property: 'twitter:site', - content: siteTwitter - }, { - property: 'twitter:card', - content: 'summary' - }]; -}; - -var createAssetMetaTags = function createAssetMetaTags(_ref3) { - var siteHost = _ref3.siteHost, - siteTitle = _ref3.siteTitle, - siteTwitter = _ref3.siteTwitter, - asset = _ref3.asset, - defaultDescription = _ref3.defaultDescription, - defaultThumbnail = _ref3.defaultThumbnail; - var claimData = asset.claimData; - var contentType = claimData.contentType; - 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, "/asset/").concat(claimData.name, "/").concat(claimData.claimId); - var ogTitle = claimData.title || claimData.name; - var ogDescription = claimData.description || defaultDescription; - var ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail); - var ogThumbnail = claimData.thumbnail || defaultThumbnail; - var metaTags = [{ - property: 'og:title', - content: ogTitle - }, { - property: 'twitter:title', - content: ogTitle - }, { - property: 'og:url', - content: showUrl - }, { - property: 'og:site_name', - content: siteTitle - }, { - property: 'og:description', - content: ogDescription - }, { - property: 'twitter:description', - content: ogDescription - }, { - property: 'og:image:width', - content: 600 - }, { - property: 'og:image:height', - content: 315 - }, { - property: 'twitter:site', - content: siteTwitter - }]; - - if (contentType === 'video/mp4' || contentType === 'video/webm') { - metaTags.push({ - property: 'og:video', - content: source - }); - metaTags.push({ - property: 'og:video:secure_url', - content: source - }); - metaTags.push({ - property: 'og:video:type', - content: contentType - }); - metaTags.push({ - property: 'og:image', - content: ogThumbnail - }); - metaTags.push({ - property: 'twitter:image', - content: ogThumbnail - }); - metaTags.push({ - property: 'og:image:type', - content: ogThumbnailContentType - }); - metaTags.push({ - property: 'og:type', - content: 'video.other' - }); - metaTags.push({ - property: 'twitter:card', - content: 'player' - }); - 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 - }); - metaTags.push({ - property: 'twitter:player:stream', - content: source - }); - metaTags.push({ - property: 'twitter:player:stream:content_type', - content: contentType - }); - } else { - metaTags.push({ - property: 'og:image', - content: source - }); - metaTags.push({ - property: 'twitter:image', - content: source - }); - metaTags.push({ - property: 'og:image:type', - content: contentType - }); - metaTags.push({ - property: 'og:type', - content: 'article' - }); - metaTags.push({ - property: 'twitter:card', - content: 'summary_large_image' - }); - } - - return metaTags; -}; - -var createMetaTags = function createMetaTags(_ref4) { - var siteDescription = _ref4.siteDescription, - siteHost = _ref4.siteHost, - siteTitle = _ref4.siteTitle, - siteTwitter = _ref4.siteTwitter, - asset = _ref4.asset, - channel = _ref4.channel, - defaultDescription = _ref4.defaultDescription, - defaultThumbnail = _ref4.defaultThumbnail; +var createMetaTags = function createMetaTags(_ref) { + var asset = _ref.asset, + channel = _ref.channel; if (asset) { - return createAssetMetaTags({ - siteHost: siteHost, - siteTitle: siteTitle, - siteTwitter: siteTwitter, - asset: asset, - defaultDescription: defaultDescription, - defaultThumbnail: defaultThumbnail - }); + return createAssetMetaTags(asset); } if (channel) { - return createChannelMetaTags({ - siteHost: siteHost, - siteTitle: siteTitle, - siteTwitter: siteTwitter, - channel: channel - }); + return createChannelMetaTags(channel); } - return createBasicMetaTags({ - siteDescription: siteDescription, - siteHost: siteHost, - siteTitle: siteTitle, - siteTwitter: siteTwitter, - defaultThumbnail: defaultThumbnail - }); + return createBasicMetaTags(); }; exports.createMetaTags = createMetaTags; \ No newline at end of file diff --git a/client/src/components/AssetPreview/index.jsx b/client/src/components/AssetPreview/index.jsx index e9e10cef..be09c200 100644 --- a/client/src/components/AssetPreview/index.jsx +++ b/client/src/components/AssetPreview/index.jsx @@ -2,10 +2,10 @@ import React from 'react'; import { Link } from 'react-router-dom'; const AssetPreview = ({ defaultThumbnail, claimData: { name, claimId, fileExt, contentType, thumbnail } }) => { - const directSourceLink = `asset/${name}/${claimId}`; - const showUrlLink = `/${claimId}/${name}`; + const embedUrl = `/${claimId}/${name}.${fileExt}`; + const showUrl = `/${claimId}/${name}`; return ( - + {(() => { switch (contentType) { case 'image/jpeg': @@ -15,7 +15,7 @@ const AssetPreview = ({ defaultThumbnail, claimData: { name, claimId, fileExt, c return ( {name} ); diff --git a/client/src/containers/AssetDisplay/view.jsx b/client/src/containers/AssetDisplay/view.jsx index c742c851..e07bfa78 100644 --- a/client/src/containers/AssetDisplay/view.jsx +++ b/client/src/containers/AssetDisplay/view.jsx @@ -9,6 +9,7 @@ class AssetDisplay extends React.Component { } render () { const { status, error, asset: { claimData: { name, claimId, contentType, fileExt, thumbnail } } } = this.props; + const sourceUrl = `/${claimId}/${name}.${fileExt}`; return (
{(status === LOCAL_CHECK) && @@ -39,7 +40,7 @@ class AssetDisplay extends React.Component { return ( {name} ); @@ -50,14 +51,14 @@ class AssetDisplay extends React.Component { controls poster={thumbnail} >

Your browser does not support the video element.

); default: return ( -

Unsupported file type

+

Unsupported content type

); } })() diff --git a/client/src/containers/AssetInfo/view.jsx b/client/src/containers/AssetInfo/view.jsx index e251e81d..ccf88fbd 100644 --- a/client/src/containers/AssetInfo/view.jsx +++ b/client/src/containers/AssetInfo/view.jsx @@ -50,7 +50,7 @@ class AssetInfo extends React.Component { content={ } /> @@ -81,12 +81,12 @@ class AssetInfo extends React.Component { - Direct Link - + { - const { defaultDescription, defaultThumbnail, description: siteDescription, host: siteHost, title: siteTitle, twitter: siteTwitter } = site; - return { - defaultDescription, - defaultThumbnail, - siteDescription, - siteHost, - siteTitle, - siteTwitter, - }; -}; - -export default connect(mapStateToProps, null)(View); +export default connect(null, null)(View); diff --git a/client/src/containers/SEO/view.jsx b/client/src/containers/SEO/view.jsx index 58c12cf3..85574695 100644 --- a/client/src/containers/SEO/view.jsx +++ b/client/src/containers/SEO/view.jsx @@ -2,30 +2,22 @@ import React from 'react'; import Helmet from 'react-helmet'; import PropTypes from 'prop-types'; -import { createPageTitle } from '../../utils/pageTitle'; -import { createMetaTags } from '../../utils/metaTags'; -import { createCanonicalLink } from '../../utils/canonicalLink'; +import createPageTitle from '../../utils/createPageTitle'; +import createMetaTags from '../../utils/createMetaTags'; +import createCanonicalLink from '../../utils/createCanonicalLink'; class SEO extends React.Component { render () { - // props from state - const { defaultDescription, defaultThumbnail, siteDescription, siteHost, siteTitle, siteTwitter } = this.props; // props from parent const { asset, channel, pageUri } = this.props; let { pageTitle } = this.props; // create page title, tags, and canonical link - pageTitle = createPageTitle(siteTitle, pageTitle); + pageTitle = createPageTitle(pageTitle); const metaTags = createMetaTags({ - siteDescription, - siteHost, - siteTitle, - siteTwitter, asset, channel, - defaultDescription, - defaultThumbnail, }); - const canonicalLink = createCanonicalLink(asset, channel, pageUri, siteHost); + const canonicalLink = createCanonicalLink(asset, channel, pageUri); // render results return ( { - return `${siteHost}/${page}`; -}; - -const createAssetCanonicalLink = (asset, siteHost) => { - let channelName, certificateId, name, claimId; - if (asset.claimData) { - ({ channelName, certificateId, name, claimId } = asset.claimData); - }; - if (channelName) { - return `${siteHost}/${channelName}:${certificateId}/${name}`; - }; - return `${siteHost}/${claimId}/${name}`; -}; - -const createChannelCanonicalLink = (channel, siteHost) => { - const { name, longId } = channel; - return `${siteHost}/${name}:${longId}`; -}; - -export const createCanonicalLink = (asset, channel, page, siteHost) => { - if (asset) { - return createAssetCanonicalLink(asset, siteHost); - } - if (channel) { - return createChannelCanonicalLink(channel, siteHost); - } - return createBasicCanonicalLink(page, siteHost); -}; diff --git a/client/src/utils/createAssetMetaTags.js b/client/src/utils/createAssetMetaTags.js new file mode 100644 index 00000000..531df9e3 --- /dev/null +++ b/client/src/utils/createAssetMetaTags.js @@ -0,0 +1,93 @@ +import siteConfig from '@config/siteConfig.json'; +import determineContentTypeFromExtension from './determineContentTypeFromExtension'; +import createMetaTagsArray from './createMetaTagsArray'; + +const { + details: { + host, + title: siteTitle, + twitter, + }, + assetDefaults: { + description: defaultDescription, + thumbnail: defaultThumbnail, + }, +} = siteConfig; + +const VIDEO = 'VIDEO'; +const IMAGE = 'IMAGE'; +const GIF = 'GIF'; + +const determineMediaType = (contentType) => { + switch (contentType) { + case 'image/jpg': + case 'image/jpeg': + case 'image/png': + return IMAGE; + case 'image/gif': + return GIF; + case 'video/mp4': + case 'video/webm': + return VIDEO; + default: + return ''; + } +}; + +const createAssetMetaTags = (asset) => { + const { claimData } = asset; + const { contentType } = claimData; + const showUrl = `${host}/${claimData.claimId}/${claimData.name}`; + const serveUrl = `${host}/${claimData.claimId}/${claimData.name}.${claimData.fileExt}`; + const ogTitle = claimData.title || claimData.name; + const ogDescription = claimData.description || defaultDescription; + const ogThumbnailContentType = determineContentTypeFromExtension(claimData.thumbnail); + const ogThumbnail = claimData.thumbnail || defaultThumbnail; + // {property: 'og:title'] = ogTitle}, + const metaTags = { + 'og:title' : ogTitle, + 'twitter:title' : ogTitle, + 'og:description' : ogDescription, + 'twitter:description': ogDescription, + 'og:url' : showUrl, + 'og:site_name' : siteTitle, + 'twitter:site' : twitter, + 'fb:app_id' : '1371961932852223', + }; + if (determineMediaType(contentType) === VIDEO) { + const videoEmbedUrl = `${host}/video-embed/${claimData.name}/${claimData.claimId}`; + // card type tags + metaTags['og:type'] = 'video.other'; + metaTags['twitter:card'] = 'player'; + metaTags['twitter:player'] = videoEmbedUrl; + metaTags['twitter:player:width'] = 600; + metaTags['twitter:text:player_width'] = 600; + metaTags['twitter:player:height'] = 350; + metaTags['twitter:player:stream'] = serveUrl; + metaTags['twitter:player:stream:content_type'] = contentType; + // video tags + metaTags['og:video'] = serveUrl; + metaTags['og:video:secure_url'] = serveUrl; + metaTags['og:video:type'] = contentType; + // image tags + metaTags['og:image'] = ogThumbnail; + metaTags['og:image:width'] = 600; + metaTags['og:image:height'] = 315; + metaTags['og:image:type'] = ogThumbnailContentType; + metaTags['twitter:image'] = ogThumbnail; + } else { + // card type tags + metaTags['og:type'] = 'article'; + metaTags['twitter:card'] = 'summary_large_image'; + // image tags + metaTags['og:image'] = serveUrl; + metaTags['og:image'] = serveUrl; + metaTags['og:image:width'] = 600; + metaTags['og:image:height'] = 315; + metaTags['og:image:type'] = contentType; + metaTags['twitter:image'] = serveUrl; + } + return createMetaTagsArray(metaTags); +}; + +export default createAssetMetaTags; diff --git a/client/src/utils/createBasicMetaTags.js b/client/src/utils/createBasicMetaTags.js new file mode 100644 index 00000000..090d796d --- /dev/null +++ b/client/src/utils/createBasicMetaTags.js @@ -0,0 +1,44 @@ +import siteConfig from '@config/siteConfig.json'; +import determineContentTypeFromExtension from './determineContentTypeFromExtension.js'; +import createMetaTagsArray from './createMetaTagsArray'; + +const { + details: { + description, + host, + title, + twitter, + }, + assetDefaults: { + thumbnail, + }, +} = siteConfig; + +const createBasicMetaTags = () => { + const metaTags = { + // page details + 'og:title' : title, + 'twitter:title' : title, + 'og:description' : description, + 'twitter:description': description, + // url + 'og:url' : host, + // site id + 'og:site_name' : title, + 'twitter:site' : twitter, + 'fb:app_id' : '1371961932852223', + // card type + 'og:type' : 'article', + 'twitter:card' : 'summary_large_image', + // image + 'og:image' : thumbnail, + 'og:image:width' : 600, + 'og:image:height' : 315, + 'og:image:type' : determineContentTypeFromExtension(thumbnail), + 'twitter:image' : thumbnail, + 'twitter:image:alt' : 'Spee.ch Logo', + }; + return createMetaTagsArray(metaTags); +}; + +export default createBasicMetaTags; diff --git a/client/src/utils/createCanonicalLink.js b/client/src/utils/createCanonicalLink.js new file mode 100644 index 00000000..d73e183d --- /dev/null +++ b/client/src/utils/createCanonicalLink.js @@ -0,0 +1,39 @@ +import siteConfig from '@config/siteConfig.json'; + +const { + details: { + host, + }, +} = siteConfig; + +const createBasicCanonicalLink = (page) => { + return `${host}/${page}`; +}; + +const createAssetCanonicalLink = (asset) => { + let channelName, certificateId, name, claimId; + if (asset.claimData) { + ({ channelName, certificateId, name, claimId } = asset.claimData); + } + if (channelName) { + return `${host}/${channelName}:${certificateId}/${name}`; + } + return `${host}/${claimId}/${name}`; +}; + +const createChannelCanonicalLink = (channel) => { + const { name, longId } = channel; + return `${host}/${name}:${longId}`; +}; + +const createCanonicalLink = (asset, channel, page) => { + if (asset) { + return createAssetCanonicalLink(asset); + } + if (channel) { + return createChannelCanonicalLink(channel); + } + return createBasicCanonicalLink(page); +}; + +export default createCanonicalLink; diff --git a/client/src/utils/createChannelMetaTags.js b/client/src/utils/createChannelMetaTags.js new file mode 100644 index 00000000..fea67ec5 --- /dev/null +++ b/client/src/utils/createChannelMetaTags.js @@ -0,0 +1,44 @@ +import siteConfig from '@config/siteConfig.json'; +import determineContentTypeFromExtension from './determineContentTypeFromExtension'; +import createMetaTagsArray from './createMetaTagsArray'; + +const { + details: { + host, + title: siteTitle, + twitter, + }, + assetDefaults: { + thumbnail: defaultThumbnail, + }, +} = siteConfig; + +export const createChannelMetaTags = (channel) => { + const { name, longId } = channel; + const metaTags = { + // page detail tags + 'og:title' : `${name} on ${siteTitle}`, + 'twitter:title' : `${name} on ${siteTitle}`, + 'og:description' : `${name}, a channel on ${siteTitle}`, + 'twitter:description': `${name}, a channel on ${siteTitle}`, + // url + 'og:url' : `${host}/${name}:${longId}`, + // site info + 'og:site_name' : siteTitle, + 'twitter:site' : twitter, + 'fb:app_id' : '1371961932852223', + // card type tags + 'og:type' : 'article', + 'twitter:card' : 'summary_large_image', + // image tags + 'og:image' : defaultThumbnail, + 'og:image:width' : 600, + 'og:image:height' : 315, + 'og:image:type' : determineContentTypeFromExtension(defaultThumbnail), + 'twitter:image' : defaultThumbnail, + 'twitter:image:alt' : 'Spee.ch Logo', + }; + return createMetaTagsArray(metaTags); +}; + +export default createChannelMetaTags; diff --git a/client/src/utils/createMetaTags.js b/client/src/utils/createMetaTags.js new file mode 100644 index 00000000..19287478 --- /dev/null +++ b/client/src/utils/createMetaTags.js @@ -0,0 +1,15 @@ +import createAssetMetaTags from './createAssetMetaTags'; +import createChannelMetaTags from './createChannelMetaTags.js'; +import createBasicMetaTags from './createBasicMetaTags.js'; + +const createMetaTags = ({ asset, channel }) => { + if (asset) { + return createAssetMetaTags(asset); + } + if (channel) { + return createChannelMetaTags(channel); + } + return createBasicMetaTags(); +}; + +export default createMetaTags; diff --git a/client/src/utils/createMetaTagsArray.js b/client/src/utils/createMetaTagsArray.js new file mode 100644 index 00000000..e4052724 --- /dev/null +++ b/client/src/utils/createMetaTagsArray.js @@ -0,0 +1,14 @@ +const createMetaTagsArray = (metaTagsObject) => { + let metaTagsArray = []; + for (let key in metaTagsObject) { + if (metaTagsObject.hasOwnProperty(key)) { + metaTagsArray.push({ + property: key, + content : metaTagsObject[key], + }); + } + } + return metaTagsArray; +}; + +export default createMetaTagsArray; diff --git a/client/src/utils/createPageTitle.js b/client/src/utils/createPageTitle.js new file mode 100644 index 00000000..0093e190 --- /dev/null +++ b/client/src/utils/createPageTitle.js @@ -0,0 +1,16 @@ +import siteConfig from '@config/siteConfig.json'; + +const { + details: { + title: siteTitle, + }, +} = siteConfig; + +const createPageTitle = (pageTitle) => { + if (!pageTitle) { + return `${siteTitle}`; + } + return `${siteTitle} - ${pageTitle}`; +}; + +export default createPageTitle; diff --git a/client/src/utils/determineContentTypeFromExtension.js b/client/src/utils/determineContentTypeFromExtension.js new file mode 100644 index 00000000..cd7f85b4 --- /dev/null +++ b/client/src/utils/determineContentTypeFromExtension.js @@ -0,0 +1,21 @@ +const determineContentTypeFromExtension = (thumbnail) => { + if (thumbnail) { + const fileExt = thumbnail.substring(thumbnail.lastIndexOf('.')); + switch (fileExt) { + case 'jpeg': + case 'jpg': + return 'image/jpg'; + case 'png': + return 'image/png'; + case 'gif': + return 'image/gif'; + case 'mp4': + return 'video/mp4'; + default: + return ''; + } + } + return ''; +}; + +export default determineContentTypeFromExtension; diff --git a/client/src/utils/metaTags.js b/client/src/utils/metaTags.js deleted file mode 100644 index 7f0094e1..00000000 --- a/client/src/utils/metaTags.js +++ /dev/null @@ -1,122 +0,0 @@ -const determineOgThumbnailContentType = (thumbnail) => { - if (thumbnail) { - const fileExt = thumbnail.substring(thumbnail.lastIndexOf('.')); - switch (fileExt) { - case 'jpeg': - case 'jpg': - return 'image/jpeg'; - case 'png': - return 'image/png'; - case 'gif': - return 'image/gif'; - case 'mp4': - return 'video/mp4'; - default: - return 'image/jpeg'; - } - } - return ''; -}; - -const createBasicMetaTags = ({siteHost, siteDescription, siteTitle, siteTwitter, defaultThumbnail}) => { - return [ - {property: 'og:title', content: siteTitle}, - {property: 'twitter:title', content: siteTitle}, - {property: 'og:url', content: siteHost}, - {property: 'og:site_name', content: siteTitle}, - {property: 'og:description', content: siteDescription}, - {property: 'twitter:description', content: siteDescription}, - {property: 'twitter:site', content: siteTwitter}, - {property: 'twitter:card', content: 'summary_large_image'}, - {property: 'og:image', content: defaultThumbnail}, - {property: 'twitter:image', content: defaultThumbnail}, - {property: 'og:image:type', content: 'image/jpeg'}, - ]; -}; - -const createChannelMetaTags = ({siteHost, siteTitle, siteTwitter, channel}) => { - const { name, longId } = channel; - return [ - {property: 'og:title', content: `${name} on ${siteTitle}`}, - {property: 'twitter:title', content: `${name} on ${siteTitle}`}, - {property: 'og:url', content: `${siteHost}/${name}:${longId}`}, - {property: 'og:site_name', content: siteTitle}, - {property: 'og:description', content: `${name}, a channel on ${siteTitle}`}, - {property: 'twitter:site', content: siteTwitter}, - {property: 'twitter:card', content: 'summary'}, - ]; -}; - -const createAssetMetaTags = ({siteHost, siteTitle, siteTwitter, asset, defaultDescription, defaultThumbnail}) => { - const { claimData } = asset; - const { contentType } = claimData; - const videoEmbedUrl = `${siteHost}/video-embed/${claimData.name}/${claimData.claimId}`; - const showUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`; - const source = `${siteHost}/asset/${claimData.name}/${claimData.claimId}`; - const ogTitle = claimData.title || claimData.name; - const ogDescription = claimData.description || defaultDescription; - const ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail); - const ogThumbnail = claimData.thumbnail || defaultThumbnail; - const metaTags = [ - {property: 'og:title', content: ogTitle}, - {property: 'twitter:title', content: ogTitle}, - {property: 'og:url', content: showUrl}, - {property: 'og:site_name', content: siteTitle}, - {property: 'og:description', content: ogDescription}, - {property: 'twitter:description', content: ogDescription}, - {property: 'og:image:width', content: 600}, - {property: 'og:image:height', content: 315}, - {property: 'twitter:site', content: siteTwitter}, - ]; - if (contentType === 'video/mp4' || contentType === 'video/webm') { - metaTags.push({property: 'og:video', content: source}); - metaTags.push({property: 'og:video:secure_url', content: source}); - metaTags.push({property: 'og:video:type', content: contentType}); - metaTags.push({property: 'og:image', content: ogThumbnail}); - metaTags.push({property: 'twitter:image', content: ogThumbnail}); - metaTags.push({property: 'og:image:type', content: ogThumbnailContentType}); - metaTags.push({property: 'og:type', content: 'video.other'}); - metaTags.push({property: 'twitter:card', content: 'player'}); - 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}); - metaTags.push({property: 'twitter:player:stream', content: source}); - metaTags.push({property: 'twitter:player:stream:content_type', content: contentType}); - } else { - metaTags.push({property: 'og:image', content: source}); - metaTags.push({property: 'twitter:image', content: source}); - metaTags.push({property: 'og:image:type', content: contentType}); - metaTags.push({property: 'og:type', content: 'article'}); - metaTags.push({property: 'twitter:card', content: 'summary_large_image'}); - } - return metaTags; -}; - -export const createMetaTags = ({ siteDescription, siteHost, siteTitle, siteTwitter, asset, channel, defaultDescription, defaultThumbnail }) => { - if (asset) { - return createAssetMetaTags({ - siteHost, - siteTitle, - siteTwitter, - asset, - defaultDescription, - defaultThumbnail, - }); - } - if (channel) { - return createChannelMetaTags({ - siteHost, - siteTitle, - siteTwitter, - channel, - }); - } - return createBasicMetaTags({ - siteDescription, - siteHost, - siteTitle, - siteTwitter, - defaultThumbnail, - }); -}; diff --git a/client/src/utils/pageTitle.js b/client/src/utils/pageTitle.js deleted file mode 100644 index 2b577c0b..00000000 --- a/client/src/utils/pageTitle.js +++ /dev/null @@ -1,6 +0,0 @@ -export const createPageTitle = (siteTitle, pageTitle) => { - if (!pageTitle) { - return `${siteTitle}`; - } - return `${siteTitle} - ${pageTitle}`; -}; diff --git a/server/controllers/api/claim/publish/index.js b/server/controllers/api/claim/publish/index.js index 51e6e9be..b43995f5 100644 --- a/server/controllers/api/claim/publish/index.js +++ b/server/controllers/api/claim/publish/index.js @@ -27,6 +27,7 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) ip, headers, body, + files, }); // check for disabled publishing if (disabled) { @@ -36,14 +37,14 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) }); } // define variables - let channelName, channelId, channelPassword, description, fileName, filePath, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title; + let channelName, channelId, channelPassword, description, fileName, filePath, fileExtension, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title; // record the start time of the request gaStartTime = Date.now(); // validate the body and files of the request try { // validateApiPublishRequest(body, files); ({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body)); - ({fileName, filePath, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files)); + ({fileName, filePath, fileExtension, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files)); ({channelName, channelId, channelPassword} = body); } catch (error) { return res.status(400).json({success: false, message: error.message}); @@ -76,8 +77,9 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res) data : { name, claimId : result.claim_id, - url : `${host}/${result.claim_id}/${name}`, - embedUrl: `${host}/asset/${name}/${result.claim_id}`, + url : `${host}/${result.claim_id}/${name}`, // for backwards compatability with app + showUrl : `${host}/${result.claim_id}/${name}`, + serveUrl: `${host}/${result.claim_id}/${name}${fileExtension}`, lbryTx : result, }, }); diff --git a/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js index 66f57be9..3e99ad20 100644 --- a/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js +++ b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js @@ -1,3 +1,4 @@ +const path = require('path'); const validateFileTypeAndSize = require('./validateFileTypeAndSize.js'); const parsePublishApiRequestFiles = ({file, thumbnail}) => { @@ -33,6 +34,7 @@ const parsePublishApiRequestFiles = ({file, thumbnail}) => { return { fileName : file.name, filePath : file.path, + fileExtension : path.extname(file.path), fileType : file.type, thumbnailFileName: (thumbnail ? thumbnail.name : null), thumbnailFilePath: (thumbnail ? thumbnail.path : null), diff --git a/server/controllers/assets/constants/request_types.js b/server/controllers/assets/constants/request_types.js index 22f0d0ce..4c32b6f1 100644 --- a/server/controllers/assets/constants/request_types.js +++ b/server/controllers/assets/constants/request_types.js @@ -1,9 +1,7 @@ -const EMBED = 'EMBED'; -const BROWSER = 'BROWSER'; -const SOCIAL = 'SOCIAL'; +const SERVE = 'SERVE'; +const SHOW = 'SHOW'; module.exports = { - EMBED, - BROWSER, - SOCIAL, + SERVE, + SHOW, }; diff --git a/server/controllers/assets/serveByClaim/index.js b/server/controllers/assets/serveByClaim/index.js index 6e0e9e40..1ca0be13 100644 --- a/server/controllers/assets/serveByClaim/index.js +++ b/server/controllers/assets/serveByClaim/index.js @@ -1,3 +1,5 @@ +const logger = require('winston'); + const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); const handleShowRender = require('../../../render/build/handleShowRender.js'); @@ -6,7 +8,7 @@ const lbryUri = require('../utils/lbryUri.js'); const determineRequestType = require('../utils/determineRequestType.js'); const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); -const { EMBED } = require('../constants/request_types.js'); +const { SHOW } = require('../constants/request_types.js'); /* @@ -16,29 +18,32 @@ const { EMBED } = require('../constants/request_types.js'); const serveByClaim = (req, res) => { const { headers, ip, originalUrl, params } = req; - // decide if this is a show request - let hasFileExtension; + try { + let isChannel, hasFileExtension, claimName; + + ({ isChannel } = lbryUri.parseIdentifier(params.claim)); + if (isChannel) { + logger.debug('channel request:', { headers, ip, originalUrl, params }); + return handleShowRender(req, res); + } + ({ hasFileExtension } = lbryUri.parseModifier(params.claim)); + if (determineRequestType(hasFileExtension, headers) === SHOW) { + logger.debug('show request:', { headers, ip, originalUrl, params }); + return handleShowRender(req, res); + } + + ({ claimName } = lbryUri.parseClaim(params.claim)); + logger.debug('serve request:', { headers, ip, originalUrl, params }); + getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res); + + sendGAServeEvent(headers, ip, originalUrl); + } catch (error) { return res.status(400).json({success: false, message: error.message}); } - // determine request type - let requestType = determineRequestType(hasFileExtension, headers); - if (requestType !== EMBED) { - return handleShowRender(req, res); - } - // parse the claim - let claimName; - try { - ({claimName} = lbryUri.parseClaim(params.claim)); - } catch (error) { - return res.status(400).json({success: false, message: error.message}); - } - // 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 = serveByClaim; diff --git a/server/controllers/assets/serveByIdentifierAndClaim/index.js b/server/controllers/assets/serveByIdentifierAndClaim/index.js index 609a1256..34434f5b 100644 --- a/server/controllers/assets/serveByIdentifierAndClaim/index.js +++ b/server/controllers/assets/serveByIdentifierAndClaim/index.js @@ -1,3 +1,5 @@ +const logger = require('winston'); + const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); const handleShowRender = require('../../../render/build/handleShowRender.js'); @@ -7,7 +9,7 @@ const determineRequestType = require('../utils/determineRequestType.js'); const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); const flipClaimNameAndId = require('../utils/flipClaimNameAndId.js'); -const { EMBED } = require('../constants/request_types.js'); +const { SHOW } = require('../constants/request_types.js'); /* @@ -17,40 +19,32 @@ const { EMBED } = require('../constants/request_types.js'); const serverByIdentifierAndClaim = (req, res) => { const { headers, ip, originalUrl, params } = req; - // parse request - let hasFileExtension; + try { + let hasFileExtension, claimName, isChannel, channelName, channelClaimId, claimId; + ({ hasFileExtension } = lbryUri.parseModifier(params.claim)); - } catch (error) { - return res.status(400).json({success: false, message: error.message}); - } - // determine request type - let requestType = determineRequestType(hasFileExtension, headers); - if (requestType !== EMBED) { - return handleShowRender(req, res); - } - // parse the claim - let claimName; - try { + if (determineRequestType(hasFileExtension, headers) === SHOW) { + logger.debug('show request:', { headers, ip, originalUrl, params }); + return handleShowRender(req, res); + } + ({ claimName } = lbryUri.parseClaim(params.claim)); - } catch (error) { - return res.status(400).json({success: false, message: error.message}); - } - // parse the identifier - let isChannel, channelName, channelClaimId, claimId; - try { ({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(params.identifier)); + + if (!isChannel) { + [claimId, claimName] = flipClaimNameAndId(claimId, claimName); + } + + logger.debug('serve request:', { headers, ip, originalUrl, params }); + getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res); + + sendGAServeEvent(headers, ip, originalUrl); + } catch (error) { return res.status(400).json({success: false, message: error.message}); } - // for backwards compatability, flip claim name and claim id if necessary - if (!isChannel) { - [claimId, claimName] = flipClaimNameAndId(claimId, claimName); - } - // 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 = serverByIdentifierAndClaim; diff --git a/server/controllers/assets/utils/determineRequestType.js b/server/controllers/assets/utils/determineRequestType.js index afc5574f..02e08fbc 100644 --- a/server/controllers/assets/utils/determineRequestType.js +++ b/server/controllers/assets/utils/determineRequestType.js @@ -1,60 +1,16 @@ -const logger = require('winston'); -const { EMBED, BROWSER, SOCIAL } = require('../constants/request_types.js'); - -function headersMatchesSocialBotList (headers) { - const userAgent = headers['user-agent']; - const socialBotList = [ - 'facebookexternalhit', - 'Twitterbot', - ]; - for (let i = 0; i < socialBotList.length; i++) { - if (userAgent.includes(socialBotList[i])) { - logger.debug('request is from social bot:', socialBotList[i]); - return true; - } - } - return false; -} - -function clientAcceptsHtml ({accept}) { - return accept && accept.match(/text\/html/); -} - -function requestIsFromBrowser (headers) { - return headers['user-agent'] && headers['user-agent'].match(/Mozilla/); -} +const { SERVE, SHOW } = require('../constants/request_types.js'); function clientWantsAsset ({accept, range}) { - const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/); - const videoIsWanted = accept && range; + const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/); + const videoIsWanted = accept && accept.match(/video\/.*/) && !accept.match(/text\/html/); 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 (hasFileExtension || clientWantsAsset(headers)) { + return SERVE; } - // 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; + return SHOW; }; module.exports = determineRequestType; diff --git a/server/routes/assets/index.js b/server/routes/assets/index.js index 5d4f92d1..ef70ea3f 100644 --- a/server/routes/assets/index.js +++ b/server/routes/assets/index.js @@ -1,9 +1,7 @@ const serveByClaim = require('../../controllers/assets/serveByClaim'); const serveByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim'); -const serveAsset = require('../../controllers/assets/serveAsset'); module.exports = (app) => { - app.get('/asset/:claimName/:claimId/', serveAsset); app.get('/:identifier/:claim', serveByIdentifierAndClaim); app.get('/:claim', serveByClaim); }; diff --git a/server/views/embed.handlebars b/server/views/embed.handlebars index 9cc0d40e..6b1a4ed6 100644 --- a/server/views/embed.handlebars +++ b/server/views/embed.handlebars @@ -1,4 +1,4 @@