🦄 refactor: 修复翻译策略模式,提高扩展性

1. 修复翻译策略模式,提高扩展性
2. 修正README
3. 删除网易云,难维护
This commit is contained in:
zhiyu 2024-01-19 14:32:51 +08:00
parent 8c5092faab
commit c8fe813404
10 changed files with 154 additions and 979 deletions

View File

@ -28,10 +28,6 @@ utils -- 工具类
## 🧏 ‍使用实例
![help](./img/example.webp)
![help](./img/example2.webp)
![help](./img/example3.webp)
![help](./img/example4.webp)
![help](./img/example5.webp)
## 📔 使用说明
@ -143,7 +139,7 @@ sudo apt-get install ffmpeg
| mitsuha | 1杯瑞幸 |
| [Kr] 5s¹ | 1杯瑞幸 |
## 🚀 后记
## 🚀 声明
* 文件借鉴了很多插件,精简个人认为可以精简的内容。
* 素材来源于网络,仅供交流学习使用
* 严禁用于任何商业用途和非法行为

View File

@ -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}`;
}
}

View File

@ -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解析

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

View File

@ -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}&timestamp=${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&timestamp=${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&timestamp=${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}&timestamp=${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&timestamp=${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}&timestamp=${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}&timestamp=${Date.now()}`,
method: "get",
data: {
cookie,
},
}).then(resp => {
return resp.data;
});
}
export {
getCookies,
getLoginStatus,
getDailyRecommend,
getKey,
getQrCode,
getUserRecord,
checkMusic,
getSong,
getSongDetail,
getCloud,
getCloudMusicDetail
};

View File

@ -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);
}
}