mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-09 04:57:09 +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 React from "react";
|
||||||
import * as CompileConfig from "../../../config.json";
|
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";
|
import { CategorySkipOption } from "../../types";
|
||||||
|
|
||||||
let configSaveTimeout: NodeJS.Timeout | null = null;
|
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 { Category, CategorySelection, CategorySkipOption, NoticeVisibilityMode, PreviewBarOption, SponsorTime, VideoID, SponsorHideType } from "./types";
|
||||||
import { Keybind, ProtoConfig, keybindEquals } from "../maze-utils/src/config";
|
import { Keybind, ProtoConfig, keybindEquals } from "../maze-utils/src/config";
|
||||||
import { HashedValue } from "../maze-utils/src/hash";
|
import { HashedValue } from "../maze-utils/src/hash";
|
||||||
|
import { Permission, AdvancedSkipRuleSet } from "./utils/skipRule";
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SBConfig {
|
interface SBConfig {
|
||||||
userID: string;
|
userID: string;
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ import { asyncRequestToServer } from "./utils/requests";
|
|||||||
import { isMobileControlsOpen } from "./utils/mobileUtils";
|
import { isMobileControlsOpen } from "./utils/mobileUtils";
|
||||||
import { defaultPreviewTime } from "./utils/constants";
|
import { defaultPreviewTime } from "./utils/constants";
|
||||||
import { onVideoPage } from "../maze-utils/src/pageInfo";
|
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();
|
cleanPage();
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { DataCache } from "../../maze-utils/src/cache";
|
import { DataCache } from "../../maze-utils/src/cache";
|
||||||
import { getHash, HashedValue } from "../../maze-utils/src/hash";
|
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 * 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 { getHashParams } from "./pageUtils";
|
||||||
import { asyncRequestToServer } from "./requests";
|
import { asyncRequestToServer } from "./requests";
|
||||||
import { extensionUserAgent } from "../../maze-utils/src";
|
import { extensionUserAgent } from "../../maze-utils/src";
|
||||||
import { VideoLabelsCacheData } from "./videoLabels";
|
import { getCategorySelection } from "./skipRule";
|
||||||
import { getVideoDuration } from "../../maze-utils/src/video";
|
|
||||||
|
|
||||||
const segmentDataCache = new DataCache<VideoID, SegmentResponse>(() => {
|
const segmentDataCache = new DataCache<VideoID, SegmentResponse>(() => {
|
||||||
return {
|
return {
|
||||||
@@ -105,102 +104,4 @@ function getEnabledActionTypes(forceFullVideo = false): ActionType[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return actionTypes;
|
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 { getHash } from "../../maze-utils/src/hash";
|
||||||
import { logWarn } from "./logger";
|
import { logWarn } from "./logger";
|
||||||
import { asyncRequestToServer } from "./requests";
|
import { asyncRequestToServer } from "./requests";
|
||||||
import { getCategorySelection } from "./segmentData";
|
import { getCategorySelection } from "./skipRule";
|
||||||
|
|
||||||
export interface VideoLabelsCacheData {
|
export interface VideoLabelsCacheData {
|
||||||
category: Category;
|
category: Category;
|
||||||
|
|||||||
Reference in New Issue
Block a user