// ==UserScript==
// @name 哔哩哔哩直播间舰长列表新增减少检测
// @version 1.0.4
// @description 看看是哪个小宝贝过期了2333
// @author Sonic853
// @namespace https://blog.853lab.com
// @include https://live.bilibili.com/*
// @run-at document-end
// @license MIT License
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_getResourceText
// @grant unsafeWindow
// ==/UserScript==
//
// 律师函收到之日,即是我死期到来之时。
// 学写代码学到现在也不过是一枚棋子,随用随弃。
// :)
//
// https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=15667&page=1&ruid=1968333&page_size=29
(function () {
'use strict';
const DEV_Log = Boolean(localStorage.getItem("Dev-853"));
const localItem = "Lab8A";
const NAME = "舰长检测";
const Console_log = function (text) {
let d = new Date().toLocaleTimeString();
console.log("[" + NAME + "][" + d + "]: " + text);
};
const Console_Devlog = function (text) {
let d = new Date().toLocaleTimeString();
DEV_Log && (console.log("[" + NAME + "][" + d + "]: " + text));
};
const Console_error = function (text) {
let d = new Date().toLocaleTimeString();
console.error("[" + NAME + "][" + d + "]: " + text);
};
let dateFormat = function (fmt, date) {
let ret;
const opt = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
if (typeof GM_xmlhttpRequest === 'undefined' && typeof GM_registerMenuCommand === 'undefined' && typeof GM_setValue === 'undefined' && typeof GM_getValue === 'undefined' && typeof GM_addStyle === 'undefined') {
Console_error("GM is no Ready.");
} else {
Console_log("GM is Ready.");
};
let BLab8A = class {
constructor() {
this.data = this.load();
}
load() {
Console_log("正在加载数据");
let newj = "{\"Roomid\":\"15667\",\"ruid\":\"1968333\",\"GList\":[],\"Lost\":[],\"New\":[],\"Check_date\":\"1997-07-22\",\"auto\":false,\"first_use\":true,\"HL\":[],\"History\":{}}";
if (typeof GM_getValue !== 'undefined') {
let gdata = JSON.parse(GM_getValue(localItem, newj));
return gdata;
} else {
let ldata = JSON.parse(localStorage.getItem(localItem) === null ? newj : localStorage.getItem(localItem));
return ldata;
}
};
save(d) {
Console_log("正在保存数据");
d === undefined ? (d = this.data) : (this.data = d);
typeof GM_getValue != 'undefined' ? GM_setValue(localItem, JSON.stringify(d)) : localStorage.setItem(localItem, JSON.stringify(d));
return this;
};
};
let bLab8A = new BLab8A();
let window = unsafeWindow;
!DEV_Log && GM_addStyle(`#Bili8-UI{position:fixed;left:0;bottom:0;z-index:9999;background-color:white;border:1px solid black;width:400px;height:300px;}#Bili8-UI .Close{position:absolute;top:-25px;height:25px;right:0;}#Bili8-UI .State{position:absolute;top:2px;height:20px;line-height:20px;left:2px;right:2px;}#Bili8-UI .MainList{position:absolute;top:22px;bottom:44px;left:2px;right:2px;border:1px solid black;overflow-y:auto;}#Bili8-UI .ListNew{position:absolute;width:calc(30% - 3px);top:0;bottom:0;left:0;right:calc(70% - 3px);resize:none;}#Bili8-UI .ListNow{position:absolute;top:0;bottom:0;width:40%;left:30%;resize:none;}#Bili8-UI .ListLost{position:absolute;width:calc(30% - 3px);top:0;bottom:0;left:calc(70% - 3px);right:0;resize:none;}#Bili8-UI .MainBottom{position:absolute;bottom:2px;left:2px;right:2px;height:40px;}#Bili8-UI .MainBottom .MBtn{position:absolute;display:block;height:20px;padding:0;box-sizing:border-box;}#Bili8-UI .MainBottom .MBRID{top:20px;left:0;width:100px;}#Bili8-UI .MainBottom .MBTAuto{top:20px;left:100px;width:50px;line-height:20px;}#Bili8-UI .MainBottom .MBAuto{top:20px;left:150px;width:20px;}#Bili8-UI .MainBottom .MBSaveSetting{top:20px;left:170px;}#Bili8-UI .MainBottom .LoadList{bottom:0;right:0;height:28px;width:70px;}#Bili8-UI .MainBottom .MBTNew{top:0;left:0;}#Bili8-UI .MainBottom .MBTLost{top:0;right:0;}`);
let HTTPsend = function (url, method, Type, successHandler, errorHandler) {
Console_Devlog(url);
if (typeof GM_xmlhttpRequest != 'undefined') {
GM_xmlhttpRequest({
method: method,
url: url,
responseType: Type,
onerror: function (response) {
Console_Devlog(response.status);
errorHandler && errorHandler(response.status);
},
onload: function (response) {
let status;
if (response.readyState == 4) { // `DONE`
status = response.status;
if (status == 200) {
Console_Devlog(response.response);
successHandler && successHandler(response.response);
} else {
Console_Devlog(status);
errorHandler && errorHandler(status);
}
}
},
});
} else {
let xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.withCredentials = true;
xhr.responseType = Type;
xhr.onreadystatechange = function () {
let status;
if (xhr.readyState == 4) { // `DONE`
status = xhr.status;
if (status == 200) {
Console_log(xhr.response);
successHandler && successHandler(xhr.response);
} else {
Console_log(status);
errorHandler && errorHandler(status);
}
}
};
xhr.send();
}
};
let JSON_parse = function (data) {
let rdata;
try {
rdata = JSON.parse(data);
} catch (error) {
Console_Devlog("JSON已解析,直接跳过");
rdata = result;
}
return rdata;
}
let GLC = class {
constructor() {
this.List = new Array();
this.old_List = bLab8A.data.GList;
this.page = this.now = 1;
this.first_use = bLab8A.data.first_use;
this.cdate = dateFormat("YYYY-mm-dd", new Date());
this.runing = false;
}
check_room() {
if (window.location.pathname != "/" + bLab8A.data.Roomid) {
if (window.location.pathname != "/blanc/" + bLab8A.data.Roomid) {
Console_log("检测到当前直播间并非在执行范围内:" + window.location.pathname);
return false;
}
return true;
}
return true;
}
change_rid(Roomid) {
if (Roomid === undefined) {
Roomid = bLab8A.data.Roomid;
} else {
if (bLab8A.data.Roomid != Roomid) {
bLab8A.data.GList = bLab8A.data.New = bLab8A.data.Lost = this.old_List = this.List = new Array();
bLab8A.data.first_use = this.first_use = true;
}
bLab8A.data.Roomid = Roomid;
}
HTTPsend("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser?room_id=" + Roomid, "GET", "", (result) => {
let rdata = JSON_parse(result);
if (rdata.code == 0) {
bLab8A.data.ruid = rdata.data.medal.up_medal.uid.toString();
bLab8A.save();
Console_log("保存成功。");
} else {
Console_error("保存出错。");
}
});
}
first_check() {
this.cdate = dateFormat("YYYY-mm-dd", new Date());
if (bLab8A.data.Check_date != this.cdate) {
(bLab8A.data.HL.indexOf(bLab8A.data.Check_date) == -1) && bLab8A.data.HL.push(bLab8A.data.Check_date);
bLab8A.data.History[bLab8A.data.Check_date] = { New: [], Lost: [] }
bLab8A.data.History[bLab8A.data.Check_date]["New"] = bLab8A.data.New;
bLab8A.data.History[bLab8A.data.Check_date]["Lost"] = bLab8A.data.Lost;
// console.log(bLab8A.data);
bLab8A.save();
}
this.List = new Array();
this.old_List = bLab8A.data.GList;
this.now = 1;
this.runing = true;
this.check(this.now);
}
check(page) {
// 获得当前的舰长列表
if (page === undefined) {
this.now = page = 1 + this.now;
} else {
this.now = page;
}
HTTPsend("https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=" + bLab8A.data.Roomid + "&page=" + page + "&ruid=" + bLab8A.data.ruid + "&page_size=29", "GET", "", (result) => {
let rdata = JSON_parse(result);
if (rdata.code == 0) {
this.page = rdata.data.info.page;
rdata.data.list.forEach(e => {
this.List.push({
uid: e.uid,
username: e.username,
face: e.face,
guard_level: e.guard_level
});
});
if (rdata.data.info.page > page) {
setTimeout(() => { this.check(); }, 300);
} else {
// this.cdate = dateFormat("YYYY-mm-dd",new Date());
if (this.first_use) {
bLab8A.data.first_use = this.first_use = false;
} else {
this.check_lost();
this.check_new();
}
bLab8A.data.GList = this.old_List = this.List;
bLab8A.data.Check_date = this.cdate;
this.runing = false;
bLab8A.save();
}
}
});
}
check_lost() {
// 丢失了多少舰长
// 旧列表 - 新列表 = 丢失的舰长
let ll = this.check_list(this.old_List, this.List);
if (bLab8A.data.Check_date != this.cdate) {
bLab8A.data.Lost = ll;
} else {
bLab8A.data.Lost.concat(ll);
}
}
check_new() {
// 新增了多少舰长
// 新列表 - 旧列表 = 新增的舰长
let nl = this.check_list(this.List, this.old_List);
if (bLab8A.data.Check_date != this.cdate) {
bLab8A.data.New = nl;
} else {
bLab8A.data.New.concat(nl);
}
}
check_list(list1, list2) {
// 以上两个列表对比,没有相同的数据,放到 tmp_List 里
let tmp_List = new Array();
for (let i = 0; i < list1.length; i++) {
let not_new = false;
const e = list1[i];
for (let k = 0; k < list2.length; k++) {
const d = list2[k];
if (e.uid == d.uid) {
not_new = true;
break;
}
}
!not_new && tmp_List.push(e);
}
return tmp_List;
}
}
let gLC = new GLC();
let CreactUI = function () {
if (document.getElementById("Bili8-UI")) {
// lists.Set("加载中。。。");
// lists.BG("normal");
document.getElementById("Bili8-UI").style.display = "block";
} else {
let Panel_ui = document.createElement("div");
Panel_ui.classList.add("Bili8-UI", "Panel");
Panel_ui.id = "Bili8-UI";
let PanelClose_ui = document.createElement("button");
PanelClose_ui.classList.add("Close");
PanelClose_ui.innerText = "关闭";
let StateText_ui = document.createElement("div");
StateText_ui.innerHTML = "";
StateText_ui.classList.add("State");
let MainList_ui = document.createElement("div");
MainList_ui.classList.add("MainList");
let List_ui = document.createElement("textarea");
List_ui.classList.add("ListNew");
List_ui.readOnly = true;
let List_ui2 = document.createElement("textarea");
List_ui2.classList.add("ListLost");
List_ui2.readOnly = true;
let List_ui3 = document.createElement("textarea");
List_ui3.classList.add("ListNow");
List_ui3.readOnly = true;
let MainBottom_ui = document.createElement("div");
MainBottom_ui.classList.add("MainBottom");
let RIDInput_ui = document.createElement("input");
RIDInput_ui.title = "主播房间ID";
RIDInput_ui.placeholder = "主播房间ID";
RIDInput_ui.type = "text";
RIDInput_ui.value = bLab8A.data.Roomid;
RIDInput_ui.classList.add("MBtn", "MBRID");
let AutoInput_ui = document.createElement("input");
AutoInput_ui.title = "自动查询";
AutoInput_ui.type = "checkbox";
AutoInput_ui.checked = bLab8A.data.auto;
AutoInput_ui.classList.add("MBtn", "MBAuto");
let AutoText_ui = document.createElement("div");
AutoText_ui.innerHTML = "自动查询";
AutoText_ui.classList.add("MBtn", "MBTAuto");
let NewText_ui = document.createElement("div");
NewText_ui.innerHTML = "新增";
NewText_ui.classList.add("MBtn", "MBTNew");
let LostText_ui = document.createElement("div");
LostText_ui.innerHTML = "失去";
LostText_ui.classList.add("MBtn", "MBTLost");
let SaveSetting_ui = document.createElement("button");
SaveSetting_ui.classList.add("MBtn", "MBSaveSetting");
SaveSetting_ui.innerText = "保存设置";
let LoadList_ui = document.createElement("button");
LoadList_ui.classList.add("MBtn", "LoadList");
LoadList_ui.innerText = "开始查询";
// LoadList_ui.disabled = true;
Panel_ui.appendChild(PanelClose_ui);
Panel_ui.appendChild(StateText_ui);
MainList_ui.appendChild(List_ui);
MainList_ui.appendChild(List_ui3);
MainList_ui.appendChild(List_ui2);
Panel_ui.appendChild(MainList_ui);
MainBottom_ui.appendChild(RIDInput_ui);
MainBottom_ui.appendChild(AutoText_ui);
MainBottom_ui.appendChild(AutoInput_ui);
MainBottom_ui.appendChild(NewText_ui);
MainBottom_ui.appendChild(LostText_ui);
MainBottom_ui.appendChild(SaveSetting_ui);
MainBottom_ui.appendChild(LoadList_ui);
Panel_ui.appendChild(MainBottom_ui);
document.body.appendChild(Panel_ui);
SaveSetting_ui.addEventListener("click", () => {
(bLab8A.data.Roomid != RIDInput_ui.value) && confirm("确定要改变监听的直播间吗?改变后将清空之前保存的舰长列表!") && gLC.change_rid(RIDInput_ui.value);
bLab8A.data.auto = AutoInput_ui.checked;
bLab8A.save();
lists.Set("设置已保存");
});
LoadList_ui.addEventListener("click", () => {
if (!gLC.runing) {
if (!gLC.check_room()) {
confirm("当前直播间并不在设置的直播间内,是否先回到设置的直播间?") && (window.location.href = "/" + bLab8A.data.Roomid);
return;
}
lists.BG("running");
lists.Set("正在查询");
gLC.first_check();
let t2 = setInterval(() => {
if (!gLC.runing) {
load_list();
lists.BG("normal");
lists.Set("新增:" + bLab8A.data.New.length + ",失去:" + bLab8A.data.Lost.length);
clearInterval(t2);
}
}, 100);
} else {
lists.Set("请求已经发送过去了,请勿重复点击!");
}
});
PanelClose_ui.addEventListener("click", () => {
document.getElementById("Bili8-UI").style.display = "none";
});
}
};
let Lists = class {
Get(obj) {
if (obj === undefined) {
obj = document.getElementById("Bili8-UI").getElementsByClassName("State")[0];
}
return obj.innerHTML;
};
Set(text, obj) {
if (obj === undefined) {
obj = document.getElementById("Bili8-UI").getElementsByClassName("State")[0];
}
obj.innerHTML = text;
};
Add(text, obj) {
if (obj === undefined) {
obj = document.getElementById("Bili8-UI").getElementsByClassName("List")[0];
}
if (obj.innerHTML == "") {
obj.innerHTML = text;
} else {
obj.innerHTML += "\n" + text;
}
};
Clear(obj) {
if (obj === undefined) {
obj = document.getElementById("Bili8-UI").getElementsByClassName("List")[0];
}
obj.innerHTML = "";
};
BG(status, obj) {
if (obj === undefined) {
obj = document.getElementById("Bili8-UI").getElementsByClassName("State")[0];
}
let color = "#FFFFFF";
switch (status) {
case "normal":
color = "#FFFFFF";
break;
case "running":
color = "#FFCC80";
break;
case "success":
color = "#91FFC2";
break;
case "error":
color = "#F45A8D";
break;
default:
color = "#FFFFFF";
break;
}
obj.style.backgroundColor = color;
}
};
let lists = new Lists();
let load_list = function () {
let List_ui = document.getElementById("Bili8-UI").getElementsByClassName("ListNew")[0];
lists.Clear(List_ui);
if (bLab8A.data.New.length > 0) {
bLab8A.data.New.forEach(e => {
lists.Add(e.username + ":" + e.uid, List_ui);
});
}
let List_ui2 = document.getElementById("Bili8-UI").getElementsByClassName("ListLost")[0];
lists.Clear(List_ui2);
if (bLab8A.data.Lost.length > 0) {
bLab8A.data.Lost.forEach(e => {
lists.Add(e.username + ":" + e.uid, List_ui2);
});
}
let List_ui3 = document.getElementById("Bili8-UI").getElementsByClassName("ListNow")[0];
lists.Clear(List_ui3);
if (bLab8A.data.GList.length > 0) {
bLab8A.data.GList.forEach(e => {
lists.Add(e.username + ":" + e.uid, List_ui3);
});
}
}
let CreactMenu = function () {
let Creact_G = function (Mode) {
if (Mode == 1) {
if (!gLC.check_room()) {
confirm("当前直播间并不在设置的直播间内,是否先回到设置的直播间?") && (window.location.href = "/" + bLab8A.data.Roomid);
return;
}
lists.BG("running");
lists.Set("正在查询");
gLC.first_check();
let t2 = setInterval(() => {
if (!gLC.runing) {
load_list();
lists.BG("normal");
lists.Set("新增:" + bLab8A.data.New.length + ",失去:" + bLab8A.data.Lost.length);
clearInterval(t2);
}
}, 100);
}
CreactUI();
}
GM_registerMenuCommand("打开面板", () => { Creact_G(0) });
GM_registerMenuCommand("开始查询", () => { Creact_G(1) });
};
CreactMenu();
gLC.check_room() && CreactUI();
document.getElementById("Bili8-UI").style.display = "none";
gLC.check_room() && bLab8A.data.auto && gLC.first_check();
if (gLC.runing) {
let t2 = setInterval(() => {
if (!gLC.runing) {
load_list();
lists.Set("新增:" + bLab8A.data.New.length + ",失去:" + bLab8A.data.Lost.length);
clearInterval(t2);
}
}, 100);
}
})();