// ==UserScript==
// @name Bilidown联动脚本[音频mp3🎵,视频mp4📹,弹幕xml,ass🌴,封面🌾]
// @namespace http://tampermonkey.net/
// @version 0.2.5
// @description 脚本负责获取音频,工具负责视频封面弹幕等等,相互联动,互相增强,好耶ヽ(✿゚▽゚)ノ
// @author 王子周棋洛
// @match https://www.bilibili.com/video/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant none
// @license MIT
// ==/UserScript==
(function () {
let audioState = false;
let index = 0;
let my_xhr = null;
/**
* 单例添加css style在head中
* @param {*} css 样式字符串
* @param {*} name 样式类名
*/
function renderCSS(css, name) {
if (!document.head.querySelector(`.${name}`)) {
let style = document.createElement("style");
style.className = name;
style.innerHTML = css;
document.head.appendChild(style);
}
}
function renderAlert($el) {
let my_bili_system = document.createElement("div");
let my_bili_system_header = document.createElement("div");
let my_bili_system_close = document.createElement("div");
let my_bili_system_content = document.createElement("div");
let my_bili_system_join_time = document.createElement("div");
let h1 = document.createElement("h1");
let a1 = document.createElement("a");
let a2 = document.createElement("a");
let span1 = document.createElement("span");
let span2 = document.createElement("span");
let my_bili_system_btns = document.createElement("div");
my_bili_system.className = "my_bili_system";
my_bili_system_header.className = "my_bili_system_header";
my_bili_system_close.className = "my_bili_system_close";
my_bili_system_content.className = "my_bili_system_content";
my_bili_system_btns.className = "my_bili_system_btns";
my_bili_system_join_time.className = "my_bili_system_join_time";
for (let i = 0; i < 3; i++) {
let div = document.createElement("div");
div.className = "my_bili_system_btn";
let p = document.createElement("p");
let label = document.createElement("label");
let input = document.createElement("input");
input.type = "checkbox";
let span = document.createElement("span");
span.classList = "checkbox";
label.appendChild(input);
label.appendChild(span);
if (i == 0) p.innerHTML = "封面";
if (i == 1) p.innerHTML = "下载音频";
if (i == 2) p.innerHTML = "下载视频";
div.appendChild(p);
div.appendChild(label);
my_bili_system_content.appendChild(div);
}
a1.innerHTML = "重置";
a2.innerHTML = "作者主页";
span1.innerHTML = "入站时间: ";
my_bili_system_close.innerHTML = "X";
h1.innerHTML = "bilidown联动脚本";
a2.href = "https://zhouql.vip/";
a2.target = "_blank";
my_bili_system_join_time.appendChild(span1);
my_bili_system_join_time.appendChild(span2);
my_bili_system_btns.appendChild(a1);
my_bili_system_btns.appendChild(a2);
my_bili_system_header.appendChild(my_bili_system_close);
my_bili_system_header.appendChild(h1);
my_bili_system.appendChild(my_bili_system_header);
my_bili_system.appendChild(my_bili_system_join_time);
my_bili_system.appendChild(my_bili_system_content);
my_bili_system.appendChild(my_bili_system_btns);
// 挂载
$el.appendChild(my_bili_system);
}
/**
* 移除元素
* @param {*} p 移除元素的父容器,dom
* @param {*} e 移除的元素,字符串
*/
function removeDom(p, e) {
if (p.querySelector(`.${e}`)) {
p.querySelectorAll(`.${e}`).forEach(i => {
p.removeChild(i);
})
}
}
// 时间戳格式化为标准时间
function formatTimestamp(timestamp) {
var date = new Date(timestamp);
var year = date.getFullYear();
var month = ("0" + (date.getMonth() + 1)).slice(-2);
var day = ("0" + date.getDate()).slice(-2);
var hours = ("0" + date.getHours()).slice(-2);
var minutes = ("0" + date.getMinutes()).slice(-2);
var seconds = ("0" + date.getSeconds()).slice(-2);
return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
}
// 获取信息,主要用于查看入站时间
function getLoginUserData() {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'https://member.bilibili.com/x2/creative/h5/calendar/event?ts=0', true);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
let jsonData = JSON.parse(xhr.responseText)
let time = formatTimestamp(jsonData.data.pfs.profile.jointime * 1000);
document.querySelector(".my_bili_system_join_time").querySelectorAll("span")[1].innerHTML = time;
} else {
document.querySelector(".my_bili_system_join_time").style.display = "none";
}
}
};
xhr.send(null);
}
let renderButton = async() => {
if (!document.querySelector(".my_bili_system_button")) {
let myBiliSystemButton = createNode('a', '设置', 'my_bili_system_button');
if (!document.querySelector(".my_bili_system")) {
renderAlert(document.body);
renderCSS(`.my_bili_system .my_bili_system_content .my_bili_system_btn label{display:block;width:15px;height:15px;cursor:pointer;display:flex;justify-content:flex-end}.my_bili_system .my_bili_system_content .my_bili_system_btn input[type='checkbox']{position:absolute;transform:scale(0)}.my_bili_system .my_bili_system_content .my_bili_system_btn input[type='checkbox']:checked~.checkbox{transform:rotate(45deg);width:14px;margin-left:5px;border-color:#24c78e;border-width:5px;border-top-color:transparent;border-left-color:transparent;border-radius:0;box-sizing:border-box}.my_bili_system .my_bili_system_content .my_bili_system_btn .checkbox{display:block;width:inherit;height:inherit;border:solid 2px #919191b7;border-radius:5px;transition:all .375s}.my_bili_system{font-family:SF Pro SC,SF Pro Text,SF Pro Icons,PingFang SC,Helvetica Neue,Helvetica,Arial,sans-serif;position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:400px;max-height:300px;border:1px solid #ddd;box-shadow:0 2px 3px #ccc;border-radius:4px;transition:height .3s;overflow:auto;padding:5px 10px;background-color:#fafafa;display:none;z-index:9999999999999}.my_bili_system::-webkit-scrollbar{width:5px}.my_bili_system::-webkit-scrollbar-track{background-color:#d8d8d8;border-radius:100px}.my_bili_system::-webkit-scrollbar-thumb{background-color:#6eb79d;border-radius:100px}.my_bili_system .my_bili_system_header .my_bili_system_close:hover{background-color:#d0d2d5;color:#888}.my_bili_system .my_bili_system_header .my_bili_system_close{position:absolute;right:0;top:0;color:#ccc;cursor:pointer;padding:4px 10px;border-radius:0 4px 0 0;display:flex;align-items:center;justify-content:center;transition:background-color .15s,color .2s}.my_bili_system .my_bili_system_header h1{font-size:15px;color:#333;margin:0}.my_bili_system .my_bili_system_content .my_bili_system_btn{display:flex;align-items:center;width:100%;border-bottom:1px solid #eee;padding:5px 0}.my_bili_system .my_bili_system_content .my_bili_system_btn label{flex:1}.my_bili_system .my_bili_system_content .my_bili_system_btn p{font-size:13px;color:#686868;font-weight:600;margin:5px 0}.my_bili_system_btns{padding:5px 0}.my_bili_system_btns a{text-decoration:none;color:#fff;background-color:#37a27266;font-size:12px;padding:2px 4px;border-radius:4px;margin-right:5px}.my_bili_system_btns span{color:#767b7f;font-size:12px}.my_bili_system_join_time{font-size:12px;color:#37a27266;padding-top:5px}.my_bili_system_join_time span:nth-of-type(1){color:#24c78e}`, "my_bili_system_css");
}
myBiliSystemButton.addEventListener('click', e => {
e.preventDefault();
getLoginUserData();
document.querySelector(".my_bili_system").style.display = "block";
let systems = document.querySelectorAll(".my_bili_system input");
let biliSystem = document.querySelector(".my_bili_system")
let closeBtn = document.querySelector(".my_bili_system_close");
let btns = document.querySelector(".my_bili_system_btns").querySelectorAll("a");
if (localStorage.getItem("myBiliCoverImg") && localStorage.getItem("myBiliCoverImg") == 'true') systems[0].checked = true;
if (localStorage.getItem("myBiliMP3") && localStorage.getItem("myBiliMP3") == 'true') systems[1].checked = true;
if (localStorage.getItem("myBiliMP4") && localStorage.getItem("myBiliMP4") == 'true') systems[2].checked = true;
systems[0].addEventListener('change', e => {
if (e.target.checked == true) {
localStorage.setItem("myBiliCoverImg", true);
} else {
localStorage.setItem("myBiliCoverImg", false);
}
})
systems[1].addEventListener('change', e => {
if (e.target.checked == true) {
localStorage.setItem("myBiliMP3", true);
} else {
localStorage.setItem("myBiliMP3", false);
}
})
systems[2].addEventListener('change', e => {
if (e.target.checked == true) {
localStorage.setItem("myBiliMP4", true);
} else {
localStorage.setItem("myBiliMP4", false);
}
})
closeBtn.addEventListener('click', e => {
setTimeout(() => {
biliSystem.style.display = 'none';
}, 120);
})
btns[0].addEventListener("click", e => {
e.preventDefault();
systems.forEach(s => {
s.checked = false;
})
if (localStorage.getItem("myBiliCoverImg")) localStorage.removeItem("myBiliCoverImg");
if (localStorage.getItem("myBiliMP3")) localStorage.removeItem("myBiliMP3");
if (localStorage.getItem("myBiliMP4")) localStorage.removeItem("myBiliMP4");
if (localStorage.getItem("myBiliCloseTou")) localStorage.removeItem("myBiliCloseTou");
if (localStorage.getItem("myBiliCloseThree")) localStorage.removeItem("myBiliCloseThree");
})
})
}
// 根据设置和具体要求,选择性渲染按钮,设置是必渲染项
if (localStorage.getItem("myBiliCoverImg") && localStorage.getItem("myBiliCoverImg") == "true") {
if (__INITIAL_STATE__.videoData.pic && !document.querySelector(".my_coverImg_button")) {
let coverImgButton = createNode('a', '封面', 'my_coverImg_button');
coverImgButton.href = __INITIAL_STATE__.videoData.pic;
coverImgButton.target = '_blank';
}
} else {
removeDom(chooseEl(), "my_coverImg_button");
}
let items = document.querySelectorAll('.clickitem');
let heji = document.querySelectorAll(".video-episode-card");
if (items.length != 0) {
items.forEach((item, i) => {
item.addEventListener('click', e => {
if (my_xhr != null) my_xhr.abort();
index = i;
if (document.querySelector(".my_audio_button")) document.querySelector(".my_audio_button").remove();
if (document.querySelector(".my_coverImg_button")) document.querySelector(".my_coverImg_button").remove();
if (document.querySelector(".my_video_button")) document.querySelector(".my_video_button").remove();
})
})
}
if (heji.length != 0) {
heji.forEach((item, i) => {
item.addEventListener('click', e => {
if (my_xhr != null) my_xhr.abort();
if (document.querySelector(".my_audio_button")) document.querySelector(".my_audio_button").remove();
if (document.querySelector(".my_coverImg_button")) document.querySelector(".my_coverImg_button").remove();
if (document.querySelector(".my_video_button")) document.querySelector(".my_video_button").remove();
})
})
}
if (localStorage.getItem("myBiliMP3") && localStorage.getItem("myBiliMP3") == 'true') {
if (__INITIAL_STATE__.aid && __INITIAL_STATE__.bvid && __INITIAL_STATE__.videoData.pages[0].cid && !document.querySelector(".my_audio_button")) {
let audioButton = createNode('a', '下载MP3', 'my_audio_button');
audioButton.addEventListener('click', e => {
if (!audioState) {
audioState = true;
let url = `https://api.bilibili.com/x/player/playurl?avid=${__INITIAL_STATE__.aid}&bvid=${__INITIAL_STATE__.bvid}&cid=${__INITIAL_STATE__.videoData.pages[index].cid}&fnval=4048`;
fetch(url, {
method: "GET",
responseType: "application/json"
}).then(resp => {
return resp.json();
}).then(i => {
my_xhr = new XMLHttpRequest();
my_xhr.responseType = 'blob';
my_xhr.open('GET', i.data.dash.audio[0].base_url, true);
my_xhr.addEventListener('progress', function (event) {
audioButton.textContent = `下载中... ${parseInt((event.loaded / event.total) * 100)}%`;
}, false);
my_xhr.onload = () => {
if (my_xhr.status === 200) {
const reader = new FileReader();
reader.readAsDataURL(my_xhr.response);
reader.onload = function (e) {
const a = document.createElement('a');
if (document.querySelector(".video-title")) {
a.download = document.querySelector(".video-title").textContent + ".mp3";
} else {
a.download = `Hello Wolrd.mp3`
}
a.href = e.target.result;
document.documentElement.appendChild(a);
a.click();
a.remove();
audioState = false;
my_xhr = null;
audioButton.textContent = `下载MP3`;
};
}
}
my_xhr.send();
})
} else {
my_xhr.abort();
audioButton.textContent = `已取消下载`;
audioState = false;
setTimeout(() => { audioButton.textContent = `下载MP3` }, 1000);
}
})
}
} else {
removeDom(chooseEl(), "my_audio_button");
}
if (localStorage.getItem("myBiliMP4") && localStorage.getItem("myBiliMP4") == 'true') {
if (location.href && !document.querySelector(".my_video_button")) {
let videoButton = createNode('a', '下载MP4', 'my_video_button');
videoButton.href = `http://zhouql.vip/bilibili/?${location.href}`;
videoButton.target = `_blank`;
}
} else {
removeDom(chooseEl(), "my_video_button");
}
}
// 选择按钮正确挂载点,兼容旧播放器
let chooseEl = () => {
if (document.querySelector(".video-info-detail-list")) return document.querySelector(".video-info-detail-list");
if (document.querySelector(".video-data")) return document.querySelector(".video-data");
}
// 创建按钮
let createNode = (type, text, className) => {
let node = document.createElement(type);
node.textContent = text;
node.className = className;
node.style = `font-size:12px;text-decoration:none;padding:2px 6px;border-radius:4px;background-color:#37a27266;color:#fff;margin-left:6px`;
console.log(chooseEl());
chooseEl().appendChild(node);
return node;
}
// 定时渲染
setInterval(() => {
renderButton();
}, 1500)
})();