Skip to content

Commit

Permalink
feat: video page filter related videos
Browse files Browse the repository at this point in the history
  • Loading branch information
festoney8 committed Aug 17, 2024
1 parent 8e635c0 commit 0fb8a36
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 108 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# CHANGELOG

## 3.10.5

- 移除:播放页 接下来播放免过滤、播放结束免过滤
- 新增:播放页 对相关视频暂存数据进行整体过滤

## 3.10.4

- 修复:番剧页 小窗播放器记录位置
Expand Down
165 changes: 58 additions & 107 deletions src/filters/video/video.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { GM_getValue, GM_setValue } from '$'
import { GM_getValue, GM_setValue, unsafeWindow } from '$'
import { ContextMenu } from '../../components/contextmenu'
import { Group } from '../../components/group'
import { CheckboxItem, NumberItem, ButtonItem } from '../../components/item'
import { WordList } from '../../components/wordlist'
import { debugVideoFilter as debug, error } from '../../utils/logger'
import { isPageVideo, isPageBangumi, isPagePlaylist } from '../../utils/pageType'
import { convertTimeToSec, hideEle, isEleHide, matchBvid, showEle, waitForEle } from '../../utils/tool'
import { convertTimeToSec, isEleHide, matchBvid, waitForEle } from '../../utils/tool'
import { SelectorResult, SubFilterPair, coreCheck } from '../core/core'
import {
VideoBvidFilter,
Expand Down Expand Up @@ -40,6 +40,9 @@ const GM_KEYS = {
statusKey: 'video-title-keyword-filter-status',
valueKey: 'global-title-keyword-filter-value',
},
related: {
statusKey: 'video-related-filter-status',
},
},
white: {
uploader: {
Expand All @@ -50,12 +53,6 @@ const GM_KEYS = {
statusKey: 'video-title-keyword-whitelist-filter-status',
valueKey: 'global-title-keyword-whitelist-filter-value',
},
isNext: {
statusKey: 'video-next-play-whitelist-filter-status',
},
isEnding: {
statusKey: 'video-ending-whitelist-filter-status',
},
},
}

