diff --git a/README.md b/README.md index 32b041f..4f0d3ee 100644 --- a/README.md +++ b/README.md @@ -452,6 +452,8 @@ export interface SuperChatMsg { | onGuardBuy | 舰长上舰消息 | | onRedPocketStart | 红包抽奖开始 | | onRedPocketEnd | 红包抽奖结果 | +| onAnchorLotteryStart | 主播天选时刻抽奖开启 | +| onAnchorLotteryEnd | 主播天选时刻抽奖结果 |
Type Definitions @@ -617,6 +619,106 @@ interface RedPocketEndAward { award_price: number } ``` + +##### handler.onAnchorLotteryStart + +主播天选时刻抽奖开启 + +```ts +export type Handler = { + /** 主播天选时刻抽奖开启 */ + onAnchorLotteryStart: (msg: Message) => void +} + +type msgType = 'ANCHOR_LOT_START' + +export interface AnchorLotteryStartMsg { + /** 天选抽奖id */ + id: number + /** 开始时间,秒级时间戳 */ + start_time: number + /** 持续时间,秒 */ + duration: number + /** 天选奖品信息 */ + award: { + /** 奖品图片 */ + image: string + /** 奖品名称 */ + name: string + /** 奖品数量 */ + num: number + /** 是否为虚拟礼物奖品 */ + virtual: boolean + /** 虚拟奖品价值描述,实物奖品为空 */ + price_text: string + } + /** 抽奖要求 */ + require: { + /** 口令弹幕内容,无需弹幕为空字符串 */ + danmu: string + /** 需送主播礼物,无需送礼为空 */ + gift: { + /** 礼物id */ + id: string + /** 礼物名称 */ + name: string + /** 礼物数量 */ + num: number + /** 单个礼物价值,除以1000为RMB */ + price: number + } | null + /** 抽奖参与人群要求,无要求为空 */ + user: { + /** 参与人群限制(关注/粉丝勋章/大航海) */ + type: 'follow' | 'medal' | 'guard' + /** 参与人群限制等级,如粉丝勋章等级 */ + value: number + /** 参与人群限制描述 */ + text: string + } | null + } +} +``` + +##### handler.onAnchorLotteryEnd + +主播天选时刻抽奖结果 + +```ts +export type Handler = { + /** 主播天选时刻抽奖结果 */ + onAnchorLotteryEnd: (msg: Message) => void +} + +type msgType = 'ANCHOR_LOT_AWARD' + +export interface AnchorLotteryEndMsg { + /** 天选抽奖id */ + id: number + /** 天选奖品信息 */ + award: { + /** 奖品图片 */ + image: string + /** 奖品名称 */ + name: string + /** 是否为虚拟礼物奖品 */ + virtual: boolean + } + /** 中奖用户列表 */ + winner: ({ + /** 用户uid */ + uid: number + /** 用户昵称 */ + uname: string + /** 用户头像 */ + face: number + /** 用户粉丝勋章等级 */ + level: number + /** 中奖数量 */ + num: number + })[] +} +```
#### 房间管理相关 diff --git a/src/listener/index.ts b/src/listener/index.ts index 7bb5ebf..910a3ee 100644 --- a/src/listener/index.ts +++ b/src/listener/index.ts @@ -2,6 +2,8 @@ import { HEARTBEAT, type AttentionChangeMsgHandler, LIVE, type LiveStartMsgHandler, PREPARING, type LiveStopMsgHandler, + ANCHOR_LOT_AWARD, type AnchorLotteryEndMsgHandler, + ANCHOR_LOT_START, type AnchorLotteryStartMsgHandler, DANMU_MSG, type DanmuMsgHandler, GUARD_BUY, type GuardBuyHandler, INTERACT_WORD, ENTRY_EFFECT, LIKE_INFO_V3_CLICK, type UserActionMsgHandler, @@ -34,6 +36,8 @@ export type MsgHandler = Partial< & AttentionChangeMsgHandler & LiveStartMsgHandler & LiveStopMsgHandler + & AnchorLotteryEndMsgHandler + & AnchorLotteryStartMsgHandler & DanmuMsgHandler & GuardBuyHandler & UserActionMsgHandler @@ -109,6 +113,26 @@ export const listenAll = (instance: KeepLiveTCP | KeepLiveWS, roomId: number, ha }) } + // ANCHOR_LOT_AWARD + if (handler[ANCHOR_LOT_AWARD.handlerName] || rawHandlerNames.has(ANCHOR_LOT_AWARD.eventName)) { + rawHandlerNames.delete(ANCHOR_LOT_AWARD.eventName) + instance.on(ANCHOR_LOT_AWARD.eventName as any, (data: WSMessage) => { + isHandleRaw && rawHandler[ANCHOR_LOT_AWARD.eventName]?.(data.data) + const parsedData = ANCHOR_LOT_AWARD.parser(data.data, roomId) + handler[ANCHOR_LOT_AWARD.handlerName]?.(normalizeDanmu(ANCHOR_LOT_AWARD.eventName, parsedData, data.data)) + }) + } + + // ANCHOR_LOT_START + if (handler[ANCHOR_LOT_START.handlerName] || rawHandlerNames.has(ANCHOR_LOT_START.eventName)) { + rawHandlerNames.delete(ANCHOR_LOT_START.eventName) + instance.on(ANCHOR_LOT_START.eventName as any, (data: WSMessage) => { + isHandleRaw && rawHandler[ANCHOR_LOT_START.eventName]?.(data.data) + const parsedData = ANCHOR_LOT_START.parser(data.data, roomId) + handler[ANCHOR_LOT_START.handlerName]?.(normalizeDanmu(ANCHOR_LOT_START.eventName, parsedData, data.data)) + }) + } + // DANMU_MSG if (handler[DANMU_MSG.handlerName] || rawHandlerNames.has(DANMU_MSG.eventName)) { rawHandlerNames.delete(DANMU_MSG.eventName) diff --git a/src/parser/ANCHOR_LOT_AWARD.ts b/src/parser/ANCHOR_LOT_AWARD.ts new file mode 100644 index 0000000..0c655ce --- /dev/null +++ b/src/parser/ANCHOR_LOT_AWARD.ts @@ -0,0 +1,59 @@ +import type { Message } from '../types/app' + +export interface AnchorLotteryEndMsg { + /** 天选抽奖id */ + id: number + /** 天选奖品信息 */ + award: { + /** 奖品图片 */ + image: string + /** 奖品名称 */ + name: string + /** 是否为虚拟礼物奖品 */ + virtual: boolean + } + /** 中奖用户列表 */ + winner: ({ + /** 用户uid */ + uid: number + /** 用户昵称 */ + uname: string + /** 用户头像 */ + face: number + /** 用户粉丝勋章等级 */ + level: number + /** 中奖数量 */ + num: number + })[] +} + +const parser = (data: any, roomId: number): AnchorLotteryEndMsg => { + const rawData = data.data + + return { + id: rawData.id, + award: { + image: rawData.award_image, + name: rawData.award_name, + virtual: rawData.award_type === 1, + }, + winner: rawData.award_users.map((user: any) => ({ + uid: user.uid, + uname: user.uname, + face: user.face, + level: user.level, + num: user.num, + })), + } +} + +export const ANCHOR_LOT_AWARD = { + parser, + eventName: 'ANCHOR_LOT_AWARD' as const, + handlerName: 'onAnchorLotteryEnd' as const, +} + +export type Handler = { + /** 主播天选时刻抽奖结果 */ + onAnchorLotteryEnd: (msg: Message) => void +} diff --git a/src/parser/ANCHOR_LOT_START.ts b/src/parser/ANCHOR_LOT_START.ts new file mode 100644 index 0000000..165665b --- /dev/null +++ b/src/parser/ANCHOR_LOT_START.ts @@ -0,0 +1,90 @@ +import type { Message } from '../types/app' + +export interface AnchorLotteryStartMsg { + /** 天选抽奖id */ + id: number + /** 开始时间,秒级时间戳 */ + start_time: number + /** 持续时间,秒 */ + duration: number + /** 天选奖品信息 */ + award: { + /** 奖品图片 */ + image: string + /** 奖品名称 */ + name: string + /** 奖品数量 */ + num: number + /** 是否为虚拟礼物奖品 */ + virtual: boolean + /** 虚拟奖品价值描述,实物奖品为空 */ + price_text: string + } + /** 抽奖要求 */ + require: { + /** 口令弹幕内容,无需弹幕为空字符串 */ + danmu: string + /** 需送主播礼物,无需送礼为空 */ + gift: { + /** 礼物id */ + id: string + /** 礼物名称 */ + name: string + /** 礼物数量 */ + num: number + /** 单个礼物价值,除以1000为RMB */ + price: number + } | null + /** 抽奖参与人群要求,无要求为空 */ + user: { + /** 参与人群限制(关注/粉丝勋章/大航海) */ + type: 'follow' | 'medal' | 'guard' + /** 参与人群限制等级,如粉丝勋章等级 */ + value: number + /** 参与人群限制描述 */ + text: string + } | null + } +} + +const parser = (data: any, roomId: number): AnchorLotteryStartMsg => { + const rawData = data.data + + return { + id: rawData.id, + start_time: rawData.current_time, + duration: rawData.max_time, + award: { + image: rawData.award_image, + name: rawData.award_name, + num: rawData.award_num, + virtual: rawData.award_type === 1, + price_text: rawData.award_price_text || '', + }, + require: { + danmu: rawData.danmu || '', + gift: rawData.gift_id ? { + id: rawData.gift_id, + name: rawData.gift_name, + num: rawData.gift_num, + price: rawData.gift_price, + } : null, + user: rawData.require_type ? { + type: (['follow', 'medal', 'guard'] as const)[rawData.require_type - 1], + value: rawData.require_value, + text: rawData.require_text, + } : null, + }, + } +} + +export const ANCHOR_LOT_START = { + parser, + eventName: 'ANCHOR_LOT_START' as const, + handlerName: 'onAnchorLotteryStart' as const, +} + +export type Handler = { + /** 主播天选时刻抽奖开启 */ + onAnchorLotteryStart: (msg: Message) => void +} diff --git a/src/parser/index.ts b/src/parser/index.ts index e34ae8c..0d4379a 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -1,6 +1,8 @@ export { HEARTBEAT, type Handler as AttentionChangeMsgHandler, type AttentionChangeMsg } from './HEARTBEAT' export { LIVE, type Handler as LiveStartMsgHandler, type LiveStartMsg } from './LIVE' export { PREPARING, type Handler as LiveStopMsgHandler, type LiveEndMsg } from './PREPARING' +export { ANCHOR_LOT_AWARD, type Handler as AnchorLotteryEndMsgHandler, type AnchorLotteryEndMsg } from './ANCHOR_LOT_AWARD' +export { ANCHOR_LOT_START, type Handler as AnchorLotteryStartMsgHandler, type AnchorLotteryStartMsg } from './ANCHOR_LOT_START' export { DANMU_MSG, type Handler as DanmuMsgHandler, type DanmuMsg } from './DANMU_MSG' export { GUARD_BUY, type Handler as GuardBuyHandler, type GuardBuyMsg } from './GUARD_BUY' export { INTERACT_WORD, ENTRY_EFFECT, LIKE_INFO_V3_CLICK, type Handler as UserActionMsgHandler, type UserActionMsg } from './INTERACT_WORD_ENTRY_EFFECT'