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杯瑞幸 |
|
||||
| [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}`;
|
||||
}
|
||||
}
|
351
apps/tools.js
351
apps/tools.js
@ -132,17 +132,7 @@ export class tools extends plugin {
|
||||
proxy: this.myProxy,
|
||||
});
|
||||
// 如果没有百度那就Google
|
||||
let translateResult;
|
||||
if (
|
||||
_.isEmpty(this.toolsConfig.translateAppId) ||
|
||||
_.isEmpty(this.toolsConfig.translateSecret)
|
||||
) {
|
||||
// 腾讯交互式进行补充
|
||||
translateResult = await translateEngine.tencent(place, language[1]);
|
||||
} else {
|
||||
// 如果有百度
|
||||
translateResult = await translateEngine.baidu(place, language[1]);
|
||||
}
|
||||
const translateResult = await translateEngine.translate(place, language[1]);
|
||||
e.reply(translateResult.trim(), true);
|
||||
return true;
|
||||
}
|
||||
@ -462,285 +452,70 @@ export class tools extends plugin {
|
||||
// 小蓝鸟解析
|
||||
// 例子:https://twitter.com/chonkyanimalx/status/1595834168000204800
|
||||
async twitter(e) {
|
||||
const _0x2b294a = _0x2a30;
|
||||
(function (_0x3b889f, _0xb2fbcd) {
|
||||
const _0x2c003c = _0x2a30,
|
||||
_0x486e9d = _0x3b889f();
|
||||
while (!![]) {
|
||||
try {
|
||||
const _0x238c8c =
|
||||
(parseInt(_0x2c003c(0x196, "St*P")) / 0x1) *
|
||||
(-parseInt(_0x2c003c(0x189, "$#GN")) / 0x2) +
|
||||
(-parseInt(_0x2c003c(0x188, "n58F")) / 0x3) *
|
||||
(-parseInt(_0x2c003c(0x1a3, "WOCh")) / 0x4) +
|
||||
(-parseInt(_0x2c003c(0x18d, "i(e%")) / 0x5) *
|
||||
(-parseInt(_0x2c003c(0x19e, "b0CJ")) / 0x6) +
|
||||
parseInt(_0x2c003c(0x18c, "i(e%")) / 0x7 +
|
||||
(-parseInt(_0x2c003c(0x185, "a1WE")) / 0x8) *
|
||||
(-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 => {
|
||||
const _0x466f71 = _0x2b294a,
|
||||
_0x446b97 = _0x19042c[_0x466f71(0x16d, "#E4x")];
|
||||
e[_0x466f71(0x182, "a1WE")](
|
||||
"识别:小蓝鸟学习版," + _0x446b97[_0x466f71(0x19d, "sFkZ")],
|
||||
);
|
||||
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 = [],
|
||||
_0x183d7d = [];
|
||||
await Promise[_0x466f71(0x186, "n58F")](_0xafdb9d)[_0x466f71(0x19b, "Wshq")](
|
||||
_0x4cff3f => {
|
||||
_0x4cff3f["forEach"](_0x22c263 => {
|
||||
const _0x49694d = _0x2a30;
|
||||
_0x183d7d[_0x49694d(0x195, "q#t*")](_0x22c263),
|
||||
_0x3b71e4[_0x49694d(0x1a7, "#E4x")]({
|
||||
message: segment[_0x49694d(0x180, "XTb0")](
|
||||
fs["readFileSync"](_0x22c263),
|
||||
),
|
||||
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 => {
|
||||
const _0x4bccf3 = _0x466f71;
|
||||
fs[_0x4bccf3(0x19f, "WOCh")](_0x35c45b);
|
||||
});
|
||||
// 配置参数及解析
|
||||
const reg = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/;
|
||||
const twitterUrl = reg.exec(e.msg);
|
||||
const id = twitterUrl[1];
|
||||
const httpAgent = new HttpProxyAgent(this.myProxy);
|
||||
const twitterClient = new TwitterApi(this.bearerToken, { httpAgent });
|
||||
|
||||
// Tell typescript it's a readonly app
|
||||
const readOnlyClient = twitterClient.readOnly;
|
||||
|
||||
readOnlyClient.v2
|
||||
.singleTweet(id, {
|
||||
"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"],
|
||||
})
|
||||
["catch"](_0x1a0949 => {
|
||||
const _0x5b9cf4 = _0x2b294a;
|
||||
e[_0x5b9cf4(0x18e, "ZG#8")](_0x5b9cf4(0x198, "PrCv"));
|
||||
.then(async resp => {
|
||||
e.reply(`识别:小蓝鸟学习版,${resp.data.text}`);
|
||||
const downloadPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`;
|
||||
// 创建文件夹(如果没有过这个群)
|
||||
if (!fs.existsSync(downloadPath)) {
|
||||
mkdirsSync(downloadPath);
|
||||
}
|
||||
// 逐个遍历判断
|
||||
let task = [];
|
||||
for (let item of resp.includes.media) {
|
||||
if (item.type === "photo") {
|
||||
// 图片
|
||||
task.push(this.downloadImg(item.url, downloadPath, "", true));
|
||||
} else if (item.type === "video") {
|
||||
// 视频
|
||||
await this.downloadVideo(resp.includes.media[0].variants[0].url, true).then(
|
||||
_ => {
|
||||
e.reply(segment.video(`${downloadPath}/temp.mp4`));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
// 如果没有图片直接返回走
|
||||
if (task.length === 0) {
|
||||
return true;
|
||||
}
|
||||
// 下面是有图片的情况
|
||||
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,
|
||||
});
|
||||
});
|
||||
});
|
||||
await e.reply(await Bot.makeForwardMsg(images));
|
||||
// 清理文件
|
||||
path.forEach(item => {
|
||||
fs.unlinkSync(item);
|
||||
});
|
||||
});
|
||||
return !![];
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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 fetch from "node-fetch";
|
||||
import HttpProxyAgent from "https-proxy-agent";
|
||||
import _ from 'lodash'
|
||||
|
||||
/**
|
||||
* 翻译插件策略模式
|
||||
*/
|
||||
export default class Translate {
|
||||
config = {
|
||||
/**
|
||||
* 百度翻译appid
|
||||
*/
|
||||
translateAppId: "",
|
||||
/**
|
||||
* 百度翻译密匙
|
||||
*/
|
||||
translateSecret: "",
|
||||
/**
|
||||
* 魔法
|
||||
*/
|
||||
proxy: ""
|
||||
// 定义翻译策略接口
|
||||
class TranslateStrategy {
|
||||
async translate(query, targetLanguage) {
|
||||
throw new Error("This method should be implemented by subclasses");
|
||||
}
|
||||
}
|
||||
|
||||
// 百度翻译策略
|
||||
class TencentTranslateStrategy extends TranslateStrategy {
|
||||
constructor(config) {
|
||||
super();
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 百度翻译
|
||||
* @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) {
|
||||
async translate(query, targetLanguage) {
|
||||
// 腾讯翻译的具体实现
|
||||
const url = `https://transmart.qq.com/api/imt`
|
||||
const sourceLanguage = await fetch(url, {
|
||||
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