Giter Club home page Giter Club logo

blive-message-listener's Introduction

blive-message-listener

npm

类型友好的 Bilibili 直播间弹幕监听库。

Features

  • 原始数据 转为更友好的格式输出
  • Node 环境与浏览器环境支持
  • 支持监听与获取原始消息

Install

npm i blive-message-listener

Usage

import { startListen, type MsgHandler } from 'blive-message-listener'
// 浏览器环境,从 '/browser' 导入 startListen
// import { startListen } from 'blive-message-listener/browser'

const handler: MsgHandler = {
  onIncomeDanmu: (msg) => {
    console.log(msg.id, msg.body)
  },
  onIncomeSuperChat: (msg) => {
    console.log(msg.id, msg.body)
  },
}

const instance = startListen(652581, handler)

instance.close()
  1. 需传入房间的长id。短id需转为长id才能接收到消息。(#19)
  2. 2023年7月后需登录后才可展示完整用户名,可参考下一节 Options 配置连接选项 (#29)

Options

你可以向 startListen 传入第三个参数 options 来手动配置连接选项。

interface MessageListenerOptions {
  /**
   * tiny-bilibili-ws 连接选项
   *
   * @see https://github.com/starknt/tiny-bilibili-ws
   */
  ws?: WSOptions | TCPOptions
}
startListen(652581, handler, {
  ws: {
    platform: 'web',
    uid: 541993,
    key: '<login_key>',
    buvid: '<login_buvid>',
  }
})

Handlers & Type Definitions

Common

const startListen: (roomId: number, handler: MsgHandler) => MessageListener

export interface MessageListener {
  /** 直播间房间号 */
  roomId: number
  /** 关闭连接 */
  close: () => void
  /** 刷新当前直播间热度 */
  getAttention: () => Promise<number>
}

export interface Message<T> {
  /** 消息id */
  id: string,
  /** 接收消息的时间,毫秒时间戳 */
  timestamp: number,
  /** 消息类型 */
  type: string,
  /** 消息内容 */
  body: T
  /** 原始消息内容 */
  raw: any
}

export interface User {
  /** 用户uid */
  uid: number
  /** 用户名 */
  uname: string
  /** 用户头像 */
  face?: string
  /** 用户牌子·*/
  badge?: {
    /** 是否点亮 */
    active: boolean
    /** 牌子名称 */
    name: string
    /** 牌子等级 */
    level: number
    /** 牌子颜色 */
    color: string
    /** 渐变色牌子,当用户长时间未消费,则会变为灰色,即 `#c0c0c0` */
    gradient?: [string, string, string]
    /** 主播信息 */
    anchor: {
      /** 主播uid */
      uid: number
      /** 主播用户名 */
      uname: string
      /** 主播房间号 */
      room_id: number
      /** 是否为本直播间 */
      is_same_room?: boolean
    }
  }
  /** 用户身份 */
  identity?: {
    /** 直播榜单排名 */
    rank: 0 | 1 | 2 | 3
    /** 大航海信息 */
    guard_level: GuardLevel
    /** 房管 */
    room_admin: boolean
  }
}

export enum GuardLevel {
  /** 无 */
  None = 0,
  /** 总督 */
  Zongdu = 1,
  /** 提督 */
  Tidu = 2,
  /** 舰长 */
  Jianzhang = 3,
}

Handler

Type definition can be also found in src/parser.

连接基础信息

Handler Description
onOpen 连接成功
onClose 连接关闭
onError 连接错误
onStartListen 开始监听消息
Type Definitions
Handler.onOpen

连接成功

export type Handler = {
  /** 连接成功 */
  onOpen: () => void,
}
Handler.onClose

连接关闭

export type Handler = {
  /** 连接关闭 */
  onClose: () => void,
}
Handler.onError

连接错误

export type Handler = {
  /** 连接错误 */
  onError: (e: Error) => void,
}
Handler.onStartListen

开始监听消息

export type Handler = {
  /** 开始监听消息 */
  onStartListen: () => void,
}

直播间基础信息

Handler Description
onLiveStart 直播开始消息
onLiveEnd 直播结束消息
onAttentionChange 直播间热度变化
onWatchedChange 累计看过人数变化
onLikedChange 累计点赞人数变化
onRankCountChange 高能用户人数变化
onUserAction 用户进入、关注、分享、点赞直播间
onRoomInfoChange 直播间信息修改
Type Definitions
handler.onLiveStart

直播开始消息

export type Handler = {
  /** 直播开始消息 */
  onLiveStart: (msg: Message<LiveStartMsg>) => void
}

type msgType = 'LIVE'

export interface LiveStartMsg {
  /** 开播平台 */
  live_platform: string
  /** 房间号 */
  room_id: number
}
handler.onLiveEnd

直播结束消息

export type Handler = {
  /** 直播结束消息 */
  onLiveEnd: (msg: Message<LiveEndMsg>) => void
}

type msgType = 'PREPARING'

export interface LiveEndMsg {
  /** 房间号 */
  room_id: number
}
handler.onAttentionChange

直播间热度变化

export type Handler = {
  /** 直播间热度变化 */
  onAttentionChange: (msg: Message<AttentionChangeMsg>) => void
}

type msgType = 'heartbeat'

export interface AttentionChangeMsg {
  /** 直播间热度 */
  attention: number
}
handler.onWatchedChange

累计看过人数变化

export type Handler = {
  /** 累计看过人数变化 */
  onWatchedChange: (msg: Message<WatchedChangeMsg>) => void
}

type msgType = 'WATCHED_CHANGE'

export interface WatchedChangeMsg {
  /** 累计入场人数 */
  num: number
  /** 累计入场人数,格式化输出 */
  text_small: string
}
handler.onLikedChange

累计点赞人数变化

export type Handler = {
  /** 累计点赞人数变化 */
  onLikedChange: (msg: Message<LikedChangeMsg>) => void
}

type msgType = 'LIKE_INFO_V3_UPDATE'

export interface LikedChangeMsg {
  /** 直播间点赞人数 */
  count: number
}
handler.onRankCountChange

高能用户人数变化

export type Handler = {
  /** 高能用户人数变化 */
  onRankCountChange: (msg: Message<RankCountChangeMsg>) => void
}

type msgType = 'ONLINE_RANK_COUNT'

export interface RankCountChangeMsg {
  /** 高能用户人数 */
  count: number
}
handler.onUserAction

用户进入、关注、分享、点赞直播间

  • 舰长进入直播间时,有几率会触发两次
  • 舰长进入直播间时,uname 超长可能会省略号截断
export type Handler = {
  /** 用户进入、关注、分享、点赞直播间 */
  onUserAction: (msg: Message<UserActionMsg>) => void
}

type msgType = 'INTERACT_WORD' | 'ENTRY_EFFECT' | 'LIKE_INFO_V3_CLICK'

type UserAction = 'enter' | 'follow' | 'share' | 'like' | 'unknown'

export interface UserActionMsg {
  user: User
  /** 事件类型 */
  action: UserAction
  /** 事件时间,毫秒时间戳 */
  timestamp: number
}
handler.onRoomInfoChange

直播间信息修改

export type Handler = {
  /** 直播间信息修改 */
  onRoomInfoChange: (msg: Message<RoomInfoChangeMsg>) => void
}

type msgType = 'ROOM_CHANGE'

export interface RoomInfoChangeMsg {
  /** 直播间标题 */
  title: string
  /** 一级分区id */
  parent_area_id: number
  /** 一级分区名 */
  parent_area_name: string
  /** 二级分区id */
  area_id: number
  /** 二级分区名 */
  area_name: string
}

弹幕相关

Handler Description
onIncomeDanmu 收到普通弹幕消息
onIncomeSuperChat 收到醒目留言
Type Definitions
handler.onIncomeDanmu

收到普通弹幕消息

export type Handler = {
  /** 收到普通弹幕消息 */
  onIncomeDanmu: (msg: Message<DanmuMsg>) => void
}

type msgType = 'DANMU_MSG'

export interface DanmuMsg {
  user: User
  /** 弹幕内容 */
  content: string
  /** 发送时间,毫秒时间戳 */
  timestamp: number
  /** 是否为天选抽奖弹幕 */
  lottery: boolean
  /** 表情弹幕内容 */
  emoticon?: {
    id: string
    height: number
    width: number
    url: string
  }
  /** 弹幕内小表情映射,key为表情文字,如"[妙]" */
  in_message_emoticon?: Record<string, {
    id: string
    emoticon_id: number
    height: number
    width: number
    url: string
    description: string
  }>
}
handler.onIncomeSuperChat

收到醒目留言

export type Handler = {
  /** 收到醒目留言 */
  onIncomeSuperChat: (msg: Message<SuperChatMsg>) => void
}

type msgType = 'SUPER_CHAT_MESSAGE'

export interface SuperChatMsg {
  /** 消息id */
  id: number
  /** 发送用户 */
  user: User
  /** 弹幕内容 */
  content: string
  /** 弹幕颜色 */
  content_color: string
  /** 价格,RMB */
  price: number
  /** 持续时间,秒 */
  time: number
}

礼物相关

Handler Description
onGift 收到礼物
onGuardBuy 舰长上舰消息
onRedPocketStart 红包抽奖开始
onRedPocketEnd 红包抽奖结果
onAnchorLotteryStart 主播天选时刻抽奖开启
onAnchorLotteryEnd 主播天选时刻抽奖结果
Type Definitions
handler.onGift

收到礼物

  • 礼物信息的用户牌子可见,但没有牌子对应主播的用户名及房间号,也无法判断 is_same_room 是否为本直播间。
export type Handler = {
  /** 收到礼物 */
  onGift: (msg: Message<GiftMsg>) => void
}

type msgType = 'SEND_GIFT'

export interface GiftMsg {
  user: User
  /** 礼物id */
  gift_id: number
  /** 礼物名称 */
  gift_name: string
  /** 礼物价格类型 */
  coin_type: 'silver' | 'gold'
  /** 礼物价格,除以1000为RMB */
  price: number
  /** 礼物数量 */
  amount: number
  /** 送礼指向主播信息,多人直播间可指定要送给的主播,单人直播间为空 */
  send_master?: {
    uid: number
    uname: string
    room_id: number
  }
  /** 礼物连击 */
  combo?: {
    /** 连击id */
    batch_id: string
    /** 当前连击数(礼物总数) */
    combo_num: number
    /** 连击礼物总价格,除以1000为RMB */
    total_price: number
  }
}
handler.onGuardBuy

舰长上舰消息

export type Handler = {
  /** 舰长上舰消息 */
  onGuardBuy: (msg: Message<GuardBuyMsg>) => void
}

type msgType = 'GUARD_BUY'

export interface GuardBuyMsg {
  user: User
  /** 礼物id */
  gift_id: number
  /** 礼物名称 */
  gift_name: string
  /** 大航海信息 */
  guard_level: GuardLevel
  /** 价格,RMB */
  price: number
  /** 等级生效时间 */
  start_time: number
  /** 等级过期时间 */
  end_time: number
}
handler.onRedPocketStart

红包抽奖开始

export type Handler = {
  /** 红包抽奖开始 */
  onRedPocketStart: (msg: Message<RedPocketStartMsg>) => void
}

type msgType = 'POPULARITY_RED_POCKET_START'

export interface RedPocketStartMsg {
  /** 红包抽奖id */
  id: number
  /** 红包发送用户 */
  user: User
  /** 开始时间,秒级时间戳 */
  start_time: number
  /** 结束时间,秒级时间戳 */
  end_time: number
  /** 持续时间,秒 */
  duration: number
  /** 口令弹幕内容 */
  danmu: string
  /** 红包奖品 */
  awards: RedPocketStartAward[]
  /** 奖品总价值,除以1000为RMB */
  total_price: number
  /** 剩余等待的红包数 */
  wait_num: number
}

interface RedPocketStartAward {
  /** 奖品id */
  gift_id: number
  /** 奖品名称 */
  gift_name: string
  /** 奖品图片 */
  gift_pic: string
  /** 奖品数量 */
  num: number
}
handler.onRedPocketEnd

红包抽奖结果

export type Handler = {
  /** 红包抽奖结果 */
  onRedPocketEnd: (msg: Message<RedPocketEndMsg>) => void
}

type msgType = 'POPULARITY_RED_POCKET_WINNER_LIST'

export interface RedPocketEndMsg {
  /** 红包抽奖id */
  id: number
  /** 中奖人数 */
  total_num: number
  /** 中奖用户列表 */
  winner: ({
    /** 用户uid */
    uid: number
    /** 用户昵称 */
    uname: string
    /** 奖品id */
    award_id: number
  } & RedPocketEndAward)[]
  /** 红包奖品列表 */
  awards: Record<string, RedPocketEndAward>
}

interface RedPocketEndAward {
  /** 奖品类型,待补充 */
  award_type: number
  /** 奖品名称 */
  award_name: string
  /** 奖品图片 */
  award_pic: string
  /** 奖品图片大图 */
  award_big_pic: string
  /** 奖品价值,除以1000为RMB */
  award_price: number
}
handler.onAnchorLotteryStart

主播天选时刻抽奖开启

export type Handler = {
  /** 主播天选时刻抽奖开启 */
  onAnchorLotteryStart: (msg: Message<AnchorLotteryStartMsg>) => 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

主播天选时刻抽奖结果

export type Handler = {
  /** 主播天选时刻抽奖结果 */
  onAnchorLotteryEnd: (msg: Message<AnchorLotteryEndMsg>) => 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
  })[]
}

房间管理相关

Handler Description
onRoomWarn 房间被超管警告、切断
onRoomSilent 房间开启、关闭全局禁言
onRoomAdminSet 房间设立、撤销房管
Type Definitions
handler.onRoomWarn

房间被超管警告、切断

export type Handler = {
  /** 房间被超管警告、切断 */
  onRoomWarn: (msg: Message<RoomWarnMsg>) => void
}

type msgType = 'WARNING'  'CUT_OFF'

export interface RoomWarnMsg {
  /** 处理类型 */
  type: 'warning' | 'cut'
  /** 处理原因 */
  msg: string
}
handler.onRoomSilent

房间开启、关闭全局禁言

export type Handler = {
  /** 房间开启、关闭全局禁言 */
  onRoomSilent: (msg: Message<RoomSilentMsg>) => void
}

type msgType = 'ROOM_SILENT_ON'  'ROOM_SILENT_OFF'

export interface RoomSilentMsg {
  /** 禁言类型(按用户等级、勋章等级、全员、关闭) */
  type: 'level' | 'medal' | 'member' | 'off'
  /** 禁言等级 */
  level: number
  /** 禁言结束时间,秒级时间戳,-1 为无限 */
  second: number
}
handler.onRoomAdminSet

房间设立、撤销房管

export type Handler = {
  /** 房间设立、撤销房管 */
  onRoomAdminSet: (msg: Message<RoomAdminSetMsg>) => void
}

type msgType = 'room_admin_entrance'  'ROOM_ADMIN_REVOKE'

export interface RoomAdminSetMsg {
  /** 类型(设立、撤销) */
  type: 'set' | 'revoke'
  /** 用户uid */
  uid: number
}

监听原始消息

export type Handler = {
  /** 原始消息 */
  raw: Record<'msg' | string, (msg: any) => void>
}

可在 raw 中监听任意原始消息。

example:

const handler: MsgHandler = {
  raw: {
    'msg': (msg) => {
      // 监听所有 cmd 消息
      console.log(msg)
    },
    'INTERACT_WORD': (msg) => {
      // 监听特定的 cmd
      console.log(msg)
    },
  }
}

startListen(652581, handler)

Credits

License

MIT

blive-message-listener's People

Contributors

ddiu8081 avatar nauxscript avatar starknt avatar tymon42 avatar widcardw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

blive-message-listener's Issues

Large amount of danmu freshes when the liver draws a lottery

当某位 UP 发起一次天选之人时,会有大量的抽奖弹幕,在一定程度上会挤掉文字性弹幕。此处我使用了白河愁的直播间(老白真的好喜欢抽奖)。

改进方案:可以通过弹幕消息中的 data.info[0][9] 字段初步判断是不是抽奖弹幕,当这个字段不是 0,则可能是抽奖弹幕,在 我的分析 中给出了初步的判断

image

上图中颜文字弹幕就是抽奖弹幕

Electron 和 Vue3开发打包的时候会出现报错

报错内容如下:

 error  in ./node_modules/blive-message-listener/dist/chunk-XFSH6FXD.mjs

Module parse failed: Unexpected token (159:29)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     timestamp: rawData[0][4],
|     lottery: rawData[0][9] !== 0,
>     emoticon: rawData[0][13]?.emoticon_unique ? {
|       id: rawData[0][13].emoticon_unique,
|       height: rawData[0][13].height,

 @ ./node_modules/blive-message-listener/dist/index.mjs 1:0-3:30 20:2-11

 error  in ./node_modules/tiny-bilibili-ws/dist/index.cjs

Module parse failed: Unexpected token (20:45)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| function brotliDecompress(buf, options) {
|   return new Promise((resolve, reject) => {
>     node_zlib.brotliDecompress(buf, options ?? {}, handler(resolve, reject));
|   });
| }

 @ ./node_modules/blive-message-listener/dist/index.mjs 6:0-47 19:19-30

自我排查应该是webpack没有能解析mjs和cjs,不太清楚如何解决
环境:

"electron": "23.1.0",
"vue": "^3.0.0",
"blive-message-listener": "^0.4.4",

add `/browser` test file

Clear and concise description of the problem

Suggested solution

Add test files for main/browser package.

Alternative

No response

Additional context

No response

Validations

监听弹幕时获取用户头像

Clear and concise description of the problem

如题

Suggested solution

如题

Alternative

No response

Additional context

No response

Validations

emoji表情

既然你要类型友好,就不如把emoji加上,不是指别的表情
比如[花],[爱]的这种从表情面板选择的

我现在的做法如下,字段是在info[0][15]里,height,width也有,但我写死20了,反正也是20
你可以定义个更友好的字段或几个字段,让用户自己这样拼也行

我的实现
//解emoji表情的地址
const extra = JSON.parse(msg.raw.info[0][15].extra)
if(extra.emots){
    // 替换emoji表情
    console.log(extra.emots)
    msg.body.contentHtml = msg.body.content
    for(let key in extra.emots){
        let reg = new RegExp(key.replace('[','\\[').replace(']','\\]'),'gi')
        msg.body.contentHtml = msg.body.contentHtml.replaceAll(reg, `<img style="width: 20px; height: 20px;" src="${extra.emots[key].url}" />`)
    }
}

是否无法支持短房号?

发现有些房间的房间号是比较短的,房号只有 3、4 位(好像是排行榜靠前的或者一些比较火的主播会有这样的房间号),通过这种短的房号无法抓到弹幕;不知道是什么原因呢?有点疑惑;有没有一些解决方法?

app.d.ts 写的有问题,编译后的 index.d.ts 会报错

因为 app.d.ts 里有个 export enum GuardLevel,现在会编译到 index.d.ts 里变成 enum GuardLevel,然后引入这个包后就会报错:

// file: index.ts
import { startListen, MsgHandler } from 'blive-message-listener'
// ... codes ...
$ tsc
node_modules/blive-message-listener/dist/index.d.ts:41:1 - error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.

编译的时候 d.ts 和 ts 的处理是不同的,其实按你这个项目的用途来看,app 不应该是 d.ts,而是一个正常的 ts 文件,因为按照官方的解释 microsoft/TypeScript#5112 (comment) ,d.ts 文件应该是构建系统的输入,不应该参与到输出,而你 app 文件里全是用于输出的,所以应该是 ts 文件,那样就可以编译成正常的 declare enum GuardLevel

electron preload 中 exposeInMainWorld 使用该库报错

安装

yarn add blive-message-listener

引入错误:

Error: require() of ES Module C:\Users\why00\Documents\project\2someone-app\node_modules\blive-message-listener\dist\index.js from C:\Users\why00\Documents\project\2someone-app\dist\preload\index.js not supported.
Instead change the require of C:\Users\why00\Documents\project\2someone-app\node_modules\blive-message-listener\dist\index.js in C:\Users\why00\Documents\project\2someone-app\dist\preload\index.js to a dynamic import() which is available in all CommonJS modules.
    at __node_internal_captureLargerStackTrace (node:internal/errors:465:5)
    at new NodeError (node:internal/errors:372:5)
    at Module._extensions..js (node:internal/modules/cjs/loader:1148:19)
    at Module.load (node:internal/modules/cjs/loader:988:32)
    at Module._load (node:internal/modules/cjs/loader:829:12)
    at c._load (node:electron/js2c/asar_bundle:5:13343)
    at i._load (node:electron/js2c/renderer_init:33:356)
    at Module.require (node:internal/modules/cjs/loader:1012:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (C:\Users\why00\Documents\project\2someone-app\dist\preload\index.js:3:37)
    at Object.<anonymous> (C:\Users\why00\Documents\project\2someone-app\dist\preload\index.js:13:3)
    at Module._compile (node:internal/modules/cjs/loader:1120:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1175:10)
    at Module.load (node:internal/modules/cjs/loader:988:32)
    at Module._load (node:internal/modules/cjs/loader:829:12)
    at c._load (node:electron/js2c/asar_bundle:5:13343)
    at i._load (node:electron/js2c/renderer_init:33:356)
    at Object.<anonymous> (node:electron/js2c/renderer_init:73:2296)
    at ./lib/renderer/init.ts (node:electron/js2c/renderer_init:73:2423)
    at __webpack_require__ (node:electron/js2c/renderer_init:1:170)
    at node:electron/js2c/renderer_init:1:1242
    at ___electron_webpack_init__ (node:electron/js2c/renderer_init:1:1310)
    at node:electron/js2c/renderer_init:141:194
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at NativeModule.compileForPublicLoader (node:internal/bootstrap/loaders:252:10)
    at loadNativeModule (node:internal/modules/cjs/helpers:49:9)
    at Module._load (node:internal/modules/cjs/loader:811:15)
    at c._load (node:electron/js2c/asar_bundle:5:13343)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

使用预加载脚本报错:

源代码:

// preload/index.ts
import { startListen } from 'blive-message-listener'
contextBridge.exposeInMainWorld(
  'biliApi',
  {
    startListen,
  },
)

// ****.vue
 window.biliApi.startListen(inputRoomId, handler)
console.log(typeof window.biliApi.startListen)     // undefine

报错:

TypeError: Cannot read properties of undefined (reading 'startListen')
    at DanmuTest.vue:31:5
    at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
    at hook.__weh.hook.__weh (runtime-core.esm-bundler.js:2684:29)
    at flushPostFlushCbs (runtime-core.esm-bundler.js:341:32)
    at render2 (runtime-core.esm-bundler.js:6234:9)
    at mount (runtime-core.esm-bundler.js:4424:25)
    at app.mount (runtime-dom.esm-bundler.js:1606:23)
    at main.ts:4:16

大佬能从报错看出问题吗?如果需要看源码请直接回复。

开始监听后立刻就关闭了

Describe the bug

const bilive = require('blive-message-listener');

bilive.startListen(5050, {
  onOpen() {
    console.log('open');
  },
  onClose() {
    console.log('close');
    process.exit()
  },
  onIncomeDanmu: (msg) => {
    console.log(msg.id, msg.body);
  },
});

运行后立刻就关闭了。

Reproduction

https://stackblitz.com/edit/stackblitz-starters-d4vbxi?file=index.js

System Info

System:
    OS: macOS 14.1.2
    CPU: (10) arm64 Apple M1 Pro
    Memory: 280.48 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node
    npm: 10.2.3 - ~/.nvm/versions/node/v20.10.0/bin/npm
    pnpm: 8.7.6 - /opt/homebrew/bin/pnpm
    bun: 1.0.0 - /opt/homebrew/bin/bun
  Browsers:
    Chrome: 123.0.6312.87

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guide.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Connected to server but no Danmu received.

Describe the bug

Chinese is OK for me, I would like chatting in Chinese.

I wrote a very simple program, and it goes like this:

onIncomeDanmu: (msg) => {
...
},
onOpen: () => {
console.log('connected')
},
onStartListen: () => {
console.log('start listen')
},
onError: (err: any) => {
console.log(`error: ${err}`)

In the past few days, every time this code is executed, it can output connected and start listen correctly but there is no Danmu msg received.

I don't know what happened, but I noticed that there is a similar issue with the library that this project depends on here.

Reproduction

https://gist.github.com/tymon42/ca150b1f93a82c1be0f1bffb0586f716

System Info

System:
    OS: macOS 13.4
    CPU: (8) arm64 Apple M2
    Memory: 79.36 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 19.7.0 - ~/.nvm/versions/node/v19.7.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v19.7.0/bin/yarn
    npm: 9.5.0 - ~/.nvm/versions/node/v19.7.0/bin/npm
    pnpm: 8.5.1 - ~/.nvm/versions/node/v19.7.0/bin/pnpm
  Browsers:
    Edge: 115.0.1901.188
    Safari: 16.5

Used Package Manager

yarn

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guide.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

是否有字段或方法可以获取直播间信息?

目前只在 onRoomInfoChange 回调中看到有和直播间相关的信息,是否有其他字段或方法可以在 onStartListen 后获取直播间的相关信息呢?如 直播间名称、主播名称、上下播时间之类的。

十分感谢!

`parent_area_name` 和 `area_name` 是否是应该为 `string` 类型呢?

文档中的 handler.onRoomInfoChange 类型定义:

export type Handler = {
  /** 直播间信息修改 */
  onRoomInfoChange: (msg: Message<RoomInfoChangeMsg>) => void
}

type msgType = 'ROOM_CHANGE'

export interface RoomInfoChangeMsg {
  /** 直播间标题 */
  title: number
  /** 一级分区id */
  parent_area_id: number
  /** 一级分区名 */
  parent_area_name: number
  /** 二级分区id */
  area_id: number
  /** 二级分区名 */
  area_name: number
}

parent_area_namearea_name 是否是应该为 string 类型呢?

过滤重复的舰长进入直播间消息

目前,onUserAction 事件融合了 INTERACT_WORDENTRY_EFFECT 两类消息。

  • INTERACT_WORD 包括一般用户与大航海用户的进入消息,但会有遗漏
  • ENTRY_EFFECT 应该仅包含大航海用户的,不过昵称不全,超长时会截断

这样航海用户进入直播间时,很容易会发送两次。计划开启一个稍短的定时器来融合两条消息。

调用close方法时,会触发两次onClose

Describe the bug

代码如下:

import { startListen } from "blive-message-listener";

const listener = startListen(652581, {
  onClose: () => console.log("与直播间的连接断开了"),
});

setTimeout(() => listener.close(), 2000);

console.log会被执行两次:

与直播间的连接断开了
与直播间的连接断开了

感觉像是tiny-bilibili-ws的问题,但不确定到底是什么原因

Reproduction

none

System Info

node v16.13.1

Used Package Manager

npm

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guide.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.

Browser environment support

Currently it should only be available in the Node.js environment.

Later it will need to be tested and supported in the browser environment.

浏览器中使用的问题

安装方式

pnpm i blive-message-listener

pnpm dev 报错:

X [ERROR] No matching export in "browser-external:node:net" for import "connect"

    node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:1:9:
      1 │ import { connect } from 'node:net';
        ╵          ~~~~~~~

X [ERROR] No matching export in "browser-external:node:zlib" for import "brotliDecompress"

    node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:5:9:
      5 │ import { brotliDecompress as brotliDecompress$1, inflate as inflate$1 } from 'node:zlib';
        ╵          ~~~~~~~~~~~~~~~~

X [ERROR] No matching export in "browser-external:node:zlib" for import "inflate"

    node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:5:49:
      5 │ import { brotliDecompress as brotliDecompress$1, inflate as inflate$1 } from 'node:zlib';
        ╵                                                  ~~~~~~~

22:54:27 [vite] error while updating dependencies:
Error: Build failed with 3 errors:
node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:1:9: ERROR: No matching export in "browser-external:node:net" for import "connect"
node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:5:9: ERROR: No matching export in "browser-external:node:zlib" for import "brotliDecompress"
node_modules/.pnpm/[email protected]/node_modules/tiny-bilibili-ws/dist/index.mjs:5:49: ERROR: No matching export in "browser-external:node:zlib" for import "inflate"
    at failureErrorWithLog (C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:1624:15)
    at C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:1266:28
    at runOnEndCallbacks (C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:1046:63)
    at buildResponseToResult (C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:1264:7)
    at C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:1377:14
    at C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:678:9
    at handleIncomingPacket (C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:775:9)
    at Socket.readFromStdout (C:\Users\why00\Documents\project\bubblebox-web\node_modules\.pnpm\[email protected]\node_modules\esbuild\lib\main.js:644:7)
    at Socket.emit (node:events:526:28)
    at addChunk (node:internal/streams/readable:315:12)

貌似和这个issues 是同一个原因。
我暂时还不知道有什么解决方法。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.