diff --git a/src/content.ts b/src/content.ts index 63835301..89e78938 100644 --- a/src/content.ts +++ b/src/content.ts @@ -16,6 +16,7 @@ import * as Chat from "./js-components/chat"; import { getCategoryActionType } from "./utils/categoryUtils"; import { SkipButtonControlBar } from "./js-components/skipButtonControlBar"; import { Tooltip } from "./render/Tooltip"; +import { getStartTimeFromUrl } from "./utils/urlParser"; // Hack to get the CSS loaded on permission-based sites (Invidious) utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); @@ -775,22 +776,25 @@ function retryFetch(): void { function startSkipScheduleCheckingForStartSponsors() { if (!switchingVideos && sponsorTimes) { // See if there are any starting sponsors - let startingSegmentTime = -1; + let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1; + let found = false; let startingSegment: SponsorTime = null; for (const time of sponsorTimes) { if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime && getCategoryActionType(time.category) === CategoryActionType.Skippable) { startingSegmentTime = time.segment[0]; startingSegment = time; + found = true; break; } } - if (startingSegmentTime === -1) { + if (!found) { for (const time of sponsorTimesSubmitting) { if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime && getCategoryActionType(time.category) === CategoryActionType.Skippable) { startingSegmentTime = time.segment[0]; startingSegment = time; + found = true; break; } } diff --git a/src/utils/urlParser.ts b/src/utils/urlParser.ts new file mode 100644 index 00000000..37f5067c --- /dev/null +++ b/src/utils/urlParser.ts @@ -0,0 +1,26 @@ + +export function getStartTimeFromUrl(url: string): number { + const urlParams = new URLSearchParams(url); + const time = urlParams?.get('t') || urlParams?.get('time_continue'); + + return urlTimeToSeconds(time); +} + +export function urlTimeToSeconds(time: string): number { + if (!time) { + return 0; + } + + const re = /(?:(?\d{1,3})h)?(?:(?\d{1,2})m)?(?\d+)s?/; + const match = re.exec(time); + + if (match) { + const hours = parseInt(match.groups.hours ?? '0', 10); + const minutes = parseInt(match.groups.minutes ?? '0', 10); + const seconds = parseInt(match.groups.seconds ?? '0', 10); + + return hours * 3600 + minutes * 60 + seconds; + } else if (/\d+/.test(time)) { + return parseInt(time, 10); + } +} \ No newline at end of file diff --git a/test/urlParser.test.ts b/test/urlParser.test.ts new file mode 100644 index 00000000..32cf1568 --- /dev/null +++ b/test/urlParser.test.ts @@ -0,0 +1,27 @@ +import { getStartTimeFromUrl } from '../src/utils/urlParser'; + +describe("getStartTimeFromUrl", () => { + it("parses with a number", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=123")).toBe(123); + }); + + it("parses with a seconds", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=123s")).toBe(123); + }); + + it("parses with a minutes", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=23m3s")).toBe(23 * 60 + 3); + }); + + it("parses with a hours", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=1h2m3s")).toBe(1 * 60 * 60 + 2 * 60 + 3); + }); + + it("works with time_continue", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&time_continue=123")).toBe(123); + }); + + it("works with no time", () => { + expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ")).toBe(0); + }); +}); \ No newline at end of file