• Stars
    star
    143
  • Rank 257,007 (Top 6 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 2 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Bilibili live danmu listener with type. 类型友好的 Bilibili 直播间弹幕监听库。

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