// ==UserScript==
// @name 网易云下载
// @description 歌单里好多歌用以前的脚本都404了,于是简单修改了下。
// @version 20170604
// @author 糖果君
// @include http*://music.163.com/*
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @require https://gf.qytechs.cn/scripts/26727-网易云音乐歌曲封面下载/code/网易云音乐歌曲封面下载.user.js
// @namespace
// ==/UserScript==
//参考 https://gf.qytechs.cn/zh-CN/scripts/10548-网易云音乐下载
//以及更早的 https://gf.qytechs.cn/zh-CN/scripts/1099-netease-music-download
var api = {
//参考 https://gf.qytechs.cn/zh-CN/scripts/10582-网易云音乐高音质支持
getTrackURL: function(dfsId) {
var byte1 = '3go8&$8*3*3h0k(2)2';
var byte2 = dfsId + '';
var byte3 = [];
for (var i = 0; i < byte2.length; i++) {
byte3[i] = byte2.charCodeAt(i) ^ byte1.charCodeAt(i % byte1.length);
}
byte3 = byte3.map(function(i) {
return String.fromCharCode(i);
}).join('');
var results = unsafeWindow.CryptoJS.MD5(byte3).toString(unsafeWindow.CryptoJS.enc.Base64).replace(/\//g, '_').replace(/\+/g, '-');
var url = 'http://p2.music.126.net/' + results + '/' + byte2 + '.jpg';
return url;
},
encrypt_request: function(callback, url, data) {
// 这个好像不重要。var token = unsafeWindow.document.cookie.split('__csrf') [1].split(';') [0].substring(1);
var token = '';
data.csrf_token = token;
var req = new XMLHttpRequest();
req.open('POST', url + token, true);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.onload = function() {
callback(JSON.parse(this.responseText));
};
//参考 https://github.com/darknessomi/musicbox/wiki/网易云音乐新版WebAPI分析。
var pubKey = '010001';
var modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7';
var nonce = '0CoJUm6Qyw8W8jud';
var result = unsafeWindow.asrsea(JSON.stringify(data), pubKey, modulus, nonce);
req.send('params=' + encodeURIComponent(result.encText) + '&encSecKey=' + encodeURIComponent(result.encSecKey));
},
detail: function(songId, callback) {
var url = '/weapi/v3/song/detail?csrf_token=';
var data = {
c:
JSON.stringify([{
id: songId
}
])
};
this.encrypt_request(callback, url, data);
},
lrc: function(songId, callback) {
var url = '/weapi/song/lyric?csrf_token=';
var data = {
id: songId,
lv: -1,
tv: -1
};
this.encrypt_request(callback, url, data);
},
newsong: function(songId, callback) {
var url = '/weapi/song/enhance/player/url?csrf_token=';
var data = {
ids: [songId],
br: 999000,
};
this.encrypt_request(callback, url, data);
},
mv: function(mvId, callback) {
var url = '/weapi/mv/detail/';
var data = {
id: mvId,
};
this.encrypt_request(callback, url, data);
},
};
var innerFrame = document.querySelector('iframe');
var pages = [
{
url: 'music.163.com/#/song?id=',
handler: function() {
var songId = location.href.match(/id=([0-9]+)/)[1];
var downloadLine = this.createDownloadLine(songId);
var innerFrameDoc = innerFrame.contentWindow.document;
var albumNode = innerFrameDoc.querySelectorAll('p.des.s-fc4')[1];
var parentNode = albumNode.parentNode;
parentNode.insertBefore(downloadLine, albumNode.nextElementSibling);
},
createDownloadLine: function(songId) {
var disableStyle = function(link) {
link.text += '(无)';
link.style.color = 'gray';
link.style.textDecoration = 'none';
link.style.cursor = 'auto';
};
var setUrlAndSize = function(mp3Link, Music) {
if (Music) {
var href = Music.url;
if (href) {
mp3Link.href = href;
mp3Link.text += (Music.size / 1024 / 1024).toFixed(1) + 'M';
return;
}
}
disableStyle(mp3Link);
};
var setLyric = function(LycLink, result) {
var LrC = '';
var lrc = result.lrc;
var tlrc = result.tlyric;
var num = 0;
if (lrc && lrc.lyric) {
LrC += lrc.lyric + '\n';
num+=1;}
if (tlrc && tlrc.lyric) {
LrC += tlrc.lyric;
num+=2;}
if (num != 0) {
var html = '';
switch (num) {
case 1:html="(原)";break;
case 2:html="(译)";break;
case 3:html="(合)";break;
}
LycLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(LrC);
LycLink.innerHTML += html;
} else {
disableStyle(LycLink);
}
};
var newMp3Link = this.createLink('歌曲');
var lyricLink = this.createLink('歌词');
var mvLink = this.createLink('mv');
var picLink = this.createLink('封面');
api.detail(songId, function (result) {
var song = result.songs[0];
if (song.mv) {
api.mv(song.mv, function (result) {
var mv = result.data.brs;
mvLink.href = mv[720] || mv[480] || mv[240];
});
}
else {
disableStyle(mvLink);
};
if (song.al.pic_str || song.al.pic) {
var img = innerFrame.contentWindow.document.querySelector(".j-img");
picLink.href = img.dataset["src"] = api.getTrackURL(song.al.pic_str || song.al.pic);
img.src = img.dataset["src"] + "?param=130y130";
} else {
disableStyle(picLink);
};
});
api.newsong(songId, function (result) {
var song = result.data[0];
setUrlAndSize(newMp3Link, song);
});
api.lrc(songId, function (result) {
setLyric(lyricLink, result);
});
var container = this.createLineContainer('下载');
container.appendChild(newMp3Link);
container.appendChild(lyricLink);
container.appendChild(mvLink);
container.appendChild(picLink);
return container;
},
createLink: function(label) {
var link = document.createElement('a');
link.innerHTML = label;
link.className = 's-fc7';
link.style.marginRight = '10px';
link.href = 'javascript:void(0);';
link.target = '_blank';
return link;
},
createLineContainer: function(label) {
var container = document.createElement('p');
container.className = 'desc s-fc4';
container.innerHTML = label + ':';
container.style.margin = '10px 0';
return container;
},
},
];
if (innerFrame) {
innerFrame.addEventListener('load', function () {
var i, page;
for (i = 0; i < pages.length; i += 1) {
page = pages[i];
if (location.href.indexOf(page.url) != -1) {
page.handler();
}
}
});
}
document.cookie = 'os=linux';