// ==UserScript==
// @name bilibili直播间显示更多信息
// @description bilibili直播间显示开播时间,直播时长,粉丝数,人气,收益,在线人数,封面,其他关注直播,pk等信息
// @version 3.20
// @author killall
// @match https://live.bilibili.com/*
// @icon https://www.bilibili.com/favicon.ico
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
// @license MIT
// @namespace https://greasyfork.org/users/1060750
// ==/UserScript==
; (function () {
const $ = jQuery.noConflict(true);
let Config = {
livetime: {
enable: true, // 显示直播开始时间,持续时间
},
fans: {
enable: true, // 显示粉丝,人气,收益
maxWidth: 450, // 显示最大宽度(显示有问题才需要考虑改)
},
rank: {
//(目前b站官方已经显示在线人数了 2024-05-05)
//(现在改成显示在聊天框下面 2024-12-13)
enable: true, // 显示高能榜(同接)
},
cover: {
enable: true, // 显示直播封面
location: 'afterbegin', // 封面显示位置(afterbegin,beforeend)
},
pk: {
enable: true, // 显示pk相关信息
},
otherLive: {
enable: true, // 显示其他关注的直播
showTime: true, // 是否在头像下面显示直播时长
location: 'right', // 显示位置(left,right)
opacity: 1.0, // 透明度
maxHeight: 550, // 最大显示高度(px)
imgSize: 40, // 头像大小
},
}
async function main() {
initSucceed = await G.init()
if (!initSucceed) return
console.log(`G.init done`)
initSucceed = await Dao.init()
console.log(`Dao.init done`)
tasklist = []
tasklist.push(Dao.run())
Config.livetime.enable && tasklist.push(LiveTimeModule.run())
Config.fans.enable && tasklist.push(FansModule.run())
Config.rank.enable && tasklist.push(RankModule.run())
Config.cover.enable && tasklist.push(CoverModule.run())
Config.otherLive.enable && tasklist.push(otherLiveModule.run())
await ut.sleep(200) //等数据初始化完成
await Promise.all(tasklist)
}
let G = {
roomId_short: 0, // 直播房间号(short,从当前url获取)
roomId: 0, // 直播房间号
uid: 0, // 主播uid
async init() {
this.roomId_short = api.getRoomID()
if (!this.roomId_short) return false
liveInfo = await api.getLiveInfo(this.roomId_short)
this.uid = liveInfo.data.uid
this.roomId = liveInfo.data.room_id
console.log(`roomId(short_id): ${this.roomId_short} `)
console.log(`roomId: ${this.roomId} `)
console.log(`uid: ${this.uid}`)
return true
},
}
let Dao = {
liveInfo: null,
liveStartTimeStamp: null, // 开播时间时间戳
income: 0, // 高能榜收入 初始化从api统计 之后从hook_wrapper统计收入
// rankCount: 0, // 非零在线人数 从api获取
guardCount: 0, // 舰长数
rank1: 0, // hook_wrapper获取
rank2: 0, // hook_wrapper获取
aliveList: null, // 其他关注直播
inpk: false,
pk: {
pkInfo: null,
roomId: null,
uid: null,
uname: null,
liveInfo: null,
rankCount: 0,
income: 0,
guardCount: 0,
},
async init() {
this.liveInfo = await api.getLiveInfo(G.roomId)
// console.log('liveInfo', this.liveInfo)
this.liveStartTimeStamp = await api.getLiveTimeStamp(G.roomId)
// console.log('liveStartTimeStamp', this.liveStartTimeStamp)
Config.otherLive.enable && (this.aliveList = await api.getAliveList())
Config.rank.enable && ut.hook_wrapper()
this.income = (await api.getGongxian(G.roomId, G.uid)) / 10
},
updateData() {
const update_liveInfo = async () => {
this.liveInfo = await api.getLiveInfo(G.roomId)
}
// const update_income = async () => {
// this.income = await api.getIncome(G.roomId, G.uid)
// }
const update_rankCount = async () => {
// this.rankCount = await api.getOnlinePeople(G.roomId, G.uid)
this.guardCount = await api.getGuardCount(G.roomId, G.uid)
}
const update_aliveList = async () => {
this.aliveList = await api.getAliveList()
}
const update_pkInfo = async () => {
const pkInfo = await api.getPkInfo(G.roomId)
if (!pkInfo.data.pk_id) {
this.inpk = false
this.pk.pkInfo = null
this.pk.roomId = null
this.pk.uid = null
this.pk.liveInfo = null
this.pk.rankCount = 0
this.pk.income = 0
this.pk.guardCount = 0
return
}
newpk = !this.inpk
this.inpk = true
this.pk.pkInfo =
pkInfo.data.init_info.room_id == G.roomId ? pkInfo.data.match_info : pkInfo.data.init_info
this.pk.roomId = this.pk.pkInfo.room_id
this.pk.uid = this.pk.pkInfo.uid
this.pk.uname = this.pk.pkInfo.uname
this.pk.liveInfo = await api.getLiveInfo(this.pk.roomId)
this.pk.rankCount = await api.getOnlinePeople(this.pk.roomId, this.pk.uid)
this.pk.income = (await api.getGongxian(this.pk.roomId, this.pk.uid)) / 10
this.pk.guardCount = await api.getGuardCount(this.pk.roomId, this.pk.uid)
if (newpk) {
console.log(`pk开始(${this.pk.roomId}) ${this.pk.uname} : ${this.pk.liveInfo.data.title}`)
}
}
Config.fans.enable && update_liveInfo(), setInterval(update_liveInfo, 1000)
Config.rank.enable && update_rankCount(), setInterval(update_rankCount, 1000)
// Config.fans.enable && update_income(), setInterval(update_income, 10000)
Config.otherLive.enable && update_aliveList(), setInterval(update_aliveList, 60000)
Config.pk.enable && update_pkInfo(), setInterval(update_pkInfo, 5000)
},
async run() {
// 定时更新数据
this.updateData()
},
}
// 直播时间,开播时长
let LiveTimeModule = {
html: `
<div class="live-skin-normal-a-text livetimeContainer" >
<div id="liveStartTime">0000-00-00 00:00:00</div>
<div id="liveDuration">0小时0分钟0秒</div>
</div> `,
css: `
.livetimeContainer {
display: flex;
margin-left: 10px;
user-select: text;
flex-direction: column;
opacity: 1;
}
`,
dom: {
liveStartTime: null, // 开播时间
liveDuration: null, // 直播持续时间
},
initialized: false,
prefix: ['', ''],
// perfix: ['开播时间:', '直播时长:'],
async initUI() {
ut.addCSS(this.css)
let container = await ut.waitForElement('#head-info-vm > div > div > div.upper-row > div.left-ctnr.left-header-area')
if (container) {
$(container).append(this.html);
this.dom.liveStartTime = $('#liveStartTime')
this.dom.liveDuration = $('#liveDuration')
this.initialized = true
}
this.dom.liveStartTime.text(`${this.prefix[0]}${Dao.liveInfo.data.live_time}`)
},
updateUI() {
if (Dao.liveInfo.data.live_status == 0) {
this.dom.liveStartTime.text(`当前状态:未开播`)
return
}
if (Dao.liveInfo.data.live_status == 2) {
this.dom.liveStartTime.text(`当前状态:轮播中`)
// liveStatus = liveInfo.data.live_status (0:未开播 1:直播中 2:轮播中)`);
return
}
let timeText = ut.timeFrom(Dao.liveStartTimeStamp, '{h}小时 {mm}分钟 {ss}秒')
this.dom.liveDuration.text(`${this.prefix[1]}${timeText}`)
},
async run() {
await this.initUI()
this.updateUI(), setInterval(() => this.updateUI(), 1000)
},
}
// 粉丝,人气,收益
let FansModule = {
html: `
<div id="fans" class="right-text live-skin-normal-a-text v-middle preserve-space"
title="收益的计算方法为先初始化为高能榜的和(这里不计入小于20)的,之后有礼物、sc、上舰等事件加入统计"
>
`,
css: `
#fans{
display: flex;
opacity: 1;
margin-bottom: 2px;
padding-left: 15px;
justify-content: flex-end;
}
.preserve-space{
white-space: pre;
}
.fansContainer{
display: flex;
flex-direction: row;
flex-wrap: wrap-reverse;
align-content: center;
justify-content: right;
align-items: center;
max-width: ${Config.fans.maxWidth}px;
}
`,
dom: {
fans: null,
},
initialized: false,
prefix: ['粉丝:', '人气:', '收益:'],
async initUI() {
ut.addCSS(this.css)
let container = await ut.waitForElement('#head-info-vm > div > div > div.upper-row > div.right-ctnr')
// document.querySelector("#head-info-vm > div > div > div.upper-row > div.right-ctnr")
// console.log("container", container);
if (container) {
$(container).append(this.html)
$(container).addClass('fansContainer')
this.dom.fans = $('#fans')
this.initialized = true
}
},
updateUI() {
let fensi = `${this.prefix[0]}${Dao.liveInfo.data.attention}`
let renqi = `${this.prefix[1]}${Dao.liveInfo.data.online}`
let gongxian = `${this.prefix[2]}${Dao.income.toFixed(1)}`
if (Dao.inpk) {
fensi += `/ ${Dao.pk.liveInfo.data.attention}`
renqi += `/ ${Dao.pk.liveInfo.data.online}`
gongxian += `/ ${Dao.pk.income.toFixed(1)}`
}
$('#fans').text(`${fensi} ${renqi} ${gongxian}`)
// console.log("`${fensi} ${renqi} ${gongxian}`", `${fensi} ${renqi} ${gongxian}`);
// this.dom.fans.text(`${fensi} ${renqi} ${gongxian}`)
},
async run() {
await this.initUI()
this.updateUI(), setInterval(() => this.updateUI(), 1000)
},
}
let RankModule = {
html: `
<div
style="width: 50%; position: relative; color: #666666"
id="rank_gurad_div"
title="同接/高能(0/0) = 0.00%">
<div id="rank_num" style="width: 100%; margin-bottom: 5px">同接:0</div>
<div id="guard_num">舰长:0</div>
</div>
`,
dom: {
rank_guard_card: null,
rank: null,
guard: null,
},
initialized: false,
prefix: ['同接:', '舰长:'],
dirtyfix: false,
async initUI() {
let container = await ut.waitForElement("#control-panel-ctnr-box")
// container.insertAdjacentHTML('beforeend', this.html)
$(container).append(this.html)
if (container) {
this.dom.rank_guard_card = $('#rank_gurad_div')
this.dom.rank = this.dom.rank_guard_card.children().first();
this.dom.guard = this.dom.rank_guard_card.children().last();
this.initialized = true
}
},
updateUI() {
this.dom.rank.text(this.prefix[0] + (!Dao.inpk ? `${Dao.rank1}/${Dao.rank2}` : `${Dao.rank1}/${Dao.pk.rankCount}`))
this.dom.guard.text(this.prefix[1] + (!Dao.inpk ? `${Dao.guardCount}` : `${Dao.guardCount}/${Dao.pk.guardCount}`))
this.dom.rank_guard_card.attr('title', `同接/高能(${Dao.rank1}/${Dao.rank2}) = ${(Dao.rank1 * 100 / Dao.rank2).toFixed(2)}%`);
},
async run() {
await this.initUI()
this.updateUI(), setInterval(() => this.updateUI(), 1000)
},
}
// 直播封面
let CoverModule = {
html: `
<div data-v-03a54292 class="announcement-cntr" >
<div data-v-03a54292 class="header">
<p data-v-03a54292 style="color:#ff6699">直播封面
<span id="coverTitle" data-v-03a54292>2020-9-24 点击刷新</span>
</p>
</div>
<div data-v-03a54292 class="content">
<img alt="直播封面" id="cover" style="width: 100%; height: auto;">
</div>
</div>
`,
dom: {
coverTitle: null,
cover: null,
},
initialized: false,
async initUI() {
let CoverContainer = await ut.waitForElement('#sections-vm > div.section-block.f-clear.z-section-blocks > div.right-container')
if (CoverContainer) {
// CoverContainer.insertAdjacentHTML("beforeend", this.html)
// CoverContainer.insertAdjacentHTML(Config.cover.location, this.html)
Config.cover.location == "beforeend" ?
$(CoverContainer).append(this.html) :
$(CoverContainer).prepend(this.html)
this.dom.cover = $('#cover')
this.dom.coverTitle = $('#coverTitle')
this.dom.cover.on('click', () => this.updateUI());
this.initialized = true
}
},
updateUI() {
const timestr = ut.formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss')
this.dom.coverTitle.text(`${timestr}更新 点击刷新`)
this.dom.cover.src = Dao.liveInfo.data.user_cover
this.dom.cover.attr('src', Dao.liveInfo.data.user_cover)
},
async run() {
await this.initUI()
this.updateUI(), setInterval(() => this.updateUI(), 60 * 1000)
},
}
// 其他关注直播
let otherLiveModule = {
html: {
roomCardContainer: `
<div id = "roomCardContainer"></div>
`,
roomCard: `
<div class="roomCard">
<a href="{room.link}" target="_blank">
<img class="roomAvatar"
src="{room.face}"
alt="{room.title}"
title="{room.uname} : {room.title}">
</a>
{roomText}
</div> `,
pkRoomCard: `
<div class="roomCard">
<a href="{room.link}" target="_blank">
<img id="pkAvatar"
src="{room.face}"
alt="{room.title}"
title="{room.uname} : {room.title}">
</a>
{roomText}
</div> `,
},
css: `
#roomCardContainer {
position: fixed;
z-index: 9999;
display: flex;
flex-direction: column;
flex-wrap: ${Config.otherLive.location == 'right' ? 'wrap-reverse' : 'wrap'};
opacity:${Config.otherLive.opacity};
align-content: center;
justify-content: flex-end;
align-items: center;
max-height: ${Config.otherLive.maxHeight}px;
${Config.otherLive.location}: 5px;
top: calc(50% + 32px);
transform: translateY(-50%);
}
#roomCardContainer .roomCard{
padding-bottom: 5px;
padding-left: 5px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
align-content: center
}
#roomCardContainer .roomCard .roomText{
/*
border-radius: 20%;
border: 1px solid #0095ff;
*/
min-width: -webkit-fill-available;
text-align: center;
background-color: rgba(255, 255, 255, 0.5);
}
#roomCardContainer .roomCard .roomAvatar {
/* 头像O */
border: 2px solid #0095ff;
border-radius: 50%;
opacity: 1;
width: ${Config.otherLive.imgSize}px;
height: ${Config.otherLive.imgSize}px;
}
#roomCardContainer .roomCard #pkAvatar {
/* 头像O */
border: 2px solid #ff0000;
border-radius: 50%;
opacity: 1;
width: ${Config.otherLive.imgSize}px;
height: ${Config.otherLive.imgSize}px;
}
`,
dom: {
aliveList: null,
},
initialized: false,
async initUI() {
ut.addCSS(this.css)
$('body').append(this.html.roomCardContainer);
this.dom.aliveList = $('#roomCardContainer')
this.initialized = true
},
updateUI() {
this.dom.aliveList = $('#roomCardContainer')
this.dom.aliveList.html('');
let cnt = 0
if (Dao.inpk) {
let pk_roomLiveTime = ut.timeFrom(Dao.pk.liveInfo.data.live_time, '{h}h{mm}m')
let pk_roomText = Config.otherLive.showTime
? `<div class="roomText"> ${pk_roomLiveTime} </div> `
: ''
const pkRoomCard = this.html.pkRoomCard
.replace('{room.link}', `https://live.bilibili.com/${Dao.pk.roomId}`)
.replace(/{room.title}/g, Dao.pk.liveInfo.data.title)
.replace('{room.face}', Dao.pk.pkInfo.face)
.replace('{room.uname}', Dao.pk.uname)
.replace('{roomText}', pk_roomText)
this.dom.aliveList.append(pkRoomCard)
cnt++
}
for (const [index, room] of Dao.aliveList.entries()) {
if (room.room_id == G.roomId) continue
let roomLiveTime = ut.formatSeconds(room.live_time, '{h}h{mm}m')
let roomText = Config.otherLive.showTime
? `<div class="roomText"> ${roomLiveTime} </div> `
: ''
const roomCard = this.html.roomCard
.replace('{room.link}', room.link)
.replace('{room.face}', room.face)
.replace(/{room.title}/g, room.title)
.replace('{room.uname}', room.uname)
.replace('{roomText}', roomText)
this.dom.aliveList.append(roomCard)
if (++cnt >= 24) break
}
},
async run() {
await this.initUI()
this.updateUI(), setInterval(() => this.updateUI(), 5000)
},
}
const api = {
// ============================== api ==============================
// liveInfo = get https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${roomId}
// 开播时间 = liveInfo.data.live_time
// 主播uid = liveInfo.data.uid
// 真roomId = liveInfo.data.room_id
// liveStatus = liveInfo.data.live_status (0:未开播 1:直播中 2:轮播中)`);
// 粉丝数 = liveInfo.data.attention
// 人气 = liveInfo.data.online
// 分区 = liveInfo.data.area_name
// 父分区 = liveInfo.data.parent_area_name
// pk信息 `https://api.live.bilibili.com/xlive/general-interface/v1/battle/getInfoById?room_id=${roomId}&pk_version=6`;
// getOnlineGoldRank = https://api.live.bilibili.com/xlive/general-interface/v1/rank/getOnlineGoldRank?ruid=${uid}&roomId=${roomId}&page=1&pageSize=1
// 在线人数 = getOnlineGoldRank.data.onlineNum
// room_init = `https://api.live.bilibili.com/room/v1/Room/room_init?id=${roomId}`;
// 开播时间戳 = room_init.data.live_time
// alive = `https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList?page=1`;
// 其他关注直播间 = alive.data.rooms
// =================================================================
// 获取直播间id
getRoomID() {
try {
const urlpathname = window.location.pathname
// const W = typeof unsafeWindow === 'undefined' ? window : unsafeWindow
// const urlpathname = W.location.pathname
console.log(`urlpathname: ${urlpathname} `)
return urlpathname.match(/\d{3,}/)[0]
} catch (error) {
console.log(`getRoomID error`)
return null
}
},
// 获取直播开始时间时间戳
async getLiveTimeStamp(roomId) {
// https://api.live.bilibili.com/room/v1/Room/room_init?id=60989
const url = `https://api.live.bilibili.com/room/v1/Room/room_init?id=${roomId}`
return (await ut.fetchURL(url)).data.live_time
},
// 获取直播信息数据
async getLiveInfo(roomId) {
const url = `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${roomId}`
return await ut.fetchURL(url)
},
// 获取在线人数
async getOnlinePeople(roomId, uid) {
// 计算规则 https://ngabbs.com/read.php?tid=29562585
// https://api.live.bilibili.com/xlive/general-interface/v1/rank/getOnlineGoldRank?ruid=2978046&roomId=60989&page=1&pageSize=1
const url = `https://api.live.bilibili.com/xlive/general-interface/v1/rank/getOnlineGoldRank?ruid=${uid}&roomId=${roomId}&page=1&pageSize=1`
return (await ut.fetchURL(url)).data.onlineNum
},
// 获取高能榜贡献值
async getGongxian(roomId, uid) {
let res = 0
let page = 1
while (true) {
// 大概每页需要100ms
const url = `https://api.live.bilibili.com/xlive/general-interface/v1/rank/getOnlineGoldRank?ruid=${uid}&roomId=${roomId}&page=${page}&pageSize=50`
const onlineRankItem = (await ut.fetchURL(url)).data.OnlineRankItem
page++
const len = onlineRankItem.length
// len > 0 && (res += onlineRankItem.reduce((total, item) => total + item.score, 0))
// 小于20的不算在内
if (len > 0) {
res += onlineRankItem.reduce((total, item) => total + (item.score <= 20 ? 0 : item.score), 0)
if (onlineRankItem[0].score < 20)
break
}
if (len < 50) break
}
return res
},
// 获取舰长数量
async getGuardCount(roomId, uid) {
const url = `https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=${roomId}&page=1&ruid=${uid}&page_size=0`
return (await ut.fetchURL(url)).data.info.num
},
// 获取关注直播列表
async getAliveList() {
let roomlist = []
const url = `https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList?page=1`
let res = (await ut.fetchURL(url, true)).data
roomlist = [].concat(res.rooms)
if (res.count > 10) {
for (let page = 2; page <= Math.ceil(res.count / 10); page++) {
const nextPageUrl = `https://api.live.bilibili.com/xlive/web-ucenter/v1/xfetter/GetWebList?page=${page}`
const nextPageRes = (await ut.fetchURL(nextPageUrl, true)).data
roomlist = roomlist.concat(nextPageRes.rooms)
}
}
roomlist.sort((a, b) => a.live_time - b.live_time)
return roomlist
},
// 获取pk信息
async getPkInfo(roomId) {
const url = `https://api.live.bilibili.com/xlive/general-interface/v1/battle/getInfoById?room_id=${roomId}&pk_version=6`
return await ut.fetchURL(url)
},
}
const ut = {
async fetchURL(url, useCookie = false) {
try {
const response = await fetch(url, {
credentials: useCookie ? 'include' : 'same-origin',
})
if (!response.ok) throw new Error(`请求${url}错误 response.status : ${response.status}`)
const data = await response.json()
return data
} catch (error) {
throw new Error(`请求${url}错误 error.message: ${error.message}`)
}
},
// 添加CSS
addCSS(css) {
let myStyle = document.createElement('style')
myStyle.textContent = css
let doc = document.head || document.documentElement
doc.appendChild(myStyle)
},
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
},
timeFrom(startTime, format, Ltrip0 = true) {
if (typeof startTime === 'number') {
startTime = startTime > 9999999999
? startTime
: startTime * 1000
}
const elapsedSeconds = Math.floor((new Date() - new Date(startTime)) / 1000)
return ut.formatSeconds(elapsedSeconds, format, Ltrip0)
},
formatSeconds(seconds, format, Ltrip0 = true) {
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
const remainingSeconds = seconds % 60
Ltrip0 && hours == 0 && (format = format.replace(/.*\{mm\}/, '{mm}').replace(/.*\{m\}/, '{m}'))
let formattedTime = format
.replace('{hh}', hours.toString().padStart(2, '0'))
.replace('{mm}', minutes.toString().padStart(2, '0'))
.replace('{ss}', remainingSeconds.toString().padStart(2, '0'))
.replace('{h}', hours)
.replace('{m}', minutes)
.replace('{s}', remainingSeconds)
return formattedTime
},
getFirstNumber(text) {
// 使用正则表达式匹配第一个数字
const match = text.match(/\d+/)
// 如果找到匹配的数字,则返回第一个匹配结果
if (match) {
return parseInt(match[0], 10) // 将匹配的字符串转换为整数并返回
}
// 如果未找到数字,则返回 null 或其他指定的默认值
return 0
},
formatDate(date, format) {
const year = date.getFullYear()
const month = date.getMonth() + 1 // 月份是从 0 开始的
const day = date.getDate()
const hours = date.getHours()
const minutes = date.getMinutes()
const seconds = date.getSeconds()
const formattedDate = format
.replace('YYYY', year)
.replace('YY', year % 100)
.replace('MM', (month < 10 ? '0' : '') + month)
.replace('DD', (day < 10 ? '0' : '') + day)
.replace('hh', (hours < 10 ? '0' : '') + hours)
.replace('mm', (minutes < 10 ? '0' : '') + minutes)
.replace('ss', (seconds < 10 ? '0' : '') + seconds)
return formattedDate
},
waitForElement(selector, interval = 200, timeout = 500000) {
// console.log("waitForElement selector", selector);
return new Promise((resolve) => {
const checkExist = setInterval(() => {
// const element = document.querySelector(selector)
// if (element) {
const element = $(selector)
if (element.length) {
// console.log("find element", element);
clearInterval(checkExist)
clearTimeout(timeoutTimer)
resolve(element)
}
}, interval)
const timeoutTimer = setTimeout(() => {
clearInterval(checkExist)
resolve(null)
}, timeout)
})
},
toggleShow(dom, display) {
dom.style.display = dom.style.display == 'none' ? display : 'none'
},
changeOpacity(dom, dif) {
let currentOpacity = dom.style.opacity === '' ? 1 : parseFloat(dom.style.opacity)
dom.style.opacity = Math.max(0, Math.min(parseFloat(currentOpacity) + dif, 1))
console.log('dom.style.opacity', dom.style.opacity)
},
hook_wrapper() {
const cb_map = {
ONLINE_RANK_COUNT: function (obj) {
Dao.rank1 = obj.data.count;
Dao.rank2 = obj.data.online_count;
},
GUARD_BUY: function (obj) {
// console.log("GUARD_BUY\n", obj);
const d = obj.data
console.log(`GUARD_BUY: ${d.username} 开通 ${d.gift_name} (¥${d.price / 1000})`)
Dao.income += d.price / 1000 / 2
// console.log("Dao.income += ", d.price / 1000);
},
SUPER_CHAT_MESSAGE: function (obj) {
const d = obj.data
console.log(`SUPER_CHAT_MESSAGE: (¥${d.price}) ${d.uinfo.base.name}: ${d.message}`)
Dao.income += d.price / 2
// console.log("Dao.income += ", d.price);
},
COMBO_SEND: function (obj) {
const d = obj.data
console.log(`COMBO_SEND: ${d.uname} ${d.action} ${d.combo_num}个 $(gift_name} (共¥${d.combo_total_coin / 1000})`)
// Dao.income += d.combo_total_coin / 1000 / 2
// return obj.data.coin_type === 'gold' ? (obj.data.total_coin / 1000).toFixed(2) : '0.00';
// console.log("Dao.income += ", d.combo_total_coin / 1000);
},
SEND_GIFT: function (obj) {
// console.log("SEND_GIFT:", obj);
const d = obj.data
const price = d.coin_type == 'gold' ? d.total_coin / 1000 : 0
console.log(`SEND_GIFT: ${d.uname} ${d.action} ${d.num}个 ${d.giftName} (共¥${d.total_coin / 1000})`)
Dao.income += price / 2
// console.log("Dao.income += ", price);
},
}
const cmdTracker = new Map();
Array.prototype.push = new Proxy(Array.prototype.push, {
apply(target, thisArg, argArray) {
try {
if (argArray && argArray.length > 0) {
for (let i = 0; i < argArray.length; i++) {
if (argArray[i] && argArray[i].cmd) {
!cmdTracker.has(argArray[i].cmd) && cmdTracker.set(argArray[i].cmd, argArray[i])
if (cb_map[argArray[i].cmd]) {
cb_map[argArray[i].cmd](argArray[i])
}
} else {
break
}
}
}
} catch (e) {
console.error(e)
}
return Reflect.apply(target, thisArg, argArray)
},
})
// this.mapKey('0', () => { console.log(cmdTracker); })
},
mapKey(key, func) {
document.addEventListener('keydown', function (event) {
if (event.key === key) {
func()
}
})
},
}
// await Utils.sleep(3000)
// if (W.location.pathname != '/p/html/live-web-mng/index.html') main()
$(document).ready(function () {
console.log("ready document.URL:", document.URL);
if (/^https?:\/\/live\.bilibili\.com\/(blanc\/)?\d+\??.*/.test(document.URL)) {
main()
}
// if (/^\/\d+$/.test(window.location.pathname))
// main()
});
})()