Subscribe Rules

This commit is contained in:
Gabe Yuan
2023-08-20 19:27:29 +08:00
parent a8caa34bbe
commit 7ec43a1d3f
12 changed files with 491 additions and 105 deletions

View File

@@ -6,10 +6,11 @@ import {
STOKEY_FAB,
GLOBLA_RULE,
GLOBAL_KEY,
BUILTIN_RULES,
DEFAULT_SUBRULES_LIST,
} from "../config";
import { browser } from "./browser";
import { isMatch } from "./utils";
import { tryLoadRules } from "./rules";
/**
* 获取节点列表并转为数组
@@ -53,9 +54,21 @@ export const setFab = async (obj) => await storage.setObj(STOKEY_FAB, obj);
* @param {string} href
* @returns
*/
export const matchRule = (rules, href, { injectRules }) => {
export const matchRule = async (
rules,
href,
{ injectRules, subrulesList = DEFAULT_SUBRULES_LIST }
) => {
if (injectRules) {
rules.splice(-1, 0, ...BUILTIN_RULES);
try {
const selectedSub = subrulesList.find((item) => item.selected);
if (selectedSub?.url) {
const subRules = await tryLoadRules(selectedSub.url);
rules.splice(-1, 0, ...subRules);
}
} catch (err) {
console.log("[load injectRules]", err);
}
}
const rule = rules.find((rule) =>

View File

@@ -1,3 +1,11 @@
/**
* 任务池
* @param {*} fn
* @param {*} preFn
* @param {*} _interval
* @param {*} _limit
* @returns
*/
export const taskPool = (fn, preFn, _interval = 100, _limit = 100) => {
const pool = [];
const maxRetry = 2; // 最大重试次数
@@ -6,11 +14,6 @@ export const taskPool = (fn, preFn, _interval = 100, _limit = 100) => {
let interval = _interval; // 间隔时间
let timer = null;
/**
* 任务池
* @param {*} item
* @param {*} preArgs
*/
const handleTask = async (item, preArgs) => {
curCount++;
const { args, resolve, reject, retry } = item;

99
src/libs/rules.js Normal file
View File

@@ -0,0 +1,99 @@
import storage from "./storage";
import { fetchPolyfill } from "./fetch";
import { matchValue, type } from "./utils";
import {
STOKEY_RULESCACHE_PREFIX,
GLOBAL_KEY,
OPT_TRANS_ALL,
OPT_STYLE_ALL,
OPT_LANGS_FROM,
OPT_LANGS_TO,
} from "../config";
const fromLangs = OPT_LANGS_FROM.map((item) => item[0]);
const toLangs = OPT_LANGS_TO.map((item) => item[0]);
/**
* 检查过滤rules
* @param {*} rules
* @returns
*/
export const checkRules = (rules) => {
if (type(rules) === "string") {
rules = JSON.parse(rules);
}
if (type(rules) !== "array") {
throw new Error("data error");
}
const patternSet = new Set();
rules = rules
.filter((rule) => type(rule) === "object")
.filter(({ pattern }) => {
if (type(pattern) !== "string" || patternSet.has(pattern.trim())) {
return false;
}
patternSet.add(pattern.trim());
return true;
})
.map(
({
pattern,
selector,
translator,
fromLang,
toLang,
textStyle,
transOpen,
bgColor,
}) => ({
pattern: pattern.trim(),
selector: type(selector) === "string" ? selector : "",
bgColor: type(bgColor) === "string" ? bgColor : "",
translator: matchValue([GLOBAL_KEY, ...OPT_TRANS_ALL], translator),
fromLang: matchValue([GLOBAL_KEY, ...fromLangs], fromLang),
toLang: matchValue([GLOBAL_KEY, ...toLangs], toLang),
textStyle: matchValue([GLOBAL_KEY, ...OPT_STYLE_ALL], textStyle),
transOpen: matchValue([GLOBAL_KEY, "true", "false"], transOpen),
})
);
return rules;
};
/**
* 本地rules缓存
*/
export const rulesCache = {
fetch: async (url) => {
const res = await fetchPolyfill(url);
const rules = checkRules(res).filter(
(rule) => rule.pattern.replaceAll(GLOBAL_KEY, "") !== ""
);
return rules;
},
set: async (url, rules) => {
await storage.setObj(`${STOKEY_RULESCACHE_PREFIX}${url}`, rules);
},
get: async (url) => {
return await storage.getObj(`${STOKEY_RULESCACHE_PREFIX}${url}`);
},
del: async (url) => {
await storage.del(`${STOKEY_RULESCACHE_PREFIX}${url}`);
},
};
/**
* 从缓存或远程加载订阅的rules
* @param {*} url
* @returns
*/
export const tryLoadRules = async (url) => {
let rules = await rulesCache.get(url);
if (rules?.length) {
return rules;
}
rules = await rulesCache.fetch(url);
await rulesCache.set(url, rules);
return rules;
};

View File

@@ -88,3 +88,13 @@ export const isMatch = (s, p) => {
return p.slice(pIndex).replaceAll("*", "") === "";
};
/**
* 类型检查
* @param {*} o
* @returns
*/
export const type = (o) => {
const s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};