m1.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // 小枸音乐
  2. "use strict";
  3. Object.defineProperty(exports, "__esModule", {value: true});
  4. const axios_1 = require("axios");
  5. const cheerio_1 = require("cheerio");
  6. const CryptoJs = require("crypto-js");
  7. const he = require("he");
  8. const pageSize = 20;
  9. function formatMusicItem(_) {
  10. var _a, _b, _c, _d, _e, _f, _g, _h, _i;
  11. return {
  12. id: (_d = _.FileHash) !== null && _d !== void 0 ? _d : _.Grp[0].FileHash,
  13. title: (_a = _.SongName) !== null && _a !== void 0 ? _a : _.OriSongName,
  14. artist: (_b = _.SingerName) !== null && _b !== void 0 ? _b : _.Singers[0].name,
  15. album: (_c = _.AlbumName) !== null && _c !== void 0 ? _c : _.Grp[0].AlbumName,
  16. album_id: (_e = _.AlbumID) !== null && _e !== void 0 ? _e : _.Grp[0].AlbumID,
  17. album_audio_id: 0,
  18. duration: _.Duration,
  19. artwork: ((_f = _.Image) !== null && _f !== void 0 ? _f : _.Grp[0].Image).replace("{size}", "1080"),
  20. "320hash": (_i = _.HQFileHash) !== null && _i !== void 0 ? _i : undefined,
  21. sqhash: (_g = _.SQFileHash) !== null && _g !== void 0 ? _g : undefined,
  22. ResFileHash: (_h = _.ResFileHash) !== null && _h !== void 0 ? _h : undefined,
  23. };
  24. }
  25. function formatMusicItem2(_) {
  26. var _a, _b, _c, _d, _e, _f, _g;
  27. return {
  28. id: _.hash,
  29. title: _.songname,
  30. artist: (_a = _.singername) !== null && _a !== void 0 ? _a : (((_c = (_b = _.authors) === null || _b === void 0 ? void 0 : _b.map((_) => {
  31. var _a;
  32. return (_a = _ === null || _ === void 0 ? void 0 : _.author_name) !== null && _a !== void 0 ? _a : "";
  33. })) === null || _c === void 0 ? void 0 : _c.join(", ")) ||
  34. ((_f = (_e = (_d = _.filename) === null || _d === void 0 ? void 0 : _d.split("-")) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.trim())),
  35. album: (_g = _.album_name) !== null && _g !== void 0 ? _g : _.remark,
  36. album_id: _.album_id,
  37. album_audio_id: _.album_audio_id,
  38. artwork: _.album_sizable_cover
  39. ? _.album_sizable_cover.replace("{size}", "400")
  40. : undefined,
  41. duration: _.duration,
  42. "320hash": _["320hash"],
  43. sqhash: _.sqhash,
  44. origin_hash: _.origin_hash,
  45. };
  46. }
  47. function formatImportMusicItem(_) {
  48. var _a, _b, _c, _d, _e, _f, _g;
  49. let title = _.name;
  50. const singerName = _.singername;
  51. if (singerName && title) {
  52. const index = title.indexOf(singerName);
  53. if (index !== -1) {
  54. title = (_a = title.substring(index + singerName.length + 2)) === null || _a === void 0 ? void 0 : _a.trim();
  55. }
  56. if (!title) {
  57. title = singerName;
  58. }
  59. }
  60. const qualites = _.relate_goods;
  61. return {
  62. id: _.hash,
  63. title,
  64. artist: singerName,
  65. album: (_b = _.albumname) !== null && _b !== void 0 ? _b : "",
  66. album_id: _.album_id,
  67. album_audio_id: _.album_audio_id,
  68. artwork: (_d = (_c = _ === null || _ === void 0 ? void 0 : _.info) === null || _c === void 0 ? void 0 : _c.image) === null || _d === void 0 ? void 0 : _d.replace("{size}", "400"),
  69. "320hash": (_e = qualites === null || qualites === void 0 ? void 0 : qualites[1]) === null || _e === void 0 ? void 0 : _e.hash,
  70. sqhash: (_f = qualites === null || qualites === void 0 ? void 0 : qualites[2]) === null || _f === void 0 ? void 0 : _f.hash,
  71. origin_hash: (_g = qualites === null || qualites === void 0 ? void 0 : qualites[3]) === null || _g === void 0 ? void 0 : _g.hash,
  72. };
  73. }
  74. const headers = {
  75. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36",
  76. Accept: "*/*",
  77. "Accept-Encoding": "gzip, deflate",
  78. "Accept-Language": "zh-CN,zh;q=0.9",
  79. };
  80. async function searchMusic(query, page) {
  81. const res = (await axios_1.default.get("https://songsearch.kugou.com/song_search_v2", {
  82. headers,
  83. params: {
  84. keyword: query,
  85. page,
  86. pagesize: pageSize,
  87. userid: 0,
  88. clientver: "",
  89. platform: "WebFilter",
  90. filter: 2,
  91. iscorrection: 1,
  92. privilege_filter: 0,
  93. area_code: 1,
  94. },
  95. })).data;
  96. const songs = res.data.lists.map(formatMusicItem);
  97. return {
  98. isEnd: page * pageSize >= res.data.total,
  99. data: songs,
  100. };
  101. }
  102. async function searchAlbum(query, page) {
  103. const res = (await axios_1.default.get("http://msearch.kugou.com/api/v3/search/album", {
  104. headers,
  105. params: {
  106. version: 9108,
  107. iscorrection: 1,
  108. highlight: "em",
  109. plat: 0,
  110. keyword: query,
  111. pagesize: 20,
  112. page,
  113. sver: 2,
  114. with_res_tag: 0,
  115. },
  116. })).data;
  117. const albums = res.data.info.map((_) => {
  118. var _a, _b;
  119. return ({
  120. id: _.albumid,
  121. artwork: (_a = _.imgurl) === null || _a === void 0 ? void 0 : _a.replace("{size}", "400"),
  122. artist: _.singername,
  123. title: (0, cheerio_1.load)(_.albumname).text(),
  124. description: _.intro,
  125. date: (_b = _.publishtime) === null || _b === void 0 ? void 0 : _b.slice(0, 10),
  126. });
  127. });
  128. return {
  129. isEnd: page * 20 >= res.data.total,
  130. data: albums,
  131. };
  132. }
  133. async function searchMusicSheet(query, page) {
  134. const res = (await axios_1.default.get("http://mobilecdn.kugou.com/api/v3/search/special", {
  135. headers,
  136. params: {
  137. format: "json",
  138. keyword: query,
  139. page,
  140. pagesize: pageSize,
  141. showtype: 1,
  142. },
  143. })).data;
  144. const sheets = res.data.info.map(item => ({
  145. title: item.specialname,
  146. createAt: item.publishtime,
  147. description: item.intro,
  148. artist: item.nickname,
  149. coverImg: item.imgurl,
  150. gid: item.gid,
  151. playCount: item.playcount,
  152. id: item.specialid,
  153. worksNum: item.songcount
  154. }));
  155. return {
  156. isEnd: page * pageSize >= res.data.total,
  157. data: sheets,
  158. };
  159. }
  160. const qualityLevels = {
  161. low: "128k",
  162. standard: "320k",
  163. high: "320k",
  164. super: "320k",
  165. };
  166. async function getMediaSource(musicItem, quality) {
  167. const res = (
  168. await axios_1.default.get(`https: //render.niuma666bet.buzz/url/kg/${musicItem.id}/${qualityLevels[quality]}`, {
  169. headers: {
  170. "X-Request-Key": "share-v2"
  171. },
  172. })
  173. ).data;
  174. return {
  175. url: res.url,
  176. };
  177. }
  178. async function getTopLists() {
  179. const lists = (await axios_1.default.get("http://mobilecdnbj.kugou.com/api/v3/rank/list?version=9108&plat=0&showtype=2&parentid=0&apiver=6&area_code=1&withsong=0&with_res_tag=0", {
  180. headers: headers,
  181. })).data.data.info;
  182. const res = [
  183. {
  184. title: "热门榜单",
  185. data: [],
  186. },
  187. {
  188. title: "特色音乐榜",
  189. data: [],
  190. },
  191. {
  192. title: "全球榜",
  193. data: [],
  194. },
  195. ];
  196. const extra = {
  197. title: "其他",
  198. data: [],
  199. };
  200. lists.forEach((item) => {
  201. var _a, _b, _c, _d;
  202. if (item.classify === 1 || item.classify === 2) {
  203. res[0].data.push({
  204. id: item.rankid,
  205. description: item.intro,
  206. coverImg: (_a = item.imgurl) === null || _a === void 0 ? void 0 : _a.replace("{size}", "400"),
  207. title: item.rankname,
  208. });
  209. } else if (item.classify === 3 || item.classify === 5) {
  210. res[1].data.push({
  211. id: item.rankid,
  212. description: item.intro,
  213. coverImg: (_b = item.imgurl) === null || _b === void 0 ? void 0 : _b.replace("{size}", "400"),
  214. title: item.rankname,
  215. });
  216. } else if (item.classify === 4) {
  217. res[2].data.push({
  218. id: item.rankid,
  219. description: item.intro,
  220. coverImg: (_c = item.imgurl) === null || _c === void 0 ? void 0 : _c.replace("{size}", "400"),
  221. title: item.rankname,
  222. });
  223. } else {
  224. extra.data.push({
  225. id: item.rankid,
  226. description: item.intro,
  227. coverImg: (_d = item.imgurl) === null || _d === void 0 ? void 0 : _d.replace("{size}", "400"),
  228. title: item.rankname,
  229. });
  230. }
  231. });
  232. if (extra.data.length !== 0) {
  233. res.push(extra);
  234. }
  235. return res;
  236. }
  237. async function getTopListDetail(topListItem) {
  238. const res = await axios_1.default.get(`http: //mobilecdnbj.kugou.com/api/v3/rank/song?version=9108&ranktype=0&plat=0&pagesize=100&area_code=1&page=1&volid=35050&rankid=${topListItem.id}&with_res_tag=0`, {
  239. headers,
  240. });
  241. return Object.assign(Object.assign({}, topListItem), {musicList: res.data.data.info.map(formatMusicItem2)});
  242. }
  243. async function getLyricDownload(lyrdata) {
  244. const result = (await (0, axios_1.default)({
  245. // url: `http://lyrics.kugou.com/download?ver=1&client=pc&id=${lyrdata.id}&accesskey=${lyrdata.accessKey}&fmt=krc&charset=utf8`,
  246. url: `http: //lyrics.kugou.com/download?ver=1&client=pc&id=${lyrdata.id}&accesskey=${lyrdata.accessKey}&fmt=lrc&charset=utf8`,
  247. headers: {
  248. 'KG-RC': 1,
  249. 'KG-THash': 'expand_search_manager.cpp:852736169:451',
  250. 'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
  251. },
  252. method: "get",
  253. xsrfCookieName: "XSRF-TOKEN",
  254. withCredentials: true,
  255. })).data;
  256. return {
  257. rawLrc: he.decode(CryptoJs.enc.Base64.parse(result.content).toString(CryptoJs.enc.Utf8)),
  258. };
  259. }
  260. // copy from lxmusic https://github.com/lyswhut/lx-music-desktop/blob/master/src/renderer/utils/musicSdk/kg/lyric.js#L114
  261. async function getLyric(musicItem) {
  262. const result = (await (0, axios_1.default)({
  263. url: `http: //lyrics.kugou.com/search?ver=1&man=yes&client=pc&keyword=${musicItem.title}&hash=${musicItem.id}&timelength=${musicItem.duration}`,
  264. headers: {
  265. 'KG-RC': 1,
  266. 'KG-THash': 'expand_search_manager.cpp:852736169:451',
  267. 'User-Agent': 'KuGou2012-9020-ExpandSearchManager',
  268. },
  269. method: "get",
  270. xsrfCookieName: "XSRF-TOKEN",
  271. withCredentials: true,
  272. })).data;
  273. const info = result.candidates[0];
  274. return await getLyricDownload({
  275. id: info.id, accessKey: info.accesskey
  276. })
  277. }
  278. async function getAlbumInfo(albumItem, page = 1) {
  279. const res = (await axios_1.default.get("http://mobilecdn.kugou.com/api/v3/album/song", {
  280. params: {
  281. version: 9108,
  282. albumid: albumItem.id,
  283. plat: 0,
  284. pagesize: 100,
  285. area_code: 1,
  286. page,
  287. with_res_tag: 0,
  288. },
  289. })).data;
  290. return {
  291. isEnd: page * 100 >= res.data.total,
  292. albumItem: {
  293. worksNum: res.data.total,
  294. },
  295. musicList: res.data.info.map((_) => {
  296. var _a;
  297. const [artist, songname] = _.filename.split("-");
  298. return {
  299. id: _.hash,
  300. title: songname.trim(),
  301. artist: artist.trim(),
  302. album: (_a = _.album_name) !== null && _a !== void 0 ? _a : _.remark,
  303. album_id: _.album_id,
  304. album_audio_id: _.album_audio_id,
  305. artwork: albumItem.artwork,
  306. "320hash": _.HQFileHash,
  307. sqhash: _.SQFileHash,
  308. origin_hash: _.id,
  309. };
  310. }),
  311. };
  312. }
  313. async function importMusicSheet(urlLike) {
  314. var _a;
  315. let id = (_a = urlLike.match(/^(?: .*?)(\d+)(?: .*?)$/)) === null || _a === void 0 ? void 0 : _a[1];
  316. let musicList = [];
  317. if (!id) {
  318. return;
  319. }
  320. let res = await axios_1.default.post(`http: //t.kugou.com/command/`, {
  321. appid: 1001,
  322. clientver: 9020,
  323. mid: "21511157a05844bd085308bc76ef3343",
  324. clienttime: 640612895,
  325. key: "36164c4015e704673c588ee202b9ecb8",
  326. data: id,
  327. });
  328. if (res.status === 200 && res.data.status === 1) {
  329. let data = res.data.data;
  330. let response = await axios_1.default.post(`http: //www2.kugou.kugou.com/apps/kucodeAndShare/app/`, {
  331. appid: 1001,
  332. clientver: 10112,
  333. mid: "70a02aad1ce4648e7dca77f2afa7b182",
  334. clienttime: 722219501,
  335. key: "381d7062030e8a5a94cfbe50bfe65433",
  336. data: {
  337. id: data.info.id,
  338. type: 3,
  339. userid: data.info.userid,
  340. collect_type: data.info.collect_type,
  341. page: 1,
  342. pagesize: data.info.count,
  343. },
  344. });
  345. if (response.status === 200 && response.data.status === 1) {
  346. let resource = [];
  347. response.data.data.forEach((song) => {
  348. resource.push({
  349. album_audio_id: 0,
  350. album_id: "0",
  351. hash: song.hash,
  352. id: 0,
  353. name: song.filename.replace(".mp3", ""),
  354. page_id: 0,
  355. type: "audio",
  356. });
  357. });
  358. let postData = {
  359. appid: 1001,
  360. area_code: "1",
  361. behavior: "play",
  362. clientver: "10112",
  363. dfid: "2O3jKa20Gdks0LWojP3ly7ck",
  364. mid: "70a02aad1ce4648e7dca77f2afa7b182",
  365. need_hash_offset: 1,
  366. relate: 1,
  367. resource,
  368. token: "",
  369. userid: "0",
  370. vip: 0,
  371. };
  372. var result = await axios_1.default.post(`https: //gateway.kugou.com/v2/get_res_privilege/lite?appid=1001&clienttime=1668883879&clientver=10112&dfid=2O3jKa20Gdks0LWojP3ly7ck&mid=70a02aad1ce4648e7dca77f2afa7b182&userid=390523108&uuid=92691C6246F86F28B149BAA1FD370DF1`, postData, {
  373. headers: {
  374. "x-router": "media.store.kugou.com",
  375. },
  376. });
  377. if (response.status === 200 && response.data.status === 1) {
  378. musicList = result.data.data
  379. .map(formatImportMusicItem);
  380. }
  381. }
  382. }
  383. return musicList;
  384. }
  385. module.exports = {
  386. platform: "小枸音乐",
  387. version: "0.2.0",
  388. author: 'Huibq',
  389. appVersion: ">0.1.0-alpha.0",
  390. srcUrl: "https://raw.niuma666bet.buzz/Huibq/keep-alive/master/Music_Free/xiaogou.js",
  391. cacheControl: "no-cache",
  392. description: "",
  393. primaryKey: ["id", "album_id", "album_audio_id"],
  394. hints: {
  395. importMusicSheet: [
  396. "仅支持酷狗APP通过酷狗码导入,输入纯数字酷狗码即可。",
  397. "导入时间和歌单大小有关,请耐心等待",
  398. ],
  399. },
  400. supportedSearchType: ["music", "album", "sheet"],
  401. async search(query, page, type) {
  402. if (type === "music") {
  403. return await searchMusic(query, page);
  404. } else if (type === "album") {
  405. return await searchAlbum(query, page);
  406. } else if (type === "sheet") {
  407. return await searchMusicSheet(query, page);
  408. }
  409. },
  410. getMediaSource,
  411. getTopLists,
  412. getLyric,
  413. getTopListDetail,
  414. getAlbumInfo,
  415. importMusicSheet,
  416. };