Skip to content

Commit ebfb007

Browse files
authored
v4.3.18 (#305)
2 parents e7ea9e3 + 5e883de commit ebfb007

File tree

16 files changed

+842
-565
lines changed

16 files changed

+842
-565
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# CHANGELOG
22

3+
## 4.3.18
4+
5+
- 新增:评论区 隐藏大表情弹框
6+
- 新增:动态过滤支持白名单
7+
- 修复:动态过滤顶栏动态列表失效问题
8+
- 更新:排除页面列表
9+
- 更新:部分功能细节
10+
311
## 4.3.17
412

513
- 新增:播放页 隐藏举报按钮

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484

8585
### 2. 视频过滤
8686

87-
- **每个页面有独立的功能开关,但黑名单、白名单全站共用一份**
87+
- **每个页面有独立的功能开关,但标题关键词黑、白名单全站共用一份**
8888
- **白名单权限高于黑名单,命中白名单的视频不会被隐藏**
8989
- 启用 UP 主过滤后,右键单击 UP 主即可屏蔽
9090
- 启用 BV 号过滤后,右键单击视频标题即可屏蔽

package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@
1818
"p-limit": "^6.2.0",
1919
"pinia": "^2.3.1",
2020
"universal-cookie": "^7.2.2",
21-
"vue": "^3.5.27"
21+
"vue": "^3.5.30"
2222
},
2323
"devDependencies": {
24-
"@eslint/js": "^9.39.2",
24+
"@eslint/js": "^9.39.4",
2525
"@thedutchcoder/postcss-rem-to-px": "^0.0.2",
2626
"@vitejs/plugin-vue": "^5.2.4",
27-
"autoprefixer": "^10.4.23",
28-
"eslint": "^9.39.2",
27+
"autoprefixer": "^10.4.27",
28+
"eslint": "^9.39.4",
2929
"eslint-config-prettier": "^9.1.2",
3030
"eslint-plugin-vue": "^9.33.0",
3131
"globals": "^15.15.0",
3232
"husky": "^9.1.7",
3333
"lint-staged": "^15.5.2",
34-
"postcss": "^8.5.6",
34+
"postcss": "^8.5.8",
3535
"prettier": "3.4.2",
3636
"prettier-plugin-tailwindcss": "^0.6.14",
3737
"stylelint": "^16.26.1",
3838
"stylelint-config-standard-scss": "^14.0.0",
3939
"tailwindcss": "^3.4.19",
4040
"typescript": "^5.9.3",
41-
"typescript-eslint": "^8.53.1",
41+
"typescript-eslint": "^8.56.1",
4242
"vite": "^6.4.1",
4343
"vite-plugin-monkey": "^5.0.9",
4444
"vue-tsc": "^2.2.12"
@@ -48,5 +48,5 @@
4848
"src/**/*.{js,mjs,cjs,ts,vue}": "npx eslint --fix",
4949
"src/**/*.scss": "npx stylelint --fix"
5050
},
51-
"packageManager": "pnpm@10.20.0+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd"
51+
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017"
5252
}

pnpm-lock.yaml

