🌈 美化代码,不做任何修改

This commit is contained in:
zhiyu1998 2023-02-14 14:41:02 +08:00
parent 6f28c43880
commit ea81c265a3
7 changed files with 774 additions and 672 deletions

4
.gitignore vendored
View File

@ -15,4 +15,8 @@ node_modules/
ehthumbs.db
Thumbs.db
.idea
.history
package.json
package-lock.json
yarn.lock
.prettierrc.json

View File

@ -1,51 +1,51 @@
import common from '../../../lib/common/common.js'
import fetch from 'node-fetch'
import schedule from 'node-schedule'
import { Group, segment } from 'oicq'
import common from "../../../lib/common/common.js";
import fetch from "node-fetch";
import schedule from "node-schedule";
import { Group, segment } from "oicq";
// 指定定时发送的群号
const groupList = [ '169721415' ]
const groupList = ["169721415"];
// 是否开启定时推送,默认为 true
let isAutoPush = true
let isAutoPush = true;
function autoTask(func, time) {
if (isAutoPush) {
schedule.scheduleJob(time, () => {
for (let i = 0; i < groupList.length; i++) {
let group = Bot.pickGroup(groupList[i])
func(group)
common.sleep(1000)
let group = Bot.pickGroup(groupList[i]);
func(group);
common.sleep(1000);
}
})
});
}
}
// 定时任务合集
autoTask(pushDailyWorld, '0 30 8 * * ?')
autoTask(pushTouchFish, '0 31 8 * * ?')
autoTask(pushDailyWorld, "0 30 8 * * ?");
autoTask(pushTouchFish, "0 31 8 * * ?");
export class daily extends plugin {
constructor(e) {
super({
name: 'rconsole插件帮助',
dsc: 'rconsole插件帮助插件帮助',
event: 'message',
name: "rconsole插件帮助",
dsc: "rconsole插件帮助插件帮助",
event: "message",
priority: 500,
rule: [
{
reg: '^#每天60秒$',
fnc: 'dailyWorld'
reg: "^#每天60秒$",
fnc: "dailyWorld",
},
{
reg: '^#摸鱼人日历$',
fnc: 'touchFish'
reg: "^#摸鱼人日历$",
fnc: "touchFish",
},
{
reg: '^#开关每日推送$',
fnc: 'shutdown'
reg: "^#开关每日推送$",
fnc: "shutdown",
},
]
})
],
});
}
async dailyWorld(e) {
@ -60,8 +60,8 @@ export class daily extends plugin {
}
async shutdown(e) {
isAutoPush = !isAutoPush
e.reply(`【当前推送状态】:${ isAutoPush ? '开启' : '关闭' }`)
isAutoPush = !isAutoPush;
e.reply(`【当前推送状态】:${isAutoPush ? "开启" : "关闭"}`);
}
}
@ -71,39 +71,41 @@ export class daily extends plugin {
*/
async function pushDailyWorld(e) {
// 每天60秒读懂世界接口地址
const url = await fetch('https://api.vvhan.com/api/60s?type=json')
.catch(err => logger.error(err))
const imgUrl = await url.json()
const res = await imgUrl.imgUrl
const url = await fetch("https://api.vvhan.com/api/60s?type=json").catch(err =>
logger.error(err)
);
const imgUrl = await url.json();
const res = await imgUrl.imgUrl;
// 判断接口是否请求成功
if (!res) {
e.reply('[60秒读懂世界] 接口请求失败')
e.reply("[60秒读懂世界] 接口请求失败");
}
// 回复消息
if (e instanceof Group) {
e.sendMsg(segment.image(res))
e.sendMsg(segment.image(res));
} else {
e.reply(segment.image(res))
e.reply(segment.image(res));
}
}
async function pushTouchFish(e) {
const url = await fetch('https://api.vvhan.com/api/moyu?type=json')
.catch(err => logger.error(err))
const imgUrl = await url.json()
const res = await imgUrl.url
const url = await fetch("https://api.vvhan.com/api/moyu?type=json").catch(err =>
logger.error(err)
);
const imgUrl = await url.json();
const res = await imgUrl.url;
// 判断接口是否请求成功
if (!res) {
e.reply('[摸鱼人日历] 接口请求失败')
e.reply("[摸鱼人日历] 接口请求失败");
}
// 回复消息
if (e instanceof Group) {
e.sendMsg(segment.image(res))
e.sendMsg(segment.image(res));
} else {
e.reply(segment.image(res))
e.reply(segment.image(res));
}
}

View File

@ -1,42 +1,42 @@
import Help from '../model/help.js'
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import md5 from 'md5'
import Help from "../model/help.js";
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
import md5 from "md5";
let helpData = {
md5: '',
img: ''
}
md5: "",
img: "",
};
export class help extends plugin {
constructor(e) {
super({
name: 'rconsole插件帮助',
dsc: 'rconsole插件帮助插件帮助',
event: 'message',
name: "rconsole插件帮助",
dsc: "rconsole插件帮助插件帮助",
event: "message",
priority: 500,
rule: [
{
reg: '^#*(R|r)(插件)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$',
fnc: 'help'
}
]
})
reg: "^#*(R|r)(插件)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$",
fnc: "help",
},
],
});
}
async help() {
let data = await Help.get(this.e)
if (!data) return
let img = await this.cache(data)
await this.reply(img)
let data = await Help.get(this.e);
if (!data) return;
let img = await this.cache(data);
await this.reply(img);
}
async cache(data) {
let tmp = md5(JSON.stringify(data))
if (helpData.md5 == tmp) return helpData.img
let tmp = md5(JSON.stringify(data));
if (helpData.md5 == tmp) return helpData.img;
helpData.img = await puppeteer.screenshot('help', data)
helpData.md5 = tmp
helpData.img = await puppeteer.screenshot("help", data);
helpData.md5 = tmp;
return helpData.img
return helpData.img;
}
}

View File

