mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
🪛 chore: 格式化分号
This commit is contained in:
parent
6220016ace
commit
ded7fed89d
248
apps/tools.js
248
apps/tools.js
@ -7,12 +7,13 @@ import { Buffer } from 'node:buffer';
|
||||
import fs from "node:fs";
|
||||
import PQueue from 'p-queue';
|
||||
import path from "path";
|
||||
import qrcode from "qrcode"
|
||||
import qrcode from "qrcode";
|
||||
import querystring from "querystring";
|
||||
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
|
||||
import {
|
||||
BILI_CDN_SELECT_LIST,
|
||||
BILI_DEFAULT_INTRO_LEN_LIMIT, BILI_RESOLUTION_LIST,
|
||||
BILI_DEFAULT_INTRO_LEN_LIMIT,
|
||||
BILI_RESOLUTION_LIST,
|
||||
COMMON_USER_AGENT,
|
||||
DIVIDING_LINE,
|
||||
douyinTypeMap,
|
||||
@ -57,9 +58,9 @@ import {
|
||||
XHS_REQ_LINK
|
||||
} from "../constants/tools.js";
|
||||
import BiliInfoModel from "../model/bili-info.js";
|
||||
import NeteaseMusicInfo from '../model/neteaseMusicInfo.js'
|
||||
import config from "../model/config.js";
|
||||
import NeteaseModel from "../model/netease.js";
|
||||
import NeteaseMusicInfo from '../model/neteaseMusicInfo.js';
|
||||
import * as aBogus from "../utils/a-bogus.cjs";
|
||||
import { downloadM3u8Videos, mergeAcFileToMp4, parseM3u8, parseUrl } from "../utils/acfun.js";
|
||||
import { startBBDown } from "../utils/bbdown-util.js";
|
||||
@ -105,8 +106,7 @@ import Translate from "../utils/trans-strategy.js";
|
||||
import { mid2id } from "../utils/weibo.js";
|
||||
import { convertToSeconds, removeParams, ytbFormatTime } from "../utils/youtube.js";
|
||||
import { ytDlpGetDuration, ytDlpGetThumbnail, ytDlpGetTilt, ytDlpHelper } from "../utils/yt-dlp-util.js";
|
||||
import { textArrayToMakeForward, sendMusicCard } from "../utils/yunzai-util.js";
|
||||
|
||||
import { textArrayToMakeForward } from "../utils/yunzai-util.js";
|
||||
|
||||
|
||||
export class tools extends plugin {
|
||||
@ -324,7 +324,7 @@ export class tools extends plugin {
|
||||
);
|
||||
return;
|
||||
}
|
||||
let place = msg.slice(1 + language[1].length)
|
||||
let place = msg.slice(1 + language[1].length);
|
||||
if (_.isEmpty(place)) {
|
||||
const reply = await e?.getReply();
|
||||
if (reply !== undefined) {
|
||||
@ -353,7 +353,7 @@ export class tools extends plugin {
|
||||
if (douUrl.includes("v.douyin.com")) {
|
||||
const { location, ttwidValue } = await this.douyinRequest(douUrl);
|
||||
ttwid = ttwidValue;
|
||||
douUrl = location
|
||||
douUrl = location;
|
||||
}
|
||||
// TODO 如果有新的好解决方案可以删除,如果遇到https://www.iesdouyin.com/share/slides,这类动图暂时交付给其他API解析
|
||||
if (douUrl.includes("share/slides")) {
|
||||
@ -384,7 +384,7 @@ export class tools extends plugin {
|
||||
let dyApi;
|
||||
if (douUrl.includes("live.douyin.com")) {
|
||||
// 第一类直播类型
|
||||
dyApi = DY_LIVE_INFO.replaceAll("{}", douId)
|
||||
dyApi = DY_LIVE_INFO.replaceAll("{}", douId);
|
||||
} else if (douUrl.includes("webcast.amemv.com")) {
|
||||
// 第二类直播类型,这里必须使用客户端的 fetch 请求
|
||||
dyApi = DY_LIVE_INFO_2.replace("{}", douId) + `&verifyFp=${ genVerifyFp() }` + `&msToken=${ ttwid }`;
|
||||
@ -392,7 +392,7 @@ export class tools extends plugin {
|
||||
const webcastData = await webcastResp.json();
|
||||
const item = webcastData.data.room;
|
||||
const { title, cover, user_count, stream_url } = item;
|
||||
const dySendContent = `${this.identifyPrefix}识别:抖音直播,${title}`
|
||||
const dySendContent = `${ this.identifyPrefix }识别:抖音直播,${ title }`;
|
||||
e.reply([segment.image(cover?.url_list?.[0]), dySendContent, `\n🏄♂️在线人数:${ user_count }人正在观看`]);
|
||||
// 下载10s的直播流
|
||||
await this.sendStreamSegment(e, stream_url?.flv_pull_url?.HD1 || stream_url?.flv_pull_url?.FULL_HD1 || stream_url?.flv_pull_url?.SD1 || stream_url?.flv_pull_url?.SD2);
|
||||
@ -408,7 +408,7 @@ export class tools extends plugin {
|
||||
);
|
||||
// const param = resp.data.result[0].paramsencode;
|
||||
const resDyApi = `${ dyApi }&a_bogus=${ abParam }`;
|
||||
headers['Referer'] = `https://www.douyin.com/`
|
||||
headers['Referer'] = `https://www.douyin.com/`;
|
||||
// 定义一个dy请求
|
||||
const dyResponse = () => axios.get(resDyApi, {
|
||||
headers,
|
||||
@ -421,7 +421,7 @@ export class tools extends plugin {
|
||||
if (douUrl.includes("live")) {
|
||||
const item = await data.data.data?.[0];
|
||||
const { title, cover, user_count_str, stream_url } = item;
|
||||
const dySendContent = `${this.identifyPrefix}识别:抖音直播,${title}`
|
||||
const dySendContent = `${ this.identifyPrefix }识别:抖音直播,${ title }`;
|
||||
e.reply([segment.image(cover?.url_list?.[0]), dySendContent, `\n🏄♂️在线人数:${ user_count_str }人正在观看`]);
|
||||
// 下载10s的直播流
|
||||
await this.sendStreamSegment(e, stream_url?.flv_pull_url?.HD1 || stream_url?.flv_pull_url?.FULL_HD1 || stream_url?.flv_pull_url?.SD1 || stream_url?.flv_pull_url?.SD2);
|
||||
@ -480,7 +480,7 @@ export class tools extends plugin {
|
||||
const path = `${ this.getCurDownloadPath(e) }/temp.mp4`;
|
||||
// 加入队列
|
||||
await this.downloadVideo(resUrl).then(() => {
|
||||
this.sendVideoToUpload(e, path)
|
||||
this.sendVideoToUpload(e, path);
|
||||
});
|
||||
} else if (urlType === "image") {
|
||||
// 发送描述
|
||||
@ -507,7 +507,7 @@ export class tools extends plugin {
|
||||
await this.douyinComment(e, douId, headers);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
logger.mark(`Cookie 过期或者 Cookie 没有填写,请参考\n${HELP_DOC}\n尝试无效后可以到官方QQ群[575663150]提出 bug 等待解决`)
|
||||
logger.mark(`Cookie 过期或者 Cookie 没有填写,请参考\n${ HELP_DOC }\n尝试无效后可以到官方QQ群[575663150]提出 bug 等待解决`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -594,7 +594,7 @@ export class tools extends plugin {
|
||||
);
|
||||
const commentsResp = await axios.get(`${ dyCommentUrl }&a_bogus=${ abParam }`, {
|
||||
headers
|
||||
})
|
||||
});
|
||||
// logger.info(headers)
|
||||
// saveJsonToFile(commentsResp.data, "data.json", _);
|
||||
const comments = commentsResp.data.comments;
|
||||
@ -603,8 +603,8 @@ export class tools extends plugin {
|
||||
message: item.text,
|
||||
nickname: this.e.sender.card || this.e.user_id,
|
||||
user_id: this.e.user_id,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
e.reply(await Bot.makeForwardMsg(replyComments));
|
||||
}
|
||||
|
||||
@ -639,18 +639,18 @@ export class tools extends plugin {
|
||||
e.reply('R插件开源免责声明:\n您将通过扫码完成获取哔哩哔哩refresh_token以及ck。\n本Bot将不会保存您的登录状态。\n我方仅提供视频解析及相关B站内容服务,若您的账号封禁、被盗等处罚与我方无关。\n害怕风险请勿扫码 ~', { recallMsg: 180 });
|
||||
// 图片发送钩子
|
||||
const imgSendHook = function (e, path) {
|
||||
e.reply([segment.image(path), segment.at(e.user_id), '请扫码以完成获取'], { recallMsg: 180 })
|
||||
e.reply([segment.image(path), segment.at(e.user_id), '请扫码以完成获取'], { recallMsg: 180 });
|
||||
};
|
||||
// 检查路径是否存在文件夹
|
||||
await mkdirIfNotExists(this.defaultPath);
|
||||
// 发送请求
|
||||
const saveCodePath = `${ this.defaultPath }qrcode.png`;
|
||||
|
||||
const { SESSDATA, refresh_token } = await getScanCodeData(saveCodePath, 8, () => imgSendHook(e, saveCodePath))
|
||||
const { SESSDATA, refresh_token } = await getScanCodeData(saveCodePath, 8, () => imgSendHook(e, saveCodePath));
|
||||
|
||||
// 更新到配置文件
|
||||
config.updateField("tools", "biliSessData", SESSDATA);
|
||||
e.reply('登录成功!相关信息已保存至配置文件', true)
|
||||
e.reply('登录成功!相关信息已保存至配置文件', true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -718,7 +718,7 @@ export class tools extends plugin {
|
||||
// 直接发送BV号的处理
|
||||
if (/^BV[1-9a-zA-Z]{10}$/.exec(url)?.[0]) {
|
||||
url = `https://www.bilibili.com/video/${ url }`;
|
||||
logger.info(url)
|
||||
logger.info(url);
|
||||
}
|
||||
// 短号处理
|
||||
if (url.includes("b23.tv")) {
|
||||
@ -809,7 +809,7 @@ export class tools extends plugin {
|
||||
const query = querystring.parse(url);
|
||||
const curPage = query?.p || 0;
|
||||
const curDuration = pages?.[curPage]?.duration || duration;
|
||||
const isLimitDuration = curDuration > this.biliDuration
|
||||
const isLimitDuration = curDuration > this.biliDuration;
|
||||
// 动态构造哔哩哔哩信息
|
||||
let biliInfo = await this.constructBiliInfo(videoInfo);
|
||||
// 总结
|
||||
@ -856,13 +856,13 @@ export class tools extends plugin {
|
||||
message: { type: "text", text: `标题:${ title }\n作者:${ author_name }` },
|
||||
nickname: e.sender.card || e.user_id,
|
||||
user_id: e.user_id,
|
||||
}
|
||||
};
|
||||
await e.reply(Bot.makeForwardMsg(origin_image_urls.map(item => {
|
||||
return {
|
||||
message: segment.image(item),
|
||||
nickname: e.sender.card || e.user_id,
|
||||
user_id: e.user_id,
|
||||
}
|
||||
};
|
||||
}).concat(titleMsg)));
|
||||
}
|
||||
}
|
||||
@ -904,7 +904,7 @@ export class tools extends plugin {
|
||||
const onlineTotal = await this.biliOnlineTotal(bvid, cid);
|
||||
combineContent += `\n🏄♂️️ 当前视频有 ${ onlineTotal.total } 人在观看,其中 ${ onlineTotal.count } 人在网页端观看`;
|
||||
}
|
||||
let biliInfo = [`${this.identifyPrefix}识别:哔哩哔哩,${title}`, combineContent]
|
||||
let biliInfo = [`${ this.identifyPrefix }识别:哔哩哔哩,${ title }`, combineContent];
|
||||
// 是否显示封面
|
||||
if (this.biliDisplayCover) {
|
||||
// 加入图片
|
||||
@ -926,8 +926,8 @@ export class tools extends plugin {
|
||||
const ssid = url.match(/\/ss(\d+)/)?.[1];
|
||||
let resp = await (await fetch(BILI_SSID_INFO.replace("{}", ssid), {
|
||||
headers: BILI_HEADER
|
||||
})).json()
|
||||
ep = (resp.result.main_section.episodes[0].share_url).replace("https://www.bilibili.com/bangumi/play/ep", "")
|
||||
})).json();
|
||||
ep = (resp.result.main_section.episodes[0].share_url).replace("https://www.bilibili.com/bangumi/play/ep", "");
|
||||
}
|
||||
// 处理普通情况,上述情况无法处理的
|
||||
if (_.isEmpty(ep)) {
|
||||
@ -1018,7 +1018,7 @@ export class tools extends plugin {
|
||||
logger.error('[R插件][哔哩哔哩视频发送]下载错误,具体原因为:', err);
|
||||
e.reply("解析失败,请重试一下");
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1033,7 +1033,7 @@ export class tools extends plugin {
|
||||
return {
|
||||
total: online.total,
|
||||
count: online.count
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 下载哔哩哔哩音乐
|
||||
@ -1042,14 +1042,14 @@ export class tools extends plugin {
|
||||
this.queue.add(() => {
|
||||
getBiliAudio(videoId, "").then(async audioUrl => {
|
||||
const path = this.getCurDownloadPath(e);
|
||||
const biliMusicPath = await m4sToMp3(audioUrl, path)
|
||||
const biliMusicPath = await m4sToMp3(audioUrl, path);
|
||||
// 发送语音
|
||||
e.reply(segment.record(biliMusicPath));
|
||||
// 上传群文件
|
||||
await this.uploadGroupFile(e, biliMusicPath);
|
||||
})
|
||||
})
|
||||
return true
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// 发送哔哩哔哩动态的算法
|
||||
@ -1089,13 +1089,13 @@ export class tools extends plugin {
|
||||
*/
|
||||
async getBiliSummary(bvid, cid, up_mid) {
|
||||
// 这个有点用,但不多
|
||||
let wbi = "wts=1701546363&w_rid=1073871926b3ccd99bd790f0162af634"
|
||||
let wbi = "wts=1701546363&w_rid=1073871926b3ccd99bd790f0162af634";
|
||||
if (!_.isEmpty(this.biliSessData)) {
|
||||
wbi = await getWbi({ bvid, cid, up_mid }, this.biliSessData);
|
||||
}
|
||||
// 构造API
|
||||
const summaryUrl = `${ BILI_SUMMARY }?${ wbi }`;
|
||||
logger.info(summaryUrl)
|
||||
logger.info(summaryUrl);
|
||||
// 构造结果:https://api.bilibili.com/x/web-interface/view/conclusion/get?bvid=BV1L94y1H7CV&cid=1335073288&up_mid=297242063&wts=1701546363&w_rid=1073871926b3ccd99bd790f0162af634
|
||||
return axios.get(summaryUrl)
|
||||
.then(resp => {
|
||||
@ -1106,7 +1106,7 @@ export class tools extends plugin {
|
||||
let resReply = "";
|
||||
// 总体总结
|
||||
if (summary) {
|
||||
resReply = `\n摘要:${summary}\n`
|
||||
resReply = `\n摘要:${ summary }\n`;
|
||||
}
|
||||
// 分段总结
|
||||
if (outline) {
|
||||
@ -1115,8 +1115,8 @@ export class tools extends plugin {
|
||||
const keyPoint = item?.part_outline;
|
||||
// 时间点的总结
|
||||
const specificContent = keyPoint.map(point => {
|
||||
const { timestamp, content } = point
|
||||
const specificTime = secondsToTime(timestamp)
|
||||
const { timestamp, content } = point;
|
||||
const specificTime = secondsToTime(timestamp);
|
||||
return `${ specificTime } ${ content }\n`;
|
||||
}).join("");
|
||||
return `- ${ smallTitle }\n${ specificContent }\n`;
|
||||
@ -1124,7 +1124,7 @@ export class tools extends plugin {
|
||||
resReply += specificTimeSummary.join("");
|
||||
}
|
||||
return resReply;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1171,7 +1171,7 @@ export class tools extends plugin {
|
||||
"media.fields":
|
||||
"duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width,alt_text,variants",
|
||||
"expansions": ["entities.mentions.username", "attachments.media_keys"],
|
||||
}
|
||||
};
|
||||
await fetch(TWITTER_TWEET_INFO.replace("{}", id), {
|
||||
headers: {
|
||||
"User-Agent": "v2TweetLookupJS",
|
||||
@ -1180,7 +1180,7 @@ export class tools extends plugin {
|
||||
...params,
|
||||
agent: !isOversea ? '' : new HttpsProxyAgent(this.myProxy),
|
||||
}).then(async resp => {
|
||||
logger.info(resp)
|
||||
logger.info(resp);
|
||||
e.reply(`${ this.identifyPrefix }识别:小蓝鸟学习版,${ resp.data.text }`);
|
||||
const downloadPath = `${ this.getCurDownloadPath(e) }`;
|
||||
// 创建文件夹(如果没有过这个群)
|
||||
@ -1259,7 +1259,7 @@ export class tools extends plugin {
|
||||
'User-Agent': COMMON_USER_AGENT,
|
||||
},
|
||||
timeout: 10000 // 设置超时时间
|
||||
}
|
||||
};
|
||||
|
||||
let resp = await axios.get(videoUrl, config);
|
||||
if (resp.data.data == null) {
|
||||
@ -1284,7 +1284,7 @@ export class tools extends plugin {
|
||||
proxyPort: this.proxyPort
|
||||
},
|
||||
downloadMethod: this.biliDownloadMethod,
|
||||
})
|
||||
});
|
||||
e.reply(segment.image(xImgPath));
|
||||
}
|
||||
} else {
|
||||
@ -1314,7 +1314,7 @@ export class tools extends plugin {
|
||||
parseM3u8(res.urlM3u8s[res.urlM3u8s.length - 1]).then(res2 => {
|
||||
downloadM3u8Videos(res2.m3u8FullUrls, path).then(_ => {
|
||||
mergeAcFileToMp4(res2.tsNames, path, `${ path }out.mp4`).then(_ => {
|
||||
this.sendVideoToUpload(e, `${path}out.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }out.mp4`);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1337,7 +1337,7 @@ export class tools extends plugin {
|
||||
)?.[0]
|
||||
|| /(http:|https:)\/\/www\.xiaohongshu\.com\/discovery\/item\/(\w+)/.exec(
|
||||
e.msg,
|
||||
)?.[0]
|
||||
)?.[0];
|
||||
// 注入ck
|
||||
XHS_NO_WATERMARK_HEADER.cookie = this.xiaohongshuCookie;
|
||||
// 解析短号
|
||||
@ -1409,7 +1409,7 @@ export class tools extends plugin {
|
||||
// 创建文件,如果不存在
|
||||
path = `${ this.getCurDownloadPath(e) }/`;
|
||||
}
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
return true;
|
||||
} else if (type === "normal") {
|
||||
@ -1605,11 +1605,11 @@ export class tools extends plugin {
|
||||
try {
|
||||
// 优先判断是否使用自建 API
|
||||
const isOversea = await this.isOverseasServer();
|
||||
let autoSelectNeteaseApi
|
||||
let autoSelectNeteaseApi;
|
||||
if (this.useLocalNeteaseAPI) {
|
||||
autoSelectNeteaseApi = this.neteaseCloudAPIServer
|
||||
autoSelectNeteaseApi = this.neteaseCloudAPIServer;
|
||||
} else {
|
||||
autoSelectNeteaseApi = (isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN)
|
||||
autoSelectNeteaseApi = (isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN);
|
||||
await e.reply('未使用自建服务器,高概率#rnq失败');
|
||||
}
|
||||
// 获取登录key
|
||||
@ -1648,7 +1648,7 @@ export class tools extends plugin {
|
||||
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-Z0-9]+)/.exec(message)?.[0]
|
||||
message = /(http:|https:)\/\/163cn\.tv\/([a-zA-Z0-9]+)/.exec(message)?.[0];
|
||||
// logger.info(message)
|
||||
message = await axios.head(message).then((resp) => {
|
||||
return resp.request.res.responseUrl;
|
||||
@ -1666,37 +1666,37 @@ export class tools extends plugin {
|
||||
// 如果没有下载地址跳出if
|
||||
if (_.isEmpty(id)) {
|
||||
e.reply(`识别:网易云音乐,解析失败!`);
|
||||
logger.error("[R插件][网易云解析] 没有找到id,无法进行下一步!")
|
||||
return
|
||||
logger.error("[R插件][网易云解析] 没有找到id,无法进行下一步!");
|
||||
return;
|
||||
}
|
||||
// 优先判断是否使用自建 API
|
||||
let autoSelectNeteaseApi
|
||||
let autoSelectNeteaseApi;
|
||||
// 判断海外
|
||||
const isOversea = await this.isOverseasServer();
|
||||
if (this.useLocalNeteaseAPI) {
|
||||
// 使用自建 API
|
||||
autoSelectNeteaseApi = this.neteaseCloudAPIServer
|
||||
autoSelectNeteaseApi = this.neteaseCloudAPIServer;
|
||||
} else {
|
||||
// 自动选择 API
|
||||
autoSelectNeteaseApi = isOversea ? NETEASE_SONG_DOWNLOAD : NETEASE_API_CN;
|
||||
}
|
||||
// 检测ck可用性
|
||||
const statusUrl = autoSelectNeteaseApi + '/login/status'
|
||||
const statusUrl = autoSelectNeteaseApi + '/login/status';
|
||||
const isCkExpired = await axios.get(statusUrl, {
|
||||
headers: {
|
||||
"User-Agent": COMMON_USER_AGENT,
|
||||
"Cookie": this.neteaseCookie
|
||||
},
|
||||
}).then(res => {
|
||||
const userInfo = res.data.data.profile
|
||||
const userInfo = res.data.data.profile;
|
||||
if (userInfo) {
|
||||
logger.info('[R插件][netease]ck活着,使用ck进行高音质下载')
|
||||
return true
|
||||
logger.info('[R插件][netease]ck活着,使用ck进行高音质下载');
|
||||
return true;
|
||||
} else {
|
||||
logger.info('[R插件][netease]ck失效,将启用临时接口下载')
|
||||
return false
|
||||
logger.info('[R插件][netease]ck失效,将启用临时接口下载');
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
// mv截断
|
||||
if (/mv\?/.test(message)) {
|
||||
const AUTO_NETEASE_MV_DETAIL = autoSelectNeteaseApi + "/mv/detail?mvid={}";
|
||||
@ -1723,17 +1723,17 @@ export class tools extends plugin {
|
||||
// logger.info(mvUrlData.data)
|
||||
const { url: mvUrl } = mvUrlData.data?.data;
|
||||
this.downloadVideo(mvUrl).then(path => {
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + id
|
||||
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + id;
|
||||
// 国内解决方案,替换为国内API (其中,NETEASE_API_CN是国内基址)
|
||||
const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality;
|
||||
const AUTO_NETEASE_SONG_DETAIL = autoSelectNeteaseApi + "/song/detail?ids={}";
|
||||
// logger.info(AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", id));
|
||||
const downloadUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", id)
|
||||
const detailUrl = AUTO_NETEASE_SONG_DETAIL.replace("{}", id)
|
||||
const downloadUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", id);
|
||||
const detailUrl = AUTO_NETEASE_SONG_DETAIL.replace("{}", id);
|
||||
// 请求netease数据
|
||||
axios.get(downloadUrl, {
|
||||
headers: {
|
||||
@ -1768,8 +1768,8 @@ export class tools extends plugin {
|
||||
}
|
||||
|
||||
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)
|
||||
const AudioLevel = translateToChinese(resp.data.data?.[0]?.level);
|
||||
const AudioSize = bytesToMB(resp.data.data?.[0]?.size);
|
||||
// 获取歌曲信息
|
||||
let { songName, artistName } = await axios.get(detailUrl).then(res => {
|
||||
const song = res.data.songs[0];
|
||||
@ -1778,13 +1778,13 @@ export class tools extends plugin {
|
||||
artistName: cleanFilename(song?.ar?.[0].name)
|
||||
};
|
||||
});
|
||||
let title = artistName + '-' + songName
|
||||
let title = artistName + '-' + songName;
|
||||
// 获取歌曲封面
|
||||
let coverUrl = await axios.get(detailUrl).then(res => {
|
||||
const song = res.data.songs[0];
|
||||
return song?.al?.picUrl
|
||||
return song?.al?.picUrl;
|
||||
});
|
||||
let typelist = []
|
||||
let typelist = [];
|
||||
// 歌曲百科API
|
||||
await axios.get(songWikiUrl, {
|
||||
headers: {
|
||||
@ -1792,37 +1792,37 @@ export class tools extends plugin {
|
||||
// "Cookie": this.neteaseCookie
|
||||
},
|
||||
}).then(res => {
|
||||
const wikiData = res.data.data.blocks[1].creatives
|
||||
const wikiData = res.data.data.blocks[1].creatives;
|
||||
try {
|
||||
typelist.push(wikiData[0].resources[0]?.uiElement?.mainTitle?.title || "")
|
||||
typelist.push(wikiData[0].resources[0]?.uiElement?.mainTitle?.title || "");
|
||||
// 防止数据过深出错
|
||||
const recTags = wikiData[1]
|
||||
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)
|
||||
typelist.push(recTags.resources[i].uiElement.mainTitle.title);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (recTags.uiElement.textLinks[0].text) typelist.push(recTags.uiElement.textLinks[0].text)
|
||||
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)
|
||||
typelist.push('BPM ' + wikiData[2].uiElement.textLinks[0].text);
|
||||
} else {
|
||||
typelist.push(wikiData[2].uiElement.textLinks[0].text || '')
|
||||
typelist.push(wikiData[2].uiElement.textLinks[0].text || '');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('获取标签报错:', error)
|
||||
logger.error('获取标签报错:', error);
|
||||
}
|
||||
typelist.push(AudioLevel)
|
||||
})
|
||||
typelist.push(AudioLevel);
|
||||
});
|
||||
let musicInfo = {
|
||||
'cover': coverUrl,
|
||||
'songName': songName,
|
||||
'singerName': artistName,
|
||||
'size': AudioSize + " MB",
|
||||
'musicType': typelist
|
||||
}
|
||||
};
|
||||
// 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用,必须自建并且ck可用状态才能进行高质量解析)
|
||||
if (!isCkExpired || url == null) {
|
||||
url = await this.musicTempApi(e, title, "网易云音乐", musicInfo);
|
||||
@ -1832,13 +1832,13 @@ export class tools extends plugin {
|
||||
if (AudioLevel == '杜比全景声') {
|
||||
audioInfo += '\n(杜比下载文件为MP4,编码格式为AC-4,需要设备支持才可播放)';
|
||||
}
|
||||
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
|
||||
const data = await new NeteaseMusicInfo(e).getData(musicInfo);
|
||||
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
|
||||
await e.reply(img);
|
||||
// e.reply([segment.image(coverUrl), `${this.identifyPrefix}识别:网易云音乐,${title}\n当前下载音质: ${audioInfo}\n预估大小: ${AudioSize}MB`]);
|
||||
}
|
||||
// 动态判断后缀名
|
||||
let musicExt = resp.data.data?.[0]?.type
|
||||
let musicExt = resp.data.data?.[0]?.type;
|
||||
// 下载音乐
|
||||
downloadAudio(url, this.getCurDownloadPath(e), title, 'follow', musicExt).then(async path => {
|
||||
// 发送群文件
|
||||
@ -1878,9 +1878,9 @@ export class tools extends plugin {
|
||||
const singer = vipMusicData.data?.singer ?? vipMusicData.data?.data?.song_singer ?? vipMusicData.data?.singer;
|
||||
const id = vipMusicData.data?.id ?? vipMusicData.data?.data?.quality ?? vipMusicData.data?.pay;
|
||||
if (musicType === "网易云音乐") {
|
||||
musicInfo.size = id
|
||||
musicInfo.musicType = musicInfo.musicType.slice(0, -1)
|
||||
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
|
||||
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);
|
||||
await e.reply(img);
|
||||
} else {
|
||||
@ -1890,8 +1890,8 @@ export class tools extends plugin {
|
||||
'singerName': singer,
|
||||
'size': id,
|
||||
'musicType': ""
|
||||
}
|
||||
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
|
||||
};
|
||||
const data = await new NeteaseMusicInfo(e).getData(musicInfo);
|
||||
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
|
||||
await e.reply(img);
|
||||
}
|
||||
@ -1969,7 +1969,7 @@ export class tools extends plugin {
|
||||
// 视频
|
||||
const videoUrl = page_info.urls?.mp4_720p_mp4 || page_info.urls?.mp4_hd_mp4;
|
||||
// 文章
|
||||
if (!videoUrl) return true
|
||||
if (!videoUrl) return true;
|
||||
try {
|
||||
// wb 视频只能强制使用 1,由群友@非酋提出
|
||||
this.downloadVideo(videoUrl, false, {
|
||||
@ -1977,7 +1977,7 @@ export class tools extends plugin {
|
||||
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"referer": "https://weibo.com/",
|
||||
}, 1).then(path => {
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
} catch (err) {
|
||||
e.reply("视频资源获取失败");
|
||||
@ -2004,29 +2004,29 @@ export class tools extends plugin {
|
||||
message: segment.image(item),
|
||||
nickname: this.e.sender.card || this.e.user_id,
|
||||
user_id: this.e.user_id,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
e.reply(Bot.makeForwardMsg(images));
|
||||
} else if (adapter.video && adapter.video !== '') {
|
||||
// 视频:https://www.kuaishou.com/short-video/3xhjgcmir24m4nm
|
||||
const url = adapter.video;
|
||||
this.downloadVideo(url).then(path => {
|
||||
logger.info(path);
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
} else {
|
||||
e.reply("解析失败:无法获取到资源");
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("解析失败 ", err);
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// 油管解析
|
||||
async sy2b(e) {
|
||||
const timeRange = ytbFormatTime(this.youtubeClipTime)
|
||||
const timeRange = ytbFormatTime(this.youtubeClipTime);
|
||||
const isOversea = await this.isOverseasServer();
|
||||
if (!isOversea && !(await testProxy(this.proxyAddr, this.proxyPort))) {
|
||||
e.reply("检测到没有梯子,无法解析油管");
|
||||
@ -2040,18 +2040,18 @@ export class tools extends plugin {
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
// 匹配并转义 URL 中的 & 符号(仅对 Windows 进行转义)
|
||||
let url = removeParams(urlRex.exec(e.msg)?.[0] || url2Rex.exec(e.msg)?.[0]).replace(/&/g, isWindows ? '^&' : '&')
|
||||
let url = removeParams(urlRex.exec(e.msg)?.[0] || url2Rex.exec(e.msg)?.[0]).replace(/&/g, isWindows ? '^&' : '&');
|
||||
//非最高画质,就按照设定的来
|
||||
let graphics = ""
|
||||
let graphics = "";
|
||||
if (this.youtubeGraphicsOptions != 0) {
|
||||
graphics = `[height<=${this.youtubeGraphicsOptions}]`
|
||||
graphics = `[height<=${ this.youtubeGraphicsOptions }]`;
|
||||
}
|
||||
|
||||
const path = this.getCurDownloadPath(e);
|
||||
await checkAndRemoveFile(path + "/temp.mp4")
|
||||
await checkAndRemoveFile(path + "/temp.flac")
|
||||
await checkAndRemoveFile(path + "/thumbnail.png")
|
||||
await ytDlpGetThumbnail(path, url, isOversea, this.myProxy, this.youtubeCookiePath)
|
||||
await checkAndRemoveFile(path + "/temp.mp4");
|
||||
await checkAndRemoveFile(path + "/temp.flac");
|
||||
await checkAndRemoveFile(path + "/thumbnail.png");
|
||||
await ytDlpGetThumbnail(path, url, isOversea, this.myProxy, this.youtubeCookiePath);
|
||||
const title = ytDlpGetTilt(url, isOversea, this.myProxy, this.youtubeCookiePath).toString().replace(/\n/g, '');
|
||||
|
||||
// 音频逻辑
|
||||
@ -2144,7 +2144,7 @@ export class tools extends plugin {
|
||||
message: segment.image(item),
|
||||
nickname: this.e.sender.card || this.e.user_id,
|
||||
user_id: this.e.user_id,
|
||||
}
|
||||
};
|
||||
});
|
||||
e.reply(Bot.makeForwardMsg(replyImages));
|
||||
}
|
||||
@ -2158,13 +2158,13 @@ export class tools extends plugin {
|
||||
// 暂时选取分辨率较低的video进行解析
|
||||
const videoUrl = resolutions[i].url;
|
||||
this.downloadVideo(videoUrl).then(path => {
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 微视
|
||||
@ -2185,7 +2185,7 @@ export class tools extends plugin {
|
||||
if (!idMatch || idMatch.length !== 2) {
|
||||
e.reply("识别:微视,但无法完整检测到视频ID");
|
||||
// 打个日志 方便后面出bug知道位置
|
||||
logger.error("[R插件][微视] 无法检测到ID,逻辑大概问题在正则表达式")
|
||||
logger.error("[R插件][微视] 无法检测到ID,逻辑大概问题在正则表达式");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2206,7 +2206,7 @@ export class tools extends plugin {
|
||||
e.reply([segment.image(cover), `${ this.identifyPrefix }识别:微视,${ title }`]);
|
||||
|
||||
this.downloadVideo(noWatermarkDownloadUrl).then(path => {
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
@ -2244,7 +2244,7 @@ export class tools extends plugin {
|
||||
imgSrcs.push(match[1]); // Adds the content of the src attribute to the array
|
||||
}
|
||||
|
||||
const images = imgSrcs.filter(item => item.includes("\/img\/view\/id"))
|
||||
const images = imgSrcs.filter(item => item.includes("\/img\/view\/id"));
|
||||
|
||||
// Construct the response object
|
||||
const shortVideoInfo = {
|
||||
@ -2255,7 +2255,7 @@ export class tools extends plugin {
|
||||
images,
|
||||
};
|
||||
|
||||
e.reply(`${this.identifyPrefix}识别:最右,${shortVideoInfo.authorName}\n${shortVideoInfo.title}`)
|
||||
e.reply(`${ this.identifyPrefix }识别:最右,${ shortVideoInfo.authorName }\n${ shortVideoInfo.title }`);
|
||||
|
||||
if (shortVideoInfo.images.length > 0) {
|
||||
const replyImages = shortVideoInfo.images.map(item => {
|
||||
@ -2263,13 +2263,13 @@ export class tools extends plugin {
|
||||
message: segment.image(item),
|
||||
nickname: this.e.sender.card || this.e.user_id,
|
||||
user_id: this.e.user_id,
|
||||
}
|
||||
};
|
||||
});
|
||||
e.reply(Bot.makeForwardMsg(replyImages));
|
||||
}
|
||||
if (shortVideoInfo.noWatermarkDownloadUrl) {
|
||||
this.downloadVideo(shortVideoInfo.noWatermarkDownloadUrl).then(path => {
|
||||
this.sendVideoToUpload(e, `${path}/temp.mp4`)
|
||||
this.sendVideoToUpload(e, `${ path }/temp.mp4`);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@ -2287,7 +2287,7 @@ export class tools extends plugin {
|
||||
// 找到R插件保存目录
|
||||
const currentWorkingDirectory = path.resolve(this.getCurDownloadPath(e));
|
||||
// 如果没有文件夹就创建一个
|
||||
await mkdirIfNotExists(currentWorkingDirectory + "/am")
|
||||
await mkdirIfNotExists(currentWorkingDirectory + "/am");
|
||||
// 检测是否存在框架
|
||||
const isExistFreyr = await checkToolInCurEnv("freyr");
|
||||
if (!isExistFreyr) {
|
||||
@ -2308,7 +2308,7 @@ export class tools extends plugin {
|
||||
"Origin": "https://apple-music-downloader.com",
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
},
|
||||
})
|
||||
});
|
||||
const { name, artists } = data.data.result;
|
||||
title = name;
|
||||
artist = artists;
|
||||
@ -2391,7 +2391,7 @@ export class tools extends plugin {
|
||||
// 计算阅读时间
|
||||
const stats = estimateReadingTime(kimiAns);
|
||||
const titleMatch = kimiAns.match(/(Title|标题)([::])\s*(.*?)\n/)?.[3];
|
||||
e.reply(`《${titleMatch}》 预计阅读时间: ${stats.minutes} 分钟,总字数: ${stats.words}`)
|
||||
e.reply(`《${ titleMatch }》 预计阅读时间: ${ stats.minutes } 分钟,总字数: ${ stats.words }`);
|
||||
const Msg = await Bot.makeForwardMsg(textArrayToMakeForward(e, [`「R插件 x ${ model }」联合为您总结内容:`, kimiAns]));
|
||||
await e.reply(Msg);
|
||||
return true;
|
||||
@ -2431,7 +2431,7 @@ export class tools extends plugin {
|
||||
musicInfo = prompt + "-" + desc;
|
||||
// 空判定
|
||||
if (musicInfo.trim() === "-" || prompt === undefined || desc === undefined) {
|
||||
logger.info(`没有识别到QQ音乐小程序,帮助文档如下:${HELP_DOC}`)
|
||||
logger.info(`没有识别到QQ音乐小程序,帮助文档如下:${ HELP_DOC }`);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -2523,7 +2523,7 @@ export class tools extends plugin {
|
||||
nickname: e.sender.card || e.user_id,
|
||||
user_id: e.user_id,
|
||||
};
|
||||
})
|
||||
});
|
||||
e.reply(await Bot.makeForwardMsg(imagesData), true, { recallMsg: MESSAGE_RECALL_TIME });
|
||||
} else if (mediaFiles.videos.length > 0) {
|
||||
for (const item of mediaFiles.videos) {
|
||||
@ -2554,11 +2554,11 @@ export class tools extends plugin {
|
||||
const top = postList[0];
|
||||
// 提取标题和内容
|
||||
const { title, content } = top;
|
||||
let sendContent = `${this.identifyPrefix}识别:贴吧,${title}`
|
||||
let sendContent = `${ this.identifyPrefix }识别:贴吧,${ title }`;
|
||||
let extractImages = [];
|
||||
// 如果内容中有图片、文本或视频,它会将它们添加到 sendContent 消息中
|
||||
if (content && content.length > 0) {
|
||||
sendContent = [sendContent]
|
||||
sendContent = [sendContent];
|
||||
for (const { cdn_src, text, link } of content) {
|
||||
logger.info({ cdn_src, text, link }); // 可以一次性输出多个属性
|
||||
|
||||
@ -2670,7 +2670,7 @@ export class tools extends plugin {
|
||||
|
||||
const location = resp.request.res.responseUrl;
|
||||
|
||||
const setCookieHeaders = resp.headers['set-cookie']
|
||||
const setCookieHeaders = resp.headers['set-cookie'];
|
||||
let ttwidValue;
|
||||
if (setCookieHeaders) {
|
||||
setCookieHeaders.forEach(cookie => {
|
||||
@ -2704,7 +2704,7 @@ export class tools extends plugin {
|
||||
* @returns {string}
|
||||
*/
|
||||
getCurDownloadPath(e) {
|
||||
return `${this.defaultPath}${e.group_id || e.user_id}`
|
||||
return `${ this.defaultPath }${ e.group_id || e.user_id }`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2737,7 +2737,7 @@ export class tools extends plugin {
|
||||
...(isProxy && {
|
||||
httpAgent: new HttpsProxyAgent(`http://${ this.proxyAddr }:${ this.proxyPort }`),
|
||||
}),
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 构造下载视频参数
|
||||
@ -2751,7 +2751,7 @@ export class tools extends plugin {
|
||||
proxyOption,
|
||||
target,
|
||||
groupPath,
|
||||
}
|
||||
};
|
||||
logger.info(`[R插件][视频下载]:当前队列长度为 ${ this.queue.size + 1 }`);
|
||||
return await this.queue.add(async () => {
|
||||
// 如果是用户设置了单线程,则不分片下载
|
||||
@ -2811,7 +2811,7 @@ export class tools extends plugin {
|
||||
promises.push(axios.get(url, partAxiosConfig).then(res => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const partPath = `${ target }.part${ i }`;
|
||||
logger.mark(`[R插件][视频下载引擎] 正在下载 part${i}`)
|
||||
logger.mark(`[R插件][视频下载引擎] 正在下载 part${ i }`);
|
||||
const writer = fs.createWriteStream(partPath);
|
||||
res.data.pipe(writer);
|
||||
writer.on("finish", () => {
|
||||
@ -3031,7 +3031,7 @@ export class tools extends plugin {
|
||||
if (!(await redisExistKey(REDIS_YUNZAI_ISOVERSEA))) {
|
||||
await redisSetKey(REDIS_YUNZAI_ISOVERSEA, {
|
||||
os: false,
|
||||
})
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// 如果有就取出来
|
||||
|
Loading…
x
Reference in New Issue
Block a user