RSS Fixes #6436
This commit is contained in:
commit
35e4c604ef
4 changed files with 65 additions and 31 deletions
|
@ -701,7 +701,11 @@
|
||||||
"Bid position must be a number.": "Bid position must be a number.",
|
"Bid position must be a number.": "Bid position must be a number.",
|
||||||
"Copy": "Copy",
|
"Copy": "Copy",
|
||||||
"Copy Link": "Copy Link",
|
"Copy Link": "Copy Link",
|
||||||
|
"Link copied.": "Link copied.",
|
||||||
|
"Failed to copy link.": "Failed to copy link.",
|
||||||
"Copy RSS URL": "Copy RSS URL",
|
"Copy RSS URL": "Copy RSS URL",
|
||||||
|
"RSS URL copied.": "RSS URL copied.",
|
||||||
|
"Failed to copy RSS URL.": "Failed to copy RSS URL.",
|
||||||
"Text copied": "Text copied",
|
"Text copied": "Text copied",
|
||||||
"Rewards Disabled": "Rewards Disabled",
|
"Rewards Disabled": "Rewards Disabled",
|
||||||
"Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.": "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.",
|
"Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.": "Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more%.",
|
||||||
|
|
|
@ -44,7 +44,7 @@ type Props = {
|
||||||
collectionName?: string,
|
collectionName?: string,
|
||||||
collectionId: string,
|
collectionId: string,
|
||||||
isMyCollection: boolean,
|
isMyCollection: boolean,
|
||||||
doToast: ({ message: string }) => void,
|
doToast: ({ message: string, isError?: boolean }) => void,
|
||||||
claimIsMine: boolean,
|
claimIsMine: boolean,
|
||||||
fileInfo: FileListItem,
|
fileInfo: FileListItem,
|
||||||
prepareEdit: ({}, string, {}) => void,
|
prepareEdit: ({}, string, {}) => void,
|
||||||
|
@ -103,7 +103,7 @@ function ClaimMenuList(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const shareUrl: string = generateShareUrl(SHARE_DOMAIN, uri);
|
const shareUrl: string = generateShareUrl(SHARE_DOMAIN, uri);
|
||||||
const rssUrl: string = generateRssUrl(URL, uri);
|
const rssUrl: string = isChannel ? generateRssUrl(URL, uri) : '';
|
||||||
const isCollectionClaim = claim && claim.value_type === 'collection';
|
const isCollectionClaim = claim && claim.value_type === 'collection';
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
const isPlayable =
|
const isPlayable =
|
||||||
|
@ -183,12 +183,23 @@ function ClaimMenuList(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyToClipboard(textToCopy, successMsg, failureMsg) {
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(textToCopy)
|
||||||
|
.then(() => {
|
||||||
|
doToast({ message: __(successMsg) });
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
doToast({ message: __(failureMsg), isError: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handleCopyRssLink() {
|
function handleCopyRssLink() {
|
||||||
navigator.clipboard.writeText(rssUrl);
|
copyToClipboard(rssUrl, 'RSS URL copied.', 'Failed to copy RSS URL.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCopyLink() {
|
function handleCopyLink() {
|
||||||
navigator.clipboard.writeText(shareUrl);
|
copyToClipboard(shareUrl, 'Link copied.', 'Failed to copy link.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleReportContent() {
|
function handleReportContent() {
|
||||||
|
|
|
@ -150,6 +150,6 @@ export const generateShareUrl = (
|
||||||
|
|
||||||
export const generateRssUrl = (domain, lbryUrl) => {
|
export const generateRssUrl = (domain, lbryUrl) => {
|
||||||
const { channelName, channelClaimId } = parseURI(lbryUrl);
|
const { channelName, channelClaimId } = parseURI(lbryUrl);
|
||||||
const url = `${domain}/$/rss/@${channelName}/${channelClaimId}`;
|
const url = `${domain}/$/rss/@${channelName}/${channelClaimId.slice(0, 2)}`;
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,8 @@ const SDK_API_PATH = `${LBRY_WEB_API}/api/v1`;
|
||||||
const proxyURL = `${SDK_API_PATH}/proxy`;
|
const proxyURL = `${SDK_API_PATH}/proxy`;
|
||||||
Lbry.setDaemonConnectionString(proxyURL);
|
Lbry.setDaemonConnectionString(proxyURL);
|
||||||
|
|
||||||
|
const NUM_ENTRIES = 500;
|
||||||
|
|
||||||
async function doClaimSearch(options) {
|
async function doClaimSearch(options) {
|
||||||
let results;
|
let results;
|
||||||
try {
|
try {
|
||||||
|
@ -14,15 +16,17 @@ async function doClaimSearch(options) {
|
||||||
return results ? results.items : undefined;
|
return results ? results.items : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getChannelClaim(claimId) {
|
async function getChannelClaim(name, claimId) {
|
||||||
const options = {
|
let claim;
|
||||||
claim_ids: [claimId],
|
try {
|
||||||
page_size: 1,
|
const url = `lbry://${name}#${claimId}`;
|
||||||
no_totals: true,
|
const response = await Lbry.resolve({ urls: [url] });
|
||||||
};
|
|
||||||
|
|
||||||
const claims = await doClaimSearch(options);
|
if (response && response[url] && !response[url].error) {
|
||||||
return claims ? claims[0] : undefined;
|
claim = response && response[url];
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return claim || 'The RSS URL is invalid or is not associated with any channel.';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getClaimsFromChannel(claimId, count) {
|
async function getClaimsFromChannel(claimId, count) {
|
||||||
|
@ -38,40 +42,49 @@ async function getClaimsFromChannel(claimId, count) {
|
||||||
return await doClaimSearch(options);
|
return await doClaimSearch(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFeed(channelClaim) {
|
async function getFeed(channelClaim, feedLink) {
|
||||||
const replaceLineFeeds = (str) => str.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
const replaceLineFeeds = (str) => str.replace(/(?:\r\n|\r|\n)/g, '<br />');
|
||||||
|
const fmtDescription = (description) => replaceLineFeeds(description);
|
||||||
|
const sanitizeThumbsUrl = (url) => {
|
||||||
|
if (typeof url === 'string' && url.startsWith('https://')) {
|
||||||
|
return encodeURI(url).replace(/&/g, '%26');
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
const value = channelClaim.value;
|
const value = channelClaim.value;
|
||||||
const title = value ? value.title : channelClaim.name;
|
const title = value ? value.title : channelClaim.name;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
title: title + ' on ' + SITE_NAME,
|
|
||||||
description: value && value.description ? replaceLineFeeds(value.description) : '',
|
|
||||||
link: `${URL}/${channelClaim.name}:${channelClaim.claim_id}`,
|
|
||||||
favicon: URL + '/public/favicon.png',
|
favicon: URL + '/public/favicon.png',
|
||||||
generator: SITE_NAME + ' RSS Feed',
|
generator: SITE_NAME + ' RSS Feed',
|
||||||
image: value && value.thumbnail ? value.thumbnail.url : '',
|
title: title + ' on ' + SITE_NAME,
|
||||||
|
description: fmtDescription(value && value.description ? value.description : ''),
|
||||||
|
link: encodeURI(`${URL}/${channelClaim.name}:${channelClaim.claim_id}`),
|
||||||
|
image: sanitizeThumbsUrl(value && value.thumbnail ? value.thumbnail.url : ''),
|
||||||
|
feedLinks: {
|
||||||
|
rss: encodeURI(feedLink),
|
||||||
|
},
|
||||||
author: {
|
author: {
|
||||||
name: channelClaim.name,
|
name: encodeURI(channelClaim.name),
|
||||||
link: URL + '/' + channelClaim.name + ':' + channelClaim.claim_id,
|
link: encodeURI(URL + '/' + channelClaim.name + ':' + channelClaim.claim_id),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const feed = new Feed(options);
|
const feed = new Feed(options);
|
||||||
|
const latestClaims = await getClaimsFromChannel(channelClaim.claim_id, NUM_ENTRIES);
|
||||||
const latestClaims = await getClaimsFromChannel(channelClaim.claim_id, 50);
|
|
||||||
|
|
||||||
latestClaims.forEach((c) => {
|
latestClaims.forEach((c) => {
|
||||||
const meta = c.meta;
|
const meta = c.meta;
|
||||||
const value = c.value;
|
const value = c.value;
|
||||||
|
|
||||||
feed.addItem({
|
feed.addItem({
|
||||||
guid: c.claim_id,
|
|
||||||
id: c.claim_id,
|
id: c.claim_id,
|
||||||
title: value ? value.title : c.name,
|
guid: encodeURI(URL + '/' + c.name + ':' + c.claim_id),
|
||||||
description: value && value.description ? replaceLineFeeds(value.description) : '',
|
title: value && value.title ? value.title : c.name,
|
||||||
image: value && value.thumbnail ? value.thumbnail.url : '',
|
description: fmtDescription(value && value.description ? value.description : ''),
|
||||||
link: URL + '/' + c.name + ':' + c.claim_id,
|
image: sanitizeThumbsUrl(value && value.thumbnail ? value.thumbnail.url : ''),
|
||||||
|
link: encodeURI(URL + '/' + c.name + ':' + c.claim_id),
|
||||||
date: new Date(meta ? meta.creation_timestamp * 1000 : null),
|
date: new Date(meta ? meta.creation_timestamp * 1000 : null),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -79,18 +92,24 @@ async function getFeed(channelClaim) {
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function postProcess(feed) {
|
||||||
|
// Handle 'Feed' creating an invalid MIME type when trying to guess
|
||||||
|
// from 'https://thumbnails.lbry.com/UCgQ8eREJzR1dO' style of URLs.
|
||||||
|
return feed.replace(/type="image\/\/.*"\/>/g, 'type="image/*"/>');
|
||||||
|
}
|
||||||
|
|
||||||
async function getRss(ctx) {
|
async function getRss(ctx) {
|
||||||
if (!ctx.params.claimName || !ctx.params.claimId) {
|
if (!ctx.params.claimName || !ctx.params.claimId) {
|
||||||
return 'Invalid URL';
|
return 'Invalid URL';
|
||||||
}
|
}
|
||||||
|
|
||||||
const channelClaim = await getChannelClaim(ctx.params.claimId);
|
const channelClaim = await getChannelClaim(ctx.params.claimName, ctx.params.claimId);
|
||||||
if (typeof channelClaim === 'string' || !channelClaim) {
|
if (typeof channelClaim === 'string' || !channelClaim) {
|
||||||
return channelClaim;
|
return channelClaim;
|
||||||
}
|
}
|
||||||
|
|
||||||
const feed = await getFeed(channelClaim);
|
const feed = await getFeed(channelClaim, `${URL}/$/rss/${ctx.params.claimName}/${ctx.params.claimId}`);
|
||||||
return feed.rss2();
|
return postProcess(feed.rss2());
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { getRss };
|
module.exports = { getRss };
|
||||||
|
|
Loading…
Add table
Reference in a new issue