mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-11 05:57:07 +03:00
Add channel skip profiles
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
|
||||
import Config from "../config";
|
||||
import { getSkipProfileBool } from "./skipProfiles";
|
||||
|
||||
export function getControls(): HTMLElement {
|
||||
const controlsSelectors = [
|
||||
@@ -70,7 +70,7 @@ export function getExistingChapters(currentVideoID: VideoID, duration: number):
|
||||
if (title?.textContent?.includes("Key moment")) return [];
|
||||
|
||||
const autogenerated = hasAutogeneratedChapters();
|
||||
if (!Config.config.showAutogeneratedChapters && autogenerated) return [];
|
||||
if (!getSkipProfileBool("showAutogeneratedChapters") && autogenerated) return [];
|
||||
|
||||
const chapters: SponsorTime[] = [];
|
||||
// .ytp-timed-markers-container indicates that key-moments are present, which should not be divided
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DataCache } from "../../maze-utils/src/cache";
|
||||
import { getHash, HashedValue } from "../../maze-utils/src/hash";
|
||||
import Config, { } from "../config";
|
||||
import * as CompileConfig from "../../config.json";
|
||||
import { ActionType, ActionTypes, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { ActionTypes, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { getHashParams } from "./pageUtils";
|
||||
import { asyncRequestToServer } from "./requests";
|
||||
import { extensionUserAgent } from "../../maze-utils/src";
|
||||
@@ -60,12 +60,9 @@ async function fetchSegmentsForVideo(videoID: VideoID): Promise<SegmentResponse>
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const enabledActionTypes = getEnabledActionTypes();
|
||||
|
||||
const receivedSegments: SponsorTime[] = JSON.parse(response.responseText)
|
||||
?.filter((video) => video.videoID === videoID)
|
||||
?.map((video) => video.segments)?.[0]
|
||||
?.filter((segment) => enabledActionTypes.includes(segment.actionType))
|
||||
?.map((segment) => ({
|
||||
...segment,
|
||||
source: SponsorSourceType.Server
|
||||
@@ -90,16 +87,4 @@ async function fetchSegmentsForVideo(videoID: VideoID): Promise<SegmentResponse>
|
||||
segments: null,
|
||||
status: response.status
|
||||
};
|
||||
}
|
||||
|
||||
function getEnabledActionTypes(forceFullVideo = false): ActionType[] {
|
||||
const actionTypes = [ActionType.Skip, ActionType.Poi, ActionType.Chapter];
|
||||
if (Config.config.muteSegments) {
|
||||
actionTypes.push(ActionType.Mute);
|
||||
}
|
||||
if (Config.config.fullVideoSegments || forceFullVideo) {
|
||||
actionTypes.push(ActionType.Full);
|
||||
}
|
||||
|
||||
return actionTypes;
|
||||
}
|
||||
97
src/utils/skipProfiles.ts
Normal file
97
src/utils/skipProfiles.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { getChannelIDInfo, getVideoID } from "../../maze-utils/src/video";
|
||||
import Config, { ConfigurationID, CustomConfiguration } from "../config";
|
||||
import { SponsorHideType, SponsorTime } from "../types";
|
||||
|
||||
let currentTabSkipProfile: ConfigurationID = null;
|
||||
|
||||
export function getSkipProfileIDForTime(): ConfigurationID | null {
|
||||
if (Config.local.skipProfileTemp !== null && Config.local.skipProfileTemp.time > Date.now() - 60 * 60 * 1000) {
|
||||
return Config.local.skipProfileTemp.configID;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getSkipProfileIDForTab(): ConfigurationID | null {
|
||||
return currentTabSkipProfile;
|
||||
}
|
||||
|
||||
export function setCurrentTabSkipProfile(configID: ConfigurationID | null) {
|
||||
currentTabSkipProfile = configID ?? null;
|
||||
}
|
||||
|
||||
export function getSkipProfileIDForVideo(): ConfigurationID | null {
|
||||
return Config.local.channelSkipProfileIDs[getVideoID()] ?? null;
|
||||
}
|
||||
|
||||
export function getSkipProfileIDForChannel(): ConfigurationID | null {
|
||||
const channelInfo = getChannelIDInfo();
|
||||
|
||||
if (!channelInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Config.local.channelSkipProfileIDs[channelInfo.id]
|
||||
?? Config.local.channelSkipProfileIDs[channelInfo.author]
|
||||
?? null;
|
||||
}
|
||||
|
||||
export function getSkipProfileID(): ConfigurationID | null {
|
||||
const configID =
|
||||
getSkipProfileIDForTime()
|
||||
?? getSkipProfileIDForTab()
|
||||
?? getSkipProfileIDForVideo()
|
||||
?? getSkipProfileIDForChannel();
|
||||
|
||||
return configID ?? null;
|
||||
}
|
||||
|
||||
export function getSkipProfile(): CustomConfiguration | null {
|
||||
const configID = getSkipProfileID();
|
||||
|
||||
if (configID) {
|
||||
return Config.local.skipProfiles[configID];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
type SkipProfileBoolKey =
|
||||
"showAutogeneratedChapters"
|
||||
| "autoSkipOnMusicVideos"
|
||||
| "skipNonMusicOnlyOnYoutubeMusic"
|
||||
| "muteSegments"
|
||||
| "fullVideoSegments"
|
||||
| "manualSkipOnFullVideo";
|
||||
|
||||
export function getSkipProfileBool(key: SkipProfileBoolKey): boolean {
|
||||
return getSkipProfileValue<boolean>(key);
|
||||
}
|
||||
|
||||
export function getSkipProfileNum(key: "minDuration"): number {
|
||||
return getSkipProfileValue<number>(key);
|
||||
}
|
||||
|
||||
function getSkipProfileValue<T>(key: keyof CustomConfiguration): T {
|
||||
const profile = getSkipProfile();
|
||||
if (profile && profile[key] !== undefined) {
|
||||
return profile[key] as T;
|
||||
}
|
||||
|
||||
return Config.config[key];
|
||||
}
|
||||
|
||||
export function hideTooShortSegments(sponsorTimes: SponsorTime[]) {
|
||||
const minDuration = getSkipProfileNum("minDuration");
|
||||
|
||||
if (minDuration !== 0) {
|
||||
for (const segment of sponsorTimes) {
|
||||
const duration = segment.segment[1] - segment.segment[0];
|
||||
if (duration > 0 && duration < minDuration && (segment.hidden === SponsorHideType.Visible || SponsorHideType.MinimumDuration)) {
|
||||
segment.hidden = SponsorHideType.MinimumDuration;
|
||||
} else if (segment.hidden === SponsorHideType.MinimumDuration) {
|
||||
segment.hidden = SponsorHideType.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { getCurrentPageTitle } from "../../maze-utils/src/elements";
|
||||
import { getChannelIDInfo, getVideoDuration } from "../../maze-utils/src/video";
|
||||
import Config from "../config";
|
||||
import { CategorySelection, CategorySkipOption, SponsorSourceType, SponsorTime } from "../types";
|
||||
import { getSkipProfile, getSkipProfileBool } from "./skipProfiles";
|
||||
import { VideoLabelsCacheData } from "./videoLabels";
|
||||
|
||||
export interface Permission {
|
||||
@@ -53,12 +54,28 @@ export interface AdvancedSkipRuleSet {
|
||||
}
|
||||
|
||||
export function getCategorySelection(segment: SponsorTime | VideoLabelsCacheData): CategorySelection {
|
||||
// First check skip rules
|
||||
for (const ruleSet of Config.local.skipRules) {
|
||||
if (ruleSet.rules.every((rule) => isSkipRulePassing(segment, rule))) {
|
||||
return { name: segment.category, option: ruleSet.skipOption } as CategorySelection;
|
||||
}
|
||||
}
|
||||
|
||||
// Action type filters
|
||||
if ("actionType" in segment && (segment as SponsorTime).actionType === "mute" && !getSkipProfileBool("muteSegments")) {
|
||||
return { name: segment.category, option: CategorySkipOption.Disabled } as CategorySelection;
|
||||
}
|
||||
|
||||
// Then check skip profile
|
||||
const profile = getSkipProfile();
|
||||
if (profile) {
|
||||
const profileSelection = profile.categorySelections.find(selection => selection.name === segment.category);
|
||||
if (profileSelection) {
|
||||
return profileSelection;
|
||||
}
|
||||
}
|
||||
|
||||
// Then fallback to default
|
||||
for (const selection of Config.config.categorySelections) {
|
||||
if (selection.name === segment.category) {
|
||||
return selection;
|
||||
|
||||
Reference in New Issue
Block a user