mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 16:19:18 +00:00
🦄 refactor: 修复翻译策略模式,提高扩展性
1. 修复翻译策略模式,提高扩展性 2. 修正README 3. 删除网易云,难维护
This commit is contained in:
parent
8c5092faab
commit
c8fe813404
@ -28,10 +28,6 @@ utils -- 工具类
|
|||||||
|
|
||||||
## 🧏 使用实例
|
## 🧏 使用实例
|
||||||

|

|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
## 📔 使用说明
|
## 📔 使用说明
|
||||||
|
|
||||||
@ -143,7 +139,7 @@ sudo apt-get install ffmpeg
|
|||||||
| mitsuha | 1杯瑞幸 |
|
| mitsuha | 1杯瑞幸 |
|
||||||
| [Kr] 5s¹ | 1杯瑞幸 |
|
| [Kr] 5s¹ | 1杯瑞幸 |
|
||||||
|
|
||||||
## 🚀 后记
|
## 🚀 声明
|
||||||
* 文件借鉴了很多插件,精简个人认为可以精简的内容。
|
* 文件借鉴了很多插件,精简个人认为可以精简的内容。
|
||||||
* 素材来源于网络,仅供交流学习使用
|
* 素材来源于网络,仅供交流学习使用
|
||||||
* 严禁用于任何商业用途和非法行为
|
* 严禁用于任何商业用途和非法行为
|
||||||
|
@ -1,459 +0,0 @@
|
|||||||
import plugin from "../../../lib/plugins/plugin.js";
|
|
||||||
import axios from "axios";
|
|
||||||
import fs from "node:fs";
|
|
||||||
import {
|
|
||||||
checkMusic,
|
|
||||||
getCookies,
|
|
||||||
getDailyRecommend,
|
|
||||||
getKey,
|
|
||||||
getLoginStatus,
|
|
||||||
getQrCode,
|
|
||||||
getSong,
|
|
||||||
getSongDetail,
|
|
||||||
getUserRecord,
|
|
||||||
getCloud,
|
|
||||||
getCloudMusicDetail,
|
|
||||||
} from "../utils/netease.js";
|
|
||||||
import { ha12store, store2ha1 } from "../utils/encrypt.js";
|
|
||||||
import { downloadMp3 } from "../utils/common.js";
|
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
export class neteasepro extends plugin {
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
/** 功能名称 */
|
|
||||||
name: "R插件网易云音乐解析",
|
|
||||||
/** 功能描述 */
|
|
||||||
dsc: "网易云音乐解析Pro",
|
|
||||||
/** https://oicqjs.github.io/oicq/#events */
|
|
||||||
event: "message",
|
|
||||||
/** 优先级,数字越小等级越高 */
|
|
||||||
priority: 500,
|
|
||||||
rule: [
|
|
||||||
{
|
|
||||||
/** 命令正则匹配 */
|
|
||||||
reg: "^#网易云登录$",
|
|
||||||
/** 执行方法 */
|
|
||||||
fnc: "neteaseCloudLogin",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "^#网易云每日推荐$",
|
|
||||||
fnc: "neteaseDailyRecommend",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "^#网易云听歌排行$",
|
|
||||||
fnc: "neteaseListenRank",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "^#网易云云盘$",
|
|
||||||
fnc: "neteaseCloud",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "^#网易云云盘下载(.*)",
|
|
||||||
fnc: "neteaseCloudDownload",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "^#网易云云盘(.*)",
|
|
||||||
fnc: "neteaseCloudApplet",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reg: "music.163.com",
|
|
||||||
fnc: "netease",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseCloudLogin(e) {
|
|
||||||
let neteaseCookie;
|
|
||||||
// 如果不存在cookie
|
|
||||||
if (!(await redis.exists(await this.getRedisKey(e.user_id)))) {
|
|
||||||
// 获取密钥
|
|
||||||
const key = await getKey();
|
|
||||||
// console.log(key);
|
|
||||||
// 获取二维码
|
|
||||||
const qrPic = await getQrCode(key);
|
|
||||||
// 下载qrcode
|
|
||||||
await this.downloadQrCode(qrPic).then(path => {
|
|
||||||
// 发送二维码
|
|
||||||
e.reply(segment.image(fs.readFileSync(path)));
|
|
||||||
});
|
|
||||||
// 定时轮询
|
|
||||||
await this.poll(key).then(async cookie => {
|
|
||||||
// 存放到redis
|
|
||||||
neteaseCookie = cookie;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const userData = await redis.get(await this.getRedisKey(e.user_id));
|
|
||||||
// 如果cookie存在但是为空
|
|
||||||
if (_.isEmpty(userData)) {
|
|
||||||
await redis.del(await this.getRedisKey(e.user_id));
|
|
||||||
e.reply("发生已知错误:cookie为空,请重试 #网易云登录 即可!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 已经登陆过的,直接从redis取出
|
|
||||||
neteaseCookie = await store2ha1(JSON.parse(userData).cookie);
|
|
||||||
}
|
|
||||||
// 获取用户信息
|
|
||||||
const userInfo = await getLoginStatus(neteaseCookie);
|
|
||||||
// 提取信息
|
|
||||||
const { userId, nickname, avatarUrl } = userInfo.profile;
|
|
||||||
e.reply(["欢迎使用 🎶网易云音乐 🎶," + nickname, segment.image(avatarUrl)]);
|
|
||||||
// 重组后存放到redis {uid, cookie}
|
|
||||||
await redis.set(
|
|
||||||
await this.getRedisKey(e.user_id),
|
|
||||||
JSON.stringify({
|
|
||||||
uid: userId,
|
|
||||||
cookie: await ha12store(neteaseCookie),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseDailyRecommend(e) {
|
|
||||||
const realCookie = (await this.aopBefore(e)).cookie;
|
|
||||||
if (realCookie === "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 获取每日推荐所有数据
|
|
||||||
const dailyRecommend = await getDailyRecommend(realCookie);
|
|
||||||
const combineMsg = await dailyRecommend.dailySongs.map(async item => {
|
|
||||||
// 组合数据
|
|
||||||
return {
|
|
||||||
message: segment.json(await this.musicPack(item)),
|
|
||||||
nickname: e.sender.card || e.user_id,
|
|
||||||
user_id: e.user_id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
let forwardMsg = await Bot.makeForwardMsg(await Promise.all(combineMsg));
|
|
||||||
await e.reply(await this.musicForwardPack(forwardMsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseListenRank(e) {
|
|
||||||
const userInfo = await this.aopBefore(e);
|
|
||||||
const realCookie = userInfo.cookie;
|
|
||||||
if (realCookie === "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 获取用户id
|
|
||||||
const uid = userInfo.uid;
|
|
||||||
// 获取听歌排行榜
|
|
||||||
const userRecord = await getUserRecord(uid);
|
|
||||||
e.reply(" 😘亲,这是你的听歌排行榜Top10");
|
|
||||||
// 由于数据过大,取前10
|
|
||||||
const rank = userRecord.weekData.slice(0, 10).map(async item => {
|
|
||||||
// 组合数据
|
|
||||||
const song = item.song;
|
|
||||||
return {
|
|
||||||
message: segment.json(await this.musicPack(song)),
|
|
||||||
nickname: e.sender.card || e.user_id,
|
|
||||||
user_id: e.user_id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
let forwardMsg = await Bot.makeForwardMsg(await Promise.all(rank));
|
|
||||||
await e.reply(await this.musicForwardPack(forwardMsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseCloud(e) {
|
|
||||||
const userInfo = await this.aopBefore(e);
|
|
||||||
const realCookie = userInfo.cookie;
|
|
||||||
if (realCookie === "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const cloudMusics = await (
|
|
||||||
await getCloud(realCookie)
|
|
||||||
).map(item => {
|
|
||||||
return {
|
|
||||||
message: `${item.songId}: ${item?.songName??"暂无歌曲信息"}-${item?.artist??"暂无歌手信息"}`,
|
|
||||||
nickname: e.sender.card || e.user_id,
|
|
||||||
user_id: e.user_id,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 获取用户信息
|
|
||||||
const { profile } = await getLoginStatus(realCookie);
|
|
||||||
e.reply(`<${profile.nickname}> 的网易云云盘`);
|
|
||||||
e.reply(await Bot.makeForwardMsg(cloudMusics));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseCloudDownload(e) {
|
|
||||||
const id = e.msg.replace("#网易云云盘下载", "").trim();
|
|
||||||
const userInfo = await this.aopBefore(e);
|
|
||||||
const realCookie = userInfo.cookie;
|
|
||||||
if (realCookie === "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const music = (await getSong(id, realCookie))[0];
|
|
||||||
const item = (await getCloudMusicDetail(id, realCookie)).data[0];
|
|
||||||
const simpleSong = item.simpleSong;
|
|
||||||
e.reply([
|
|
||||||
segment.image(simpleSong?.al?.picUrl),
|
|
||||||
`识别:云盘音乐,${simpleSong?.name}-${simpleSong?.al?.name}`,
|
|
||||||
]);
|
|
||||||
const downloadPath = `./data/rcmp4/${this.e.group_id || this.e.user_id}`;
|
|
||||||
await downloadMp3(music.url, downloadPath)
|
|
||||||
.then(path => {
|
|
||||||
Bot.acquireGfs(e.group_id).upload(
|
|
||||||
fs.readFileSync(path),
|
|
||||||
"/",
|
|
||||||
`${simpleSong?.name}.mp3`,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(`下载音乐失败,错误信息为: ${err.message}`);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async neteaseCloudApplet(e) {
|
|
||||||
const id = e.msg.replace("#网易云云盘", "").trim();
|
|
||||||
logger.mark(id);
|
|
||||||
const userInfo = await this.aopBefore(e);
|
|
||||||
const realCookie = userInfo.cookie;
|
|
||||||
if (realCookie === "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const music = (await getSong(id, realCookie))[0];
|
|
||||||
const item = (await getCloudMusicDetail(id, realCookie)).data[0];
|
|
||||||
const appletMusic = {
|
|
||||||
message: segment.json(await this.cloudMusicPack(item, music.url)),
|
|
||||||
nickname: e.sender.card || e.user_id,
|
|
||||||
user_id: e.user_id,
|
|
||||||
};
|
|
||||||
let forwardMsg = await Bot.makeForwardMsg(appletMusic);
|
|
||||||
await e.reply(await this.musicForwardPack(forwardMsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
async netease(e) {
|
|
||||||
const message =
|
|
||||||
e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
|
||||||
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 =
|
|
||||||
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)))) {
|
|
||||||
// 是小程序
|
|
||||||
if (await this.isJSON(message)) {
|
|
||||||
const musicJson = JSON.parse(message);
|
|
||||||
const { preview, title, desc } = musicJson.meta.music || musicJson.meta.news;
|
|
||||||
// console.log(musicUrl, preview, title, desc);
|
|
||||||
// 如果没有登陆,就使用官方接口
|
|
||||||
e.reply([`识别:网易云音乐,${title}--${desc}`, segment.image(preview)]);
|
|
||||||
} else {
|
|
||||||
// 非小程序
|
|
||||||
const title = await getSongDetail(id).then(res => {
|
|
||||||
const song = res.songs?.[0];
|
|
||||||
return song?.length > 0
|
|
||||||
? `${song?.name}-${song?.ar?.[0].name}`.replace(/[\/\?<>\\:\*\|".… ]/g, "")
|
|
||||||
: "暂无信息";
|
|
||||||
});
|
|
||||||
e.reply(`识别:网易云音乐,${title}`);
|
|
||||||
}
|
|
||||||
// 下载游客歌曲
|
|
||||||
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`);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(`下载音乐失败,错误信息为: ${err.message}`);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 检查当前歌曲是否可用
|
|
||||||
const checkOne = await checkMusic(id);
|
|
||||||
if (checkOne.success === "false") {
|
|
||||||
e.reply(checkOne.message);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const userInfo = await this.aopBefore(e);
|
|
||||||
// 可用,开始下载
|
|
||||||
const userDownloadUrl = (await getSong(id, await userInfo.cookie))[0].url;
|
|
||||||
const title = await getSongDetail(id).then(res => {
|
|
||||||
const song = res.songs[0];
|
|
||||||
return `${song?.name}-${song?.ar?.[0].name}`.replace(/[\/\?<>\\:\*\|".… ]/g, "");
|
|
||||||
});
|
|
||||||
await downloadMp3(userDownloadUrl, downloadPath)
|
|
||||||
.then(path => {
|
|
||||||
Bot.acquireGfs(e.group_id).upload(fs.readFileSync(path), "/", `${title}.mp3`);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(`下载音乐失败,错误信息为: ${err.message}`);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切面方法检测cookie & 获取cookie和uid
|
|
||||||
async aopBefore(e) {
|
|
||||||
// 取出cookie
|
|
||||||
const userDataJson = await redis.get(await this.getRedisKey(e.user_id));
|
|
||||||
// 如果不存在cookie
|
|
||||||
if (_.isEmpty(userDataJson)) {
|
|
||||||
e.reply("请先#网易云登录");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
let userData = JSON.parse(userDataJson);
|
|
||||||
const cookie = userData?.cookie;
|
|
||||||
logger.mark(cookie);
|
|
||||||
// 解析cookie
|
|
||||||
userData.cookie = await store2ha1(cookie);
|
|
||||||
// 检查cookie是否可用
|
|
||||||
const userInfo = await getLoginStatus(userData.cookie);
|
|
||||||
logger.mark(userData);
|
|
||||||
if (_.isNil(userInfo.profile)) {
|
|
||||||
e.reply("cookie已经过期,请重新#网易云登录!");
|
|
||||||
// 删除过期的cookie
|
|
||||||
await redis.del(await this.getRedisKey(e.user_id));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
// 没有过期直接返回
|
|
||||||
return userData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载二维码
|
|
||||||
async downloadQrCode(qrPic) {
|
|
||||||
return axios
|
|
||||||
.get(qrPic, {
|
|
||||||
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",
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
const filepath = "./netease_qr.jpg";
|
|
||||||
const writer = fs.createWriteStream(filepath);
|
|
||||||
resp.data.pipe(writer);
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
writer.on("finish", () => resolve(filepath));
|
|
||||||
writer.on("error", reject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否是json的字符串
|
|
||||||
async isJSON(str) {
|
|
||||||
if (typeof str !== "string") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
JSON.parse(str);
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定时轮询
|
|
||||||
async poll(key) {
|
|
||||||
let timer;
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
timer = setInterval(async () => {
|
|
||||||
const statusRes = await getCookies(key);
|
|
||||||
// console.log(statusRes);
|
|
||||||
if (statusRes.code === 800) {
|
|
||||||
clearInterval(timer);
|
|
||||||
reject("二维码已过期,请重新获取");
|
|
||||||
}
|
|
||||||
if (statusRes.code === 803) {
|
|
||||||
// 这一步会返回cookie
|
|
||||||
clearInterval(timer);
|
|
||||||
const cookie = statusRes.cookie;
|
|
||||||
resolve(
|
|
||||||
/__csrf=[0-9a-z]+;/.exec(cookie)[0] + /MUSIC_U=[0-9a-z]+;/.exec(cookie)[0],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async cloudMusicPack(item, url) {
|
|
||||||
return {
|
|
||||||
app: "com.tencent.structmsg",
|
|
||||||
desc: "音乐",
|
|
||||||
view: "music",
|
|
||||||
ver: "0.0.0.1",
|
|
||||||
prompt: "[分享]" + item.songName + "-" + item.album,
|
|
||||||
meta: {
|
|
||||||
music: {
|
|
||||||
app_type: 1,
|
|
||||||
appid: 100495085,
|
|
||||||
desc: item.artist,
|
|
||||||
jumpUrl: `https://y.music.163.com/m/song?id=${item.songId}`,
|
|
||||||
musicUrl: url,
|
|
||||||
preview: "https://i.gtimg.cn/open/app_icon/00/49/50/85/100495085_100_m.png",
|
|
||||||
sourceMsgId: "0",
|
|
||||||
source_icon: "https://i.gtimg.cn/open/app_icon/00/49/50/85/100495085_100_m.png",
|
|
||||||
source_url: "",
|
|
||||||
tag: "网易云音乐",
|
|
||||||
title: item.fileName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
type: "normal",
|
|
||||||
forward: true,
|
|
||||||
ctime: Date.now(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 包装分享小程序数据
|
|
||||||
async musicPack(song) {
|
|
||||||
const title = song.name;
|
|
||||||
const singer = song.ar?.[0]?.name;
|
|
||||||
const jumpUrl = `https://y.music.163.com/m/song?id=${song.id}`;
|
|
||||||
const preview = song.al?.picUrl;
|
|
||||||
const musicUrl = `https://music.163.com/song/media/outer/url?id=${song.id}.mp3`;
|
|
||||||
return {
|
|
||||||
app: "com.tencent.structmsg",
|
|
||||||
desc: "音乐",
|
|
||||||
view: "music",
|
|
||||||
ver: "0.0.0.1",
|
|
||||||
prompt: "[分享]" + title + "-" + singer,
|
|
||||||
meta: {
|
|
||||||
music: {
|
|
||||||
app_type: 1,
|
|
||||||
appid: 100495085,
|
|
||||||
desc: singer,
|
|
||||||
jumpUrl: jumpUrl,
|
|
||||||
musicUrl: musicUrl,
|
|
||||||
preview: preview,
|
|
||||||
sourceMsgId: "0",
|
|
||||||
source_icon: "https://i.gtimg.cn/open/app_icon/00/49/50/85/100495085_100_m.png",
|
|
||||||
source_url: "",
|
|
||||||
tag: "网易云音乐",
|
|
||||||
title: title,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
type: "normal",
|
|
||||||
forward: true,
|
|
||||||
ctime: Date.now(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async musicForwardPack(forwardMsg, forwardMsgName = "R插件消息") {
|
|
||||||
forwardMsg.data = forwardMsg.data
|
|
||||||
.replace(
|
|
||||||
'<?xml version="1.0" encoding="utf-8"?>',
|
|
||||||
'<?xml version="1.0" encoding="utf-8" ?>',
|
|
||||||
)
|
|
||||||
.replace(/\n/g, "")
|
|
||||||
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, "___")
|
|
||||||
.replace(/___+/, `<title color="#777777" size="26">${forwardMsgName}</title>`);
|
|
||||||
return forwardMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取redis的key
|
|
||||||
async getRedisKey(user_id) {
|
|
||||||
return `Yz:rconsole:netease:${user_id}`;
|
|
||||||
}
|
|
||||||
}
|
|
345
apps/tools.js
345
apps/tools.js
@ -132,17 +132,7 @@ export class tools extends plugin {
|
|||||||
proxy: this.myProxy,
|
proxy: this.myProxy,
|
||||||
});
|
});
|
||||||
// 如果没有百度那就Google
|
// 如果没有百度那就Google
|
||||||
let translateResult;
|
const translateResult = await translateEngine.translate(place, language[1]);
|
||||||
if (
|
|
||||||
_.isEmpty(this.toolsConfig.translateAppId) ||
|
|
||||||
_.isEmpty(this.toolsConfig.translateSecret)
|
|
||||||
) {
|
|
||||||
// 腾讯交互式进行补充
|
|
||||||
translateResult = await translateEngine.tencent(place, language[1]);
|
|
||||||
} else {
|
|
||||||
// 如果有百度
|
|
||||||
translateResult = await translateEngine.baidu(place, language[1]);
|
|
||||||
}
|
|
||||||
e.reply(translateResult.trim(), true);
|
e.reply(translateResult.trim(), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -462,285 +452,70 @@ export class tools extends plugin {
|
|||||||
// 小蓝鸟解析
|
// 小蓝鸟解析
|
||||||
// 例子:https://twitter.com/chonkyanimalx/status/1595834168000204800
|
// 例子:https://twitter.com/chonkyanimalx/status/1595834168000204800
|
||||||
async twitter(e) {
|
async twitter(e) {
|
||||||
const _0x2b294a = _0x2a30;
|
// 配置参数及解析
|
||||||
(function (_0x3b889f, _0xb2fbcd) {
|
const reg = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/;
|
||||||
const _0x2c003c = _0x2a30,
|
const twitterUrl = reg.exec(e.msg);
|
||||||
_0x486e9d = _0x3b889f();
|
const id = twitterUrl[1];
|
||||||
while (!![]) {
|
const httpAgent = new HttpProxyAgent(this.myProxy);
|
||||||
try {
|
const twitterClient = new TwitterApi(this.bearerToken, { httpAgent });
|
||||||
const _0x238c8c =
|
|
||||||
(parseInt(_0x2c003c(0x196, "St*P")) / 0x1) *
|
// Tell typescript it's a readonly app
|
||||||
(-parseInt(_0x2c003c(0x189, "$#GN")) / 0x2) +
|
const readOnlyClient = twitterClient.readOnly;
|
||||||
(-parseInt(_0x2c003c(0x188, "n58F")) / 0x3) *
|
|
||||||
(-parseInt(_0x2c003c(0x1a3, "WOCh")) / 0x4) +
|
readOnlyClient.v2
|
||||||
(-parseInt(_0x2c003c(0x18d, "i(e%")) / 0x5) *
|
.singleTweet(id, {
|
||||||
(-parseInt(_0x2c003c(0x19e, "b0CJ")) / 0x6) +
|
"media.fields":
|
||||||
parseInt(_0x2c003c(0x18c, "i(e%")) / 0x7 +
|
"duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width,alt_text,variants",
|
||||||
(-parseInt(_0x2c003c(0x185, "a1WE")) / 0x8) *
|
expansions: ["entities.mentions.username", "attachments.media_keys"],
|
||||||
(-parseInt(_0x2c003c(0x17f, "sNWj")) / 0x9) +
|
|
||||||
(parseInt(_0x2c003c(0x1a8, "(HXB")) / 0xa) *
|
|
||||||
(-parseInt(_0x2c003c(0x179, "sNWj")) / 0xb) +
|
|
||||||
-parseInt(_0x2c003c(0x175, "WNyv")) / 0xc;
|
|
||||||
if (_0x238c8c === _0xb2fbcd) break;
|
|
||||||
else _0x486e9d["push"](_0x486e9d["shift"]());
|
|
||||||
} catch (_0x3f707b) {
|
|
||||||
_0x486e9d["push"](_0x486e9d["shift"]());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})(_0x2d2e, 0x9d183);
|
|
||||||
function _0x2d2e() {
|
|
||||||
const _0x358dbc = [
|
|
||||||
"cSk4W4JcRuu",
|
|
||||||
"wX7cJGxdPCoKW5hcQmkJWPpcGCo3W6tdHSo1vGqdW5BdG37dKLNdTCoJgwnQlWrnWQjZW4/dPbb7W7BcNa",
|
|
||||||
"f8oJWOBcJq",
|
|
||||||
"W4euW4ldMa",
|
|
||||||
"k8kJWRhdHW",
|
|
||||||
"retdVXfAW4VcNWpcGHS",
|
|
||||||
"W4RcTmklaxZdJG",
|
|
||||||
"57YY57Mg6lYO5O2n5Aw26lAl772H6k2l6ys/6kYR7760",
|
|
||||||
"bqddMW",
|
|
||||||
"W5qCW5tdMqq",
|
|
||||||
"WOhcRSkCtG",
|
|
||||||
"p8oWq8o9W7rtW6SFfW",
|
|
||||||
"WRG9W7DE",
|
|
||||||
"WOZcPZ3dG2XGWQy",
|
|
||||||
"aCoAW7JdPwLKjZvcW50",
|
|
||||||
"WPlcUIH5WOGTeWVcQG",
|
|
||||||
"WOldMGfhENL7W7JcVuRcI3Gr",
|
|
||||||
"jCozxdPUsCk9WOq",
|
|
||||||
"qmoNW5xdTw5dhG",
|
|
||||||
"WR1Fe8oU",
|
|
||||||
"WR5XACkhu8kRW67cG2ldGSkEFGuW",
|
|
||||||
"W5hcPCkrfvBdII8VWPydxcC",
|
|
||||||
"WPlcVtrP",
|
|
||||||
"EhDbW51XzNNdOMSAW5hcHxW",
|
|
||||||
"WRmQWPipi8oyzNjxF2e",
|
|
||||||
"bsy4WQFdPxhdPCofpG",
|
|
||||||
"WOBcQtnG",
|
|
||||||
"zSkXWOPrfM7cPW",
|
|
||||||
"W6yHmmosjSoWWQJcK2ddT8klsIu",
|
|
||||||
"hqhdKa",
|
|
||||||
"bcOkWOqRpcJcUrjYWONdQJOxWPnYWOmqW5SGW6XBpZ3dVH4lmWBdNtBdS0SXW77cKSkjW6eMkmoma8ozqs/cUCk4kmkLrSkmkmk0sZ4SWQOOtSoalHRcLmkHW6VcRqf/WRiHi1OmbmosWOLWW67dPqLcW7HBkIBdNgW4WPiNiZ0NtSoFo8oTWORdSSooFZlcIXZdPmkDWQBdJCosWRy4W6i/lSkSWPddUIhdLmkTAmkdWORcSSkqeSkXW7vfWQe7EIldR0C",
|
|
||||||
"gSkzW4FcPSktWROUrXFdQe9VW6W",
|
|
||||||
"WOG7jflcSu7cKa",
|
|
||||||
"hSoVW7DRsbH8WQVcGWSB",
|
|
||||||
"vw0EWRLUWRVdUJVdLdPKu8o5eq",
|
|
||||||
"WRTsbSoSWRu",
|
|
||||||
"seFcGCkLnWqA",
|
|
||||||
"gahdK8odzGtcPd3cOW",
|
|
||||||
"eu1OWOhdNCkipCkG",
|
|
||||||
"xSkYW6VcNuTZoa",
|
|
||||||
"z8olWQZdQ8k3e8kxdG",
|
|
||||||
"W6r2W5DqFCkonNnhvwxdKCkR",
|
|
||||||
"WRibWRJcS8o6",
|
|
||||||
"u8koW63cVu1ohq",
|
|
||||||
"gHbMWRhdPCk9hq",
|
|
||||||
"WRRcIHnyka",
|
|
||||||
"iCkgWPT8W5hdUmooWPVdL1i",
|
|
||||||
"wCkSD1ldOG",
|
|
||||||
"WOVdO8kSde7dUcuF",
|
|
||||||
"W4BcMLW",
|
|
||||||
"hSo4nq7cQmkztSoCbmkjd8ozoa",
|
|
||||||
"W5JcVCkj",
|
|
||||||
"f8kOW5/cRa",
|
|
||||||
"WORdOSoxvcVcHxS4WOCWsZiE",
|
|
||||||
"WP7cLZVcKd/dJ3BdPgiw",
|
|
||||||
"as1kW60",
|
|
||||||
"tXPpWO/dVSkK",
|
|
||||||
"w0dcJmkolghdSYpcLmoHW7jTrW",
|
|
||||||
"xexcI8knl23dVHNcOmoXW5vWuW",
|
|
||||||
"mmooqYnN",
|
|
||||||
"WQrseSoPWQ0",
|
|
||||||
"BSkpkSkZ",
|
|
||||||
];
|
|
||||||
_0x2d2e = function () {
|
|
||||||
return _0x358dbc;
|
|
||||||
};
|
|
||||||
return _0x2d2e();
|
|
||||||
}
|
|
||||||
const reg = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/,
|
|
||||||
twitterUrl = reg[_0x2b294a(0x18a, "WNyv")](e[_0x2b294a(0x199, "i(e%")]);
|
|
||||||
function _0x2a30(_0x530974, _0x1c7c1a) {
|
|
||||||
const _0x2d2e9c = _0x2d2e();
|
|
||||||
return (
|
|
||||||
(_0x2a30 = function (_0x2a30ca, _0x37fd16) {
|
|
||||||
_0x2a30ca = _0x2a30ca - 0x16d;
|
|
||||||
let _0x21253e = _0x2d2e9c[_0x2a30ca];
|
|
||||||
if (_0x2a30["ogixyo"] === undefined) {
|
|
||||||
var _0x52d638 = function (_0x446b97) {
|
|
||||||
const _0xa7d17e =
|
|
||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=";
|
|
||||||
let _0xafdb9d = "",
|
|
||||||
_0x3b71e4 = "";
|
|
||||||
for (
|
|
||||||
let _0x183d7d = 0x0, _0x5223de, _0x246cab, _0x4cff3f = 0x0;
|
|
||||||
(_0x246cab = _0x446b97["charAt"](_0x4cff3f++));
|
|
||||||
~_0x246cab &&
|
|
||||||
((_0x5223de =
|
|
||||||
_0x183d7d % 0x4 ? _0x5223de * 0x40 + _0x246cab : _0x246cab),
|
|
||||||
_0x183d7d++ % 0x4)
|
|
||||||
? (_0xafdb9d += String["fromCharCode"](
|
|
||||||
0xff & (_0x5223de >> ((-0x2 * _0x183d7d) & 0x6)),
|
|
||||||
))
|
|
||||||
: 0x0
|
|
||||||
) {
|
|
||||||
_0x246cab = _0xa7d17e["indexOf"](_0x246cab);
|
|
||||||
}
|
|
||||||
for (
|
|
||||||
let _0x22c263 = 0x0, _0x35c45b = _0xafdb9d["length"];
|
|
||||||
_0x22c263 < _0x35c45b;
|
|
||||||
_0x22c263++
|
|
||||||
) {
|
|
||||||
_0x3b71e4 +=
|
|
||||||
"%" +
|
|
||||||
("00" + _0xafdb9d["charCodeAt"](_0x22c263)["toString"](0x10))[
|
|
||||||
"slice"
|
|
||||||
](-0x2);
|
|
||||||
}
|
|
||||||
return decodeURIComponent(_0x3b71e4);
|
|
||||||
};
|
|
||||||
const _0x19042c = function (_0x1a0949, _0x39973a) {
|
|
||||||
let _0x13bd90 = [],
|
|
||||||
_0x58b48b = 0x0,
|
|
||||||
_0x52565c,
|
|
||||||
_0x412ec8 = "";
|
|
||||||
_0x1a0949 = _0x52d638(_0x1a0949);
|
|
||||||
let _0x4766c1;
|
|
||||||
for (_0x4766c1 = 0x0; _0x4766c1 < 0x100; _0x4766c1++) {
|
|
||||||
_0x13bd90[_0x4766c1] = _0x4766c1;
|
|
||||||
}
|
|
||||||
for (_0x4766c1 = 0x0; _0x4766c1 < 0x100; _0x4766c1++) {
|
|
||||||
(_0x58b48b =
|
|
||||||
(_0x58b48b +
|
|
||||||
_0x13bd90[_0x4766c1] +
|
|
||||||
_0x39973a["charCodeAt"](_0x4766c1 % _0x39973a["length"])) %
|
|
||||||
0x100),
|
|
||||||
(_0x52565c = _0x13bd90[_0x4766c1]),
|
|
||||||
(_0x13bd90[_0x4766c1] = _0x13bd90[_0x58b48b]),
|
|
||||||
(_0x13bd90[_0x58b48b] = _0x52565c);
|
|
||||||
}
|
|
||||||
(_0x4766c1 = 0x0), (_0x58b48b = 0x0);
|
|
||||||
for (
|
|
||||||
let _0x26b7be = 0x0;
|
|
||||||
_0x26b7be < _0x1a0949["length"];
|
|
||||||
_0x26b7be++
|
|
||||||
) {
|
|
||||||
(_0x4766c1 = (_0x4766c1 + 0x1) % 0x100),
|
|
||||||
(_0x58b48b = (_0x58b48b + _0x13bd90[_0x4766c1]) % 0x100),
|
|
||||||
(_0x52565c = _0x13bd90[_0x4766c1]),
|
|
||||||
(_0x13bd90[_0x4766c1] = _0x13bd90[_0x58b48b]),
|
|
||||||
(_0x13bd90[_0x58b48b] = _0x52565c),
|
|
||||||
(_0x412ec8 += String["fromCharCode"](
|
|
||||||
_0x1a0949["charCodeAt"](_0x26b7be) ^
|
|
||||||
_0x13bd90[
|
|
||||||
(_0x13bd90[_0x4766c1] + _0x13bd90[_0x58b48b]) %
|
|
||||||
0x100
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return _0x412ec8;
|
|
||||||
};
|
|
||||||
(_0x2a30["JRXdPT"] = _0x19042c),
|
|
||||||
(_0x530974 = arguments),
|
|
||||||
(_0x2a30["ogixyo"] = !![]);
|
|
||||||
}
|
|
||||||
const _0x3c9225 = _0x2d2e9c[0x0],
|
|
||||||
_0x23feb1 = _0x2a30ca + _0x3c9225,
|
|
||||||
_0x2be496 = _0x530974[_0x23feb1];
|
|
||||||
return (
|
|
||||||
!_0x2be496
|
|
||||||
? (_0x2a30["wKJatu"] === undefined && (_0x2a30["wKJatu"] = !![]),
|
|
||||||
(_0x21253e = _0x2a30["JRXdPT"](_0x21253e, _0x37fd16)),
|
|
||||||
(_0x530974[_0x23feb1] = _0x21253e))
|
|
||||||
: (_0x21253e = _0x2be496),
|
|
||||||
_0x21253e
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
_0x2a30(_0x530974, _0x1c7c1a)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
axios["get"](_0x2b294a(0x192, "8xd3") + twitterUrl, {
|
|
||||||
headers: { "User-Agent": _0x2b294a(0x171, "(HXB") },
|
|
||||||
httpAgent: tunnel[_0x2b294a(0x1a6, "n58F")]({
|
|
||||||
proxy: { host: this["proxyAddr"], port: this[_0x2b294a(0x1a0, "#E4x")] },
|
|
||||||
}),
|
|
||||||
httpsAgent: tunnel["httpOverHttp"]({
|
|
||||||
proxy: {
|
|
||||||
host: this[_0x2b294a(0x19c, "8AxH")],
|
|
||||||
port: this[_0x2b294a(0x178, "i(e%")],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
[_0x2b294a(0x1a4, "ljiK")](async _0x19042c => {
|
.then(async resp => {
|
||||||
const _0x466f71 = _0x2b294a,
|
e.reply(`识别:小蓝鸟学习版,${resp.data.text}`);
|
||||||
_0x446b97 = _0x19042c[_0x466f71(0x16d, "#E4x")];
|
const downloadPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`;
|
||||||
e[_0x466f71(0x182, "a1WE")](
|
// 创建文件夹(如果没有过这个群)
|
||||||
"识别:小蓝鸟学习版," + _0x446b97[_0x466f71(0x19d, "sFkZ")],
|
if (!fs.existsSync(downloadPath)) {
|
||||||
);
|
mkdirsSync(downloadPath);
|
||||||
const _0xa7d17e =
|
|
||||||
"" +
|
|
||||||
this[_0x466f71(0x174, "e^@[")] +
|
|
||||||
(this["e"][_0x466f71(0x1a2, "ZG#8")] || this["e"]["user_id"]);
|
|
||||||
await mkdirIfNotExists(_0xa7d17e);
|
|
||||||
let _0xafdb9d = [];
|
|
||||||
for (let _0x5223de of _0x446b97[_0x466f71(0x18f, "ljiK")]) {
|
|
||||||
if (_0x5223de[_0x466f71(0x193, "PrCv")] === "photo")
|
|
||||||
_0xafdb9d[_0x466f71(0x187, "l3ea")](
|
|
||||||
this[_0x466f71(0x1a9, "8Z)x")](
|
|
||||||
_0x5223de[_0x466f71(0x170, "i(e%")],
|
|
||||||
_0xa7d17e,
|
|
||||||
"",
|
|
||||||
!![],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
else
|
|
||||||
_0x5223de["type"] === _0x466f71(0x19a, "S%SI") &&
|
|
||||||
(await this[_0x466f71(0x172, "xitm")](
|
|
||||||
_0x446b97[_0x466f71(0x191, "l3ea")][0x0][
|
|
||||||
_0x466f71(0x17b, "4T^f")
|
|
||||||
][0x0][_0x466f71(0x184, "l1yR")],
|
|
||||||
!![],
|
|
||||||
)[_0x466f71(0x190, "7^hS")](_0x246cab => {
|
|
||||||
const _0x18d3e3 = _0x466f71;
|
|
||||||
e[_0x18d3e3(0x17d, "lxBO")](
|
|
||||||
segment["video"](_0xa7d17e + _0x18d3e3(0x1aa, "Qdr[")),
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
if (_0xafdb9d[_0x466f71(0x18b, "sNWj")] === 0x0) return !![];
|
// 逐个遍历判断
|
||||||
let _0x3b71e4 = [],
|
let task = [];
|
||||||
_0x183d7d = [];
|
for (let item of resp.includes.media) {
|
||||||
await Promise[_0x466f71(0x186, "n58F")](_0xafdb9d)[_0x466f71(0x19b, "Wshq")](
|
if (item.type === "photo") {
|
||||||
_0x4cff3f => {
|
// 图片
|
||||||
_0x4cff3f["forEach"](_0x22c263 => {
|
task.push(this.downloadImg(item.url, downloadPath, "", true));
|
||||||
const _0x49694d = _0x2a30;
|
} else if (item.type === "video") {
|
||||||
_0x183d7d[_0x49694d(0x195, "q#t*")](_0x22c263),
|
// 视频
|
||||||
_0x3b71e4[_0x49694d(0x1a7, "#E4x")]({
|
await this.downloadVideo(resp.includes.media[0].variants[0].url, true).then(
|
||||||
message: segment[_0x49694d(0x180, "XTb0")](
|
_ => {
|
||||||
fs["readFileSync"](_0x22c263),
|
e.reply(segment.video(`${downloadPath}/temp.mp4`));
|
||||||
),
|
|
||||||
nickname:
|
|
||||||
this["e"][_0x49694d(0x197, "n58F")][
|
|
||||||
_0x49694d(0x194, "S%SI")
|
|
||||||
] || this["e"][_0x49694d(0x177, "3o)K")],
|
|
||||||
user_id: this["e"][_0x49694d(0x173, "3Kft")],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
await e[_0x466f71(0x176, "ljiK")](
|
}
|
||||||
await Bot[_0x466f71(0x1a5, "k90U")](_0x3b71e4),
|
}
|
||||||
),
|
// 如果没有图片直接返回走
|
||||||
_0x183d7d["forEach"](_0x35c45b => {
|
if (task.length === 0) {
|
||||||
const _0x4bccf3 = _0x466f71;
|
return true;
|
||||||
fs[_0x4bccf3(0x19f, "WOCh")](_0x35c45b);
|
}
|
||||||
|
// 下面是有图片的情况
|
||||||
|
let images = [];
|
||||||
|
let path = [];
|
||||||
|
// 获取所有图片的promise
|
||||||
|
await Promise.all(task).then(resp => {
|
||||||
|
// console.log(resp)
|
||||||
|
resp.forEach(item => {
|
||||||
|
path.push(item);
|
||||||
|
images.push({
|
||||||
|
message: segment.image(fs.readFileSync(item)),
|
||||||
|
nickname: this.e.sender.card || this.e.user_id,
|
||||||
|
user_id: this.e.user_id,
|
||||||
});
|
});
|
||||||
})
|
|
||||||
["catch"](_0x1a0949 => {
|
|
||||||
const _0x5b9cf4 = _0x2b294a;
|
|
||||||
e[_0x5b9cf4(0x18e, "ZG#8")](_0x5b9cf4(0x198, "PrCv"));
|
|
||||||
});
|
});
|
||||||
return !![];
|
});
|
||||||
|
await e.reply(await Bot.makeForwardMsg(images));
|
||||||
|
// 清理文件
|
||||||
|
path.forEach(item => {
|
||||||
|
fs.unlinkSync(item);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// acfun解析
|
// acfun解析
|
||||||
|
BIN
img/example.webp
BIN
img/example.webp
Binary file not shown.
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 265 KiB |
Binary file not shown.
Before Width: | Height: | Size: 248 KiB |
Binary file not shown.
Before Width: | Height: | Size: 174 KiB |
Binary file not shown.
Before Width: | Height: | Size: 278 KiB |
Binary file not shown.
Before Width: | Height: | Size: 184 KiB |
163
utils/netease.js
163
utils/netease.js
@ -1,163 +0,0 @@
|
|||||||
// 获取cookie
|
|
||||||
import fetch from "node-fetch";
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
const BASE_URL = "http://cloud-music.pl-fe.cn";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取cookie
|
|
||||||
* @param key
|
|
||||||
* @returns {Promise<unknown>}
|
|
||||||
*/
|
|
||||||
async function getCookies(key) {
|
|
||||||
const cookieUrl = `${BASE_URL}/login/qr/check?key=${key}×tamp=${Date.now()}`;
|
|
||||||
return fetch(cookieUrl).then(async resp => {
|
|
||||||
return await resp.json();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取登陆状态
|
|
||||||
* @param cookie
|
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
|
||||||
*/
|
|
||||||
async function getLoginStatus(cookie) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/login/status?timestamp=${Date.now()}`,
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
cookie,
|
|
||||||
},
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取每日推荐
|
|
||||||
* @param cookie
|
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
|
||||||
*/
|
|
||||||
async function getDailyRecommend(cookie) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/recommend/songs?timestamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
data: {
|
|
||||||
cookie,
|
|
||||||
},
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取密匙
|
|
||||||
* @returns {Promise<*>}
|
|
||||||
*/
|
|
||||||
async function getKey() {
|
|
||||||
const keyUrl = `${BASE_URL}/login/qr/key?timestamp=${Date.now()}`;
|
|
||||||
return await fetch(keyUrl).then(async resp => {
|
|
||||||
const respJson = await resp.json();
|
|
||||||
return respJson.data.unikey;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取二维码
|
|
||||||
* @param key
|
|
||||||
* @returns {Promise<*>}
|
|
||||||
*/
|
|
||||||
async function getQrCode(key) {
|
|
||||||
const qrPicUrl = `${BASE_URL}/login/qr/create?key=${key}&qrimg=true×tamp=${Date.now()}`;
|
|
||||||
return await fetch(qrPicUrl).then(async resp => {
|
|
||||||
const respJson = await resp.json();
|
|
||||||
return respJson.data.qrimg;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取听歌排行榜
|
|
||||||
* @param uid
|
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
|
||||||
*/
|
|
||||||
async function getUserRecord(uid) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/user/record?uid=${uid}&type=1×tamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查当前歌曲是否可用
|
|
||||||
* @param id
|
|
||||||
* @returns {Promise<AxiosResponse<any>>} 返回{success:true|false, message: 'ok'}
|
|
||||||
*/
|
|
||||||
async function checkMusic(id) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/check/music?id=${id}×tamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSong(id, cookie) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/song/url/v1?id=${id}&level=standard×tamp=${Date.now()}`,
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
cookie,
|
|
||||||
},
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSongDetail(ids) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/song/detail?ids=${ids}×tamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCloud(cookie) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/user/cloud?timestamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
data: {
|
|
||||||
cookie,
|
|
||||||
},
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCloudMusicDetail(id, cookie) {
|
|
||||||
return axios({
|
|
||||||
url: `${BASE_URL}/user/cloud/detail?id=${id}×tamp=${Date.now()}`,
|
|
||||||
method: "get",
|
|
||||||
data: {
|
|
||||||
cookie,
|
|
||||||
},
|
|
||||||
}).then(resp => {
|
|
||||||
return resp.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
getCookies,
|
|
||||||
getLoginStatus,
|
|
||||||
getDailyRecommend,
|
|
||||||
getKey,
|
|
||||||
getQrCode,
|
|
||||||
getUserRecord,
|
|
||||||
checkMusic,
|
|
||||||
getSong,
|
|
||||||
getSongDetail,
|
|
||||||
getCloud,
|
|
||||||
getCloudMusicDetail
|
|
||||||
};
|
|
@ -2,77 +2,24 @@ import {transMap, tencentTransMap, googleTransMap} from "./constant.js";
|
|||||||
import md5 from "md5";
|
import md5 from "md5";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import HttpProxyAgent from "https-proxy-agent";
|
import HttpProxyAgent from "https-proxy-agent";
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
/**
|
// 定义翻译策略接口
|
||||||
* 翻译插件策略模式
|
class TranslateStrategy {
|
||||||
*/
|
async translate(query, targetLanguage) {
|
||||||
export default class Translate {
|
throw new Error("This method should be implemented by subclasses");
|
||||||
config = {
|
}
|
||||||
/**
|
|
||||||
* 百度翻译appid
|
|
||||||
*/
|
|
||||||
translateAppId: "",
|
|
||||||
/**
|
|
||||||
* 百度翻译密匙
|
|
||||||
*/
|
|
||||||
translateSecret: "",
|
|
||||||
/**
|
|
||||||
* 魔法
|
|
||||||
*/
|
|
||||||
proxy: ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 百度翻译策略
|
||||||
|
class TencentTranslateStrategy extends TranslateStrategy {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
super();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async translate(query, targetLanguage) {
|
||||||
* 百度翻译
|
// 腾讯翻译的具体实现
|
||||||
* @param query 查询句子
|
|
||||||
* @param targetLanguage 目标语言
|
|
||||||
* @returns {Promise<unknown>}
|
|
||||||
*/
|
|
||||||
async baidu(query, targetLanguage) {
|
|
||||||
const url = `http://api.fanyi.baidu.com/api/trans/vip/translate?from=auto&to=${
|
|
||||||
transMap[targetLanguage]
|
|
||||||
}&appid=${this.config.translateAppId}&salt=rconsole&sign=${md5(
|
|
||||||
this.config.translateAppId + query + "rconsole" + this.config.translateSecret,
|
|
||||||
)}&q=${query}`;
|
|
||||||
return fetch(url)
|
|
||||||
.then(resp => resp.json())
|
|
||||||
.then(text => text.trans_result)
|
|
||||||
.then(res => res[0].dst)
|
|
||||||
.catch(err => logger.error(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* google翻译
|
|
||||||
* @param query
|
|
||||||
* @param targetLanguage
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
async google(query, targetLanguage) {
|
|
||||||
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&sl=auto&tl=${googleTransMap[targetLanguage]}&q=${query}`;
|
|
||||||
return fetch(url, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"USER-AGENT": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
|
|
||||||
},
|
|
||||||
agent: new HttpProxyAgent(this.config.proxy || "http://127.0.0.1:7890"),
|
|
||||||
})
|
|
||||||
.then(resp => resp.text())
|
|
||||||
.then(res => JSON.parse(res))
|
|
||||||
.then(res => res[0][0][0])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 腾选交互式翻译
|
|
||||||
* @param query
|
|
||||||
* @param targetLanguage
|
|
||||||
* @returns {Promise<Response>}
|
|
||||||
*/
|
|
||||||
async tencent(query, targetLanguage) {
|
|
||||||
const url = `https://transmart.qq.com/api/imt`
|
const url = `https://transmart.qq.com/api/imt`
|
||||||
const sourceLanguage = await fetch(url, {
|
const sourceLanguage = await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -131,3 +78,82 @@ export default class Translate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 百度翻译策略
|
||||||
|
class BaiduTranslateStrategy extends TranslateStrategy {
|
||||||
|
|
||||||
|
config = {
|
||||||
|
/**
|
||||||
|
* 百度翻译appid
|
||||||
|
*/
|
||||||
|
translateAppId: "",
|
||||||
|
/**
|
||||||
|
* 百度翻译密匙
|
||||||
|
*/
|
||||||
|
translateSecret: "",
|
||||||
|
/**
|
||||||
|
* 魔法
|
||||||
|
*/
|
||||||
|
proxy: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(config) {
|
||||||
|
super();
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
async translate(query, targetLanguage) {
|
||||||
|
// 百度翻译的具体实现
|
||||||
|
const url = `http://api.fanyi.baidu.com/api/trans/vip/translate?from=auto&to=${
|
||||||
|
transMap[targetLanguage]
|
||||||
|
}&appid=${this.config.translateAppId}&salt=rconsole&sign=${md5(
|
||||||
|
this.config.translateAppId + query + "rconsole" + this.config.translateSecret,
|
||||||
|
)}&q=${query}`;
|
||||||
|
return fetch(url)
|
||||||
|
.then(resp => resp.json())
|
||||||
|
.then(text => text.trans_result)
|
||||||
|
.then(res => res[0].dst)
|
||||||
|
.catch(err => logger.error(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoogleTranslateStrategy extends TranslateStrategy {
|
||||||
|
constructor(config) {
|
||||||
|
super();
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
async translate(query, targetLanguage) {
|
||||||
|
// 谷歌翻译的具体实现
|
||||||
|
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&sl=auto&tl=${googleTransMap[targetLanguage]}&q=${query}`;
|
||||||
|
return fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"USER-AGENT": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
|
||||||
|
},
|
||||||
|
agent: new HttpProxyAgent(this.config.proxy || "http://127.0.0.1:7890"),
|
||||||
|
})
|
||||||
|
.then(resp => resp.text())
|
||||||
|
.then(res => JSON.parse(res))
|
||||||
|
.then(res => res[0][0][0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主逻辑
|
||||||
|
export default class Translate {
|
||||||
|
constructor(config) {
|
||||||
|
this.config = config;
|
||||||
|
this.strategy = null;
|
||||||
|
|
||||||
|
if (!_.isEmpty(this.config.translateAppId) && !_.isEmpty(this.config.translateSecret)) {
|
||||||
|
this.strategy = new BaiduTranslateStrategy(this.config);
|
||||||
|
} else {
|
||||||
|
// 根据配置选择其他策略,例如 Tencent 或 Google
|
||||||
|
this.strategy = new TencentTranslateStrategy(this.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async translate(query, targetLanguage) {
|
||||||
|
return this.strategy.translate(query, targetLanguage);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user