🏠 Home 

BiliBili+

在B站个人动态的视频列表里直接加入稍后看按钮

// ==UserScript==
// @name        BiliBili+
// @namespace   [email protected]
// @include     /https?:\/\/www\.bilibili\.com\/account\/dynamic/
// @version     2017-6-21b
// @grant       none
// jshint esversion:6
// @description 在B站个人动态的视频列表里直接加入稍后看按钮
// ==/UserScript==
const WATCH_LATER_TEXT = "  【稍候再看】  ";
const REMOVE_WATCH_LATER_TEXT = "  【移除稍候再看】  ";
const WATCH_LATER_BG_COLOR = "#1672A4";
// 观察者,执行“添加稍后看按钮”
let observer = new MutationObserver(AddWatchLaterButton);
// 视频列表
let vidsList = document.querySelector(".stm-lst");
if(vidsList){
observer.observe( vidsList, { childList: true } );
} else {
alert("[Bili+]: Vids list not exist");
}
// 添加稍候看按钮
async function AddWatchLaterButton(recs){
// console.log("[Bili+]: recs %o", recs); // DEBUG
// 先获取稍后看列表
let addedVids = await GettingAddedWatchList();
// console.log("[Bili+]: addedVids %o", addedVids); // DEBUG
for(let rec of recs){
rec.addedNodes.forEach(vidRow => {
// 如果是视频,加个按钮
if(vidRow.className == "stm-lst-item"){
let vid = vidRow.querySelector(".hint>a");
let av = vid.href;
av = av.match(/\d+/)[0];
// console.log("[Bili+]: av " + av); // DEBUG
if(!vid.parentNode.querySelector(".watch-later-btn")){
let watchLaterBtn = document.createElement("button");
watchLaterBtn.className = "watch-later-btn";
watchLaterBtn.style.trasition = "0.5s";
if(!addedVids.includes(parseInt(av))){
// 不在稍后看里,只改提示
watchLaterBtn.innerText = WATCH_LATER_TEXT;
} else {
// 已在稍后看里,改为移除按钮样式
watchLaterBtn.innerText = REMOVE_WATCH_LATER_TEXT;
watchLaterBtn.style.backgroundColor = WATCH_LATER_BG_COLOR;
}
// 挂添加/移除事件处理
watchLaterBtn.onclick = ()=>{ ToggleWatchLater(av, watchLaterBtn); };
// 加在链接后面
vid.parentNode.appendChild(document.createElement("br"));
vid.parentNode.appendChild(watchLaterBtn);
}
}
});
}
}
// 获取稍后看列表
async function GettingAddedWatchList(){
return new Promise(async (resolve, reject)=>{
let r = null;
let url = new URL(location.protocol + "//api.bilibili.com/x/v2/history/toview/web");
let params = {
jsonp: "jsonp",
sid: GetCookieValue('sid'), // 大概是用户id
csrf: GetCookieValue('bili_jct') // 并不清楚这是啥
}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
try{
r = await (await fetch(url, {method: "GET", credentials: "include"})).json();
} catch (ex) {
r = null;
}
// console.log("[Bili+]: fetch r###lt %o", r); // DEBUG
if(r && r.data && r.data.list){
resolve(r.data.list.map(vid=>vid.aid));
} else {
reject([])
}
});
}
// 切换稍后看状态
async function ToggleWatchLater(av, btn){
// console.log("[Bili+]: Toggle av %o", av); // DEBUG
// 先获取稍后看列表
let addedVids = await GettingAddedWatchList();
let isWatchLater = addedVids.includes(parseInt(av));
// console.log("[Bili+]: " + (isWatchLater ? "Removing from watch later" : "Adding to watch later")); // DEBUG
let r###lt = null;
let url = new URL(location.protocol + "//api.bilibili.com/x/v2/history/toview/" + (isWatchLater ? "del" : "add"));
let params = {
aid: av,
jsonp: "jsonp",
csrf: GetCookieValue('bili_jct') // 并不清楚这是啥
}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
try{
r###lt = await (await fetch(url, {method: "POST", credentials: "include"})).json();
} catch (ex) {
// 一般来说是网络错误
r###lt = ex;
btn.innerText = "  【操作失败,请重试】 ";
}
if(r###lt.code == "0"){
// 添加/移除成功
btn.innerText = (isWatchLater ? WATCH_LATER_TEXT : REMOVE_WATCH_LATER_TEXT);
btn.style.backgroundColor = (isWatchLater ? "" : WATCH_LATER_BG_COLOR);
if(MessageBox){(new MessageBox).show(btn, "已" + (isWatchLater ? "移除" : "添加"), 700, "info")};
} else {
// 服务器返回失败
if(MessageBox){(new MessageBox).show(btn, "粗错啦:\n" + r###lt.message, 3000, "error")};
btn.innerText = r###lt.message;
}
}
// 获取cookie
function GetCookieValue(name) {
var valueMatch = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
return valueMatch ? valueMatch.pop() : '';
}