🏠 Home 

[Bilibili] MarkAsRead

Mark all sessions as read with one click!

// ==UserScript==
// @name         [Bilibili] MarkAsRead
// @name:zh-CN   [Bilibili] 一键已读
// @namespace    ckylin-script-bilibili-mark-as-read
// @version      0.6
// @description  Mark all sessions as read with one click!
// @description:zh-CN 一键设置所有会话已读!
// @author       CKylinMC
// @match        https://message.bilibili.com/*
// @grant        unsafeWindow
// @supportURL   https://github.com/CKylinMC/UserJS
// @license      GPL-3.0-only
// ==/UserScript==
if (typeof (unsafeWindow) === "undefined") var unsafeWindow = window;
(function () {
'use strict';
const blacklist_elTitle = ["我的应援团","未关注人消息","疑似不良消息"];
const wait = t => new Promise(r => setTimeout(r, t));
const inBlacklist = el=>{
for(let titleItem of blacklist_elTitle){
if(el.querySelector(`[title='${titleItem}']`)) return true;
}
return false;
}
const touch = async el => {
el.click();
await wait(100)
};
const touchList = async div => {
let active = div.querySelector(".active");
for (let el of [...div.children].splice(1)) {
if (el.classList.contains("list-item") && el.querySelector(".notify") && !inBlacklist(el)) await touch(el)
}
if (active) await touch(active)
else location.hash = "#/whisper";
};
const msgList = () => document.querySelector("div.list");
const asRead = async () => await touchList(msgList());
const settingList = () => document.querySelector("ul.list");
const intervalLog = {
intervalId: null,
lastHash: location.hash,
lastState: false
};
const intervalHashChecker = ()=>{
if(location.hash!==intervalLog.lastHash) {
hashChecker();
intervalLog.lastHash = location.hash;
}
}
const hashChecker = ()=>{
if(location.hash.startsWith("#/whisper")) {
if(!intervalLog.lastState) {
injectBtn();
intervalLog.lastState = true;
}
}
else{
if(!intervalLog.lastState) return;
let old;
if (old = document.querySelector("#CKMARKREAD-BTN")) {
old.style.transition = "margin .3s .2s, opacity .5s";
old.style.opacity = "0";
old.style.margin = "0px 0px";
setTimeout(()=>old.remove(),300);
}
intervalLog.lastState = false;
}
};
const waitFor = async (func, waitt = 100, retries = 100) => {
while (--retries > 0) {
try {
const val = await func();
if (val) return val;
await wait(waitt);
} catch (e) {
console.log(e);
await wait(100);
}
}
return false;
};
const injectBtn = async () => {
if (await waitFor(() => settingList())) {
let old;
if (old = document.querySelector("#CKMARKREAD-BTN")) old.remove();
const a = document.createElement("a");
a.href = "javascript:void(0)";
a.innerHTML = "💬 全部标为已读";
a.onclick = async (e) => {
e.target.innerHTML = "🕓 请稍等...";
await waitFor(() => msgList());
await asRead();
e.target.innerHTML = "✔ 已标为已读";
e.target.onclick = e => e.target.innerHTML = "✔ 无需操作";
setTimeout(()=>{
e.target.parentElement.style.transition = "margin .3s .2s, opacity .5s";
e.target.parentElement.style.opacity = "0";
e.target.parentElement.style.margin = "0px 0px";
setTimeout(()=>e.target.parentElement.remove(),300);
},3000);
};
const item = document.createElement("li");
item.classList.add("item");
item.id = "CKMARKREAD-BTN";
item.style.opacity = "0";
item.style.margin = "0px 0";
item.style.transition = "all .3s";
item.appendChild(a);
settingList().appendChild(item);
setTimeout(()=>{
if(item){
item.style.margin = "15px 0";
item.style.opacity = "1";
}
},50)
}
};
const delayedInjectTask = async () => {
await wait(1000);
hashChecker();
if(intervalLog.intervalId)clearInterval(intervalLog.intervalId);
intervalLog.intervalId = setInterval(intervalHashChecker,300);
};
delayedInjectTask();
})();