网易云音乐 - 显示歌单中的所有歌曲

显示歌单中的所有歌曲

目前为 2020-06-24 提交的版本。查看 最新版本

// ==UserScript==
// @name                CloudMusic - Show all songs on the playlist
// @name:zh-CN          网易云音乐 - 显示歌单中的所有歌曲
// @namespace           https://gf.qytechs.cn/zh-CN/users/193133-pana
// @homepage            https://www.sailboatweb.com
// @version             1.0.1
// @description         Show all songs in the playlist
// @description:zh-CN   显示歌单中的所有歌曲
// @author              pana
// @license             GNU General Public License v3.0 or later
// @match               *://music.163.com/*
// @connect             api.imjad.cn
// @connect             music.163.com
// @grant               GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';
    class Basic_Obj {
        constructor(id, name) {
            this.id = id;
            this.name = name;
        }
        getId() {
            return this.id;
        }
        getName() {
            return this.name;
        }
    }
    class Song_Obj extends Basic_Obj {
        constructor(song_id, song_name, play_time, mvid = 0, no_copyright_rcmd = null, alias = null, trans_name = null) {
            super(song_id, song_name);
            this.playTime = play_time;
            this.mvid = mvid;
            this.noCopyrightRcmd = no_copyright_rcmd;
            this.alias = alias;
            this.transName = trans_name;
        }
        getPlayTime() {
            let time = '';
            let seconds = Math.round(this.playTime / 1000);
            if ((seconds / 3600) >= 1) {
                time += Math.floor(seconds / 3600) + ":";
            }
            seconds %= 3600;
            if ((seconds / 60) >= 1) {
                if ((seconds / 60) > 9) {
                    time += Math.floor(seconds / 60) + ":";
                } else {
                    time += "0" + Math.floor(seconds / 60).toString() + ":";
                }
            }
            seconds %= 60;
            if (seconds >= 10) {
                time += seconds;
            } else {
                time += "0" + seconds.toString();
            }
            return time;
        }
        getMvid() {
            return this.mvid;
        }
        getAliasName() {
            if (this.alias) {
                return this.alias[0];
            }
            return null;
        }
        getTransName() {
            return this.transName;
        }
        isExistsMv() {
            if (this.mvid > 0) {
                return true;
            }
            return false;
        }
        isNoCopyright() {
            if (this.noCopyrightRcmd) {
                return true;
            }
            return false;
        }
    }
    class Aritst_Obj extends Basic_Obj {
        constructor(aritst_id, aritst_name) {
            super(aritst_id, aritst_name);
        }
    }
    class Album_Obj extends Basic_Obj {
        constructor(album_id, album_name, pic_url) {
            super(album_id, album_name);
            this.picUrl = pic_url;
        }
        getPicUrl() {
            return this.picUrl;
        }
    }
    class Music_Obj {
        constructor(playlist_id, song_obj, aritst_arr, album_obj) {
            this.playlistId = playlist_id;
            this.song = song_obj;
            this.aritst = aritst_arr;
            this.album = album_obj;
        }
        createTableItem(position, is_even = false) {
            let tr = document.createElement('tr');
            tr.id = this.song.getId().toString() + Date.now().toString();
            if (is_even) {
                tr.classList.add('even');
            }
            if (this.song.isNoCopyright()) {
                tr.classList.add('js-dis');
            }
            let aritst_name = '';
            this.aritst.forEach((item) => {
                if (aritst_name) {
                    aritst_name += "/" + item.getName();
                } else {
                    aritst_name = item.getName();
                }
            });
            let td_0 = document.createElement('td');
            td_0.className = 'left';
            let td_0_div = document.createElement('div');
            td_0_div.className = 'hd';
            let td_0_div_span_0 = document.createElement('span');
            td_0_div_span_0.className = 'ply';
            td_0_div_span_0.setAttribute('data-res-id', this.song.getId());
            td_0_div_span_0.setAttribute('data-res-type', '18');
            td_0_div_span_0.setAttribute('data-res-action', 'play');
            td_0_div_span_0.setAttribute('data-res-from', '13');
            td_0_div_span_0.setAttribute('data-res-data', this.playlistId);
            let td_0_div_span_1 = document.createElement('span');
            td_0_div_span_1.className = 'num';
            td_0_div_span_1.textContent = position;
            td_0_div.appendChild(td_0_div_span_0);
            td_0_div.appendChild(td_0_div_span_1);
            td_0.appendChild(td_0_div);
            let alias_name = '';
            let song_title = '';
            if (this.song.isExistsMv()) {
                song_title = this.song.getName();
            } else if (this.song.getTransName()) {
                alias_name = this.song.getTransName();
                song_title = this.song.getName() + ' - (' +  this.song.getTransName() + ')';
            } else if (this.song.getAliasName()) {
                alias_name = this.song.getAliasName();
                song_title = this.song.getName() + ' - (' + this.song.getAliasName() + ')';
            } else {
                song_title = this.song.getName();
            }
            let td_1 = document.createElement('td');
            let td_1_div = document.createElement('div');
            td_1_div.className = 'f-cb';
            let td_1_div_div = document.createElement('div');
            td_1_div_div.className = 'tt';
            let td_1_div_div_div = document.createElement('div');
            td_1_div_div_div.className = 'ttc';
            let td_1_div_div_div_span = document.createElement('span');
            td_1_div_div_div_span.className = 'txt';
            let td_1_div_div_div_span_a = document.createElement('a');
            td_1_div_div_div_span_a.href = '/song?id=' + this.song.getId();
            let td_1_div_div_div_span_a_b = document.createElement('b');
            td_1_div_div_div_span_a_b.textContent = this.song.getName();
            td_1_div_div_div_span_a_b.title = song_title;
            td_1_div_div_div_span_a.appendChild(td_1_div_div_div_span_a_b);
            td_1_div_div_div_span.appendChild(td_1_div_div_div_span_a);
            td_1_div_div_div.appendChild(td_1_div_div_div_span);
            td_1_div_div.appendChild(td_1_div_div_div);
            td_1_div.appendChild(td_1_div_div);
            td_1.appendChild(td_1_div);
            if (this.song.isExistsMv()) {
                let td_1_div_div_div_span_span = document.createElement('span');
                td_1_div_div_div_span_span.className = 'mv';
                td_1_div_div_div_span_span.textContent = 'MV';
                td_1_div_div_div_span_span.title = '播放mv';
                td_1_div_div_div_span_span.setAttribute('data-res-id', this.song.getId());
                td_1_div_div_div_span_span.setAttribute('data-res-action', 'mv');
                td_1_div_div_div_span_span.addEventListener('click', () => {
                    window.parent.location.href = '/mv?id=' + this.song.getMvid();
                });
                td_1_div_div_div_span.appendChild(td_1_div_div_div_span_span);
            } else if (alias_name) {
                let td_1_div_div_div_span_span = document.createElement('span');
                td_1_div_div_div_span_span.className = 's-fc8';
                td_1_div_div_div_span_span.title = alias_name;
                td_1_div_div_div_span_span.textContent = ' - (' + alias_name + ')';
                td_1_div_div_div_span.appendChild(td_1_div_div_div_span_span);
            }
            let td_2 = document.createElement('td');
            td_2.className = 's-fc3';
            let td_2_span = document.createElement('span');
            td_2_span.className = 'u-dur';
            td_2_span.textContent = this.song.getPlayTime();
            let td_2_div = document.createElement('div');
            td_2_div.className = 'opt hshow';
            let td_2_div_a = document.createElement('a');
            td_2_div_a.className = 'u-icn u-icn-81 icn-add';
            td_2_div_a.href = 'javascript:;';
            td_2_div_a.title = '添加到播放列表';
            td_2_div_a.setAttribute('hidefocus', 'true');
            td_2_div_a.setAttribute('data-res-type', '18');
            td_2_div_a.setAttribute('data-res-id', this.song.getId());
            td_2_div_a.setAttribute('data-res-action', 'addto');
            td_2_div_a.setAttribute('data-res-from', '13');
            td_2_div_a.setAttribute('data-res-data', this.playlistId);
            let td_2_div_span_0 = document.createElement('span');
            td_2_div_span_0.className = 'icn icn-fav';
            td_2_div_span_0.title = '收藏';
            td_2_div_span_0.setAttribute('data-res-id', this.song.getId());
            td_2_div_span_0.setAttribute('data-res-type', '18');
            td_2_div_span_0.setAttribute('data-res-action', 'fav');
            let td_2_div_span_1 = document.createElement('span');
            td_2_div_span_1.className = 'icn icn-share';
            td_2_div_span_1.title = '分享';
            td_2_div_span_1.textContent = '分享';
            td_2_div_span_1.setAttribute('data-res-id', this.song.getId());
            td_2_div_span_1.setAttribute('data-res-type', '18');
            td_2_div_span_1.setAttribute('data-res-action', 'share');
            td_2_div_span_1.setAttribute('data-res-name', this.song.getName());
            td_2_div_span_1.setAttribute('data-res-author', aritst_name);
            td_2_div_span_1.setAttribute('data-res-pic', this.album.getPicUrl());
            let td_2_div_span_2 = document.createElement('span');
            td_2_div_span_2.className = 'icn icn-dl';
            td_2_div_span_2.title = '下载';
            td_2_div_span_2.setAttribute('data-res-id', this.song.getId());
            td_2_div_span_2.setAttribute('data-res-type', '18');
            td_2_div_span_2.setAttribute('data-res-action', 'download');
            td_2_div.appendChild(td_2_div_a);
            td_2_div.appendChild(td_2_div_span_0);
            td_2_div.appendChild(td_2_div_span_1);
            td_2_div.appendChild(td_2_div_span_2);
            td_2.appendChild(td_2_span);
            td_2.appendChild(td_2_div);
            let td_3 = document.createElement('td');
            let td_3_div = document.createElement('div');
            td_3_div.className = 'text';
            td_3_div.title = aritst_name;
            let td_3_div_span = document.createElement('span');
            td_3_div_span.title = aritst_name;
            this.aritst.forEach((item, index) => {
                let td_3_div_span_a = document.createElement('a');
                td_3_div_span_a.href = '/aritst?id=' + item.getId();
                td_3_div_span_a.textContent = item.getName();
                td_3_div_span_a.setAttribute('hidefocus', 'true');
                td_3_div_span.appendChild(td_3_div_span_a);
                if (index > 0) {
                    td_3_div_span_a.before("/");
                }
            });
            td_3_div.appendChild(td_3_div_span);
            td_3.appendChild(td_3_div);
            let td_4 = document.createElement('td');
            let td_4_div = document.createElement('div');
            td_4_div.className = 'text';
            let td_4_div_a = document.createElement('a');
            td_4_div_a.title = this.album.getName();
            td_4_div_a.textContent = this.album.getName();
            td_4_div_a.href = '/album?id=' + this.album.getId();
            td_4_div.appendChild(td_4_div_a);
            td_4.appendChild(td_4_div);
            tr.appendChild(td_0);
            tr.appendChild(td_1);
            tr.appendChild(td_2);
            tr.appendChild(td_3);
            tr.appendChild(td_4);
            return tr;
        }
    }
    function get_Music_Info(music_id) {
        return new Promise(function(resolve, _reject) {
            let music_details = {
                'method': 'GET',
                'url': 'http://music.163.com/api/song/detail/?id=' + music_id + '&ids=%5B' + music_id + '%5D',
                'headers': {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                'responseType': 'json',
                'onload': function(res) {
                    if (res.status == 200 && res.readyState == 4) {
                        resolve(res.response);
                    } else {
                        console.warn('返回的歌曲信息状态码异常。code: ' + res.status + ' readyState: ' + res.readyState);
                        resolve(null);
                    }
                },
                'onerror': function() {
                    console.error('获取歌曲信息出错!id:', music_id);
                    resolve(null);
                }
            };
            GM_xmlhttpRequest(music_details);
        });
    }
    async function main_Cloud_Music(playlist_obj, callback) {
        let record_arr = [];
        document.querySelectorAll('#song-list-pre-cache tbody tr').forEach((item) => {
            record_arr.push(item.id.replace(/\d{13}$/, ''));
        });
        let position = record_arr.length;
        for (let ele of playlist_obj.playlist.trackIds) {
            if (! record_arr.includes(ele.id.toString())) {
                await get_Music_Info(ele.id).then((data) => {
                    if (data) {
                        if (data.code == 200) {
                            position ++;
                            let music_info = data.songs[0];
                            let song_obj = new Song_Obj(music_info.id ,music_info.name, music_info.duration, music_info.mvid, music_info.noCopyrightRcmd, music_info.alias, music_info.transName);
                            let aritst_arr = [];
                            for (let a_ele of music_info.artists) {
                                let artist_obj = new Aritst_Obj(a_ele.id, a_ele.name);
                                aritst_arr.push(artist_obj);
                            }
                            let album_obj = new Album_Obj(music_info.album.id, music_info.album.name, music_info.album.picUrl);
                            let music_obj = new Music_Obj(ele.id ,song_obj, aritst_arr, album_obj);
                            if (document.querySelector('#song-list-pre-cache tbody')) {
                                document.querySelector('#song-list-pre-cache tbody').appendChild(music_obj.createTableItem(position, (position % 2 === 1)));
                            }
                        }
                    }
                });
            }
        }
        if (typeof(callback) === 'function') {
            callback();
        }
    }
    function init_Cloud_Music() {
        if (location.href.indexOf('/playlist?id=') !== -1) {
            if (document.getElementById('m-playlist')) {
                document.querySelectorAll('.soil').forEach((item) => {
                    item.parentNode.removeChild(item);
                });
                let playlist_id = '';
                if (document.getElementById('content-operation')) {
                    playlist_id = document.getElementById('content-operation').getAttribute('data-rid');
                }
                if (playlist_id) {
                    let show_text = null;
                    if (document.querySelector('.m-playlist-see-more .text')) {
                        show_text = document.querySelector('.m-playlist-see-more .text');
                        show_text.textContent = '正在获取歌单信息,请稍等...';
                    }
                    let details = {
                        'method': 'GET',
                        'url': 'https://api.imjad.cn/cloudmusic/?type=playlist&id=' + playlist_id,
                        'headers': {
                            'Content-Type': 'application/x-www-form-urlencoded'
                        },
                        'responseType': 'json',
                        'onload': function(res) {
                            if (res.status == 200 && res.readyState == 4) {
                                let playlist_obj = res.response;
                                if (playlist_obj.code == 200) {
                                    if (show_text) {
                                        show_text.textContent = '已经获取歌单信息,正在创建歌曲条目,请稍等...';
                                    }
                                    main_Cloud_Music(playlist_obj, () => {
                                        if (document.querySelector('.m-playlist-see-more')) {
                                            let show_module = document.querySelector('.m-playlist-see-more');
                                            show_module.parentNode.removeChild(show_module);
                                        }
                                    });
                                }
                            } else {
                                if (show_text) {
                                    show_text.textContent = '返回的歌单信息状态码异常。code: ' + res.status + ' readyState: ' + res.readyState;
                                }
                                console.warn('返回的歌单信息状态码异常。code: ' + res.status + ' readyState: ' + res.readyState);
                            }
                        },
                        'onerror': function() {
                            if (show_text) {
                                show_text.textContent = '获取歌单信息失败了!可能是网络不佳或者 API 失效了。';
                            }
                            console.error('获取歌单信息失败了!\n可能是网络不佳或者 API 失效了。');
                        }
                    };
                    GM_xmlhttpRequest(details);
                }
            }
        }
    }
    init_Cloud_Music();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址