Greasy Fork

Greasy Fork is available in English.

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

显示歌单中的所有歌曲

当前为 2020-06-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                CloudMusic - Show all songs on the playlist
// @name:zh-CN          网易云音乐 - 显示歌单中的所有歌曲
// @namespace           http://greasyfork.icu/zh-CN/users/193133-pana
// @homepage            https://www.sailboatweb.com
// @version             1.0.0
// @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;
        }
        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.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();
})();