Added support for chapters on youtubejs fallback
This commit is contained in:
@@ -103,18 +103,20 @@ export function decodeHtmlCharCodes(str: string): string {
|
||||
return decode(str);
|
||||
}
|
||||
|
||||
export function phaseDescription(content: string): PhasedDescription {
|
||||
export function phaseDescription(content: string, usingYoutubeJs: boolean = false): PhasedDescription {
|
||||
const timestamps: { title: string; time: number; timePretty: string; }[] = [];
|
||||
const lines = content.split('\n');
|
||||
|
||||
// Regular expressions for different timestamp formats
|
||||
const urlRegex = /<a href="([^"]+)"/;
|
||||
const timestampRegex =
|
||||
/<a href="([^"]+)" data-onclick="jump_to_time" data-jump-time="(\d+)">(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/;
|
||||
const timestampRegexInvidious = /<a href="([^"]+)" data-onclick="jump_to_time" data-jump-time="(\d+)">(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/;
|
||||
const timestampRegexYtJs = /&t=(\d+)\s*s.*?<span[^>]*>([^<]*)<\/span>.*?>(.*?)<\/span>/;
|
||||
|
||||
let filteredLines: string[] = [];
|
||||
lines.forEach((line) => {
|
||||
const urlMatch = urlRegex.exec(line);
|
||||
const timestampMatch = timestampRegex.exec(line);
|
||||
// Use appropriate regex based on the `usingYoutubeJs` flag
|
||||
const timestampMatch = (usingYoutubeJs ? timestampRegexYtJs : timestampRegexInvidious).exec(usingYoutubeJs ? line + '</span>' : line);
|
||||
|
||||
if (urlMatch !== null && timestampMatch === null) {
|
||||
// If line contains a URL but not a timestamp, modify the URL
|
||||
@@ -125,13 +127,13 @@ export function phaseDescription(content: string): PhasedDescription {
|
||||
filteredLines.push(modifiedLine);
|
||||
} else if (timestampMatch !== null) {
|
||||
// If line contains a timestamp, extract details and push into timestamps array
|
||||
const time = timestampMatch[2];
|
||||
const timestamp = timestampMatch[3];
|
||||
const title = timestampMatch[4] || '';
|
||||
const time = usingYoutubeJs ? timestampMatch[1] : timestampMatch[2];
|
||||
const timestamp = usingYoutubeJs ? timestampMatch[2] : timestampMatch[3];
|
||||
const title = usingYoutubeJs ? timestampMatch[3] || '' : timestampMatch[4] || '';
|
||||
timestamps.push({
|
||||
time: convertToSeconds(time),
|
||||
// Remove any URL in the timestamp title.
|
||||
title: decodeHtmlCharCodes(title.replace(/<a\b[^>]*>(.*?)<\/a>/gi, '')),
|
||||
// Remove any HTML in the timestamp title.
|
||||
title: decodeHtmlCharCodes(title.replace(/<[^>]+>/g, '').replace(/\n/g, '').trim()),
|
||||
timePretty: timestamp
|
||||
});
|
||||
} else {
|
||||
@@ -144,6 +146,7 @@ export function phaseDescription(content: string): PhasedDescription {
|
||||
return { description: filteredContent, timestamps: timestamps };
|
||||
}
|
||||
|
||||
|
||||
function convertToSeconds(time: string): number {
|
||||
const parts = time.split(':').map((part) => parseInt(part));
|
||||
let seconds = 0;
|
||||
|
||||
@@ -62,7 +62,7 @@ export async function load({ params, url }) {
|
||||
|
||||
return {
|
||||
video: video,
|
||||
content: phaseDescription(video.descriptionHtml),
|
||||
content: phaseDescription(video.descriptionHtml, video.fallbackPatch === 'youtubejs'),
|
||||
playlistId: url.searchParams.get('playlist'),
|
||||
streamed: {
|
||||
personalPlaylists: personalPlaylists,
|
||||
|
||||
Reference in New Issue
Block a user