您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在B站个人动态的视频列表里直接加入稍后看按钮
- // ==UserScript==
- // @name BiliBili+
- // @namespace BiliBili+@Byzod.user.js
- // @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 result %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 result = 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{
- result = await (await fetch(url, {method: "POST", credentials: "include"})).json();
- } catch (ex) {
- // 一般来说是网络错误
- result = ex;
- btn.innerText = " 【操作失败,请重试】 ";
- }
- if(result.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" + result.message, 3000, "error")};
- btn.innerText = result.message;
- }
- }
- // 获取cookie
- function GetCookieValue(name) {
- var valueMatch = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
- return valueMatch ? valueMatch.pop() : '';
- }