Skip to content

Commit

Permalink
feat: add uploader keyword filter
Browse files Browse the repository at this point in the history
  • Loading branch information
festoney8 committed Mar 27, 2024
1 parent 51689fe commit dc40880
Show file tree
Hide file tree
Showing 12 changed files with 333 additions and 71 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# CHANGELOG

## 3.2.2
## 3.3.0

- 新增:支持UP主昵称关键词过滤(首页、热门页、播放页、频道页、搜索页)
- 新增:UP主昵称关键词黑名单
- 新增:播放页隐藏接下来播放
- 更新:净化分享适配新版标题

Expand Down
21 changes: 21 additions & 0 deletions src/filters/videoFilter/agency/agency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import durationFilterInstance from '../filters/subfilters/duration'
import titleKeywordFilterInstance from '../filters/subfilters/titleKeyword'
import titleKeywordWhitelistFilterInstance from '../filters/subfilters/titleKeywordWhitelist'
import uploaderFilterInstance from '../filters/subfilters/uploader'
import uploaderKeywordFilterInstance from '../filters/subfilters/uploaderKeyword'
import uploaderWhitelistFilterInstance from '../filters/subfilters/uploaderWhitelist'

// 代理, 接收页面操作通知, 更新子过滤器的参数
Expand Down Expand Up @@ -86,6 +87,26 @@ class VideoFilterAgency {
break
}
}
notifyUploaderKeyword(event: string, value?: string | string[]) {
switch (event) {
case 'disable':
uploaderKeywordFilterInstance.setStatus(false)
break
case 'enable':
uploaderKeywordFilterInstance.setStatus(true)
break
case 'add':
if (typeof value === 'string' && value.trim()) {
uploaderKeywordFilterInstance.addParam(value.trim())
}
break
case 'edit':
if (Array.isArray(value)) {
uploaderKeywordFilterInstance.setParams(value.map((v) => v.trim()).filter((v) => v))
}
break
}
}
notifyUploaderWhitelist(event: string, value?: string | string[]) {
switch (event) {
case 'disable':
Expand Down
9 changes: 9 additions & 0 deletions src/filters/videoFilter/filters/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import durationFilterInstance from './subfilters/duration'
import titleKeywordFilterInstance from './subfilters/titleKeyword'
import titleKeywordWhitelistFilterInstance from './subfilters/titleKeywordWhitelist'
import uploaderFilterInstance from './subfilters/uploader'
import uploaderKeywordFilterInstance from './subfilters/uploaderKeyword'
import uploaderWhitelistFilterInstance from './subfilters/uploaderWhitelist'

// 子过滤器实现IVideoSubFilter,包括白名单
Expand Down Expand Up @@ -45,6 +46,7 @@ class CoreVideoFilter {
const checkDuration = durationFilterInstance.isEnable && selectorFunc.duration !== undefined
const checkTitleKeyword = titleKeywordFilterInstance.isEnable && selectorFunc.titleKeyword !== undefined
const checkUploader = uploaderFilterInstance.isEnable && selectorFunc.uploader !== undefined
const checkUploaderKeyword = uploaderKeywordFilterInstance.isEnable && selectorFunc.uploader !== undefined
const checkBvid = bvidFilterInstance.isEnable && selectorFunc.bvid !== undefined
const checkUploaderWhitelist =
uploaderWhitelistFilterInstance.isEnable && selectorFunc.uploader !== undefined
Expand Down Expand Up @@ -84,6 +86,13 @@ class CoreVideoFilter {
info.uploader = uploader
}
}
if (checkUploaderKeyword) {
const uploader = selectorFunc.uploader!(video)?.trim()
if (uploader) {
blackTasks.push(uploaderKeywordFilterInstance.check(uploader))
info.uploader = uploader
}
}
if (checkTitleKeyword) {
const title = selectorFunc.titleKeyword!(video)?.trim()
if (title) {
Expand Down
2 changes: 1 addition & 1 deletion src/filters/videoFilter/filters/subfilters/titleKeyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class TitleKeywordFilter implements IVideoSubFilter {
// 关键词为正则表达式(反斜杠使用单斜杠),大小写不敏感,支持unicodeSets
const pattern = new RegExp(word.slice(1, -1), 'iv')
if (title.match(pattern)) {
// 命中白名单正则
// 命中黑名单正则
flag = true
reject(`TitleKeyword reject, ${title} match ${word} in blacklist`)
}
Expand Down
60 changes: 60 additions & 0 deletions src/filters/videoFilter/filters/subfilters/uploaderKeyword.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { error } from '../../../../utils/logger'
import { IVideoSubFilter } from '../core'

class UploaderKeywordFilter implements IVideoSubFilter {
isEnable = false
private uploaderKeywordSet = new Set<string>()

setStatus(status: boolean) {
this.isEnable = status
}

setParams(values: string[]) {
this.uploaderKeywordSet = new Set(values.map((v) => v.trim()).filter((v) => v))
}

addParam(value: string) {
if (value.trim()) {
this.uploaderKeywordSet.add(value.trim())
}
}

check(uploader: string): Promise<string> {
// 忽略大小写
uploader = uploader.trim().toLowerCase()
return new Promise<string>((resolve, reject) => {
try {
if (!this.isEnable || uploader.length === 0 || this.uploaderKeywordSet.size === 0) {
resolve(`UploaderKeyword resolve, disable or empty`)
}
let flag = false
this.uploaderKeywordSet.forEach((word) => {
if (word.startsWith('/') && word.endsWith('/')) {
// 关键词为正则表达式(反斜杠使用单斜杠),大小写不敏感
const pattern = new RegExp(word.slice(1, -1), 'iv')
if (uploader.match(pattern)) {
// 命中黑名单正则
flag = true
reject(`UploaderKeyword reject, ${uploader} match ${word} in blacklist`)
}
} else {
if (word && uploader.includes(word.toLowerCase())) {
flag = true
reject(`UploaderKeyword reject, ${uploader} match ${word} in blacklist`)
}
}
})
if (!flag) {
resolve(`UploaderKeyword resolve, uploader not match blacklist`)
}
} catch (err) {
error(err)
resolve(`UploaderKeyword resolve, error`)
}
})
}
}

// 单例
const uploaderKeywordFilterInstance = new UploaderKeywordFilter()
export default uploaderKeywordFilterInstance
58 changes: 58 additions & 0 deletions src/filters/videoFilter/pages/actions/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import durationFilterInstance from '../../filters/subfilters/duration'
import titleKeywordFilterInstance from '../../filters/subfilters/titleKeyword'
import titleKeywordWhitelistFilterInstance from '../../filters/subfilters/titleKeywordWhitelist'
import uploaderFilterInstance from '../../filters/subfilters/uploader'
import uploaderKeywordFilterInstance from '../../filters/subfilters/uploaderKeyword'
import uploaderWhitelistFilterInstance from '../../filters/subfilters/uploaderWhitelist'

// 定义各种黑名单功能、白名单功能的属性和行为
Expand Down Expand Up @@ -234,6 +235,63 @@ export class TitleKeywordAction implements VideoFilterAction {
}
}

export class UploaderKeywordAction implements VideoFilterAction {
statusKey: string
valueKey: string
checkVideoList: (fullSite: boolean) => void
status: boolean
value: string[]
blacklist: WordList

/**
* 昵称关键字过滤操作
* @param statusKey 是否启用的GM key
* @param valueKey 存储数据的GM key
* @param checkVideoList 检测视频列表函数
*/
constructor(statusKey: string, valueKey: string, checkVideoList: (fullSite: boolean) => void) {
this.statusKey = statusKey
this.valueKey = valueKey
this.status = GM_getValue(`BILICLEANER_${this.statusKey}`, false)
this.value = GM_getValue(`BILICLEANER_${this.valueKey}`, [])
this.checkVideoList = checkVideoList

// 配置子过滤器
uploaderKeywordFilterInstance.setStatus(this.status)
uploaderKeywordFilterInstance.setParams(this.value)
// 初始化黑名单, callback触发edit
this.blacklist = new WordList(
this.valueKey,
'昵称关键词 黑名单',
`每行一个关键词,支持正则(iv),语法:/abc|\\d+/`,
(values: string[]) => {
this.edit(values)
},
)
}

enable() {
// 告知agency
agencyInstance.notifyUploaderKeyword('enable')
// 触发全站过滤
this.checkVideoList(true)
}
disable() {
agencyInstance.notifyUploaderKeyword('disable')
this.checkVideoList(true)
}
add(value: string) {
this.blacklist.addValue(value)
agencyInstance.notifyUploaderKeyword('add', value)
this.checkVideoList(true)
}
// edit由编辑黑名单的保存动作回调, 数据由编辑器实例存储
edit(values: string[]) {
agencyInstance.notifyUploaderKeyword('edit', values)
this.checkVideoList(true)
}
}

export class UploaderWhitelistAction implements VideoFilterAction {
statusKey: string
valueKey: string
Expand Down
50 changes: 37 additions & 13 deletions src/filters/videoFilter/pages/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TitleKeywordAction,
TitleKeywordWhitelistAction,
UploaderAction,
UploaderKeywordAction,
UploaderWhitelistAction,
} from './actions/action'

Expand Down Expand Up @@ -124,6 +125,11 @@ if (isPageChannel()) {
'global-uploader-filter-value',
checkVideoList,
)
const channelUploaderKeywordAction = new UploaderKeywordAction(
'channel-uploader-keyword-filter-status',
'global-uploader-keyword-filter-value',
checkVideoList,
)
const channelBvidAction = new BvidAction('channel-bvid-filter-status', 'global-bvid-filter-value', checkVideoList)
const channelTitleKeywordAction = new TitleKeywordAction(
'channel-title-keyword-filter-status',
Expand Down Expand Up @@ -211,7 +217,7 @@ if (isPageChannel()) {
// 启用 频道页时长过滤
new CheckboxItem({
itemID: channelDurationAction.statusKey,
description: '启用 频道页时长过滤',
description: '启用 时长过滤',
/**
* 需使用匿名函数包装后传参, 否则报错, 下同
*
Expand Down Expand Up @@ -249,10 +255,10 @@ if (isPageChannel()) {

// UI组件, UP主过滤
const uploaderItems = [
// 启用 频道页UP主过滤
// 启用 UP主过滤
new CheckboxItem({
itemID: channelUploaderAction.statusKey,
description: '启用 频道页UP主过滤',
description: '启用 UP主过滤 (右键单击UP主)',
itemFunc: () => {
// 启用右键功能
isContextMenuUploaderEnable = true
Expand All @@ -265,7 +271,7 @@ if (isPageChannel()) {
channelUploaderAction.disable()
},
}),
// 按钮功能:打开uploader黑名单编辑框
// 编辑 UP主黑名单
new ButtonItem({
itemID: 'channel-uploader-edit-button',
description: '编辑 UP主黑名单',
Expand All @@ -275,17 +281,35 @@ if (isPageChannel()) {
channelUploaderAction.blacklist.show()
},
}),
// 启用 昵称关键词过滤
new CheckboxItem({
itemID: channelUploaderKeywordAction.statusKey,
description: '启用 昵称关键词过滤',
itemFunc: () => {
channelUploaderKeywordAction.enable()
},
callback: () => {
channelUploaderKeywordAction.disable()
},
}),
// 编辑 昵称关键词黑名单
new ButtonItem({
itemID: 'channel-uploader-keyword-edit-button',
description: '编辑 昵称关键词黑名单',
name: '编辑',
itemFunc: () => {
channelUploaderKeywordAction.blacklist.show()
},
}),
]
channelPageVideoFilterGroupList.push(
new Group('channel-uploader-filter-group', '频道页 UP主过滤 (右键单击UP主)', uploaderItems),
)
channelPageVideoFilterGroupList.push(new Group('channel-uploader-filter-group', '频道页 UP主过滤', uploaderItems))

// UI组件, 标题关键词过滤
const titleKeywordItems = [
// 启用 频道页关键词过滤
new CheckboxItem({
itemID: channelTitleKeywordAction.statusKey,
description: '启用 频道页关键词过滤',
description: '启用 标题关键词过滤',
itemFunc: () => {
channelTitleKeywordAction.enable()
},
Expand All @@ -296,7 +320,7 @@ if (isPageChannel()) {
// 按钮功能:打开titleKeyword黑名单编辑框
new ButtonItem({
itemID: 'channel-title-keyword-edit-button',
description: '编辑 关键词黑名单(支持正则)',
description: '编辑 标题关键词黑名单(支持正则)',
name: '编辑',
// 按钮功能
itemFunc: () => {
Expand All @@ -313,7 +337,7 @@ if (isPageChannel()) {
// 启用 频道页BV号过滤
new CheckboxItem({
itemID: channelBvidAction.statusKey,
description: '启用 频道页BV号过滤',
description: '启用 BV号过滤',
itemFunc: () => {
// 启用右键功能
isContextMenuBvidEnable = true
Expand Down Expand Up @@ -346,7 +370,7 @@ if (isPageChannel()) {
// 启用 频道页UP主白名单
new CheckboxItem({
itemID: channelUploaderWhitelistAction.statusKey,
description: '启用 频道页UP主白名单',
description: '启用 UP主白名单 (右键单击UP主)',
itemFunc: () => {
channelUploaderWhitelistAction.enable()
},
Expand All @@ -367,7 +391,7 @@ if (isPageChannel()) {
// 启用 频道页标题关键词白名单
new CheckboxItem({
itemID: channelTitleKeyworldWhitelistAction.statusKey,
description: '启用 频道页标题关键词白名单',
description: '启用 标题关键词白名单',
itemFunc: () => {
channelTitleKeyworldWhitelistAction.enable()
},
Expand All @@ -378,7 +402,7 @@ if (isPageChannel()) {
// 编辑 关键词白名单
new ButtonItem({
itemID: 'channel-title-keyword-whitelist-edit-button',
description: '编辑 关键词白名单(支持正则)',
description: '编辑 标题关键词白名单(支持正则)',
name: '编辑',
// 按钮功能:显示白名单编辑器
itemFunc: () => {
Expand Down
Loading

0 comments on commit dc40880

Please sign in to comment.