diff --git a/app.js b/app.js index f2f5cdc..dd2e422 100644 --- a/app.js +++ b/app.js @@ -42,14 +42,6 @@ app.use(cache('2 minutes', onlyStatus200)) app.use(express.static(path.resolve(__dirname, 'public'))) -app.use(function(req, res, next) { - const proxy = req.query.proxy - if (proxy) { - req.headers.cookie += `__proxy__${proxy}` - } - next() -}) - // 补全缺失的cookie const { completeCookie } = require('./util/init') app.use(function(req, res, next) { @@ -59,6 +51,24 @@ app.use(function(req, res, next) { next() }) +// cookie parser +app.use(function(req, res, next) { + req.cookies = {}, (req.headers.cookie || '').split(/\s*;\s*/).forEach(pair => { + let crack = pair.indexOf('=') + if(crack < 1 || crack == pair.length - 1) return + req.cookies[decodeURIComponent(pair.slice(0, crack)).trim()] = decodeURIComponent(pair.slice(crack + 1)).trim() + }) + next() +}) + +app.use(function(req, res, next) { + const proxy = req.query.proxy + if (proxy) { + req.headers.cookie += `__proxy__${proxy}` + } + next() +}) + // 因为这几个文件对外所注册的路由 和 其他文件对外注册的路由规则不一样, 所以专门写个MAP对这些文件做特殊处理 const UnusualRouteFileMap = { // key 为文件名, value 为对外注册的路由 @@ -72,27 +82,41 @@ const { createWebAPIRequest, request } = require('./util/util') const Wrap = fn => (req, res) => fn(req, res, createWebAPIRequest, request) // 同步读取 router 目录中的js文件, 根据命名规则, 自动注册路由 -fs.readdirSync(path.resolve(__dirname, 'router')) - .reverse() - .forEach(file => { - if (/\.js$/i.test(file) === false) { - return - } +fs.readdirSync(path.join(__dirname, 'router')) +.reverse() +.forEach(file => { + if (!/\.js$/i.test(file)) return + let route = (file in UnusualRouteFileMap) ? UnusualRouteFileMap[file] : '/' + file.replace(/\.js$/i, '').replace(/_/g, '/') + app.use(route, Wrap(require(path.join(__dirname, 'router', file)))) +}) - let route - if (typeof UnusualRouteFileMap[file] !== 'undefined') { - route = UnusualRouteFileMap[file] - } else { - route = - '/' + - file - .replace(/\.js$/i, '') - .replace(/_/g, '/') - } - - app.use(route, Wrap(require('./router/' + file))) +// 改写router为module +const requestMod = require('./util/request') +let dev = express() +fs.readdirSync(path.join(__dirname, 'module')) +.reverse() +.forEach(file => { + if (!(/\.js$/i.test(file))) return + let route = (file in UnusualRouteFileMap) ? UnusualRouteFileMap[file] : '/' + file.replace(/\.js$/i, '').replace(/_/g, '/') + let question = require(path.join(__dirname, 'module', file)) + + dev.use(route, (req, res) => { + let query = {...req.query, cookie: req.cookies} + question(query, requestMod) + .then(answer => { + console.log('[OK]', decodeURIComponent(req.originalUrl)) + res.append('Set-Cookie', answer.cookie) + res.status(answer.status).send(answer.body) + }) + .catch(answer => { + console.log('[ERR]', decodeURIComponent(req.originalUrl)) + res.append('Set-Cookie', answer.cookie) + res.status(answer.status).send(answer.body) + }) }) +}) +app.use('/dev', dev) const port = process.env.PORT || 3000 diff --git a/module/album.js b/module/album.js new file mode 100644 index 0000000..d8d0ecd --- /dev/null +++ b/module/album.js @@ -0,0 +1,8 @@ +// 专辑内容 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/album/${query.id}`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_album.js b/module/artist_album.js new file mode 100644 index 0000000..8964c2a --- /dev/null +++ b/module/artist_album.js @@ -0,0 +1,13 @@ +// 歌手专辑列表 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 30, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/artist/albums/${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_desc.js b/module/artist_desc.js new file mode 100644 index 0000000..37677a3 --- /dev/null +++ b/module/artist_desc.js @@ -0,0 +1,11 @@ +// 歌手介绍 + +module.exports = (query, request) => { + const data = { + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/artist/introduction`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_list.js b/module/artist_list.js new file mode 100644 index 0000000..7fbce65 --- /dev/null +++ b/module/artist_list.js @@ -0,0 +1,37 @@ +// 歌手分类 + +/* + categoryCode 取值 + 入驻歌手 5001 + 华语男歌手 1001 + 华语女歌手 1002 + 华语组合/乐队 1003 + 欧美男歌手 2001 + 欧美女歌手 2002 + 欧美组合/乐队 2003 + 日本男歌手 6001 + 日本女歌手 6002 + 日本组合/乐队 6003 + 韩国男歌手 7001 + 韩国女歌手 7002 + 韩国组合/乐队 7003 + 其他男歌手 4001 + 其他女歌手 4002 + 其他组合/乐队 4003 + + initial 取值 a-z/A-Z +*/ + +module.exports = (query, request) => { + const data = { + categoryCode: query.cat || '1001', + initial: (query.initial || '').toUpperCase().charCodeAt() || '', + offset: query.offset || 0, + limit: query.limit || 30, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/artist/list`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_mv.js b/module/artist_mv.js new file mode 100644 index 0000000..8eb953c --- /dev/null +++ b/module/artist_mv.js @@ -0,0 +1,14 @@ +// 歌手相关MV + +module.exports = (query, request) => { + const data = { + artistId: query.id, + limit: query.limit, + offset: query.offset, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/artist/mvs`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_sub.js b/module/artist_sub.js new file mode 100644 index 0000000..05bc4cf --- /dev/null +++ b/module/artist_sub.js @@ -0,0 +1,13 @@ +// 收藏与取消收藏歌手 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'sub' : 'unsub') + const data = { + artistId: query.id, + artistIds: '[' + query.id + ']' + } + return request( + 'POST', `http://music.163.com/weapi/artist/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artist_sublist.js b/module/artist_sublist.js new file mode 100644 index 0000000..d4d8096 --- /dev/null +++ b/module/artist_sublist.js @@ -0,0 +1,13 @@ +// 我的歌手列表 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 25, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/artist/sublist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/artists.js b/module/artists.js new file mode 100644 index 0000000..a9efd17 --- /dev/null +++ b/module/artists.js @@ -0,0 +1,8 @@ +// 歌手单曲 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/artist/${query.id}`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/banner.js b/module/banner.js new file mode 100644 index 0000000..869bd2a --- /dev/null +++ b/module/banner.js @@ -0,0 +1,20 @@ +// 首页轮播图 + +module.exports = (query, request) => { + return request( + 'GET', `http://music.163.com/discover`, {}, + {ua: 'pc', proxy: query.proxy} + ) + .then(response => { + try{ + const banners = eval(`(${/Gbanners\s*=\s*([^;]+);/.exec(response.body)[1]})`) + response.body = {code: 200, banners: banners} + return response + } + catch(err){ + response.status = 500 + response.body = {code: 500, msg: err.stack} + return Promise.reject(response) + } + }) +} \ No newline at end of file diff --git a/module/check_music.js b/module/check_music.js new file mode 100644 index 0000000..8d11dff --- /dev/null +++ b/module/check_music.js @@ -0,0 +1,25 @@ +// 歌曲可用性 + +module.exports = (query, request) => { + const data = { + ids: '[' + parseInt(query.id) + ']', + br: parseInt(query.br || 999000) + } + return request( + 'POST', `http://music.163.com/weapi/song/enhance/player/url`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) + .then(response => { + if (response.body.code == 200) { + if (response.body.data[0].code == 200){ + response.body = {success: true, message: 'ok'} + return response + } + } + else{ + response.status = 404 + response.body = {success: false, message: '亲爱的,暂无版权'} + return Promise.reject(response) + } + }) +} \ No newline at end of file diff --git a/module/comment.js b/module/comment.js new file mode 100644 index 0000000..bac7ce3 --- /dev/null +++ b/module/comment.js @@ -0,0 +1,25 @@ +// 发送与删除评论 + +module.exports = (query, request) => { + query.cookie.os = 'pc' + query.t = (query.t == 1 ? 'add' : 'delete') + query.type = { + 0: 'R_SO_4_', // 歌曲 + 1: 'R_MV_5_', // MV + 2: 'A_PL_0_', // 歌单 + 3: 'R_AL_3_', // 专辑 + 4: 'A_DJ_1_', // 电台, + 5: 'R_VI_62_' // 视频 + }[query.type] + const data = { + threadId: query.type + query.id + } + if(query.t == 'add') + data.content = query.content + else if(query.t == 'delete') + data.commentId = query.commentId + return request( + 'POST', `http://music.163.com/weapi/resource/comments/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_album.js b/module/comment_album.js new file mode 100644 index 0000000..da56f03 --- /dev/null +++ b/module/comment_album.js @@ -0,0 +1,13 @@ +// 专辑评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/R_AL_3_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_dj.js b/module/comment_dj.js new file mode 100644 index 0000000..c436a35 --- /dev/null +++ b/module/comment_dj.js @@ -0,0 +1,13 @@ +// 电台评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/A_DJ_1_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_hot.js b/module/comment_hot.js new file mode 100644 index 0000000..e03d959 --- /dev/null +++ b/module/comment_hot.js @@ -0,0 +1,22 @@ +// 热门评论 + +module.exports = (query, request) => { + query.cookie.os = 'pc' + query.type = { + 0: 'R_SO_4_', // 歌曲 + 1: 'R_MV_5_', // MV + 2: 'A_PL_0_', // 歌单 + 3: 'R_AL_3_', // 专辑 + 4: 'A_DJ_1_', // 电台, + 5: 'R_VI_62_' // 视频 + }[query.type] + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/hotcomments/${query.type}${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_like.js b/module/comment_like.js new file mode 100644 index 0000000..98c0cf4 --- /dev/null +++ b/module/comment_like.js @@ -0,0 +1,22 @@ +// 点赞与取消点赞评论 + +module.exports = (query, request) => { + query.cookie.os = 'pc' + query.t = (query.t == 1 ? 'like' : 'unlike') + query.type = { + 0: 'R_SO_4_', // 歌曲 + 1: 'R_MV_5_', // MV + 2: 'A_PL_0_', // 歌单 + 3: 'R_AL_3_', // 专辑 + 4: 'A_DJ_1_', // 电台, + 5: 'R_VI_62_' // 视频 + }[query.type] + const data = { + threadId: query.type + query.id, + commentId: query.cid + } + return request( + 'POST', `http://music.163.com/weapi/v1/comment/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_music.js b/module/comment_music.js new file mode 100644 index 0000000..afb3315 --- /dev/null +++ b/module/comment_music.js @@ -0,0 +1,13 @@ +// 歌曲评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/R_SO_4_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_mv.js b/module/comment_mv.js new file mode 100644 index 0000000..57133bf --- /dev/null +++ b/module/comment_mv.js @@ -0,0 +1,13 @@ +// MV评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/R_MV_5_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_playlist.js b/module/comment_playlist.js new file mode 100644 index 0000000..1431483 --- /dev/null +++ b/module/comment_playlist.js @@ -0,0 +1,13 @@ +// 歌单评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/A_PL_0_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/comment_video.js b/module/comment_video.js new file mode 100644 index 0000000..7df4221 --- /dev/null +++ b/module/comment_video.js @@ -0,0 +1,13 @@ +// 视频评论 + +module.exports = (query, request) => { + const data = { + rid: query.id, + limit: query.limit || 20, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/resource/comments/R_VI_62_${query.id}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/daily_signin.js b/module/daily_signin.js new file mode 100644 index 0000000..f0ba150 --- /dev/null +++ b/module/daily_signin.js @@ -0,0 +1,18 @@ +// 签到 + +/* + 0为安卓端签到 3点经验, 1为网页签到,2点经验 + 签到成功 {'android': {'point': 3, 'code': 200}, 'web': {'point': 2, 'code': 200}} + 重复签到 {'android': {'code': -2, 'msg': '重复签到'}, 'web': {'code': -2, 'msg': '重复签到'}} + 未登录 {'android': {'code': 301}, 'web': {'code': 301}} +*/ + +module.exports = (query, request) => { + const data = { + type: query.type || 0 + } + return request( + 'POST', `http://music.163.com/weapi/point/dailyTask`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_catelist.js b/module/dj_catelist.js new file mode 100644 index 0000000..d64709f --- /dev/null +++ b/module/dj_catelist.js @@ -0,0 +1,8 @@ +// 电台分类列表 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/djradio/category/get`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_detail.js b/module/dj_detail.js new file mode 100644 index 0000000..35fe0c4 --- /dev/null +++ b/module/dj_detail.js @@ -0,0 +1,11 @@ +// 电台详情 + +module.exports = (query, request) => { + const data = { + id: query.rid + } + return request( + 'POST', `http://music.163.com/weapi/djradio/get`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_hot.js b/module/dj_hot.js new file mode 100644 index 0000000..175294d --- /dev/null +++ b/module/dj_hot.js @@ -0,0 +1,17 @@ +// 热门电台 + +module.exports = (query, request) => { + const data = { + cat: query.type, + cateId: query.type, + type: query.type, + categoryId: query.type, + category: query.type, + limit: query.limit, + offset: query.offset + } + return request( + 'POST', `http://music.163.com/weapi/djradio/hot/v1`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_paygift.js b/module/dj_paygift.js new file mode 100644 index 0000000..2f4680b --- /dev/null +++ b/module/dj_paygift.js @@ -0,0 +1,12 @@ +// 付费电台 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 10, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/djradio/home/paygift/list?_nmclfl=1`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_program.js b/module/dj_program.js new file mode 100644 index 0000000..9ed4020 --- /dev/null +++ b/module/dj_program.js @@ -0,0 +1,14 @@ +// 电台节目列表 + +module.exports = (query, request) => { + const data = { + radioId: query.rid, + limit: query.limit || 30, + offset: query.offset || 0, + asc: query.asc + } + return request( + 'POST', `http://music.163.com/weapi/dj/program/byradio`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_program_detail.js b/module/dj_program_detail.js new file mode 100644 index 0000000..838d9b3 --- /dev/null +++ b/module/dj_program_detail.js @@ -0,0 +1,11 @@ +// 电台节目详情 + +module.exports = (query, request) => { + const data = { + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/dj/program/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_recommend.js b/module/dj_recommend.js new file mode 100644 index 0000000..43e7f4e --- /dev/null +++ b/module/dj_recommend.js @@ -0,0 +1,8 @@ +// 精选电台 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/djradio/recommend/v1`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} diff --git a/module/dj_recommend_type.js b/module/dj_recommend_type.js new file mode 100644 index 0000000..b39720b --- /dev/null +++ b/module/dj_recommend_type.js @@ -0,0 +1,34 @@ +// 精选电台分类 + +/* + 有声书 10001 + 知识技能 453050 + 商业财经 453051 + 人文历史 11 + 外语世界 13 + 亲子宝贝 14 + 创作|翻唱 2001 + 音乐故事 2 + 3D|电子 10002 + 相声曲艺 8 + 情感调频 3 + 美文读物 6 + 脱口秀 5 + 广播剧 7 + 二次元 3001 + 明星做主播 1 + 娱乐|影视 4 + 科技科学 453052 + 校园|教育 4001 + 旅途|城市 12 +*/ + +module.exports = (query, request) => { + const data = { + cateId: query.type + } + return request( + 'POST', `http://music.163.com/weapi/djradio/recommend`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_sub.js b/module/dj_sub.js new file mode 100644 index 0000000..8a2523e --- /dev/null +++ b/module/dj_sub.js @@ -0,0 +1,12 @@ +// 订阅与取消电台 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'sub' : 'unsub') + const data = { + id: query.rid + } + return request( + 'POST', `http://music.163.com/weapi/djradio/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/dj_sublist.js b/module/dj_sublist.js new file mode 100644 index 0000000..d42c830 --- /dev/null +++ b/module/dj_sublist.js @@ -0,0 +1,13 @@ +// 我的电台列表 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 30, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/djradio/get/subed`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/event.js b/module/event.js new file mode 100644 index 0000000..de941b3 --- /dev/null +++ b/module/event.js @@ -0,0 +1,8 @@ +// 动态 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/event/get`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/fm_trash.js b/module/fm_trash.js new file mode 100644 index 0000000..35a4ee9 --- /dev/null +++ b/module/fm_trash.js @@ -0,0 +1,11 @@ +// 垃圾桶 + +module.exports = (query, request) => { + const data = { + songId: query.id + } + return request( + 'POST', `http://music.163.com/weapi/radio/trash/add?alg=RT&songId=${query.id}&time=${query.time || 25}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/follow.js b/module/follow.js new file mode 100644 index 0000000..460d76b --- /dev/null +++ b/module/follow.js @@ -0,0 +1,9 @@ +// 关注与取消关注用户 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'follow' : 'delfollow') + return request( + 'POST', `http://music.163.com/weapi/user/${query.t}/${query.id}`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/like.js b/module/like.js new file mode 100644 index 0000000..3e29699 --- /dev/null +++ b/module/like.js @@ -0,0 +1,13 @@ +// 红心取消红心歌曲 + +module.exports = (query, request) => { + query.like = (query.like ? true : false) + const data = { + trackId: query.id, + like: query.like + } + return request( + 'POST', `http://music.163.com/weapi/radio/like?alg=${query.alg || 'itembased'}&trackId=${query.id}&like=${query.like}&time=${query.time || 25}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/likelist.js b/module/likelist.js new file mode 100644 index 0000000..6dbd62f --- /dev/null +++ b/module/likelist.js @@ -0,0 +1,11 @@ +// 喜欢的歌曲(无序) + +module.exports = (query, request) => { + const data = { + uid: query.uid + } + return request( + 'POST', `http://music.163.com/weapi/song/like/get`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/login.js b/module/login.js new file mode 100644 index 0000000..d3c2345 --- /dev/null +++ b/module/login.js @@ -0,0 +1,15 @@ +// 邮箱登录 + +const crypto = require('crypto') + +module.exports = (query, request) => { + const data = { + username: query.email, + password: crypto.createHash('md5').update(query.password).digest('hex'), + rememberLogin: 'true' + } + return request( + 'POST', `http://music.163.com/weapi/login`, data, + {crypto: 'weapi', ua: 'pc', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/login_cellphone.js b/module/login_cellphone.js new file mode 100644 index 0000000..71beb88 --- /dev/null +++ b/module/login_cellphone.js @@ -0,0 +1,15 @@ +// 手机登录 + +const crypto = require('crypto') + +module.exports = (query, request) => { + const data = { + phone: query.phone, + password: crypto.createHash('md5').update(query.password).digest('hex'), + rememberLogin: 'true' + } + return request( + 'POST', `http://music.163.com/weapi/login/cellphone`, data, + {crypto: 'weapi', ua: 'pc', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/login_refresh.js b/module/login_refresh.js new file mode 100644 index 0000000..fa83612 --- /dev/null +++ b/module/login_refresh.js @@ -0,0 +1,8 @@ +// 登录刷新 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/login/token/refresh`, {}, + {crypto: 'weapi', ua: 'pc', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/login_status.js b/module/login_status.js new file mode 100644 index 0000000..edd21ab --- /dev/null +++ b/module/login_status.js @@ -0,0 +1,21 @@ +// 登录状态 + +module.exports = (query, request) => { + return request( + 'GET', `http://music.163.com`, {}, + {cookie: query.cookie, proxy: query.proxy} + ) + .then(response => { + try{ + let profile = eval(`(${/GUser\s*=\s*([^;]+);/.exec(response.body)[1]})`) + let bindings = eval(`(${/GBinds\s*=\s*([^;]+);/.exec(response.body)[1]})`) + response.body = {code: 200, profile: profile, bindings: bindings} + return response + } + catch(err){ + response.status = 301 + response.body = {code: 301} + return Promise.reject(response) + } + }) +} \ No newline at end of file diff --git a/module/logout.js b/module/logout.js new file mode 100644 index 0000000..8063e1d --- /dev/null +++ b/module/logout.js @@ -0,0 +1,8 @@ +// 退出登录 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/logout`, {}, + {crypto: 'weapi', ua: 'pc', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/lyric.js b/module/lyric.js new file mode 100644 index 0000000..02d9f8c --- /dev/null +++ b/module/lyric.js @@ -0,0 +1,8 @@ +// 歌词 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/song/lyric?os=osx&id=${query.id}&lv=-1&kv=-1&tv=-1`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/mv_detail.js b/module/mv_detail.js new file mode 100644 index 0000000..0c69478 --- /dev/null +++ b/module/mv_detail.js @@ -0,0 +1,11 @@ +// MV详情 + +module.exports = (query, request) => { + const data = { + id: query.mvid + } + return request( + 'POST', `http://music.163.com/weapi/mv/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/mv_first.js b/module/mv_first.js new file mode 100644 index 0000000..59af71a --- /dev/null +++ b/module/mv_first.js @@ -0,0 +1,13 @@ +// 最新MV + +module.exports = (query, request) => { + const data = { + // 'offset': query.offset || 0, + limit: query.limit || 30, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/mv/first`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/mv_sub.js b/module/mv_sub.js new file mode 100644 index 0000000..b87e99b --- /dev/null +++ b/module/mv_sub.js @@ -0,0 +1,13 @@ +// 收藏与取消收藏MV + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'sub' : 'unsub') + const data = { + mvId: query.mvid, + mvIds: '["' + query.mvid + '"]' + } + return request( + 'POST', `http://music.163.com/weapi/mv/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/mv_url.js b/module/mv_url.js new file mode 100644 index 0000000..1338861 --- /dev/null +++ b/module/mv_url.js @@ -0,0 +1,12 @@ +// MV链接 + +module.exports = (query, request) => { + const data = { + id: query.id, + r: query.res || 1080 + } + return request( + 'POST', `http://music.163.com/weapi/song/enhance/play/mv/url`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personal_fm.js b/module/personal_fm.js new file mode 100644 index 0000000..128c3f3 --- /dev/null +++ b/module/personal_fm.js @@ -0,0 +1,8 @@ +// 私人FM + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/radio/get`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personalized.js b/module/personalized.js new file mode 100644 index 0000000..67b9296 --- /dev/null +++ b/module/personalized.js @@ -0,0 +1,14 @@ +// 推荐歌单 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 30, + offset: query.limit || 0, + total: true, + n: 1000 + } + return request( + 'POST', `http://music.163.com/weapi/personalized/playlist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personalized_djprogram.js b/module/personalized_djprogram.js new file mode 100644 index 0000000..9a3de44 --- /dev/null +++ b/module/personalized_djprogram.js @@ -0,0 +1,8 @@ +// 推荐电台 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/personalized/djprogram`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personalized_mv.js b/module/personalized_mv.js new file mode 100644 index 0000000..2381871 --- /dev/null +++ b/module/personalized_mv.js @@ -0,0 +1,8 @@ +// 推荐MV + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/personalized/mv`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personalized_newsong.js b/module/personalized_newsong.js new file mode 100644 index 0000000..7b8ae31 --- /dev/null +++ b/module/personalized_newsong.js @@ -0,0 +1,11 @@ +// 推荐新歌 + +module.exports = (query, request) => { + const data = { + type: "recommend" + } + return request( + 'POST', `http://music.163.com/weapi/personalized/newsong`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/personalized_privatecontent.js b/module/personalized_privatecontent.js new file mode 100644 index 0000000..8d130c5 --- /dev/null +++ b/module/personalized_privatecontent.js @@ -0,0 +1,8 @@ +// 独家放送 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/personalized/privatecontent`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_catlist.js b/module/playlist_catlist.js new file mode 100644 index 0000000..3d4b557 --- /dev/null +++ b/module/playlist_catlist.js @@ -0,0 +1,8 @@ +// 全部歌单分类 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/playlist/catalogue`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_create.js b/module/playlist_create.js new file mode 100644 index 0000000..da818e4 --- /dev/null +++ b/module/playlist_create.js @@ -0,0 +1,12 @@ +// 创建歌单 + +module.exports = (query, request) => { + query.cookie.os = 'pc' + const data = { + name: query.name + } + return request( + 'POST', `http://music.163.com/weapi/playlist/create`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_detail.js b/module/playlist_detail.js new file mode 100644 index 0000000..306c8f0 --- /dev/null +++ b/module/playlist_detail.js @@ -0,0 +1,13 @@ +// 歌单详情 + +module.exports = (query, request) => { + const data = { + id: query.id, + n: 100000, + s: query.s || 8 + } + return request( + 'POST', `http://music.163.com/weapi/v3/playlist/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_hot.js b/module/playlist_hot.js new file mode 100644 index 0000000..bda73b5 --- /dev/null +++ b/module/playlist_hot.js @@ -0,0 +1,8 @@ +// 热门歌单分类 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/playlist/hottags`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_subscribe.js b/module/playlist_subscribe.js new file mode 100644 index 0000000..be2ac35 --- /dev/null +++ b/module/playlist_subscribe.js @@ -0,0 +1,12 @@ +// 收藏与取消收藏歌单 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'subscribe' : 'unsubscribe') + const data = { + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/playlist/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_tracks.js b/module/playlist_tracks.js new file mode 100644 index 0000000..a612232 --- /dev/null +++ b/module/playlist_tracks.js @@ -0,0 +1,13 @@ +// 收藏单曲到歌单 从歌单删除歌曲 + +module.exports = (query, request) => { + const data = { + op: query.op, // del,add + pid: query.pid, // 歌单id + trackIds: '[' + query.tracks + ']' // 歌曲id + } + return request( + 'POST', `http://music.163.com/weapi/playlist/manipulate/tracks`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/playlist_update.js b/module/playlist_update.js new file mode 100644 index 0000000..ade75be --- /dev/null +++ b/module/playlist_update.js @@ -0,0 +1,16 @@ +// 编辑歌单 + +module.exports = (query, request) => { + query.cookie.os = 'pc' + query.desc = query.desc || '' + query.tags = query.tags || '' + const data = { + "/api/playlist/desc/update": `{"id":${query.id},"desc":"${query.desc}"}`, + "/api/playlist/tags/update": `{"id":${query.id},"tags":"${query.tags}"}`, + "/api/playlist/update/name": `{"id":${query.id},"name":"${query.name}"}` + } + return request( + 'POST', `http://music.163.com/weapi/batch`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/program_recommend.js b/module/program_recommend.js new file mode 100644 index 0000000..55f7a6e --- /dev/null +++ b/module/program_recommend.js @@ -0,0 +1,13 @@ +// 推荐节目 + +module.exports = (query, request) => { + const data = { + cateId: query.type, + limit: query.limit || 10, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/program/recommend/v1`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/recommend_resource.js b/module/recommend_resource.js new file mode 100644 index 0000000..d66913f --- /dev/null +++ b/module/recommend_resource.js @@ -0,0 +1,8 @@ +// 每日推荐歌单 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/discovery/recommend/resource`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/recommend_songs.js b/module/recommend_songs.js new file mode 100644 index 0000000..8804e50 --- /dev/null +++ b/module/recommend_songs.js @@ -0,0 +1,13 @@ +// 每日推荐歌曲 + +module.exports = (query, request) => { + const data = { + limit: 20, + offset: 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/v1/discovery/recommend/songs`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/related_allvideo.js b/module/related_allvideo.js new file mode 100644 index 0000000..1d6e635 --- /dev/null +++ b/module/related_allvideo.js @@ -0,0 +1,12 @@ +// 相关视频 + +module.exports = (query, request) => { + const data = { + id: query.id, + type: (/^\d+$/.test(query.id)) ? 0 : 1 + } + return request( + 'POST', `http://music.163.com/weapi/cloudvideo/v1/allvideo/rcmd`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/related_playlist.js b/module/related_playlist.js new file mode 100644 index 0000000..c7431ee --- /dev/null +++ b/module/related_playlist.js @@ -0,0 +1,32 @@ +// 相关歌单 + +module.exports = (query, request) => { + return request( + 'GET', `http://music.163.com/playlist?id=${query.id}`, {}, + {ua: 'pc', cookie: query.cookie, proxy: query.proxy} + ) + .then(response => { + try{ + const pattern = /
[\s\S]*?[\s\S]*?]*>([^<]+?)<\/a>[\s\S]*?]*>([^<]+?)<\/a>/g; + let result, playlists = [] + while((result = pattern.exec(response.body)) != null){ + playlists.push({ + creator: { + userId: result[4].slice('/user/home?id='.length), + nickname: result[5] + }, + coverImgUrl: result[1].slice(0,-('?param=50y50'.length)), + name: result[3], + id: result[2].slice('/playlist?id='.length) + }) + } + response.body = {code: 200, playlists: playlists} + return response + } + catch(err){ + response.status = 500 + response.body = {code: 500, msg: err.stack} + return Promise.reject(response) + } + }) +} diff --git a/module/resource_like.js b/module/resource_like.js new file mode 100644 index 0000000..9b3c0dc --- /dev/null +++ b/module/resource_like.js @@ -0,0 +1,17 @@ +// 点赞与取消点赞资源 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'like' : 'unlike') + query.type = { + 1: 'R_MV_5_', // MV + 4: 'A_DJ_1_', // 电台 + 5: 'R_VI_62_' // 视频 + }[query.type] + const data = { + threadId: query.type + query.id + } + return request( + 'POST', `http://music.163.com/weapi/resource/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/search.js b/module/search.js new file mode 100644 index 0000000..544aacb --- /dev/null +++ b/module/search.js @@ -0,0 +1,14 @@ +// 搜索 + +module.exports = (query, request) => { + const data = { + s: query.keywords, + type: query.type || 1, // 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频 + limit: query.limit || 30, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/search/get`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/search_hot.js b/module/search_hot.js new file mode 100644 index 0000000..8e9736c --- /dev/null +++ b/module/search_hot.js @@ -0,0 +1,11 @@ +// 热门搜索 + +module.exports = (query, request) => { + const data = { + type: 1111 + } + return request( + 'POST', `http://music.163.com/weapi/search/hot`, data, + {crypto: 'weapi', ua: 'mobile', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/search_multimatch.js b/module/search_multimatch.js new file mode 100644 index 0000000..402720a --- /dev/null +++ b/module/search_multimatch.js @@ -0,0 +1,12 @@ +// 多类型搜索 + +module.exports = (query, request) => { + const data = { + type: query.type || 1, + s: query.keywords || '' + } + return request( + 'POST', `http://music.163.com/weapi/search/suggest/multimatch`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/search_suggest.js b/module/search_suggest.js new file mode 100644 index 0000000..276de74 --- /dev/null +++ b/module/search_suggest.js @@ -0,0 +1,11 @@ +// 搜索建议 + +module.exports = (query, request) => { + const data = { + s: query.keywords || '' + } + return request( + 'POST', `http://music.163.com/weapi/search/suggest/web`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/send_playlist.js b/module/send_playlist.js new file mode 100644 index 0000000..1d9a3ba --- /dev/null +++ b/module/send_playlist.js @@ -0,0 +1,14 @@ +// 私信歌单 + +module.exports = (query, request) => { + const data = { + id: query.playlist, + type: 'playlist', + msg: query.msg, + userIds: '[' + query.user_ids + ']' + } + return request( + 'POST', `http://music.163.com/weapi/msg/private/send`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/send_text.js b/module/send_text.js new file mode 100644 index 0000000..6cd8715 --- /dev/null +++ b/module/send_text.js @@ -0,0 +1,14 @@ +// 私信 + +module.exports = (query, request) => { + const data = { + id: query.playlist, + type: 'text', + msg: query.msg, + userIds: '[' + query.user_ids + ']' + } + return request( + 'POST', `http://music.163.com/weapi/msg/private/send`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/simi_artist.js b/module/simi_artist.js new file mode 100644 index 0000000..9f616ac --- /dev/null +++ b/module/simi_artist.js @@ -0,0 +1,11 @@ +// 相似歌手 + +module.exports = (query, request) => { + const data = { + artistid: query.id + } + return request( + 'POST', `http://music.163.com/weapi/discovery/simiArtist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/simi_mv.js b/module/simi_mv.js new file mode 100644 index 0000000..6a1eb5c --- /dev/null +++ b/module/simi_mv.js @@ -0,0 +1,11 @@ +// 相似MV + +module.exports = (query, request) => { + const data = { + mvid: query.mvid + } + return request( + 'POST', `http://music.163.com/weapi/discovery/simiMV`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/simi_playlist.js b/module/simi_playlist.js new file mode 100644 index 0000000..3e8ad4b --- /dev/null +++ b/module/simi_playlist.js @@ -0,0 +1,13 @@ +// 相似歌单 + +module.exports = (query, request) => { + const data = { + songid: query.id, + limit: query.limit || 50, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/discovery/simiPlaylist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/simi_song.js b/module/simi_song.js new file mode 100644 index 0000000..7212615 --- /dev/null +++ b/module/simi_song.js @@ -0,0 +1,13 @@ +// 相似歌曲 + +module.exports = (query, request) => { + const data = { + songid: query.id, + limit: query.limit || 50, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/discovery/simiSong`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/simi_user.js b/module/simi_user.js new file mode 100644 index 0000000..b6a7f19 --- /dev/null +++ b/module/simi_user.js @@ -0,0 +1,13 @@ +// 相似用户 + +module.exports = (query, request) => { + const data = { + songid: query.id, + limit: query.limit || 50, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/discovery/simiUser`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/song_detail.js b/module/song_detail.js new file mode 100644 index 0000000..541b97e --- /dev/null +++ b/module/song_detail.js @@ -0,0 +1,13 @@ +// 歌曲详情 + +module.exports = (query, request) => { + query.ids = query.ids.split(/\s*,\s*/) + const data = { + c: '[' + query.ids.map(id => ('{"id":' + id + '}')).join(',') + ']', + ids: '[' + query.ids.join(',') + ']' + } + return request( + 'POST', `http://music.163.com/weapi/v3/song/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/song_url.js b/module/song_url.js new file mode 100644 index 0000000..da24713 --- /dev/null +++ b/module/song_url.js @@ -0,0 +1,15 @@ +// 歌曲链接 + +const crypto = require('crypto') + +module.exports = (query, request) => { + if(!('MUSIC_U' in query.cookie)) query.cookie._ntes_nuid = crypto.randomBytes(16).toString("hex") + const data = { + ids: '[' + parseInt(query.id) + ']', + br: parseInt(query.br || 999000) + } + return request( + 'POST', `http://music.163.com/weapi/song/enhance/player/url`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_album.js b/module/top_album.js new file mode 100644 index 0000000..841fa3e --- /dev/null +++ b/module/top_album.js @@ -0,0 +1,14 @@ +// 新碟上架 + +module.exports = (query, request) => { + const data = { + area: query.type || 'ALL', // ALL,ZH,EA,KR,JP + limit: query.limit || 50, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/album/new`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_artists.js b/module/top_artists.js new file mode 100644 index 0000000..86e43ac --- /dev/null +++ b/module/top_artists.js @@ -0,0 +1,13 @@ +// 热门歌手 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 50, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/artist/top`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_list.js b/module/top_list.js new file mode 100644 index 0000000..e738aeb --- /dev/null +++ b/module/top_list.js @@ -0,0 +1,39 @@ +// 排行榜 + +const topList = { + 0: "3779629", //云音乐新歌榜 + 1: "3778678", //云音乐热歌榜 + 2: "2884035", ///云音乐原创榜 + 3: "19723756", //云音乐飙升榜 + 4: "10520166", //云音乐电音榜 + 5: "180106", //UK排行榜周榜 + 6: "60198", //美国Billboard周榜 + 7: "21845217", //KTV嗨榜 + 8: "11641012", //iTunes榜 + 9: "120001", //Hit FM Top榜 + 10: "60131", //日本Oricon周榜 + 11: "3733003", //韩国Melon排行榜周榜 + 12: "60255", //韩国Mnet排行榜周榜 + 13: "46772709", //韩国Melon原声周榜 + 14: "112504", //中国TOP排行榜(港台榜) + 15: "64016", //中国TOP排行榜(内地榜) + 16: "10169002", //香港电台中文歌曲龙虎榜 + 17: "4395559", //华语金曲榜 + 18: "1899724", //中国嘻哈榜 + 19: "27135204", //法国 NRJ EuroHot 30周榜 + 20: "112463", //台湾Hito排行榜 + 21: "3812895", //Beatport全球电子舞曲榜 + 22: "71385702", //云音乐ACG音乐榜 + 23: "991319590" //云音乐嘻哈榜 +} + +module.exports = (query, request) => { + const data = { + id: topList[query.idx], + n: 10000 + } + return request( + 'POST', `http://music.163.com/weapi/v3/playlist/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_mv.js b/module/top_mv.js new file mode 100644 index 0000000..f54d1a3 --- /dev/null +++ b/module/top_mv.js @@ -0,0 +1,13 @@ +// MV排行榜 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 30, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/mv/toplist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_playlist.js b/module/top_playlist.js new file mode 100644 index 0000000..d7bdbd9 --- /dev/null +++ b/module/top_playlist.js @@ -0,0 +1,15 @@ +// 分类歌单 + +module.exports = (query, request) => { + const data = { + cat: query.cat || '全部', // 全部,华语,欧美,日语,韩语,粤语,小语种,流行,摇滚,民谣,电子,舞曲,说唱,轻音乐,爵士,乡村,R&B/Soul,古典,民族,英伦,金属,朋克,蓝调,雷鬼,世界音乐,拉丁,另类/独立,New Age,古风,后摇,Bossa Nova,清晨,夜晚,学习,工作,午休,下午茶,地铁,驾车,运动,旅行,散步,酒吧,怀旧,清新,浪漫,性感,伤感,治愈,放松,孤独,感动,兴奋,快乐,安静,思念,影视原声,ACG,儿童,校园,游戏,70后,80后,90后,网络歌曲,KTV,经典,翻唱,吉他,钢琴,器乐,榜单,00后 + order: query.order || 'hot', // hot,new + limit: query.limit || 50, + offset: query.offset || 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/playlist/list`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_playlist_highquality.js b/module/top_playlist_highquality.js new file mode 100644 index 0000000..beb73a3 --- /dev/null +++ b/module/top_playlist_highquality.js @@ -0,0 +1,14 @@ +// 精品歌单 + +module.exports = (query, request) => { + const data = { + cat: query.cat || '全部', // 全部,华语,欧美,韩语,日语,粤语,小语种,运动,ACG,影视原声,流行,摇滚,后摇,古风,民谣,轻音乐,电子,器乐,说唱,古典,爵士 + limit: query.limit || 50, + lasttime: query.before || 0, // 歌单updateTime + total: true + } + return request( + 'POST', `http://music.163.com/weapi/playlist/highquality/list`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/top_song.js b/module/top_song.js new file mode 100644 index 0000000..304d94e --- /dev/null +++ b/module/top_song.js @@ -0,0 +1,8 @@ +// 最新单曲(暂时废弃?) + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/discovery/new/songs`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/toplist.js b/module/toplist.js new file mode 100644 index 0000000..2d16185 --- /dev/null +++ b/module/toplist.js @@ -0,0 +1,8 @@ +// 所有榜单介绍 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/toplist`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/toplist_artist.js b/module/toplist_artist.js new file mode 100644 index 0000000..7bcad97 --- /dev/null +++ b/module/toplist_artist.js @@ -0,0 +1,14 @@ +// 歌手榜 + +module.exports = (query, request) => { + const data = { + type: 1, + limit: 100, + offset: 0, + total: true + } + return request( + 'POST', `http://music.163.com/weapi/toplist/artist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/toplist_detail.js b/module/toplist_detail.js new file mode 100644 index 0000000..c4ddb07 --- /dev/null +++ b/module/toplist_detail.js @@ -0,0 +1,8 @@ +// 所有榜单内容摘要 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/toplist/detail`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_audio.js b/module/user_audio.js new file mode 100644 index 0000000..3b22707 --- /dev/null +++ b/module/user_audio.js @@ -0,0 +1,11 @@ +// 用户创建的电台 + +module.exports = (query, request) => { + const data = { + userId: query.uid + } + return request( + 'POST', `http://music.163.com/weapi/djradio/get/byuser`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_cloud.js b/module/user_cloud.js new file mode 100644 index 0000000..d60b583 --- /dev/null +++ b/module/user_cloud.js @@ -0,0 +1,12 @@ +// 云盘数据 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 200, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/v1/cloud/get`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_cloud_search.js b/module/user_cloud_search.js new file mode 100644 index 0000000..d17b5b9 --- /dev/null +++ b/module/user_cloud_search.js @@ -0,0 +1,12 @@ +// 云盘数据详情?(暂时不要使用) + +module.exports = (query, request) => { + const data = { + byids: query.id, + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/v1/cloud/get/byids`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_detail.js b/module/user_detail.js new file mode 100644 index 0000000..967f804 --- /dev/null +++ b/module/user_detail.js @@ -0,0 +1,8 @@ +// 用户详情 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/v1/user/detail/${query.uid}`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_dj.js b/module/user_dj.js new file mode 100644 index 0000000..a6205d7 --- /dev/null +++ b/module/user_dj.js @@ -0,0 +1,12 @@ +// 用户电台节目 + +module.exports = (query, request) => { + const data = { + limit: query.limit || 30, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/dj/program/${query.uid}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_event.js b/module/user_event.js new file mode 100644 index 0000000..5dea33f --- /dev/null +++ b/module/user_event.js @@ -0,0 +1,12 @@ +// 用户动态 + +module.exports = (query, request) => { + const data = { + time: -1, + getcounts: true + } + return request( + 'POST', `http://music.163.com/weapi/event/get/${query.uid}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_followeds.js b/module/user_followeds.js new file mode 100644 index 0000000..b451e91 --- /dev/null +++ b/module/user_followeds.js @@ -0,0 +1,13 @@ +// 关注TA的人(粉丝) + +module.exports = (query, request) => { + const data = { + userId: query.uid, + limit: query.limit || 30, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/user/getfolloweds`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_follows.js b/module/user_follows.js new file mode 100644 index 0000000..db69ee4 --- /dev/null +++ b/module/user_follows.js @@ -0,0 +1,13 @@ +// TA关注的人(关注) + +module.exports = (query, request) => { + const data = { + offset: query.offset || 0, + limit: query.limit || 30, + order: true + } + return request( + 'POST', `http://music.163.com/weapi/user/getfollows/${query.uid}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_playlist.js b/module/user_playlist.js new file mode 100644 index 0000000..8df830c --- /dev/null +++ b/module/user_playlist.js @@ -0,0 +1,13 @@ +// 用户歌单 + +module.exports = (query, request) => { + const data = { + uid: query.uid, + limit: query.limit || 30, + offset: query.offset || 0 + } + return request( + 'POST', `http://music.163.com/weapi/user/playlist`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_record.js b/module/user_record.js new file mode 100644 index 0000000..4b73476 --- /dev/null +++ b/module/user_record.js @@ -0,0 +1,12 @@ +// 听歌排行 + +module.exports = (query, request) => { + const data = { + uid: query.uid, + type: query.type || 1 // 1: 最近一周, 0: 所有时间 + } + return request( + 'POST', `http://music.163.com/weapi/v1/play/record`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_subcount.js b/module/user_subcount.js new file mode 100644 index 0000000..b214d13 --- /dev/null +++ b/module/user_subcount.js @@ -0,0 +1,8 @@ +// 收藏计数 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/subcount`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/user_update.js b/module/user_update.js new file mode 100644 index 0000000..e0ce885 --- /dev/null +++ b/module/user_update.js @@ -0,0 +1,17 @@ +// 编辑用户信息 + +module.exports = (query, request) => { + const data = { + avatarImgId: "0", + birthday: query.birthday, + city: query.city, + gender: query.gender, + nickname: query.nickname, + province: query.province, + signature: query.signature + } + return request( + 'POST', `http://music.163.com/weapi/user/profile/update`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/video_detail.js b/module/video_detail.js new file mode 100644 index 0000000..0c938b5 --- /dev/null +++ b/module/video_detail.js @@ -0,0 +1,11 @@ +// 视频详情 + +module.exports = (query, request) => { + const data = { + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/cloudvideo/v1/video/detail`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/video_sub.js b/module/video_sub.js new file mode 100644 index 0000000..9499eb3 --- /dev/null +++ b/module/video_sub.js @@ -0,0 +1,12 @@ +// 收藏与取消收藏视频 + +module.exports = (query, request) => { + query.t = (query.t == 1 ? 'sub' : 'unsub') + const data = { + id: query.id + } + return request( + 'POST', `http://music.163.com/weapi/cloudvideo/video/${query.t}`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/video_url.js b/module/video_url.js new file mode 100644 index 0000000..7aaf17c --- /dev/null +++ b/module/video_url.js @@ -0,0 +1,12 @@ +// 视频链接 + +module.exports = (query, request) => { + const data = { + ids: '["' + query.id + '"]', + resolution: query.res || 1080 + } + return request( + 'POST', `http://music.163.com/weapi/cloudvideo/playurl`, data, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/module/weblog.js b/module/weblog.js new file mode 100644 index 0000000..73f2147 --- /dev/null +++ b/module/weblog.js @@ -0,0 +1,8 @@ +// 操作记录 + +module.exports = (query, request) => { + return request( + 'POST', `http://music.163.com/weapi/feedback/weblog`, {}, + {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy} + ) +} \ No newline at end of file diff --git a/util/init.js b/util/init.js index bf36199..c6c10f8 100644 --- a/util/init.js +++ b/util/init.js @@ -1,10 +1,10 @@ function randomString(pattern, length){ - return Array.apply(null, {length: length}).map(() => (pattern[Math.floor(Math.random() * pattern.length)])).join('') + return Array.apply(null, {length: length}).map(() => (pattern[Math.floor(Math.random() * pattern.length)])).join('') } function completeCookie(cookie){ let origin = (cookie || '').split(/;\s*/).map(element => (element.split('=')[0])), extra = [] - let now = (new Date).getTime() + let now = Date.now() if(!origin.includes('JSESSIONID-WYYY')){ let expire = new Date(now + 1800000) //30 minutes diff --git a/util/request.js b/util/request.js new file mode 100644 index 0000000..3ff5f0a --- /dev/null +++ b/util/request.js @@ -0,0 +1,85 @@ +const encrypt = require('./crypto.js') +const request = require('request') +const queryString = require('querystring') + +// request.debug = false + +function chooseUserAgent(ua) { + const userAgentList = [ + 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', + 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', + 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', + 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Mobile Safari/537.36', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89;GameHelper', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A300 Safari/602.1', + 'Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A300 Safari/602.1', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:46.0) Gecko/20100101 Firefox/46.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:46.0) Gecko/20100101 Firefox/46.0', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/13.10586' + ] + let index = 0 + if(typeof(ua) == 'undefined') + index = Math.floor(Math.random() * userAgentList.length) + else if(ua == 'mobile') + index = Math.floor(Math.random() * 7) + else if(ua == 'pc') + index = Math.floor(Math.random() * 5) + 8 + else + return ua + return userAgentList[index] +} + +function createRequest(method, url, data, options){ + return new Promise((resolve, reject) => { + + let headers = {'User-Agent': chooseUserAgent(options.ua)} + if(method.toUpperCase() == 'POST') headers['Content-Type'] = 'application/x-www-form-urlencoded' + if(url.indexOf('music.163.com') != -1) headers['Referer'] = 'http://music.163.com' + // headers['X-Real-IP'] = '118.88.88.88' + + if(typeof(options.cookie) === 'object') + headers['Cookie'] = Object.keys(options.cookie).map(key => (encodeURIComponent(key) + '=' + encodeURIComponent(options.cookie[key]))).join('; ') + else if(options.cookie) + headers['Cookie'] = options.cookie + + if(options.crypto == 'weapi'){ + const csrfToken = (headers['Cookie'] || '').match(/_csrf=([^(;|$)]+)/) + data.csrf_token = (csrfToken ? csrfToken[1] : '') + data = encrypt(data) + } + + const answer = {status: 500, body: {}, cookie: []} + request( + {method: method, url: url, headers: headers, body: queryString.stringify(data), proxy: options.proxy}, + (err, res, body) => { + if(err){ + answer.status = 502 + answer.body = {code: 502, msg: err.stack} + reject(answer) + } + else{ + answer.cookie = (res.headers['set-cookie'] || []).map(x => x.replace(/\s*Domain=[^(;|$)]+;*/, '')) + try{ + answer.body = JSON.parse(body) + answer.status = answer.body.code || res.statusCode + } + catch(e){ + answer.body = body + answer.status = res.statusCode + } + answer.status = (100 < answer.status && answer.status < 600) ? answer.status : 400 + if(answer.status == 200) + resolve(answer) + else + reject(answer) + } + } + ) + }) +} + +module.exports = createRequest