@ -1,11 +1,11 @@
// 主库
import { segment } from 'oicq'
import common from '../../../lib/common/common.js'
import fetch from 'node-fetch'
import { segment } from "oicq";
import common from "../../../lib/common/common.js";
import fetch from "node-fetch";
// 配置文件
import config from '../model/index.js'
import config from "../model/index.js";
// 其他库
import _ from 'lodash'
import _ from "lodash";
// import mongodb from 'mongodb'
// Mongodb初始化
@ -26,42 +26,47 @@ import _ from 'lodash'
//
// const mongo = initMongo()
// 60s后撤回
const recallTime = 109
const recallTime = 109;
export class mystery extends plugin {
constructor() {
super({
name: '神秘区域',
dsc: '神秘指令',
event: 'message.group',
name: "神秘区域",
dsc: "神秘指令",
event: "message.group",
priority: 500,
rule: [
{
reg: '^#(雀食|确实)$', fnc: 'mystery'
reg: "^#(雀食|确实)$",
fnc: "mystery",
},
{
reg: '^#*来份涩图 (.*)$', fnc: 'setu'
reg: "^#*来份涩图 (.*)$",
fnc: "setu",
},
{
reg: '^#(累了)$', fnc: 'cospro'
reg: "^#(累了)$",
fnc: "cospro",
},
{
reg: '^#(啊?|啊?)$', fnc: 'aaa'
}
reg: "^#(啊?|啊?)$",
fnc: "aaa",
},
// {
// reg: '^#我靠', fnc: 'tuiimg'
// }
]
})
this.mysteryConfig = config.getConfig('mystery')
],
});
this.mysteryConfig = config.getConfig("mystery");
}
/** 接受到消息都会先执行一次 */
async accept() {
if (this.e.isGroup) {
let group = this.e.group;
if (!group.is_owner && (group.is_admin && group.mute_left > 0)) return;
if (!(group.is_owner || group.is_admin) && (group.all_muted || group.mute_left > 0)) return;
if (!group.is_owner && group.is_admin && group.mute_left > 0) return;
if (!(group.is_owner || group.is_admin) && (group.all_muted || group.mute_left > 0))
return;
}
let old_reply = this.e.reply;
@ -75,8 +80,11 @@ export class mystery extends plugin {
let isxml = false;
for (let msg of msgs) {
if (msg && msg?.type == 'xml' && msg?.data) {
msg.data = msg.data.replace(/^<\?xml.*version=.*?>/g, '<?xml version="1.0" encoding="utf-8" ?>');
if (msg && msg?.type == "xml" && msg?.data) {
msg.data = msg.data.replace(
/^<\?xml.*version=.*?>/g,
'<?xml version="1.0" encoding="utf-8" ?>'
);
isxml = true;
}
}
@ -84,172 +92,183 @@ export class mystery extends plugin {
if (isxml) {
result = await old_reply(msgs, quote, data);
} else {
let MsgList = [{
let MsgList = [
{
message: msgs,
nickname: Bot.nickname,
user_id: Bot.uin
}];
user_id: Bot.uin,
},
];
let forwardMsg = await Bot.makeForwardMsg(MsgList);
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(
'<?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">请点击查看内容</title>');
msgs = forwardMsg;
result = await old_reply(msgs, quote, data);
}
if (!result || !result.message_id) {
logger.error('风控消息处理失败请登录手机QQ查看是否可手动解除风控');
logger.error("风控消息处理失败请登录手机QQ查看是否可手动解除风控");
}
}
return result;
}
};
}
async mystery(e) {
// 最大页数
const maxPage = this.mysteryConfig.mystery.maxPage
const maxPigObj = this.mysteryConfig.mystery.maxPigObj
const maxPage = this.mysteryConfig.mystery.maxPage;
const maxPigObj = this.mysteryConfig.mystery.maxPigObj;
// 限制最大图片数量
const imageCountLimit = this.mysteryConfig.mystery.imageCountLimit
const imageCountLimit = this.mysteryConfig.mystery.imageCountLimit;
// 随机算法
const page = _.random(1, maxPage)
const randomIndex = _.random(0, maxPigObj - 1)
const page = _.random(1, maxPage);
const randomIndex = _.random(0, maxPigObj - 1);
// 回复
this.reply('确实是吧, 正在探索...')
this.reply("确实是吧, 正在探索...");
// 请求
let url = `https://www.cos6.net/wp-json/wp/v2/posts?page=${ page }`
let images = []
let url = `https://www.cos6.net/wp-json/wp/v2/posts?page=${page}`;
let images = [];
await fetch(url)
.then((resp) => {
return resp.json()
.then(resp => {
return resp.json();
})
.then((json) => {
.then(json => {
const template = {
nickname: this.e.sender.card || this.e.user_id,
user_id: this.e.user_id
}
user_id: this.e.user_id,
};
const content = json[randomIndex].content
images = this.getCos6Img(content.rendered)
const content = json[randomIndex].content;
images = this.getCos6Img(content.rendered);
// 洗牌
images = _.shuffle(images)
images = _.shuffle(images);
// 限制长度
if (images.length > imageCountLimit) {
images = images.slice(1, imageCountLimit + 1)
images = images.slice(1, imageCountLimit + 1);
}
// 循环队列
for (let i = 0; i < images.length; i++) {
images[i] = {
message: segment.image(images[i]),
...template
}
...template,
};
}
})
.catch((err) => {
this.e.reply('探索失败,你再我去一次吧')
logger.error(err)
return false
})
return !!(await this.reply(await Bot.makeForwardMsg(images)))
.catch(err => {
this.e.reply("探索失败,你再我去一次吧");
logger.error(err);
return false;
});
return !!(await this.reply(await Bot.makeForwardMsg(images)));
}
async cospro(e) {
let req = [ ...await fetch('https://imgapi.cn/cos2.php?return=jsonpro').then((resp) => resp.json()).then((json) => json.imgurls), ...await fetch('https://imgapi.cn/cos.php?return=jsonpro').then((resp) => resp.json()).then((json) => json.imgurls) ]
e.reply('哪天克火掉一定是在这个群里面...')
let images = []
let req = [
...(await fetch("https://imgapi.cn/cos2.php?return=jsonpro")
.then(resp => resp.json())
.then(json => json.imgurls)),
...(await fetch("https://imgapi.cn/cos.php?return=jsonpro")
.then(resp => resp.json())
.then(json => json.imgurls)),
];
e.reply("哪天克火掉一定是在这个群里面...");
let images = [];
req.forEach(item => {
images.push({
message: segment.image(encodeURI(item)),
nickname: this.e.sender.card || this.e.user_id,
user_id: this.e.user_id
})
})
return !!(await this.reply(await Bot.makeForwardMsg(images)))
user_id: this.e.user_id,
});
});
return !!(await this.reply(await Bot.makeForwardMsg(images)));
}
async aaa(e) {
// https://yingtall.com/wp-json/wp/v2/posts?page=64
// 最大页数
const maxPage = this.mysteryConfig.aaa.maxPage
const maxPigObj = this.mysteryConfig.aaa.maxPigObj
const maxPage = this.mysteryConfig.aaa.maxPage;
const maxPigObj = this.mysteryConfig.aaa.maxPigObj;
// 限制最大图片数量
const imageCountLimit = this.mysteryConfig.aaa.imageCountLimit
const imageCountLimit = this.mysteryConfig.aaa.imageCountLimit;
// 随机算法
const page = _.random(1, maxPage)
const randomIndex = _.random(0, maxPigObj - 1)
const page = _.random(1, maxPage);
const randomIndex = _.random(0, maxPigObj - 1);
// 回复
this.reply('真变态啊...')
this.reply("真变态啊...");
// 请求
let images = []
let imgData = []
let url = `https://yingtall.com/wp-json/wp/v2/posts?page=${ page }`
let images = [];
let imgData = [];
let url = `https://yingtall.com/wp-json/wp/v2/posts?page=${page}`;
await fetch(url)
.then((resp) => {
return resp.json()
.then(resp => {
return resp.json();
})
.then((json) => {
.then(json => {
if (!json.length) {
e.reply('探索失败,你再我去一次吧')
return false
e.reply("探索失败,你再我去一次吧");
return false;
}
const content = json[randomIndex].content
images = this.getImages2(content.rendered)
const content = json[randomIndex].content;
images = this.getImages2(content.rendered);
// 如果图片为空直接返回
if (images.length === 0) {
e.reply('探索失败,你再我去一次吧')
return false
e.reply("探索失败,你再我去一次吧");
return false;
}
// 洗牌
images = _.shuffle(images)
images = _.shuffle(images);
// 限制长度
if (images.length > imageCountLimit) {
images = images.slice(1, imageCountLimit + 1)
images = images.slice(1, imageCountLimit + 1);
}
// 循环队列
images.forEach((item) => {
images.forEach(item => {
imgData.push({
message: segment.image(item),
nickname: e.sender.card || e.user_id,
user_id: e.user_id
user_id: e.user_id,
});
});
})
})
})
.catch((err) => logger.error(err))
return !!(await this.reply(await Bot.makeForwardMsg(imgData)))
.catch(err => logger.error(err));
return !!(await this.reply(await Bot.makeForwardMsg(imgData)));
}
async setu(e) {
const keyword = e.msg.split(' ')[1]
const numb = this.mysteryConfig.setu.count
await e.reply('正在给你找图片啦~', true, { recallMsg: 7 });
const keyword = e.msg.split(" ")[1];
const numb = this.mysteryConfig.setu.count;
await e.reply("正在给你找图片啦~", true, { recallMsg: 7 });
let url = `https://api.lolicon.app/setu/v2?r18=${keyword}&num=${numb}`; //←此处修改图片类型0为非181为182为18非18混合
const response = await fetch(url);
const imgJson = await response.json();
const images = []
const images = [];
for (let image of imgJson.data) {
images.push({
message: segment.image(image.urls.original),
nickname: e.sender.card || e.user_id,
user_id: e.user_id
})
user_id: e.user_id,
});
}
const res = await this.reply(
await Bot.makeForwardMsg(images),
false,
{ recallMsg: 60 })
const res = await this.reply(await Bot.makeForwardMsg(images), false, { recallMsg: 60 });
if (!res) {
return e.reply('好、好涩(//// ^ ////)……不、不行啦……被、被吞啦o(≧口≦)o',true,{recallMsg:60});
return e.reply("好、好涩(//// ^ ////)……不、不行啦……被、被吞啦o(≧口≦)o", true, {
recallMsg: 60,
});
}
return true
return true;
}
// async tuiimg (e) {
@ -275,23 +294,23 @@ export class mystery extends plugin {
// 正则:获取图片
getCos6Img(string) {
const imgRex = /\/([\w].*?).(jpg|JPG|png|PNG|gif|GIF|jpeg|JPEG|svg)/g
const images = []
let img
const imgRex = /\/([\w].*?).(jpg|JPG|png|PNG|gif|GIF|jpeg|JPEG|svg)/g;
const images = [];
let img;
while ((img = imgRex.exec(string))) {
images.push(`https://www.cos6.net/${ img[1] }.jpg`)
images.push(`https://www.cos6.net/${img[1]}.jpg`);
}
return images
return images;
}
// 正则:获取图片
getImages2(string) {
const imgRex = /<img.*?src="(.*?)"[^>]+>/g
const images = []
let img
const imgRex = /<img.*?src="(.*?)"[^>]+>/g;
const images = [];
let img;
while ((img = imgRex.exec(string))) {
images.push(img[1])
images.push(img[1]);
}
return images
return images;
}
}

