diff --git a/README.md b/README.md
index b1455b2..68e3de1 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,6 @@ utils -- 工具类
## 🧏 使用实例

-
-
-
-
## 📔 使用说明
@@ -143,7 +139,7 @@ sudo apt-get install ffmpeg
| mitsuha | 1杯瑞幸 |
| [Kr] 5s¹ | 1杯瑞幸 |
-## 🚀 后记
+## 🚀 声明
* 文件借鉴了很多插件,精简个人认为可以精简的内容。
* 素材来源于网络,仅供交流学习使用
* 严禁用于任何商业用途和非法行为
diff --git a/apps/neteasepro.js b/apps/neteasepro.js
deleted file mode 100644
index b7d0a93..0000000
--- a/apps/neteasepro.js
+++ /dev/null
@@ -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(
- '',
- '',
- )
- .replace(/\n/g, "")
- .replace(/
(.+?)<\/title>/g, "___")
- .replace(/___+/, `${forwardMsgName}`);
- return forwardMsg;
- }
-
- // 获取redis的key
- async getRedisKey(user_id) {
- return `Yz:rconsole:netease:${user_id}`;
- }
-}
diff --git a/apps/tools.js b/apps/tools.js
index 42e9481..ecf5855 100644
--- a/apps/tools.js
+++ b/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解析
diff --git a/img/example.webp b/img/example.webp
index 099126d..7ae065a 100644
Binary files a/img/example.webp and b/img/example.webp differ
diff --git a/img/example2.webp b/img/example2.webp
deleted file mode 100644
index d1176db..0000000
Binary files a/img/example2.webp and /dev/null differ
diff --git a/img/example3.webp b/img/example3.webp
deleted file mode 100644
index eea4330..0000000
Binary files a/img/example3.webp and /dev/null differ
diff --git a/img/example4.webp b/img/example4.webp
deleted file mode 100644
index d437ba3..0000000
Binary files a/img/example4.webp and /dev/null differ
diff --git a/img/example5.webp b/img/example5.webp
deleted file mode 100644
index 90fbb65..0000000
Binary files a/img/example5.webp and /dev/null differ
diff --git a/utils/netease.js b/utils/netease.js
deleted file mode 100644
index 567ef7b..0000000
--- a/utils/netease.js
+++ /dev/null
@@ -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}
- */
-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>}
- */
-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>}
- */
-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>}
- */
-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>} 返回{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
-};
diff --git a/utils/trans-strategy.js b/utils/trans-strategy.js
index 2361768..e3b9f5c 100644
--- a/utils/trans-strategy.js
+++ b/utils/trans-strategy.js
@@ -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}
- */
- 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}
- */
- 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}
- */
- 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);
+ }
+}
\ No newline at end of file