Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name 网易云音乐
- // @namespace http://tampermonkey.net/
- // @version 27.0
- // @description 解锁网页完全歌单,来自公开音源
- // @author YourName & Gemini
- // @match *://music.163.com/*
- // @grant GM_xmlhttpRequest
- // @grant unsafeWindow
- // @run-at document-start
- // ==/UserScript==
- (function() {
- 'use strict';
- // --- 新增: 设置Cookie ---
- // 强制将 os cookie 设置为 'pc',以获取桌面端体验
- document.cookie = 'os=pc; domain=.music.163.com; path=/; max-age=31536000';
- function log(message, ...args) {
- console.log(`[NCM Unlocker v27.0]`, message, ...args);
- }
- // --- API注入 ---
- const APIHooker = {
- hooks: [],
- originalOpen: XMLHttpRequest.prototype.open,
- originalSend: XMLHttpRequest.prototype.send,
- hook: function(urlMatcher, dealer) {
- this.hooks.push({ matcher: urlMatcher, dealer: dealer });
- },
- init: function() {
- const self = this;
- XMLHttpRequest.prototype.open = function(method, url, ...args) {
- this._hook = self.hooks.find(h => h.matcher.test(url));
- return self.originalOpen.apply(this, [method, url, ...args]);
- };
- XMLHttpRequest.prototype.send = function(...sendArgs) {
- if (this._hook) {
- const hook = this._hook;
- let originalOnReadyStateChange = this.onreadystatechange;
- this.onreadystatechange = function(...progressArgs) {
- if (this.readyState === 4 && this.status === 200) {
- hook.dealer(this, originalOnReadyStateChange, progressArgs);
- } else if (originalOnReadyStateChange) {
- originalOnReadyStateChange.apply(this, progressArgs);
- }
- };
- }
- return self.originalSend.apply(this, sendArgs);
- };
- }
- };
- // --- 核心逻辑 ---
- function main() {
- APIHooker.init();
- log('Cookie "os=pc" 已设置,注入器已初始化。');
- const requestState = {};
- // --- 按钮绕过 ---
- APIHooker.hook(
- /\/weapi\/(v3\/song\/detail|v1\/play\/record|v6\/playlist\/detail)/,
- (xhr, originalCallback, callbackArgs) => {
- try {
- let data = JSON.parse(xhr.responseText);
- let privilegesModified = false;
- const fixPrivilege = (p) => {
- if (p && (p.st !== 0 || p.fee > 0 || p.pl === 0)) {
- p.st = 0; p.fee = 0; p.pl = 320000; p.dl = 320000;
- p.plLevel = 'exhigh'; p.dlLevel = 'exhigh';
- privilegesModified = true;
- }
- };
- if (data.privileges) data.privileges.forEach(fixPrivilege);
- if (data.songs) data.songs.forEach(s => s.privilege && fixPrivilege(s.privilege));
- if (data.allData) data.allData.forEach(d => d.song && d.song.privilege && fixPrivilege(d.song.privilege));
- if (data.weekData) data.weekData.forEach(d => d.song && d.song.privilege && fixPrivilege(d.song.privilege));
- if (privilegesModified) {
- const modifiedText = JSON.stringify(data);
- Object.defineProperty(xhr, 'responseText', { value: modifiedText, writable: true });
- }
- } catch(e) { /* Silent fail */ }
- if (originalCallback) originalCallback.apply(xhr, callbackArgs);
- }
- );
- // --- 注入 ---
- APIHooker.hook(/\/weapi\/song\/enhance\/player\/url\/v1/, (xhr, originalCallback, callbackArgs) => {
- let originalResponse;
- try { originalResponse = JSON.parse(xhr.responseText); } catch (e) {
- if (originalCallback) originalCallback.apply(xhr, callbackArgs); return;
- }
- const songData = originalResponse.data[0];
- if (!songData || !songData.id || (songData.url && songData.code === 200)) {
- if (originalCallback) originalCallback.apply(xhr, callbackArgs); return;
- }
- if (requestState[songData.id] === 'processing') return;
- requestState[songData.id] = 'processing';
- GM_xmlhttpRequest({
- method: 'GET',
- url: `https://wyy-api-three.vercel.app/song/url?id=${songData.id}&quality=320k`,
- onload: function(response) {
- try {
- if (response.status === 200) {
- const customData = JSON.parse(response.responseText);
- const customUrl = customData.url;
- if (customUrl) {
- const fakeResponse = {
- data: [{ ...songData, url: customUrl, br: 320000, code: 200, type: 'mp3', fee: 0, md5: '0', level: 'exhigh', flag: 0 }],
- code: 200
- };
- const fakeResponseText = JSON.stringify(fakeResponse);
- Object.defineProperty(xhr, 'responseText', { value: fakeResponseText, writable: true });
- log(`✅ 音源注入成功 (ID: ${songData.id})`);
- }
- }
- } catch (e) { /* Silent fail */ }
- if (originalCallback) originalCallback.apply(xhr, callbackArgs);
- setTimeout(() => delete requestState[songData.id], 500);
- },
- onerror: function(e) {
- if (originalCallback) originalCallback.apply(xhr, callbackArgs);
- setTimeout(() => delete requestState[songData.id], 500);
- }
- });
- });
- }
- if (document.body) { main(); } else { new MutationObserver((_, obs) => { if (document.body) { obs.disconnect(); main(); } }).observe(document.documentElement, { childList: true }); }
- })();
Advertisement
Add Comment
Please, Sign In to add comment