本帖最后由 cxxjackie 于 2022-6-23 23:41 编辑
在歌单处点击+号将单曲添加至播放列表;点击播放按钮添加至播放列表并播放;点击上方“立即播放”将全部添加并播放。api就不用了,我平时不用酷我的。
// ==UserScript==
// @name 酷我音乐破解付费
// @description 直接播放酷我音乐的付费歌曲
// @namespace cxxjackie
// @author cxxjackie
// @version 1.1
// @match http*://www.kuwo.cn/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// 在这里填你的api,可以改post,加data、headers等属性,涉及跨域记得写@connect
function getSongUrl(rid) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: `https://www.example.com/api?id=${rid}`,
method: 'get',
onload: res => res.status === 200 ? resolve(res.responseText) : reject(res.status),
onerror: () => reject('error')
});
});
}
// 修改歌曲信息
async function hackSong(songinfo) {
songinfo.isListenFee = false;
songinfo.disable = false;
songinfo.notAutoplay = false;
songinfo.url = await getSongUrl(songinfo.rid);
songinfo.ishacked = true;
}
// 对每个符合selector的元素执行回调函数
function elementEach(selector, parent, callback) {
const elms = parent.querySelectorAll(selector);
elms.forEach(callback);
const mutationObserver = window.MutationObserver
|| window.WebkitMutationObserver
|| window.MozMutationObserver;
const matchesSelector = Element.prototype.matches
|| Element.prototype.matchesSelector
|| Element.prototype.webkitMatchesSelector
|| Element.prototype.msMatchesSelector
|| Element.prototype.mozMatchesSelector;
const observer = new mutationObserver(mutations => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode instanceof Element) {
let elms = addedNode.querySelectorAll(selector);
if (matchesSelector.call(addedNode, selector)) {
elms = [addedNode, ...elms];
}
elms.forEach(callback);
}
}
}
});
observer.observe(parent, {
childList: true,
subtree: true
});
}
// 主函数
function main() {
GM_addStyle('.page > .model_out{display: none !important;}');
const playControl = document.querySelector('.playControl');
if (!playControl) return;
const store = playControl.__vue__.$store;
const getPlayUrl = playControl.__vue__.getPlayUrl;
playControl.__vue__.getPlayUrl = function(songinfo) {
if (!songinfo.ishacked) {
if (songinfo.isListenFee || songinfo.disable) {
hackSong(songinfo).then(() => store.commit('song/changeSong', songinfo));
} else {
return getPlayUrl.call(this, songinfo);
}
} else {
// 这里有时会暂停播放,原因不明
setTimeout(() => {
if (!playControl.__vue__.playing) {
playControl.__vue__.songReady = true;
playControl.__vue__.togglePlaying();
}
}, 500);
}
};
if ('songlist/playAll' in store._mutations) {
const playAll = store._mutations['songlist/playAll'][0];
store._mutations['songlist/playAll'][0] = function() {
const task = [];
for (const songinfo of arguments[0].list) {
if (songinfo.isListenFee || songinfo.disable) {
task.push(hackSong(songinfo));
}
}
Promise.all(task).then(() => playAll.apply(this, arguments));
}
}
elementEach('.main_con', document, mainCon => {
if (mainCon.__vue__.songinfo && (mainCon.__vue__.songinfo.isListenFee || mainCon.__vue__.songinfo.disable)) {
hackSong(mainCon.__vue__.songinfo);
}
const div = mainCon.querySelector('.btns + div > div:nth-child(1)');
if (div && div.__vue__ && div.__vue__.list) {
elementEach('.song_item', mainCon, async songItem => {
const rid = songItem.querySelector('.song_name > a').href.split('/').pop();
const songinfo = div.__vue__.list.find(s => s.rid == rid);
if (songinfo) {
songItem.querySelector('.icon-icon_play_').addEventListener('click', async e => {
e.stopImmediatePropagation();
if (songinfo.isListenFee || songinfo.disable) {
await hackSong(songinfo);
}
store.commit('songlist/add', songinfo);
store.commit('song/changeSong', songinfo);
}, true);
songItem.querySelector('.icon-playlist_icon_add_').addEventListener('click', async e => {
e.stopImmediatePropagation();
if (songinfo.isListenFee || songinfo.disable) {
await hackSong(songinfo);
}
store.commit('songlist/add', songinfo);
}, true);
}
});
}
});
}
main();
})();