Skip to content

Commit

Permalink
Merge pull request #100 from festoney8/dev
Browse files Browse the repository at this point in the history
merge dev to main, v3.8.0
  • Loading branch information
festoney8 committed Jul 4, 2024
2 parents 53bb63c + 5656fbe commit 57d6ca8
Show file tree
Hide file tree
Showing 37 changed files with 1,009 additions and 121 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# CHANGELOG

## 3.8.0

- 新增:动态过滤器
- 新增:动态过滤 用户名过滤
- 新增:动态过滤 标题过滤
- 新增:动态过滤 时长过滤
- 新增:直播页 折叠排行榜/大航海
- 新增:直播页 禁用壁纸
- 优化:评论区 踩/回复只在hover时显示,增加延迟减少跳变
- 优化:顶栏 隐藏活动,搜索框样式

## 3.7.4

- 修复:动态页 隐藏动态右侧饰品
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
> - **页面净化:「首页、播放页、影视番剧播放页、直播间、搜索页、动态页、热门页、频道页」**
> - **视频过滤:「首页、播放页、搜索页、热门页、频道页、空间页」**
> - **评论过滤:「播放页、影视番剧播放页、动态页」**
> - **动态过滤:「动态页」**
![](images/usage.png)

Expand Down
21 changes: 0 additions & 21 deletions src/components/wordlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ export class WordList {
GM_setValue(`BILICLEANER_${this.listID}`, this.wordArr)
}
private getValue() {
debug(`key`, `BILICLEANER_${this.listID}`)
this.wordArr = GM_getValue(`BILICLEANER_${this.listID}`, [])
debug(`list ${this.listID} getValue ${this.wordArr.length} lines`)
this.wordSet = new Set(this.wordArr)
}

Expand All @@ -60,25 +58,6 @@ export class WordList {
}
}

// /** 添加多个值到列表 */
// addValues(values: string[]) {
// try {
// this.getValue()
// values.forEach((value) => {
// value = value.trim()
// if (value && !this.wordSet.has(value)) {
// this.wordArr.push(value)
// this.wordSet.add(value)
// }
// })
// this.setValue()
// debug(`list ${this.listID} add ${values.length} lines, OK`)
// } catch (err) {
// error(err)
// error(`list ${this.listID} add ${values.length} lines, ERROR`)
// }
// }

