Skip to content
Merged

7.3.5 #649

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

## [Unreleased]

## [7.3.5] - 2026-8-26

### 修复

- 【亲密喂养】修复无法正确判断直播间是否支持亲密喂养活动的问题,改为使用直播画面上方右侧是否有亲密喂养活动组件(挂件)作为判定依据

## [7.3.4] - 2026-8-25

### 新增

- 新增【亲密喂养】模块,自动完成亲密喂养活动(B站超能粉丝节的养猫活动)的选猫,每日签到,喂猫粮和撸猫。支持黑白名单。
- 新增【亲密喂养】模块,自动完成亲密喂养活动(B站超能粉丝节的养猫活动)的选猫,每日签到,喂猫粮和撸猫。支持黑白名单
- 优化【屏蔽挂机检测】模块,使其尽早运行;增加页面焦点状态属性的修改

### 调整
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bilibili-live-tasks-helper",
"private": true,
"version": "7.3.4",
"version": "7.3.5",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
9 changes: 9 additions & 0 deletions src/library/bili-api/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ interface BapiMethods {
supported_drms?: string,
web_location?: string,
) => Promise<Live.GetRoomPlayInfo>
getWidgetBannerList: (
room_id: number,
page_source?: number,
platform?: string,
position?: number,
position_flag?: number,
source?: string,
web_location?: string,
) => Promise<Live.GetWidgetBannerList>
Q3FansS1MiaoZaiHome: (
room_id: number,
ruid: number,
Expand Down
52 changes: 51 additions & 1 deletion src/library/bili-api/data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -1361,6 +1361,56 @@ declare namespace LiveData {
}
}

namespace GetWidgetBannerList {
interface Data {
/** 键为组件 id 的字符串形式,没有任何组件时可能为 null */
list: Record<string, Banner> | 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
Expand Down
24 changes: 24 additions & 0 deletions src/library/bili-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
},
/**
* 获取超能粉丝节——粉丝福利——亲密喂养(养猫活动)主页数据
*/
Expand Down
7 changes: 7 additions & 0 deletions src/library/bili-api/response.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 58 additions & 7 deletions src/modules/dailyTasks/liveTasks/medalTasks/miaoZaiTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 时无限循环) */
Expand Down Expand Up @@ -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<boolean> {
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
}
}

/**
* 获取养猫活动主页数据
*
Expand Down Expand Up @@ -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} 无法获取养猫活动数据,跳过该直播间`)
Expand All @@ -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} 还没有选择喵崽,先选择一只`)
Expand Down