// ==UserScript==
// @name 懒人专用,全网VIP视频免费破解去广告、全网音乐直接下载、百度网盘直接下载、知乎视频下载等多合一版。长期更新,放心使用。
// @namespace lanhaha
// @version 2.4.3
// @description 自用组合型多功能脚本,无需关注公众号,集合了优酷、爱奇艺、腾讯、芒果等全网VIP视频免费破解去广告,网易云音乐、QQ音乐、酷狗、酷我、虾米、蜻蜓FM、荔枝FM、喜马拉雅等网站音乐免客户端下载,百度网盘直接下载,知乎视频下载,优惠券查询等几个自己常用的功能。
// @author lanhaha,syhyz1990,Chao,zuihuimai
// @include *://pan.baidu.com/disk/home*
// @include *://yun.baidu.com/disk/home*
// @include *://pan.baidu.com/s*
// @include *://yun.baidu.com/s*
// @include *://*.zhihu.com/*
// @include *://v.vzuu.com/video/*
// @include *.youku.com/v*
// @include *m.youku.com/*
// @include *v.qq.com/x/*
// @include *v.qq.com/p*
// @include *v.qq.com/cover*
// @include *v.qq.com/tv/*
// @include *film.sohu.com/album/*
// @include *tv.sohu.com/*
// @include *.iqiyi.com/v_*
// @include *.iqiyi.com/w_*
// @include *.iqiyi.com/a_*
// @include *.le.com/ptv/vplay/*
// @include *.tudou.com/listplay/*
// @include *.tudou.com/albumplay/*
// @include *.tudou.com/programs/view/*
// @include *.tudou.com/v*
// @include *.mgtv.com/b/*
// @include *.acfun.cn/v/*
// @include *.bilibili.com/video/*
// @include *.bilibili.com/anime/*
// @include *.bilibili.com/bangumi/play/*
// @include *.pptv.com/show/*
// @include *.wasu.cn/Play/show*
// @include *v.yinyuetai.com/video/*
// @include *v.yinyuetai.com/playlist/*
// @include *://item.taobao.com/*
// @include *://*detail.tmall.com/*
// @include *://*detail.tmall.hk/*
// @include *://*.liangxinyao.com/*
// @include *://music.163.com/song*
// @include *://music.163.com/m/song*
// @include *://y.qq.com/n/*
// @include *://*.kugou.com/song*
// @include *://*.kuwo.cn/yinyue*
// @include *://*.kuwo.cn/play_detail*
// @include *://*.xiami.com/*
// @include *://music.taihe.com/song*
// @include *://*.1ting.com/player*
// @include *://music.migu.cn/v*
// @include *://*.lizhi.fm/*
// @include *://*.qingting.fm/*
// @include *://*.ximalaya.com/*
// @exclude *://*.eggvod.cn/*
// @connect d.pcs.baidu.com
// @connect baidu.com
// @connect baidupcs.com
// @connect baiduyun.wiki
// @connect localhost
// @require https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js
// @require https://cdn.jsdelivr.net/npm/sweetalert2@9
// @license GPL License
// @grant GM_download
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant unsafeWindow
// @grant GM_setClipboard
// @grant GM_getResourceURL
// @grant GM_getResourceText
// @grant GM_info
// @grant GM_registerMenuCommand
// @run-at document-idle
// ==/UserScript==
//百度网盘
(function() {
var pan_title=new Array()
pan_title[0]= "https://pan.baidu.com/"
pan_title[1]= "https://yun.baidu.com/"
let pan_link = location.href;
for(var a=0;a<pan_title.length;a++){
if(pan_link.indexOf(pan_title[a])!= -1){
pan_link = pan_link.replace('baidu.com','baiduwp.com');
var pan_html = "<a href="+pan_link+" target='_blank' style='cursor:pointer;z-index:98;display:block;width:30px;height:30px;line-height:30px;position:fixed;left:0;top:300px;text-align:center;'><img src='https://cdn.80note.com/vip.gif' style='width:50px' ></a>";
$("body").append(pan_html);
//百度网盘脚本开始
;(() => {
'use strict'
const version = GM_info.script.version
const classMap = {
'bar-search': 'OFaPaO',
'list-tools': 'tcuLAu',
'header': 'vyQHNyb'
}
const errorMsg = {
'dir': '提示:不支持整个文件夹下载,可进入文件夹内获取文件链接下载!',
'unlogin': '提示:登录网盘后才能使用此功能哦!',
'fail': '提示:获取下载链接失败!请刷新网页后重试!',
'unselected': '提示:请先选择要下载的文件!',
'morethan': '提示:多个文件请点击【显示链接】!',
'toobig': '提示:只支持300M以下的文件夹,若链接无法下载,请进入文件夹后勾选文件获取!',
'timeout': '提示:页面过期,请刷新重试!',
'wrongcode': '提示:获取验证码失败!',
'deleted': '提示:文件不存在或已被百度和谐,无法下载!',
}
let defaultCode = 250528
let secretCode = getValue('secretCodeV') ? getValue('secretCodeV') : defaultCode
let panhelper = {}
let userAgent = ''
let Toast = Swal.mixin({
toast: true,
position: 'top',
showConfirmButton: false,
timer: 3000,
timerProgressBar: false,
onOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
})
let ariaRPC = {
domain: getValue('rpcDomain') || 'http://localhost',
port: getValue('rpcPort') || 6800,
token: getValue('rpcToken') || '',
dir: getValue('rpcDir') || 'D:/',
}
function clog(c1, c2, c3) {
c1 = c1 ? c1 : ''
c2 = c2 ? c2 : ''
c3 = c3 ? c3 : ''
console.group('[网盘直链下载助手]')
console.log(c1, c2, c3)
console.groupEnd()
}
function getBDUSS() {
let baiduyunPlugin_BDUSS = getStorage('baiduyunPlugin_BDUSS') ? getStorage('baiduyunPlugin_BDUSS') : '{"baiduyunPlugin_BDUSS":""}'
let BDUSS = JSON.parse(baiduyunPlugin_BDUSS).BDUSS
if (!BDUSS) {
Swal.fire({
icon: 'error',
title: '提示',
html: panhelper.t.e,
footer: '【网盘万能助手】是增强扩展插件,安装后请刷新',
confirmButtonText: '安装'
}).then((result) => {
if (result.value) {
GM_openInTab(panhelper.w, {active: true})
}
})
}
return BDUSS
}
function aria2c(link, filename, ua) {
let BDUSS = getBDUSS()
ua = ua || userAgent
if (BDUSS) {
return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "User-Agent: ${ua}" --header "Cookie: BDUSS=${BDUSS}"`)
} else {
return '请先安装网盘万能助手,安装后请重启浏览器!!!'
}
}
function replaceLink(link) {
return link ? link.replace(/&/g, '&') : ''
}
function detectPage() {
let regx = /[\/].+[\/]/g
let page = location.pathname.match(regx)
return page[0].replace(/\//g, '')
}
function getCookie(e) {
let o, t
let n = document, c = decodeURI
return n.cookie.length > 0 && (o = n.cookie.indexOf(e + "="), -1 != o) ? (o = o + e.length + 1, t = n.cookie.indexOf(";", o), -1 == t && (t = n.cookie.length), c(n.cookie.substring(o, t))) : ""
}
function setCookie(key, value, t) {
let oDate = new Date() //创建日期对象
oDate.setTime(oDate.getTime() + t * 60 * 1000) //设置过期时间
document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString() //设置cookie的名称,数值,过期时间
}
function getValue(name) {
return GM_getValue(name)
}
function setValue(name, value) {
GM_setValue(name, value)
}
function getStorage(key) {
return localStorage.getItem(key)
}
function setStorage(key, value) {
return localStorage.setItem(key, value)
}
function encode(str) {
return btoa(unescape(encodeURIComponent(btoa(unescape(encodeURIComponent(str))))))
}
function decode(str) {
return decodeURIComponent(escape(atob(decodeURIComponent(escape(atob(str))))))
}
function getLogID() {
let name = "BAIDUID"
let u = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/~!@#¥%……&"
let d = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
let f = String.fromCharCode
function l(e) {
if (e.length < 2) {
let n = e.charCodeAt(0)
return 128 > n ? e : 2048 > n ? f(192 | n >>> 6) + f(128 | 63 & n) : f(224 | n >>> 12 & 15) + f(128 | n >>> 6 & 63) + f(128 | 63 & n)
}
let n = 65536 + 1024 * (e.charCodeAt(0) - 55296) + (e.charCodeAt(1) - 56320)
return f(240 | n >>> 18 & 7) + f(128 | n >>> 12 & 63) + f(128 | n >>> 6 & 63) + f(128 | 63 & n)
}
function g(e) {
return (e + "" + Math.random()).replace(d, l)
}
function m(e) {
let n = [0, 2, 1][e.length % 3]
let t = e.charCodeAt(0) << 16 | (e.length > 1 ? e.charCodeAt(1) : 0) << 8 | (e.length > 2 ? e.charCodeAt(2) : 0)
let o = [u.charAt(t >>> 18), u.charAt(t >>> 12 & 63), n >= 2 ? "=" : u.charAt(t >>> 6 & 63), n >= 1 ? "=" : u.charAt(63 & t)]
return o.join("")
}
function h(e) {
return e.replace(/[\s\S]{1,3}/g, m)
}
function p() {
return h(g((new Date()).getTime()))
}
function w(e, n) {
return n ? p(String(e)).replace(/[+\/]/g, (e) => {
return "+" == e ? "-" : "_"
}).replace(/=/g, "") : p(String(e))
}
return w(getCookie(name))
}
function rpcSetting() {
let dom = ''
dom += '<div class="flex-center-between"><label for="rpcDomain" class="label">主机</label><input type="text" id="rpcDomain" value="' + ariaRPC.domain + '" class="swal2-input" placeholder="http://localhost"></div>'
dom += '<div class="flex-center-between"><label for="rpcPort" class="label">端口</label><input type="text" id="rpcPort" value="' + ariaRPC.port + '" class="swal2-input" placeholder="6800"></div>'
dom += '<div class="flex-center-between"><label for="rpcToken" class="label">密钥</label><input type="text" id="rpcToken" value="' + ariaRPC.token + '" class="swal2-input" placeholder="没有留空"></div>'
dom += '<div class="flex-center-between"><label for="rpcDir" class="label">下载路径</label><input type="text" id="rpcDir" value="' + ariaRPC.dir + '" class="swal2-input" placeholder="默认为D:\"></div>'
dom += '<div class="flex-center-between" style="margin-top: 15px;font-size: 0.85em;color: #999;"><div class="label">快速配置</div> <div style="flex: 1;text-align: left;"><span class="rtag" id="rpc1">Motrix</span><span class="rtag" id="rpc2">Aria2 Tools</span><span class="rtag" id="rpc3">AriaNgGUI</span></div></div>'
dom = '<div>' + dom + '</div>'
let $dom = $(dom)
$(document).on('click', '#rpc1', () => {
$('#rpcDomain').val('http://localhost')
$('#rpcPort').val(16800)
$('#rpcDir').val('D:')
})
$(document).on('click', '#rpc2', () => {
$('#rpcDomain').val('http://localhost')
$('#rpcPort').val(6800)
$('#rpcDir').val('D:')
})
$(document).on('click', '#rpc3', () => {
$('#rpcDomain').val('http://192.168.0.?')
$('#rpcPort').val(6800)
$('#rpcDir').val('/storage/emulated/0/Download')
})
Swal.fire({
title: 'RPC配置',
allowOutsideClick: false,
html: $dom[0],
showCancelButton: true,
confirmButtonText: '保存',
cancelButtonText: '取消',
footer: panhelper.t.n
}
).then((result) => {
if (result.value) {
ariaRPC.domain = $('#rpcDomain').val()
ariaRPC.port = $('#rpcPort').val()
ariaRPC.token = $('#rpcToken').val()
ariaRPC.dir = $('#rpcDir').val()
setValue('rpcDomain', ariaRPC.domain)
setValue('rpcPort', ariaRPC.port)
setValue('rpcToken', ariaRPC.token)
setValue('rpcDir', ariaRPC.dir)
Toast.fire({
text: '设置成功',
icon: 'success'
})
}
})
}
function Dialog() {
let linkList = []
let showParams
let dialog, shadow
function createDialog() {
let screenWidth = document.body.clientWidth
let dialogLeft = screenWidth > 800 ? (screenWidth - 800) / 2 : 0
let $dialog_div = $('<div class="dialog" style="width: 800px; top: 0px; bottom: auto; left: ' + dialogLeft + 'px; right: auto; display: hidden; visibility: visible; z-index: 52;"></div>')
let $dialog_header = $('<div class="dialog-header"><h3><span class="dialog-title" style="display:inline-block;width:740px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis"></span></h3></div>')
let $dialog_control = $('<div class="dialog-control"><span class="dialog-icon dialog-close">×</span></div>')
let $dialog_body = $('<div class="dialog-body"></div>')
let $dialog_tip = $('<div class="dialog-tip"><p></p></div>')
$dialog_div.append($dialog_header.append($dialog_control)).append($dialog_body)
let $dialog_button = $('<div class="dialog-button" style="display:none"></div>')
let $dialog_button_div = $('<div style="display:table;margin:auto"></div>')
let $dialog_copy_button = $('<button id="dialog-copy-button" style="display:none">复制全部链接</button>')
let $dialog_send_button = $('<button id="dialog-send-button" class="send-all" style="display:none">发送全部链接</button>')
let $dialog_rpc_button = $('<button id="dialog-rpc-button" class="rpc-setting" style="display:none">配置RPC服务</button>')
$dialog_button_div.append($dialog_copy_button).append($dialog_send_button).append($dialog_rpc_button)
$dialog_button.append($dialog_button_div)
$dialog_div.append($dialog_button)
$dialog_copy_button.click(() => {
let content = ''
if (showParams.type === 'pcs') {
$.each(linkList, (index, element) => {
console.log(element)
if (index === linkList.length - 1)
content += element.dlink
else
content += element.dlink + '\r\n'
})
}
if (showParams.type === 'batchAria') {
$.each(linkList, (index, element) => {
if (index === linkList.length - 1)
content += decodeURIComponent(aria2c(element.dlink, element.filename, userAgent))
else
content += decodeURIComponent(aria2c(element.dlink, element.filename, userAgent) + '\r\n')
})
}
if (showParams.type === 'rpc') {
$.each(linkList, (index, element) => {
if (index === linkList.length - 1)
content += element.downloadlink
else
content += element.downloadlink + '\r\n'
})
}
if (showParams.type === 'shareLink') {
$.each(linkList, (index, element) => {
if (element.dlink == 'error')
return
if (index == linkList.length - 1)
content += element.dlink
else
content += element.dlink + '\r\n'
})
}
if (showParams.type == 'shareAriaLink') {
$.each(linkList, (index, element) => {
if (element.dlink == 'error')
return
if (index == linkList.length - 1)
content += decodeURIComponent(aria2c(element.dlink, element.server_filename))
else
content += decodeURIComponent(aria2c(element.dlink, element.server_filename) + '\r\n')
})
}
GM_setClipboard(content, 'text')
if (content != '') {
Toast.fire({
icon: 'success',
text: '已将链接复制到剪贴板!'
})
} else {
Toast.fire({
icon: 'error',
text: '复制失败,请手动复制!'
})
}
})
$dialog_div.append($dialog_tip)
$('body').append($dialog_div)
$dialog_control.click(dialogControl)
return $dialog_div
}
function createShadow() {
let $shadow = $('<div class="dialog-shadow" style="position: fixed; left: 0px; top: 0px; z-index: 50; background: rgb(0, 0, 0) none repeat scroll 0% 0%; opacity: 0.5; width: 100%; height: 100%; display: none;"></div>')
$('body').append($shadow)
return $shadow
}
this.open = (params) => {
showParams = params
linkList = []
if (params.type == 'link') {
linkList = params.list.urls
$('div.dialog-header h3 span.dialog-title', dialog).html(params.title + ":" + params.list.filename)
$.each(params.list.urls, (index, element) => {
element.url = replaceLink(element.url)
let $div = $('<div><div style="width:30px;float:left">' + element.rank + ':</div><div style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis"><a href="' + element.url + '">' + element.url + '</a></div></div>')
$('div.dialog-body', dialog).append($div)
})
}
if (params.type === 'batchAria' || params.type === 'batchAriaRPC' || params.type === 'pcs') {
linkList = params.list
$('div.dialog-header h3 span.dialog-title', dialog).html(params.title)
$.each(params.list, (index, element) => {
let $div = $('<div class="row"><div class="ui-title" title="' + element.filename + '">' + element.filename + '</div><span>:</span></div>')
if (params.type === 'pcs') {
$div.append($('<a class="ui-link api-dlink" data-filename=' + element.filename + ' data-link=' + element.dlink + ' href="' + element.dlink + '">' + element.dlink + '</a>'))
}
if (params.type === 'batchAria') {
let link = decodeURIComponent(aria2c(element.dlink, element.filename, userAgent))
$div.append($('<a class="ui-link aria-link" href="javascript:;">' + link + '</a>'))
}
if (params.type === 'batchAriaRPC') {
$div.append($('<button class="aria-rpc" data-link="' + element.dlink + '" data-filename="' + element.filename + '">点击发送到Aria下载器</button>'))
}
$('div.dialog-body', dialog).append($div)
})
}
if (params.type === 'shareLink') {
linkList = params.list
$('div.dialog-header h3 span.dialog-title', dialog).html(params.title)
$.each(params.list, (index, element) => {
element.dlink = replaceLink(element.dlink)
if (element.isdir == 1) return
let $div = $('<div class="row"><div class="ui-title" title="' + element.server_filename + '">' + element.server_filename + '</div><span>:</span><a href="' + element.dlink + '" class="api-dlink">' + element.dlink + '</a></div>')
$('div.dialog-body', dialog).append($div)
})
}
if (params.type === 'rpcLink') {
linkList = params.list
$('div.dialog-header h3 span.dialog-title', dialog).html(params.title)
$.each(params.list, (index, element) => {
element.dlink = replaceLink(element.dlink)
if (element.isdir == 1) return
let $div = $('<div class="row"><div class="ui-title" title="' + element.server_filename + '">' + element.server_filename + '</div><span>:</span><button class="aria-rpc" data-link="' + element.dlink + '" data-filename="' + element.server_filename + '">点击发送到Aria下载器</button></div>')
$('div.dialog-body', dialog).append($div)
})
}
if (params.type === 'shareAriaLink') {
linkList = params.list
$('div.dialog-header h3 span.dialog-title', dialog).html(params.title)
$.each(params.list, (index, element) => {
if (element.isdir == 1) return
let link = decodeURIComponent(aria2c(element.dlink, element.server_filename))
let $div = $('<div class="row"><div class="ui-title" title="' + element.server_filename + '">' + element.server_filename + '</div><span>:</span><a href="javasctipt:void(0)" class="aria-link">' + link + '</a></div>')
$('div.dialog-body', dialog).append($div)
})
}
if (params.tip) {
$('div.dialog-tip p', dialog).html(params.tip)
}
if (params.showcopy) {
$('div.dialog-button', dialog).show()
$('div.dialog-button #dialog-copy-button', dialog).show()
}
if (params.showrpc) {
$('div.dialog-button', dialog).show()
$('div.dialog-button #dialog-send-button', dialog).show()
$('div.dialog-button #dialog-rpc-button', dialog).show()
}
shadow.show()
dialog.show()
}
this.close = () => {
dialogControl()
}
function dialogControl() {
$('div.dialog-body', dialog).children().remove()
$('div.dialog-header h3 span.dialog-title', dialog).text('')
$('div.dialog-tip p', dialog).text('')
$('div.dialog-button', dialog).hide()
$('div.dialog-button button#dialog-copy-button', dialog).hide()
$('div.dialog-button button#dialog-send-button', dialog).hide()
$('div.dialog-button button#dialog-rpc-button', dialog).hide()
dialog.hide()
shadow.hide()
}
dialog = createDialog()
shadow = createShadow()
}
function PanHelper() {
let yunData, sign, timestamp, bdstoken, logid, fid_list
let fileList = [], selectFileList = [], batchLinkList = [], batchLinkListAll = [], linkList = []
let dialog, searchKey
let panAPIUrl = location.protocol + "//" + location.host + "/api/"
let restAPIUrl = location.protocol + "//pcs.baidu.com/rest/2.0/pcs/"
let clientAPIUrl = location.protocol + "//pan.baidu.com/rest/2.0/"
this.init = () => {
yunData = unsafeWindow.yunData
initVar()
registerEventListener()
addButton()
dialog = new Dialog({addCopy: true})
clog('下载助手加载成功!当前版本:', version)
}
function getSelectedFile() {
return require("disk-system:widget/pageModule/list/listInit.js").getCheckedItems()
}
function initVar() {
timestamp = yunData.timestamp || ''
bdstoken = yunData.MYBDSTOKEN || ''
logid = getLogID()
}
function registerEventListener() {
$(document).on('click', '.aria-rpc', (e) => {
$(e.target).addClass('clicked')
let link = e.target.dataset.link
let filename = e.target.dataset.filename
let url = ariaRPC.domain + ":" + ariaRPC.port + '/jsonrpc'
let json_rpc = {
id: new Date().getTime(),
jsonrpc: '2.0',
method: 'aria2.addUri',
params: [
"token:" + ariaRPC.token,
[link],
{
dir: ariaRPC.dir,
out: filename,
header: ['User-Agent:' + userAgent, 'Cookie: BDUSS=' + getBDUSS()]
}
]
}
GM_xmlhttpRequest({
method: "POST",
headers: {"User-Agent": userAgent},
url: url,
responseType: 'json',
timeout: 3000,
data: JSON.stringify(json_rpc),
onload: (response) => {
if (response.response.result) {
Toast.fire({
icon: 'success',
title: '任务已发送至RPC下载器'
})
} else {
Toast.fire({
icon: 'error',
title: response.response.message
})
}
},
ontimeout: () => {
Toast.fire({
icon: 'error',
title: '连接到RPC服务器超时,请检查RPC配置'
})
}
})
})
$(document).on('click', '.rpc-setting', () => {
rpcSetting()
})
$(document).on('click', '.send-all', () => {
$('.aria-rpc').click()
$('.dialog').hide()
$('.dialog-shadow').hide()
})
}
function addButton() {
$('div.' + classMap['bar-search']).css('width', '18%')
let $dropdownbutton = $('<span class="g-dropdown-button"></span>')
let $dropdownbutton_a = $('<a class="g-button" data-button-id="b200" data-button-index="200" href="javascript:;"></a>')
let $dropdownbutton_a_span = $('<span class="g-button-right"><em class="icon icon-download"></em><span class="text" style="width: 60px;">下载助手</span></span>')
let $dropdownbutton_span = $('<span class="menu" style="width:auto;z-index:41"></span>')
let $linkButton = $('<a class="g-button-menu" id="batchhttplink-pcs" href="javascript:;" data-type="down">API下载</a>')
let $aricLinkButton = $('<a class="g-button-menu" id="batchhttplink-aria" href="javascript:;">Aria下载</a>')
let $aricRPCButton = $('<a class="g-button-menu" id="batchhttplink-rpc" href="javascript:;" data-type="rpc">RPC下载</a>')
let $versionButton = $(`<a style="color: #F24C43;" class="g-button-menu" target="_blank" href="${panhelper.u}">${panhelper.t.u}</a>`)
$dropdownbutton_span.append($linkButton).append($aricLinkButton).append($aricRPCButton)
$dropdownbutton_a.append($dropdownbutton_a_span)
$dropdownbutton.append($dropdownbutton_a).append($dropdownbutton_span)
if (getValue('up')) {$dropdownbutton_span.append($versionButton)}
$dropdownbutton.hover(() => {
$dropdownbutton.toggleClass('button-open')
})
$aricRPCButton.click(batchClick)
$linkButton.click(batchClick)
$aricLinkButton.click(batchClick)
$('.' + classMap['list-tools']).append($dropdownbutton)
$('.' + classMap['list-tools']).css('height', '40px')
}
function batchClick(event) {
selectFileList = getSelectedFile()
if (selectFileList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return
}
let id = event.target.id
let tip
batchLinkList = []
batchLinkListAll = []
if (id.indexOf('pcs') > 0) {
getPCSBatchLink((batchLinkList) => {
let tip = panhelper.t.j
if (batchLinkList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return
}
dialog.open({title: panhelper.t.k, type: 'pcs', list: batchLinkList, tip: tip, showcopy: false})
})
}
if (id.indexOf('aria') > 0) {
getPCSBatchLink((batchLinkList) => {
tip = panhelper.t.f
if (batchLinkList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return
}
dialog.open({title: panhelper.t.l, type: 'batchAria', list: batchLinkList, tip: tip, showcopy: true})
})
}
if (id.indexOf('rpc') > 0) {
getPCSBatchLink((batchLinkList) => {
tip = panhelper.t.g
if (batchLinkList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return
}
dialog.open({title: panhelper.t.m, type: 'batchAriaRPC', list: batchLinkList, tip: tip, showcopy: false, showrpc: true})
})
}
}
function getPCSBatchLink(callback) {
let fsids = [], token = undefined
$.each(selectFileList, (index, element) => {
if (element.isdir == 1)
return
fsids.push(element.fs_id)
})
fsids = encodeURIComponent(JSON.stringify(fsids))
let link = panhelper.p.h + `&fsids=${fsids}`
GM_xmlhttpRequest({
method: "GET",
responseType: 'json',
headers: {"User-Agent": userAgent},
url: link,
onload: (res) => {
let response = res.response
if (response.errno === 0) {
callback(response.list)
}
}
})
}
}
function PanShareHelper() {
let yunData, sign, timestamp, bdstoken, channel, clienttype, web, app_id, logid, encrypt, product, uk,
primaryid, fid_list, extra, shareid
let shareType, buttonTarget, dialog
let selectFileList = []
let panAPIUrl = location.protocol + "//" + location.host + "/api/"
this.init = () => {
yunData = unsafeWindow.yunData
initVar()
addButton()
dialog = new Dialog({addCopy: false})
registerEventListener()
clog('下载助手加载成功!当前版本:', version)
}
function initVar() {
shareType = getShareType()
sign = yunData.SIGN
timestamp = yunData.TIMESTAMP
bdstoken = yunData.MYBDSTOKEN
channel = 'chunlei'
clienttype = 0
web = 1
app_id = secretCode
logid = getLogID()
encrypt = 0
product = 'share'
primaryid = yunData.SHARE_ID
uk = yunData.SHARE_UK
if (shareType == 'secret') {
extra = getExtra()
}
if (!isSingleShare()) {
shareid = yunData.SHARE_ID
}
}
function getSelctedFile() {
if (isSingleShare()) {
return yunData.FILEINFO
} else {
return require("disk-share:widget/pageModule/list/listInit.js").getCheckedItems()
}
}
function getShareType() {
return yunData.SHARE_PUBLIC === 1 ? 'public' : 'secret'
}
function isSingleShare() {
return yunData.SHAREPAGETYPE === "single_file_page"
}
function isSelfShare() {
return yunData.MYSELF === 1
}
function getExtra() {
let seKey = decodeURIComponent(getCookie('BDCLND'))
return '{' + '"sekey":"' + seKey + '"' + "}"
}
function getPath() {
let hash = location.hash
let regx = new RegExp("path=([^&]*)(&|$)", 'i')
let result = hash.match(regx)
return decodeURIComponent(result[1])
}
function addButton() {
if (isSingleShare()) {
$('div.slide-show-right').css('width', '500px')
$('div.frame-main').css('width', '96%')
$('div.share-file-viewer').css('width', '740px').css('margin-left', 'auto').css('margin-right', 'auto')
} else
$('div.slide-show-right').css('width', '500px')
let $dropdownbutton = $('<span class="g-dropdown-button"></span>')
let $dropdownbutton_a = $('<a class="g-button" data-button-id="b200" data-button-index="200" href="javascript:;"></a>')
let $dropdownbutton_a_span = $('<span class="g-button-right"><em class="icon icon-download"></em><span class="text" style="width: 60px;">下载助手</span></span>')
let $dropdownbutton_span = $('<span class="menu" style="width:auto;z-index:41"></span>')
let $linkButton = $('<a class="g-button-menu" href="javascript:;" data-type="down">API下载</a>')
let $aricLinkButton = $('<a class="g-button-menu" href="javascript:;">Aria下载</a>')
let $aricRPCButton = $('<a class="g-button-menu" href="javascript:;" data-type="rpc">RPC下载</a>')
let $versionButton = $(`<a style="color: #F24C43;" class="g-button-menu" target="_blank" href="${panhelper.u}">${panhelper.t.u}</a>`)
$dropdownbutton_span.append($linkButton).append($aricLinkButton).append($aricRPCButton)
$dropdownbutton_a.append($dropdownbutton_a_span)
$dropdownbutton.append($dropdownbutton_a).append($dropdownbutton_span)
if (getValue('up')) {$dropdownbutton_span.append($versionButton)}
$dropdownbutton.hover(() => {
$dropdownbutton.toggleClass('button-open')
})
$aricRPCButton.click(linkButtonClick)
$linkButton.click(linkButtonClick)
$aricLinkButton.click(ariclinkButtonClick)
$('div.module-share-top-bar div.bar div.x-button-box').append($dropdownbutton)
}
function ariclinkButtonClick() {
selectFileList = getSelctedFile()
if (bdstoken === null) {
Toast.fire({
icon: 'error',
text: errorMsg.unlogin
})
return false
}
if (selectFileList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return false
}
buttonTarget = 'ariclink'
getDownloadLink((downloadLink) => {
if (downloadLink === undefined) return
if (downloadLink.errno === 0) {
let tip = panhelper.t.f
dialog.open({title: panhelper.t.l, type: 'shareAriaLink', list: downloadLink.list, tip: tip, showcopy: true})
} else if (downloadLink.errno == 112) {
Toast.fire({
icon: 'error',
text: errorMsg.timeout
})
return false
} else {
Toast.fire({
icon: 'error',
text: errorMsg.fail
})
}
})
}
function registerEventListener() {
$(document).on('click', '.aria-rpc', (e) => {
$(e.target).addClass('clicked')
let link = e.target.dataset.link
let filename = e.target.dataset.filename
let url = ariaRPC.domain + ":" + ariaRPC.port + '/jsonrpc'
let json_rpc = {
id: new Date().getTime(),
jsonrpc: '2.0',
method: 'aria2.addUri',
params: [
"token:" + ariaRPC.token,
[link],
{
dir: ariaRPC.dir,
out: filename,
header: ['User-Agent:' + userAgent, 'Cookie: BDUSS=' + getBDUSS()]
}
]
}
GM_xmlhttpRequest({
method: "POST",
headers: {"User-Agent": userAgent},
url: url,
responseType: 'json',
timeout: 3000,
data: JSON.stringify(json_rpc),
onload: (response) => {
if (response.response.result) {
Toast.fire({
icon: 'success',
title: '任务已发送至RPC下载器'
})
} else {
Toast.fire({
icon: 'error',
title: response.response.message
})
}
},
ontimeout: () => {
Toast.fire({
icon: 'error',
title: '连接到RPC服务器超时,请检查RPC配置'
})
}
})
})
$(document).on('click', '.rpc-setting', (e) => {
rpcSetting()
})
$(document).on('click', '.send-all', (e) => {
$('.aria-rpc').click()
$('.dialog').hide()
$('.dialog-shadow').hide()
})
}
function getFidList() {
let fidlist = []
$.each(selectFileList, (index, element) => {
fidlist.push(element.fs_id)
})
return '[' + fidlist + ']'
}
function linkButtonClick(e) {
selectFileList = getSelctedFile()
if (bdstoken === null) {
Toast.fire({
icon: 'error',
text: errorMsg.unlogin
})
return false
}
if (selectFileList.length === 0) {
Toast.fire({
icon: 'error',
text: errorMsg.unselected
})
return false
}
buttonTarget = 'link'
getDownloadLink((downloadLink) => {
if (downloadLink === undefined) return
if (downloadLink.errno === 0) {
if (e.target.dataset.type === 'rpc') {
let tip = panhelper.t.g
dialog.open({title: panhelper.t.m, type: 'rpcLink', list: downloadLink.list, tip: tip, showcopy: false, showrpc: true})
} else {
let tip = panhelper.t.i
dialog.open({title: panhelper.t.k, type: 'shareLink', list: downloadLink.list, tip: tip, showcopy: true})
}
} else if (downloadLink.errno == 112) {
Toast.fire({
icon: 'error',
text: errorMsg.timeout
})
return false
} else {
Toast.fire({
icon: 'error',
text: errorMsg.fail
})
}
})
}
function getDownloadLink(cb) {
if (bdstoken === null) {
Toast.fire({
icon: 'error',
text: errorMsg.unlogin
})
return ''
}
if (isSingleShare) {
fid_list = getFidList()
logid = getLogID()
let params = new FormData()
params.append('encrypt', encrypt)
params.append('product', product)
params.append('uk', uk)
params.append('primaryid', primaryid)
params.append('fid_list', fid_list)
if (shareType == 'secret') {
params.append('extra', extra)
}
GM_xmlhttpRequest({
method: "POST",
data: params,
url: panhelper.p.s + `&sign=${sign}×tamp=${timestamp}&logid=${logid}`,
onload: (res) => {
cb(JSON.parse(res.response))
}
})
}
}
}
function PanPlugin() {
clog('RPC:', ariaRPC)
this.init = () => {
main()
addGMStyle()
checkUpdate()
getValue('SETTING_H') ? createHelp() : ''
createMenu()
}
function loadPanhelper() {
switch (detectPage()) {
case 'disk':
case 'oauth2.0':
let panHelper = new PanHelper()
panHelper.init()
return
case 'share':
case 's':
let panShareHelper = new PanShareHelper()
panShareHelper.init()
return
default:
return
}
}
function addGMStyle() {
GM_addStyle(`
.dialog .row {overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}
.dialog .row .ui-title {width: 150px;float: left;overflow: hidden;text-overflow: ellipsis;}
.dialog .row .ui-link {margin-right: 20px;}
.dialog-body {max-height: 450px;overflow-y: auto;padding: 0 20px;}
.dialog-tip {padding: 0 20px;background-color: #fff;border-top: 1px solid #c4dbfe;color: #dc373c;}
.tm-setting {display: flex;align-items: center;justify-content: space-between;padding-top: 20px;}
.tm-checkbox {width: 16px;height: 16px;}
#dialog-copy-button {width: 120px;margin: 5px 10px 10px;cursor: pointer;background: #cc3235;border: none;height: 30px;color: #fff;border-radius: 3px;}
#dialog-send-button {width: 120px;margin: 5px 10px 10px;cursor: pointer;background: #cc3235;border: none;height: 30px;color: #fff;border-radius: 3px;}
#dialog-rpc-button {width: 120px;margin: 5px 10px 10px;cursor: pointer;background: #4e97ff;border: none;height: 30px;color: #fff;border-radius: 3px;}
.flex-center-between {display: flex;align-items: center;justify-content: space-between}
.flex-center-between .label {margin-right: 20px;flex: 0 0 100px;text-align:right}
.swal2-input {height:50px!important;margin:10px auto!important;}
.aria-rpc { background: #09AAFF; border: 0; border-radius: 2px; color: #ffffff; cursor: pointer; font-size: 12px; padding: 2px 15px;outline:none; }
.aria-rpc.clicked { background: #808080; }
.rtag {padding: 3px 8px; background: #e6e0e0; border-radius: 5px; margin: 0 10px 0 0; color: #666; cursor: pointer;}
`)
}
function checkUpdate() {
setValue('up', 0)
GM_xmlhttpRequest({
method: "POST",
data: encode(JSON.stringify(GM_info.script)),
url: `https://api.baiduyun.wiki/update?ver=${version}`,
onload: (r) => {
let res = JSON.parse(decode(r.response))
panhelper = res
setValue('lastest_version', res.v)
userAgent = res.a
if (res.s != getValue('scode')) {
Swal.fire({
title: res.t.b,
//html: $(`<div><img style="width: 250px;margin-bottom: 10px;" src="${res.q}"><input class="swal2-input" id="scode" type="text" placeholder="${res.t.a}"></div>`)[0],
allowOutsideClick: false,
confirmButtonText: '确定'
}).then((result) => {
if (res.s == $('#scode').val()) {
setValue('scode', res.s)
setValue('init', 1)
Toast.fire({
icon: 'success',
text: res.t.c,
}).then(() => {
history.go(0)
})
} else {
setValue('scode', res.s)
setValue('init', 1)
Toast.fire({
icon: 'success',
text: res.t.c,
}).then(() => {
history.go(0)
})
}
})
} else {
loadPanhelper()
}
}
})
}
function compareVersion(a, b) {
return (a.replace(/\./g, '') - b.replace(/\./g, '')) > 0
}
function createHelp() {
setTimeout(() => {
let topbar = $('.' + classMap['header'])
let toptemp = $('<span class="cMEMEF" node-type="help-author" style="opacity: .5" ><a href="' + panhelper.h + '" target="_blank">' + panhelper.o + '</a><i class="find-light-icon" style="display: inline;background-color: #009fe8;"></i></span>')
topbar.append(toptemp)
}, panhelper.tt || 5000)
}
function createMenu() {
GM_registerMenuCommand('设置', () => {
if (getValue('SETTING_H') === undefined) {
setValue('SETTING_H', true)
}
let dom = ''
if (getValue('SETTING_H')) {
dom += '<label class="tm-setting">开启教程<input type="checkbox" id="S-H" checked class="tm-checkbox"></label>'
} else {
dom += '<label class="tm-setting">开启教程<input type="checkbox" id="S-H" class="tm-checkbox"></label>'
}
dom = '<div>' + dom + '</div>'
let $dom = $(dom)
Swal.fire({
title: '脚本配置',
html: $dom[0],
confirmButtonText: '保存'
}).then((result) => {
history.go(0)
})
})
$(document).on('change', '#S-H', (e) => {
setValue('SETTING_H', e.currentTarget.checked)
})
}
function main() {
setValue('current_version', version)
let oMeta = document.createElement('meta')
oMeta.httpEquiv = 'Content-Security-Policy'
oMeta.content = 'upgrade-insecure-requests'
document.getElementsByTagName('head')[0].appendChild(oMeta)
$(document).on('contextmenu', '.aria-link', (e) => {
e.preventDefault()
return false
})
$(document).on('mousedown', '.aria-link', (e) => {
e.preventDefault()
let link = e.currentTarget.innerText
GM_setClipboard(link, 'text')
Toast.fire({
icon: 'success',
text: '已将链接复制到剪贴板!'
})
return false
})
$(document).on('click', '.api-dlink', (e) => {
e.preventDefault()
if (e.target.innerText) {
GM_xmlhttpRequest({
method: "GET",
headers: {"User-Agent": userAgent},
url: e.target.innerText,
})
}
})
}
}
$(() => {
let plugin = new PanPlugin()
plugin.init()
})
})()
//百度网盘脚本结束
}
}
})();
//百度网盘结束
(function() {
var couponUrl = window.location.href;
if(couponUrl.indexOf('taobao') != -1 || couponUrl.indexOf('tmall') != -1){
//is_off
$.get('https://www.zuihuimai.net/vrhr/loading.php',function(loading_html){
if(loading_html){
var head = document.getElementsByTagName('head')[0],
cssURL = 'https://www.zuihuimai.net/tm/style.css',
linkTag = document.createElement('link');
linkTag.id = 'dynamic-style';
linkTag.href = cssURL;
linkTag.setAttribute('rel','stylesheet');
linkTag.setAttribute('media','all');
linkTag.setAttribute('type','text/css');
head.appendChild(linkTag);
var goods_id = getQueryString('id');
var zhm_url = 'https://www.zuihuimai.net/vrhr/index.php';
if(goods_id){
$('#J_LinkBasket').parent().after(loading_html);
$('.J_LinkAdd').parent().after(loading_html);
if(window.location.host.search('taobao.com') != -1){
$('#zhm_table').addClass('zhm_tab_taobao');
}else{
$('#zhm_table').addClass('zhm_tab_tmall');
}
$.get(zhm_url,{goods_id:goods_id},function(data){
$('#zhm_div_s').html(data);
$('#zhm_div_s').html(data);
if(window.location.host.search('taobao.com') != -1){
$('#zhm_table').addClass('zhm_tab_taobao');
}else{
$('#zhm_table').addClass('zhm_tab_tmall');
}
});
}
}
});
}
var id_random = Math.ceil(Math.random()*100000000);
var play_url = window.location.href;
var arr = new Array();
arr = play_url.split('?')
var get_url = arr[0];
if(get_url.indexOf('eggvod.cn') == -1){
var jx_title=new Array()
jx_title[0]="youku.com"
jx_title[1]="iqiyi.com"
jx_title[2]="le.com"
jx_title[3]="qq.com"
jx_title[4]="tudou.com"
jx_title[5]="mgtv.com"
jx_title[6]="sohu.com"
jx_title[7]="acfun.cn"
jx_title[8]="bilibili.com"
jx_title[9]="pptv.com"
jx_title[10]="baofeng.com"
jx_title[11]="yinyuetai.com"
jx_title[12]="wasu.cn"
var title_result = false;
for(var n=0;n<jx_title.length;n++){
if(get_url.indexOf(jx_title[n])!= -1){
var zhm_html = "<div href='javascript:void(0)' target='_blank' id="+id_random+" style='cursor:pointer;z-index:98;display:block;width:30px;height:30px;line-height:30px;position:fixed;left:0;top:300px;text-align:center;overflow:visible'><img src='https://cdn.80note.com/vip.gif' style='width:50px' ></div>";
$("body").append(zhm_html);
}
}
$("#"+id_random).click(function(){
var play_jx_url = window.location.href;
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
var mobile_html = "<div style='margin:0 auto;padding:10px;'>";
mobile_html +="<button type='button' style='position:absolute;top:0;right:30px;font-size:30px;line-height: 1;color: #000;text-shadow: 0 1px 0 #fff;cursor: pointer;border:0;background:0 0;' onclick='location.reload();'>×</button>";
mobile_html += "<div><iframe src='https://www.eggvod.cn/mobile.php?zhm_jx="+play_jx_url +"' allowtransparency=true frameborder='0' scrolling='no' allowfullscreen=true allowtransparency=true name='jx_play'style='height:600px;width:100%'></iframe></div>"
mobile_html += "</div>";
$("body").html(mobile_html);
} else {
$.get('https://www.eggvod.cn/jxcode.php',{in:81566699,code:2},function(data){
location.href='https://www.eggvod.cn/jx.php?lrspm='+data+'&zhm_jx='+play_jx_url;
});
}
});
var music_id = Math.ceil(Math.random()*100000000);
var music_title=new Array()
music_title[0]="163.com"
music_title[1]= "y.qq.com"
music_title[2]= "kugou.com"
music_title[3]= "kuwo.cn"
music_title[4]= "xiami.com"
music_title[5]= "taihe.com"
music_title[6]= "1ting.com"
music_title[7]= "migu.cn"
music_title[8]= "qingting.fm"
music_title[9]= "lizhi.fm"
music_title[10]= "ximalaya.com"
for(var i=0;i<music_title.length;i++){
if(get_url.indexOf(music_title[i])!= -1){
var music_html = "<div href='javascript:void(0)' id="+music_id+" style='cursor:pointer;z-index:98;display:block;width:30px;height:30px;line-height:30px;position:fixed;left:0;top:300px;text-align:center;'><img src='https://cdn.80note.com/vip.gif' style='width:50px' ></div>";
$("body").append(music_html);
}
}
$("#"+music_id).click(function(){
var music_jx_url = encodeURIComponent(window.location.href);
window.open('http://www.eggvod.cn/music/?url='+music_jx_url);
});
}
//获取url参数;
function getQueryString(e) {
var t = new RegExp("(^|&)" + e + "=([^&]*)(&|$)");
var a = window.location.search.substr(1).match(t);
if (a != null) return a[2];
return "";
}
})();
//知乎视频
(async () => {
if (window.location.host == 'www.zhihu.com') return;
const playlistBaseUrl = 'https://lens.zhihu.com/api/videos/';
//const videoBaseUrl = 'https://video.zhihu.com/video/';
const videoId = window.location.pathname.split('/').pop(); // 视频id
const menuStyle = 'transform:none !important; left:auto !important; right:-0.5em !important;';
const playerId = 'player';
const coverSelector = '#' + playerId + ' > div:first-child > div:first-child > div:nth-of-type(2)';
const controlBarSelector = '#' + playerId + ' > div:first-child > div:first-child > div:last-child > div:last-child > div:first-child';
const svgDownload = '<path d="M9.5,4 H14.5 V10 H17.8 L12,15.8 L6.2,10 H9.5 Z M6.2,18 H17.8 V20 H6.2 Z"></path>';
let player = document.getElementById(playerId);
let resolutionMap = {'标清': 'sd', '高清': 'ld', '超清': 'hd'};
let videos = []; // 存储各分辨率的视频信息
let downloading = false;
function getBrowerInfo() {
let browser = (function (window) {
let document = window.document;
let navigator = window.navigator;
let agent = navigator.userAgent.toLowerCase();
// IE8+支持.返回浏览器渲染当前文档所用的模式
// IE6,IE7:undefined.IE8:8(兼容模式返回7).IE9:9(兼容模式返回7||8)
// IE10:10(兼容模式7||8||9)
let IEMode = document.documentMode;
let chrome = window.chrome || false;
let system = {
// user-agent
agent: agent,
// 是否为IE
isIE: /trident/.test(agent),
// Gecko内核
isGecko: agent.indexOf('gecko') > 0 && agent.indexOf('like gecko') < 0,
// webkit内核
isWebkit: agent.indexOf('webkit') > 0,
// 是否为标准模式
isStrict: document.compatMode === 'CSS1Compat',
// 是否支持subtitle
supportSubTitle: function () {
return 'track' in document.createElement('track');
},
// 是否支持scoped
supportScope: function () {
return 'scoped' in document.createElement('style');
},
// 获取IE的版本号
ieVersion: function () {
let rMsie = /(msie\s|trident.*rv:)([\w.]+)/;
let match = rMsie.exec(agent);
try {
return match[2];
} catch (e) {
return IEMode;
}
},
// Opera版本号
operaVersion: function () {
try {
if (window.opera) {
return agent.match(/opera.([\d.]+)/)[1];
}
else if (agent.indexOf('opr') > 0) {
return agent.match(/opr\/([\d.]+)/)[1];
}
} catch (e) {
return 0;
}
}
};
try {
// 浏览器类型(IE、Opera、Chrome、Safari、Firefox)
system.type = system.isIE ? 'IE' :
window.opera || (agent.indexOf('opr') > 0) ? 'Opera' :
(agent.indexOf('chrome') > 0) ? 'Chrome' :
//safari也提供了专门的判定方式
window.openDatabase ? 'Safari' :
(agent.indexOf('firefox') > 0) ? 'Firefox' :
'unknow';
// 版本号
system.version = (system.type === 'IE') ? system.ieVersion() :
(system.type === 'Firefox') ? agent.match(/firefox\/([\d.]+)/)[1] :
(system.type === 'Chrome') ? agent.match(/chrome\/([\d.]+)/)[1] :
(system.type === 'Opera') ? system.operaVersion() :
(system.type === 'Safari') ? agent.match(/version\/([\d.]+)/)[1] :
'0';
// 浏览器外壳
system.shell = function () {
if (agent.indexOf('edge') > 0) {
system.version = agent.match(/edge\/([\d.]+)/)[1] || system.version;
return 'Edge';
}
// 遨游浏览器
if (agent.indexOf('maxthon') > 0) {
system.version = agent.match(/maxthon\/([\d.]+)/)[1] || system.version;
return 'Maxthon';
}
// QQ浏览器
if (agent.indexOf('qqbrowser') > 0) {
system.version = agent.match(/qqbrowser\/([\d.]+)/)[1] || system.version;
return 'QQBrowser';
}
// 搜狗浏览器
if (agent.indexOf('se 2.x') > 0) {
return '搜狗浏览器';
}
// Chrome:也可以使用window.chrome && window.chrome.webstore判断
if (chrome && system.type !== 'Opera') {
let external = window.external;
let clientInfo = window.clientInformation;
// 客户端语言:zh-cn,zh.360下面会返回undefined
let clientLanguage = clientInfo.languages;
// 猎豹浏览器:或者agent.indexOf("lbbrowser")>0
if (external && 'LiebaoGetVersion' in external) {
return 'LBBrowser';
}
// 百度浏览器
if (agent.indexOf('bidubrowser') > 0) {
system.version = agent.match(/bidubrowser\/([\d.]+)/)[1] ||
agent.match(/chrome\/([\d.]+)/)[1];
return 'BaiDuBrowser';
}
// 360极速浏览器和360安全浏览器
if (system.supportSubTitle() && typeof clientLanguage === 'undefined') {
let storeKeyLen = Object.keys(chrome.webstore).length;
let v8Locale = 'v8Locale' in window;
return storeKeyLen > 1 ? '360极速浏览器' : '360安全浏览器';
}
return 'Chrome';
}
return system.type;
};
// 浏览器名称(如果是壳浏览器,则返回壳名称)
system.name = system.shell();
// 对版本号进行过滤过处理
// System.version = System.versionFilter(System.version);
} catch (e) {
// console.log(e.message);
}
return system;
})(window);
if (browser.name == undefined || browser.name == '') {
browser.name = 'Unknown';
browser.version = 'Unknown';
}
else if (browser.version == undefined) {
browser.version = 'Unknown';
}
return browser;
}
function fetchRetry(url, options = {}, times = 1, delay = 1000, checkStatus = true) {
return new Promise((resolve, reject) => {
// fetch 成功处理函数
function success(res) {
if (checkStatus && !res.ok) {
failure(res);
}
else {
resolve(res);
}
}
// 单次失败处理函数
function failure(error) {
times--;
if (times) {
setTimeout(fetchUrl, delay);
}
else {
reject(error);
}
}
// 总体失败处理函数
function finalHandler(error) {
throw error;
}
function fetchUrl() {
return fetch(url, options)
.then(success)
.catch(failure)
.catch(finalHandler);
}
fetchUrl();
});
}
// 下载指定url的资源
async function downloadUrl(url, name = (new Date()).valueOf() + '.mp4') {
let browser = getBrowerInfo();
// Greasemonkey 需要把 url 转为 blobUrl
if (GM_info.scriptHandler == 'Greasemonkey') {
let res = await fetchRetry(url);
let blob = await res.blob();
url = URL.createObjectURL(blob);
}
// Chrome 可以使用 Tampermonkey 的 GM_download 函数绕过 CSP(Content Security Policy) 的限制
if (window.GM_download) {
GM_download({url, name});
}
else {
// firefox 需要禁用 CSP, about:config -> security.csp.enable => false
let a = document.createElement('a');
a.href = url;
a.download = name;
// a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function () {
URL.revokeObjectURL(url);
}, 100);
}
}
function humanSize(size) {
let n = Math.log(size) / Math.log(1024) | 0;
return (size / Math.pow(1024, n)).toFixed(0) + ' ' + (n ? 'KMGTPEZY'[--n] + 'B' : 'Bytes');
}
if (!player) return;
// 获取视频信息
const res = await fetchRetry(playlistBaseUrl + videoId, {
headers: {
'referer': 'refererBaseUrl + videoId',
'authorization': 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20' // in zplayer.min.js of zhihu
}
}, 3);
const videoInfo = await res.json();
// 获取不同分辨率视频的信息
for (let [key, video] of Object.entries(videoInfo.playlist)) {
video.name = key;
if (!videos.find(v => v.width == video.width)) {
videos.push(video);
}
}
// 按分辨率大小排序
videos = videos.sort(function (v1, v2) {
return v1.width == v2.width ? 0 : (v1.width > v2.width ? 1 : -1);
}).reverse();
document.addEventListener('DOMNodeInserted', (evt) => {
let domControlBar = evt.relatedNode.querySelector(':scope > div:last-child > div:first-child');
if (!domControlBar || domControlBar.querySelector('.download')) return;
let domFullScreenBtn = domControlBar.querySelector(':scope > div:nth-last-of-type(1)');
let domResolutionBtn = domControlBar.querySelector(':scope > div:nth-last-of-type(3)');
let domDownloadBtn, defaultResolution, buttons;
if (!domFullScreenBtn || !domFullScreenBtn.querySelector('button')) return;
// 克隆分辨率菜单或全屏按钮为下载按钮
domDownloadBtn = (domResolutionBtn && (domResolutionBtn.className == domFullScreenBtn.className))
? domResolutionBtn.cloneNode(true)
: domFullScreenBtn.cloneNode(true);
defaultResolution = domDownloadBtn.querySelector('button').innerText;
// 生成下载按钮图标
domDownloadBtn.querySelector('button:first-child').outerHTML = domFullScreenBtn.cloneNode(true).querySelector('button').outerHTML;
domDownloadBtn.querySelector('svg').innerHTML = svgDownload;
domDownloadBtn.className = domDownloadBtn.className + ' download';
buttons = domDownloadBtn.querySelectorAll('button');
// button 元素添加对应的下载地址
buttons.forEach(dom => {
let video = videos.find(v => v.name == resolutionMap[dom.innerText || defaultResolution]);
video = video || videos[0];
dom.dataset.video = video.play_url;
if (dom.innerText) {
(dom.innerText = `${dom.innerText} (${humanSize(video.size)})`);
}
else if (buttons.length == 1) {
dom.nextSibling.querySelector('div').innerText = humanSize(video.size);
}
});
// 鼠标事件 - 显示菜单
domDownloadBtn.addEventListener('pointerenter', () => {
let domMenu = domDownloadBtn.querySelector('div:nth-of-type(1)');
if (domMenu) {
domMenu.style.cssText = menuStyle + 'opacity:1 !important; visibility:visible !important';
}
});
// 鼠标事件 - 隐藏菜单
domDownloadBtn.addEventListener('pointerleave', () => {
let domMenu = domDownloadBtn.querySelector('div:nth-of-type(1)');
if (domMenu) {
domMenu.style.cssText = menuStyle;
}
});
// 鼠标事件 - 选择菜单项
domDownloadBtn.addEventListener('pointerup', event => {
if (downloading) {
alert('当前正在执行下载任务,请等待任务完成。');
return;
}
let e = event.srcElement || event.target;
while (e.tagName != 'BUTTON') {
e = e.parentNode;
}
downloadUrl(e.dataset.video);
});
// 显示下载按钮
domControlBar.appendChild(domDownloadBtn);
});
})();