1 Star 0 Fork 0

RIVE2012/Less Player Desktop Plugins

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
音乐平台-豆瓣FM-WhoamI-v1.0.0.js 45.36 KB
一键复制 编辑 原始数据 按行查看 历史
RIVE2012 提交于 2024-08-12 22:12 . 代码微调
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
/**
* @name 音乐平台 - 豆瓣FM
* @version 1.0.0
* @author WhoamI
* @about
* @repository
*/
/* 默认提供的插件API */
const { common, utils, crypto, events, nets, permissions } = lessAPI
const { Category, Playlist, Track, Album, Lyric } = common
const { toTrimString, getImageUrlByQuality, nextInt, stringEquals, } = utils
const { base64Parse, base64Stringify, hexDecode, randomTextDefault, } = crypto
const { APIEvents, register, unregister } = events
const { getDoc, getJson, postJson, getInternalIpv4 } = nets
const { APIPermissions, access } = permissions
let v4ip = null
const getIpv4 = async () => {
if (!v4ip) v4ip = await getInternalIpv4()
return v4ip
}
const moduleReq = (module, method, param) => {
return { module, method, param }
}
const getAlbumCover = (albummid) => {
return albummid ? `http://y.gtimg.cn/music/photo_new/T002R500x500M000${albummid}.jpg` : null
}
const getArtistCover = (artistmid) => {
return artistmid ? `http://y.gtimg.cn/music/photo_new/T001R500x500M000${artistmid}.jpg` : null
}
const getTrackTypeMeta = (typeName) => {
return {
m4a: {
prefix: 'C400',
ext: '.m4a',
},
128: {
prefix: 'M500',
ext: '.mp3',
},
320: {
prefix: 'M800',
ext: '.mp3',
},
ape: {
prefix: 'A000',
ext: '.ape',
},
flac: {
prefix: 'F000',
ext: '.flac',
}
/*,
mgg: {
prefix: 'O4M000',
ext: '.mgg',
}
*/
}[typeName]
}
//新版本歌词信息
const lyricExtReqBody = (id, track) => {
const { title, artist, album, duration, songID } = track
const songName = base64Stringify(title)
const singerName = base64Stringify(artist[0].name)
const albumName = base64Stringify(album.name)
const interval = parseInt(duration / 1000)
return {
data: JSON.stringify({
comm: {
"tmeAppID": "qqmusic",
"authst": "",
"uid": "5019772269",
"gray": "1",
"OpenUDID": "2057708153c9fc13f0e801c14d39af5fccdfdc60",
"ct": "6",
"patch": "2",
"sid": "202304202127285019772269",
"wid": "2722428046011261952",
"cv": "80605",
//"gzip" : "1",
"qq": "",
"nettype": "2"
},
req_1: moduleReq('music.musichallSong.PlayLyricInfo', 'GetPlayLyricInfo',
{
"trans_t": 0,
"roma_t": 0,
"crypt": 0,
"lrc_t": 0,
interval,
"trans": 1,
"ct": 6,
singerName,
"type": 0,
"qrc_t": 0,
"cv": 80605,
"roma": 1,
songID,
"qrc": 0,
albumName,
songName
})
})
}
}
//TODO
const vkeyReqData = (trackInfo, type) => {
const { mid: mediaId, type: songtype } = trackInfo
const filename = [type].map(item => {
const { prefix, ext } = getTrackTypeMeta(item)
return `${prefix}${mediaId}${mediaId}${ext}`
})
const guid = nextInt(10000000).toFixed(0)
const uin = "0"
return {
comm: {
uin,
format: 'json',
ct: 24,
cv: 0
},
req_1: moduleReq('vkey.GetVkeyServer', 'CgiGetVkey',
{
filename,
guid,
songmid: [mediaId],
songtype: [songtype],
uin,
loginflag: 1,
platform: "20"
})
}
}
const vkeyReqBody = (trackInfo, type) => {
return {
'-': 'getplaysongvkey',
'g_tk': 5381,
loginUin: 0,
hostUin: 0,
format: 'json',
inCharset: 'utf8',
outCharset: 'utf8',
notice: 1,
platform: 'yqq.json',
needNewCode: 0,
data: JSON.stringify(vkeyReqData(trackInfo, type))
}
}
class DouBan {
static CODE = 'douban'
static MHZ_CODE = 'MHZ'
static TAG_PLAYLIST_CODE = 'T_PLAYLIST'
static RECOMMAND_BY_EDITOR_CODE = 'R_BY_EDITOR'
static RECOMMAND_PLAYLIST_CODE = 'R_PLAYLIST'
static RECOMMAND_ALBUM_CODE = 'R_ALBUM'
static RECOMMAND_SONGS_CODE = 'R_SONGS'
static SECTION_SONGS_CODE = 'SECTION_SONGS'
static MAIN_BG = 'http://doubanfm.kuwo.cn/assets/img/bg.jpg'
static RADIO_CACHE = { channel: 0, data: [] }
//全部分类
static categories() {
return new Promise(async (resolve, reject) => {
const result = { platform: DouBan.CODE, data: [], orders: [] }
const defaultCate = new Category('推荐')
const tagPlaylistCate = new Category('风格', DouBan.TAG_PLAYLIST_CODE)
const othersCate = new Category('其他')
defaultCate.add('主题兆赫', DouBan.MHZ_CODE)
defaultCate.add('精选歌单', DouBan.RECOMMAND_PLAYLIST_CODE)
othersCate.add('编辑精选', DouBan.RECOMMAND_BY_EDITOR_CODE)
othersCate.add('精选专辑', DouBan.RECOMMAND_ALBUM_CODE)
othersCate.add('推荐单曲', DouBan.RECOMMAND_SONGS_CODE)
const tagPlaylistCatesJson = await DouBan.tagPlaylistCategories()
if(tagPlaylistCatesJson.data.length < 1) return resolve(result)
tagPlaylistCatesJson.data.forEach(item => {
const { name, value } = item
tagPlaylistCate.add(name, value)
})
result.data.push(defaultCate)
result.data.push(tagPlaylistCate)
result.data.push(othersCate)
resolve(result)
})
}
//主题歌单分类
static tagPlaylistCategories() {
const result = { platform: DouBan.CODE, data: [] }
return new Promise(async (resolve, reject) => {
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=ListTag'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.mooSearch.MooSearchServer", "ListTag", {})
})
postJson(url, reqBody).then(json => {
const { tagList } = json.cgi.data
tagList.forEach(item => {
const { tagInfo } = item
const { id, name, cover, tag_othername, type } = tagInfo
result.data.push({
name: tag_othername || name,
value: DouBan.TAG_PLAYLIST_CODE + '_' + id,
cover,
type
})
})
resolve(result)
}).catch(error => resolve(result))
})
}
//歌单(列表)广场
static square(cate, offset, limit, page, order) {
const originCate = cate
let resolvedCate = (cate || '').toString().trim()
resolvedCate = resolvedCate.length > 0 ? resolvedCate : DouBan.MHZ_CODE
//主题兆赫
if (resolvedCate == DouBan.MHZ_CODE) return DouBan.mhzChannels(cate, offset, limit, page)
//主题歌单
if (resolvedCate.includes(DouBan.TAG_PLAYLIST_CODE)) return DouBan.tagPlaylists(cate, offset, limit, page)
//编辑精选
if (resolvedCate.includes(DouBan.RECOMMAND_BY_EDITOR_CODE)) return DouBan.recommandByEditor(cate, offset, limit, page)
//精选专辑
if (resolvedCate.includes(DouBan.RECOMMAND_ALBUM_CODE)) return DouBan.recommandAlbums(cate, offset, limit, page)
//推荐单曲
if (resolvedCate.includes(DouBan.RECOMMAND_SONGS_CODE)) return DouBan.recommandSongs(cate, offset, limit, page)
//精选歌单
return new Promise(async (resolve, reject) => {
const result = { platform: DouBan.CODE, cate: originCate, offset, limit, page, total: 10, data: [] }
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=MergePage'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.fmPlaylistPage.fmPlaylistPageSvr", "MergePage", { "offset": offset + (page - 1) * 20 })
})
postJson(url, reqBody).then(json => {
const { lst: list } = json.cgi.data
list.forEach(item => {
const { bizId: id, bizType, title, pic: cover } = item
const playlist = new Playlist(id, DouBan.CODE, cover, title)
playlist.bizType = bizType
result.data.push(playlist)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//暂时用不上
static playlistRadios(cate, offset, limit, page) {
return DouBan.mhzChannels(cate, offset, limit, page)
}
//主题兆赫,playlistRadios
static mhzChannels(cate, offset, limit, page) {
return new Promise(async (resolve, reject) => {
const result = { platform: DouBan.CODE, cate, offset, limit, page, total: 1, data: [] }
if (page > 1) {
return resolve(result)
}
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=RadioPage'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.fmRadio.FmRadioSvr", "RadioPage", { "nouse": 0 })
})
postJson(url, reqBody).then(json => {
const { top, sections } = json.cgi.data
if (top) {
top.forEach(item => {
const { id, title1: title, pic: cover, color } = item
const playlist = new Playlist(DouBan.MHZ_CODE + '_' + id, DouBan.CODE, null, title)
playlist.type = Playlist.NORMAL_RADIO_TYPE
const { R, G, B } = color
playlist.color = `rgb(${R},${G}, ${B})`
result.data.push(playlist)
})
}
if (sections) {
sections.forEach(section => {
const { id: sid, title: stitle, radios } = section
if (!radios) return
radios.forEach(radio => {
const { id, title1, title2, color } = radio
const rtitle = (title1 == title2) ? title1 : `${title1} ${title2}`
const title = `${stitle}${rtitle}`
const playlist = new Playlist(DouBan.MHZ_CODE + '_' + id, DouBan.CODE, null, title)
playlist.type = Playlist.NORMAL_RADIO_TYPE
const { R, G, B } = color
playlist.color = `rgb(${R},${G}, ${B})`
result.data.push(playlist)
})
})
}
resolve(result)
}).catch(error => resolve(result))
})
}
//主题歌单
static tagPlaylists(cate, offset, limit, page) {
const result = { platform: DouBan.CODE, cate, offset, limit, page, total: 100, data: [] }
const tagId = parseInt((cate || '').replace(DouBan.TAG_PLAYLIST_CODE + '_', '').trim())
return new Promise(async (resolve, reject) => {
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=ListGenreSongPlayList'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.mooSearch.MooSearchServer", "ListGenreSongPlayList", {
"tagId": tagId,
"tagType": 1,
"startTime": (page - 1)
})
})
postJson(url, reqBody).then(json => {
const { playlistVec: list } = json.cgi.data
list.forEach(item => {
const { id, playlistType: bizType, title, pic: cover } = item
const playlist = new Playlist(id, DouBan.CODE, cover, title)
playlist.bizType = bizType
result.data.push(playlist)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//推荐单曲
static recommandSongs(cate, offset, limit, page) {
const result = { platform: DouBan.CODE, cate, offset, limit, page, total: 1, data: [] }
return new Promise((resolve, reject) => {
const list = [{
id: DouBan.SECTION_SONGS_CODE + '_1',
title: '宝藏单曲',
cover: DouBan.MAIN_BG
}, {
id: DouBan.SECTION_SONGS_CODE + '_2',
title: '探索发现',
cover: DouBan.MAIN_BG
}]
list.forEach(item => {
const { id, title, cover } = item
const playlist = new Playlist(id, DouBan.CODE, cover, title)
result.data.push(playlist)
})
resolve(result)
})
}
//编辑精选
static recommandByEditor(cate, offset, limit, page) {
return new Promise(async (resolve, reject) => {
const result = { platform: DouBan.CODE, cate, offset, limit, page, total: 1, data: [] }
if (page > 1) {
return resolve(result)
}
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=Discover'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
cgi: moduleReq("fm.fmPlaylistPage.fmPlaylistPageSvr", "Discover", {
"Pos": 1
}),
'Discover': moduleReq("fm.fmPlaylistPage.fmPlaylistPageSvr", "Discover", {
"Pos": 2
})
})
postJson(url, reqBody).then(json => {
const { lst: list1 } = json.cgi.data
const { lst: list2 } = json.Discover.data
const list = []
if (list1) list.push(...list1)
if (list2) list.push(...list2)
list.forEach(item => {
const { bizId: id, bizType, title, pic: cover } = item
const playlist = new Playlist(id, DouBan.CODE, cover, title)
playlist.bizType = bizType
result.data.push(playlist)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//精选专辑
static recommandAlbums(cate, offset, limit, page) {
const result = { platform: DouBan.CODE, cate, offset, limit, page, total: 1, data: [], dataType: 1 }
//const cateId = parseInt(toTrimString(cate).replace(DouBan.RECOMMAND_ALBUM_CODE + '_', ''))
return new Promise(async (resolve, reject) => {
if (page > 1) {
return resolve(result)
}
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=AlbumMergePage'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.fmDiscover.fmDiscoverAlbumSvr", "AlbumMergePage", { "date": "" })
})
postJson(url, reqBody).then(json => {
const { albums: list } = json.cgi.data
list.forEach(item => {
const { bizId: id, bizType, name: title, pic: cover, subTitle } = item
const albumId = DouBan.RECOMMAND_ALBUM_CODE + '_' + id
const album = new Album(albumId, DouBan.CODE, title, cover)
album.bizType = bizType
album.subtitle = subTitle
result.data.push(album)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//宝藏单曲、探索发现
static recommandSectionSongs(id, offset, limit, page) {
const pos = parseInt(toTrimString(id).replace(DouBan.SECTION_SONGS_CODE + '_', ''))
const titles = ['未知歌单', '宝藏单曲', '探索发现']
return new Promise(async (resolve, reject) => {
const result = new Playlist(id, DouBan.CODE, DouBan.MAIN_BG, titles[pos])
Object.assign(result, {
about: '每一次的不期而遇,也许都会有别样的风景。'
+ '<br>一起去发现美吧,让内心来指引我们方向。 '
+ '<br><br>PS: 每次重新进入页面时,歌曲数据可能会随时被刷新哦 ~'
})
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=SongSection'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
cgi: moduleReq("fm.fmDiscover.fmDiscoverSvr", "SongSection", {
"Pos": pos
})
})
postJson(url, reqBody).then(json => {
const { songs } = json.cgi.data
songs.forEach(item => {
const { track: song } = item
const artist = song.singer.map(ar => ({ id: ar.id, name: ar.name }))
const album = { id: song.album.id, name: song.album.title }
const duration = song.interval * 1000
const cover = getAlbumCover(song.album.mid)
const track = new Track(song.id, DouBan.CODE, song.name, artist, album, duration, cover)
track.mid = song.mid
track.pid = id
result.addTrack(track)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//歌单详情
static playlistDetail(id, offset, limit, page) {
id = toTrimString(id)
//(歌曲合集)宝藏单曲、探索发现
if (id.includes(DouBan.SECTION_SONGS_CODE)) return DouBan.recommandSectionSongs(id, offset, limit, page)
//普通歌单
id = parseInt(id.replace(DouBan.TAG_PLAYLIST_CODE + '_', ''))
return new Promise(async (resolve, reject) => {
const result = new Playlist(id, DouBan.CODE)
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=QueryPlaylistDetailEx'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.mooDetailPage.MooPlaylistDetailSvr", "QueryPlaylistDetailEx", {
"id": id,
"lastIndex": (page - 1),
"location": 0
})
})
postJson(url, reqBody).then(json => {
const { songlist, songs, totalSongsCnt } = json.cgi.data
const { name: title, pic: cover, desc: about } = songlist.header
Object.assign(result, {
cover,
title,
about,
total: totalSongsCnt
})
songs.forEach(item => {
const { song } = item
const artist = song.singer.map(ar => ({ id: ar.id, name: ar.name }))
const album = { id: song.album.id, name: song.album.title }
const duration = song.interval * 1000
const cover = getAlbumCover(song.album.mid)
const track = new Track(song.id, DouBan.CODE, song.name, artist, album, duration, cover)
track.mid = song.mid
track.pid = id
result.addTrack(track)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//歌曲播放详情:url、cover、lyric等
static playDetail(id, track) {
return new Promise(async (resolve, reject) => {
const result = new Track(id, DouBan.CODE)
const types = ['320', '128', 'm4a']
for (var i = 0; i < types.length; i++) {
const vkeyJson = await DouBan.getVKeyJson(track, types[i])
const { midurlinfo, sip } = vkeyJson.req_1.data
const urlInfo = midurlinfo[0]
const { vkey } = urlInfo
if ((vkey || '').trim().length > 0) {
result.url = sip[0] + urlInfo.purl
break
}
}
resolve(result)
})
}
//获取VKey、purl和sip服务器等信息
static getVKeyJson(trackInfo, type) {
return new Promise((resolve, reject) => {
const url = "https://u.y.qq.com/cgi-bin/musicu.fcg"
const reqBody = vkeyReqBody(trackInfo, type)
getJson(url, reqBody).then(json => resolve(json))
})
}
//歌词
static lyric(id, track) {
return new Promise((resolve, reject) => {
const url = 'http://u.y.qq.com/cgi-bin/musicu.fcg'
const reqBody = lyricExtReqBody(id, track)
const result = { id, platform: DouBan.CODE, lyric: null, trans: null }
getJson(url, reqBody).then(json => {
const { lyric, roma, trans } = json.req_1.data
Object.assign(result, { lyric: Lyric.parseFromText(base64Parse(lyric)) })
if (roma) { //TODO
Object.assign(result, { roma: Lyric.parseFromText(hexDecode(roma)) })
}
if (trans) {
Object.assign(result, { trans: Lyric.parseFromText(base64Parse(trans)) })
}
resolve(result)
})
})
}
//歌手详情:Name、Cover、简介(如果有)、热门歌曲等
static artistDetail(id) {
return new Promise(async (resolve, reject) => {
const result = { id, platform: DouBan.CODE, title: '未知歌手', cover: '', data: [], about: '' }
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=ListSingerSong'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
cgi: moduleReq("fm.mooVisit.mooVisitServer", "ListSingerSong", {
"id": parseInt(id),
"idType": 2,
"sortType": 1,
"cursor": 0
})
})
postJson(url, reqBody).then(json => {
const { songList: songs } = json.cgi.data
songs.forEach(item => {
const song = item
const artist = song.singer.map(ar => {
if (stringEquals(ar.id, id)) {
if (result.title === '未知歌手') {
Object.assign(result, {
title: ar.name || ar.title
})
}
if (result.cover === '') {
Object.assign(result, {
cover: getArtistCover(ar.mid)
})
}
}
return { id: ar.id, name: ar.name || ar.title }
})
const album = { id: song.album.id, name: song.album.title }
const duration = song.interval * 1000
const cover = getAlbumCover(song.album.mid)
const track = new Track(song.id, DouBan.CODE, song.name, artist, album, duration, cover)
track.mid = song.mid
track.pid = id
result.data.push(track)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//歌手详情:歌曲
static artistDetailAllSongs(id, offset, limit, page) {
if (page < 2) return DouBan.artistDetail(id)
return new Promise((resolve, reject) => {
//const result = { id, offset, limit, page, total: 0, data: [] }
resolve({ id, offset, limit, page, total: 0, data: [] })
})
}
//歌手详情: 专辑
static artistDetailAlbums(id, offset, limit, page) {
return new Promise(async (resolve, reject) => {
const result = { id, platform: DouBan.CODE, offset, limit, page, total: 1, data: [] }
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=ListSingerAlbum'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
cgi: moduleReq("fm.mooVisit.mooVisitServer", "ListSingerAlbum", {
"id": parseInt(id),
"idType": 2,
"sortType": 1,
"cursor": 0
})
})
postJson(url, reqBody).then(json => {
const { albumList: list } = json.cgi.data
list.forEach(item => {
const { id: albumId, type: bizType, name: title, pic: cover, artists, publish_date: publishTime } = item
const artist = artists.map(ar => ({ id: ar.id, name: ar.name }))
const album = new Album(albumId, DouBan.CODE, title, cover, artist, null, publishTime)
album.bizType = bizType
result.data.push(album)
})
resolve(result)
}).catch(error => resolve(result))
})
}
//歌手详情: 简介
static artistDetailAbout(id) {
return new Promise((resolve, reject) => {
resolve('')
})
}
//电台:下一首歌曲
static nextPlaylistRadioTrack(channel, track) {
channel = channel.replace(DouBan.MHZ_CODE + '_', '')
return new Promise(async (resolve, reject) => {
let result = null
const firstplay = !track ? 1 : 0
//是否命中缓存
if (channel == DouBan.RADIO_CACHE.channel) {
const index = (firstplay == 1) ? 0 :
DouBan.RADIO_CACHE.data.findIndex(item => item.id == track.id)
const length = DouBan.RADIO_CACHE.data.length
if (length > 0 && index > -1 && index < (length - 1)) {
result = DouBan.RADIO_CACHE.data[index + 1]
resolve(result)
return
}
}
//不命中,重置缓存
DouBan.RADIO_CACHE.channel = channel
DouBan.RADIO_CACHE.data.length = 0
//拉取数据
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=ListRadioSong'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": "1_098346_" + Date.now()
},
"fm.fmRadio.FmRadioSvr.ListRadioSong": moduleReq("fm.fmRadio.FmRadioSvr", "ListRadioSong", { "id": parseInt(channel) })
})
postJson(url, reqBody).then(json => {
const { songList } = json['fm.fmRadio.FmRadioSvr.ListRadioSong'].data
songList.forEach(song => {
const { songInfo, candidateInfo, midUrlInfo, extra_info } = song
const artist = songInfo.singer.map(ar => ({ id: ar.id, name: ar.name }))
const album = { id: songInfo.album.id, name: songInfo.album.title }
const duration = songInfo.interval * 1000
const cover = getAlbumCover(songInfo.album.mid)
const cacheTrack = new Track(songInfo.id, DouBan.CODE, songInfo.title, artist, album, duration, cover)
cacheTrack.mid = songInfo.mid
cacheTrack.channel = channel
cacheTrack.type = Playlist.NORMAL_RADIO_TYPE
DouBan.RADIO_CACHE.data.push(cacheTrack)
})
result = DouBan.RADIO_CACHE.data[0]
resolve(result)
}, error => resolve(null))
})
}
//专辑详情
static albumDetail(id) {
id = parseInt(toTrimString(id).replace(DouBan.RECOMMAND_ALBUM_CODE + '_', ''))
return new Promise(async (resolve, reject) => {
const url = 'https://u6.kuwo.cn/cgi-bin/musicu.fcg?cgiKey=QueryAlbumDetailEx'
const reqBody = JSON.stringify({
"comm": {
"OpenUDID": "ffffffffe3950e2e000000000033c587",
"udid": "ffffffffe3950e2e000000000033c587",
"ct": "111",
"cv": "7010001",
"v": "7010001",
"chid": "72280",
"os_ver": "7.1.2",
"aid": "6C96CFE0D9AB0000",
"phonetype": "SM-N950N",
"tmeAppID": "fm",
"nettype": "1010",
"wid": "3246708651311727616",
"rom": "samsung/samsung/dream2ltexx/dream2lte:7.1.2/NRD90M/700210421:user/release-keys/",
"uid": "98346",
"qimei": "b13acea18edc3ca714cbfce610001e817518",
"qimei36": "b13acea18edc3ca714cbfce610001e817518",
"fPersonality": "0",
"v4ip": await getIpv4(),
"gzip": "0",
"traceid": '1_098365_' + Date.now()
},
"cgi": moduleReq("fm.mooDetailPage.MooAlbumDetailSvr", "QueryAlbumDetailEx", {
"album_id": id,
"lastIndex": 0
})
})
postJson(url, reqBody).then(json => {
const { album, songs } = json.cgi.data
const { id, name: title, pic: cover, desc: about, publish_date: publishTime, album_mid: mid, artists } = album
const artist = artists.map(ar => ({ id: ar.id, name: ar.name }))
const result = new Album(id, DouBan.CODE, title, cover, artist, null, publishTime, about)
result.mid = mid
songs.forEach(item => {
const { track: song } = item
const artist = song.singer.map(ar => ({ id: ar.id, name: ar.name }))
const album = { id: song.album.id, name: song.album.title }
const duration = song.interval * 1000
const cover = getAlbumCover(song.album.mid)
const track = new Track(song.id, DouBan.CODE, song.name, artist, album, duration, cover)
track.mid = song.mid
track.pid = id
result.addTrack(track)
})
resolve(result)
})
})
}
//专辑详情: 歌曲
static albumDetailAllSongs(id, offset, limit, page) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(null), 1000)
})
}
/* 暂时不再提供搜索实现
//搜索: 歌曲
static searchSongs(keyword, offset, limit, page) {
return new Promise((resolve, reject) => {
keyword = keyword.trim()
const url = "https://fm.douban.com/j/v2/query/song?q=" + keyword + "&limit=" + limit
getJson(url).then(json => {
const list = json.items
const data = list.map(item => {
const artist = item.singers.map(ar => ({ id: ar.id, name: ar.name }))
const album = { id: item.aid, name: item.albumtitle }
const cover = item.cover || item.picture
const duration = item.length * 1000
const track = new Track(item.sid, DouBan.CODE, item.title, artist, album, duration, cover)
track.ssid = item.ssid
track.url = item.url
return track
})
const result = { platform: DouBan.CODE, offset, limit, page, data }
resolve(result)
})
})
}
//搜索: 歌单
static searchPlaylists(keyword, offset, limit, page) {
return new Promise((resolve, reject) => {
const url = "https://fm.douban.com/j/v2/query/songlist?q=" + keyword + "&limit=" + limit
const result = { platform: DouBan.CODE, offset, limit, page, data: [] }
getJson(url).then(json => {
const list = json.items
const data = list.map(item => {
const playlist = new Playlist(item.id, DouBan.CODE, item.cover, item.title)
return playlist
})
if (data && data.length > 0) result.data.push(...data)
resolve(result)
}).catch(error => resolve(result))
})
}
//搜索: 专辑
static searchAlbums(keyword, offset, limit, page) {
return new Promise((resolve, reject) => {
const result = { platform: DouBan.CODE, offset, limit, page, data: [] }
resolve(result)
})
}
//搜索: 歌手
static searchArtists(keyword, offset, limit, page) {
return new Promise((resolve, reject) => {
const url = "https://fm.douban.com/j/v2/query/artist?q=" + keyword + "&limit=" + limit
getJson(url).then(json => {
const list = json.items
const data = list.map(item => ({
id: item.id,
platform: DouBan.CODE,
title: item.name_usual,
cover: item.avatar,
channel: item.channel
}))
const result = { platform: DouBan.CODE, offset, limit, page, data }
resolve(result)
})
})
}
*/
}
/* 插件接入规范区 */
//插件启用
export const activate = async () => {
//获取权限
access(APIPermissions.ADD_PLATFORM, {
code: DouBan.CODE,
vendor: DouBan,
name: '豆瓣FM',
shortName: 'DB',
online: true,
types: ['playlists', 'albums'],
scopes: ['playlists', 'userhome', 'random'],
artistTabs: [ 'all-songs', 'albums','about' ],
weight: 8
})
//获取UserAgent
//const userAgent = await access(APIPermissions.GET_USER_AGENT)
access(APIPermissions.ADD_REQUEST_HANDLER, {
id: DouBan.CODE,
hosts: ['douban', 'u6.kuwo.cn'],
includes: [{
pattern: 'douban',
headers: {
Origin: 'https://fm.douban.com/',
Referer: 'https://fm.douban.com/',
Cookie: `bid=${randomTextDefault(11)}`
}
}, {
pattern: 'u6.kuwo.cn',
headers: {
'User-Agent': 'fm 7010001}(android 7.1.2)',
Cookie: ''
}
}]
})
console.log('[ PLUGIN - Activated ] 音乐平台 - 豆瓣FM')
}
//插件停用
export const deactivate = () => {
//归还权限
access(APIPermissions.REMOVE_PLATFORM, DouBan.CODE)
access(APIPermissions.REMOVE_REQUEST_HANDLER, DouBan.CODE)
console.log('[ PLUGIN - Deactivated ] 音乐平台 - 豆瓣FM')
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/rive08/less-player-desktop-plugins.git
git@gitee.com:rive08/less-player-desktop-plugins.git
rive08
less-player-desktop-plugins
Less Player Desktop Plugins
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385