mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
609 lines
26 KiB
JavaScript
609 lines
26 KiB
JavaScript
import axios from "axios";
|
||
import fs from "node:fs";
|
||
import { formatTime, toGBorTB } from '../utils/other.js'
|
||
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
|
||
import PickSongList from "../model/pick-song.js";
|
||
import NeteaseMusicInfo from '../model/neteaseMusicInfo.js'
|
||
import { NETEASE_API_CN, NETEASE_SONG_DOWNLOAD, NETEASE_TEMP_API } from "../constants/tools.js";
|
||
import { COMMON_USER_AGENT, REDIS_YUNZAI_ISOVERSEA, REDIS_YUNZAI_SONGINFO, REDIS_YUNZAI_CLOUDSONGLIST } from "../constants/constant.js";
|
||
import { downloadAudio } from "../utils/common.js";
|
||
import { redisExistKey, redisGetKey, redisSetKey } from "../utils/redis-util.js";
|
||
import { checkAndRemoveFile } from "../utils/file.js";
|
||
import { sendMusicCard } from "../utils/yunzai-util.js";
|
||
import config from "../model/config.js";
|
||
import FormData from 'form-data';
|
||
|
||
export class songRequest extends plugin {
|
||
constructor() {
|
||
super({
|
||
name: "R插件点歌",
|
||
dsc: "实现快捷点歌",
|
||
priority: 300,
|
||
rule: [
|
||
{
|
||
reg: '^#点歌|#听[1-9][0-9]*|#听[1-9]*$',
|
||
fnc: 'pickSong'
|
||
},
|
||
{
|
||
reg: "^#播放(.*)",
|
||
fnc: "playSong"
|
||
},
|
||
{
|
||
reg: "^#?上传$",
|
||
fnc: "upLoad"
|
||
},
|
||
{
|
||
reg: '^#?我的云盘$',
|
||
fnc: 'myCloud',
|
||
permission: 'master'
|
||
},
|
||
{
|
||
reg: '^#?云盘更新|#?更新云盘$',
|
||
fnc: 'songCloudUpdate',
|
||
permission: 'master'
|
||
},
|
||
{
|
||
reg: '^#?上传云盘|#?上传网盘$',
|
||
fnc: 'uploadCloud',
|
||
permission: 'master'
|
||
},
|
||
{
|
||
reg: '^#?清除云盘缓存$',
|
||
fnc: 'cleanCloudData',
|
||
permission: 'master'
|
||
}
|
||
]
|
||
});
|
||
this.toolsConfig = config.getConfig("tools");
|
||
// 加载网易云Cookie
|
||
this.neteaseCookie = this.toolsConfig.neteaseCookie
|
||
// 加载是否转化群语音
|
||
this.isSendVocal = this.toolsConfig.isSendVocal
|
||
// 加载是否自建服务器
|
||
this.useLocalNeteaseAPI = this.toolsConfig.useLocalNeteaseAPI
|
||
// 加载自建服务器API
|
||
this.neteaseCloudAPIServer = this.toolsConfig.neteaseCloudAPIServer
|
||
// 加载网易云解析最高音质
|
||
this.neteaseCloudAudioQuality = this.toolsConfig.neteaseCloudAudioQuality
|
||
// 加载识别前缀
|
||
this.identifyPrefix = this.toolsConfig.identifyPrefix;
|
||
// 加载是否开启网易云点歌功能
|
||
this.useNeteaseSongRequest = this.toolsConfig.useNeteaseSongRequest
|
||
// 加载点歌列表长度
|
||
this.songRequestMaxList = this.toolsConfig.songRequestMaxList
|
||
// 视频保存路径
|
||
this.defaultPath = this.toolsConfig.defaultPath;
|
||
// uid
|
||
this.uid = this.toolsConfig.neteaseUserId
|
||
}
|
||
|
||
async pickSong(e) {
|
||
// 判断功能是否开启
|
||
if (!this.useNeteaseSongRequest) {
|
||
logger.info('当前未开启网易云点歌')
|
||
return false
|
||
}
|
||
// 获取自定义API
|
||
const autoSelectNeteaseApi = await this.pickApi()
|
||
// 只在群里可以使用
|
||
let group_id = e.group.group_id
|
||
if (!group_id) return
|
||
// 初始化
|
||
let songInfo = await redisGetKey(REDIS_YUNZAI_SONGINFO) || []
|
||
const saveId = songInfo.findIndex(item => item.group_id === e.group.group_id)
|
||
let musicDate = { 'group_id': group_id, data: [] }
|
||
// 获取搜索歌曲列表信息
|
||
let detailUrl = autoSelectNeteaseApi + "/song/detail?ids={}" //歌曲详情API
|
||
if (e.msg.replace(/\s+/g, "").match(/点歌(.+)/)) {
|
||
const songKeyWord = e.msg.replace(/\s+/g, "").match(/点歌(.+)/)[1]
|
||
// 获取云盘歌单列表
|
||
const cloudSongList = await this.getCloudSong()
|
||
// 搜索云盘歌单并进行搜索
|
||
const matchedSongs = await cloudSongList.filter(({ songName, singerName }) =>
|
||
songName.includes(songKeyWord) || singerName.includes(songKeyWord)
|
||
);
|
||
// 计算列表数 计算偏移量
|
||
let songListCount = matchedSongs.length >= this.songRequestMaxList ? this.songRequestMaxList : matchedSongs.length
|
||
let searchCount = this.songRequestMaxList - songListCount
|
||
for (let i = 0; i < songListCount; i++) {
|
||
musicDate.data.push({
|
||
'id': matchedSongs[i].id,
|
||
'songName': matchedSongs[i].songName,
|
||
'singerName': matchedSongs[i].singerName,
|
||
'duration': matchedSongs[i].duration
|
||
});
|
||
}
|
||
let searchUrl = autoSelectNeteaseApi + '/search?keywords={}&limit=' + searchCount + '&offset=' + songListCount//搜索API
|
||
searchUrl = searchUrl.replace("{}", songKeyWord)
|
||
await axios.get(searchUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT
|
||
},
|
||
}).then(async res => {
|
||
if (res.data.result.songs || musicDate.data[0]) {
|
||
try {
|
||
for (const info of res.data.result.songs) {
|
||
musicDate.data.push({
|
||
'id': info.id,
|
||
'songName': info.name,
|
||
'singerName': info.artists[0]?.name,
|
||
'duration': formatTime(info.duration)
|
||
});
|
||
}
|
||
} catch (error) {
|
||
logger.info('并未获取云服务歌曲')
|
||
}
|
||
const ids = musicDate.data.map(item => item.id).join(',');
|
||
detailUrl = detailUrl.replace("{}", ids)
|
||
await axios.get(detailUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT
|
||
},
|
||
}).then(res => {
|
||
for (let i = 0; i < res.data.songs.length; i++) {
|
||
musicDate.data[i].cover = res.data.songs[i].al.picUrl
|
||
}
|
||
})
|
||
if (saveId == -1) {
|
||
songInfo.push(musicDate)
|
||
} else {
|
||
songInfo[saveId] = musicDate
|
||
}
|
||
logger.info('当前搜索列表---', songInfo)
|
||
await redisSetKey(REDIS_YUNZAI_SONGINFO, songInfo)
|
||
const data = await new PickSongList(e).getData(musicDate.data)
|
||
let img = await puppeteer.screenshot("pick-song", data);
|
||
e.reply(img);
|
||
} else {
|
||
e.reply('暂未找到你想听的歌哦~')
|
||
}
|
||
})
|
||
} else if (await redisGetKey(REDIS_YUNZAI_SONGINFO) != []) {
|
||
if (e.msg.replace(/\s+/g, "").match(/^#听(\d+)/)) {
|
||
const pickNumber = e.msg.replace(/\s+/g, "").match(/^#听(\d+)/)[1] - 1
|
||
let group_id = e.group.group_id
|
||
if (!group_id) return
|
||
let songInfo = await redisGetKey(REDIS_YUNZAI_SONGINFO)
|
||
const saveId = songInfo.findIndex(item => item.group_id === e.group.group_id)
|
||
const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality;
|
||
const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[saveId].data[pickNumber].id)
|
||
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + songInfo[saveId].data[pickNumber].id
|
||
const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API
|
||
const isCkExpired = await this.checkCooike(statusUrl)
|
||
// // 请求netease数据
|
||
this.neteasePlay(e, pickSongUrl, songWikiUrl, songInfo[saveId].data, pickNumber, isCkExpired)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// 播放策略
|
||
async playSong(e) {
|
||
if (!this.useNeteaseSongRequest) {
|
||
logger.info('当前未开启网易云点歌')
|
||
return
|
||
}
|
||
// 只在群里可以使用
|
||
let group_id = e.group.group_id
|
||
if (!group_id) return
|
||
const autoSelectNeteaseApi = await this.pickApi()
|
||
let songInfo = []
|
||
// 获取搜索歌曲列表信息
|
||
const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality;
|
||
let searchUrl = autoSelectNeteaseApi + '/search?keywords={}&limit=1' //搜索API
|
||
let detailUrl = autoSelectNeteaseApi + "/song/detail?ids={}" //歌曲详情API
|
||
if (e.msg.replace(/\s+/g, "").match(/播放(.+)/)) {
|
||
const songKeyWord = e.msg.replace(/\s+/g, "").match(/播放(.+)/)[1]
|
||
searchUrl = searchUrl.replace("{}", songKeyWord)
|
||
await axios.get(searchUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT
|
||
},
|
||
}).then(async res => {
|
||
if (res.data.result.songs) {
|
||
for (const info of res.data.result.songs) {
|
||
songInfo.push({
|
||
'id': info.id,
|
||
'songName': info.name,
|
||
'singerName': info.artists[0]?.name,
|
||
'duration': formatTime(info.duration)
|
||
});
|
||
}
|
||
const ids = songInfo.map(item => item.id).join(',');
|
||
detailUrl = detailUrl.replace("{}", ids)
|
||
await axios.get(detailUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT
|
||
},
|
||
}).then(res => {
|
||
for (let i = 0; i < res.data.songs.length; i++) {
|
||
songInfo[i].cover = res.data.songs[i].al.picUrl
|
||
}
|
||
})
|
||
const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[0].id)
|
||
const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API
|
||
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + songInfo[0].id
|
||
const isCkExpired = await this.checkCooike(statusUrl)
|
||
this.neteasePlay(e, pickSongUrl, songWikiUrl, songInfo, 0, isCkExpired)
|
||
} else {
|
||
e.reply('暂未找到你想听的歌哦~')
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
|
||
// 获取云盘信息
|
||
async myCloud(e) {
|
||
const autoSelectNeteaseApi = await this.pickApi()
|
||
const cloudUrl = autoSelectNeteaseApi + '/user/cloud'
|
||
// 云盘数据API
|
||
await axios.get(cloudUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
"Cookie": this.neteaseCookie
|
||
},
|
||
}).then(res => {
|
||
const cloudData = {
|
||
'songCount': res.data.count,
|
||
'useSize': toGBorTB(res.data.size),
|
||
'cloudSize': toGBorTB(res.data.maxSize)
|
||
}
|
||
e.reply(`云盘数据\n歌曲数量:${cloudData.songCount}\n云盘容量:${cloudData.cloudSize}\n已使用容量:${cloudData.useSize}\n数据可能有延迟`)
|
||
})
|
||
}
|
||
|
||
// 更新云盘
|
||
async songCloudUpdate(e) {
|
||
try {
|
||
await this.cleanCloudData()
|
||
await this.getCloudSong(e, true)
|
||
try {
|
||
await e?.reply('更新成功')
|
||
} catch (error) {
|
||
logger.error('trss又拉屎了?')
|
||
}
|
||
await this.myCloud(e)
|
||
} catch (error) {
|
||
logger.error('更新云盘失败', error)
|
||
}
|
||
}
|
||
|
||
// 上传音频文件
|
||
async upLoad(e) {
|
||
let msg = await e?.getReply();
|
||
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 musicUrlReg3 = /(http:|https:)\/\/music.163.com\/m\/song\/(\d+)/;
|
||
const id =
|
||
musicUrlReg2.exec(msg.message[0].data)?.[3] ||
|
||
musicUrlReg.exec(msg.message[0].data)?.[2] ||
|
||
musicUrlReg3.exec(msg.message[0].data)?.[2] ||
|
||
/(?<!user)id=(\d+)/.exec(msg.message[0].data)[1] || "";
|
||
const title = msg.message[0].data.match(/"title":"([^"]+)"/)[1]
|
||
const desc = msg.message[0].data.match(/"desc":"([^"]+)"/)[1]
|
||
if (id === "") return
|
||
let path = this.getCurDownloadPath(e) + '/' + title + '-' + desc + '.flac'
|
||
try {
|
||
// 上传群文件
|
||
await this.uploadGroupFile(e, path);
|
||
// 删除文件
|
||
await checkAndRemoveFile(path);
|
||
} catch (error) {
|
||
logger.error(error);
|
||
}
|
||
}
|
||
|
||
// 上传云盘
|
||
async uploadCloud(e) {
|
||
let msg = await e?.getReply();
|
||
const autoSelectNeteaseApi = await this.pickApi()
|
||
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 musicUrlReg3 = /(http:|https:)\/\/music.163.com\/m\/song\/(\d+)/;
|
||
const id =
|
||
musicUrlReg2.exec(msg.message[0].data)?.[3] ||
|
||
musicUrlReg.exec(msg.message[0].data)?.[2] ||
|
||
musicUrlReg3.exec(msg.message[0].data)?.[2] ||
|
||
/(?<!user)id=(\d+)/.exec(msg.message[0].data)[1] || "";
|
||
const title = msg.message[0].data.match(/"title":"([^"]+)"/)[1]
|
||
const desc = msg.message[0].data.match(/"desc":"([^"]+)"/)[1]
|
||
if (id === "") return
|
||
let path = this.getCurDownloadPath(e) + '/' + title + '-' + desc + '.flac'
|
||
let tryCount = 0
|
||
const tryUpload = async () => {
|
||
let formData = new FormData()
|
||
await formData.append('songFile', fs.createReadStream(path))
|
||
const headers = {
|
||
...formData.getHeaders(),
|
||
'Cookie': this.neteaseCookie,
|
||
};
|
||
const updateUrl = autoSelectNeteaseApi + `/cloud?time=${Date.now()}`
|
||
axios({
|
||
method: 'post',
|
||
url: updateUrl,
|
||
headers: headers,
|
||
data: formData,
|
||
})
|
||
.then(async res => {
|
||
if (res.data.code == 200) {
|
||
let matchUrl = autoSelectNeteaseApi + '/cloud/match?uid=' + this.uid + "&sid=" + res.data.privateCloud.songId + '&asid=' + id
|
||
await axios.get(matchUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
"Cookie": this.neteaseCookie
|
||
},
|
||
}).then(res => {
|
||
logger.info('歌曲信息匹配成功')
|
||
})
|
||
.catch(error => {
|
||
logger.error('歌曲信息匹配错误', error)
|
||
})
|
||
this.songCloudUpdate(e)
|
||
}
|
||
})
|
||
.catch(error => {
|
||
tryCount += 1;
|
||
logger.info('失败喽~再试一次')
|
||
if (tryCount < 3) {
|
||
tryUpload(); // 直接调用
|
||
} else {
|
||
logger.error('怎么想都传不上去吧', error)
|
||
}
|
||
}
|
||
)
|
||
};
|
||
tryUpload();
|
||
}
|
||
|
||
// 获取云盘歌单
|
||
async getCloudSong(e, cloudUpdate = false) {
|
||
let songList = await redisGetKey(REDIS_YUNZAI_CLOUDSONGLIST) || []
|
||
if (!songList[0] || cloudUpdate) {
|
||
const autoSelectNeteaseApi = await this.pickApi();
|
||
const limit = 100;
|
||
let offset = 0;
|
||
let cloudUrl = autoSelectNeteaseApi + `/user/cloud?limit=${limit}&offset=${offset}×tamp=${Date.now()}`;
|
||
while (true) {
|
||
try {
|
||
const res = await axios.get(cloudUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
"Cookie": this.neteaseCookie
|
||
}
|
||
});
|
||
const songs = res.data.data.map(({ simpleSong }) => ({
|
||
'songName': simpleSong.name,
|
||
'id': simpleSong.id,
|
||
'singerName': simpleSong.ar[0].name || '喵喵~',
|
||
'duration': '云盘'
|
||
}));
|
||
songList.push(...songs);
|
||
if (!res.data.hasMore) {
|
||
break;
|
||
}
|
||
offset += limit;
|
||
cloudUrl = autoSelectNeteaseApi + `/user/cloud?limit=${limit}&offset=${offset}`;
|
||
} catch (error) {
|
||
console.error("获取歌单失败", error);
|
||
break;
|
||
}
|
||
}
|
||
await redisSetKey(REDIS_YUNZAI_CLOUDSONGLIST, songList)
|
||
return songList;
|
||
} else {
|
||
return songList;
|
||
}
|
||
}
|
||
|
||
async cleanCloudData(e) {
|
||
await redisSetKey(REDIS_YUNZAI_CLOUDSONGLIST, [])
|
||
}
|
||
|
||
// 判断是否海外服务器
|
||
async isOverseasServer() {
|
||
// 如果第一次使用没有值就设置
|
||
if (!(await redisExistKey(REDIS_YUNZAI_ISOVERSEA))) {
|
||
await redisSetKey(REDIS_YUNZAI_ISOVERSEA, {
|
||
os: false,
|
||
})
|
||
return true;
|
||
}
|
||
// 如果有就取出来
|
||
return (await redisGetKey(REDIS_YUNZAI_ISOVERSEA)).os;
|
||
}
|
||
|
||
// API选择
|
||
async pickApi() {
|
||
const isOversea = await this.isOverseasServer();
|
||
let autoSelectNeteaseApi
|
||
if (this.useLocalNeteaseAPI) {
|
||
// 使用自建 API
|
||
return autoSelectNeteaseApi = this.neteaseCloudAPIServer
|
||
} else {
|
||
// 自动选择 API
|
||
return autoSelectNeteaseApi = isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN;
|
||
}
|
||
}
|
||
|
||
// 检测cooike活性
|
||
async checkCooike(statusUrl) {
|
||
let status
|
||
await axios.get(statusUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
"Cookie": this.neteaseCookie
|
||
},
|
||
}).then(async res => {
|
||
const userInfo = res.data.data.profile
|
||
await config.updateField("tools", "neteaseUserId", res.data.data.profile.userId);
|
||
if (userInfo) {
|
||
logger.info('ck活着,使用ck进行高音质下载')
|
||
status = true
|
||
} else {
|
||
logger.info('ck失效,将启用临时接口下载')
|
||
status = false
|
||
}
|
||
})
|
||
return status
|
||
}
|
||
|
||
// 网易云音乐下载策略
|
||
neteasePlay(e, pickSongUrl, songWikiUrl, songInfo, pickNumber = 0, isCkExpired) {
|
||
axios.get(pickSongUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
"Cookie": this.neteaseCookie
|
||
},
|
||
}).then(async resp => {
|
||
// 国内解决方案,替换API后这里也需要修改
|
||
|
||
// 英转中字典匹配
|
||
const translationDict = {
|
||
'standard': '标准',
|
||
'higher': '较高',
|
||
'exhigh': '极高',
|
||
'lossless': '无损',
|
||
'hires': 'Hi-Res',
|
||
'jyeffect': '高清环绕声',
|
||
'sky': '沉浸环绕声',
|
||
'dolby': '杜比全景声',
|
||
'jymaster': '超清母带'
|
||
};
|
||
|
||
// 英转中
|
||
function translateToChinese(word) {
|
||
return translationDict[word] || word; // 如果找不到对应翻译,返回原词
|
||
}
|
||
|
||
// 字节转MB
|
||
function bytesToMB(sizeInBytes) {
|
||
const sizeInMB = sizeInBytes / (1024 * 1024); // 1 MB = 1024 * 1024 bytes
|
||
return sizeInMB.toFixed(2); // 保留两位小数
|
||
}
|
||
let url = await resp.data.data?.[0]?.url || null;
|
||
const AudioLevel = translateToChinese(resp.data.data?.[0]?.level)
|
||
const AudioSize = bytesToMB(resp.data.data?.[0]?.size)
|
||
|
||
// 获取歌曲标题
|
||
let title = songInfo[pickNumber].songName + '-' + songInfo[pickNumber].singerName
|
||
let typelist = []
|
||
// 歌曲百科API
|
||
await axios.get(songWikiUrl, {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
// "Cookie": this.neteaseCookie
|
||
},
|
||
}).then(res => {
|
||
const wikiData = res.data.data.blocks[1].creatives
|
||
|
||
typelist.push(wikiData[0].resources[0].uiElement.mainTitle.title)
|
||
// 防止数据过深出错
|
||
const recTags = wikiData[1]
|
||
if (recTags.resources[0]) {
|
||
for (let i = 0; i < Math.min(3, recTags.resources.length); i++) {
|
||
if (recTags.resources[i] && recTags.resources[i].uiElement && recTags.resources[i].uiElement.mainTitle.title) {
|
||
typelist.push(recTags.resources[i].uiElement.mainTitle.title)
|
||
}
|
||
}
|
||
} else {
|
||
if (recTags.uiElement.textLinks[0].text) typelist.push(recTags.uiElement.textLinks[0].text)
|
||
}
|
||
if (wikiData[2].uiElement.mainTitle.title == 'BPM') {
|
||
typelist.push('BPM ' + wikiData[2].uiElement.textLinks[0].text)
|
||
} else {
|
||
typelist.push(wikiData[2].uiElement.textLinks[0].text)
|
||
}
|
||
typelist.push(AudioLevel)
|
||
})
|
||
let musicInfo = {
|
||
'cover': songInfo[pickNumber].cover,
|
||
'songName': songInfo[pickNumber].songName,
|
||
'singerName': songInfo[pickNumber].singerName,
|
||
'size': AudioSize + ' MB',
|
||
'musicType': typelist
|
||
}
|
||
// 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用,必须自建并且ck可用状态才能进行高质量解析)
|
||
if (!isCkExpired || url == null) {
|
||
url = await this.musicTempApi(e, musicInfo, title);
|
||
} else {
|
||
// 拥有ck,并且有效,直接进行解析
|
||
let audioInfo = AudioLevel;
|
||
if (AudioLevel == '杜比全景声') {
|
||
audioInfo += '\n(杜比下载文件为MP4,编码格式为AC-4,需要设备支持才可播放)';
|
||
}
|
||
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
|
||
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
|
||
e.reply(img);
|
||
}
|
||
// 动态判断后缀名
|
||
let musicExt = resp.data.data?.[0]?.type
|
||
// 下载音乐
|
||
downloadAudio(url, this.getCurDownloadPath(e), title, 'follow', musicExt).then(async path => {
|
||
try {
|
||
// 发送卡片
|
||
await sendMusicCard(e, '163', songInfo[pickNumber].id)
|
||
} catch (error) {
|
||
if (error.error.message) {
|
||
logger.error("发送卡片错误错误:", error.error.message, '发送群语音');
|
||
} else {
|
||
logger.error("发送卡片错误错误,请查看控制台报错,将发送群语音")
|
||
logger.error(error)
|
||
}
|
||
// 发送群文件
|
||
await this.uploadGroupFile(e, path);
|
||
// 发送语音
|
||
if (musicExt != 'mp4' && this.isSendVocal) {
|
||
await e.reply(segment.record(path));
|
||
}
|
||
// 删除文件
|
||
await checkAndRemoveFile(path);
|
||
}
|
||
}).catch(err => {
|
||
logger.error(`下载音乐失败,错误信息为: ${err}`);
|
||
});
|
||
});
|
||
}
|
||
|
||
async musicTempApi(e, musicInfo, title) {
|
||
let musicReqApi = NETEASE_TEMP_API;
|
||
// 临时接口,title经过变换后搜索到的音乐质量提升
|
||
const vipMusicData = await axios.get(musicReqApi.replace("{}", title.replace("-", " ")), {
|
||
headers: {
|
||
"User-Agent": COMMON_USER_AGENT,
|
||
},
|
||
});
|
||
const url = vipMusicData.data?.music_url
|
||
const id = vipMusicData.data?.id ?? vipMusicData.data?.data?.quality ?? vipMusicData.data?.pay;
|
||
musicInfo.size = id
|
||
musicInfo.musicType = musicInfo.musicType.slice(0, -1)
|
||
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
|
||
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
|
||
e.reply(img);
|
||
return url;
|
||
}
|
||
|
||
/**
|
||
* 获取当前发送人/群的下载路径
|
||
* @param e Yunzai 机器人事件
|
||
* @returns {string}
|
||
*/
|
||
getCurDownloadPath(e) {
|
||
return `${this.defaultPath}${e.group_id || e.user_id}`
|
||
}
|
||
|
||
/**
|
||
* 上传到群文件
|
||
* @param e 交互事件
|
||
* @param path 上传的文件所在路径
|
||
* @return {Promise<void>}
|
||
*/
|
||
async uploadGroupFile(e, path) {
|
||
// 判断是否是ICQQ
|
||
if (e.bot?.sendUni) {
|
||
await e.group.fs.upload(path);
|
||
} else {
|
||
await e.group.sendFile(path);
|
||
}
|
||
}
|
||
} |