/**
* 编辑整个列表
* @param values 编辑框内输入的列表
Expand Down
2 changes: 1 addition & 1 deletion src/filters/commentFilter/filters/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class CoreCommentFilter {
.catch((_result) => {
// 命中黑名单
// debug(_result)
if (whiteTasks) {
if (whiteTasks.length) {
Promise.all(whiteTasks)
.then((_result) => {
// 命中黑名单,未命中白名单
Expand Down
18 changes: 7 additions & 11 deletions src/filters/commentFilter/pages/dynamic.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { GM_getValue } from '$'
import { Group } from '../../../components/group'
import { CheckboxItem, ButtonItem } from '../../../components/item'
import { debugCommentFilter as debug, error } from '../../../utils/logger'
import { isPageDynamic } from '../../../utils/page-type'
import { isPageDynamic } from '../../../utils/pageType'
import { showEle, waitForEle } from '../../../utils/tool'
import { ContentAction, UsernameAction } from './actions/action'
import coreCommentFilterInstance, { CommentSelectorFunc } from '../filters/core'
Expand All @@ -16,15 +15,12 @@ let isContextMenuFuncRunning = false
let isContextMenuUsernameEnable = false

// 白名单功能开关
let isRootCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_dynamic-comment-root-whitelist-status', false)
let isSubCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_dynamic-comment-sub-whitelist-status', false)
let isUploaderCommentWhitelistEnable: boolean = GM_getValue(
'BILICLEANER_dynamic-comment-uploader-whitelist-status',
true,
)
let isPinnedCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_dynamic-comment-pinned-whitelist-status', true)
let isNoteCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_dynamic-comment-note-whitelist-status', true)
let isLinkCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_dynamic-comment-link-whitelist-status', true)
let isRootCommentWhitelistEnable = false
let isSubCommentWhitelistEnable = false
let isUploaderCommentWhitelistEnable = true
let isPinnedCommentWhitelistEnable = true
let isNoteCommentWhitelistEnable = true
let isLinkCommentWhitelistEnable = true

if (isPageDynamic()) {
let commentListContainer: HTMLElement
Expand Down
15 changes: 7 additions & 8 deletions src/filters/commentFilter/pages/video.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { GM_getValue } from '$'
import { Group } from '../../../components/group'
import { CheckboxItem, ButtonItem } from '../../../components/item'
import { debugCommentFilter as debug, error } from '../../../utils/logger'
import { isPageBangumi, isPagePlaylist, isPageVideo } from '../../../utils/page-type'
import { isPageBangumi, isPagePlaylist, isPageVideo } from '../../../utils/pageType'
import { showEle, waitForEle } from '../../../utils/tool'
import { ContentAction, UsernameAction } from './actions/action'
import coreCommentFilterInstance, { CommentSelectorFunc } from '../filters/core'
Expand All @@ -16,12 +15,12 @@ let isContextMenuFuncRunning = false
let isContextMenuUsernameEnable = false

// 白名单功能开关
let isRootCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-root-whitelist-status', false)
let isSubCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-sub-whitelist-status', false)
let isUploaderCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-uploader-whitelist-status', true)
let isPinnedCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-pinned-whitelist-status', true)
let isNoteCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-note-whitelist-status', true)
let isLinkCommentWhitelistEnable: boolean = GM_getValue('BILICLEANER_video-comment-link-whitelist-status', true)
let isRootCommentWhitelistEnable = false
let isSubCommentWhitelistEnable = false
let isUploaderCommentWhitelistEnable = true
let isPinnedCommentWhitelistEnable = true
let isNoteCommentWhitelistEnable = true
let isLinkCommentWhitelistEnable = true

if (isPageVideo() || isPageBangumi() || isPagePlaylist()) {
let commentListContainer: HTMLElement
Expand Down
70 changes: 70 additions & 0 deletions src/filters/dynFilter/agency/agency.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import dynDurationFilterInstance from '../filters/subfilters/dynDuration'
import dynTitleFilterInstance from '../filters/subfilters/dynTitle'
import dynUploaderFilterInstance from '../filters/subfilters/dynUploader'

// 代理, 接收页面操作通知, 更新子过滤器的参数
class DynUploaderFilterAgency {
notifyDynUploader(event: string, value?: string | string[]) {
switch (event) {
case 'disable':
dynUploaderFilterInstance.setStatus(false)
break
case 'enable':
dynUploaderFilterInstance.setStatus(true)
break
case 'add':
if (typeof value === 'string') {
if (value.trim()) {
dynUploaderFilterInstance.addParam(value.trim())
}
}
break
case 'edit':
if (Array.isArray(value)) {
dynUploaderFilterInstance.setParams(value.map((v) => v.trim()).filter((v) => v))
}
break
}
}
notifyDynTitle(event: string, value?: string | string[]) {
switch (event) {
case 'disable':
dynTitleFilterInstance.setStatus(false)
break
case 'enable':
dynTitleFilterInstance.setStatus(true)
break
case 'add':
if (typeof value === 'string') {
if (value.trim()) {
dynTitleFilterInstance.addParam(value.trim())
}
}
break
case 'edit':
if (Array.isArray(value)) {
dynTitleFilterInstance.setParams(value.map((v) => v.trim()).filter((v) => v))
}
break
}
}
notifyDynDuration(event: string, value?: number) {
switch (event) {
case 'disable':
dynDurationFilterInstance.setStatus(false)
break
case 'enable':
dynDurationFilterInstance.setStatus(true)
break
case 'change':
if (typeof value === 'number') {
dynDurationFilterInstance.setParams(value)
}
break
}
}
}

// 单例
const dynUploaderFilterAgencyInstance = new DynUploaderFilterAgency()
export default dynUploaderFilterAgencyInstance
129 changes: 129 additions & 0 deletions src/filters/dynFilter/filters/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import settings from '../../../settings'
import { debugDynFilter as debug, error, log } from '../../../utils/logger'
import { hideEle, isEleHide, showEle } from '../../../utils/tool'
import dynDurationFilterInstance from './subfilters/dynDuration'
import dynTitleFilterInstance from './subfilters/dynTitle'
import dynUploaderFilterInstance from './subfilters/dynUploader'

export interface IDynSubFilter {
isEnable: boolean
setStatus(status: boolean): void
setParams?(value: string[] | number): void
addParam?(value: string): void
check(value: string): Promise<string>
}

export type DynSelectorFunc = {
dynUploader?: (dyn: HTMLElement) => string | null
dynDuration?: (dyn: HTMLElement) => string | null
dynTitle?: (dyn: HTMLElement) => string | null
}

interface DynInfo {
dynUploader?: string | undefined
dynDuration?: string | undefined
dynTitle?: string | undefined
}

class CoreDynFilter {
/**
* 对动态内容进行并发检测
* @param dyns 动态列表
* @param sign 是否标记已过滤项
* @param selectorFunc 使用selector选取元素的函数
*/
checkAll(dyns: HTMLElement[], sign = true, selectorFunc: DynSelectorFunc) {
try {
const checkDynUploader = dynUploaderFilterInstance.isEnable && selectorFunc.dynUploader !== undefined
const checkDynDuration = dynDurationFilterInstance.isEnable && selectorFunc.dynDuration !== undefined
const checkDynTitle = dynTitleFilterInstance.isEnable && selectorFunc.dynTitle !== undefined

if (!checkDynUploader && !checkDynDuration && !checkDynTitle) {
// 黑名单全部关闭时 恢复全部动态
dyns.forEach((dyn) => showEle(dyn))
return
}

dyns.forEach((dyn) => {
const info: DynInfo = {}

// 构建黑白名单任务, 调用各个子过滤器的check()方法检测
const blackTasks: Promise<string>[] = []
const whiteTasks: Promise<string>[] = []

if (checkDynUploader) {
const dynUploader = selectorFunc.dynUploader!(dyn)
if (dynUploader) {
blackTasks.push(dynUploaderFilterInstance.check(dynUploader))
info.dynUploader = dynUploader
}
}
if (checkDynDuration) {
const dynDuration = selectorFunc.dynDuration!(dyn)
if (dynDuration) {
blackTasks.push(dynDurationFilterInstance.check(dynDuration))
info.dynDuration = dynDuration
}
}
if (checkDynTitle) {
const dynTitle = selectorFunc.dynTitle!(dyn)
if (dynTitle) {
blackTasks.push(dynTitleFilterInstance.check(dynTitle))
info.dynTitle = dynTitle
}
}

// 执行检测
Promise.all(blackTasks)
.then((_result) => {
// 未命中黑名单
// debug(_result)
showEle(dyn)
Promise.all(whiteTasks)
.then((_result) => {})
.catch((_result) => {})
})
.catch((_result) => {
// 命中黑名单
debug(_result)
if (whiteTasks.length) {
Promise.all(whiteTasks)
.then((_result) => {
// 命中黑名单,未命中白名单
// debug(_result)
if (!isEleHide(dyn)) {
log(`hide dyn
dynUploader: ${info.dynUploader}
dynDuration: ${info.dynDuration}
dynTitle: ${info.dynTitle}`)
}
hideEle(dyn)
})
.catch((_result) => {
// 命中白名单
// debug(_result)
showEle(dyn)
})
} else {
if (!isEleHide(dyn)) {
log(`hide dyn
dynUploader: ${info.dynUploader}
dynDuration: ${info.dynDuration}
dynTitle: ${info.dynTitle}`)
}
hideEle(dyn)
}
})

// 标记已过滤动态
sign && dyn.setAttribute(settings.filterSign, '')
})
} catch (err) {
error(err)
error('CoreDynFilter checkAll error')
}
}
}