Lines changed: 562 additions & 526 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const main = () => {
3838
waitForBody().then(() => document.body.appendChild(wrap))
3939

4040
// 创建插件面板
41-
const app = createApp(App)
41+
const app = createApp(App as any)
4242
app.config.errorHandler = (err, vm, info) => {
4343
error('Vue:', err)
4444
error('Component:', vm)

src/modules/filters/variety/comment/extra/bots.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const bots = [
2222
'AI识片酱', // 1835753760
2323
'AI知识总结', // 3546765074630961
2424
'AI小精灵呀', // 13339272
25+
'AI课程教学', // 3546880084544175
2526
]
2627

2728
export const botsSet = new Set(bots)

src/modules/filters/variety/dynamic/pages/dynamic.ts

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
DynUploaderFilter,
1515
DynVideoTitleFilter,
1616
} from '../subFilters/black'
17+
import { DynContentWhiteFilter, DynVideoTitleWhiteFilter } from '../subFilters/white'
1718

1819
const GM_KEYS = {
1920
black: {
@@ -42,6 +43,16 @@ const GM_KEYS = {
4243
statusKey: 'dyn-playback-filter-status',
4344
},
4445
},
46+
white: {
47+
title: {
48+
statusKey: 'dyn-video-title-white-filter-status',
49+
valueKey: 'global-title-keyword-whitelist-filter-value',
50+
},
51+
content: {
52+
statusKey: 'dyn-content-white-filter-status',
53+
valueKey: 'global-content-keyword-whitelist-filter-value',
54+
},
55+
},
4556
}
4657

4758
// 动态信息提取
@@ -92,13 +103,19 @@ class DynamicFilterDynamic implements IMainFilter {
92103
dynContentFilter = new DynContentFilter()
93104
dynDynVideoFilter = new DynDynVideoFilter()
94105
dynPlaybackFilter = new DynPlaybackFilter()
106+
// 白名单
107+
dynVideoTitleWhiteFilter = new DynVideoTitleWhiteFilter()
108+
dynContentWhiteFilter = new DynContentWhiteFilter()
95109

96110
init() {
97111
// 黑名单
98112
this.dynUploaderFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.uploader.valueKey, []))
99113
this.dynDurationFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.duration.valueKey, 0))
100114
this.dynVideoTitleFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.title.valueKey, []))
101115
this.dynContentFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.content.valueKey, []))
116+
// 白名单
117+
this.dynVideoTitleWhiteFilter.setParam(BiliCleanerStorage.get(GM_KEYS.white.title.valueKey, []))
118+
this.dynContentWhiteFilter.setParam(BiliCleanerStorage.get(GM_KEYS.white.content.valueKey, []))
102119
}
103120