View File

@ -1,88 +1,93 @@
// 主库
import { segment } from 'oicq'
import fetch from 'node-fetch'
import { segment } from "oicq";
import fetch from "node-fetch";
// 配置文件
import config from '../model/index.js'
import config from "../model/index.js";
// 爬虫库
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import _ from 'lodash'
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
import _ from "lodash";
export class query extends plugin {
constructor() {
super({
name: '查询类',
dsc: '查询相关指令',
event: 'message.group',
name: "查询类",
dsc: "查询相关指令",
event: "message.group",
priority: 500,
rule: [
{
reg: '^#*医药查询 (.*)$',
fnc: 'doctor'
reg: "^#*医药查询 (.*)$",
fnc: "doctor",
},
{
reg: '^#*评分 (.*)',
fnc: 'videoScore'
reg: "^#*评分 (.*)",
fnc: "videoScore",
},
{
reg: '^#(cat)$',
fnc: 'cat'
reg: "^#(cat)$",
fnc: "cat",
},
{
reg: '^#电脑软件推荐$', /** 执行方法 */
fnc: 'computerRecommended'
reg: "^#电脑软件推荐$" /** 执行方法 */,
fnc: "computerRecommended",
},
{
reg: '^#安卓软件推荐$', /** 执行方法 */
fnc: 'androidRecommended'
reg: "^#安卓软件推荐$" /** 执行方法 */,
fnc: "androidRecommended",
},
{
reg: '^#(热搜)(.*)$',
fnc: 'hotSearch'
reg: "^#(热搜)(.*)$",
fnc: "hotSearch",
},
{
reg: '#买家秀',
fnc: 'buyerShow'
}
]
})
this.catConfig = config.getConfig('query')
reg: "#买家秀",
fnc: "buyerShow",
},
],
});
this.catConfig = config.getConfig("query");
}
async doctor(e) {
let keyword = e.msg.split(' ')[1]
const url = `https://api2.dayi.org.cn/api/search2?keyword=${ keyword }&pageNo=1&pageSize=10`
let keyword = e.msg.split(" ")[1];
const url = `https://api2.dayi.org.cn/api/search2?keyword=${keyword}&pageNo=1&pageSize=10`;
let res = await fetch(url)
.then((resp) => resp.json())
.then((resp) => resp.list)
let msg = []
.then(resp => resp.json())
.then(resp => resp.list);
let msg = [];
for (const element of res) {
const title = this.removeTag(element.title)
const title = this.removeTag(element.title);
const template = `
${title}\n
标签${element.secondTitle}\n
介绍${element.introduction}
`
`;
// 如果完全匹配,直接响应页面
if (title === keyword) {
const browser = await puppeteer.browserInit()
const page = await browser.newPage()
await page.goto(`https://www.dayi.org.cn/drug/${ element.id }`)
const browser = await puppeteer.browserInit();
const page = await browser.newPage();
await page.goto(`https://www.dayi.org.cn/drug/${element.id}`);
let buff = await page.screenshot({
fullPage: true, type: 'jpeg', omitBackground: false, quality: 90
})
browser.close()
await e.reply(segment.image(buff))
fullPage: true,
type: "jpeg",
omitBackground: false,
quality: 90,
});
browser.close();
await e.reply(segment.image(buff));
}
msg.push({
message: { type: 'text', text: `${ template }` }, nickname: Bot.nickname, user_id: Bot.user_id
})
message: { type: "text", text: `${template}` },
nickname: Bot.nickname,
user_id: Bot.user_id,
});
}
/** 最后回复消息 */
return !!this.reply(await Bot.makeForwardMsg(msg))
return !!this.reply(await Bot.makeForwardMsg(msg));
}
async videoScore(e) {
let keyword = e.msg.split(' ')[1]
let keyword = e.msg.split(" ")[1];
const api = `https://movie.douban.com/j/subject_suggest?q=${encodeURI(keyword)}`;
let movieId = 30433417;
@ -91,8 +96,10 @@ export class query extends plugin {
"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",
"Content-Type": "application/json",
}
}).then(resp => resp.json()).then(resp => {
},
})
.then(resp => resp.json())
.then(resp => {
if (resp.length === 0 || resp === "") {
e.reply("没找到!");
return true;
@ -104,140 +111,158 @@ export class query extends plugin {
"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",
"Content-Type": "application/json",
}
}).then(resp => resp.json()).then(resp => {
},
})
.then(resp => resp.json())
.then(resp => {
if (resp.length === 0 || resp === "") {
e.reply("没找到!");
return true;
}
e.reply(`识别:${resp.data[0].name}\n烂番茄评分:${resp.imdbRating}\n豆瓣评分:${resp.doubanRating}\n评分:${resp.imdbRating}`);
})
})
e.reply(
`识别:${resp.data[0].name}\n烂番茄评分:${resp.imdbRating}\n豆瓣评分:${resp.doubanRating}\n评分:${resp.imdbRating}`
);
});
});
return true;
}
async cat(e) {
const numb = this.catConfig.count
let images = []
let reqRes = [ ...await fetch(`https://shibe.online/api/cats?count=${ numb }`).then(data => data.json()), ...await fetch(`https://api.thecatapi.com/v1/images/search?limit=${ numb }`).then(data => data.json()).then(json => json.map(item => item.url)) ]
e.reply('涩图也不看了,就看猫是吧, 探索中...')
const numb = this.catConfig.count;
let images = [];
let reqRes = [
...(await fetch(`https://shibe.online/api/cats?count=${numb}`).then(data =>
data.json()
)),
...(await fetch(`https://api.thecatapi.com/v1/images/search?limit=${numb}`)
.then(data => data.json())
.then(json => json.map(item => item.url))),
];
e.reply("涩图也不看了,就看猫是吧, 探索中...");
reqRes.forEach(item => {
images.push({
message: segment.image(item), nickname: this.e.sender.card || this.e.user_id, user_id: this.e.user_id
})
})
return !!(await this.reply(await Bot.makeForwardMsg(images)))
message: segment.image(item),
nickname: this.e.sender.card || this.e.user_id,
user_id: this.e.user_id,
});
});
return !!(await this.reply(await Bot.makeForwardMsg(images)));
}
async computerRecommended(e) {
let url = 'https://www.ghxi.com/ghapi?type=query&n=pc'
let url = "https://www.ghxi.com/ghapi?type=query&n=pc";
/** 调用接口获取数据 */
let res = await fetch(url).catch((err) => logger.error(err))
let res = await fetch(url).catch(err => logger.error(err));
/** 接口结果json字符串转对象 */
res = await res.json()
let msg = []
res.data.list.forEach((element) => {
const template = `推荐软件:${ element.title }\n地址:${ element.url }\n`
res = await res.json();
let msg = [];
res.data.list.forEach(element => {
const template = `推荐软件:${element.title}\n地址:${element.url}\n`;
msg.push({
message: { type: 'text', text: `${ template }` }, nickname: Bot.nickname, user_id: Bot.user_id
})
})
message: { type: "text", text: `${template}` },
nickname: Bot.nickname,
user_id: Bot.user_id,
});
});
/** 最后回复消息 */
return !!this.reply(await Bot.makeForwardMsg(msg))
return !!this.reply(await Bot.makeForwardMsg(msg));
}
async androidRecommended(e) {
let url = 'https://www.ghxi.com/ghapi?type=query&n=and'
let res = await fetch(url).catch((err) => logger.error(err))
res = await res.json()
let msg = []
res.data.list.forEach((element) => {
const template = `推荐软件:${ element.title }\n地址:${ element.url }\n`
let url = "https://www.ghxi.com/ghapi?type=query&n=and";
let res = await fetch(url).catch(err => logger.error(err));
res = await res.json();
let msg = [];
res.data.list.forEach(element => {
const template = `推荐软件:${element.title}\n地址:${element.url}\n`;
msg.push({
message: { type: 'text', text: `${ template }` }, nickname: Bot.nickname, user_id: Bot.user_id
})
})
return !!this.reply(await Bot.makeForwardMsg(msg))
message: { type: "text", text: `${template}` },
nickname: Bot.nickname,
user_id: Bot.user_id,
});
});
return !!this.reply(await Bot.makeForwardMsg(msg));
}
async hotSearch(e) {
let keyword = e.msg.replace(/#|热搜/g, '').trim()
console.log(keyword)
let keyword = e.msg.replace(/#|热搜/g, "").trim();
console.log(keyword);
// 虎扑/知乎/36氪/百度/哔哩哔哩/贴吧/微博/抖音/豆瓣/少数派/IT资讯/微信
let url = 'https://api.vvhan.com/api/hotlist?type='
let url = "https://api.vvhan.com/api/hotlist?type=";
switch (keyword) {
case '虎扑':
url += 'huPu'
break
case '知乎':
url += 'zhihuHot'
break
case '36氪':
url += '36Ke'
break
case '百度':
url += 'baiduRD'
break
case '哔哩哔哩':
url += 'bili'
break
case '贴吧':
url += 'baiduRY'
break
case '微博':
url += 'wbHot'
break
case '抖音':
url += 'douyinHot'
break
case '豆瓣':
url += 'douban'
break
case '少数派':
url += 'ssPai'
break
case 'IT资讯':
url += 'itInfo'
break
case '微信':
url += 'wxHot'
break
case "虎扑":
url += "huPu";
break;
case "知乎":
url += "zhihuHot";
break;
case "36氪":
url += "36Ke";
break;
case "百度":
url += "baiduRD";
break;
case "哔哩哔哩":
url += "bili";
break;
case "贴吧":
url += "baiduRY";
break;
case "微博":
url += "wbHot";
break;
case "抖音":
url += "douyinHot";
break;
case "豆瓣":
url += "douban";
break;
case "少数派":
url += "ssPai";
break;
case "IT资讯":
url += "itInfo";
break;
case "微信":
url += "wxHot";
break;
default:
url += 'history'
break
url += "history";
break;
}
let sendTemplate = {
nickname: this.e.sender.card || this.e.user_id, user_id: this.e.user_id
}
let msg = []
nickname: this.e.sender.card || this.e.user_id,
user_id: this.e.user_id,
};
let msg = [];
await fetch(url, {
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",
"Content-Type": "application/json",
}
},
})
.then((resp) => resp.json())
.then((resp) => {
.then(resp => resp.json())
.then(resp => {
for (let element of resp.data) {
if (_.isUndefined(element)) {
continue
continue;
}
const template = `
标题${ _.isNull(element.title) ? '暂无' : element.title }\n
简介${ _.isNull(element.desc) ? '暂无' : element.desc }\n
热度${ _.isNull(element.hot) ? '暂无' : element.hot }\n
访问详情${ _.isNull(element.url) ? '暂无' : element.url }\n
标题${_.isNull(element.title) ? "暂无" : element.title}\n
简介${_.isNull(element.desc) ? "暂无" : element.desc}\n
热度${_.isNull(element.hot) ? "暂无" : element.hot}\n
访问详情${_.isNull(element.url) ? "暂无" : element.url}\n
`;
msg.push({
message: { type: 'text', text: `${ template }` },
...sendTemplate
})
message: { type: "text", text: `${template}` },
...sendTemplate,
});
}
})
.catch((err) => logger.error(err))
return !!this.reply(await Bot.makeForwardMsg(msg))
.catch(err => logger.error(err));
return !!this.reply(await Bot.makeForwardMsg(msg));
}
async buyerShow(e) {
@ -247,26 +272,31 @@ export class query extends plugin {
// const randomIndex = Math.floor(Math.random() * urls.length);
// const randomElement = urls.splice(randomIndex, 1)[0];
const p1 = new Promise((resolve, reject) => {
fetch("https://api.vvhan.com/api/tao").then(resp => {
return resolve(resp.url)
}).catch(err => reject(err))
fetch("https://api.vvhan.com/api/tao")
.then(resp => {
return resolve(resp.url);
})
.catch(err => reject(err));
});
const p2 = new Promise((resolve, reject) => {
fetch("https://api.uomg.com/api/rand.img3?format=json").then(resp => resp.json()).then(resp => {
return resolve(resp.imgurl)
}).catch(err => reject(err))
fetch("https://api.uomg.com/api/rand.img3?format=json")
.then(resp => resp.json())
.then(resp => {
return resolve(resp.imgurl);
})
.catch(err => reject(err));
});
Promise.all([p1, p2]).then(res => {
res.forEach(item => {
e.reply(segment.image(item))
})
})
e.reply(segment.image(item));
});
});
return true;
}
// 删除标签
removeTag(title) {
const titleRex = /<[^>]+>/g
return title.replace(titleRex, '')
const titleRex = /<[^>]+>/g;
return title.replace(titleRex, "");
}
}