const coreDynFilterInstance = new CoreDynFilter()
export default coreDynFilterInstance
51 changes: 51 additions & 0 deletions src/filters/dynFilter/filters/subfilters/dynDuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { IDynSubFilter } from '../core'

class DynDurationFilter implements IDynSubFilter {
// 时长阈值, 单位秒
private threshold = 0
isEnable = false

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

setParams(threshold: number) {
this.threshold = threshold
}

// dynDuration转换为秒数, 支持 HH:MM:SS, MM:SS, 纯数字
dynDurationToSec = (dynDuration: string): number => {
dynDuration = dynDuration.trim()
if (dynDuration.match(/^(?:\d+:)?\d+:\d+$/)) {
const parts = dynDuration.split(':').map((part) => parseInt(part))
if (parts.length === 3) {
return parts[0] * 3600 + parts[1] * 60 + parts[2]
}
if (parts.length === 2) {
return parts[0] * 60 + parts[1]
}
} else if (dynDuration.match(/^\d+$/)) {
return parseInt(dynDuration)
}
return -1
}

check(dynDuration: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
if (!this.isEnable || this.threshold === 0) {
resolve(`DynDuration resolve, disable or 0`)
} else {
const seconds = this.dynDurationToSec(dynDuration)
if (seconds > 0 && seconds > this.threshold) {
resolve(`DynDuration OK`)
} else {
reject(`DynDuration too short`)
}
}
})
}
}

// 单例
const dynDurationFilterInstance = new DynDurationFilter()
export default dynDurationFilterInstance
Loading

0 comments on commit 57d6ca8

Please sign in to comment.