From 7e820cbf26c5ff6df5d6b4927fdf0feb181e1771 Mon Sep 17 00:00:00 2001 From: zhiyu1998 <542716863@qq.com> Date: Tue, 30 Apr 2024 22:35:56 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix:=20V1.6.7-lts=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=BD=91=E6=98=93=E4=BA=91=E9=9F=B3=E4=B9=90=20&=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9A=AE=E7=9A=AE=E8=99=BE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复函数`downloadMp3`导致的一系列下载问题 2. 修复netease music下载 3. 修复皮皮虾的问题 4. 修正部分注释 --- apps/tools.js | 85 +++++++++++++++++++++-------------- constants/tools.js | 2 +- utils/common.js | 67 ++++++++++++++++----------- utils/general-link-adapter.js | 4 +- 4 files changed, 95 insertions(+), 63 deletions(-) diff --git a/apps/tools.js b/apps/tools.js index 2c272c9..029e090 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -991,6 +991,15 @@ export class tools extends plugin { async netease(e) { let message = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim(); + // 处理短号,此时会变成y.music.163.com + if (message.includes("163cn.tv")) { + message = /(http:|https:)\/\/163cn\.tv\/([a-zA-Z1-9]+)/.exec(message)?.[0] + logger.info(message) + message = await axios.head(message).then((resp) => { + return resp.request.res.responseUrl; + }); + } + // 处理网页链接 const musicUrlReg = /(http:|https:)\/\/music.163.com\/song\/media\/outer\/url\?id=(\d+)/; const musicUrlReg2 = /(http:|https:)\/\/y.music.163.com\/m\/song\?(.*)&id=(\d+)/; const id = @@ -1005,41 +1014,49 @@ export class tools extends plugin { if (typeof message !== "string") { return false; } - try { - // 小程序 - const musicJson = JSON.parse(message); - const { preview, title, desc } = musicJson.meta.music || musicJson.meta.news; - e.reply([`识别:网易云音乐,${ title }--${ desc }`, segment.image(preview)]); - JSON.parse(message); - return true; - } catch (err) { - axios.get(NETEASE_SONG_DOWNLOAD.replace("{}", id), { - 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", - }, - }).then(async resp => { - const url = await resp.data.data?.[0].url; - // 获取歌曲信息 - const title = await axios.get(NETEASE_SONG_DETAIL.replace("{}", id)).then(res => { - const song = res.data.songs[0]; - return `${ song?.name }-${ song?.ar?.[0].name }`.replace(/[\/\?<>\\:\*\|".… ]/g, ""); + axios.get(NETEASE_SONG_DOWNLOAD.replace("{}", id), { + 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", + }, + }).then(async resp => { + logger.info(resp.data) + let url = await resp.data.data?.[0].url; + // 获取歌曲信息 + let title = await axios.get(NETEASE_SONG_DETAIL.replace("{}", id)).then(res => { + const song = res.data.songs[0]; + return `${ song?.name }-${ song?.ar?.[0].name }`.replace(/[\/\?<>\\:\*\|".… ]/g, ""); + }); + // 一般这个情况是VIP歌曲 + if (url == null) { + // 临时接口 + const vipMusicData = await axios.get(`https://www.hhlqilongzhu.cn/api/dg_wyymusic.php?gm=${ title }&n=1&type=json`, { + 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", + }, }); - e.reply(`识别:网易云音乐,${ title }`); - // const mvUrlJson = await getKugouMv(title, 1, 1, 0); - // const mvUrl = mvUrlJson.map(item => item.mv_url)?.[0]; - // this.downloadVideo(mvUrl).then(path => { - // e.reply(segment.video(path + "/temp.mp4")); - // }); - downloadMp3(url, 'follow').then(path => { - e.group.sendFile(fs.readFileSync(path), '/', `${ title.replace(/[\/\?<>\\:\*\|".… ]/g, '') }.mp3`); - }) - .catch(err => { - console.error(`下载音乐失败,错误信息为: ${ err.message }`); - }); - }) - return true; - } + title += "\nR插件检测到当前为VIP音乐,正在转换..."; + url = vipMusicData.data.music_url; + } + e.reply(`识别:网易云音乐,${ title }`); + // const mvUrlJson = await getKugouMv(title, 1, 1, 0); + // const mvUrl = mvUrlJson.map(item => item.mv_url)?.[0]; + // this.downloadVideo(mvUrl).then(path => { + // e.reply(segment.video(path + "/temp.mp4")); + // }); + downloadMp3(url, 'follow').then(path => { + // 判断是不是icqq + if (e.bot?.sendUni) { + e.group.fs.upload(path); + } else { + e.group.sendFile(path); + } + }).catch(err => { + logger.error(`下载音乐失败,错误信息为: ${ err.message }`); + }); + }) + return true; } // 微博解析 diff --git a/constants/tools.js b/constants/tools.js index 22bf60a..c02f271 100644 --- a/constants/tools.js +++ b/constants/tools.js @@ -92,7 +92,7 @@ export const TWITTER_TWEET_INFO = "https://api.twitter.com/2/tweets?ids={}" export const XHS_REQ_LINK = "https://www.xiaohongshu.com/explore/" /** - * 🍉 的请求链接 + * 通用解析的请求链接 * @type {string} */ export const GENERAL_REQ_LINK = { diff --git a/utils/common.js b/utils/common.js index 2732fc1..5ccd6f1 100644 --- a/utils/common.js +++ b/utils/common.js @@ -130,39 +130,54 @@ export function generateRandomStr(randomlength = 16) { * @returns {Promise} */ export async function downloadMp3(mp3Url, path, redirect = "manual") { - return fetch(mp3Url, { + // 如果没有目录就创建一个 + await mkdirIfNotExists(path) + + // 补充保存文件名 + path += "/temp.mp3"; + if (fs.existsSync(path)) { + console.log(`音频已存在`); + fs.unlinkSync(path); + } + + // 发起请求 + const response = await 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(async res => { - // 如果没有目录就创建一个 - await mkdirIfNotExists(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); - }); - }); - }); }); + + if (!response.ok) { + throw new Error(`Failed to fetch ${response.statusText}`); + } + + try { + const response = await axios({ + method: 'get', + url: mp3Url, + responseType: 'stream', + 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" + } + }); + + // 开始下载 + const writer = fs.createWriteStream(path); + + response.data.pipe(writer); + + return new Promise((resolve, reject) => { + writer.on('finish', () => resolve(path)); + writer.on('error', reject); + }); + + } catch (error) { + console.error(`下载音乐失败,错误信息为: ${error.message}`); + throw error; + } } /** diff --git a/utils/general-link-adapter.js b/utils/general-link-adapter.js index b450f30..3a8c9bb 100644 --- a/utils/general-link-adapter.js +++ b/utils/general-link-adapter.js @@ -33,6 +33,7 @@ class GeneralLinkAdapter { * @returns {*} */ createReqLink(externalInterface, requestURL) { + // 这里必须使用{ ...GENERAL_REQ_LINK_2 }赋值,不然就是对象的引用赋值,会造成全局数据问题! let reqLink = { ...externalInterface }; reqLink.link = reqLink.link.replace("{}", requestURL); return reqLink; @@ -81,8 +82,7 @@ class GeneralLinkAdapter { async pipixia(link) { const msg = /https:\/\/h5\.pipix\.com\/s\/[A-Za-z0-9]+/.exec(link)?.[0]; - // 这里必须使用{ ...GENERAL_REQ_LINK_2 }赋值,不然就是对象的引用赋值,会造成全局数据问题! - const reqLink = this.createReqLink(GENERAL_REQ_LINK_2, msg); + const reqLink = this.createReqLink(GENERAL_REQ_LINK, msg); return { name: "皮皮虾", reqLink }; }