From 21279bf500ce8857bad6dea4c5530d589a17e718 Mon Sep 17 00:00:00 2001 From: "wuhao.igno" Date: Wed, 16 Aug 2023 18:03:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E8=BF=81=E7=A7=BB=20bilibili=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=88=B0=E5=8F=AF=E7=94=A8=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/provider/bilibili.js | 169 +++++++++++++++++++++++++++++++++------- js/vendor/md5.min.js | 2 + listen1.html | 1 + manifest.json | 1 + manifest_firefox.json | 1 + 5 files changed, 145 insertions(+), 29 deletions(-) create mode 100644 js/vendor/md5.min.js diff --git a/js/provider/bilibili.js b/js/provider/bilibili.js index 0dfbf4e8..51a12081 100644 --- a/js/provider/bilibili.js +++ b/js/provider/bilibili.js @@ -1,3 +1,4 @@ +let wbi_key = null; /* global getParameterByName */ // eslint-disable-next-line no-unused-vars /* global cookieSet cookieGet */ @@ -8,6 +9,102 @@ class bilibili { return parser.parseFromString(value, 'text/html').body.textContent; } + static fetch_wbi_key() { + return axios({ + url: 'https://api.bilibili.com/x/web-interface/nav', + method: 'get', + responseType: 'json', + }).then((resp) => { + const json_content = resp.data; + const { img_url } = json_content.data.wbi_img; + const { sub_url } = json_content.data.wbi_img; + return { + img_key: img_url.slice( + img_url.lastIndexOf('/') + 1, + img_url.lastIndexOf('.') + ), + sub_key: sub_url.slice( + sub_url.lastIndexOf('/') + 1, + sub_url.lastIndexOf('.') + ), + }; + }); + } + + static clear_wbi_key() { + wbi_key = null; + } + + static get_wbi_key() { + if (wbi_key) { + return Promise.resolve(wbi_key); + } + return bilibili.fetch_wbi_key().then((key) => { + wbi_key = key; + return key; + }); + } + + static enc_wbi(params) { + return bilibili.get_wbi_key().then(({ img_key, sub_key }) => { + const mixinKeyEncTab = [ + 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, + 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, + 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, + 57, 62, 11, 36, 20, 34, 44, 52, + ]; + + // 对 imgKey 和 subKey 进行字符顺序打乱编码 + function get_mixin_key(original) { + let temp = ''; + mixinKeyEncTab.forEach((n) => { + temp += original[n]; + }); + return temp.slice(0, 32); + } + + const mixin_key = get_mixin_key(img_key + sub_key); + const curr_time = Math.round(Date.now() / 1000); + const chr_filter = /[!'()*]/g; + const query = []; + Object.assign(params, { wts: curr_time }); // 添加 wts 字段 + // 按照 key 重排参数 + Object.keys(params) + .sort() + .forEach((key) => { + query.push( + `${encodeURIComponent(key)}=${encodeURIComponent( + // 过滤 value 中的 "!'()*" 字符 + params[key].toString().replace(chr_filter, '') + )}` + ); + }); + const query_string = query.join('&'); + const wbi_sign = window.md5(query_string + mixin_key); // 计算 w_rid + return `${query_string}&w_rid=${wbi_sign}`; + }); + } + + static wrap_wbi_request(url, params) { + return bilibili + .enc_wbi(params) + .then((query_string) => { + const target_url = `${url}?${query_string}`; + return axios.get(target_url); + }) + .catch(() => { + // 失败时进行一次清空 wbi_key 后的重试,避免因为 wbi_key 过期导致的错误 + bilibili.clear_wbi_key(); + return bilibili + .enc_wbi(params) + .then((query_string) => { + const target_url = `${url}?${query_string}`; + return axios.get(target_url); + }) + .catch(() => undefined); + }); + } + static bi_convert_song(song_info) { const track = { id: `bitrack_${song_info.id}`, @@ -131,7 +228,7 @@ class bilibili { const author = response.data.data.owner; const default_img = response.data.data.pic; const tracks = response.data.data.pages.map((item) => - this.bi_convert_song3(item,track_id,author,default_img) + this.bi_convert_song3(item, track_id, author, default_img) ); return fn({ tracks, @@ -142,9 +239,9 @@ class bilibili { }; } - static bi_convert_song3(song_info,bvid,author,default_img) { + static bi_convert_song3(song_info, bvid, author, default_img) { let imgUrl = song_info.first_frame; - if (imgUrl === undefined){ + if (imgUrl === undefined) { imgUrl = default_img; } else if (imgUrl.startsWith('//')) { imgUrl = `https:${imgUrl}`; @@ -166,37 +263,51 @@ class bilibili { return { success: (fn) => { - let target_url = `https://api.bilibili.com/x/space/acc/info?mid=${artist_id}&jsonp=jsonp`; - axios.get(target_url).then((response) => { - const info = { - cover_img_url: response.data.data.face, - title: response.data.data.name, - id: `biartist_${artist_id}`, - source_url: `https://space.bilibili.com/${artist_id}/#/audio`, - }; - if (getParameterByName('list_id', url).split('_').length === 3) { - target_url = `https://api.bilibili.com/x/space/arc/search?mid=${artist_id}&pn=1&ps=25&order=click&index=1&jsonp=jsonp`; + let target_url; + bilibili + .wrap_wbi_request('https://api.bilibili.com/x/space/wbi/acc/info', { + mid: artist_id, + }) + .then((response) => { + const info = { + cover_img_url: response.data.data.face, + title: response.data.data.name, + id: `biartist_${artist_id}`, + source_url: `https://space.bilibili.com/${artist_id}/#/audio`, + }; + if (getParameterByName('list_id', url).split('_').length === 3) { + return bilibili + .wrap_wbi_request( + 'https://api.bilibili.com/x/space/wbi/arc/search', + { + mid: artist_id, + pn: 1, + ps: 25, + order: 'click', + index: 1, + } + ) + .then((res) => { + const tracks = res.data.data.list.vlist.map((item) => + this.bi_convert_song2(item) + ); + return fn({ + tracks, + info, + }); + }); + } + target_url = `https://api.bilibili.com/audio/music-service-c/web/song/upper?pn=1&ps=0&order=2&uid=${artist_id}`; return axios.get(target_url).then((res) => { - const tracks = res.data.data.list.vlist.map((item) => - this.bi_convert_song2(item) + const tracks = res.data.data.data.map((item) => + this.bi_convert_song(item) ); return fn({ tracks, info, }); }); - } - target_url = `https://api.bilibili.com/audio/music-service-c/web/song/upper?pn=1&ps=0&order=2&uid=${artist_id}`; - return axios.get(target_url).then((res) => { - const tracks = res.data.data.data.map((item) => - this.bi_convert_song(item) - ); - return fn({ - tracks, - info, - }); }); - }); }, }; } @@ -225,14 +336,14 @@ class bilibili { let bvid = track.id.slice('bitrack_v_'.length); const trackIdCheck = trackId.split('-'); - if(trackIdCheck.length > 1){ + if (trackIdCheck.length > 1) { bvid = trackIdCheck[0].slice('bitrack_v_'.length); } const target_url = `https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`; return axios.get(target_url).then((response) => { let { cid } = response.data.data.pages[0]; - if(trackIdCheck.length > 1){ - [,cid] = trackIdCheck; + if (trackIdCheck.length > 1) { + [, cid] = trackIdCheck; } const target_url2 = `http://api.bilibili.com/x/player/playurl?fnval=16&bvid=${bvid}&cid=${cid}`; axios.get(target_url2).then((response2) => { diff --git a/js/vendor/md5.min.js b/js/vendor/md5.min.js new file mode 100644 index 00000000..f414e7c6 --- /dev/null +++ b/js/vendor/md5.min.js @@ -0,0 +1,2 @@ +!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((u=d(d(t,n),d(e,u)))<>>32-o,r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function c(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return i(c(a(n=r(n)),8*n.length))}function u(n,t){return function(n,t){var r,e=a(n),o=[],u=[];for(o[15]=u[15]=void 0,16 + diff --git a/manifest.json b/manifest.json index b17c45be..a813528f 100644 --- a/manifest.json +++ b/manifest.json @@ -2,6 +2,7 @@ "background": { "scripts": [ "js/vendor/axios.min.js", + "js/vendor/md5.min.js", "js/vendor/forge_listen1_fork.min.js", "js/github.js", diff --git a/manifest_firefox.json b/manifest_firefox.json index 6731af01..dc4c747d 100644 --- a/manifest_firefox.json +++ b/manifest_firefox.json @@ -8,6 +8,7 @@ "background": { "scripts": [ "js/vendor/axios.min.js", + "js/vendor/md5.min.js", "js/github.js", "js/background.js", "js/vendor/howler.core.min.js", From 52a933de4f8482f7afcece0b81345330d352d036 Mon Sep 17 00:00:00 2001 From: "wuhao.igno" Date: Wed, 16 Aug 2023 19:37:30 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E8=8E=B7=E5=8F=96=20playlist=20?= =?UTF-8?q?=E6=88=90=E5=8A=9F=E5=90=8E=E6=89=8B=E5=8A=A8=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E8=84=8F=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/controller/navigation.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/controller/navigation.js b/js/controller/navigation.js index 101db77e..4e32d49e 100644 --- a/js/controller/navigation.js +++ b/js/controller/navigation.js @@ -195,7 +195,9 @@ angular.module('listenone').controller('NavigationController', [ $scope.is_local = data.info.id.slice(0, 2) === 'lm'; MediaService.queryPlaylist(data.info.id, 'favorite').success((res) => { + // success 函数可能在异步回调中执行,需要手动触发脏检查 $scope.is_favorite = res.result; + $scope.$digest(); }); $scope.window_type = 'list'; From 3824703e779d4aaac2c0b97bb1261782d46c4388 Mon Sep 17 00:00:00 2001 From: "wuhao.igno" Date: Thu, 17 Aug 2023 11:00:05 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8=20$timeout=20?= =?UTF-8?q?=E6=9B=BF=E4=BB=A3=20$digest=20=E9=81=BF=E5=85=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=8F=98=E6=9B=B4=E5=9C=BA=E6=99=AF=E4=B8=8B=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/controller/navigation.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/controller/navigation.js b/js/controller/navigation.js index 4e32d49e..ca5c6994 100644 --- a/js/controller/navigation.js +++ b/js/controller/navigation.js @@ -196,8 +196,9 @@ angular.module('listenone').controller('NavigationController', [ MediaService.queryPlaylist(data.info.id, 'favorite').success((res) => { // success 函数可能在异步回调中执行,需要手动触发脏检查 - $scope.is_favorite = res.result; - $scope.$digest(); + $timeout(() => { + $scope.is_favorite = res.result; + }, 0); }); $scope.window_type = 'list'; From f9d32a82ad21569fe53df0d331ee411d6f9a6d4a Mon Sep 17 00:00:00 2001 From: "wuhao.igno" Date: Mon, 18 Dec 2023 11:18:44 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20forge=20=E6=8F=90=E4=BE=9B=20md5=20=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/provider/bilibili.js | 6 +++++- js/vendor/md5.min.js | 2 -- listen1.html | 1 - manifest.json | 1 - manifest_firefox.json | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 js/vendor/md5.min.js diff --git a/js/provider/bilibili.js b/js/provider/bilibili.js index 51a12081..b3b4e85b 100644 --- a/js/provider/bilibili.js +++ b/js/provider/bilibili.js @@ -80,7 +80,11 @@ class bilibili { ); }); const query_string = query.join('&'); - const wbi_sign = window.md5(query_string + mixin_key); // 计算 w_rid + const wbi_sign = window.forge.md5 + .create() + .update(window.forge.util.encodeUtf8(query_string + mixin_key)) + .digest() + .toHex(); return `${query_string}&w_rid=${wbi_sign}`; }); } diff --git a/js/vendor/md5.min.js b/js/vendor/md5.min.js deleted file mode 100644 index f414e7c6..00000000 --- a/js/vendor/md5.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((u=d(d(t,n),d(e,u)))<>>32-o,r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function c(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return i(c(a(n=r(n)),8*n.length))}function u(n,t){return function(n,t){var r,e=a(n),o=[],u=[];for(o[15]=u[15]=void 0,16 - diff --git a/manifest.json b/manifest.json index a813528f..b17c45be 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,6 @@ "background": { "scripts": [ "js/vendor/axios.min.js", - "js/vendor/md5.min.js", "js/vendor/forge_listen1_fork.min.js", "js/github.js", diff --git a/manifest_firefox.json b/manifest_firefox.json index dc4c747d..6731af01 100644 --- a/manifest_firefox.json +++ b/manifest_firefox.json @@ -8,7 +8,6 @@ "background": { "scripts": [ "js/vendor/axios.min.js", - "js/vendor/md5.min.js", "js/github.js", "js/background.js", "js/vendor/howler.core.min.js",