Expand Down Expand Up @@ -106,39 +103,23 @@ if (isPageVideo() || isPageBangumi() || isPagePlaylist()) {
let videoListContainer: HTMLElement

// 检测视频列表
let isNextPlayWhitelistEnable = false
const checkVideoList = async (_fullSite: boolean) => {
if (!videoListContainer) {
return
}
try {
// 提取元素
const nextVideos = Array.from(
videoListContainer.querySelectorAll<HTMLElement>(
`.next-play :is(.video-page-card-small, .video-page-operator-card-small)`,
),
)
const rcmdVideos = Array.from(
const videos = Array.from(
videoListContainer.querySelectorAll<HTMLElement>(
`.rec-list :is(.video-page-card-small, .video-page-operator-card-small), .recommend-video-card`,
`.next-play :is(.video-page-card-small, .video-page-operator-card-small),
.rec-list :is(.video-page-card-small, .video-page-operator-card-small), .recommend-video-card`,
),
)

// nextVideos.forEach((v) => {
// debug(
// [
// `nextVideos`,
// `bvid: ${selectorFns.bvid(v)}`,
// `duration: ${selectorFns.duration(v)}`,
// `title: ${selectorFns.title(v)}`,
// `uploader: ${selectorFns.uploader(v)}`,
// ].join('\n'),
// )
// })
// rcmdVideos.forEach((v) => {
// videos.forEach((v) => {
// debug(
// [
// `rcmdVideos`,
// `videos`,
// `bvid: ${selectorFns.bvid(v)}`,
// `duration: ${selectorFns.duration(v)}`,
// `title: ${selectorFns.title(v)}`,
Expand All @@ -160,70 +141,58 @@ if (isPageVideo() || isPageBangumi() || isPagePlaylist()) {
videoTitleWhiteFilter.isEnable && whitePairs.push([videoTitleWhiteFilter, selectorFns.title])

// 检测
if (!isNextPlayWhitelistEnable && nextVideos.length) {
await coreCheck(nextVideos, false, blackPairs, whitePairs)
} else {
nextVideos.forEach((el) => showEle(el))
}
rcmdVideos.length && (await coreCheck(rcmdVideos, false, blackPairs, whitePairs))
debug(`check ${nextVideos.length} next, ${rcmdVideos.length} rcmd videos`)
videos.length && (await coreCheck(videos, false, blackPairs, whitePairs))
debug(`check ${videos.length} videos`)
} catch (err) {
error('checkVideoList error', err)
}
}

const check = (fullSite: boolean) => {
if (
videoBvidFilter.isEnable ||
videoDurationFilter.isEnable ||
videoTitleFilter.isEnable ||
videoUploaderFilter.isEnable ||
videoUploaderKeywordFilter.isEnable
) {
checkVideoList(fullSite).then().catch()
}
}

// 视频结束后筛选播放器内视频
let isEndingWhitelistEnable = false
const watchPlayerEnding = () => {
if (isEndingWhitelistEnable) {
// 检测相关视频数据 __INITIAL_STATE__.related, 右侧视频列表检测完成后触发
let isRelatedFilterEnable = false
const checkRelated = async () => {
if (!isRelatedFilterEnable) {
return
}
const video = document.querySelector('video')
if (!video) {
return
}
const check = () => {
const rightList = document.querySelectorAll<HTMLElement>(`
const rightList = document.querySelectorAll<HTMLElement>(`
.recommend-video-card,
:is(.next-play, .rec-list) :is(.video-page-card-small, .video-page-operator-card-small)
`)
const blacklistVideoTitle = new Set<string>()
rightList.forEach((video: HTMLElement) => {
if (isEleHide(video)) {
const title = video.querySelector('.info > a p')?.textContent?.trim()
title && blacklistVideoTitle.add(title)
const blackBvids = new Set<string>()
rightList.forEach((video: HTMLElement) => {
if (isEleHide(video)) {
const url = video.querySelector('.info > a')?.getAttribute('href')
if (url) {
const bvid = matchBvid(url)
bvid && blackBvids.add(bvid)
}
})
let cnt = 0
const endingId = setInterval(() => {
const endingVideos = document.querySelectorAll<HTMLElement>('.bpx-player-ending-related-item')
if (endingVideos.length > 0) {
endingVideos.forEach((video: HTMLElement) => {
const title = video.querySelector('.bpx-player-ending-related-item-title')?.textContent?.trim()
if (title && blacklistVideoTitle.has(title)) {
hideEle(video)
} else {
showEle(video)
}
})
clearInterval(endingId)
}
++cnt > 100 && clearInterval(endingId)
}, 10)
}
})

const rel = unsafeWindow.__INITIAL_STATE__?.related
if (rel?.length && blackBvids.size) {
unsafeWindow.__INITIAL_STATE__!.related = rel.filter((v) => !(v.bvid && blackBvids.has(v.bvid)))
}
}

const check = (fullSite: boolean) => {
if (
videoBvidFilter.isEnable ||
videoDurationFilter.isEnable ||
videoTitleFilter.isEnable ||
videoUploaderFilter.isEnable ||
videoUploaderKeywordFilter.isEnable
) {
checkVideoList(fullSite)
.then(() => {
checkRelated().then().catch()
})
.catch()
}
video.ended ? check() : video.addEventListener('ended', check)
}

// 右键监听, 屏蔽UP主
Expand Down Expand Up @@ -336,8 +305,6 @@ if (isPageVideo() || isPageBangumi() || isPagePlaylist()) {
}).observe(videoListContainer, { childList: true, subtree: true })
}
})
// 视频播放结束监听
document.addEventListener('DOMContentLoaded', watchPlayerEnding)
} catch (err) {
error(`watch video list error`, err)
}
Expand Down Expand Up @@ -524,40 +491,24 @@ if (isPageVideo() || isPageBangumi() || isPagePlaylist()) {
]
videoPageVideoFilterGroupList.push(new Group('video-bvid-filter-group', '播放页 BV号过滤', bvidItems))

// UI组件, 免过滤和白名单
const whitelistItems = [
// 接下来播放 免过滤
new CheckboxItem({
itemID: GM_KEYS.white.isNext.statusKey,
description: '接下来播放 免过滤',
defaultStatus: true,
enableFunc: () => {
isNextPlayWhitelistEnable = true
check(true)
},
disableFunc: () => {
isNextPlayWhitelistEnable = false
check(true)
},
}),
// 视频播放结束推荐 免过滤
const otherItems = [
// 启用 相关视频 暂存数据过滤
new CheckboxItem({
itemID: GM_KEYS.white.isEnding.statusKey,
description: '视频播放结束推荐 免过滤',
defaultStatus: true,
itemID: GM_KEYS.black.related.statusKey,
description: '相关视频 暂存数据过滤 (实验功能)\n自动替换 接下来播放\n启用时 修改其他视频过滤设置需刷新',
enableFunc: () => {
isEndingWhitelistEnable = true
document
.querySelectorAll<HTMLElement>('.bpx-player-ending-related-item')
.forEach((e: HTMLElement) => showEle(e))
check(true)
isRelatedFilterEnable = true
checkRelated()
},
disableFunc: () => {
isEndingWhitelistEnable = false
watchPlayerEnding()
check(true)
isRelatedFilterEnable = false
},
}),
]
videoPageVideoFilterGroupList.push(new Group('video-other-filter-group', '播放页 其他过滤', otherItems))

// UI组件, 免过滤和白名单
const whitelistItems = [
// 启用 播放页UP主白名单
new CheckboxItem({
itemID: GM_KEYS.white.uploader.statusKey,
Expand Down
3 changes: 3 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export declare global {
abtest?: {
comment_next_version?: 'ELEMENTS' | 'DEFAULT'
}
related?: {
bvid?: string
}[]
}
__NEXT_DATA__?: any
EmbedPlayer?: {
Expand Down
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
userscript: {
name: 'bilibili 页面净化大师',
namespace: 'http://tampermonkey.net/',
version: '3.10.4',
version: '3.10.5',
description:
'净化 B站/哔哩哔哩 页面,支持「精简功能、播放器净化、过滤视频、过滤评论、全站黑白名单」,提供 300+ 功能,定制自己的 B 站',
author: 'festoney8',
Expand Down

0 comments on commit 0fb8a36

Please sign in to comment.