mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-08 20:47:11 +03:00
Move skip rule code to new file
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import * as React from "react";
|
||||
import * as CompileConfig from "../../../config.json";
|
||||
|
||||
import Config, { AdvancedSkipRuleSet, SkipRuleAttribute, SkipRuleOperator } from "../../config";
|
||||
import Config from "../../config";
|
||||
import { AdvancedSkipRuleSet, SkipRuleAttribute, SkipRuleOperator } from "../../utils/skipRule";
|
||||
import { CategorySkipOption } from "../../types";
|
||||
|
||||
let configSaveTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
@@ -3,45 +3,7 @@ import * as invidiousList from "../ci/invidiouslist.json";
|
||||
import { Category, CategorySelection, CategorySkipOption, NoticeVisibilityMode, PreviewBarOption, SponsorTime, VideoID, SponsorHideType } from "./types";
|
||||
import { Keybind, ProtoConfig, keybindEquals } from "../maze-utils/src/config";
|
||||
import { HashedValue } from "../maze-utils/src/hash";
|
||||
|
||||
export interface Permission {
|
||||
canSubmit: boolean;
|
||||
}
|
||||
|
||||
export enum SkipRuleAttribute {
|
||||
StartTime = "startTime",
|
||||
EndTime = "endTime",
|
||||
Duration = "duration",
|
||||
StartTimePercent = "startTimePercent",
|
||||
EndTimePercent = "endTimePercent",
|
||||
DurationPercent = "durationPercent",
|
||||
Category = "category",
|
||||
Description = "description",
|
||||
Source = "source"
|
||||
}
|
||||
|
||||
export enum SkipRuleOperator {
|
||||
Less = "<",
|
||||
LessOrEqual = "<=",
|
||||
Greater = ">",
|
||||
GreaterOrEqual = ">=",
|
||||
Equal = "==",
|
||||
NotEqual = "!=",
|
||||
Contains = "*=",
|
||||
Regex = "~="
|
||||
}
|
||||
|
||||
export interface AdvancedSkipRule {
|
||||
attribute: SkipRuleAttribute;
|
||||
operator: SkipRuleOperator;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
export interface AdvancedSkipRuleSet {
|
||||
rules: AdvancedSkipRule[];
|
||||
skipOption: CategorySkipOption;
|
||||
comment: string;
|
||||
}
|
||||
import { Permission, AdvancedSkipRuleSet } from "./utils/skipRule";
|
||||
|
||||
interface SBConfig {
|
||||
userID: string;
|
||||
|
||||
@@ -51,7 +51,8 @@ import { asyncRequestToServer } from "./utils/requests";
|
||||
import { isMobileControlsOpen } from "./utils/mobileUtils";
|
||||
import { defaultPreviewTime } from "./utils/constants";
|
||||
import { onVideoPage } from "../maze-utils/src/pageInfo";
|
||||
import { getCategoryDefaultSelection, getCategorySelection, getSegmentsForVideo } from "./utils/segmentData";
|
||||
import { getSegmentsForVideo } from "./utils/segmentData";
|
||||
import { getCategoryDefaultSelection, getCategorySelection } from "./utils/skipRule";
|
||||
|
||||
cleanPage();
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { DataCache } from "../../maze-utils/src/cache";
|
||||
import { getHash, HashedValue } from "../../maze-utils/src/hash";
|
||||
import Config, { AdvancedSkipRule, SkipRuleAttribute, SkipRuleOperator } from "../config";
|
||||
import Config, { } from "../config";
|
||||
import * as CompileConfig from "../../config.json";
|
||||
import { ActionType, ActionTypes, CategorySelection, CategorySkipOption, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { ActionType, ActionTypes, CategorySkipOption, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||
import { getHashParams } from "./pageUtils";
|
||||
import { asyncRequestToServer } from "./requests";
|
||||
import { extensionUserAgent } from "../../maze-utils/src";
|
||||
import { VideoLabelsCacheData } from "./videoLabels";
|
||||
import { getVideoDuration } from "../../maze-utils/src/video";
|
||||
import { getCategorySelection } from "./skipRule";
|
||||
|
||||
const segmentDataCache = new DataCache<VideoID, SegmentResponse>(() => {
|
||||
return {
|
||||
@@ -106,101 +105,3 @@ function getEnabledActionTypes(forceFullVideo = false): ActionType[] {
|
||||
|
||||
return actionTypes;
|
||||
}
|
||||
|
||||
export function getCategorySelection(segment: SponsorTime | VideoLabelsCacheData): CategorySelection {
|
||||
for (const ruleSet of Config.local.skipRules) {
|
||||
if (ruleSet.rules.every((rule) => isSkipRulePassing(segment, rule))) {
|
||||
return { name: segment.category, option: ruleSet.skipOption } as CategorySelection;
|
||||
}
|
||||
}
|
||||
|
||||
for (const selection of Config.config.categorySelections) {
|
||||
if (selection.name === segment.category) {
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
return { name: segment.category, option: CategorySkipOption.Disabled} as CategorySelection;
|
||||
}
|
||||
|
||||
function getSkipRuleValue(segment: SponsorTime | VideoLabelsCacheData, rule: AdvancedSkipRule): string | number | undefined {
|
||||
switch (rule.attribute) {
|
||||
case SkipRuleAttribute.StartTime:
|
||||
return (segment as SponsorTime).segment?.[0];
|
||||
case SkipRuleAttribute.EndTime:
|
||||
return (segment as SponsorTime).segment?.[1];
|
||||
case SkipRuleAttribute.Duration:
|
||||
return (segment as SponsorTime).segment?.[1] - (segment as SponsorTime).segment?.[0];
|
||||
case SkipRuleAttribute.StartTimePercent: {
|
||||
const startTime = (segment as SponsorTime).segment?.[0];
|
||||
if (startTime === undefined) return undefined;
|
||||
|
||||
return startTime / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.EndTimePercent: {
|
||||
const endTime = (segment as SponsorTime).segment?.[1];
|
||||
if (endTime === undefined) return undefined;
|
||||
|
||||
return endTime / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.DurationPercent: {
|
||||
const startTime = (segment as SponsorTime).segment?.[0];
|
||||
const endTime = (segment as SponsorTime).segment?.[1];
|
||||
if (startTime === undefined || endTime === undefined) return undefined;
|
||||
|
||||
return (endTime - startTime) / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.Category:
|
||||
return segment.category;
|
||||
case SkipRuleAttribute.Description:
|
||||
return (segment as SponsorTime).description || "";
|
||||
case SkipRuleAttribute.Source:
|
||||
switch ((segment as SponsorTime).source) {
|
||||
case SponsorSourceType.Local:
|
||||
return "local";
|
||||
case SponsorSourceType.YouTube:
|
||||
return "youtube";
|
||||
case SponsorSourceType.Autogenerated:
|
||||
return "autogenerated";
|
||||
case SponsorSourceType.Server:
|
||||
return "server";
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function isSkipRulePassing(segment: SponsorTime | VideoLabelsCacheData, rule: AdvancedSkipRule): boolean {
|
||||
const value = getSkipRuleValue(segment, rule);
|
||||
|
||||
switch (rule.operator) {
|
||||
case SkipRuleOperator.Less:
|
||||
return typeof value === "number" && value < (rule.value as number);
|
||||
case SkipRuleOperator.LessOrEqual:
|
||||
return typeof value === "number" && value <= (rule.value as number);
|
||||
case SkipRuleOperator.Greater:
|
||||
return typeof value === "number" && value > (rule.value as number);
|
||||
case SkipRuleOperator.GreaterOrEqual:
|
||||
return typeof value === "number" && value >= (rule.value as number);
|
||||
case SkipRuleOperator.Equal:
|
||||
return value === rule.value;
|
||||
case SkipRuleOperator.NotEqual:
|
||||
return value !== rule.value;
|
||||
case SkipRuleOperator.Contains:
|
||||
return String(value).toLocaleLowerCase().includes(String(rule.value).toLocaleLowerCase());
|
||||
case SkipRuleOperator.Regex:
|
||||
return new RegExp(rule.value as string).test(String(value));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getCategoryDefaultSelection(category: string): CategorySelection {
|
||||
for (const selection of Config.config.categorySelections) {
|
||||
if (selection.name === category) {
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
return { name: category, option: CategorySkipOption.Disabled} as CategorySelection;
|
||||
}
|
||||
141
src/utils/skipRule.ts
Normal file
141
src/utils/skipRule.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { getVideoDuration } from "../../maze-utils/src/video";
|
||||
import Config from "../config";
|
||||
import { CategorySelection, CategorySkipOption, SponsorSourceType, SponsorTime } from "../types";
|
||||
import { VideoLabelsCacheData } from "./videoLabels";
|
||||
|
||||
export interface Permission {
|
||||
canSubmit: boolean;
|
||||
}
|
||||
|
||||
export enum SkipRuleAttribute {
|
||||
StartTime = "startTime",
|
||||
EndTime = "endTime",
|
||||
Duration = "duration",
|
||||
StartTimePercent = "startTimePercent",
|
||||
EndTimePercent = "endTimePercent",
|
||||
DurationPercent = "durationPercent",
|
||||
Category = "category",
|
||||
Description = "description",
|
||||
Source = "source"
|
||||
}
|
||||
|
||||
export enum SkipRuleOperator {
|
||||
Less = "<",
|
||||
LessOrEqual = "<=",
|
||||
Greater = ">",
|
||||
GreaterOrEqual = ">=",
|
||||
Equal = "==",
|
||||
NotEqual = "!=",
|
||||
Contains = "*=",
|
||||
Regex = "~="
|
||||
}
|
||||
|
||||
export interface AdvancedSkipRule {
|
||||
attribute: SkipRuleAttribute;
|
||||
operator: SkipRuleOperator;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
export interface AdvancedSkipRuleSet {
|
||||
rules: AdvancedSkipRule[];
|
||||
skipOption: CategorySkipOption;
|
||||
comment: string;
|
||||
}
|
||||
|
||||
export function getCategorySelection(segment: SponsorTime | VideoLabelsCacheData): CategorySelection {
|
||||
for (const ruleSet of Config.local.skipRules) {
|
||||
if (ruleSet.rules.every((rule) => isSkipRulePassing(segment, rule))) {
|
||||
return { name: segment.category, option: ruleSet.skipOption } as CategorySelection;
|
||||
}
|
||||
}
|
||||
|
||||
for (const selection of Config.config.categorySelections) {
|
||||
if (selection.name === segment.category) {
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
return { name: segment.category, option: CategorySkipOption.Disabled} as CategorySelection;
|
||||
}
|
||||
|
||||
function getSkipRuleValue(segment: SponsorTime | VideoLabelsCacheData, rule: AdvancedSkipRule): string | number | undefined {
|
||||
switch (rule.attribute) {
|
||||
case SkipRuleAttribute.StartTime:
|
||||
return (segment as SponsorTime).segment?.[0];
|
||||
case SkipRuleAttribute.EndTime:
|
||||
return (segment as SponsorTime).segment?.[1];
|
||||
case SkipRuleAttribute.Duration:
|
||||
return (segment as SponsorTime).segment?.[1] - (segment as SponsorTime).segment?.[0];
|
||||
case SkipRuleAttribute.StartTimePercent: {
|
||||
const startTime = (segment as SponsorTime).segment?.[0];
|
||||
if (startTime === undefined) return undefined;
|
||||
|
||||
return startTime / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.EndTimePercent: {
|
||||
const endTime = (segment as SponsorTime).segment?.[1];
|
||||
if (endTime === undefined) return undefined;
|
||||
|
||||
return endTime / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.DurationPercent: {
|
||||
const startTime = (segment as SponsorTime).segment?.[0];
|
||||
const endTime = (segment as SponsorTime).segment?.[1];
|
||||
if (startTime === undefined || endTime === undefined) return undefined;
|
||||
|
||||
return (endTime - startTime) / getVideoDuration() * 100;
|
||||
}
|
||||
case SkipRuleAttribute.Category:
|
||||
return segment.category;
|
||||
case SkipRuleAttribute.Description:
|
||||
return (segment as SponsorTime).description || "";
|
||||
case SkipRuleAttribute.Source:
|
||||
switch ((segment as SponsorTime).source) {
|
||||
case SponsorSourceType.Local:
|
||||
return "local";
|
||||
case SponsorSourceType.YouTube:
|
||||
return "youtube";
|
||||
case SponsorSourceType.Autogenerated:
|
||||
return "autogenerated";
|
||||
case SponsorSourceType.Server:
|
||||
return "server";
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function isSkipRulePassing(segment: SponsorTime | VideoLabelsCacheData, rule: AdvancedSkipRule): boolean {
|
||||
const value = getSkipRuleValue(segment, rule);
|
||||
|
||||
switch (rule.operator) {
|
||||
case SkipRuleOperator.Less:
|
||||
return typeof value === "number" && value < (rule.value as number);
|
||||
case SkipRuleOperator.LessOrEqual:
|
||||
return typeof value === "number" && value <= (rule.value as number);
|
||||
case SkipRuleOperator.Greater:
|
||||
return typeof value === "number" && value > (rule.value as number);
|
||||
case SkipRuleOperator.GreaterOrEqual:
|
||||
return typeof value === "number" && value >= (rule.value as number);
|
||||
case SkipRuleOperator.Equal:
|
||||
return value === rule.value;
|
||||
case SkipRuleOperator.NotEqual:
|
||||
return value !== rule.value;
|
||||
case SkipRuleOperator.Contains:
|
||||
return String(value).toLocaleLowerCase().includes(String(rule.value).toLocaleLowerCase());
|
||||
case SkipRuleOperator.Regex:
|
||||
return new RegExp(rule.value as string).test(String(value));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getCategoryDefaultSelection(category: string): CategorySelection {
|
||||
for (const selection of Config.config.categorySelections) {
|
||||
if (selection.name === category) {
|
||||
return selection;
|
||||
}
|
||||
}
|
||||
return { name: category, option: CategorySkipOption.Disabled} as CategorySelection;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { Category, CategorySkipOption, VideoID } from "../types";
|
||||
import { getHash } from "../../maze-utils/src/hash";
|
||||
import { logWarn } from "./logger";
|
||||
import { asyncRequestToServer } from "./requests";
|
||||
import { getCategorySelection } from "./segmentData";
|
||||
import { getCategorySelection } from "./skipRule";
|
||||
|
||||
export interface VideoLabelsCacheData {
|
||||
category: Category;
|
||||
|
||||
Reference in New Issue
Block a user