n374 / dmusic-plugin-NeteaseCloudMusic

NeteaseCloudMusic Plugin for Deepin Music Player
https://wu.nerd.moe/?p=1861
203 stars 45 forks source link

Ubuntu 15.04下不能搜索 #6

Open nickirk opened 9 years ago

nickirk commented 9 years ago

报错如下:

File "/home/user/.local/share/deepin-music-player/plugins/neteasecloudmusic/netease_music_browser.py", line 68, in search nplayer.search(string)], clear_first=True) TypeError: 'NoneType' object is not iterable

n374 commented 9 years ago

应该是api获取搜索结果错误,return None造成的 176e9f5f6a481dc71cd60f3a6b19873d664a3b56 现在再试试

nickirk commented 9 years ago

谢谢努力,可是还是不能搜索,全部的log file如下。每点一次search都会新出现“INFO Starting new HTTP connection (1): music.163.com”,然后没有任何结果显示。PS:我已经在本地的dmusic-plugin-NeteaseCloudMusic文件夹里运行过

git pull
./install.py

了,所以应该是最新版本吧?

INFO Loading settings... INFO Loading application theme... INFO Loading MediaDB... INFO Initialize Gui... INFO MMKeys mode: gnome /usr/lib/python2.7/dist-packages/dtk/ui/utils.py:396: PangoWarning: pango_layout_set_markup_with_accel: Error on line 1: Entity did not end with a semicolon; most likely you used an ampersand character without intending to start an entity — escape ampersand as & layout.set_markup(text) INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com <class 'Xlib.protocol.request.QueryExtension'> Traceback (most recent call last): File "/usr/share/deepin-music/src/cover_download.py", line 127, in full_update self.init_album_missions() File "/usr/share/deepin-music/src/cover_download.py", line 195, in init_album_missions albums = self.get_infos_from_db("album") File "/usr/share/deepin-music/src/cover_download.py", line 176, in get_infos_from_db if not os.path.exists(get_cover_save_path("%s-%s" % (artist_name, album_name))): File "/usr/lib/python2.7/genericpath.py", line 26, in exists os.stat(path) TypeError: must be encoded string without NULL bytes, not str INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com INFO Starting new HTTP connection (1): music.163.com Traceback (most recent call last): File "/usr/bin/deepin-music-player", line 270, in DeepinMusicApp() File "/usr/bin/deepin-music-player", line 71, in __init mainloop() File "/usr/share/deepin-music/src/widget/instance.py", line 70, in mainloop gtk.main() KeyboardInterrupt

n374 commented 9 years ago

我在虚拟机里装了15.04试了下 能正常搜索

按照描述,点Search,有终端显示,无界面显示 我在 3a636947b723dafb8e0477e24e6e04abafd1d775 中加入了些print提示,麻烦再git pull &&./install 看看是否没能正确获取搜索结果

同时下方这个错误提示是点Search时出现的么,我没法重现这个错误

Traceback (most recent call last):
File "/usr/share/deepin-music/src/cover_download.py", line 127, in full_update
self.init_album_missions()
File "/usr/share/deepin-music/src/cover_download.py", line 195, in init_album_missions
albums = self.get_infos_from_db("album")
File "/usr/share/deepin-music/src/cover_download.py", line 176, in get_infos_from_db
if not os.path.exists(get_cover_save_path("%s-%s" % (artist_name, album_name))):
File "/usr/lib/python2.7/genericpath.py", line 26, in exists
os.stat(path)
TypeError: must be encoded string without NULL bytes, not str
nickirk commented 9 years ago

这个错误不是点搜索时出现的,是开始运行程序就会报这个。我git pull && ./install后,再点击search,会报这个:

INFO     Starting new HTTP connection (1): music.163.com
search failed

具体什么原因,没有说明。

n374 commented 9 years ago

这表明Search api没有正确地返回结果。

麻烦在netease_api.py中的第266行,也就是result = self.httpRequest('POST', action, data)下方加入print result,用空格与其他行保持对齐。 如果返回的信息不多的话,麻烦贴出来,我需要确定什么地方出问题了

nickirk commented 9 years ago

按照你说的做了,结果如下

INFO     Starting new HTTP connection (1): music.163.com
{u'code': 200, u'result': u'35b1748964afb6f6ab00803a0762655b87b...', u'abroad': True}
search failed

其中的省略号省略了好几百行。。。希望对你有帮助。

n374 commented 9 years ago

那么把刚刚添加的那行删除,删除后在273-277行行头加#将其注释掉,在下方添加return songs 同时在268和270行下方添加print songs[0]['name'] 添加的内容用空格与其他行对齐,然后帖出返回内容

nickirk commented 9 years ago

按照你说的做了后,点击search后还是这样,没有其他的反馈。

INFO     Starting new HTTP connection (1): music.163.com
search failed
n374 commented 9 years ago

这应该就是api返回的数据有问题 麻烦重新clone, 在netease_api.py第266行下方添加print result,用空格对齐,将所有返回内容粘到http://paste.ubuntu.com/