View File

@ -5,16 +5,16 @@ import { segment } from "oicq";
// 其他库
import md5 from "md5";
import axios from "axios";
import _ from 'lodash'
import tunnel from 'tunnel'
import { TwitterApi } from 'twitter-api-v2'
import HttpProxyAgent from 'https-proxy-agent'
import { mkdirsSync } from '../utils/file.js'
import { downloadBFile, getDownloadUrl, mergeFileToMp4 } from '../utils/bilibili.js'
import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from '../utils/acfun.js'
import _ from "lodash";
import tunnel from "tunnel";
import { TwitterApi } from "twitter-api-v2";
import HttpProxyAgent from "https-proxy-agent";
import { mkdirsSync } from "../utils/file.js";
import { downloadBFile, getDownloadUrl, mergeFileToMp4 } from "../utils/bilibili.js";
import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../utils/acfun.js";
// import { get, remove, add } from "../utils/redisu.js";
const transMap = { "中": "zh", "日": "jp", "文": "wyw", "英": "en" }
const transMap = { : "zh", : "jp", : "wyw", : "en" };
export class tools extends plugin {
constructor() {
@ -49,17 +49,17 @@ export class tools extends plugin {
fnc: "twitter",
},
{
reg: "https:\/\/(m.)?v.qq.com\/(.*)",
fnc: "tx"
reg: "https://(m.)?v.qq.com/(.*)",
fnc: "tx",
},
{
reg: "(.*)(acfun.cn)",
fnc: "acfun"
fnc: "acfun",
},
{
reg: "(.*)(xhslink.com|xiaohongshu.com)",
fnc: "redbook"
}
fnc: "redbook",
},
],
});
// http://api.tuwei.space/girl
@ -69,10 +69,9 @@ export class tools extends plugin {
this.redisKey = `Yz:tools:cache:${this.group_id}`;
// 代理接口
// TODO 填写服务器的内网ID和clash的端口
this.proxyAddr = '10.0.8.10';
this.proxyPort = '7890'
this.proxyAddr = "10.0.8.10";
this.proxyPort = "7890";
this.myProxy = `http://${this.proxyAddr}:${this.proxyPort}`;
}
// 翻译插件
@ -81,18 +80,22 @@ export class tools extends plugin {
const msg = e.msg.trim();
const language = languageReg.exec(msg);
if (!transMap.hasOwnProperty(language[1])) {
e.reply("输入格式有误!例子:翻中 China's policy has been consistent, but Japan chooses a path of mistrust, decoupling and military expansion")
e.reply(
"输入格式有误!例子:翻中 China's policy has been consistent, but Japan chooses a path of mistrust, decoupling and military expansion"
);
return;
}
const place = msg.replace(language[0], "").trim();
// let url = /[\u4E00-\u9FFF]+/g.test(place)
// let url = `http://api.fanyi.baidu.com/api/trans/vip/translate?from=auto&to=${ transMap[language[1]] }&appid=APP ID&salt=自定义&sign=${ md5("APP ID" + place + "自定义" + "密钥") }&q=${ place }`;
let url = `http://api.fanyi.baidu.com/api/trans/vip/translate?from=auto&to=${ transMap[language[1]] }&appid=&salt=&sign=${ md5("" + place + "" + "") }&q=${ place }`;
let url = `http://api.fanyi.baidu.com/api/trans/vip/translate?from=auto&to=${
transMap[language[1]]
}&appid=&salt=&sign=${md5("" + place + "" + "")}&q=${place}`;
await fetch(url)
.then((resp) => resp.json())
.then((text) => text.trans_result)
.then((res) => this.reply(`${ res[0].dst }`, true))
.catch((err) => logger.error(err));
.then(resp => resp.json())
.then(text => text.trans_result)
.then(res => this.reply(`${res[0].dst}`, true))
.catch(err => logger.error(err));
return true;
}
@ -101,18 +104,22 @@ export class tools extends plugin {
const urlRex = /(http:|https:)\/\/v.douyin.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
const douUrl = urlRex.exec(e.msg.trim())[0];
await this.douyinRequest(douUrl).then(async (res) => {
await this.douyinRequest(douUrl).then(async res => {
const douRex = /.*video\/(\d+)\/(.*?)/g;
const douId = douRex.exec(res)[1];
// const url = `https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${ douId }`;
const url = `https://www.iesdouyin.com/aweme/v1/web/aweme/detail/?aweme_id=${ douId }&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333`
const url = `https://www.iesdouyin.com/aweme/v1/web/aweme/detail/?aweme_id=${douId}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333`;
const resp = await fetch(url);
const json = await resp.json();
const item = json.aweme_detail;
e.reply(`识别:抖音, ${item.desc}`);
const url_2 = item.video.play_addr.url_list[0];
this.downloadVideo(url_2).then(video => {
e.reply(segment.video(`${this.defaultPath}${this.e.group_id || this.e.user_id}/temp.mp4`));
e.reply(
segment.video(
`${this.defaultPath}${this.e.group_id || this.e.user_id}/temp.mp4`
)
);
});
});
return true;
@ -122,62 +129,72 @@ export class tools extends plugin {
async tiktok(e) {
const urlRex = /(http:|https:)\/\/www.tiktok.com\/[A-Za-z\d._?%&+\-=\/#@]*/g;
const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
let url = e.msg.trim()
let url = e.msg.trim();
// 短号处理
if (url.includes('vt.tiktok')) {
const temp_url = urlShortRex.exec(url)[0]
if (url.includes("vt.tiktok")) {
const temp_url = urlShortRex.exec(url)[0];
await fetch(temp_url, {
redirect: "follow",
follow: 10,
timeout: 10000,
agent: new HttpProxyAgent(this.myProxy)
}).then((resp) => {
url = resp.url
})
agent: new HttpProxyAgent(this.myProxy),
}).then(resp => {
url = resp.url;
});
} else {
url = urlRex.exec(url)[0]
url = urlRex.exec(url)[0];
}
const idVideo = await this.getIdVideo(url)
const idVideo = await this.getIdVideo(url);
// API链接
const API_URL = `https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/?aweme_id=${idVideo}&version_code=262&app_name=musical_ly&channel=App&device_id=null&os_version=14.4.2&device_platform=iphone&device_type=iPhone9`;
await axios.get(API_URL, {
await axios
.get(API_URL, {
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",
"Content-Type": "application/json",
"Accept-Encoding": "gzip,deflate,compress"
"Accept-Encoding": "gzip,deflate,compress",
},
timeout: 10000,
proxy: false,
httpAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
httpsAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
}).then(resp => {
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
})
.then(resp => {
const data = resp.data.aweme_list[0];
e.reply(`识别tiktok, ${data.desc}`)
e.reply(`识别tiktok, ${data.desc}`);
this.downloadVideo(data.video.play_addr.url_list[0], true).then(video => {
e.reply(segment.video(`${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`));
})
})
return true
e.reply(
segment.video(
`${this.defaultPath}${this.e.group_id || this.e.user_id}/temp.mp4`
)
);
});
});
return true;
}
// bilibi解析
async bili(e) {
const urlRex = /(http:|https:)\/\/www.bilibili.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g;
let url = e.msg.trim()
let url = e.msg.trim();
// 短号处理
if (url.includes('b23.tv')) {
const bShortUrl = bShortRex.exec(url)[0]
if (url.includes("b23.tv")) {
const bShortUrl = bShortRex.exec(url)[0];
await fetch(bShortUrl).then(resp => {
url = resp.url;
})
});
} else {
url = urlRex.exec(url)[0];
}
const path = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/`
const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/`;
if (!fs.existsSync(path)) {
mkdirsSync(path);
}
@ -187,39 +204,42 @@ export class tools extends plugin {
const baseVideoInfo = "http://api.bilibili.com/x/web-interface/view";
const videoId = /video\/[^\?\/ ]+/.exec(url)[0].split("/")[1];
// 获取视频信息,然后发送
fetch(videoId.startsWith("BV") ? `${baseVideoInfo}?bvid=${videoId}` : `${baseVideoInfo}?aid=${videoId}`)
fetch(
videoId.startsWith("BV")
? `${baseVideoInfo}?bvid=${videoId}`
: `${baseVideoInfo}?aid=${videoId}`
)
.then(resp => resp.json())
.then(resp => {
e.reply(`识别:哔哩哔哩, ${resp.data.title}`)
.catch(err => {
e.reply(`识别:哔哩哔哩, ${resp.data.title}`).catch(err => {
e.reply("解析失败,重试一下");
console.log(err);
})
})
}())
});
});
})();
await getDownloadUrl(url)
.then(data => {
this.downBili(`${path}temp`, data.videoUrl, data.audioUrl)
.then(data => {
e.reply(segment.video(`${ path }temp.mp4`))
e.reply(segment.video(`${path}temp.mp4`));
})
.catch(err => {
console.log(err)
e.reply('解析失败,请重试一下')
console.log(err);
e.reply("解析失败,请重试一下");
});
})
.catch(err => {
console.log(err)
e.reply('解析失败,请重试一下')
console.log(err);
e.reply("解析失败,请重试一下");
});
return true
return true;
}
// 百科
async wiki(e) {
const key = e.msg.replace(/#|百科|wiki/g, "").trim();
const url = `https://xiaoapi.cn/API/bk.php?m=json&type=sg&msg=${ encodeURI(key) }`
const url = `https://xiaoapi.cn/API/bk.php?m=json&type=sg&msg=${encodeURI(key)}`;
// const url2 = 'https://api.jikipedia.com/go/auto_complete'
Promise.all([
// axios.post(url2, {
@ -238,7 +258,8 @@ export class tools extends plugin {
// }
// return data[0].entities[0];
// }),
axios.get(url, {
axios
.get(url, {
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",
@ -246,57 +267,56 @@ export class tools extends plugin {
timeout: 10000,
})
.then(resp => {
return resp.data
})
])
.then(res => {
const data = res[0]
return resp.data;
}),
]).then(res => {
const data = res[0];
// const data2 = res[0]
const template = `
解释${ _.get(data, 'msg') }\n
详情${ _.get(data, 'more') }\n
解释${_.get(data, "msg")}\n
详情${_.get(data, "more")}\n
`;
// 小鸡解释:${ _.get(data2, 'content') }
e.reply(template)
})
return true
e.reply(template);
});
return true;
}
// twitter解析
// 例子https://twitter.com/chonkyanimalx/status/1595834168000204800
async twitter(e) {
// 配置参数及解析
const reg = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/
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('', {httpAgent});
const httpAgent = new HttpProxyAgent(this.myProxy);
const twitterClient = new TwitterApi("", { 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',
],
}).then(resp => {
e.reply(`识别:腿忒学习版,${resp.data.text}`)
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"],
})
.then(resp => {
e.reply(`识别:腿忒学习版,${resp.data.text}`);
const downloadPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`;
// 创建文件夹(如果没有过这个群)
if (!fs.existsSync(downloadPath)) {
mkdirsSync(downloadPath);
}
// 开始读取数据
if (resp.includes.media[0].type === 'photo') {
if (resp.includes.media[0].type === "photo") {
// 图片
resp.includes.media.map(item => {
const filePath = `${downloadPath}/${item.url.split('/').pop()}`
const filePath = `${downloadPath}/${item.url.split("/").pop()}`;
this.downloadImgs(item.url, downloadPath).then(tmp => {
e.reply(segment.image(fs.readFileSync(filePath)))
})
})
e.reply(segment.image(fs.readFileSync(filePath)));
});
});
} else {
// 视频
this.downloadVideo(resp.includes.media[0].variants[0].url, true).then(video => {
@ -309,25 +329,23 @@ export class tools extends plugin {
// 视频解析
async tx(e) {
const url = e.msg
const data = await ( await fetch( `https://xian.txma.cn/API/jx_txjx.php?url=${url}` ) )
.json()
const k = data.url
const name = data.title
const url = e.msg;
const data = await (await fetch(`https://xian.txma.cn/API/jx_txjx.php?url=${url}`)).json();
const k = data.url;
const name = data.title;
if (k && name) {
e.reply( name + '\n' + k )
let forward = await this.makeForwardMsg( url )
e.reply( forward )
return true
e.reply(name + "\n" + k);
let forward = await this.makeForwardMsg(url);
e.reply(forward);
return true;
} else {
e.reply( '解析腾讯视频失败~\n去浏览器使用拼接接口吧...' )
let forward = await this.makeForwardMsg( url )
e.reply( forward )
return true
e.reply("解析腾讯视频失败~\n去浏览器使用拼接接口吧...");
let forward = await this.makeForwardMsg(url);
e.reply(forward);
return true;
}
}
// 请求参数
async douyinRequest(url) {
const params = {
@ -340,11 +358,11 @@ export class tools extends plugin {
return new Promise((resolve, reject) => {
axios
.head(url, params)
.then((resp) => {
const location = resp.request.res.responseUrl
.then(resp => {
const location = resp.request.res.responseUrl;
resolve(location);
})
.catch((err) => {
.catch(err => {
reject(err);
});
});
@ -378,8 +396,12 @@ export class tools extends plugin {
"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",
httpAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
httpsAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
});
}
console.log(`开始下载: ${url}`);
@ -394,18 +416,18 @@ export class tools extends plugin {
// 工具找到tiktok的视频id
async getIdVideo(url) {
const matching = url.includes("/video/")
const matching = url.includes("/video/");
if (!matching) {
this.e.reply("没找到,正在获取随机视频!")
return null
this.e.reply("没找到,正在获取随机视频!");
return null;
}
const idVideo = url.substring(url.indexOf("/video/") + 7, url.length);
return (idVideo.length > 19) ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo;
return idVideo.length > 19 ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo;
}
// acfun解析
async acfun(e) {
const path = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp/`
const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/temp/`;
if (!fs.existsSync(path)) {
mkdirsSync(path);
}
@ -413,68 +435,74 @@ export class tools extends plugin {
let inputMsg = e.msg;
// 适配手机分享https://m.acfun.cn/v/?ac=32838812&sid=d2b0991bd6ad9c09
if (inputMsg.includes("m.acfun.cn")) {
inputMsg = `https://www.acfun.cn/v/ac${/ac=([^&?]*)/.exec(inputMsg)[1]}`
inputMsg = `https://www.acfun.cn/v/ac${/ac=([^&?]*)/.exec(inputMsg)[1]}`;
}
parseUrl(inputMsg).then(res => {
e.reply(`识别:猴山,${res.videoName}`)
e.reply(`识别:猴山,${res.videoName}`);
parseM3u8(res.urlM3u8s[res.urlM3u8s.length - 1]).then(res2 => {
downloadM3u8Videos(res2.m3u8FullUrls, path).then(_ => {
mergeAcFileToMp4(res2.tsNames, path, `${path}out.mp4`).then(_ => {
e.reply(segment.video(`${path}out.mp4`))
})
})
})
})
e.reply(segment.video(`${path}out.mp4`));
});
});
});
});
return true;
}
// 小红书解析
async redbook(e) {
const msgUrl = /(http:|https:)\/\/(xhslink|xiaohongshu).com\/[A-Za-z\d._?%&+\-=\/#@]*/.exec(e.msg)[0];
const url = `https://dlpanda.com/zh-CN/xhs?url=${msgUrl}`
const msgUrl = /(http:|https:)\/\/(xhslink|xiaohongshu).com\/[A-Za-z\d._?%&+\-=\/#@]*/.exec(
e.msg
)[0];
const url = `https://dlpanda.com/zh-CN/xhs?url=${msgUrl}`;
await axios.get(url, {
await axios
.get(url, {
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",
"Content-Type": "application/json",
"Accept-Encoding": "gzip,deflate,compress"
"Accept-Encoding": "gzip,deflate,compress",
},
timeout: 10000,
proxy: false,
}).then((resp) => {
const reg = /<img(.*)src="\/\/ci\.xiaohongshu\.com(.*?)"/g
let res = '';
})
.then(resp => {
const reg = /<img(.*)src="\/\/ci\.xiaohongshu\.com(.*?)"/g;
let res = "";
const downloadPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`;
// 创建文件夹(如果没有过这个群)
if (!fs.existsSync(downloadPath)) {
mkdirsSync(downloadPath);
}
while (res = reg.exec(resp.data)) {
const addr = `https://ci.xiaohongshu.com${res[2]}`
axios.get(addr, {
while ((res = reg.exec(resp.data))) {
const addr = `https://ci.xiaohongshu.com${res[2]}`;
axios
.get(addr, {
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 = `${downloadPath}/${/com\/(.*)\?/.exec(addr)[1]}.jpg`
})
.then(resp => {
const filepath = `${downloadPath}/${/com\/(.*)\?/.exec(addr)[1]}.jpg`;
const writer = fs.createWriteStream(filepath);
resp.data.pipe(writer)
resp.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => resolve(filepath));
writer.on('error', reject);
writer.on("finish", () => resolve(filepath));
writer.on("error", reject);
});
})
.then(filepath => {
e.reply(segment.image(fs.readFileSync(filepath)))
fs.unlinkSync(filepath)
})
e.reply(segment.image(fs.readFileSync(filepath)));
fs.unlinkSync(filepath);
});
}
})
});
return true;
}
@ -483,53 +511,57 @@ export class tools extends plugin {
return Promise.all([
downloadBFile(
videoUrl,
title + '-video.m4s',
title + "-video.m4s",
_.throttle(
value =>
console.log('download-progress', {
type: 'video',
console.log("download-progress", {
type: "video",
data: value,
}),
1000,
),
1000
)
),
downloadBFile(
audioUrl,
title + '-audio.m4s',
title + "-audio.m4s",
_.throttle(
value =>
console.log('download-progress', {
type: 'audio',
console.log("download-progress", {
type: "audio",
data: value,
}),
1000,
1000
)
),
),
])
.then(data => {
return mergeFileToMp4(data[0].fullFileName, data[1].fullFileName, title + '.mp4');
})
]).then(data => {
return mergeFileToMp4(data[0].fullFileName, data[1].fullFileName, title + ".mp4");
});
}
// 工具:下载一张网络图片
async downloadImgs(img, dir) {
const filename = img.split('/').pop();
const filename = img.split("/").pop();
const filepath = `${dir}/${filename}`;
const writer = fs.createWriteStream(filepath);
return axios.get(img, {
return axios
.get(img, {
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",
httpAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
httpsAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }),
}).then(res => {
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
})
.then(res => {
res.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => resolve(filepath));
writer.on('error', reject);
writer.on("finish", () => resolve(filepath));
writer.on("error", reject);
});
});
}

