From 45e5962489c6a40e2b435c84ce3ab25fdc39304e Mon Sep 17 00:00:00 2001 From: zhiyu1998 Date: Fri, 24 Mar 2023 17:38:23 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E6=9B=B4=E6=94=B9?= =?UTF-8?q?=E6=B3=A2=E7=82=B9=E9=9F=B3=E4=B9=90=E7=82=B9mv=E4=B8=BA?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=20&=20pref:=20=E4=BC=98=E5=8C=96=E7=BD=91?= =?UTF-8?q?=E6=98=93=E4=BA=91=E9=9F=B3=E4=B9=90=E8=A7=A3=E6=9E=90=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/neteasepro.js | 56 ++++----------------------------- apps/tools.js | 78 ++++++++++++++-------------------------------- config/help.yaml | 4 +-- utils/common.js | 48 +++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 107 deletions(-) diff --git a/apps/neteasepro.js b/apps/neteasepro.js index f2850ec..a6960d3 100644 --- a/apps/neteasepro.js +++ b/apps/neteasepro.js @@ -14,9 +14,8 @@ import { getUserRecord, } from "../utils/netease.js"; import { ha12store, store2ha1 } from "../utils/encrypt.js"; -import fetch from "node-fetch"; +import { downloadMp3 } from "../utils/common.js"; import _ from "lodash"; -import { mkdirsSync } from "../utils/file.js"; export class neteasepro extends plugin { constructor() { @@ -151,6 +150,7 @@ export class neteasepro extends plugin { musicUrlReg2.exec(message)?.[3] || musicUrlReg.exec(message)?.[2] || /id=(\d+)/.exec(message)[1]; + const downloadPath = `./data/rcmp4/${this.e.group_id || this.e.user_id}` // 是游客 if (!(await redis.get(await this.getRedisKey(e.user_id)))) { // 是小程序 @@ -171,7 +171,7 @@ export class neteasepro extends plugin { e.reply(`识别:网易云音乐,${title}`); } // 下载游客歌曲 - this.downloadMp3(`https://music.163.com/song/media/outer/url?id=${id}`, "follow") + downloadMp3(`https://music.163.com/song/media/outer/url?id=${id}`, downloadPath, "follow") .then(path => { Bot.acquireGfs(e.group_id).upload(fs.readFileSync(path), "/", `${id}.mp3`); }) @@ -193,7 +193,7 @@ export class neteasepro extends plugin { const song = res.songs[0]; return `${song?.name}-${song?.ar?.[0].name}`.replace(/[\/\?<>\\:\*\|".… ]/g, ""); }); - await this.downloadMp3(userDownloadUrl) + await downloadMp3(userDownloadUrl, downloadPath) .then(path => { Bot.acquireGfs(e.group_id).upload(fs.readFileSync(path), "/", `${title}.mp3`); }) @@ -214,12 +214,12 @@ export class neteasepro extends plugin { } let userData = JSON.parse(userDataJson); const cookie = userData?.cookie; - console.log(cookie); + logger.mark(cookie); // 解析cookie userData.cookie = await store2ha1(cookie); // 检查cookie是否可用 const userInfo = await getLoginStatus(userData.cookie); - console.log(userData); + logger.mark(userData); if (_.isNil(userInfo.profile)) { e.reply("cookie已经过期,请重新#网易云登录!"); // 删除过期的cookie @@ -335,50 +335,6 @@ export class neteasepro extends plugin { return forwardMsg; } - /** - * 下载mp3 - * @param mp3Url - * @param redirect - * @returns {Promise} - */ - async downloadMp3(mp3Url, redirect = "manual") { - return fetch(mp3Url, { - headers: { - "User-Agent": - "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36", - }, - responseType: "stream", - redirect: redirect, - }).then(res => { - let path = `./data/rcmp4/${this.e.group_id || this.e.user_id}`; - // 如果没有目录就创建一个 - if (!fs.existsSync(path)) { - mkdirsSync(path); - } - // 补充保存文件名 - path += "/temp.mp3"; - if (fs.existsSync(path)) { - console.log(`视频已存在`); - fs.unlinkSync(path); - } - // 开始下载 - const fileStream = fs.createWriteStream(path); - res.body.pipe(fileStream); - return new Promise((resolve, reject) => { - fileStream.on("finish", () => { - fileStream.close(() => { - resolve(path); - }); - }); - fileStream.on("error", err => { - fs.unlink(path, () => { - reject(err); - }); - }); - }); - }); - } - // 获取redis的key async getRedisKey(user_id) { return `Yz:rconsole:netease:${user_id}`; diff --git a/apps/tools.js b/apps/tools.js index 48e910c..e78ed2a 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -11,7 +11,7 @@ import { mkdirsSync } from "../utils/file.js"; import { downloadBFile, getDownloadUrl, mergeFileToMp4, getDynamic } from "../utils/bilibili.js"; import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../utils/acfun.js"; import { transMap, douyinTypeMap, XHS_CK, TEN_THOUSAND } from "../utils/constant.js"; -import { getIdVideo, generateRandomStr } from "../utils/common.js"; +import { getIdVideo, generateRandomStr, downloadMp3 } from "../utils/common.js"; import config from "../model/index.js"; import Translate from "../utils/trans-strategy.js"; import { getXB } from "../utils/x-bogus.js"; @@ -73,7 +73,7 @@ export class tools extends plugin { permission: "master", }, { - reg: "^#波点音乐(.*)", + reg: "(h5app.kuwo.cn)", fnc: "bodianMusic", }, ], @@ -913,67 +913,37 @@ export class tools extends plugin { return true; } + // 波点音乐解析 async bodianMusic(e) { - const msg = e.msg.replace("#波点音乐").trim(); - const API = `https://xiaobai.klizi.cn/API/music/bodian.php?msg=${msg}&n=&max=`; - // 获取列表 - const thisMethod = this; + // 例子:https://h5app.kuwo.cn/m/bodian/playMusic.html?uid=3216773&musicId=192015898&opusId=&extendType=together + const id = /(?=musicId).*?(?=&)/.exec(e.msg.trim())[0].replace("musicId=", ""); + const API = `https://bd-api.kuwo.cn/api/service/music/audioUrl/${id}?format=mp3&br=320kmp3&songType=&fromList=&weListenUid=&weListenDevId=`; + const headers = { + "User-Agent": "bodian/106 CFNetwork/1399 Darwin/22.1.0", + "devId": `95289318-8847-43D5-8477-85296654785${String.fromCharCode(65 + Math.floor(Math.random() * 26))}`, + "Host": "bd-api.kuwo.cn", + "plat": "ip", + "ver": "3.1.0", + "Cache-Control": "no-cache", + "channel": "appstore" + } await axios .get(API, { - headers: { - HOST: "xiaobai.klizi.cn", - "User-Agent": - "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36", - }, + headers }) .then(resp => { - e.reply("请选择一个要播放的视频:\n" + resp.data); - thisMethod.setContext("bodianMusicContext"); + const respJson = resp.data; + const audioUrl = respJson.data.audioUrl; + downloadMp3(audioUrl, `${this.defaultPath}${this.e.group_id || this.e.user_id}`).then(path => { + Bot.acquireGfs(e.group_id).upload(fs.readFileSync(path), "/", `${respJson.reqId}.mp3`); + }) + .catch(err => { + console.error(`下载音乐失败,错误信息为: ${err.message}`); + }); }); return true; } - /** - * @link bodianMusic 波点音乐上下文 - * @returns {Promise} - */ - async bodianMusicContext() { - // 当前消息 - const curMsg = this.e; - // 上一个消息 - const preMsg = await this.getContext().bodianMusicContext; - const msg = preMsg.msg.replace("#波点音乐", "").trim(); - const API = `https://xiaobai.klizi.cn/API/music/bodian.php?msg=${msg}&n=${Number( - curMsg.msg, - )}&max=`; - const thisMethod = this; - axios - .get(API, { - headers: { - HOST: "xiaobai.klizi.cn", - "User-Agent": - "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36", - }, - }) - .then(async res => { - // 如果没有,直接返回 - if (res.data.lowUrl === null || res.data.highUrl === null) { - return; - } - // 波点音乐信息 - const { songName, artist, coverUrl, highUrl, lowUrl, shortLowUrl } = res.data; - curMsg.reply([`${songName}-${artist}\n`, segment.image(coverUrl)]); - // 下载 && 发送 - await thisMethod.downloadVideo(lowUrl).then(path => { - curMsg.reply(segment.video(path + "/temp.mp4")); - }); - }) - .catch(err => { - curMsg.reply("发生网络错误,请重新发送!"); - thisMethod.finish("bodianMusicContext"); - }); - } - /** * 哔哩哔哩下载 * @param title diff --git a/config/help.yaml b/config/help.yaml index 8dc0d72..bac0c98 100644 --- a/config/help.yaml +++ b/config/help.yaml @@ -51,8 +51,8 @@ title: "网易云音乐" desc: 网易云音乐解析 - icon: bodian - title: "#波点音乐" - desc: 波点云音乐点MV + title: "波点音乐" + desc: 波点云音乐点解析 - icon: ins title: "Instagram" desc: 解析Instagram diff --git a/utils/common.js b/utils/common.js index 4f66ebe..40009ce 100644 --- a/utils/common.js +++ b/utils/common.js @@ -2,6 +2,8 @@ import schedule from "node-schedule"; import common from "../../../lib/common/common.js"; import axios from "axios"; import fs from "node:fs"; +import fetch from "node-fetch"; +import { mkdirsSync } from "./file.js"; /** * 请求模板 @@ -118,4 +120,48 @@ function generateRandomStr(randomlength = 16){ return random_str } -export { jFeatch, autoTask, retry, getIdVideo, generateRandomStr }; \ No newline at end of file +/** + * 下载mp3 + * @param mp3Url MP3地址 + * @param path 下载目录 + * @param redirect 是否要重定向 + * @returns {Promise} + */ +async function downloadMp3(mp3Url, path, redirect = "manual") { + return fetch(mp3Url, { + headers: { + "User-Agent": + "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36", + }, + responseType: "stream", + redirect: redirect, + }).then(res => { + // 如果没有目录就创建一个 + if (!fs.existsSync(path)) { + mkdirsSync(path); + } + // 补充保存文件名 + path += "/temp.mp3"; + if (fs.existsSync(path)) { + console.log(`视频已存在`); + fs.unlinkSync(path); + } + // 开始下载 + const fileStream = fs.createWriteStream(path); + res.body.pipe(fileStream); + return new Promise((resolve, reject) => { + fileStream.on("finish", () => { + fileStream.close(() => { + resolve(path); + }); + }); + fileStream.on("error", err => { + fs.unlink(path, () => { + reject(err); + }); + }); + }); + }); +} + +export { jFeatch, autoTask, retry, getIdVideo, generateRandomStr, downloadMp3 };