n374 commented 9 years ago

根据回复时间nickirk应该是海外党吧 根据https://github.com/darknessomi/musicbox/issues/63#issuecomment-100265052描述从国外搜索返回的结果是加密的。 经测试并对比上面贴出的结果,应该就是这个原因。 综合最后云音乐客户端更新,以后api可能会加密了。

nickirk commented 9 years ago

原来是这个原因。。。囧。真的很佩服你debug的能力诶!太神奇了。。。连这个原因都能找出来。。。能加qq好友吗? :+1:

nickirk commented 9 years ago

api加密之后,那这个插件还能用吗?

n374 commented 9 years ago

这地方不适合贴私人信息,可以在Github主页找到邮箱

新版客户端使用的API参数好像都是加密过的,除非像之前歌曲加密代码一样被破解或泄露,不然无法使用。

咱还有网页版,目前使用的API和网页版使用的一致,在国内并没有加密。既然网页端能解密数据,那么合理推测还是有可能分析出解密用的JS之类的,从而将数据还原出来。 不过不懂HTML/JS,弄起来应该会很慢,不过应该会有人先分析出来。

Catofes commented 9 years ago

有, 可以分析,当时分析过一阵子,然后发现像是RSA, 最后放弃了。。。。。。

Catofes commented 9 years ago

我当时觉得数据是在这里得到的:

"search-list": {
            url: "/api/search/get/web", type: "post", format: function (cc, bf) {
                if (cc.abroad) {
                    try {
                        cc.result = JSON.parse(decodeURIComponent(settmusic(cc.result, bp.sk)))
                    } catch (e) {
                    }
                }
                cc.result = cc.result || {};

然后调用 settmusic 解码。 settmusic实现在下面。然后比较坑的是 bk.sk 貌似是密钥不知道从哪里得到的。

(function () {
    function bjQ() {
        var sy = function (iL) {
            if (iL < -128) {
                return sy(128 - (-128 - iL))
            } else if (iL >= -128 && iL <= 127) {
                return iL
            } else if (iL > 127) {
                return sy(-129 + iL - 127)
            } else {
                throw new Error("1001")
            }
        };
        var bjO = function (iL, cl) {
            return sy(iL + cl)
        };
        var bjK = function (Fy, LP) {
            if (Fy == null) {
                return null
            }
            if (LP == null) {
                return Fy
            }
            var lJ = [];
            var bjJ = LP.length;
            for (var i = 0, ck = Fy.length; i < ck; i++) {
                lJ[i] = bjO(Fy[i], LP[i % bjJ])
            }
            return lJ
        };
        var bjG = function (FF) {
            if (FF == null) {
                return FF
            }
            var lJ = [];
            var bjF = FF.length;
            for (var i = 0, ck = bjF; i < ck; i++) {
                lJ[i] = sy(0 - FF[i])
            }
            return lJ
        };
        var bjC = function (Mb, Cw) {
            Mb = sy(Mb);
            Cw = sy(Cw);
            return sy(Mb ^ Cw)
        };
        var bdh = function (CA, Mg) {
            if (CA == null || Mg == null || CA.length != Mg.length) {
                return CA
            }
            var lJ = [];
            var bjz = CA.length;
            for (var i = 0, ck = bjz; i < ck; i++) {
                lJ[i] = bjC(CA[i], Mg[i])
            }
            return lJ
        };
        var bdk = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
        var bjr = function (dE) {
            var wM = [];
            wM.push(bdk[dE >>> 4 & 15]);
            wM.push(bdk[dE & 15]);
            return wM.join("")
        };
        var bjp = function (tO) {
            var ck = tO.length;
            if (tO == null || ck < 0) {
                return new String("")
            }
            var wM = [];
            for (var i = 0; i < ck; i++) {
                wM.push(bjr(tO[i]))
            }
            return wM.join("")
        };
        var bdn = function (Gl) {
            if (Gl == null || Gl.length == 0) {
                return Gl
            }
            var Mv = new String(Gl);
            var lJ = [];
            var ck = Mv.length / 2;
            var cl = 0;
            for (var i = 0; i < ck; i++) {
                var ud = parseInt(Mv.charAt(cl++), 16) << 4;
                var tY = parseInt(Mv.charAt(cl++), 16);
                lJ[i] = sy(ud + tY)
            }
            return lJ
        };
        var bjl = function (dL) {
            if (dL == null || dL == undefined) {
                return dL
            }
            var CE = encodeURIComponent(dL);
            var tO = [];
            var bdq = CE.length;
            for (var i = 0; i < bdq; i++) {
                if (CE.charAt(i) == "%") {
                    if (i + 2 < bdq) {
                        tO.push(bdn(CE.charAt(++i) + "" + CE.charAt(++i))[0])
                    } else {
                        throw new Error("1009")
                    }
                } else {
                    tO.push(CE.charCodeAt(i))
                }
            }
            return tO
        };
        var bje = function (po) {
            var cQ = 0;
            cQ += (po[0] & 255) << 24;
            cQ += (po[1] & 255) << 16;
            cQ += (po[2] & 255) << 8;
            cQ += po[3] & 255;
            return cQ
        };
        var bzE = function (cQ) {
            var po = [];
            po[0] = cQ >>> 24 & 255;
            po[1] = cQ >>> 16 & 255;
            po[2] = cQ >>> 8 & 255;
            po[3] = cQ & 255;
            return po
        };
        var bjc = function (dW, ME, ck) {
            var pr = [];
            if (dW == null || dW.length == 0) {
                return pr
            }
            if (dW.length < ck) {
                throw new Error("1003")
            }
            for (var i = 0; i < ck; i++) {
                pr[i] = dW[ME + i]
            }
            return pr
        };
        var MI = function (dW, ME, GC, bja, ck) {
            if (dW == null || dW.length == 0) {
                return GC
            }
            if (GC == null) {
                throw new Error("1004")
            }
            if (dW.length < ck) {
                throw new Error("1003")
            }
            for (var i = 0; i < ck; i++) {
                GC[bja + i] = dW[ME + i]
            }
            return GC
        };
        var biV = function (ck) {
            var cK = [];
            for (var i = 0; i < ck; i++) {
                cK[i] = 0
            }
            return cK
        };
        var biU = [82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, 8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, 58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125];
        var wl = 64;
        var GQ = 64;
        var bdz = 4;
        var biS = function (lV) {
            var bdB = [];
            if (lV == null || lV == undefined || lV.length == 0) {
                return biV(GQ)
            }
            if (lV.length >= GQ) {
                return bjc(lV, 0, GQ)
            } else {
                for (var i = 0; i < GQ; i++) {
                    bdB[i] = lV[i % lV.length]
                }
            }
            return bdB
        };
        var biQ = function (GV) {
            if (GV == null || GV.length % wl != 0) {
                throw new Error("1005")
            }
            var MZ = [];
            var cl = 0;
            var biC = GV.length / wl;
            for (var i = 0; i < biC; i++) {
                MZ[i] = [];
                for (var j = 0; j < wl; j++) {
                    MZ[i][j] = GV[cl++]
                }
            }
            return MZ
        };
        var biA = function (bdV) {
            var ud = bdV >>> 4 & 15;
            var tY = bdV & 15;
            var cl = ud * 16 + tY;
            return biU[cl]
        };
        var bec = function (Ni) {
            if (Ni == null) {
                return null
            }
            var bed = [];
            for (var i = 0, ck = Ni.length; i < ck; i++) {
                bed[i] = biA(Ni[i])
            }
            return bed
        };
        var biq = function (vR, lV) {
            if (vR == null) {
                return null
            }
            if (vR.length == 0) {
                return []
            }
            if (vR.length % wl != 0) {
                throw new Error("1005")
            }
            lV = biS(lV);
            var Np = lV;
            var Nq = biQ(vR);
            var CR = [];
            var bip = Nq.length;
            for (var i = 0; i < bip; i++) {
                var Nw = bec(Nq[i]);
                Nw = bec(Nw);
                var Nx = bdh(Nw, Np);
                var bio = bjK(Nx, bjG(Np));
                Nx = bdh(bio, lV);
                MI(Nx, 0, CR, i * wl, wl);
                Np = Nq[i]
            }
            var bef = [];
            MI(CR, CR.length - bdz, bef, 0, bdz);
            var ck = bje(bef);
            if (ck > CR.length) {
                throw new Error("1006")
            }
            var lJ = [];
            MI(CR, 0, lJ, 0, ck);
            return lJ
        };
        var bii = function (Hg, bF) {
            if (Hg == null) {
                return null
            }
            var beo = new String(Hg);
            if (beo.length == 0) {
                return []
            }
            var vR = bdn(beo);
            if (bF == null || bF == undefined) {
                throw new Error("1007")
            }
            var lV = bjl(bF);
            return biq(vR, lV)
        };
        this.bhW = function (Hg, bF) {
            var bhU = bii(Hg, bF);
            var NH = new String(bjp(bhU));
            var Hi = [];
            var bhR = NH.length / 2;
            var cl = 0;
            for (var i = 0; i < bhR; i++) {
                Hi.push("%");
                Hi.push(NH.charAt(cl++));
                Hi.push(NH.charAt(cl++))
            }
            return Hi.join("")
        }
    }

    window.settmusic = (new bjQ).bhW
})();
n374 commented 9 years ago

不懂JS。。 这段是实现什么功能的?

Catofes commented 9 years ago

应该是对那一段加密过的result 进行解密。

n374 commented 9 years ago

那么能直接用这段js解密么

Catofes commented 9 years ago

理论上改写成python应该就可以用,不过解密的时候有两部分,

cc.result = JSON.parse(decodeURIComponent(settmusic(cc.result, bp.sk)))

cc.result 就是api请求返回的result, 不过bp.sk不知道是啥。 需要进一步的分析。

n374 commented 9 years ago

743698725955709841a431c0c60aad0ce4083300

参照https://github.com/darknessomi/musicbox/issues/63#issuecomment-105253788