diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b13558..071daacd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,17 @@ ## [Unreleased] +## [7.3.5] - 2026-8-26 + +### 修复 + +- 【亲密喂养】修复无法正确判断直播间是否支持亲密喂养活动的问题,改为使用直播画面上方右侧是否有亲密喂养活动组件(挂件)作为判定依据 + ## [7.3.4] - 2026-8-25 ### 新增 -- 新增【亲密喂养】模块,自动完成亲密喂养活动(B站超能粉丝节的养猫活动)的选猫,每日签到,喂猫粮和撸猫。支持黑白名单。 +- 新增【亲密喂养】模块,自动完成亲密喂养活动(B站超能粉丝节的养猫活动)的选猫,每日签到,喂猫粮和撸猫。支持黑白名单 - 优化【屏蔽挂机检测】模块,使其尽早运行;增加页面焦点状态属性的修改 ### 调整 diff --git a/package-lock.json b/package-lock.json index 0c3857f1..0f4d35bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bilibili-live-tasks-helper", - "version": "7.3.4", + "version": "7.3.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bilibili-live-tasks-helper", - "version": "7.3.4", + "version": "7.3.5", "dependencies": { "ajax-hook": "^3.0.3", "crypto-js": "^4.2.0", diff --git a/package.json b/package.json index 0813b2f4..6c662d0e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bilibili-live-tasks-helper", "private": true, - "version": "7.3.4", + "version": "7.3.5", "type": "module", "scripts": { "dev": "vite", diff --git a/src/library/bili-api/api.d.ts b/src/library/bili-api/api.d.ts index 91579b25..5221f2e2 100644 --- a/src/library/bili-api/api.d.ts +++ b/src/library/bili-api/api.d.ts @@ -57,6 +57,15 @@ interface BapiMethods { supported_drms?: string, web_location?: string, ) => Promise + getWidgetBannerList: ( + room_id: number, + page_source?: number, + platform?: string, + position?: number, + position_flag?: number, + source?: string, + web_location?: string, + ) => Promise Q3FansS1MiaoZaiHome: ( room_id: number, ruid: number, diff --git a/src/library/bili-api/data.d.ts b/src/library/bili-api/data.d.ts index 7af12d58..44d30efd 100644 --- a/src/library/bili-api/data.d.ts +++ b/src/library/bili-api/data.d.ts @@ -123,7 +123,7 @@ declare namespace LiveData { light_source: number free_intimacy: number reach_free_intimacy_limit: boolean - intimacy_journey_info: IntimacyJourneyInfo + intimacy_journey_info: IntimacyJourneyInfo | null } interface IntimacyJourneyInfo { @@ -1361,6 +1361,56 @@ declare namespace LiveData { } } + namespace GetWidgetBannerList { + interface Data { + /** 键为组件 id 的字符串形式,没有任何组件时可能为 null */ + list: Record | null + room_id: number + /** 主播 uid */ + ruid: number + /** 毫秒级时间戳 */ + timestamp: number + } + + interface Banner { + id: number + title: string + cover: string + tip_text: string + tip_text_color: string + tip_bottom_color: string + jump_url: string + url: string + stay_time: number + type: number + sub_key: string + /** JSON 字符串,内容随 type 变化,无附加数据时为空字符串 */ + sub_data: string + site: number + band_id: number + web_cover: string + pc_link_conf: PcLinkConf + position: number + cover_pre: string + cover_horizontal: string + cover_vertical: string + horizon_show: number + target_url: string + schema_url: string + url_type: number + /** 秒级时间戳 */ + biz_time: number + not_merge_tab: number + } + + interface PcLinkConf { + cover: string + title: string + title_text: string + cover_w: string + } + } + namespace Q3FansS1MiaoZai { interface HomeData { current_time: number diff --git a/src/library/bili-api/index.ts b/src/library/bili-api/index.ts index 67fe7c81..898be528 100644 --- a/src/library/bili-api/index.ts +++ b/src/library/bili-api/index.ts @@ -155,6 +155,30 @@ const BAPI: BapiMethods = { }), ) }, + /** + * 获取直播间画面上方右侧的活动组件(挂件)列表 + */ + getWidgetBannerList: ( + room_id, + page_source = 1, + platform = 'pc', + position = 0, + position_flag = 0, + source = 'web', + web_location = '444.8', + ) => { + const bili_jct = useBiliStore().cookies!.bili_jct + return request.live.get('/xlive/play-interface/widgetService/GetWidgetBannerList', { + csrf: bili_jct, + page_source, + platform, + position, + position_flag, + room_id, + source, + web_location, + }) + }, /** * 获取超能粉丝节——粉丝福利——亲密喂养(养猫活动)主页数据 */ diff --git a/src/library/bili-api/response.d.ts b/src/library/bili-api/response.d.ts index 6bfddb47..7ab36c76 100644 --- a/src/library/bili-api/response.d.ts +++ b/src/library/bili-api/response.d.ts @@ -55,6 +55,13 @@ declare namespace Live { data: LiveData.GetRoomPlayInfo.Data } + interface GetWidgetBannerList { + code: number + message: string + ttl: number + data: LiveData.GetWidgetBannerList.Data + } + interface Q3FansS1MiaoZaiHome { code: number message: string diff --git a/src/modules/dailyTasks/liveTasks/medalTasks/miaoZaiTask.ts b/src/modules/dailyTasks/liveTasks/medalTasks/miaoZaiTask.ts index 2841bd89..4c7cc245 100644 --- a/src/modules/dailyTasks/liveTasks/medalTasks/miaoZaiTask.ts +++ b/src/modules/dailyTasks/liveTasks/medalTasks/miaoZaiTask.ts @@ -18,12 +18,16 @@ class MiaoZaiTask extends MedalModule { private static readonly ACTIVITY_END_TIME = 1789315199 // 2026-09-13 23:59:59 /** 活动进行中的 activity_status */ private static readonly ACTIVITY_STATUS_ONGOING = 1 + /** 亲密喂养挂件的组件 id */ + private static readonly MIAO_ZAI_WIDGET_ID = 3310 + /** 亲密喂养挂件的标题,组件 id 变化时作为兜底判断依据 */ + private static readonly MIAO_ZAI_WIDGET_TITLE = '亲密喂养' /** 签到任务的 task_key */ private static readonly SIGN_IN_TASK_KEY = 'signin' /** 任务已完成的 task_status */ private static readonly TASK_STATUS_DONE = 1 /** 连续多少次撸猫没有获得成长值就视为今日撸猫任务已完成 */ - private static readonly PET_CAT_ZERO_GROWTH_LIMIT = 5 + private static readonly PET_CAT_ZERO_GROWTH_LIMIT = 6 /** 单个直播间最多喂猫次数(兜底,避免猫粮数量异常时无限循环) */ private static readonly FEED_CAT_MAX_TIMES = 40 /** 单个直播间最多撸猫次数(兜底,避免 growth_delta 一直大于 0 时无限循环) */ @@ -64,6 +68,51 @@ class MiaoZaiTask extends MedalModule { return result } + /** + * 判断直播间是否支持亲密喂养活动 + * + * 依据直播间画面上方右侧的活动组件(挂件)列表里有没有亲密喂养挂件 + * + * @param medal 粉丝勋章 + * @param logMessage 直播间描述信息,用于日志 + * @returns 支持返回 true,不支持返回 false;请求失败时无法判断,返回 true 交由后续流程处理 + */ + private async isMiaoZaiSupported( + medal: LiveData.FansMedalPanel.List, + logMessage: string, + ): Promise { + const room_id = medal.room_info.room_id + + try { + const response = await BAPI.live.getWidgetBannerList(room_id) + this.logger.log(`BAPI.live.getWidgetBannerList(${room_id}) response`, response) + + if (response.code !== 0) { + this.logger.error(`BAPI.live.getWidgetBannerList(${room_id}) 失败`, response.message) + this.logger.warn( + `${logMessage} 无法判断该直播间是否支持亲密喂养活动,仍然尝试参与,后续任务流程可能会失败`, + ) + return true + } + + const widget = Object.values(response.data.list ?? {}).find( + (banner) => + banner.id === MiaoZaiTask.MIAO_ZAI_WIDGET_ID || + banner.title.includes(MiaoZaiTask.MIAO_ZAI_WIDGET_TITLE), + ) + + if (!widget) return false + + return true + } catch (error) { + this.logger.error(`BAPI.live.getWidgetBannerList(${room_id}) 出错`, error) + this.logger.warn( + `${logMessage} 无法判断该直播间是否支持亲密喂养活动,仍然尝试参与,后续任务流程可能会失败`, + ) + return true + } + } + /** * 获取养猫活动主页数据 * @@ -306,6 +355,14 @@ class MiaoZaiTask extends MedalModule { const medal_name = medal.medal.medal_name const logMessage = `粉丝勋章【${medal_name}】(主播【${nick_name}】,UID:${ruid},直播间:${room_id})` + if (!(await this.isMiaoZaiSupported(medal, logMessage))) { + this.logger.warn(`${logMessage} 不支持亲密喂养活动,跳过该直播间`) + // 不支持养猫活动,视为完成 + return 'completed' + } + + await sleep(MiaoZaiTask.ACTION_DYNAMIC_LONG_INTERVAL) + let home = await this.fetchHome(medal) if (!home) { this.logger.error(`${logMessage} 无法获取养猫活动数据,跳过该直播间`) @@ -319,12 +376,6 @@ class MiaoZaiTask extends MedalModule { return 'activityInvalid' } - if (!home.can_intimacy_journey) { - this.logger.warn(`${logMessage} 不支持亲密喂养活动,跳过该直播间`) - // 不支持养猫活动,视为完成 - return 'completed' - } - // 还没选猫,先选一只 if (!home.cat_selected) { this.logger.log(`${logMessage} 还没有选择喵崽,先选择一只`)