104121
async check(mode?: 'full' | 'incr') {
@@ -161,9 +178,12 @@ class DynamicFilterDynamic implements IMainFilter {
161178
this.dynContentFilter.isEnable && blackPairs.push([this.dynContentFilter, selectorFns.content])
162179
this.dynDynVideoFilter.isEnable && blackPairs.push([this.dynDynVideoFilter, selectorFns.dynVideo])
163180
this.dynPlaybackFilter.isEnable && blackPairs.push([this.dynPlaybackFilter, selectorFns.playback])
181+
const whitePairs: SubFilterPair[] = []
182+
this.dynVideoTitleWhiteFilter.isEnable && whitePairs.push([this.dynVideoTitleWhiteFilter, selectorFns.title])
183+
this.dynContentWhiteFilter.isEnable && whitePairs.push([this.dynContentWhiteFilter, selectorFns.content])
164184

165185
// 检测
166-
const blackCnt = await coreCheck(dyns, true, 'style', blackPairs, [])
186+
const blackCnt = await coreCheck(dyns, true, 'style', blackPairs, whitePairs)
167187
const time = (performance.now() - timer).toFixed(1)
168188
debug(`DynamicFilterDynamic hide ${blackCnt} in ${dyns.length} dyns, mode=${mode}, time=${time}`)
169189
}
@@ -283,7 +303,7 @@ export const dynamicFilterDynamicGroups: Group[] = [
283303
{
284304
type: 'switch',
285305
id: GM_KEYS.black.title.statusKey,
286-
name: '启用 标题关键词过滤',
306+
name: '启用 视频标题关键词过滤',
287307
noStyle: true,
288308
enableFn: () => {
289309
mainFilter.dynVideoTitleFilter.enable()
@@ -297,8 +317,8 @@ export const dynamicFilterDynamicGroups: Group[] = [
297317
{
298318
type: 'editor',
299319
id: GM_KEYS.black.title.valueKey,
300-
name: '编辑 标题关键词黑名单',
301-
editorTitle: '标题关键词 黑名单',
320+
name: '编辑 视频标题关键词黑名单',
321+
editorTitle: '视频标题关键词 黑名单',
302322
editorDescription: [
303323
'每行一个关键词或正则,不区分大小写、全半角',
304324
'请勿使用过于激进的关键词或正则',
@@ -318,7 +338,7 @@ export const dynamicFilterDynamicGroups: Group[] = [
318338
type: 'switch',
319339
id: GM_KEYS.black.content.statusKey,
320340
name: '启用 动态内容关键词过滤',
321-
description: ['包含被转发动态内容', '不含动态内视频信息'],
341+
description: ['不覆盖动态内视频标题'],
322342
noStyle: true,
323343
enableFn: () => {
324344
mainFilter.dynContentFilter.enable()
@@ -379,6 +399,74 @@ export const dynamicFilterDynamicGroups: Group[] = [
379399
},
380400
],
381401
},
402+
{
403+
name: '白名单 免过滤',
404+
items: [
405+
{
406+
type: 'switch',
407+
id: GM_KEYS.white.title.statusKey,
408+
name: '启用 标题关键词白名单',
409+
noStyle: true,
410+
enableFn: () => {
411+
mainFilter.dynVideoTitleWhiteFilter.enable()
412+
mainFilter.checkFull()
413+
},
414+
disableFn: () => {
415+
mainFilter.dynVideoTitleWhiteFilter.disable()
416+
mainFilter.checkFull()
417+
},
418+
},
419+
{
420+
type: 'editor',
421+
id: GM_KEYS.white.title.valueKey,
422+
name: '编辑 标题关键词白名单',
423+
editorTitle: '标题关键词 白名单',
424+
editorDescription: [
425+
'每行一个关键词或正则,不区分大小写、全半角',
426+
'请勿使用过于激进的关键词或正则',
427+
'正则默认 ius 模式,无需 flag,语法:/abc|\\d+/',
428+
],
429+
saveFn: async () => {
430+
mainFilter.dynVideoTitleWhiteFilter.setParam(
431+
BiliCleanerStorage.get(GM_KEYS.white.title.valueKey, []),
432+
)
433+
mainFilter.checkFull()
434+
},
435+
},
436+
{
437+
type: 'switch',
438+
id: GM_KEYS.white.content.statusKey,
439+
name: '启用 动态内容关键词白名单',
440+
description: ['不覆盖动态内视频标题'],
441+
noStyle: true,
442+
enableFn: () => {
443+
mainFilter.dynContentWhiteFilter.enable()
444+
mainFilter.checkFull()
445+
},
446+
disableFn: () => {
447+
mainFilter.dynContentWhiteFilter.disable()
448+
mainFilter.checkFull()
449+
},
450+
},
451+
{
452+
type: 'editor',
453+
id: GM_KEYS.white.content.valueKey,
454+
name: '编辑 动态内容关键词白名单',
455+
editorTitle: '动态内容关键词 白名单',
456+
editorDescription: [
457+
'每行一个关键词或正则,不区分大小写、全半角',
458+
'请勿使用过于激进的关键词或正则',
459+
'正则默认 ius 模式,无需 flag,语法:/abc|\\d+/',
460+
],
461+
saveFn: async () => {
462+
mainFilter.dynContentWhiteFilter.setParam(
463+
BiliCleanerStorage.get(GM_KEYS.white.content.valueKey, []),
464+
)
465+
mainFilter.checkFull()
466+
},
467+
},
468+
],
469+
},
382470
]
383471

384472
// 右键菜单handler

src/modules/filters/variety/dynamic/pages/header.ts

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { IMainFilter, SelectorResult, SubFilterPair } from '@/types/filter'
44
import { debugFilter as debug, error } from '@/utils/logger'
55
import { BiliCleanerStorage } from '@/utils/storage'
66
import { DynContentFilter, DynUploaderFilter, DynVideoTitleFilter } from '../subFilters/black'
7+
import { DynContentWhiteFilter, DynVideoTitleWhiteFilter } from '../subFilters/white'
78

89
const GM_KEYS = {
910
black: {
@@ -20,6 +21,16 @@ const GM_KEYS = {
2021
valueKey: 'global-content-keyword-filter-value',
2122
},
2223
},
24+
white: {
25+
title: {
26+
statusKey: 'dyn-video-title-white-filter-status',
27+
valueKey: 'global-title-keyword-whitelist-filter-value',
28+
},
29+
content: {
30+
statusKey: 'dyn-content-white-filter-status',
31+
valueKey: 'global-content-keyword-whitelist-filter-value',
32+
},
33+
},
2334
}
2435

2536
// 动态信息提取
@@ -42,12 +53,18 @@ class DynamicFilterHeader implements IMainFilter {
4253
dynUploaderFilter = new DynUploaderFilter()
4354
dynVideoTitleFilter = new DynVideoTitleFilter()
4455
dynContentFilter = new DynContentFilter()
56+
// 白名单
57+
dynVideoTitleWhiteFilter = new DynVideoTitleWhiteFilter()
58+
dynContentWhiteFilter = new DynContentWhiteFilter()
4559

4660
init() {
4761
// 黑名单
4862
this.dynUploaderFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.uploader.valueKey, []))
4963
this.dynVideoTitleFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.title.valueKey, []))
5064
this.dynContentFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.content.valueKey, []))
65+
// 白名单
66+
this.dynVideoTitleWhiteFilter.setParam(BiliCleanerStorage.get(GM_KEYS.white.title.valueKey, []))
67+
this.dynContentWhiteFilter.setParam(BiliCleanerStorage.get(GM_KEYS.white.content.valueKey, []))
5168
}
5269

5370
async check(mode?: 'full' | 'incr') {
@@ -84,9 +101,13 @@ class DynamicFilterHeader implements IMainFilter {
84101
this.dynUploaderFilter.isEnable && blackPairs.push([this.dynUploaderFilter, selectorFns.uploader])
85102
this.dynVideoTitleFilter.isEnable && blackPairs.push([this.dynVideoTitleFilter, selectorFns.title])
86103
this.dynContentFilter.isEnable && blackPairs.push([this.dynContentFilter, selectorFns.content])
104+
// 构建白名单任务
105+
const whitePairs: SubFilterPair[] = []
106+
this.dynVideoTitleWhiteFilter.isEnable && whitePairs.push([this.dynVideoTitleWhiteFilter, selectorFns.title])
107+
this.dynContentWhiteFilter.isEnable && whitePairs.push([this.dynContentWhiteFilter, selectorFns.content])
87108

88109
// 检测
89-
const blackCnt = await coreCheck(dyns, true, 'style', blackPairs, [])
110+
const blackCnt = await coreCheck(dyns, true, 'style', blackPairs, whitePairs)
90111
const time = (performance.now() - timer).toFixed(1)
91112
debug(`DynamicFilterHeader hide ${blackCnt} in ${dyns.length} dyns, mode=${mode}, time=${time}`)
92113
}
@@ -104,23 +125,21 @@ class DynamicFilterHeader implements IMainFilter {
104125
// }
105126

106127
observe() {
107-
document.addEventListener('DOMContentLoaded', () => {
108-
let cnt = 0
109-
const id = setInterval(() => {
110-
const ele = document.querySelector('.right-entry .v-popover-wrap:nth-of-type(3)') as HTMLElement
111-
if (ele) {
112-
clearInterval(id)
113-
114-
debug('DynamicFilterHeader target appear')
115-
this.target = ele
128+
let cnt = 0
129+
const id = setInterval(() => {
130+
const ele = document.querySelector('.right-entry') as HTMLElement
131+
if (ele) {
132+
clearInterval(id)
133+
134+
debug('DynamicFilterHeader target appear')
135+
this.target = ele
136+
this.checkFull()
137+
new MutationObserver(() => {
116138
this.checkFull()
117-
new MutationObserver(() => {
118-
this.checkFull()
119-
}).observe(this.target, { childList: true, subtree: true })
120-
}
121-
++cnt > 10 && clearInterval(id)
122-
}, 1000)
123-
})
139+
}).observe(this.target, { childList: true, subtree: true })
140+
}
141+
++cnt > 10 && clearInterval(id)
142+
}, 1000)
124143
}
125144
}
126145

@@ -140,4 +159,10 @@ export const dynamicFilterHeaderEntry = async () => {
140159
if (BiliCleanerStorage.get(GM_KEYS.black.content.statusKey)) {
141160
mainFilter.dynContentFilter.enable()
142161
}
162+
if (BiliCleanerStorage.get(GM_KEYS.white.title.statusKey)) {
163+
mainFilter.dynVideoTitleWhiteFilter.enable()
164+
}
165+
if (BiliCleanerStorage.get(GM_KEYS.white.content.statusKey)) {
166+
mainFilter.dynContentWhiteFilter.enable()
167+
}
143168
}

0 commit comments

Comments
 (0)