From e3a3f4410f7412509eec3568f22b8a9635b40db2 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Wed, 6 Sep 2023 13:02:51 +0800 Subject: [PATCH 01/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E4=BB=BB=E5=8A=A1ui=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/LiveTasks.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LiveTasks.vue b/src/components/LiveTasks.vue index 88049e54..c560fd22 100644 --- a/src/components/LiveTasks.vue +++ b/src/components/LiveTasks.vue @@ -196,7 +196,7 @@ function handleSelectionChange(selectedRows: ImedalInfoRow[]) { - + 分钟 From c4ed9a749873d1f1a6fcfe075ea793f11af8e611 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Wed, 6 Sep 2023 22:37:58 +0800 Subject: [PATCH 02/29] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=96=87=E5=AD=97=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/LiveTasks.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LiveTasks.vue b/src/components/LiveTasks.vue index c560fd22..62934048 100644 --- a/src/components/LiveTasks.vue +++ b/src/components/LiveTasks.vue @@ -99,7 +99,7 @@ const handleEditList = () => { medalInfoLoading.value = false } }) - // 利用 emitter 通知 BiliInfo 模块去获取数据 + // 利用 emitter 通知 FansMedals 模块去获取数据 moduleStore.emitter.emit('Default_FansMedals', { module: 'LiveTasks' }) From 61a1b642a547cf887c336f91c83afc7c3b4dfacc Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Thu, 7 Sep 2023 13:17:09 +0800 Subject: [PATCH 03/29] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=BD=93=E8=84=9A=E6=9C=AC=E5=9C=A8=E7=89=B9=E6=AE=8A=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E9=97=B4=E8=BF=90=E8=A1=8C=E6=97=B6Main=20BLTH?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E6=9C=89=E8=AF=AF=E7=9A=84Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/storage/defaultValue.ts | 3 ++- src/main.ts | 1 + src/modules/BaseModule.ts | 2 +- src/modules/enhanceExperience/banP2P.ts | 2 +- src/modules/enhanceExperience/noReport.ts | 2 +- src/modules/enhanceExperience/noSleep.ts | 2 +- .../enhanceExperience/switchLiveStreamQuality.ts | 2 +- src/modules/removeElement/removeGameParty.ts | 2 +- src/modules/removeElement/removeLiveWaterMark.ts | 2 +- src/modules/removeElement/removePKBox.ts | 2 +- src/modules/removeElement/removeShopPopover.ts | 2 +- src/stores/useCacheStore.ts | 15 ++++++++++++--- src/stores/useModuleStore.ts | 8 ++++---- src/types/storage.d.ts | 1 + 14 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/library/storage/defaultValue.ts b/src/library/storage/defaultValue.ts index 4737c207..791875b4 100644 --- a/src/library/storage/defaultValue.ts +++ b/src/library/storage/defaultValue.ts @@ -131,7 +131,8 @@ const defaultValues: IdefaultValues = { } }, cache: { - lastAliveHeartBeatTime: 0 + lastAliveHeartBeatTime: 0, + isMainBLTHRunningOnTargetFrame: false } } diff --git a/src/main.ts b/src/main.ts index eaf2234f..b4fd81dd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -48,6 +48,7 @@ if (isTargetFrame()) { app.component(key, component) } + cacheStore.cache.isMainBLTHRunningOnTargetFrame = true moduleStore.loadModules('yes') await waitForMoment('document-end') diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index 613b1dbb..6601bd89 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -14,7 +14,7 @@ class BaseModule { * * 默认false,即只在Main BLTH运行的页面上运行 */ - static runMultiple: boolean = false + static runOnMultiplePages: boolean = false /** * 模块运行时机,默认 document-body * diff --git a/src/modules/enhanceExperience/banP2P.ts b/src/modules/enhanceExperience/banP2P.ts index 3043741c..406b6b1d 100644 --- a/src/modules/enhanceExperience/banP2P.ts +++ b/src/modules/enhanceExperience/banP2P.ts @@ -3,7 +3,7 @@ import { onFrameTypes, runAtMoment } from '../../types/module' import BaseModule from '../BaseModule' class BanP2P extends BaseModule { - static runMultiple: boolean = true + static runOnMultiplePages: boolean = true static runAt: runAtMoment = 'document-start' static onFrame: onFrameTypes = 'all' static runAfterDefault: boolean = false diff --git a/src/modules/enhanceExperience/noReport.ts b/src/modules/enhanceExperience/noReport.ts index c311e0b0..a1ab7db8 100644 --- a/src/modules/enhanceExperience/noReport.ts +++ b/src/modules/enhanceExperience/noReport.ts @@ -6,7 +6,7 @@ import { getUrlFromFetchInput } from '../../library/utils' import { onFrameTypes, runAtMoment } from '../../types/module' class NoReport extends BaseModule { - static runMultiple: boolean = true + static runOnMultiplePages: boolean = true static runAt: runAtMoment = 'document-start' static onFrame: onFrameTypes = 'all' static runAfterDefault: boolean = false diff --git a/src/modules/enhanceExperience/noSleep.ts b/src/modules/enhanceExperience/noSleep.ts index 0683710b..0594fe54 100644 --- a/src/modules/enhanceExperience/noSleep.ts +++ b/src/modules/enhanceExperience/noSleep.ts @@ -2,7 +2,7 @@ import { runAtMoment } from '../../types/module' import BaseModule from '../BaseModule' class NoSleep extends BaseModule { - static runMultiple: boolean = true + static runOnMultiplePages: boolean = true static runAt: runAtMoment = 'window-load' static runAfterDefault: boolean = false diff --git a/src/modules/enhanceExperience/switchLiveStreamQuality.ts b/src/modules/enhanceExperience/switchLiveStreamQuality.ts index 4279473f..fe93161c 100644 --- a/src/modules/enhanceExperience/switchLiveStreamQuality.ts +++ b/src/modules/enhanceExperience/switchLiveStreamQuality.ts @@ -4,7 +4,7 @@ import { runAtMoment } from '../../types/module' import BaseModule from '../BaseModule' class SwitchLiveStreamQuality extends BaseModule { - static runMultiple: boolean = true + static runOnMultiplePages: boolean = true static runAt: runAtMoment = 'window-load' static runAfterDefault: boolean = false diff --git a/src/modules/removeElement/removeGameParty.ts b/src/modules/removeElement/removeGameParty.ts index 09adf18d..a26f40df 100644 --- a/src/modules/removeElement/removeGameParty.ts +++ b/src/modules/removeElement/removeGameParty.ts @@ -2,7 +2,7 @@ import { GM_addStyle } from '$' import BaseModule from '../BaseModule' class RemoveGameParty extends BaseModule { - static runMultiple = true + static runOnMultiplePages = true config = this.moduleStore.moduleConfig.RemoveElement.removeGameParty diff --git a/src/modules/removeElement/removeLiveWaterMark.ts b/src/modules/removeElement/removeLiveWaterMark.ts index 0294b754..1f62dfc4 100644 --- a/src/modules/removeElement/removeLiveWaterMark.ts +++ b/src/modules/removeElement/removeLiveWaterMark.ts @@ -2,7 +2,7 @@ import { GM_addStyle } from '$' import BaseModule from '../BaseModule' class RemoveLiveWaterMark extends BaseModule { - static runMultiple = true + static runOnMultiplePages = true config = this.moduleStore.moduleConfig.RemoveElement.removeLiveWaterMark diff --git a/src/modules/removeElement/removePKBox.ts b/src/modules/removeElement/removePKBox.ts index 242e45eb..ae1900d1 100644 --- a/src/modules/removeElement/removePKBox.ts +++ b/src/modules/removeElement/removePKBox.ts @@ -2,7 +2,7 @@ import { GM_addStyle } from '$' import BaseModule from '../BaseModule' class RemovePKBox extends BaseModule { - static runMultiple = true + static runOnMultiplePages = true config = this.moduleStore.moduleConfig.RemoveElement.removePKBox diff --git a/src/modules/removeElement/removeShopPopover.ts b/src/modules/removeElement/removeShopPopover.ts index e8f2b147..c80389ee 100644 --- a/src/modules/removeElement/removeShopPopover.ts +++ b/src/modules/removeElement/removeShopPopover.ts @@ -2,7 +2,7 @@ import { GM_addStyle } from '$' import BaseModule from '../BaseModule' class RemoveShopPopover extends BaseModule { - static runMultiple = true + static runOnMultiplePages = true config = this.moduleStore.moduleConfig.RemoveElement.removeShopPopover diff --git a/src/stores/useCacheStore.ts b/src/stores/useCacheStore.ts index 7f54d5c0..0c4d0f36 100644 --- a/src/stores/useCacheStore.ts +++ b/src/stores/useCacheStore.ts @@ -7,7 +7,7 @@ export const useCacheStore = defineStore('cache', () => { // 缓存 const cache: Icache = reactive(Storage.getCache()) // 是否有Main BLTH在运行 - // Main BLTH 指所有BLTH中唯一一个运行非 runMultiple 模块的 BLTH + // Main BLTH 指所有BLTH中唯一一个(对于特殊直播间来说有两个,因为脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH // 用户在打开第一个直播间页面时运行的BLTH一定是Main BLTH,之后打开的则不是 // 如果关掉Main BLTH所在的页面,那么下一个打开的页面上所运行的BLTH则为Main BLTH // 增加这一概念主要时为了确保任务类模块不会重复运行(比如完成各种每日任务的模块) @@ -26,6 +26,7 @@ export const useCacheStore = defineStore('cache', () => { window.addEventListener('unload', function () { clearInterval(timer) cache.lastAliveHeartBeatTime = 0 + cache.isMainBLTHRunningOnTargetFrame = false }) } @@ -33,11 +34,19 @@ export const useCacheStore = defineStore('cache', () => { * 检查是否有 Main BLTH 正在其它页面上运行 */ function checkIfMainBLTHRunning(): void { - // 允许最多3秒的误差 - if (cache.lastAliveHeartBeatTime !== 0 && Date.now() - cache.lastAliveHeartBeatTime < 8000) { + if ( + cache.lastAliveHeartBeatTime !== 0 && + // 允许最多3秒的误差 + Date.now() - cache.lastAliveHeartBeatTime < 8000 && + // 是否有 Main BLTH 运行在目标 frame 上 + // 对于特殊直播间,一个页面上会有两个 Main BLTH,需要依赖这个 flag 来判断第二个 frame 上的 BTLH 是不是 Main BLTH + cache.isMainBLTHRunningOnTargetFrame + ) { isMainBLTHRunning.value = true } else { isMainBLTHRunning.value = false + // 如果上次网页因浏览器崩溃而关闭,此时 isMainBLTHRunningOnTargetFrame 可能为 true,将其重新置为 false + cache.isMainBLTHRunningOnTargetFrame = false } } diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index ba0bd3a4..89225635 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -65,7 +65,7 @@ export const useModuleStore = defineStore('module', () => { const promiseArray: Promise[] = [] // 按优先级顺序逐个运行默认模块 for (const [name, module] of Object.entries(defaultModules)) { - if (module.runMultiple || !cacheStore.isMainBLTHRunning) { + if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { promiseArray.push(new (module as new (moduleName: string) => DefaultBaseModule)(name).run()) } } @@ -85,7 +85,7 @@ export const useModuleStore = defineStore('module', () => { if (isOnTargetFrame === 'unknown') { for (const [name, module] of Object.entries(otherModules)) { if (module.onFrame === 'all') { - if (module.runMultiple || !cacheStore.isMainBLTHRunning) { + if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { if (!module.runAfterDefault) { // 如果不需要等默认模块运行完了再运行,现在就加载并记录 // 否则不做记录,等之后(isOnTargetFrame 为 yes时)再加载 @@ -104,8 +104,8 @@ export const useModuleStore = defineStore('module', () => { // 运行其它模块 for (const [name, module] of Object.entries(otherModules)) { // 对 onFrame 为 all 的模块来说,如果之前运行过,现在就不运行了 - if (!allFrameModuleNames.includes(name)) { - if (module.runMultiple || !cacheStore.isMainBLTHRunning) { + if (module.onFrame === 'target' || !allFrameModuleNames.includes(name)) { + if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { waitForMoment(module.runAt).then(async () => { try { if (module.runAfterDefault) { diff --git a/src/types/storage.d.ts b/src/types/storage.d.ts index 90b3a4dd..c8ae8ae5 100644 --- a/src/types/storage.d.ts +++ b/src/types/storage.d.ts @@ -109,6 +109,7 @@ interface IuiConfig { interface Icache { lastAliveHeartBeatTime: number + isMainBLTHRunningOnTargetFrame: boolean } export { ImoduleConfig, IuiConfig, Icache } From 05ca6d9729ec9bb2752a9ef57b5b293b7bd6c080 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Fri, 8 Sep 2023 09:41:40 +0800 Subject: [PATCH 04/29] =?UTF-8?q?=E2=9C=A8=20feat:=20onFrame=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E9=80=89=E9=A1=B9top?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/BaseModule.ts | 4 ++++ src/stores/useCacheStore.ts | 2 +- src/stores/useModuleStore.ts | 21 ++++++++++++++------- src/types/module.d.ts | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index 6601bd89..16a945d2 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -13,6 +13,8 @@ class BaseModule { * 当脚本在多个页面上运行的时候,该模块是否要在每个页面上运行 * * 默认false,即只在Main BLTH运行的页面上运行 + * + * 该选项为 false 时如果要确保模块不会重复运行,还需将 onFrame 设置为 target 或 top */ static runOnMultiplePages: boolean = false /** @@ -35,6 +37,8 @@ class BaseModule { * `all`: 所有符合脚本`@match`规则的 frame * * `target`: window.BilibiliLive 存在的那个 frame + * + * `top`: 顶层 frame (`window.top`) */ static onFrame: onFrameTypes = 'target' /** diff --git a/src/stores/useCacheStore.ts b/src/stores/useCacheStore.ts index 0c4d0f36..d92e1826 100644 --- a/src/stores/useCacheStore.ts +++ b/src/stores/useCacheStore.ts @@ -7,7 +7,7 @@ export const useCacheStore = defineStore('cache', () => { // 缓存 const cache: Icache = reactive(Storage.getCache()) // 是否有Main BLTH在运行 - // Main BLTH 指所有BLTH中唯一一个(对于特殊直播间来说有两个,因为脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH + // Main BLTH 指所有BLTH中唯一一个(或两个,因为在特殊直播间脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH // 用户在打开第一个直播间页面时运行的BLTH一定是Main BLTH,之后打开的则不是 // 如果关掉Main BLTH所在的页面,那么下一个打开的页面上所运行的BLTH则为Main BLTH // 增加这一概念主要时为了确保任务类模块不会重复运行(比如完成各种每日任务的模块) diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index 89225635..2dd85b3f 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -18,6 +18,7 @@ import { } from '../types/module' import { deepestIterate, waitForMoment } from '../library/utils' import { useCacheStore } from './useCacheStore' +import { isSelfTopFrame } from '../library/dom' const defaultModuleStatus: ImoduleStatus = { DailyTasks: { @@ -45,8 +46,8 @@ const defaultModuleStatus: ImoduleStatus = { } } -// 在所有 frame 上运行的被加载的模块名称 -const allFrameModuleNames: string[] = [] +// 在所有 frame 或顶层 frame 上运行的被加载的模块名称 +const allAndTopFrameModuleNames: string[] = [] export const useModuleStore = defineStore('module', () => { // 所有模块的配置信息 @@ -84,7 +85,7 @@ export const useModuleStore = defineStore('module', () => { const logger = new Logger('ModuleStore_LoadModules') if (isOnTargetFrame === 'unknown') { for (const [name, module] of Object.entries(otherModules)) { - if (module.onFrame === 'all') { + if (module.onFrame === 'all' || (module.onFrame === 'top' && isSelfTopFrame())) { if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { if (!module.runAfterDefault) { // 如果不需要等默认模块运行完了再运行,现在就加载并记录 @@ -92,8 +93,8 @@ export const useModuleStore = defineStore('module', () => { waitForMoment(module.runAt).then(() => new (module as new (moduleName: string) => BaseModule)(name).run() ) - // 记录被加载的 onFrame 为 all 的模块名称 - allFrameModuleNames.push(name) + // 记录被加载的 onFrame 为 all 或 top 的模块名称 + allAndTopFrameModuleNames.push(name) } } } @@ -103,8 +104,14 @@ export const useModuleStore = defineStore('module', () => { const defaultModulesLoaded: Promise = loadDefaultModules() // 运行其它模块 for (const [name, module] of Object.entries(otherModules)) { - // 对 onFrame 为 all 的模块来说,如果之前运行过,现在就不运行了 - if (module.onFrame === 'target' || !allFrameModuleNames.includes(name)) { + // 对 onFrame 为 all 或 top 的模块来说,如果之前运行过,现在就不运行了 + if ( + module.onFrame === 'target' || + (module.onFrame === 'top' && + isSelfTopFrame() && + !allAndTopFrameModuleNames.includes(name)) || + (module.onFrame === 'all' && !allAndTopFrameModuleNames.includes(name)) + ) { if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { waitForMoment(module.runAt).then(async () => { try { diff --git a/src/types/module.d.ts b/src/types/module.d.ts index ee4e85e2..bc197725 100644 --- a/src/types/module.d.ts +++ b/src/types/module.d.ts @@ -33,7 +33,7 @@ type runAtMoment = | 'document-end' | 'window-load' -type onFrameTypes = 'all' | 'target' +type onFrameTypes = 'all' | 'target' | 'top' type isOnTargetFrameTypes = 'unknown' | 'yes' From ba6d232a4053d85eeba3ccae2e12ea8cdd6a29ad Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Fri, 8 Sep 2023 09:42:50 +0800 Subject: [PATCH 05/29] =?UTF-8?q?=F0=9F=93=83=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 14 ++++++++++++++ CONTRIBUTING.md | 12 +++++++++--- README.md | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2cfe0e..a2052f3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # 更新日志 +## [7.1.2] - 2023-9-8 + +## 新增 + +- 模块运行frame新增选项top + +## 修复 + +- 修复部分模块在特殊直播间不运行的Bug + +## 调整 + +- 直播任务板块UI微调 + ## [7.1.1] - 2023-9-5 ## 新增 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16a35f73..1f21f2f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,13 @@ BLTH 是一个基于 [Vue3](https://cn.vuejs.org), [vite-plugin-monkey](https:// ## 开始 -使用以下命令在浏览器中安装脚本并启动 [Vite](https://cn.vitejs.dev),然后你就可以开始写代码啦。 +首先切换到`dev`分支: + +```sh +git checkout dev +``` + +接着使用以下命令在浏览器中安装脚本并启动 [Vite](https://cn.vitejs.dev),然后你就可以开始写代码啦。 ```sh npm run dev @@ -140,8 +146,8 @@ npm run preview 如果要开发或调试运行时机很早的模块,建议先编译脚本(npm run build)然后运行编译后的脚本。在 dev 状态下调试这类功能可能会遇到以下问题: -- 脚本会被注入得太晚,无法很好地测试 -- 脚本会被注入得太早导致`document.head`为`null`而报错。 +- 脚本被注入得太晚,无法很好地测试 +- 脚本被注入得太早导致`document.head`为`null`而报错。 ## commit 规范 diff --git a/README.md b/README.md index 92887824..6fd14f93 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ - [hotkeys-js](https://github.com/jaywcjlove/hotkeys-js) - [crypto-js](https://github.com/brix/crypto-js) - [mitt](https://github.com/developit/mitt) +- [ajax-hook](https://github.com/wendux/ajax-hook) - [TampermonkeyJS](https://github.com/lzghzr/TampermonkeyJS) - [transform](https://github.com/ritz078/transform) - [inkscape](https://inkscape.org/) From 8983ac136a59b92bfa47b512c31edd2dd298b094 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Fri, 8 Sep 2023 09:45:47 +0800 Subject: [PATCH 06/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=89=88=E6=9C=AC=E5=8F=B7=20+=20npm=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 52 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 250066ee..cf90603e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bilibili-live-tasks-helper", - "version": "7.1.1", + "version": "7.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bilibili-live-tasks-helper", - "version": "7.1.1", + "version": "7.1.2", "dependencies": { "ajax-hook": "^3.0.1", "crypto-js": "^4.1.1", @@ -48,9 +48,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.15.tgz", - "integrity": "sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -687,9 +687,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==" + "version": "4.14.198", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz", + "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==" }, "node_modules/@types/lodash-es": { "version": "4.17.9", @@ -1034,9 +1034,9 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.8.tgz", - "integrity": "sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw==", + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.10.tgz", + "integrity": "sha512-db8PtM4ZZr7SYNH30XpKxUYnUBYaTvcuJ4c2whKK04fuAjbtjAIZ2al5GzGEfUlesmvkpgdbiSviRXUxgD9Omw==", "dev": true, "dependencies": { "@volar/language-core": "~1.10.0", @@ -1144,13 +1144,13 @@ "dev": true }, "node_modules/@vue/typescript": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.8.tgz", - "integrity": "sha512-jUnmMB6egu5wl342eaUH236v8tdcEPXXkPgj+eI/F6JwW/lb+yAU6U07ZbQ3MVabZRlupIlPESB7ajgAGixhow==", + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.10.tgz", + "integrity": "sha512-vPSpTXMk4chYwvyTGjM891cKgnx2r6vtbdANOp2mRU31f4HYGyLrZBlGgiua7SaO2cLjUg8y91OipJe0t8OFhA==", "dev": true, "dependencies": { "@volar/typescript": "~1.10.0", - "@vue/language-core": "1.8.8" + "@vue/language-core": "1.8.10" } }, "node_modules/@vueuse/core": { @@ -2677,9 +2677,9 @@ } }, "node_modules/luxon": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.2.tgz", - "integrity": "sha512-uBoAVCVcajsrqy3pv7eo5jEUz1oeLmCcnMv8n4AJpT5hbpN9lUssAXibNElpbLce3Mhm9dyBzwYLs9zctM/0tA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz", + "integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==", "engines": { "node": ">=12" } @@ -3201,9 +3201,9 @@ } }, "node_modules/rollup": { - "version": "3.28.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz", - "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.0.tgz", + "integrity": "sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -3813,13 +3813,13 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.8.tgz", - "integrity": "sha512-bSydNFQsF7AMvwWsRXD7cBIXaNs/KSjvzWLymq/UtKE36697sboX4EccSHFVxvgdBlI1frYPc/VMKJNB7DFeDQ==", + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.10.tgz", + "integrity": "sha512-ptpTFFDoHQgkWJF7i5iERxooiQzOGtG1uKTfmAUuS3qPuSQGq+Ky/S8BFHhnFGwoOxq/PjmGN2QSZEfg1rtzQA==", "dev": true, "dependencies": { - "@vue/language-core": "1.8.8", - "@vue/typescript": "1.8.8", + "@vue/language-core": "1.8.10", + "@vue/typescript": "1.8.10", "semver": "^7.3.8" }, "bin": { diff --git a/package.json b/package.json index 9ab9b8ff..fad43865 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bilibili-live-tasks-helper", "private": true, - "version": "7.1.1", + "version": "7.1.2", "type": "module", "scripts": { "dev": "vite", From 13b1c38d6ed6dbb2c0da00f0629200f1112dda62 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sat, 9 Sep 2023 20:18:35 +0800 Subject: [PATCH 07/29] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E9=A2=86=E5=8F=96?= =?UTF-8?q?=E5=A4=A7=E4=BC=9A=E5=91=98=E6=9D=83=E7=9B=8AsetTimeout?= =?UTF-8?q?=E5=BB=B6=E6=97=B6=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/dailyTasks/otherTasks/getYearVipPrivilegeTask.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/dailyTasks/otherTasks/getYearVipPrivilegeTask.ts b/src/modules/dailyTasks/otherTasks/getYearVipPrivilegeTask.ts index bcdde379..49d67d8e 100644 --- a/src/modules/dailyTasks/otherTasks/getYearVipPrivilegeTask.ts +++ b/src/modules/dailyTasks/otherTasks/getYearVipPrivilegeTask.ts @@ -95,9 +95,9 @@ class GetYearVipPrivilegeTask extends BaseModule { if (diff < 86400) { this.logger.log( '领取年度大会员权益模块下次运行时间:', - DateTime.fromSeconds(this.config._nextReceiveTime).toString() + DateTime.fromSeconds(this.config._nextReceiveTime).toJSDate() ) - setTimeout(() => this.run(), diff) + setTimeout(() => this.run(), diff * 1000) } else { this.logger.log('距离下次领取年度大会员权益的时间超过一天,不计划下次运行') } From 20d29f33476c3224269adc7b75f0db49f404a9d9 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sat, 9 Sep 2023 20:19:07 +0800 Subject: [PATCH 08/29] =?UTF-8?q?=F0=9F=93=83=20docs:=20Update=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2052f3e..b550088e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ## 修复 - 修复部分模块在特殊直播间不运行的Bug +- 修复领取大会员权益模块在领取前一天会多次运行的Bug ## 调整 From 91ac02d38f132278ebc94594b28227d9a13a9d72 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sat, 9 Sep 2023 20:19:26 +0800 Subject: [PATCH 09/29] =?UTF-8?q?=F0=9F=93=83=20docs:=20Update=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b550088e..c04d8b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # 更新日志 -## [7.1.2] - 2023-9-8 +## [7.1.2] - 2023-9-9 ## 新增 From bbf653235b12664db2ff5d10bcd6bb2b24573a1f Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sat, 9 Sep 2023 22:01:46 +0800 Subject: [PATCH 10/29] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=BC=95=E5=85=A5?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E7=B1=BB=E5=9E=8B(currentScriptType)?= =?UTF-8?q?=E6=A6=82=E5=BF=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/EnhanceExperience.vue | 6 ++- src/library/storage/defaultValue.ts | 3 +- src/main.ts | 13 ++++--- src/modules/BaseModule.ts | 2 + src/stores/useCacheStore.ts | 57 +++++++++++++++++----------- src/stores/useModuleStore.ts | 6 +-- src/types/storage.d.ts | 1 - 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/components/EnhanceExperience.vue b/src/components/EnhanceExperience.vue index 0dfc8d1b..aa74ed09 100644 --- a/src/components/EnhanceExperience.vue +++ b/src/components/EnhanceExperience.vue @@ -12,7 +12,11 @@ const qualityDescList = ['原画', '蓝光PRO', '蓝光', '超清PRO', '超清', - + diff --git a/src/library/storage/defaultValue.ts b/src/library/storage/defaultValue.ts index 791875b4..4737c207 100644 --- a/src/library/storage/defaultValue.ts +++ b/src/library/storage/defaultValue.ts @@ -131,8 +131,7 @@ const defaultValues: IdefaultValues = { } }, cache: { - lastAliveHeartBeatTime: 0, - isMainBLTHRunningOnTargetFrame: false + lastAliveHeartBeatTime: 0 } } diff --git a/src/main.ts b/src/main.ts index b4fd81dd..4770ca32 100644 --- a/src/main.ts +++ b/src/main.ts @@ -21,13 +21,15 @@ const pinia = createPinia() const cacheStore = useCacheStore(pinia) const moduleStore = useModuleStore(pinia) -cacheStore.checkIfMainBLTHRunning() +cacheStore.checkCurrentScriptType() -if (!cacheStore.isMainBLTHRunning) { - logger.log('当前脚本是Main BLTH,开始存活心跳') - cacheStore.startAliveHeartBeat() +if (cacheStore.currentScriptType === 'Main') { + logger.log('当前脚本的类型为Main,开始存活心跳') + cacheStore.startMainBLTHAliveHeartBeat() +} else if (cacheStore.currentScriptType === 'SubMain') { + logger.log('当前脚本的类型为SubMain') } else { - logger.log('其它页面上存在正在运行的Main BLTH') + logger.log('当前脚本的类型为Other') } moduleStore.loadModules('unknown') @@ -48,7 +50,6 @@ if (isTargetFrame()) { app.component(key, component) } - cacheStore.cache.isMainBLTHRunningOnTargetFrame = true moduleStore.loadModules('yes') await waitForMoment('document-end') diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index 16a945d2..a2a9b2e9 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -39,6 +39,8 @@ class BaseModule { * `target`: window.BilibiliLive 存在的那个 frame * * `top`: 顶层 frame (`window.top`) + * + * 如果设置为 target,那么至少要等到`document-body`时刻才能运行 */ static onFrame: onFrameTypes = 'target' /** diff --git a/src/stores/useCacheStore.ts b/src/stores/useCacheStore.ts index d92e1826..fa519e23 100644 --- a/src/stores/useCacheStore.ts +++ b/src/stores/useCacheStore.ts @@ -3,50 +3,63 @@ import { reactive, ref, watch } from 'vue' import Storage from '../library/storage' import { Icache } from '../types' +type scriptType = 'Main' | 'SubMain' | 'Other' + export const useCacheStore = defineStore('cache', () => { // 缓存 const cache: Icache = reactive(Storage.getCache()) - // 是否有Main BLTH在运行 - // Main BLTH 指所有BLTH中唯一一个(或两个,因为在特殊直播间脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH - // 用户在打开第一个直播间页面时运行的BLTH一定是Main BLTH,之后打开的则不是 - // 如果关掉Main BLTH所在的页面,那么下一个打开的页面上所运行的BLTH则为Main BLTH - // 增加这一概念主要时为了确保任务类模块不会重复运行(比如完成各种每日任务的模块) - const isMainBLTHRunning = ref(false) + // 当前BLTH的类型:Main BLTH,Sub Main BLTH,Other BLTH + // Main BLTH(以及可能存在的 Sub Main BLTH) 指所有BLTH中唯一一个(或两个,因为在特殊直播间脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH + + /** + * 表示当前BLTH的类型 + * - `Main`: 运行`runOnMultiplePages`为`false`的模块,有存活心跳 + * - `SubMain`: 运行`runOnMultiplePages`为`false`的模块,无存活心跳 + * - `Other`: 运行`runOnMultiplePages`为`true`的模块,无存活心跳 + * + * 用户在打开第一个直播间页面时运行的第一个BLTH一定是Main BLTH, + * 假如是特殊直播间,在第二个frame上还会有个SubMain BLTH。 + * 之后打开的直播间页面上运行的则是Other BLTH。 + * 如果关掉 Main BLTH 所在的页面,那么下一个打开的页面上所运行的 BLTH 则为 Main BLTH(也可能会有SubMain BLTH)。 + * 增加这一概念主要时为了确保任务类模块不会重复运行(比如完成各种每日任务的模块)。 + */ + const currentScriptType = ref('Main') /** * Main BLTH 存活心跳 */ - function startAliveHeartBeat(): void { + function startMainBLTHAliveHeartBeat(): void { cache.lastAliveHeartBeatTime = Date.now() // 每隔5秒写一次时间戳,表示有一个Main BLTH正在运行 // 之所以写时间戳而不是布尔值,是因为出现类似于浏览器崩溃的情况时 window.onunload 不会触发 // 那样就会留下一个永久的有脚本在运行的标记 const timer = setInterval(() => (cache.lastAliveHeartBeatTime = Date.now()), 5000) - window.addEventListener('unload', function () { + window.addEventListener('unload', () => { clearInterval(timer) cache.lastAliveHeartBeatTime = 0 - cache.isMainBLTHRunningOnTargetFrame = false }) } /** - * 检查是否有 Main BLTH 正在其它页面上运行 + * 检查当前脚本的类型 */ - function checkIfMainBLTHRunning(): void { + function checkCurrentScriptType(): void { if ( cache.lastAliveHeartBeatTime !== 0 && // 允许最多3秒的误差 - Date.now() - cache.lastAliveHeartBeatTime < 8000 && - // 是否有 Main BLTH 运行在目标 frame 上 - // 对于特殊直播间,一个页面上会有两个 Main BLTH,需要依赖这个 flag 来判断第二个 frame 上的 BTLH 是不是 Main BLTH - cache.isMainBLTHRunningOnTargetFrame + Date.now() - cache.lastAliveHeartBeatTime < 8000 ) { - isMainBLTHRunning.value = true + // 通过 sessionStorage 中的 flag 来判断当前页面上有没有 Main BLTH + if (sessionStorage.getItem('MainBLTHFlag') === null) { + currentScriptType.value = 'Other' + } else { + // 如果有,那么当前脚本的类型是 SubMain + currentScriptType.value = 'SubMain' + } } else { - isMainBLTHRunning.value = false - // 如果上次网页因浏览器崩溃而关闭,此时 isMainBLTHRunningOnTargetFrame 可能为 true,将其重新置为 false - cache.isMainBLTHRunningOnTargetFrame = false + currentScriptType.value = 'Main' + sessionStorage.setItem('MainBLTHFlag', 'Hello World') } } @@ -55,8 +68,8 @@ export const useCacheStore = defineStore('cache', () => { return { cache, - isMainBLTHRunning, - startAliveHeartBeat, - checkIfMainBLTHRunning + currentScriptType, + startMainBLTHAliveHeartBeat, + checkCurrentScriptType } }) diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index 2dd85b3f..25e83e89 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -66,7 +66,7 @@ export const useModuleStore = defineStore('module', () => { const promiseArray: Promise[] = [] // 按优先级顺序逐个运行默认模块 for (const [name, module] of Object.entries(defaultModules)) { - if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { + if (module.runOnMultiplePages || cacheStore.currentScriptType !== 'Other') { promiseArray.push(new (module as new (moduleName: string) => DefaultBaseModule)(name).run()) } } @@ -86,7 +86,7 @@ export const useModuleStore = defineStore('module', () => { if (isOnTargetFrame === 'unknown') { for (const [name, module] of Object.entries(otherModules)) { if (module.onFrame === 'all' || (module.onFrame === 'top' && isSelfTopFrame())) { - if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { + if (module.runOnMultiplePages || cacheStore.currentScriptType !== 'Other') { if (!module.runAfterDefault) { // 如果不需要等默认模块运行完了再运行,现在就加载并记录 // 否则不做记录,等之后(isOnTargetFrame 为 yes时)再加载 @@ -112,7 +112,7 @@ export const useModuleStore = defineStore('module', () => { !allAndTopFrameModuleNames.includes(name)) || (module.onFrame === 'all' && !allAndTopFrameModuleNames.includes(name)) ) { - if (module.runOnMultiplePages || !cacheStore.isMainBLTHRunning) { + if (module.runOnMultiplePages || cacheStore.currentScriptType !== 'Other') { waitForMoment(module.runAt).then(async () => { try { if (module.runAfterDefault) { diff --git a/src/types/storage.d.ts b/src/types/storage.d.ts index c8ae8ae5..90b3a4dd 100644 --- a/src/types/storage.d.ts +++ b/src/types/storage.d.ts @@ -109,7 +109,6 @@ interface IuiConfig { interface Icache { lastAliveHeartBeatTime: number - isMainBLTHRunningOnTargetFrame: boolean } export { ImoduleConfig, IuiConfig, Icache } From 22fe73f0448dd3e1fee956507039517b90bdded3 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sun, 10 Sep 2023 15:33:46 +0800 Subject: [PATCH 11/29] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96BaseModule=E7=B1=BB=EF=BC=8C=E5=88=A0=E5=8E=BBDefaultB?= =?UTF-8?q?aseModule=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/utils/index.ts | 2 +- src/modules/BaseModule.ts | 29 +++++++++++++++----------- src/modules/DefaultBaseModule.ts | 21 ------------------- src/modules/default/bilibiliLive.ts | 4 ++-- src/modules/default/cookies.ts | 4 ++-- src/modules/default/dailyRewardInfo.ts | 4 ++-- src/modules/default/dynamicVideos.ts | 4 ++-- src/modules/default/fansMetals.ts | 4 ++-- src/modules/default/userInfo.ts | 4 ++-- src/stores/useCacheStore.ts | 6 ++---- src/stores/useModuleStore.ts | 8 +++---- 11 files changed, 36 insertions(+), 54 deletions(-) delete mode 100644 src/modules/DefaultBaseModule.ts diff --git a/src/library/utils/index.ts b/src/library/utils/index.ts index 254c3bbd..47ed202d 100644 --- a/src/library/utils/index.ts +++ b/src/library/utils/index.ts @@ -17,7 +17,7 @@ function uuid(): string { * 基于 Promise 的睡眠函数 * @param miliseconds 睡眠时间 */ -function sleep(miliseconds: number): Promise { +function sleep(miliseconds: number): Promise { return new Promise((resolve) => setTimeout(resolve, miliseconds)) } diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index a2a9b2e9..79b7c2ad 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -8,7 +8,7 @@ class BaseModule { * * 输出控制台日志时会用到 */ - moduleName: string + public moduleName: string /** * 当脚本在多个页面上运行的时候,该模块是否要在每个页面上运行 * @@ -16,7 +16,7 @@ class BaseModule { * * 该选项为 false 时如果要确保模块不会重复运行,还需将 onFrame 设置为 target 或 top */ - static runOnMultiplePages: boolean = false + public static runOnMultiplePages: boolean = false /** * 模块运行时机,默认 document-body * @@ -30,7 +30,7 @@ class BaseModule { * * `window-load`: `window`的`load`事件触发后 */ - static runAt: runAtMoment = 'document-body' + public static runAt: runAtMoment = 'document-body' /** * 模块运行的 frame,默认 target * @@ -42,7 +42,7 @@ class BaseModule { * * 如果设置为 target,那么至少要等到`document-body`时刻才能运行 */ - static onFrame: onFrameTypes = 'target' + public static onFrame: onFrameTypes = 'target' /** * 是否要等默认模块运行完了再运行,默认 true * @@ -50,30 +50,30 @@ class BaseModule { * * 因为默认模块的运行时机总是 document-body,而且默认模块的运行时间是不确定的 */ - static runAfterDefault: boolean = true + public static runAfterDefault: boolean = true /** * 用于在控制台中输出日志信息 */ - logger: Logger + protected logger: Logger /** * 储存所有模块信息的 Pinia Store */ - moduleStore = useModuleStore() + protected moduleStore = useModuleStore() /** * 推荐添加一个 config 属性来表示当前模块的配置项 * - * @example this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.login + * @example config: this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.login */ - config?: any + protected config?: any /** * 如果需要在控制面板上显示模块状态,推荐添加一个 status setter 用来设置模块状态 * * @example - * public set status(s: moduleStatus) { + * set status(s: moduleStatus) { * this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.login = s * } */ - set status(_s: moduleStatus) { + protected set status(_s: moduleStatus) { throw new Error('Method not implemented.') } @@ -82,7 +82,12 @@ class BaseModule { this.logger = new Logger(this.moduleName) } - run(): void { + /** + * 运行模块 + * + * 默认模块返回一个空的Promise,其它模块无返回值 + */ + public run(): void | Promise { throw new Error('Method not implemented.') } } diff --git a/src/modules/DefaultBaseModule.ts b/src/modules/DefaultBaseModule.ts deleted file mode 100644 index 68ac3327..00000000 --- a/src/modules/DefaultBaseModule.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { onFrameTypes, runAtMoment } from '../types/module' -import BaseModule from './BaseModule' - -class DefaultBaseModule extends BaseModule { - /** - * 默认模块的运行时机总是 document-body - */ - static runAt: runAtMoment = 'document-body' - /** - * 默认模块只能在目标 frame 上运行 - */ - static onFrame: onFrameTypes = 'target' - /** - * 默认模块按顺序逐个运行,所以必须返回一个 Promise - */ - run(): Promise { - throw new Error('Method not implemented.') - } -} - -export default DefaultBaseModule diff --git a/src/modules/default/bilibiliLive.ts b/src/modules/default/bilibiliLive.ts index d8a97e3c..5fb3b281 100644 --- a/src/modules/default/bilibiliLive.ts +++ b/src/modules/default/bilibiliLive.ts @@ -1,8 +1,8 @@ import { useBiliStore } from '../../stores/useBiliStore' -import DefaultBaseModule from '../DefaultBaseModule' import { unsafeWindow } from '$' +import BaseModule from '../BaseModule' -class BilibiliLive extends DefaultBaseModule { +class BilibiliLive extends BaseModule { /** * 获取 window.BilibiliLive * @returns 一个 window.BilibiliLive 对象的引用 diff --git a/src/modules/default/cookies.ts b/src/modules/default/cookies.ts index 564c6a55..5174d65e 100644 --- a/src/modules/default/cookies.ts +++ b/src/modules/default/cookies.ts @@ -1,9 +1,9 @@ import { useBiliStore } from '../../stores/useBiliStore' -import DefaultBaseModule from '../DefaultBaseModule' import { getCookies } from '../../library/cookie' import { IbiliCookies } from '../../types/cookies' +import BaseModule from '../BaseModule' -class Cookies extends DefaultBaseModule { +class Cookies extends BaseModule { /** * 获取 Cookies * diff --git a/src/modules/default/dailyRewardInfo.ts b/src/modules/default/dailyRewardInfo.ts index 19cc4872..e529d5b7 100644 --- a/src/modules/default/dailyRewardInfo.ts +++ b/src/modules/default/dailyRewardInfo.ts @@ -1,10 +1,10 @@ import { useBiliStore } from '../../stores/useBiliStore' import BAPI from '../../library/bili-api' import { MainData } from '../../library/bili-api/data' -import DefaultBaseModule from '../DefaultBaseModule' import { delayToNextMoment, isTimestampToday } from '../../library/luxon' +import BaseModule from '../BaseModule' -class DailyRewardInfo extends DefaultBaseModule { +class DailyRewardInfo extends BaseModule { /** * 获取今日主站每日任务的完成情况 */ diff --git a/src/modules/default/dynamicVideos.ts b/src/modules/default/dynamicVideos.ts index 0aa4531c..05c8fd5f 100644 --- a/src/modules/default/dynamicVideos.ts +++ b/src/modules/default/dynamicVideos.ts @@ -1,10 +1,10 @@ import { useBiliStore } from '../../stores/useBiliStore' import BAPI from '../../library/bili-api' import { MainData } from '../../library/bili-api/data' -import DefaultBaseModule from '../DefaultBaseModule' import { delayToNextMoment, isTimestampToday } from '../../library/luxon' +import BaseModule from '../BaseModule' -class DynamicVideos extends DefaultBaseModule { +class DynamicVideos extends BaseModule { /** * 从动态中获取一页视频的信息 * diff --git a/src/modules/default/fansMetals.ts b/src/modules/default/fansMetals.ts index 7e1ee910..c630a1ef 100644 --- a/src/modules/default/fansMetals.ts +++ b/src/modules/default/fansMetals.ts @@ -1,12 +1,12 @@ import { useBiliStore } from '../../stores/useBiliStore' import BAPI from '../../library/bili-api' import { LiveData } from '../../library/bili-api/data' -import DefaultBaseModule from '../DefaultBaseModule' import { delayToNextMoment, isTimestampToday } from '../../library/luxon' import { sleep } from '../../library/utils' import { useModuleStore } from '../../stores/useModuleStore' +import BaseModule from '../BaseModule' -class FansMetals extends DefaultBaseModule { +class FansMetals extends BaseModule { /** * 获取粉丝勋章 * diff --git a/src/modules/default/userInfo.ts b/src/modules/default/userInfo.ts index 9f67cf69..bb133fba 100644 --- a/src/modules/default/userInfo.ts +++ b/src/modules/default/userInfo.ts @@ -1,10 +1,10 @@ import { useBiliStore } from '../../stores/useBiliStore' import BAPI from '../../library/bili-api' import { MainData } from '../../library/bili-api/data' -import DefaultBaseModule from '../DefaultBaseModule' import { delayToNextMoment } from '../../library/luxon' +import BaseModule from '../BaseModule' -class UserInfo extends DefaultBaseModule { +class UserInfo extends BaseModule { /** * 通过 BAPI.main.nav 获取用户基本信息 */ diff --git a/src/stores/useCacheStore.ts b/src/stores/useCacheStore.ts index fa519e23..3420c3f7 100644 --- a/src/stores/useCacheStore.ts +++ b/src/stores/useCacheStore.ts @@ -8,8 +8,6 @@ type scriptType = 'Main' | 'SubMain' | 'Other' export const useCacheStore = defineStore('cache', () => { // 缓存 const cache: Icache = reactive(Storage.getCache()) - // 当前BLTH的类型:Main BLTH,Sub Main BLTH,Other BLTH - // Main BLTH(以及可能存在的 Sub Main BLTH) 指所有BLTH中唯一一个(或两个,因为在特殊直播间脚本会被注入到两个 frame 上)运行 runOnMultiplePages 为 false 模块的 BLTH /** * 表示当前BLTH的类型 @@ -51,7 +49,7 @@ export const useCacheStore = defineStore('cache', () => { Date.now() - cache.lastAliveHeartBeatTime < 8000 ) { // 通过 sessionStorage 中的 flag 来判断当前页面上有没有 Main BLTH - if (sessionStorage.getItem('MainBLTHFlag') === null) { + if (sessionStorage.getItem('main_blth_flag') === null) { currentScriptType.value = 'Other' } else { // 如果有,那么当前脚本的类型是 SubMain @@ -59,7 +57,7 @@ export const useCacheStore = defineStore('cache', () => { } } else { currentScriptType.value = 'Main' - sessionStorage.setItem('MainBLTHFlag', 'Hello World') + sessionStorage.setItem('main_blth_flag', '🚩') } } diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index 25e83e89..d4149ce9 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -3,7 +3,6 @@ import { reactive, watch } from 'vue' import Storage from '../library/storage' import _ from 'lodash' import { ImoduleConfig } from '../types' -import DefaultBaseModule from '../modules/DefaultBaseModule' import BaseModule from '../modules/BaseModule' import * as defaultModules from '../modules/default' import * as otherModules from '../modules' @@ -63,11 +62,12 @@ export const useModuleStore = defineStore('module', () => { */ function loadDefaultModules(): Promise { const cacheStore = useCacheStore() - const promiseArray: Promise[] = [] - // 按优先级顺序逐个运行默认模块 + const promiseArray: Promise[] = [] for (const [name, module] of Object.entries(defaultModules)) { if (module.runOnMultiplePages || cacheStore.currentScriptType !== 'Other') { - promiseArray.push(new (module as new (moduleName: string) => DefaultBaseModule)(name).run()) + promiseArray.push( + new (module as new (moduleName: string) => BaseModule)(name).run() as Promise + ) } } return Promise.all(promiseArray) From 70755d5079f43422149018e2459c7d2e033c9589 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sun, 10 Sep 2023 17:35:12 +0800 Subject: [PATCH 12/29] =?UTF-8?q?=F0=9F=8E=88=20perf:=20banP2P=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/enhanceExperience/banP2P.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/modules/enhanceExperience/banP2P.ts b/src/modules/enhanceExperience/banP2P.ts index 406b6b1d..d0c5a95f 100644 --- a/src/modules/enhanceExperience/banP2P.ts +++ b/src/modules/enhanceExperience/banP2P.ts @@ -18,29 +18,27 @@ class BanP2P extends BaseModule { ] for (const i of RTClist) { // 判断属性是否存在并且是否可配置 - if ( - Object.prototype.hasOwnProperty.call(unsafeWindow, i) && - Object.getOwnPropertyDescriptor(unsafeWindow, i)?.configurable - ) { + if (Object.prototype.hasOwnProperty.call(unsafeWindow, i)) { // 定义属性 Object.defineProperty(unsafeWindow, i, { - value: function () { - this.addEventListener = function () {} - this.removeEventListener = function () {} - this.createDataChannel = function () { + value: class { + constructor() {} + addEventListener() {} + removeEventListener() {} + createDataChannel() { return { close: function () {} } } - this.createOffer = function () { + createOffer() { return Promise.resolve() } - this.setLocalDescription = function () { + setLocalDescription() { return Promise.resolve() } - this.close = function () {} - this.setRemoteDescription = function () { + close() {} + setRemoteDescription() { return Promise.resolve() } - this.createAnswer = function () {} + createAnswer() {} }, enumerable: false, writable: false, From 955d2dcf09ac5967a6098130ff81fe7aea18e02c Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sun, 10 Sep 2023 17:36:00 +0800 Subject: [PATCH 13/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20BaseModule?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/minifyUserscript.js | 2 ++ src/main.ts | 6 +----- src/modules/BaseModule.ts | 4 ++++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/minifyUserscript.js b/scripts/minifyUserscript.js index c57770bc..21174108 100644 --- a/scripts/minifyUserscript.js +++ b/scripts/minifyUserscript.js @@ -22,6 +22,8 @@ async function minifyUserscript(inputPath, outputPath) { const result = `${metadata}\n${minified.code}` await fs.writeFile(outputPath, result, 'utf-8') + + console.log(`\n压缩完成: ${inputPath} -> ${outputPath}`) } minifyUserscript( diff --git a/src/main.ts b/src/main.ts index 4770ca32..53416da4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,14 +22,10 @@ const cacheStore = useCacheStore(pinia) const moduleStore = useModuleStore(pinia) cacheStore.checkCurrentScriptType() +logger.log('当前脚本的类型为', cacheStore.currentScriptType) if (cacheStore.currentScriptType === 'Main') { - logger.log('当前脚本的类型为Main,开始存活心跳') cacheStore.startMainBLTHAliveHeartBeat() -} else if (cacheStore.currentScriptType === 'SubMain') { - logger.log('当前脚本的类型为SubMain') -} else { - logger.log('当前脚本的类型为Other') } moduleStore.loadModules('unknown') diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index 79b7c2ad..0e685c22 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -29,6 +29,8 @@ class BaseModule { * `document-end`: `document`的`DOMContentLoaded`事件触发后 * * `window-load`: `window`的`load`事件触发后 + * + * 默认模块的模块运行时机总是为 document-body */ public static runAt: runAtMoment = 'document-body' /** @@ -41,6 +43,8 @@ class BaseModule { * `top`: 顶层 frame (`window.top`) * * 如果设置为 target,那么至少要等到`document-body`时刻才能运行 + * + * 默认模块运行的 frame 总是为 target */ public static onFrame: onFrameTypes = 'target' /** From 2a8f29e8c541f788a16c6747a563778cc9e2410f Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sun, 10 Sep 2023 21:41:27 +0800 Subject: [PATCH 14/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20=E7=B2=89?= =?UTF-8?q?=E4=B8=9D=E5=8B=8B=E7=AB=A0=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/modules/default/fansMetals.ts | 15 ++++++++++++--- src/stores/useModuleStore.ts | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6fd14f93..c4e2fd50 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # 环境要求 -- 浏览器:推荐使用 Chrome,Edge, Firefox, Safari 或 Opera。 +- 浏览器:推荐使用 Chrome, Edge, Firefox, Safari 或 Opera。 - 用户脚本管理器:推荐使用 [Tampermonkey](https://www.tampermonkey.net) 或 [Violentmonkey](https://violentmonkey.github.io)。 # 安装 diff --git a/src/modules/default/fansMetals.ts b/src/modules/default/fansMetals.ts index c630a1ef..e2993705 100644 --- a/src/modules/default/fansMetals.ts +++ b/src/modules/default/fansMetals.ts @@ -14,7 +14,7 @@ class FansMetals extends BaseModule { * @param force 是否无视配置强制获取,默认fasle */ private async getFansMetals( - pages = 10, + pages = Infinity, force = false ): Promise { const medalTasks = this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks @@ -69,11 +69,20 @@ class FansMetals extends BaseModule { biliStore.fansMedals = await this.getFansMetals() setTimeout(async () => { - biliStore.fansMedals = await this.getFansMetals() + // 如果获得了新的粉丝勋章,肯定在第一页的 special_list 中,所以只获取一页 + const firstPageMedals = await this.getFansMetals(1, true) + firstPageMedals?.forEach((firstPageMedal) => { + if ( + biliStore.fansMedals?.findIndex((m) => m.medal.target_id === firstPageMedal.medal.target_id) === -1 + ) { + // 添加新的粉丝勋章 + biliStore.fansMedals.push(firstPageMedal) + } + }) }, delayToNextMoment(0, 4).ms) useModuleStore().emitter.on('Default_FansMedals', async () => { - biliStore.fansMedals = await this.getFansMetals(10, true) + biliStore.fansMedals = await this.getFansMetals(Infinity, true) }) } } diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index d4149ce9..a2331e00 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -102,7 +102,7 @@ export const useModuleStore = defineStore('module', () => { } else { // 加载默认模块 const defaultModulesLoaded: Promise = loadDefaultModules() - // 运行其它模块 + // 加载其它模块 for (const [name, module] of Object.entries(otherModules)) { // 对 onFrame 为 all 或 top 的模块来说,如果之前运行过,现在就不运行了 if ( From 093159cd5bf95ad9d0258ddb1238d474c1af81cc Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Mon, 11 Sep 2023 11:11:28 +0800 Subject: [PATCH 15/29] =?UTF-8?q?=E2=9C=A8=20feat:=20Cookies=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E4=BC=98=E5=8C=96=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E8=8E=B7=E5=8F=96Cookies=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/cookie/index.ts | 43 ++++++++++++++++++++++++++++--- src/modules/default/cookies.ts | 8 +++--- src/modules/default/fansMetals.ts | 2 +- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/library/cookie/index.ts b/src/library/cookie/index.ts index 9312d110..56895e8c 100644 --- a/src/library/cookie/index.ts +++ b/src/library/cookie/index.ts @@ -1,4 +1,4 @@ -import { IbiliCookies } from '../../types' +import _ from 'lodash' /** * 获取名称为 name 的 cookie @@ -21,7 +21,7 @@ function getCookie(name: string): string | null { * 该方法会修改 names * @param names Cookies 名称字符串 */ -function getCookies(names: string[]): IbiliCookies { +function getCookies(names: string[]): Record { const cookies: Record = {} // 所有 cookies 赋初值 null for (const name of names) { @@ -34,13 +34,48 @@ function getCookies(names: string[]): IbiliCookies { if (cookie.startsWith(nameEqual)) { const value = cookie.substring(nameEqual.length) cookies[name] = decodeURIComponent(value) + // 从 names 中删除已获取的 cookie names.splice(i, 1) break } } if (names.length === 0) break } - return cookies as unknown as IbiliCookies + return cookies } -export { getCookie, getCookies } +/** + * 获取名称在 names 中的 cookies,如果有 cookie 未获取到,会重复获取直到超时为止 + * + * 该方法会修改 names + * @param names Cookies 名称字符串 + * @param interval 获取间隔 + * @param timeout 超时时间 + */ +function getCookiesAsync( + names: string[], + interval: number = 100, + timeout: number = 10e3 +): Promise> { + return new Promise((resolve, reject) => { + const cookies = getCookies(names) + if (names.length > 0) { + const cookieTimer = setInterval(() => { + _.merge(cookies, getCookies(names)) + if (names.length === 0) { + clearInterval(cookieTimer) + clearTimeout(timeoutTimer) + resolve(cookies) + } + }, interval) + const timeoutTimer = setTimeout(() => { + clearInterval(cookieTimer) + reject('获取以下Cookies超时: ' + names.toString()) + }, timeout) + } else { + resolve(cookies) + } + }) +} + +export { getCookie, getCookies, getCookiesAsync } diff --git a/src/modules/default/cookies.ts b/src/modules/default/cookies.ts index 5174d65e..4e2354af 100644 --- a/src/modules/default/cookies.ts +++ b/src/modules/default/cookies.ts @@ -1,5 +1,5 @@ import { useBiliStore } from '../../stores/useBiliStore' -import { getCookies } from '../../library/cookie' +import { getCookiesAsync } from '../../library/cookie' import { IbiliCookies } from '../../types/cookies' import BaseModule from '../BaseModule' @@ -11,12 +11,12 @@ class Cookies extends BaseModule { * * LIVE_BUVID: 如果用户以前从来没看过直播,此时可能为 null */ - private getCookies(): IbiliCookies { - return getCookies(['bili_jct', 'LIVE_BUVID']) + private getCookies(): Promise { + return getCookiesAsync(['bili_jct', 'LIVE_BUVID']) as unknown as Promise } public async run(): Promise { - useBiliStore().cookies = this.getCookies() + useBiliStore().cookies = await this.getCookies() } } diff --git a/src/modules/default/fansMetals.ts b/src/modules/default/fansMetals.ts index e2993705..024af2db 100644 --- a/src/modules/default/fansMetals.ts +++ b/src/modules/default/fansMetals.ts @@ -73,7 +73,7 @@ class FansMetals extends BaseModule { const firstPageMedals = await this.getFansMetals(1, true) firstPageMedals?.forEach((firstPageMedal) => { if ( - biliStore.fansMedals?.findIndex((m) => m.medal.target_id === firstPageMedal.medal.target_id) === -1 + biliStore.fansMedals?.every((m) => m.medal.target_id !== firstPageMedal.medal.target_id) ) { // 添加新的粉丝勋章 biliStore.fansMedals.push(firstPageMedal) From 5470bb35116275853bc0dd986183092a9f37aad9 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Mon, 11 Sep 2023 20:17:06 +0800 Subject: [PATCH 16/29] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20cookie?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=87=BD=E6=95=B0=E6=94=B9=E4=B8=BA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=B3=9B=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/cookie/index.ts | 27 +++++++++++++++------------ src/modules/default/cookies.ts | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/library/cookie/index.ts b/src/library/cookie/index.ts index 56895e8c..6b42d49c 100644 --- a/src/library/cookie/index.ts +++ b/src/library/cookie/index.ts @@ -18,10 +18,10 @@ function getCookie(name: string): string | null { /** * 获取名称在 names 中的 cookies * - * 该方法会修改 names + * 该方法会修改 names,names 中剩余的 cookie 名称是没获取到的 cookie * @param names Cookies 名称字符串 */ -function getCookies(names: string[]): Record { +function getCookies(names: string[]): T { const cookies: Record = {} // 所有 cookies 赋初值 null for (const name of names) { @@ -41,25 +41,26 @@ function getCookies(names: string[]): Record { } if (names.length === 0) break } - return cookies + return cookies as T } /** * 获取名称在 names 中的 cookies,如果有 cookie 未获取到,会重复获取直到超时为止 * - * 该方法会修改 names + * 该方法会修改 names,names 中剩余的 cookie 名称是没获取到的 cookie * @param names Cookies 名称字符串 * @param interval 获取间隔 * @param timeout 超时时间 */ -function getCookiesAsync( +function getCookiesAsync( names: string[], interval: number = 100, timeout: number = 10e3 -): Promise> { - return new Promise((resolve, reject) => { - const cookies = getCookies(names) +): Promise { + return new Promise((resolve, reject) => { + const cookies = getCookies(names) if (names.length > 0) { + let timeoutTimer: number | undefined const cookieTimer = setInterval(() => { _.merge(cookies, getCookies(names)) if (names.length === 0) { @@ -68,10 +69,12 @@ function getCookiesAsync( resolve(cookies) } }, interval) - const timeoutTimer = setTimeout(() => { - clearInterval(cookieTimer) - reject('获取以下Cookies超时: ' + names.toString()) - }, timeout) + if (timeout !== -1) { + timeoutTimer = setTimeout(() => { + clearInterval(cookieTimer) + reject('获取以下Cookies超时: ' + names.toString()) + }, timeout) + } } else { resolve(cookies) } diff --git a/src/modules/default/cookies.ts b/src/modules/default/cookies.ts index 4e2354af..072d6514 100644 --- a/src/modules/default/cookies.ts +++ b/src/modules/default/cookies.ts @@ -12,7 +12,7 @@ class Cookies extends BaseModule { * LIVE_BUVID: 如果用户以前从来没看过直播,此时可能为 null */ private getCookies(): Promise { - return getCookiesAsync(['bili_jct', 'LIVE_BUVID']) as unknown as Promise + return getCookiesAsync(['bili_jct', 'LIVE_BUVID']) } public async run(): Promise { From c42fcb5239b2022191f74a7f1144d96f2cc69484 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Mon, 11 Sep 2023 20:17:21 +0800 Subject: [PATCH 17/29] =?UTF-8?q?=F0=9F=93=83=20docs:=20Update=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c04d8b7c..9ea87213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # 更新日志 -## [7.1.2] - 2023-9-9 +## [7.1.2] - 2023-9-11 ## 新增 @@ -14,6 +14,7 @@ ## 调整 - 直播任务板块UI微调 +- 粉丝勋章获取逻辑调整,现在可以获取完整的粉丝勋章列表(但可能会耗费很长时间) ## [7.1.1] - 2023-9-5 From afd0c19cc9d18bdb8e5a8ed7d2048739a586e834 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Tue, 12 Sep 2023 14:24:19 +0800 Subject: [PATCH 18/29] =?UTF-8?q?=F0=9F=8E=88=20perf:=20cookie=E5=BA=93?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/cookie/index.ts | 109 ++++++++++++++++----------------- src/modules/default/cookies.ts | 2 +- 2 files changed, 53 insertions(+), 58 deletions(-) diff --git a/src/library/cookie/index.ts b/src/library/cookie/index.ts index 6b42d49c..7b2cf1c8 100644 --- a/src/library/cookie/index.ts +++ b/src/library/cookie/index.ts @@ -2,82 +2,77 @@ import _ from 'lodash' /** * 获取名称为 name 的 cookie - * @param name Cookie 名称 + * @param name 要获取的 cookie 名称 */ function getCookie(name: string): string | null { - const nameEqual = name + '=' - for (const cookie of document.cookie.split('; ')) { - if (cookie.startsWith(nameEqual)) { - const value = cookie.substring(nameEqual.length) - return decodeURIComponent(value) - } - } + const value = `; ${document.cookie}` + const parts = value.split(`; ${name}=`) + if (parts.length === 2) return parts.pop()!.split(';').shift() as string return null } /** - * 获取名称在 names 中的 cookies - * - * 该方法会修改 names,names 中剩余的 cookie 名称是没获取到的 cookie - * @param names Cookies 名称字符串 + * 获取名称在 names 数组中的 cookies + * @param names 要获取的 cookie 名称数组 */ -function getCookies(names: string[]): T { - const cookies: Record = {} - // 所有 cookies 赋初值 null - for (const name of names) { +function getCookies(names: Iterable): Record { + const cookies: Record = {} as Record + const namesSet = new Set(names) + + // 初始化所有 cookie 为 null + for (const name of namesSet) { cookies[name] = null } + for (const cookie of document.cookie.split('; ')) { - for (let i = 0; i < names.length; i++) { - const name = names[i] - const nameEqual = name + '=' - if (cookie.startsWith(nameEqual)) { - const value = cookie.substring(nameEqual.length) - cookies[name] = decodeURIComponent(value) - // 从 names 中删除已获取的 cookie - names.splice(i, 1) - break - } + const [cookieName, ...cookieValueParts] = cookie.split('=') + const cookieValue = cookieValueParts.join('=') + + if (namesSet.has(cookieName as T)) { + cookies[cookieName as T] = decodeURIComponent(cookieValue) + namesSet.delete(cookieName as T) + + // 所有 cookie 都已找到,跳出循环 + if (namesSet.size === 0) break } - if (names.length === 0) break } - return cookies as T + + return cookies } /** - * 获取名称在 names 中的 cookies,如果有 cookie 未获取到,会重复获取直到超时为止 + * 获取名称在 names 中的 cookies,如果有 cookie 未获取到,会反复获取直到超时为止 * - * 该方法会修改 names,names 中剩余的 cookie 名称是没获取到的 cookie - * @param names Cookies 名称字符串 + * @param names 要获取的 cookie 名称数组 * @param interval 获取间隔 - * @param timeout 超时时间 + * @param timeout 超时时间,若为 -1 则永不超时 */ -function getCookiesAsync( - names: string[], - interval: number = 100, - timeout: number = 10e3 -): Promise { - return new Promise((resolve, reject) => { - const cookies = getCookies(names) - if (names.length > 0) { - let timeoutTimer: number | undefined - const cookieTimer = setInterval(() => { - _.merge(cookies, getCookies(names)) - if (names.length === 0) { - clearInterval(cookieTimer) - clearTimeout(timeoutTimer) - resolve(cookies) - } - }, interval) - if (timeout !== -1) { - timeoutTimer = setTimeout(() => { - clearInterval(cookieTimer) - reject('获取以下Cookies超时: ' + names.toString()) - }, timeout) +function getCookiesAsync( + names: T[], + interval: number = 200, + timeout: number = 10000 +): Promise> { + return new Promise((resolve, reject) => { + const startTime = Date.now() + const remainNamesSet = new Set(names) + const cookies: Record = {} as Record + + const timer = setInterval(() => { + Object.assign(cookies, getCookies(remainNamesSet)) + + // 删去 remainNamesSet 中已获取的 cookies + for (const name in cookies) { + if (cookies[name] !== null) remainNamesSet.delete(name) } - } else { - resolve(cookies) - } + + if (remainNamesSet.size === 0) { + clearInterval(timer) + resolve(cookies) + } else if (timeout !== -1 && Date.now() - startTime > timeout) { + clearInterval(timer) + reject('获取以下Cookies超时: ' + [...remainNamesSet]) + } + }, interval) }) } diff --git a/src/modules/default/cookies.ts b/src/modules/default/cookies.ts index 072d6514..a6e6a70d 100644 --- a/src/modules/default/cookies.ts +++ b/src/modules/default/cookies.ts @@ -12,7 +12,7 @@ class Cookies extends BaseModule { * LIVE_BUVID: 如果用户以前从来没看过直播,此时可能为 null */ private getCookies(): Promise { - return getCookiesAsync(['bili_jct', 'LIVE_BUVID']) + return getCookiesAsync(['bili_jct', 'LIVE_BUVID']) } public async run(): Promise { From 16351532aae1bb2df3247c032d47324d387806a3 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Tue, 12 Sep 2023 14:27:49 +0800 Subject: [PATCH 19/29] =?UTF-8?q?=F0=9F=8C=88=20style:=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/cookie/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/library/cookie/index.ts b/src/library/cookie/index.ts index 7b2cf1c8..9fd48438 100644 --- a/src/library/cookie/index.ts +++ b/src/library/cookie/index.ts @@ -1,5 +1,3 @@ -import _ from 'lodash' - /** * 获取名称为 name 的 cookie * @param name 要获取的 cookie 名称 From 4760be2a252734ec30d30062c5fc5bae18191ace Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Tue, 12 Sep 2023 16:39:35 +0800 Subject: [PATCH 20/29] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=AD=89=E7=BB=86=E8=8A=82=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/default/bilibiliLive.ts | 6 +-- src/modules/enhanceExperience/banP2P.ts | 6 +-- src/modules/enhanceExperience/noReport.ts | 15 ++++++- src/modules/enhanceExperience/noSleep.ts | 4 +- .../switchLiveStreamQuality.ts | 40 ++++++++++--------- src/stores/useBiliStore.ts | 14 +++---- src/stores/useCacheStore.ts | 7 ++-- src/stores/useModuleStore.ts | 9 ++--- 8 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/modules/default/bilibiliLive.ts b/src/modules/default/bilibiliLive.ts index 5fb3b281..5e0e280f 100644 --- a/src/modules/default/bilibiliLive.ts +++ b/src/modules/default/bilibiliLive.ts @@ -5,7 +5,6 @@ import BaseModule from '../BaseModule' class BilibiliLive extends BaseModule { /** * 获取 window.BilibiliLive - * @returns 一个 window.BilibiliLive 对象的引用 */ private getBilibiliLive(): Promise { this.logger.log('unsafeWindow.BilibiliLive', unsafeWindow.BilibiliLive) @@ -20,10 +19,11 @@ class BilibiliLive extends BaseModule { set(target: Window['BilibiliLive'], prop: keyof Window['BilibiliLive'], value: never) { target[prop] = value // UID 是最后被赋值的属性,等 UID 被赋值后 BilibiliLive 的所有属性就都被初始化了 - if (prop === 'UID' && unsafeWindow.BilibiliLive.UID !== 0) { - resolve(unsafeWindow.BilibiliLive) + if (prop === 'UID') { // 取消代理,还原为 Object unsafeWindow.BilibiliLive = target + // 返回 BilibiliLive + resolve(unsafeWindow.BilibiliLive) } return true } diff --git a/src/modules/enhanceExperience/banP2P.ts b/src/modules/enhanceExperience/banP2P.ts index d0c5a95f..5b417ed2 100644 --- a/src/modules/enhanceExperience/banP2P.ts +++ b/src/modules/enhanceExperience/banP2P.ts @@ -10,7 +10,7 @@ class BanP2P extends BaseModule { config = this.moduleStore.moduleConfig.EnhanceExperience.banp2p - private async banP2P() { + private banP2P(): void { const RTClist: string[] = [ 'RTCPeerConnection', 'mozRTCPeerConnection', @@ -48,11 +48,11 @@ class BanP2P extends BaseModule { } } - public async run() { + public run(): void { this.logger.log('禁用P2P模块开始运行') if (this.config.enabled) { try { - await this.banP2P() + this.banP2P() } catch (e) { this.logger.error('禁用P2P失败', e) } diff --git a/src/modules/enhanceExperience/noReport.ts b/src/modules/enhanceExperience/noReport.ts index a1ab7db8..fe971350 100644 --- a/src/modules/enhanceExperience/noReport.ts +++ b/src/modules/enhanceExperience/noReport.ts @@ -13,6 +13,10 @@ class NoReport extends BaseModule { config = this.moduleStore.moduleConfig.EnhanceExperience.noReport + /** + * 判断是否是需要拦截的 URL + * @param url 需要判断的 URL + */ private static isTargetURL(url: string) { if (url.includes('//data.bilibili.com') || url.includes('//data.bilivideo.com')) { return true @@ -21,6 +25,10 @@ class NoReport extends BaseModule { } } + /** + * 劫持一些能减少日志上报的方法 + * @param win window + */ private hookProperties(win: Window) { Object.defineProperty(win.navigator, 'sendBeacon', { value: () => { @@ -46,6 +54,9 @@ class NoReport extends BaseModule { }) } + /** + * 劫持 XHR 和 fetch 请求 + */ private async ajaxHook() { const ajaxHookProxyConfig = { onRequest: (config: XhrRequestConfig, handler: XhrRequestHandler) => { @@ -82,11 +93,11 @@ class NoReport extends BaseModule { fproxy(fetchHookConfig, unsafeWindow) } - public async run() { + public run() { this.logger.log('拦截日志数据上报模块开始运行') if (this.config.enabled) { try { - await this.ajaxHook() + this.ajaxHook() } catch (e) { this.logger.error('拦截日志数据上报失败', e) } diff --git a/src/modules/enhanceExperience/noSleep.ts b/src/modules/enhanceExperience/noSleep.ts index 0594fe54..351fb0aa 100644 --- a/src/modules/enhanceExperience/noSleep.ts +++ b/src/modules/enhanceExperience/noSleep.ts @@ -8,12 +8,12 @@ class NoSleep extends BaseModule { config = this.moduleStore.moduleConfig.EnhanceExperience.noSleep - public async run() { + public run(): void { this.logger.log('屏蔽挂机检测模块开始运行') if (this.config.enabled) { setInterval(() => { document.dispatchEvent(new MouseEvent('mousemove')) - }, 3e5) // 5分钟 + }, 3e5) // 5分钟触发一次 MouseEvent } } } diff --git a/src/modules/enhanceExperience/switchLiveStreamQuality.ts b/src/modules/enhanceExperience/switchLiveStreamQuality.ts index fe93161c..baa8aad4 100644 --- a/src/modules/enhanceExperience/switchLiveStreamQuality.ts +++ b/src/modules/enhanceExperience/switchLiveStreamQuality.ts @@ -10,7 +10,7 @@ class SwitchLiveStreamQuality extends BaseModule { config = this.moduleStore.moduleConfig.EnhanceExperience.switchLiveStreamQuality - private async waitForPlayer() { + private async waitForPlayer(): Promise { return new Promise((resolve, reject) => { const topWindow = unsafeWindow.top ? unsafeWindow.top : unsafeWindow const findPlayertimer = setInterval(() => { @@ -27,7 +27,7 @@ class SwitchLiveStreamQuality extends BaseModule { const timeoutTimer = setTimeout(() => { clearInterval(findPlayertimer) clearTimeout(timeoutTimer) - reject() + reject('等待播放器超时') }, 10e3) }) } @@ -35,34 +35,38 @@ class SwitchLiveStreamQuality extends BaseModule { private async switchQuality(livePlayer: Window['livePlayer']) { const playerInfo = livePlayer.getPlayerInfo() if (playerInfo.liveStatus === 0) { - this.logger.log('当前直播间未开播') + this.logger.log('当前直播间未开播,无需切换画质') } else { - const switchFn = () => { - const targetQuality = playerInfo.qualityCandidates.find( - ({ desc }) => desc === this.config.qualityDesc - ) - if (targetQuality && playerInfo.quality !== targetQuality.qn) { - livePlayer.switchQuality(targetQuality.qn) - this.logger.log(`已将画质切换为${this.config.qualityDesc}`, targetQuality) - } - } // 直接切换画质可能会有个加载中图标一直转圈,目前没有找到确切的最早可切换画质时机 setTimeout( - () => switchFn(), + () => { + const targetQuality = playerInfo.qualityCandidates.find( + ({ desc }) => desc === this.config.qualityDesc + ) + if (targetQuality) { + if (playerInfo.quality !== targetQuality.qn) { + livePlayer.switchQuality(targetQuality.qn) + this.logger.log(`已将画质切换为${this.config.qualityDesc}`, targetQuality) + } else { + this.logger.log('当前画质已经是目标画质了,无需切换画质') + } + } else { + this.logger.log('当前直播不支持目标画质,保持默认画质') + } + }, // 这里针对特殊直播间和普通直播间设置了两套超时时间,特殊直播间超时时间更长 - !isSelfTopFrame() ? 5000 : 2500 + isSelfTopFrame() ? 2500 : 5000 ) } } - public async run() { + public run(): void { this.logger.log('自动切换画质模块开始运行') if (this.config.enabled) { try { - const livePlayer = await this.waitForPlayer() - this.switchQuality(livePlayer) + this.waitForPlayer().then((livePlayer) => this.switchQuality(livePlayer)) } catch (e) { - this.logger.error('等待播放器超时') + this.logger.error('自动切换画质模块出错', e) } } } diff --git a/src/stores/useBiliStore.ts b/src/stores/useBiliStore.ts index aff21aeb..c36da2d4 100644 --- a/src/stores/useBiliStore.ts +++ b/src/stores/useBiliStore.ts @@ -5,19 +5,19 @@ import { IbiliCookies } from '../types' export const useBiliStore = defineStore('bili', () => { // window.BilibiliLive 包含当前直播间的一些基本信息 - const BilibiliLive = ref() + const BilibiliLive = ref(null) // 脚本要用到的 Cookies - const cookies = ref() + const cookies = ref(null) // 用户基本信息 - const userInfo = ref() + const userInfo = ref(null) // 礼物配置信息 - const giftConfig = ref() + const giftConfig = ref(null) // 主站每日任务完成情况 - const dailyRewardInfo = ref() + const dailyRewardInfo = ref(null) // 动态中一页视频的信息 - const dynamicVideos = ref() + const dynamicVideos = ref(null) // 粉丝勋章列表 - const fansMedals = ref() + const fansMedals = ref(null) // 过滤了不存在直播间的粉丝勋章 const filteredFansMedals = computed(() => { if (!fansMedals.value) return null diff --git a/src/stores/useCacheStore.ts b/src/stores/useCacheStore.ts index 3420c3f7..140f7228 100644 --- a/src/stores/useCacheStore.ts +++ b/src/stores/useCacheStore.ts @@ -45,17 +45,16 @@ export const useCacheStore = defineStore('cache', () => { function checkCurrentScriptType(): void { if ( cache.lastAliveHeartBeatTime !== 0 && - // 允许最多3秒的误差 - Date.now() - cache.lastAliveHeartBeatTime < 8000 + Date.now() - cache.lastAliveHeartBeatTime < 8000 // 允许最多3秒的误差 ) { - // 通过 sessionStorage 中的 flag 来判断当前页面上有没有 Main BLTH + // 存在 Main BLTH,通过 sessionStorage 中的 flag 来判断当前页面上有没有 Main BLTH if (sessionStorage.getItem('main_blth_flag') === null) { currentScriptType.value = 'Other' } else { - // 如果有,那么当前脚本的类型是 SubMain currentScriptType.value = 'SubMain' } } else { + // 不存在 Main BLTH,则当前脚本成为 Main BLTH 并记录 flag currentScriptType.value = 'Main' sessionStorage.setItem('main_blth_flag', '🚩') } diff --git a/src/stores/useModuleStore.ts b/src/stores/useModuleStore.ts index a2331e00..62ec42fc 100644 --- a/src/stores/useModuleStore.ts +++ b/src/stores/useModuleStore.ts @@ -52,7 +52,6 @@ export const useModuleStore = defineStore('module', () => { // 所有模块的配置信息 const moduleConfig: ImoduleConfig = reactive(Storage.getModuleConfig()) // Emitter 实例,用于模块间信息传递和 wait 函数 - // 建议使用模块名称作为 Emitter 方法的 type 参数 const emitter = mitt() // 模块状态,用于显示状态图标 const moduleStatus: ImoduleStatus = reactive(defaultModuleStatus) @@ -60,7 +59,7 @@ export const useModuleStore = defineStore('module', () => { /** * 加载默认模块(该函数不导出) */ - function loadDefaultModules(): Promise { + function loadDefaultModules(): Promise { const cacheStore = useCacheStore() const promiseArray: Promise[] = [] for (const [name, module] of Object.entries(defaultModules)) { @@ -70,7 +69,7 @@ export const useModuleStore = defineStore('module', () => { ) } } - return Promise.all(promiseArray) + return Promise.all[]>(promiseArray) } /** @@ -101,7 +100,7 @@ export const useModuleStore = defineStore('module', () => { } } else { // 加载默认模块 - const defaultModulesLoaded: Promise = loadDefaultModules() + const defaultModulesLoaded: Promise = loadDefaultModules() // 加载其它模块 for (const [name, module] of Object.entries(otherModules)) { // 对 onFrame 为 all 或 top 的模块来说,如果之前运行过,现在就不运行了 @@ -122,7 +121,7 @@ export const useModuleStore = defineStore('module', () => { new (module as new (moduleName: string) => BaseModule)(name).run() } catch (e) { // 默认模块运行出错,不运行该模块 - logger.error(`运行默认模块时出错,模块${name}不运行`, e) + logger.error(`运行默认模块时出错,模块 ${name} 不运行:`, e) } }) } From b18a3ed441b132f3a370058b97a1787429c9c9da Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Tue, 12 Sep 2023 16:55:24 +0800 Subject: [PATCH 21/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD=E7=BB=86=E8=8A=82=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/BaseModule.ts | 3 +- .../dailyTasks/mainSiteTasks/coinTask.ts | 36 +++++++++++++------ .../dailyTasks/mainSiteTasks/loginTask.ts | 12 +++---- .../dailyTasks/mainSiteTasks/shareTask.ts | 20 +++++------ .../dailyTasks/otherTasks/silverToCoinTask.ts | 12 +++---- .../switchLiveStreamQuality.ts | 5 +-- 6 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/modules/BaseModule.ts b/src/modules/BaseModule.ts index 0e685c22..30cf6ab1 100644 --- a/src/modules/BaseModule.ts +++ b/src/modules/BaseModule.ts @@ -89,7 +89,8 @@ class BaseModule { /** * 运行模块 * - * 默认模块返回一个空的Promise,其它模块无返回值 + * 默认模块必须返回一个空的Promise, + * 其它模块若需要使用 await 可以返回一个空的Promise,否则无返回值 */ public run(): void | Promise { throw new Error('Method not implemented.') diff --git a/src/modules/dailyTasks/mainSiteTasks/coinTask.ts b/src/modules/dailyTasks/mainSiteTasks/coinTask.ts index fb27c927..bc1259a4 100644 --- a/src/modules/dailyTasks/mainSiteTasks/coinTask.ts +++ b/src/modules/dailyTasks/mainSiteTasks/coinTask.ts @@ -19,14 +19,16 @@ class CoinTask extends BaseModule { // 通过其响应的copyright字段(1原创,2转载)来判断 // 不过这个接口带有 wbi 签名,实现起来复杂 // 所以干脆直接限制每个视频最多投一个币,反正视频数量足够 - readonly MAX_COIN = 1 + private readonly MAX_COIN = 1 + /** + * 获取动态视频的 aid 和 bvid + */ private getDynamicVideoIds(): { aid: string; bvid: string }[] | null { const biliStore = useBiliStore() - if (!_.isEmpty(biliStore.dynamicVideos)) { - // 当 biliStore.dynamicVideos 不是 {} 或 null 或 [] 时 - // 返回所有的 aid 和 bvid - return (biliStore.dynamicVideos as MainData.DynamicAll.Item[]).map((item) => { + if (biliStore.dynamicVideos) { + // 当 biliStore.dynamicVideos 不为 null 时,返回所有的 aid 和 bvid + return biliStore.dynamicVideos.map((item) => { const archive = item.modules.module_dynamic.major.archive return { aid: archive.aid, @@ -40,6 +42,11 @@ class CoinTask extends BaseModule { } } + /** + * 获取一个视频的你的已投硬币数量 + * + * @returns 你的已投硬币数 + */ private async getVideoCoinInfo(aid: string, bvid: string): Promise { try { const response = await BAPI.main.videoRelation(aid, bvid) @@ -56,7 +63,11 @@ class CoinTask extends BaseModule { } } - private async coinDynamicVideos(left_coin_num: number) { + /** + * 给动态中的视频投币 + * @param left_coin_num 还需要投的硬币数 + */ + private async coinDynamicVideos(left_coin_num: number): Promise { const ids = this.getDynamicVideoIds() if (ids) { for (const { aid, bvid } of ids) { @@ -87,6 +98,9 @@ class CoinTask extends BaseModule { } } + /** + * 投币 + */ private async coin(aid: string, num: number): Promise { try { const response = await BAPI.main.coinAdd(aid, num) @@ -107,7 +121,7 @@ class CoinTask extends BaseModule { } } - public async run() { + public async run(): Promise { this.logger.log('每日投币模块开始运行') if (this.config.enabled) { const biliStore = useBiliStore() @@ -139,13 +153,13 @@ class CoinTask extends BaseModule { } else { // 为了更加准确的语言描述和任务状态图标显示,需要判断当前所处的时间段 // 下面文字中的今天、昨天是指真实的今天、昨天而非在 isTimestampToday 函数中重新定义的 - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + // 在半夜00:00 ~ 00:05 + this.logger.log('昨天的每日投币任务已经完成过了,等到今天的00:05再执行') + } else { // 在非半夜00:00 ~ 00:05的其它时间 this.logger.log('今天已经完成过每日投币任务了') this.status = 'done' - } else { - // 在半夜00:00 ~ 00:05 - this.logger.log('昨天的每日投币任务已经完成过了,等到今天的00:05再执行') } } } diff --git a/src/modules/dailyTasks/mainSiteTasks/loginTask.ts b/src/modules/dailyTasks/mainSiteTasks/loginTask.ts index 7a12fba8..d330cfc5 100644 --- a/src/modules/dailyTasks/mainSiteTasks/loginTask.ts +++ b/src/modules/dailyTasks/mainSiteTasks/loginTask.ts @@ -10,9 +10,9 @@ class LoginTask extends BaseModule { this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.login = s } - private async login() { + private async login(): Promise { // 触发每日登录任务的请求是 BAPI.main.nav - // 这个请求脚本在默认模块 biliInfo 中每天都会发送 + // 这个请求脚本在默认模块 userInfo 中每天都会发送 // 而且打开任意B站页面的时候都会有这个请求 // 所以直接当作是完成了 this.logger.log('每日登录任务已完成') @@ -22,7 +22,7 @@ class LoginTask extends BaseModule { return Promise.resolve() } - public async run() { + public async run(): Promise { this.logger.log('每日登录模块开始运行') // 开启了每日登录 if (this.config.enabled) { @@ -39,11 +39,11 @@ class LoginTask extends BaseModule { this.status = 'done' } } else { - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + this.logger.log('昨天的每日登录任务已经完成过了,等到今天的00:05再执行') + } else { this.logger.log('今天已经完成过每日登录任务了') this.status = 'done' - } else { - this.logger.log('昨天的每日登录任务已经完成过了,等到今天的00:05再执行') } } } diff --git a/src/modules/dailyTasks/mainSiteTasks/shareTask.ts b/src/modules/dailyTasks/mainSiteTasks/shareTask.ts index 04059361..532ace9f 100644 --- a/src/modules/dailyTasks/mainSiteTasks/shareTask.ts +++ b/src/modules/dailyTasks/mainSiteTasks/shareTask.ts @@ -15,18 +15,16 @@ class ShareTask extends BaseModule { private getAid(): string { const biliStore = useBiliStore() - if (!_.isEmpty(biliStore.dynamicVideos)) { - // 当 biliStore.dynamicVideos 不是 {} 或 null 或 [] 时 - // 返回第一个视频的 aid - return (biliStore.dynamicVideos as MainData.DynamicAll.Item[])[0].modules.module_dynamic.major - .archive.aid + if (biliStore.dynamicVideos) { + // 当 biliStore.dynamicVideos 不为 null 时,返回第一个视频的 aid + return biliStore.dynamicVideos[0].modules.module_dynamic.major.archive.aid } else { // 否则返回 '2' return '2' } } - private async share(aid: string) { + private async share(aid: string): Promise { try { const response = await BAPI.main.share(aid) this.logger.log(`BAPI.main.share(${aid}) response`, response) @@ -45,7 +43,7 @@ class ShareTask extends BaseModule { } } - public async run() { + public async run(): Promise { this.logger.log('每日分享视频模块开始运行') if (this.config.enabled) { const biliStore = useBiliStore() @@ -60,11 +58,11 @@ class ShareTask extends BaseModule { this.logger.log('每日分享视频任务已完成') } } else { - if (!isNowIn(0, 0, 0, 5)) { - this.logger.log('今天已经完成过每日分享任务了') - this.status = 'done' // done - } else { + if (isNowIn(0, 0, 0, 5)) { this.logger.log('昨天的每日分享任务已经完成过了,等到今天的00:05再执行') + } else { + this.logger.log('今天已经完成过每日分享任务了') + this.status = 'done' } } } diff --git a/src/modules/dailyTasks/otherTasks/silverToCoinTask.ts b/src/modules/dailyTasks/otherTasks/silverToCoinTask.ts index b47a81c5..f3a90cc9 100644 --- a/src/modules/dailyTasks/otherTasks/silverToCoinTask.ts +++ b/src/modules/dailyTasks/otherTasks/silverToCoinTask.ts @@ -10,7 +10,7 @@ class SilverToCoinTask extends BaseModule { this.moduleStore.moduleStatus.DailyTasks.OtherTasks.silverToCoin = s } - private async exchange() { + private async exchange(): Promise { try { const response = await BAPI.live.silver2coin() this.logger.log(`BAPI.live.silver2coin response`, response) @@ -33,18 +33,18 @@ class SilverToCoinTask extends BaseModule { } } - public async run() { + public run(): void { this.logger.log('银瓜子换硬币模块开始运行') if (this.config.enabled) { if (!isTimestampToday(this.config._lastCompleteTime)) { this.status = 'running' - await this.exchange() + this.exchange() } else { - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + this.logger.log('昨天的银瓜子换硬币任务已经完成过了,等到今天的00:05再执行') + } else { this.logger.log('今天已经完成过银瓜子换硬币任务了') this.status = 'done' - } else { - this.logger.log('昨天的银瓜子换硬币任务已经完成过了,等到今天的00:05再执行') } } } diff --git a/src/modules/enhanceExperience/switchLiveStreamQuality.ts b/src/modules/enhanceExperience/switchLiveStreamQuality.ts index baa8aad4..39e6fa56 100644 --- a/src/modules/enhanceExperience/switchLiveStreamQuality.ts +++ b/src/modules/enhanceExperience/switchLiveStreamQuality.ts @@ -60,11 +60,12 @@ class SwitchLiveStreamQuality extends BaseModule { } } - public run(): void { + public async run(): Promise { this.logger.log('自动切换画质模块开始运行') if (this.config.enabled) { try { - this.waitForPlayer().then((livePlayer) => this.switchQuality(livePlayer)) + const livePlayer = await this.waitForPlayer() + this.switchQuality(livePlayer) } catch (e) { this.logger.error('自动切换画质模块出错', e) } From 23e02c7b80a257be7b9f1722ffa9ae529fc2d8c3 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Tue, 12 Sep 2023 19:49:25 +0800 Subject: [PATCH 22/29] =?UTF-8?q?=F0=9F=90=B3=20chore:=20=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E4=BB=BB=E5=8A=A1=E6=A8=A1=E5=9D=97=E7=BB=86=E8=8A=82?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liveTasks/medalTasks/danmuTask.ts | 18 ++++-- .../liveTasks/medalTasks/likeTask.ts | 40 ++++++++------ .../liveTasks/medalTasks/watchTask.ts | 55 ++++++++++--------- .../dailyTasks/mainSiteTasks/coinTask.ts | 1 - .../dailyTasks/mainSiteTasks/shareTask.ts | 2 - 5 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/modules/dailyTasks/liveTasks/medalTasks/danmuTask.ts b/src/modules/dailyTasks/liveTasks/medalTasks/danmuTask.ts index 6f6ae444..35651f2f 100644 --- a/src/modules/dailyTasks/liveTasks/medalTasks/danmuTask.ts +++ b/src/modules/dailyTasks/liveTasks/medalTasks/danmuTask.ts @@ -16,7 +16,7 @@ class DanmuTask extends BaseModule { /** * 获取粉丝勋章的房间号,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章 */ - private getRoomidList() { + private getRoomidList(): number[] | null { const biliStore = useBiliStore() if (biliStore.filteredFansMedals) { return biliStore.filteredFansMedals @@ -36,7 +36,12 @@ class DanmuTask extends BaseModule { } } - private async sendDanmu(danmu: string, roomid: number) { + /** + * 发弹幕 + * @param danmu 弹幕内容 + * @param roomid 直播间号 + */ + private async sendDanmu(danmu: string, roomid: number): Promise { try { const response = await BAPI.live.sendMsg(danmu, roomid) this.logger.log(`BAPI.live.sendMsg(${danmu}, ${roomid})`, response) @@ -50,7 +55,7 @@ class DanmuTask extends BaseModule { } } - public async run() { + public async run(): Promise { this.logger.log('发送弹幕模块开始运行') if (this.config.enabled) { if (!isTimestampToday(this.config._lastCompleteTime)) { @@ -70,14 +75,15 @@ class DanmuTask extends BaseModule { this.logger.log('发送弹幕任务已完成') } } else { - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + this.logger.log('昨天的发送弹幕任务已经完成过了,等到今天的00:05再执行') + } else { this.logger.log('今天已经完成过发送弹幕任务了') this.status = 'done' - } else { - this.logger.log('昨天的发送弹幕任务已经完成过了,等到今天的00:05再执行') } } } + // 通知APP用户任务模块,可以开始运行了 this.moduleStore.emitter.emit('DailyTask_LiveTask_AppUserTask', { module: this.moduleName }) diff --git a/src/modules/dailyTasks/liveTasks/medalTasks/likeTask.ts b/src/modules/dailyTasks/liveTasks/medalTasks/likeTask.ts index fdc51f71..d43cb8ac 100644 --- a/src/modules/dailyTasks/liveTasks/medalTasks/likeTask.ts +++ b/src/modules/dailyTasks/liveTasks/medalTasks/likeTask.ts @@ -15,28 +15,34 @@ class LikeTask extends BaseModule { /** * 获取粉丝勋章的房间号和主播uid,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章 - * @returns 数组,每个元素都是数组:[房间号,主播uid] + * @returns 数组,数组中的每个元素都是数组:[房间号,主播uid] */ - private getRoomidUidList() { + private getRoomidUidList(): [number, number][] | null { const biliStore = useBiliStore() if (biliStore.filteredFansMedals) { - return biliStore.filteredFansMedals - .filter( - (medal) => - (this.config.includeHighLevelMedals ? true : medal.medal.level < 20) && - (this.medalTasksConfig.isWhiteList - ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) - : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id)) - ) - .map((medal) => [medal.room_info.room_id, medal.medal.target_id]) - .slice(0, 100) + return ( + biliStore.filteredFansMedals + .filter( + (medal) => + (this.config.includeHighLevelMedals ? true : medal.medal.level < 20) && + (this.medalTasksConfig.isWhiteList + ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) + : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id)) + ) + .map((medal) => [medal.room_info.room_id, medal.medal.target_id]) as [number, number][] + ).slice(0, 100) } else { this.status = 'error' return null } } - private async like(roomid: number, target_id: number) { + /** + * 点赞 + * @param roomid 直播间号 + * @param target_id 主播UID + */ + private async like(roomid: number, target_id: number): Promise { try { const response = await BAPI.live.likeReport(roomid, target_id) this.logger.log(`BAPI.live.likeReport(${roomid}, ${target_id})`, response) @@ -53,7 +59,7 @@ class LikeTask extends BaseModule { } } - public async run() { + public async run(): Promise { this.logger.log('给主播点赞模块开始运行') if (this.config.enabled) { if (!isTimestampToday(this.config._lastCompleteTime)) { @@ -70,11 +76,11 @@ class LikeTask extends BaseModule { this.logger.log('给主播点赞任务已完成') } } else { - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + this.logger.log('昨天的给主播点赞任务已经完成过了,等到今天的00:05再执行') + } else { this.logger.log('今天已经完成过给主播点赞任务了') this.status = 'done' - } else { - this.logger.log('昨天的给主播点赞任务已经完成过了,等到今天的00:05再执行') } } } diff --git a/src/modules/dailyTasks/liveTasks/medalTasks/watchTask.ts b/src/modules/dailyTasks/liveTasks/medalTasks/watchTask.ts index fe90095b..4dcb54a9 100644 --- a/src/modules/dailyTasks/liveTasks/medalTasks/watchTask.ts +++ b/src/modules/dailyTasks/liveTasks/medalTasks/watchTask.ts @@ -211,7 +211,7 @@ class RoomHeart { const data: sypderData = JSON.parse(str) const [parent_id, area_id, seq_id, room_id]: number[] = JSON.parse(data.id) const [buvid, uuid]: string[] = JSON.parse(data.device) - const key = data.benchmark + const key: string = data.benchmark const newData = { platform: 'web', parent_id, @@ -265,21 +265,22 @@ class WatchTask extends BaseModule { /** * 获取粉丝勋章的房间号和主播uid,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章 - * @returns 数组,每个元素都是数组:[房间号,主播uid] + * @returns 数组,数组中的每个元素都是数组:[房间号,主播uid] */ - private getRoomidUidList() { + private getRoomidUidList(): [number, number][] | null { const biliStore = useBiliStore() if (biliStore.filteredFansMedals) { - return biliStore.filteredFansMedals - .filter( - (medal) => - medal.medal.level < 20 && - (this.medalTasksConfig.isWhiteList - ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) - : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id)) - ) - .map((medal) => [medal.room_info.room_id, medal.medal.target_id]) - .slice(0, 100) + return ( + biliStore.filteredFansMedals + .filter( + (medal) => + medal.medal.level < 20 && + (this.medalTasksConfig.isWhiteList + ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) + : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id)) + ) + .map((medal) => [medal.room_info.room_id, medal.medal.target_id]) as [number, number][] + ).slice(0, 100) } else { return null } @@ -288,10 +289,12 @@ class WatchTask extends BaseModule { /** * 获取指定直播间的 area_id 和 parent_area_id * + * 出错时返回 [-1, -1] + * * @param roomid 房间号 * @returns [area_id, parent_area_id] */ - private async getAreaInfo(roomid: number): Promise { + private async getAreaInfo(roomid: number): Promise<[number, number]> { try { const response = await BAPI.live.getInfoByRoom(roomid) this.logger.log(`BAPI.live.getInfoByRoom(${roomid}) response`, response) @@ -299,18 +302,18 @@ class WatchTask extends BaseModule { const room_info = response.data.room_info return [room_info.area_id, room_info.parent_area_id] } else { - return null + return [-1, -1] } } catch (error) { this.logger.error( `获取指定直播间的 area_id 和 parent_area_id(roomid = ${roomid}) 出错`, error ) - return null + return [-1, -1] } } - public async run() { + public async run(): Promise { this.logger.log('观看直播模块开始运行') if (this.config.enabled) { if (!isTimestampToday(this.config._lastCompleteTime)) { @@ -323,7 +326,7 @@ class WatchTask extends BaseModule { this.config._watchedSecondsToday -= this.config._watchedSecondsToday % 300 } this.config._lastWatchTime = tsm() - const idList = this.getRoomidUidList() + const idList: number[][] | null = this.getRoomidUidList() if (idList) { if (idList.length === 0) { this.status = 'done' @@ -331,13 +334,13 @@ class WatchTask extends BaseModule { } else { for (let i = 0; i < idList.length; i++) { const [roomid, uid] = idList[i] - const areaInfo = await this.getAreaInfo(roomid) - // area_id 和 parent_area_id 都必须存在且大于 0 - if (areaInfo && areaInfo.every((id) => id > 0)) { + const [area_id, parent_area_id] = await this.getAreaInfo(roomid) + if (area_id > 0 && parent_area_id > 0) { + // area_id 和 parent_area_id 都大于 0,说明直播间设置了分区。开始心跳 new RoomHeart( roomid, - areaInfo[0], - areaInfo[1], + area_id, + parent_area_id, uid, this.config._watchedSecondsToday, i === idList.length - 1 ? true : false @@ -349,11 +352,11 @@ class WatchTask extends BaseModule { } } } else { - if (!isNowIn(0, 0, 0, 5)) { + if (isNowIn(0, 0, 0, 5)) { + this.logger.log('昨天的观看直播任务已经完成过了,等到今天的00:05再执行') + } else { this.logger.log('今天已经完成过观看直播任务了') this.status = 'done' - } else { - this.logger.log('昨天的观看直播任务已经完成过了,等到今天的00:05再执行') } } } diff --git a/src/modules/dailyTasks/mainSiteTasks/coinTask.ts b/src/modules/dailyTasks/mainSiteTasks/coinTask.ts index bc1259a4..dad36dcb 100644 --- a/src/modules/dailyTasks/mainSiteTasks/coinTask.ts +++ b/src/modules/dailyTasks/mainSiteTasks/coinTask.ts @@ -3,7 +3,6 @@ import { isTimestampToday, delayToNextMoment, tsm, isNowIn } from '../../../libr import { useBiliStore } from '../../../stores/useBiliStore' import { MainData } from '../../../library/bili-api/data' import BAPI from '../../../library/bili-api' -import _ from 'lodash' import { moduleStatus } from '../../../types/module' class CoinTask extends BaseModule { diff --git a/src/modules/dailyTasks/mainSiteTasks/shareTask.ts b/src/modules/dailyTasks/mainSiteTasks/shareTask.ts index 532ace9f..8a8d2d31 100644 --- a/src/modules/dailyTasks/mainSiteTasks/shareTask.ts +++ b/src/modules/dailyTasks/mainSiteTasks/shareTask.ts @@ -1,9 +1,7 @@ import BaseModule from '../../BaseModule' import { isTimestampToday, delayToNextMoment, tsm, isNowIn } from '../../../library/luxon' import { useBiliStore } from '../../../stores/useBiliStore' -import { MainData } from '../../../library/bili-api/data' import BAPI from '../../../library/bili-api' -import _ from 'lodash' import { moduleStatus } from '../../../types/module' class ShareTask extends BaseModule { From 742235cd933bcd6c9c03d273a6cc93befb1651a4 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Wed, 13 Sep 2023 11:01:44 +0800 Subject: [PATCH 23/29] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=E4=BC=98=E5=8C=96=E5=92=8C=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=9D=BF=E5=9D=97=E4=B8=8D=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E7=9A=84Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stores/useUIStore.ts | 10 ++++++---- src/types/storage.d.ts | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/stores/useUIStore.ts b/src/stores/useUIStore.ts index e1a6db74..2ff6c9e8 100644 --- a/src/stores/useUIStore.ts +++ b/src/stores/useUIStore.ts @@ -2,7 +2,7 @@ import { defineStore } from 'pinia' import { reactive, computed, CSSProperties, watch } from 'vue' import Storage from '../library/storage' import _ from 'lodash' -import { IuiConfig } from '../types' +import { IuiConfig, menuIndex } from '../types' interface IbaseStyleValue { top: number @@ -16,10 +16,12 @@ export const useUIStore = defineStore('ui', () => { const uiConfig: IuiConfig = reactive(Storage.getUiConfig()) // 被激活的菜单项的名称,用于在 Header 里显示子标题 const activeMenuName = computed(() => { - const index2name: { [index: string]: string } = { + const index2name: { [index in menuIndex]: string } = { MainSiteTasks: '主站任务', LiveTasks: '直播任务', - OtherTasks: '其它任务' + OtherTasks: '其它任务', + EnhanceExperience: '体验优化', + RemoveElement: '移除元素' } return index2name[uiConfig.activeMenuIndex] }) @@ -64,7 +66,7 @@ export const useUIStore = defineStore('ui', () => { *设置被激活菜单项的名称,配合 el-menu 的 `@select` 使用 * @param index 被激活菜单项 */ - function setActiveMenuIndex(index: string) { + function setActiveMenuIndex(index: menuIndex) { uiConfig.activeMenuIndex = index } // 监听UI配置信息的变化,使用防抖降低油猴写配置信息频率 diff --git a/src/types/storage.d.ts b/src/types/storage.d.ts index 90b3a4dd..b0445d01 100644 --- a/src/types/storage.d.ts +++ b/src/types/storage.d.ts @@ -101,14 +101,16 @@ interface ImoduleConfig { } } +type menuIndex = 'MainSiteTasks' | 'LiveTasks' | 'OtherTasks' | 'EnhanceExperience' | 'RemoveElement' + interface IuiConfig { isCollapse: boolean isShowPanel: boolean - activeMenuIndex: string + activeMenuIndex: menuIndex } interface Icache { lastAliveHeartBeatTime: number } -export { ImoduleConfig, IuiConfig, Icache } +export { ImoduleConfig, IuiConfig, Icache, menuIndex } From 1eb2d98fd9f09cf31824d68ae9923f25cfbb7df7 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Wed, 13 Sep 2023 11:21:03 +0800 Subject: [PATCH 24/29] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E7=AD=89=E7=BB=86=E8=8A=82=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/components/PanelMain.vue | 5 +++-- src/library/mitt/index.ts | 1 + src/library/storage/{defaultValue.ts => defaultValues.ts} | 0 src/library/storage/index.ts | 2 +- src/stores/useBiliStore.ts | 7 +++---- src/stores/useModuleStore.ts | 2 +- src/types/cookies.d.ts | 6 ++++-- src/types/storage.d.ts | 7 ++++++- 9 files changed, 20 insertions(+), 11 deletions(-) rename src/library/storage/{defaultValue.ts => defaultValues.ts} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ea87213..a9c7da01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - 修复部分模块在特殊直播间不运行的Bug - 修复领取大会员权益模块在领取前一天会多次运行的Bug +- 修复体验优化和移除元素板块不显示标题的Bug ## 调整 diff --git a/src/components/PanelMain.vue b/src/components/PanelMain.vue index d826315d..c5b8599d 100644 --- a/src/components/PanelMain.vue +++ b/src/components/PanelMain.vue @@ -4,9 +4,10 @@ import LiveTasks from './LiveTasks.vue' import OtherTasks from './OtherTasks.vue' import EnhanceExperience from './EnhanceExperience.vue' import RemoveElement from './RemoveElement.vue' +import { defineComponent } from 'vue' // 注册对当前组件实例可用的组件 -export default { +export default defineComponent({ components: { MainSiteTasks, LiveTasks, @@ -14,7 +15,7 @@ export default { EnhanceExperience, RemoveElement } -} +}) From a13e19113dbf8079614003d4d6b366d74b386f43 Mon Sep 17 00:00:00 2001 From: andywang425 <13120989656@163.com> Date: Sun, 17 Sep 2023 20:27:18 +0800 Subject: [PATCH 29/29] =?UTF-8?q?=F0=9F=93=83=20docs:=20Update=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88e96bcd..54dabbee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # 更新日志 -## [7.1.2] - 2023-9-11 +## [7.1.2] - 2023-9-17 ### 新增 @@ -16,6 +16,7 @@ - 直播任务板块UI微调 - 粉丝勋章获取逻辑调整,现在可以获取完整的粉丝勋章列表(但可能会耗费很长时间) +- 粉丝勋章相关任务调整,将执行任务的粉丝勋章数量上调为199 ## [7.1.1] - 2023-9-5