View File

@ -1,9 +1,9 @@
// 主库
import Version from '../model/version.js'
import config from '../model/index.js'
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import Version from "../model/version.js";
import config from "../model/index.js";
import puppeteer from "../../../lib/puppeteer/puppeteer.js";
import { exec, execSync } from 'node:child_process'
import { exec, execSync } from "node:child_process";
const _path = process.cwd();
@ -13,36 +13,34 @@ const _path = process.cwd();
export class update extends plugin {
constructor() {
super({
name: '更新插件',
dsc: '更新插件代码',
event: 'message',
name: "更新插件",
dsc: "更新插件代码",
event: "message",
priority: 4000,
rule: [
{
reg: '^#*R(插件)?版本$',
fnc: 'version'
reg: "^#*R(插件)?版本$",
fnc: "version",
},
{
/** 命令正则匹配 */
reg: '^#(R更新|R强制更新)$',
reg: "^#(R更新|R强制更新)$",
/** 执行方法 */
fnc: 'rconsoleUpdate'
fnc: "rconsoleUpdate",
},
]
})
],
});
this.versionData = config.getConfig('version')
this.versionData = config.getConfig("version");
}
/**
* rule - 插件版本信息
*/
async version() {
const data = await new Version(this.e).getData(
this.versionData.slice(0, 3)
)
let img = await puppeteer.screenshot('version', data)
this.e.reply(img)
const data = await new Version(this.e).getData(this.versionData.slice(0, 3));
let img = await puppeteer.screenshot("version", data);
this.e.reply(img);
}
/**
@ -65,10 +63,17 @@ export class update extends plugin {
} else {
await this.e.reply("正在执行更新操作,请稍等");
}
const th = this
exec(command, { cwd: `${ _path }/plugins/rconsole-plugin/` }, async function (error, stdout, stderr) {
const th = this;
exec(
command,
{ cwd: `${_path}/plugins/rconsole-plugin/` },
async function (error, stdout, stderr) {
if (error) {
let isChanges = error.toString().includes("Your local changes to the following files would be overwritten by merge");
let isChanges = error
.toString()
.includes(
"Your local changes to the following files would be overwritten by merge"
);
let isNetwork = error.toString().includes("fatal: unable to access");
@ -84,10 +89,20 @@ export class update extends plugin {
);
} else if (isNetwork) {
await e.reply(
"失败!\nError code: " + error.code + "\n" + error.stack + "\n\n可能是网络问题请关闭加速器之类的网络工具或请过一会尝试。"
"失败!\nError code: " +
error.code +
"\n" +
error.stack +
"\n\n可能是网络问题请关闭加速器之类的网络工具或请过一会尝试。"
);
} else {
await e.reply("失败!\nError code: " + error.code + "\n" + error.stack + "\n\n出错了。请尝试处理错误");
await e.reply(
"失败!\nError code: " +
error.code +
"\n" +
error.stack +
"\n\n出错了。请尝试处理错误"
);
}
} else {
if (/Already up to date/.test(stdout)) {
@ -96,7 +111,8 @@ export class update extends plugin {
}
await th.restartApp();
}
});
}
);
}
async restartApp() {
@ -113,7 +129,6 @@ export class update extends plugin {
});
try {
await redis.set("Yunzai:rconsole:restart", data, { EX: 120 });
let cm = `npm run start`;