// ==UserScript==
// @name 打包下载豆瓣音乐人所有音乐
// @namespace http://tampermonkey.net/
// @description 打包下载-豆瓣音乐人-页面当前的所有音乐
// @version 0.1
// @author eboy
// @include https://site.douban.com/*
// @grant GM_notification
// @grant GM_setClipboard
// @grant GM_download
// @grant GM_xmlhttpRequest
// @grant GM_getResourceURL
// @grant GM_setValue
// @grant GM_getValue
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.0/jszip.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js
// @require https://cdn.staticfile.org/mustache.js/3.1.0/mustache.min.js
// @resource iconError https://cdn.jsdelivr.net/gh/Mr-Po/weibo-resource-download/out/media/error.png
// @resource iconSuccess https://cdn.jsdelivr.net/gh/Mr-Po/weibo-resource-download/out/media/success.png
// @resource iconInfo https://cdn.jsdelivr.net/gh/Mr-Po/weibo-resource-download/out/media/info.png
// @resource iconExtract https://cdn.jsdelivr.net/gh/Mr-Po/weibo-resource-download/out/media/extract.png
// @resource iconZip https://cdn.jsdelivr.net/gh/Mr-Po/weibo-resource-download/out/media/zip.png
// @downloadURL none
// ==/UserScript==
;(function() {
'use strict'
let id = `vue_${+new Date()}`
$('.nav-items ul').append(
'
下载所有'
)
$('#' + id).click(function() {
let domList = $('.download')
let list = []
for (let index = 0; index < domList.length; index++) {
const element = $(domList[index]).children('a')
let url = element.attr('href')
let title = element.attr('title')
try {
title = title.split('下载')[1].trim()
} catch (error) {
console.log(error)
}
list.push({ src: url, name: title + '.mp3' })
}
ZipHandler.startZip(list)
})
class ZipHandler {
/**
* 生成一个进度条
* @param {$标签对象} $sub card的子节点
* @param {int} max 最大值
* @return {标签对象} 进度条
*/
static bornProgress(count) {
const $div = $('#header')
// 尝试获取进度条
let $progress = $div.find('progress')
// 进度条不存在时,生成一个
if ($progress.length === 0) {
$progress = $(""+count+"")
$div.append($progress)
} else {
// 已存在时,重置value
$progress[0].value = 0
}
return $progress[0]
}
/**
* 开始打包
* @param {$数组} $links 图片地址集
*/
static startZip($links) {
Tip.tip('正在提取,请稍候...', 'iconExtract')
const progress = ZipHandler.bornProgress($links.length)
const zip = new JSZip()
const names = []
$links.forEach(function(it, i) {
const name = it.name
GM_xmlhttpRequest({
method: 'GET',
url: it.src,
timeout: 8000,
responseType: 'blob',
onload: function(response) {
zip.file(name, response.response)
ZipHandler.downloadZipIfComplete(
progress,
name,
zip,
names,
$links.length
)
},
onerror: function(e) {
console.error(e)
Tip.error(`第${i + 1}个对象,获取失败!`)
ZipHandler.downloadZipIfComplete(
progress,
name,
zip,
names,
$links.length
)
},
ontimeout: function() {
Tip.error(`第${i + 1}个对象,请求超时!`)
ZipHandler.downloadZipIfComplete(
progress,
name,
zip,
names,
$links.length
)
}
})
})
}
/**
* 下载打包,如果完成
*/
static downloadZipIfComplete(progress, name, zip, names, length) {
names.push(name)
const value = names.length / length
progress.value = value
if (names.length === length) {
Tip.tip('正在打包,请稍候...', 'iconZip')
zip
.generateAsync(
{
type: 'blob'
},
function(metadata) {
progress.value = metadata.percent / 100
}
)
.then(function(content) {
Tip.success('打包完成,即将开始下载!')
const zipName = $($('.sp-logo'))
.children('a')
.text()
saveAs(content, `${zipName}.zip`)
})
}
}
}
/**
* 提示
*/
class Tip {
static tip(text, iconName) {
// if (Config.isTip) {
GM_notification({
text: text,
image: GM_getResourceURL(iconName),
timeout: 3000
})
// }
}
static info(text) {
Tip.tip(text, 'iconInfo')
}
static error(text) {
Tip.tip(text, 'iconError')
}
static success(text) {
Tip.tip(text, 'iconSuccess')
}
}
})()