From 48534d4e29f103cb8e4d3069454b580189d38a0a Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Wed, 14 Apr 2021 23:02:05 +1200 Subject: [PATCH] Rewrite URLs in subscription feed --- api/subscriptions.js | 3 ++- api/video.js | 36 +----------------------------------- utils/converters.js | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/api/subscriptions.js b/api/subscriptions.js index a9c8aa3..acb475f 100644 --- a/api/subscriptions.js +++ b/api/subscriptions.js @@ -2,7 +2,7 @@ const {render} = require("pinski/plugins") const db = require("../utils/db") const {fetchChannelLatest} = require("../utils/youtube") const {getUser} = require("../utils/getuser") -const {timeToPastText} = require("../utils/converters") +const {timeToPastText, rewriteVideoDescription} = require("../utils/converters") const {refresher} = require("../background/feed-update") module.exports = [ @@ -32,6 +32,7 @@ module.exports = [ .map(video => { video.publishedText = timeToPastText(video.published * 1000) video.watched = watchedVideos.includes(video.videoId) + video.descriptionHtml = rewriteVideoDescription(video.descriptionHtml, video.videoId) return video }) } diff --git a/api/video.js b/api/video.js index 9ca4633..2f919da 100644 --- a/api/video.js +++ b/api/video.js @@ -84,40 +84,6 @@ function sortFormats(video, preference) { return formats } -function rewriteVideoDescription(descriptionHtml, id) { - // replace timestamps to clickable links and rewrite youtube links to stay on the instance instead of pointing to YouTube - // test cases - // https://www.youtube.com/watch?v=VdPsJW6AHqc 00:00 timestamps, youtu.be/ - // https://www.youtube.com/watch?v=FDMq9ie0ih0 00:00 & 00:00:00 timestamps - // https://www.youtube.com/watch?v=fhum63fAwrI www.youtube.com/watch?v= - // https://www.youtube.com/watch?v=i-szWOrc3Mo www.youtube.com/ (unsupported by cloudtube currently) - // https://www.youtube.com/watch?v=LSG71wbKpbQ www.youtube.com/channel/ - - descriptionHtml = descriptionHtml.replace(new RegExp(`([^<]+)`, "g"), `$3`) - descriptionHtml = descriptionHtml.replace(new RegExp(`([^<]+)<\/a>`, "g"), `$2`) - descriptionHtml = descriptionHtml.replace(new RegExp(`(?:([0-9]*):)?([0-5]?[0-9]):([0-5][0-9])`, "g"), (_, hours, minutes, seconds) => { - let timeURL, timeDisplay, timeSeconds - if (hours === undefined) { - timeURL = `${minutes}m${seconds}s` - timeDisplay = `${minutes}:${seconds}` - timeSeconds = minutes*60 + + seconds - } else { - timeURL = `${hours}h${minutes}m${seconds}s` - timeDisplay = `${hours}:${minutes}:${seconds}` - timeSeconds = hours*60*60 + minutes*60 + + seconds - } - - const params = new URLSearchParams() - params.set("v", id) - params.set("t", timeURL) - const url = "/watch?" + params - - return pug.render(`a(href=url data-clickable-timestamp=timeSeconds)= timeDisplay`, {url, timeURL, timeDisplay, timeSeconds}) - }) - - return descriptionHtml -} - async function renderVideo(video, {user, settings, id, instanceOrigin}, locals = {}) { try { if (!video) throw new Error("The instance returned null.") @@ -149,7 +115,7 @@ async function renderVideo(video, {user, settings, id, instanceOrigin}, locals = } // rewrite description - video.descriptionHtml = rewriteVideoDescription(video.descriptionHtml, id) + video.descriptionHtml = converters.rewriteVideoDescription(video.descriptionHtml, id) return render(200, "pug/video.pug", Object.assign(locals, {video, formats, subscribed, instanceOrigin})) } catch (e) { diff --git a/utils/converters.js b/utils/converters.js index f6d9272..54126d0 100644 --- a/utils/converters.js +++ b/utils/converters.js @@ -1,3 +1,6 @@ +const constants = require("./constants") +const pug = require("pug") + function timeToPastText(timestamp) { const difference = Date.now() - timestamp return [ @@ -49,6 +52,43 @@ function normaliseVideoInfo(video) { if (!video.second__viewCountText) { video.second__viewCountText = viewCountToText(video.viewCount) } + if (video.descriptionHtml) { + video.descriptionHtml = rewriteVideoDescription(video.descriptionHtml, video.videoId) + } +} + +function rewriteVideoDescription(descriptionHtml, id) { + // replace timestamps to clickable links and rewrite youtube links to stay on the instance instead of pointing to YouTube + // test cases + // https://www.youtube.com/watch?v=VdPsJW6AHqc 00:00 timestamps, youtu.be/ + // https://www.youtube.com/watch?v=FDMq9ie0ih0 00:00 & 00:00:00 timestamps + // https://www.youtube.com/watch?v=fhum63fAwrI www.youtube.com/watch?v= + // https://www.youtube.com/watch?v=i-szWOrc3Mo www.youtube.com/ (unsupported by cloudtube currently) + // https://www.youtube.com/watch?v=LSG71wbKpbQ www.youtube.com/channel/ + + descriptionHtml = descriptionHtml.replace(new RegExp(`([^<]+)`, "g"), `$3`) + descriptionHtml = descriptionHtml.replace(new RegExp(`([^<]+)<\/a>`, "g"), `$2`) + descriptionHtml = descriptionHtml.replace(new RegExp(`(?:([0-9]*):)?([0-5]?[0-9]):([0-5][0-9])`, "g"), (_, hours, minutes, seconds) => { + let timeURL, timeDisplay, timeSeconds + if (hours === undefined) { + timeURL = `${minutes}m${seconds}s` + timeDisplay = `${minutes}:${seconds}` + timeSeconds = minutes*60 + + seconds + } else { + timeURL = `${hours}h${minutes}m${seconds}s` + timeDisplay = `${hours}:${minutes}:${seconds}` + timeSeconds = hours*60*60 + minutes*60 + + seconds + } + + const params = new URLSearchParams() + params.set("v", id) + params.set("t", timeURL) + const url = "/watch?" + params + + return pug.render(`a(href=url data-clickable-timestamp=timeSeconds)= timeDisplay`, {url, timeURL, timeDisplay, timeSeconds}) + }) + + return descriptionHtml } /** @@ -125,6 +165,7 @@ function subscriberCountToText(count) { module.exports.timeToPastText = timeToPastText module.exports.lengthSecondsToLengthText = lengthSecondsToLengthText module.exports.normaliseVideoInfo = normaliseVideoInfo +module.exports.rewriteVideoDescription = rewriteVideoDescription module.exports.tToMediaFragment = tToMediaFragment module.exports.viewCountToText = viewCountToText module.exports.subscriberCountToText = subscriberCountToText