Fix the localised description containing broken URLs (#2572)

* Fix the localised description containing broken URLs

* Fix hashtag handling in title and description
This commit is contained in:
absidue 2022-09-19 14:49:30 +02:00 committed by GitHub
parent 8fa182e246
commit 76a9e5c3c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 65 additions and 3 deletions

View File

@ -271,7 +271,7 @@ export default Vue.extend({
}
try {
// workaround for title localization
this.videoTitle = result.response.contents.twoColumnWatchNextResults.results.results.contents[0].videoPrimaryInfoRenderer.title.runs[0].text
this.videoTitle = result.response.contents.twoColumnWatchNextResults.results.results.contents[0].videoPrimaryInfoRenderer.title.runs.map(run => run.text).join('')
} catch (err) {
console.error('Failed to extract localised video title, falling back to the standard one.', err)
// if the workaround for localization fails, this sets the title to the potentially non-localized value
@ -302,8 +302,20 @@ export default Vue.extend({
this.videoPublished = new Date(result.videoDetails.publishDate.replace('-', '/')).getTime()
try {
// workaround for description localization
const descriptionLines = result.response.contents.twoColumnWatchNextResults.results.results.contents[1].videoSecondaryInfoRenderer.description?.runs
this.videoDescription = descriptionLines?.map(line => line.text).join('') ?? ''
const descriptionRuns = result.response.contents.twoColumnWatchNextResults.results.results.contents[1].videoSecondaryInfoRenderer.description?.runs
if (!Array.isArray(descriptionRuns)) {
// eslint-disable-next-line no-throw-literal
throw ['not an array', descriptionRuns]
}
const fallbackDescription = result.player_response.videoDetails.shortDescription
// YouTube truncates links in the localised description
// so we need to fix them here, so that autolinker can do it's job properly later on
this.videoDescription = descriptionRuns
.map(run => this.processDescriptionPart(run, fallbackDescription))
.join('')
} catch (err) {
console.error('Failed to extract localised video description, falling back to the standard one.', err)
// if the workaround for localization fails, this sets the description to the potentially non-localized value
@ -781,6 +793,56 @@ export default Vue.extend({
})
},
processDescriptionPart(part, fallbackDescription) {
const timestampRegex = /^([0-9]+:)?[0-9]+:[0-9]+$/
if (typeof part.navigationEndpoint === 'undefined' || part.navigationEndpoint === null || part.text.startsWith('#')) {
return part.text
}
if (part.navigationEndpoint.urlEndpoint) {
const urlWithTracking = part.navigationEndpoint.urlEndpoint.url
const url = new URL(urlWithTracking)
if (url.hostname === 'www.youtube.com' && url.pathname === '/redirect' && url.searchParams.has('q')) {
// remove utm tracking parameters
const realURL = new URL(url.searchParams.get('q'))
realURL.searchParams.delete('utm_source')
realURL.searchParams.delete('utm_medium')
realURL.searchParams.delete('utm_campaign')
realURL.searchParams.delete('utm_term')
realURL.searchParams.delete('utm_content')
return realURL.toString()
} else if (fallbackDescription.includes(urlWithTracking)) {
// this is probably a special YouTube URL like http://www.youtube.com/approachingnirvana
// only use it if it exists in the fallback description
// otherwise assume YouTube has changed it's tracking URLs and throw an error
return urlWithTracking
}
// eslint-disable-next-line no-throw-literal
throw `Failed to extract real URL from tracking URL: ${urlWithTracking}`
} else if (part.navigationEndpoint.watchEndpoint) {
if (timestampRegex.test(part.text)) {
return part.text
}
const watchEndpoint = part.navigationEndpoint.watchEndpoint
let videoURL = `https://www.youtube.com/watch?v=${watchEndpoint.videoId}`
if (watchEndpoint.startTimeSeconds !== 0) {
videoURL += `&t=${watchEndpoint.startTimeSeconds}s`
}
return videoURL
} else {
// Some YouTube URLs don't have the urlEndpoint so we handle them here
const path = part.navigationEndpoint.commandMetadata.webCommandMetadata.url
return `https://www.youtube.com${path}`
}
},
addToHistory: function (watchProgress) {
const videoData = {
videoId: this.videoId,