This commit is contained in:
yeyang
2022-10-06 02:50:45 +08:00
parent a09cc262f4
commit 949ebc31dd
24 changed files with 175 additions and 2114 deletions

View File

@@ -1,36 +0,0 @@
# Yenai-Plugin
#### Description
适用于Yunzai-Botv3的plugin
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

91
apps/curve.js Normal file
View File

@@ -0,0 +1,91 @@
import plugin from '../../../lib/plugins/plugin.js'
import gsCfg from '../../genshin/model/gsCfg.js'
import { segment } from 'oicq'
import fs from 'node:fs'
import common from '../../../lib/common/common.js'
let image;
export class curve extends plugin {
constructor() {
super({
name: 'nga收益曲线',
dsc: '收益曲线',
event: 'message',
priority: 500,
rule: [
{
reg: '^#*(.*)收益曲线(帮助)?$',
fnc: 'curve'
},
]
})
this.path = './plugins/yenai-plugin/resources/curveimg'
this.json = './plugins/yenai-plugin/config/curve.json'
}
//初始化
async init() {
if (!fs.existsSync(this.path)) {
fs.mkdirSync(this.path)
}
}
async curve() {
let role = {}
if (/#?收益曲线帮助/.test(this.e.msg)) role.name = "帮助"
else role = gsCfg.getRole(this.e.msg, '收益曲线')
if (!role) return
/** 主角特殊处理 */
if (['10000005', '10000007', '20000000'].includes(String(role.roleId))) {
if (!['风主', '岩主', '雷主', '草主'].includes(role.alias)) {
await this.e.reply('请选择:风主收益曲线、岩主收益曲线、雷主收益曲线、草主收益曲线')
return
} else {
role.name = role.alias
}
}
image = await fs.promises
.readFile(this.json, 'utf8')
.then((data) => {
return JSON.parse(data)
})
.catch((err) => {
logger.error('读取失败')
console.error(err)
return false
})
if (!image[role.name]) return this.e.reply("暂时无该角色收益曲线~>_<")
this.imgPath = `${this.path}/${role.name}.png`
if (!fs.existsSync(this.imgPath)) {
await this.getImg(role.name)
}
if (fs.existsSync(this.imgPath)) {
await this.e.reply(segment.image(this.imgPath));
return true;
}
}
//下载图片
async getImg(name) {
logger.mark(`${this.e.logFnc} 下载${name}素材图`)
if (!await common.downFile(image[name], this.imgPath)) {
return false
}
logger.mark(`${this.e.logFnc} 下载${name}素材成功`)
return true
}
}

49
apps/help.js Normal file
View File

@@ -0,0 +1,49 @@
import plugin from '../../../lib/plugins/plugin.js'
import { segment } from 'oicq'
export class Help extends plugin {
constructor() {
super({
name: '帮助',
dsc: '通知帮助',
event: 'message',
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^#?通知帮助$',
/** 执行方法 */
fnc: 'help'
}
]
})
}
// 帮助
async help() {
let msg = [
segment.image('https://api.ixiaowai.cn/api/api.php'),
'通知帮助 by 超市椰羊\n',
'---------------------\n',
'#闪照通知 (开启|关闭)\n',
'#禁言通知 (开启|关闭)\n',
'#群撤回通知 (开启|关闭)\n',
'#群消息通知 (开启|关闭)\n',
'#群邀请通知 (开启|关闭)\n',
'#好友撤回通知 (开启|关闭)\n',
'#好友消息通知 (开启|关闭)\n',
'#好友申请通知 (开启|关闭)\n',
'#全部管理通知 (开启|关闭)\n',
'#群临时消息通知 (开启|关闭)\n',
'#群管理变动通知 (开启|关闭)\n',
'#群成员变动通知 (开启|关闭)\n',
'#好友列表变动通知 (开启|关闭)\n',
'#群聊列表变动通知 (开启|关闭)\n',
'#设置删除缓存时间 <时间>(s)\n',
'#查看通知设置\n',
'#刷新通知设置'
]
this.e.reply(msg)
}
}

View File

@@ -1,14 +1,8 @@
/*
* @作者: 超市椰羊(746659424)
* @介绍: 提供账号的一些事件通知闪照撤回好友申请群邀请,|好友列表变动...
* @使用: 可用 "通知帮助" 来查看指令
* @可用指令来开启或关闭某项功能 直接修改配置文件(生成在当前文件夹下可参考655行的注释来修改配置文件)修改后重启或用指令来刷新配置
*/
import plugin from '../../lib/plugins/plugin.js'
import plugin from '../../../lib/plugins/plugin.js'
import { segment } from 'oicq'
import cfg from '../../lib/config/config.js'
import common from '../../lib/common/common.js'
import fs from 'fs'
import cfg from '../../../lib/config/config.js'
import common from '../../../lib/common/common.js'
import xcfg from "../model/Config"
let config = {}
@@ -27,6 +21,11 @@ export class Friends extends plugin {
event: 'notice.friend',
priority: 5000
})
this.configpath = './plugins/yenai-plugin/config/config.json'
}
async init() {
config = await xcfg.getread(this.configpath)
}
async accept(e) {
@@ -756,176 +755,7 @@ export class anotice extends plugin {
.catch((err) => e.reply(`❎ 发送失败\n错误信息为:${err.message}`))
}
}
export class NewConfig extends plugin {
constructor() {
super({
name: '配置',
dsc: '配置文件',
event: 'message',
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^#?(.*)通知(开启|关闭)$',
/** 执行方法 */
fnc: 'Config_manage'
},
{
/** 命令正则匹配 */
reg: '^#?设置删除缓存时间(.*)$',
/** 执行方法 */
fnc: 'Config_deltime'
},
{
/** 命令正则匹配 */
reg: '^#?通知帮助$',
/** 执行方法 */
fnc: 'help'
},
{
/** 命令正则匹配 */
reg: '^#?查看通知设置$',
/** 执行方法 */
fnc: 'SeeConfig'
},
{
/** 命令正则匹配 */
reg: '^#?刷新通知设置$',
/** 执行方法 */
fnc: 'SeeConfig'
}
]
})
this.path = './plugins/example/通知配置'
this.configpath = './plugins/example/通知配置/config.json'
}
// 初始化
async init() {
if (!fs.existsSync(this.path)) {
fs.mkdirSync(this.path)
}
// 检测有无配置文件,没有就创建默认配置文件
if (!fs.existsSync(this.configpath)) {
let configs = {
privateMessage: true, // 好友消息
groupMessage: false, // 群|讨论组消息(不建议开启)
grouptemporaryMessage: true, // 群临时消息
groupRecall: true, // 群撤回
PrivateRecall: true, // 好友撤回
// 申请通知
friendRequest: true, // 好友申请
groupInviteRequest: true, // 群邀请
// 信息变动
groupAdminChange: true, // 群管理变动
// 列表变动
friendNumberChange: true, // 好友列表变动
groupNumberChange: true, // 群聊列表变动
groupMemberNumberChange: false, // 群成员变动
// 其他通知
flashPhoto: true, // 闪照
botBeenBanned: true, // 机器人被禁言
// 是否给全部管理发送通知(默认只通知第一个管理)
notificationsAll: false,
// 设置删除消息缓存的时间单位s(用于撤回监听)
deltime: 600 // 不建议太大
}
await getwrite(this.configpath, configs)
}
// 读取配置
config = await getread(this.configpath)
}
// 帮助
async help() {
let msg = [
segment.image('https://api.ixiaowai.cn/api/api.php'),
'通知帮助 by 超市椰羊\n',
'---------------------\n',
'#闪照通知 (开启|关闭)\n',
'#禁言通知 (开启|关闭)\n',
'#群撤回通知 (开启|关闭)\n',
'#群消息通知 (开启|关闭)\n',
'#群邀请通知 (开启|关闭)\n',
'#好友撤回通知 (开启|关闭)\n',
'#好友消息通知 (开启|关闭)\n',
'#好友申请通知 (开启|关闭)\n',
'#全部管理通知 (开启|关闭)\n',
'#群临时消息通知 (开启|关闭)\n',
'#群管理变动通知 (开启|关闭)\n',
'#群成员变动通知 (开启|关闭)\n',
'#好友列表变动通知 (开启|关闭)\n',
'#群聊列表变动通知 (开启|关闭)\n',
'#设置删除缓存时间 <时间>(s)\n',
'#查看通知设置\n',
'#刷新通知设置'
]
this.e.reply(msg)
}
// 更改配置
async Config_manage(e) {
this.init()
if (!e.isMaster) return
// 解析消息
let index = e.msg.indexOf('通知')
let option = e.msg.slice(0, index)
option = option.replace(/#/, '').trim()
// 开启还是关闭
let yes = false
if (/开启/.test(e.msg)) yes = true
// 回复
if (await getcfg(option, yes)) {
e.reply(`✅ 已${yes ? '开启' : '关闭'}${option}通知`)
}
}
// 设置删除缓存时间
async Config_deltime(e) {
this.init()
if (!e.isMaster) return
let time = e.msg.replace(/#|设置删除缓存时间/, '').trim()
time = time.match(/\d*/g)
if (!time) return e.reply('❎ 请输入正确的时间(单位s)')
if (time < 120) return e.reply('❎ 时间不能小于两分钟')
if (await getcfg('缓存时间', Number(time))) {
e.reply(`✅ 已设置删除缓存时间为${getsecond(time)}`)
}
}
async SeeConfig() {
this.init()
if (/刷新通知设置/.test(this.e.msg)) {
config = await getread(this.configpath)
await this.e.reply('✅ 已刷新,当前的设置为:')
}
let msg = [
`闪照 ${config.flashPhoto ? '✅' : '❎'}\n`,
`禁言 ${config.botBeenBanned ? '✅' : '❎'}\n`,
`群消息 ${config.groupMessage ? '✅' : '❎'}\n`,
`群撤回 ${config.groupRecall ? '✅' : '❎'}\n`,
`群邀请 ${config.groupInviteRequest ? '✅' : '❎'}\n`,
`好友消息 ${config.privateMessage ? '✅' : '❎'}\n`,
`好友撤回 ${config.PrivateRecall ? '✅' : '❎'}\n`,
`好友申请 ${config.friendRequest ? '✅' : '❎'}\n`,
`群成员变动 ${config.groupMemberNumberChange ? '✅' : '❎'}\n`,
`群管理变动 ${config.groupAdminChange ? '✅' : '❎'}\n`,
`群临时消息 ${config.grouptemporaryMessage ? '✅' : '❎'}\n`,
`好友列表变动 ${config.friendNumberChange ? '✅' : '❎'}\n`,
`群聊列表变动 ${config.groupNumberChange ? '✅' : '❎'}\n`,
`全部管理发送 ${config.notificationsAll ? '✅' : '❎'}\n`,
`删除缓存时间:${config.deltime}`
]
await this.e.reply(msg)
}
}
/** 发消息 */
async function getSend(msg) {
@@ -992,67 +822,4 @@ function getsecond(value) {
result = parseInt(hourTime) + '小时' + result
}
return result
}
/** 读取文件 */
async function getread(path) {
return await fs.promises
.readFile(path, 'utf8')
.then((data) => {
return JSON.parse(data)
})
.catch((err) => {
logger.error('读取失败')
console.error(err)
return false
})
}
/** 写入文件 */
async function getwrite(path, cot) {
return await fs.promises
.writeFile(path, JSON.stringify(cot, '', '\t'))
.then(() => {
return true
})
.catch((err) => {
logger.error('写入失败')
console.error(err)
return false
})
}
async function getcfg(key, value) {
// 路径
let path = './plugins/example/通知配置/config.json'
// 配置类
const parameter = {
好友消息: 'privateMessage',
群消息: 'groupMessage',
群临时消息: 'grouptemporaryMessage',
群撤回: 'groupRecall',
好友撤回: 'PrivateRecall',
好友申请: 'friendRequest',
群邀请: 'groupInviteRequest',
群管理变动: 'groupAdminChange',
好友列表变动: 'friendNumberChange',
群聊列表变动: 'groupNumberChange',
群成员变动: 'groupMemberNumberChange',
闪照: 'flashPhoto',
禁言: 'botBeenBanned',
全部管理: 'notificationsAll',
缓存时间: 'deltime'
}
// 判断是否有这一项类
if (!parameter.hasOwnProperty(key)) return false
// 读取配置
let cfg = await getread(path)
// 更改配置
cfg[parameter[key]] = value
// 写入
await getwrite(path, cfg)
// 刷新
config = await getread(path)
return true
}
}

View File

@@ -1,90 +0,0 @@
/*
* @作者: 超市椰羊(746659424)
* @介绍:
*/
import { segment } from "oicq"
//由于oicq不加好友点不上赞
/**没加好友回复 */
let notFriend = "不加好友不点🙄"
/** 点赞成功回复 n是点赞数 普通用户为 10svip 为 20*/
let success = "给你点了[n]下哦,记得回我~"
/** 点赞失败的回复(一般是点赞上限) */
let failds = "今天点过了,害搁这讨赞呐";
/**是否需要要回复的图片*/
let picture = true
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '点赞插件',
/** 功能描述 */
dsc: '给自己资料卡点赞',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^(我要|给我)?(资料卡)?(点赞|赞我)$',
/** 执行方法 */
fnc: 'zan'
}
]
})
}
async zan(e) {
/**判断是否为好友 */
let isFriend = await Bot.fl.get(e.user_id)
if (!isFriend) return e.reply(notFriend, true)
/** 点赞成功回复的图片*/
let imgs = [
"https://xiaobai.klizi.cn/API/ce/zan.php?qq=",
"https://xiaobapi.top/api/xb/api/bixin.php?qq=",
"https://xiaobapi.top/api/xb/api/zan.php?qq="]
/** 一个随机数 */
let random = Math.floor(Math.random() * (imgs.length - 0))
let success_img = segment.image(imgs[random] + e.user_id)
/** 点赞失败的图片 */
let failds_img = segment.image(`https://xiaobai.klizi.cn/API/ce/paa.php?qq=${e.user_id}`)
/** 执行点赞*/
let n = 0;
while (true) {
let res = await Bot.sendLike(e.user_id, 10)
if (!res) {
break;
} else {
n += 10;
}
}
let success_ = success.replace(/\[n]/g, String(n))
let success_result = ""
let failds_result = ""
if (picture) {
success_result = ["\n", success_, success_img]
failds_result = ["\n", failds, failds_img]
} else {
success_result = "\b" + success_
failds_result = "\b" + failds
}
/**判断点赞是否成功*/
let msg = n > 0 ? success_result : failds_result
/**回复 */
e.reply(msg, false, { at: true })
return true
}
}

View File

@@ -1,871 +0,0 @@
/*
* @作者: 超市椰羊(746659424)
* @介绍: 提供一些对机器人的远程操作 可使用 "助手帮助" 查看命令
*/
import plugin from '../../lib/plugins/plugin.js';
import { segment } from "oicq";
import fetch from 'node-fetch';
import cfg from '../../lib/config/config.js';
let Qzonedetermine;
let groupPhotoid;
export class example extends plugin {
constructor() {
super({
name: '小助手',
dsc: '远程对机器人进行一些操作',
event: 'message',
priority: 5000,
rule: [
{
reg: '^#?助手帮助$',
fnc: 'help'
},
{
reg: '^#?改头像.*$',
fnc: 'Photo'
},
{
reg: '^#?改昵称.*$',
fnc: 'Myname'
},
{
reg: '^#?改签名.*$',
fnc: 'Sign'
},
{
reg: '^#?改状态.*$',
fnc: 'State'
},
{
reg: '^#?发好友.*$',
fnc: 'Friends'
},
{
reg: '^#?发群聊.*$',
fnc: 'Groupmsg'
},
{
reg: '^#?退群.*$',
fnc: 'Quit'
},
{
reg: '^#?删好友.*$',
fnc: 'Deletes'
},
{
reg: '^#?改性别.*$',
fnc: 'Sex'
},
{
reg: '^#?取直链.*$',
fnc: 'Picture'
},
{
reg: '^#?取face.*$',
fnc: 'Face'
},
{
reg: '^#?查(Q|q)绑.*$',
fnc: 'Qbang'
},
{
reg: '^#?取说说列表.*$',
fnc: 'Qzonelist'
},
{
reg: '^#?删说说.*$',
fnc: 'Qzonedel'
},
{
reg: '^#?发说说.*$',
fnc: 'Qzonesay'
},
{
reg: '^#?(清空说说|清空留言)$',
fnc: 'QzoneEmpty'
},
{
reg: '^#?改群名片.*$',
fnc: 'MyGroupname'
},
{
reg: '^#?改群头像.*$',
fnc: 'GroupPhoto'
},
{
reg: '^#?改群昵称.*$',
fnc: 'Groupname'
},
{
reg: '^#?获取(群|好友)列表$',
fnc: 'Grouplist'
},
]
})
}
//帮助
async help(e) {
let msg = [
segment.image("https://api.ixiaowai.cn/api/api.php"),
"小助手 by 超市椰羊 \n",
"--------------------\n",
"#发群聊 <群号> <内容> \n",
"#发好友 <QQ> <内容> \n",
"#改头像 <图片> \n",
"#改状态 <状态> \n",
"#改昵称 <昵称> \n",
"#改签名 <签名> \n",
"#改性别 <性别> \n",
"#改群名片 <名片> \n",
"#改群昵称 <昵称> \n",
"#改群头像 <图片> \n",
"#删好友 <QQ> \n",
"#退群 <群号> \n",
"#获取群列表\n",
"#获取好友列表\n",
"#取说说列表 <页数> \n",
"#发说说 <内容> \n",
"#删说说 <序号>\n",
"#清空说说\n",
"#清空留言\n",
"#取直链 <图片>\n",
"#取face <face表情>",
"#查Q绑 <QQ>"
]
e.reply(msg);
}
/**改头像*/
async Photo(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
if (!e.img) {
this.setContext('Photos')
e.reply("✳️ 请发送图片");
return;
}
await Bot.setAvatar(e.img[0])
.then(() => { e.reply("✅ 头像修改成功") })
.catch((err) => {
e.reply("❎ 头像修改失败");
console.log(err);
})
}
async Photos() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('Photos')
await this.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('Photos')
await this.reply('❎ 请发送图片或取消')
return;
}
await Bot.setAvatar(img[0])
.then(() => this.e.reply("✅ 头像修改成功"))
.catch((err) => {
this.e.reply("❎ 头像修改失败");
console.log(err)
})
this.finish('Photos')
}
/** 改昵称*/
async Myname(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let name = e.msg.replace(/#|改昵称/g, "").trim()
await Bot.setNickname(name)
.then(() => e.reply("✅ 昵称修改成功"))
.catch((err) => {
e.reply("❎ 昵称修改失败");
console.log(err);
})
}
/** 改群名片 */
async MyGroupname(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let group = '';
let card = '';
if (e.isPrivate) {
let msg = e.msg.split(" ")
group = msg[1].match(/[1-9]\d*/g);
card = msg.slice(2).join(" ");
if (!group) return e.reply("❎ 群号不能为空");
if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群");
} else {
group = e.group_id;
card = e.msg.replace(/#|改群名片/g, "").trim()
}
if (!card) return e.reply("❎ 名片不能为空");
Bot.pickGroup(group).setCard(cfg.qq, card)
.then(() => e.reply("✅ 群名片修改成功"))
.catch(err => {
e.reply("✅ 群名片修改失败")
console.log(err);
})
}
/**改群头像 */
async GroupPhoto(e) {
if (e.isPrivate) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
groupPhotoid = e.msg.replace(/#|改群头像/g, "").trim()
if (!groupPhotoid) return e.reply("❎ 群号不能为空");
if (!(/^\d+$/.test(groupPhotoid))) return e.reply("❎ 您的群号不合法");
if (!Bot.gl.get(Number(groupPhotoid))) return e.reply("❎ 群聊列表查无此群");
} else {
//判断身份
if (e.member.is_admin || e.member.is_owner || e.isMaster) {
groupPhotoid = e.group_id
} else {
return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)])
}
}
groupPhotoid = Number(groupPhotoid);
if (Bot.pickGroup(groupPhotoid).is_admin || Bot.pickGroup(groupPhotoid).is_owner) {
if (!e.img) {
this.setContext('picture')
e.reply("✳️ 请发送图片");
return;
}
Bot.pickGroup(groupPhotoid).setAvatar(e.img[0])
.then(() => e.reply("✅ 群头像修改成功"))
.catch((err) => {
e.reply("✅ 群头像修改失败")
console.log(err);
})
} else {
return e.reply("❎ 没有管理员人家做不到啦~>_<");
}
}
picture() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('picture')
this.e.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('picture')
this.e.reply('❎ 请发送图片或取消')
return;
}
Bot.pickGroup(groupPhotoid).setAvatar(this.e.img[0])
.then(() => this.e.reply("✅ 群头像修改成功"))
.catch((err) => {
this.e.reply("✅ 群头像修改失败")
console.log(err);
})
this.finish('picture')
}
/**改群昵称 */
async Groupname(e) {
let group = '';
let card = '';
if (e.isPrivate) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msg = e.msg.split(" ")
group = msg[1].match(/[1-9]\d*/g);
card = msg.slice(2).join(" ");
if (!group) return e.reply("❎ 群号不能为空");
if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群");
} else {
if (e.member.is_admin || e.member.is_owner || e.isMaster) {
group = e.group_id
card = e.msg.replace(/#|改群昵称/g, "").trim()
} else {
return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)])
}
}
if (!card) return e.reply("❎ 昵称不能为空");
group = Number(group);
if (Bot.pickGroup(group).is_admin || Bot.pickGroup(group).is_owner) {
Bot.pickGroup(group).setName(card)
.then(() => e.reply("✅ 群昵称修改成功"))
.catch(err => {
e.reply("✅ 群昵称修改失败")
console.log(err);
})
} else {
return e.reply("❎ 没有管理员人家做不到啦~>_<");
}
}
/** 改签名*/
async Sign(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let signs = e.msg.replace(/#|改签名/g, "").trim()
await Bot.setSignature(signs)
.then(() => e.reply("✅ 签名修改成功"))
.catch((err) => {
e.reply("❎ 签名修改失败");
console.log(err)
})
}
/** 改状态*/
async State(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let signs = e.msg.replace(/#|改状态/g, "").trim()
if (!signs) return e.reply("❎ 状态不为空可选值我在线上离开隐身忙碌Q我吧请勿打扰");
let res = {
"离开": 31,
"忙碌": 50,
"隐身": 41,
"Q我吧": 60,
"请勿打扰": 70,
"我在线上": 11,
}
let status = {
31: "离开",
50: "忙碌",
70: "请勿打扰",
41: "隐身",
11: "我在线上",
60: "Q我吧",
};
if (!(signs in res)) return e.reply("❎ 可选值我在线上离开隐身忙碌Q我吧请勿打扰")
await Bot.setOnlineStatus(res[signs])
.then(() => e.reply("✅ 在线状态修改成功"))
.then(() => e.reply(`✅ 现在的在线状态为【${status[Bot.status]}`))
.catch(err => {
e.reply("❎ 在线状态修改失败");
console.log(err);
})
return true;
}
/** 发好友*/
async Friends(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msgs = e.message[0].text.split(" ")
if (msgs.length == 1 && !(/\d/.test(msgs[0]))) return e.reply("❎ QQ号不能为空");
let qq
if (/\d/.test(msgs[0])) {
qq = msgs[0].match(/[1-9]\d*/g)
e.message[0].text = msgs.slice(1).join(" ");
} else {
qq = msgs[1]
e.message[0].text = msgs.slice(2).join(" ");
}
if (!/^\d+$/.test(qq)) return e.reply("❎ QQ号不正确人家做不到的啦>_<~");
if (!Bot.fl.get(Number(qq))) return e.reply("❎ 好友列表查无此人");
if (!e.message[0].text) e.message.shift()
if (e.message.length === 0) return e.reply("❎ 消息不能为空");
await Bot.pickFriend(qq).sendMsg(e.message)
.then(() => e.reply("✅ 私聊消息已送达"))
.catch(err => e.reply(`❎ 发送失败\n错误信息为:${err.message}`))
}
/** 发群聊*/
async Groupmsg(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msgs = e.message[0].text.split(" ")
e.message[0].text = msgs.slice(2).join(" ");
if (msgs.length < 2) return e.reply("❎ 您输入的指令不合法");
if (!/^\d+$/.test(msgs[1])) return e.reply("❎ 您输入的群号不合法");
if (!Bot.gl.get(Number(msgs[1]))) return e.reply("❎ 群聊列表查无此群");
if (!e.message[0].text) e.message.shift()
if (e.message.length === 0) return e.reply("❎ 消息不能为空");
await Bot.pickGroup(msgs[1]).sendMsg(e.message)
.then(() => e.reply("✅ 群聊消息已送达"))
.catch((err) => e.reply(`❎ 发送失败\n错误信息为:${err.message}`))
}
/**退群 */
async Quit(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let quits = e.msg.replace(/#|退群/g, "").trim()
if (!quits) return e.reply("❎ 群号不能为空");
if (!/^\d+$/.test(quits)) return e.reply("❎ 群号不合法");
if (!Bot.gl.get(Number(quits))) return e.reply("❎ 群聊列表查无此群")
await Bot.pickGroup(quits).quit()
.then(() => e.reply(`✅ 已退出群聊`))
.catch((err) => {
e.reply("❎ 退出失败");
console.log(err)
})
}
/**删好友 */
async Deletes(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true)
let quits = e.msg.replace(/#|删好友/g, "").trim()
if (e.message[1]) {
quits = e.message[1].qq
} else {
quits = quits.match(/[1-9]\d*/g)
}
if (!quits) return e.reply("❎ 请输入正确的QQ号")
if (!Bot.fl.get(Number(quits))) return e.reply("❎ 好友列表查无此人");
await Bot.pickFriend(quits).delete()
.then(() => e.reply(`✅ 已删除好友`))
.catch((err) => {
e.reply("❎ 删除失败");
console.log(err);
})
}
/**改性别 */
async Sex(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let sex = e.msg.replace(/#|改性别/g, "").trim();
if (!sex) return e.reply("❎ 性别不能为空 可选值:男,女,无\n改为无为无性别");
let res = {
"无": 0,
"男": 1,
"女": 2,
}
if (!(sex in res)) return e.reply("❎ 可选值:男,女,无(改为无,为无性别)");
await Bot.setGender(res[sex])
.then(() => e.reply(`✅ 已修改性别`))
.catch((err) => {
e.reply("❎ 修改失败");
console.log(err);
})
}
/**取直链 */
async Picture(e) {
if (!e.img) {
this.setContext('imgs')
await this.reply('✳️ 请发送图片')
return;
}
await e.reply(`✅ 检测到${e.img.length}张图片`)
for (let i of e.img) {
await e.reply([segment.image(i), "直链:", i])
}
}
async imgs() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('imgs')
await this.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('imgs')
await this.reply('❎ 请发送图片或取消')
return;
}
await this.e.reply(img[0])
this.finish('imgs')
}
/** 取Face表情 */
async Face(e) {
let face = [];
for (let m of e.message) {
if (m.type === "face") {
let s = false;
for (let i of face) { if (i.id === m.id) s = true }
if (!s) face.push(m)
}
}
if (face.length === 0) return e.reply("❎ 表情参数不可为空", true);
let res = face.map(function (item) {
return [
`表情:`,
item,
`\nid${item.id}`,
`\n描述:${item.text}`
]
})
for (let i of res) {
await e.reply(i)
}
}
/** 查Q绑 */
async Qbang(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let qq = e.message[0].text.replace(/#|查(Q|q)绑/g, "").trim()
if (e.message[1]) {
qq = e.message[1].qq
} else {
qq = qq.match(/[1-9]\d*/g)
}
if (!qq) return e.reply("❎ 请输入正确的QQ号")
let qbang = await fetch(`https://zy.xywlapi.cc/qqapi?qq=${qq}`).then(res => res.json()).catch(err => console.log(err))
let lol = await fetch(`https://api.xywlapi.cc/qqlol?qq=${qq}`).then(res => res.json()).catch(err => console.log(err))
if (!qbang) return e.reply("❎ 接口查询失败");
if (qbang.status != 200) {
try {
e.reply(`❎ 错误信息:${qbang.message}`)
} catch {
e.reply(`❎ 此QQ号无法查询`)
}
return false;
}
let wb = await fetch(`https://api.xywlapi.cc/wbphone?phone=${qbang.phone}`).then(res => res.json()).catch(err => console.log(err))
let msg = [
`🐧:${qbang.qq}\n`,
`📱:${qbang.phone}\n`,
`🌏:${qbang.phonediqu}`
]
try {
if (lol.status == 200) {
msg.push(`\nLOL${lol.name}(${lol.daqu})`)
}
} catch {
console.log(`LOL没有找到`);
}
try {
if (wb.status == 200) {
msg.push(`\n微博uid${wb.id}`)
}
} catch {
console.log(`微博没有找到`);
}
let timeout = 600000; //0表示不撤回单位毫秒
let msgRes = await e.reply(msg);
if (timeout != 0 && msgRes && msgRes.message_id) {
let target = null;
if (e.isGroup) {
target = e.group;
} else {
target = e.friend;
}
if (target != null) {
setTimeout(() => {
target.recallMsg(msgRes.message_id);
target.recallMsg(e.message_id);
}, timeout);
}
}
return true;
}
/**QQ空间 说说列表*/
async Qzonelist(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|取说说列表/g, "").trim()
if (!res) res = 1
if (!parseInt(res)) return e.reply(`❎ 请检查页数是否正确`)
let list = await getlist()
list = list.msglist
if (!list) return e.reply(`❎ 说说列表为空`)
let msg = [
"✅ 获取成功,说说列表如下:\n"
]
let page = 5 * (res - 1)
for (let i = 0 + page; i < 5 + page; i++) {
if (!list[i]) break
let arr = `${i + 1}.${getLimit(list[i].content)}\n- [${list[i].secret ? "私密" : "公开"}] | ${formatDate(list[i].created_time)} | ${list[i].commentlist ? list[i].commentlist.length : 0}条评论\n`
msg.push(arr)
}
if (res > Math.ceil(list.length / 5)) return e.reply(`❎ 页数超过最大值`)
msg.push(`页数:[${res}/${Math.ceil(list.length / 5)}]`)
e.reply(msg)
}
/** 删除说说 */
async Qzonedel(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|删说说/g, "").trim()
if (!res) return e.reply(`❎ 序号不可为空`)
res = res.match(/\d/)
if (!res) return e.reply(`❎ 请检查序号是否正确`)
let list = await getlist()
if (!list.msglist) return e.reply(`❎ 说说列表为空`)
let ck = getck()
if ((res - 1) >= list.msglist.length) return e.reply(`❎ 序号超过最大值`)
let something = list.msglist[res - 1]
let url = `https://xiaobai.klizi.cn/API/qqgn/ss_delete.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&tid=${something.tid}`
let result = await fetch(url).then(res => res.text()).catch(err => console.log(err))
if (!result) return e.reply(`❎ 接口请求失败`)
if (/删除说说成功/.test(result)) {
e.reply(`✅ 删除说说成功:\n ${res}.${getLimit(something.content)} \n - [${something.secret ? "私密" : "公开"}] | ${formatDate(something.created_time)} | ${something.commentlist ? something.commentlist.length : 0} 条评论`)
} else if (/删除失败/.test(result)) {
e.reply(`❎ 删除失败`)
}
}
/** 发说说 */
async Qzonesay(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|发说说/g, "").trim()
let ck = getck()
let url;
if (e.img) {
url = `https://xiaobai.klizi.cn/API/qqgn/ss_sendimg.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&url=${e.img[0]}&msg=${res}`
} else {
url = `http://xiaobai.klizi.cn/API/qqgn/ss_send.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&msg=${res}`
}
let result = await fetch(url).then(res => res.json()).catch(err => console.log(err))
let msg = [`✅ 说说发表成功,内容:\n`, getLimit(result.content)]
if (result.code != 0) return e.reply(`❎ 说说发表失败\n错误信息:${result.message}`)
if (result.pic) {
msg.push(segment.image(result.pic[0].url1))
}
msg.push(`\n- [${result.secret ? "私密" : "公开"}] | ${formatDate(result.t1_ntime)}`)
e.reply(msg)
}
/** 清空说说和留言*/
async QzoneEmpty(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
if (/清空说说/.test(e.msg)) {
this.setContext('QzonedelAll')
e.reply("✳️ 即将删除全部说说请发送:\n" + "------确认清空或取消------");
Qzonedetermine = true;
return true;
} else if (/清空留言/.test(e.msg)) {
this.setContext('QzonedelAll')
e.reply("✳️ 即将删除全部留言请发送:\n" + "------确认清空或取消------");
Qzonedetermine = false
return true;
}
}
async QzonedelAll() {
let msg = this.e.msg
if (msg == "确认清空") {
this.finish('QzonedelAll')
let ck = getck()
let url
if (Qzonedetermine) {
url = `https://xiaobai.klizi.cn/API/qqgn/ss_empty.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}`
} else {
url = `https://xiaobai.klizi.cn/API/qqgn/qzone_emptymsgb.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}`
}
let result = await fetch(url).then(res => res.text()).catch(err => console.log(err))
this.e.reply(`${result}`)
return true;
} else if (msg == "取消") {
this.finish('QzonedelAll')
this.e.reply("✅ 已取消")
return false;
} else {
this.setContext('QzonedelAll')
this.e.reply("❎ 请输入:确认清空或取消")
return false;
}
}
//获取群|好友列表
async Grouplist(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let listMap;
let message = [];
let list = []
let yes = false
if (/群列表/.test(e.msg)) {
//获取群列表并转换为数组
listMap = Array.from(Bot.gl.values())
//添加有几个群
message.push(`群列表如下,共${listMap.length}个群`)
//遍历添加
listMap.forEach((item, index) => {
list.push(`${index + 1}${item.group_name}(${item.group_id})\n`)
})
yes = true
} else if (/好友列表/.test(e.msg)) {
//获取好友列表并转换为数组
listMap = Array.from(Bot.fl.values())
//添加有多少个好友
message.push(`好友列表如下,共${listMap.length}个好友`)
//遍历添加
listMap.forEach((item, index) => {
list.push(`${index + 1}${item.nickname}(${item.user_id})\n`)
})
}
//去除最后一个的换行符
list[list.length - 1] = list[list.length - 1].replace(/\n/, "")
message.push(list)
if (yes) {
message.push("可使用 #退群123456789 来退出某群")
} else {
message.push("可使用 #删好友123456789 来删除某人")
}
//制作转发消息
let forwardMsg = []
for (let i of message) {
forwardMsg.push(
{
message: i,
nickname: Bot.nickname,
user_id: Bot.uin
}
)
}
if (e.isGroup) {
forwardMsg = await e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await e.friend.makeForwardMsg(forwardMsg)
}
//发送消息
e.reply(forwardMsg)
}
}
/**字数限制 */
function getLimit(str) {
let s = str.slice(0, 10)
return str.length > 10 ? s + "..." : str
}
/**时间格式化 */
function formatDate(time) {
var now = new Date(parseFloat(time) * 1000);
var month = now.getMonth() + 1;
var date = now.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (date >= 0 && date <= 9) {
date = "0" + date;
}
var hour = now.getHours();
var minute = now.getMinutes();
if (hour >= 1 && hour <= 9) {
hour = "0" + hour;
}
if (minute >= 0 && minute <= 9) {
minute = "0" + minute;
}
return month + "/" + date + " " + hour + ":" + minute
}
/**取说说列表*/
async function getlist() {
let ck = getck()
let url = `https://xiaobai.klizi.cn/API/qqgn/ss_list.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&qq=${cfg.qq}`
let list = await fetch(url).then(res => res.json()).catch(err => console.log(err))
if (!list) {
return e.reply("❎ 取说说列表失败")
} else {
return list
}
}
/**取cookies */
function getck() {
let cookie = Bot.cookies['qzone.qq.com']
let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim()
ck = ck.substring(0, ck.length - 2)
ck = `{"`.concat(ck).concat("}")
return JSON.parse(ck)
}

View File

@@ -1,80 +0,0 @@
import fs from 'fs'
import fetch from 'node-fetch';
/**
* 在“resources”文件夹下 新建“头像”文件夹把要修改的头像扔进去
* 随机修改一个头像文件夹里面的头像,默认每五分钟修改一次
*/
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '头像',
/** 功能描述 */
dsc: '定时随机修改头像',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^#?换头像$',
/** 执行方法 */
fnc: 'avatar'
}]
})
/** 定时任务 */
this.task = {
/**Cron表达式 每五分钟执行一次 */
cron: '0 */10 * * * ?',
name: '定时随机修改头像',
fnc: () => this.avatar()
}
}
async avatar() {
//项目路径
let _path = process.cwd();
//头像路径
let paths = `${_path}/resources/头像`
let data;
let random;
try {
//获取头像文件夹下的文件
data = fs.readdirSync("././././resources/头像")
//随机数
random = Math.floor(Math.random() * (data.length - 0)) + 0;
} catch { console.log("无头像文件夹"); }
let url;
if (Math.random() > 0.5) {
url = await fetch("https://api.uomg.com/api/rand.avatar?sort=动漫女&format=json").then(res => res.json()).then(res => res.imgurl).catch(err => console.log(err))
} else {
url = "http://api.btstu.cn/sjtx/api.php?lx=c2&format=images"
}
//修改头像
try {
Bot.setAvatar(url).then(() => { logger.mark("[头像]修改网络头像") }).catch(
err => {
logger.error("[头像]API失效")
console.log(err);
}
)
} catch {
Bot.setAvatar(`file:///${paths}/${data[random]}`).then(() => { logger.mark("[头像]修改本地头像") }).catch(
err => {
logger.error("[头像]本地头像报错")
console.log(err);
}
)
}
}
}

View File

@@ -1,70 +0,0 @@
import plugin from "../../lib/plugins/plugin.js";
import fetch from 'node-fetch'
import cfg from '../../lib/config/config.js'
import common from '../../lib/common/common.js'
//设置会员参数 (普通、vip、svip)
const member = "svip"
const myck = {
"code": 0,
"uin": "746659424",
"skey": "@qPj9eqrJZ",
"gtk": "1674138517",
"pt4token": "s4xN*kb8Bf-7rWDdbtkWVRj-xg5LL3ydX4t7jC6NLTM_",
"pskey": "YAfPtfubqFp4-4K0j3KWqb-B-O07H9tpX7eESL30zsw_",
"superkey": "vLB8ZIs8Pr*r-zdlZcBYzas5l9fU2ExoG7LQko3d0QQ_",
"state": "登录成功!",
"name": "超市椰羊"
}
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: "百变气泡",
/** 功能描述 */
dsc: "百变气泡",
/** https://oicqjs.github.io/oicq/#events */
event: "message",
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: "^换气泡$",
/** 执行方法 */
fnc: "Changeable",
},
],
});
/** 定时任务默认每10分钟一次不建议太短 */
this.task = {
cron: '0 */10 * * * ?',
name: '百变气泡',
fnc: () => this.Changeable()
}
}
async Changeable() {
//获取ck
let cookie = Bot.cookies['vip.qq.com']
let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim()
ck = ck.substring(0, ck.length - 2)
ck = `{"`.concat(ck).concat("}")
ck = JSON.parse(ck)
let url = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&type=text&member=${member}`
let result = await fetch(url).then(res => res.text())
let myurl = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${myck.uin}&skey=${myck.skey}&pskey=${myck.pskey}&type=text&member=${member}`
let my = await fetch(myurl).then(res => res.text()).catch(common.relpyPrivate(746659424, "ck失效"))
logger.mark(`[百变气泡] ${result}`)
logger.mark(`[百变气泡自己] ${my}`)
}
}

View File

@@ -1,51 +0,0 @@
import plugin from '../../lib/plugins/plugin.js'
import fetch from 'node-fetch'
import { segment } from "oicq";
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '随机唱鸭',
/** 功能描述 */
dsc: '随机唱鸭',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^唱歌$',
/** 执行方法 */
fnc: 'Sing'
}
]
})
}
async Sing(e) {
let url = "https://xiaobai.klizi.cn/API/music/changya.php"
let res = await fetch(url).catch(err => console.log(err))
if (!res) {
e.reply("❎ 接口请求失败")
return false;
}
res = await res.json()
if (res.code != 200) {
e.reply("❎ 接口请求错误")
return false;
}
let data = res.data
await e.reply(segment.record(data.audioSrc))
//处理歌词
let lyric = data.lyrics.map(function (item) {
return `${item}\n`
})
lyric[lyric.length - 1] = data.lyrics[data.lyrics.length - 1]
await e.reply(lyric)
return true;
}
}

View File

@@ -1,45 +0,0 @@
import fs from 'fs'
import lodash from 'lodash'
const _path = process.cwd()
const _cfgPath = `${_path}/plugins/xiaofei-plugin/components/`
let cfg = {}
try {
if (fs.existsSync(_cfgPath + 'cfg.json')) {
cfg = JSON.parse(fs.readFileSync(_cfgPath + 'cfg.json', 'utf8')) || {}
}
} catch (e) {
// do nth
}
let Cfg = {
get (rote, def = '') {
return lodash.get(cfg, rote, def)
},
set (rote, val) {
lodash.set(cfg, rote, val)
fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t'))
},
del (rote) {
lodash.set(cfg, rote, undefined)
fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t'))
},
scale (pct = 1) {
let scale = Cfg.get('sys.scale', 100)
scale = Math.min(2, Math.max(0.5, scale / 100))
pct = pct * scale
return `style=transform:scale(${pct})`
},
isDisable (e, rote) {
if (Cfg.get(rote, true)) {
return false
}
if (/^#*小飞/.test(e.msg || '')) {
return false
}
return true
}
}
export default Cfg

View File

@@ -1,13 +0,0 @@
import Cfg from './Cfg.js'
import render from './common-lib/render.js'
function sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
export default {
render,
cfg: Cfg.get,
isDisable: Cfg.isDisable,
sleep
}

View File

@@ -1,107 +0,0 @@
import YAML from 'yaml'
import chokidar from 'chokidar'
import fs from 'node:fs'
const Path = process.cwd();
const Plugin_Name = 'xiaofei-plugin'
const Plugin_Path = `${Path}/plugins/${Plugin_Name}`;
class Config {
constructor () {
this.config = {}
/** 监听文件 */
this.watcher = {}
this.ignore = []
}
/**
* @param app 功能
* @param name 配置文件名称
*/
getdefSet (app, name) {
return this.getYaml(app, name, 'defSet')
}
/** 用户配置 */
getConfig (app, name) {
return this.getYaml(app, name, 'config')
}
/**
* 获取配置yaml
* @param app 功能
* @param name 名称
* @param type 默认跑配置-defSet用户配置-config
*/
getYaml (app, name, type) {
let file = this.getFilePath(app, name, type)
let key = `${app}.${name}`
if (this.config[type][key]) return this.config[type][key]
try {
this.config[type][key] = YAML.parse(
fs.readFileSync(file, 'utf8')
)
} catch (error) {
logger.error(`[${app}][${name}] 格式错误 ${error}`)
return false
}
this.watch(file, app, name, type)
return this[type][key]
}
getFilePath (app, name, type) {
if(!this.config[type]){
this.config[type] = {};
}
if(!this.watcher[type]){
this.watcher[type] = {};
}
let config_path = `${Plugin_Path}/${type}/`;
let file = `${config_path}${app}.${name}.yaml`;
try{
if(!fs.existsSync(file)){
let default_file = `${config_path}default/${app}.${name}.yaml`;
fs.copyFileSync(default_file,file);
}
}catch(err){}
return file;
}
/** 监听配置文件 */
watch (file, app, name, type = 'defSet') {
let key = `${app}.${name}`
if (this.watcher[type][key]) return
const watcher = chokidar.watch(file)
watcher.on('change', path => {
delete this[type][key]
logger.mark(`[修改配置文件][${type}][${app}][${name}]`)
if (this[`change_${app}${name}`]) {
this[`change_${app}${name}`]()
}
})
this.watcher[type][key] = watcher
}
save (app, name, type) {
let file = this.getFilePath(app, name, type)
if (lodash.isEmpty(data)) {
fs.existsSync(file) && fs.unlinkSync(file)
} else {
let yaml = YAML.stringify(data)
fs.writeFileSync(file, yaml, 'utf8')
}
}
}
export default new Config()

View File

@@ -1,224 +0,0 @@
import lodash from 'lodash'
import fs from 'fs'
const _path = process.cwd()
const plugin = 'xiaofei-plugin'
const getRoot = (root = '') => {
if (root === 'root' || root === 'yunzai') {
root = `${_path}/`
} else if (!root) {
root = `${_path}/plugins/${plugin}/`
}
return root
}
let Data = {
/*
* 根据指定的path依次检查与创建目录
* */
createDir (path = '', root = '', includeFile = false) {
root = getRoot(root)
let pathList = path.split('/')
let nowPath = root
pathList.forEach((name, idx) => {
name = name.trim()
if (!includeFile && idx <= pathList.length - 1) {
nowPath += name + '/'
if (name) {
if (!fs.existsSync(nowPath)) {
fs.mkdirSync(nowPath)
}
}
}
})
},
/*
* 读取json
* */
readJSON (file = '', root = '') {
root = getRoot(root)
if (fs.existsSync(`${root}/${file}`)) {
try {
return JSON.parse(fs.readFileSync(`${root}/${file}`, 'utf8'))
} catch (e) {
console.log(e)
}
}
return {}
},
/*
* 写JSON
* */
writeJSON (file, data, space = '\t', root = '') {
// 检查并创建目录
Data.createDir(file, root, true)
root = getRoot(root)
delete data._res
return fs.writeFileSync(`${root}/${file}`, JSON.stringify(data, null, space))
},
async getCacheJSON (key) {
try {
let txt = await redis.get(key)
if (txt) {
return JSON.parse(txt)
}
} catch (e) {
console.log(e)
}
return {}
},
async setCacheJSON (key, data, EX = 3600 * 24 * 90) {
await redis.set(key, JSON.stringify(data), { EX })
},
async importModule (file, root = '') {
root = getRoot(root)
if (!/\.js$/.test(file)) {
file = file + '.js'
}
if (fs.existsSync(`${root}/${file}`)) {
try {
let data = await import(`file://${root}/${file}?t=${new Date() * 1}`)
return data || {}
} catch (e) {
console.log(e)
}
}
return {}
},
async importDefault (file, root) {
let ret = await Data.importModule(file, root)
return ret.default || {}
},
async import (name) {
return await Data.importModule(`components/optional-lib/${name}.js`)
},
async importCfg (key) {
let sysCfg = await Data.importModule(`config/system/${key}_system.js`)
let diyCfg = await Data.importModule(`config/${key}.js`)
if (diyCfg.isSys) {
console.error(`miao-plugin: config/${key}.js无效已忽略`)
console.error(`如需配置请复制config/${key}_default.js为config/${key}.js请勿复制config/system下的系统文件`)
diyCfg = {}
}
return {
sysCfg,
diyCfg
}
},
/*
* 返回一个从 target 中选中的属性的对象
*
* keyList : 获取字段列表,逗号分割字符串
* key1, key2, toKey1:fromKey1, toKey2:fromObj.key
*
* defaultData: 当某个字段为空时会选取defaultData的对应内容
* toKeyPrefix返回数据的字段前缀默认为空。defaultData中的键值无需包含toKeyPrefix
*
* */
getData (target, keyList = '', cfg = {}) {
target = target || {}
let defaultData = cfg.defaultData || {}
let ret = {}
// 分割逗号
if (typeof (keyList) === 'string') {
keyList = keyList.split(',')
}
lodash.forEach(keyList, (keyCfg) => {
// 处理通过:指定 toKey & fromKey
let _keyCfg = keyCfg.split(':')
let keyTo = _keyCfg[0].trim()
let keyFrom = (_keyCfg[1] || _keyCfg[0]).trim()
let keyRet = keyTo
if (cfg.lowerFirstKey) {
keyRet = lodash.lowerFirst(keyRet)
}
if (cfg.keyPrefix) {
keyRet = cfg.keyPrefix + keyRet
}
// 通过Data.getVal获取数据
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg)
})
return ret
},
getVal (target, keyFrom, defaultValue) {
return lodash.get(target, keyFrom, defaultValue)
},
// 异步池,聚合请求
async asyncPool (poolLimit, array, iteratorFn) {
const ret = [] // 存储所有的异步任务
const executing = [] // 存储正在执行的异步任务
for (const item of array) {
// 调用iteratorFn函数创建异步任务
const p = Promise.resolve().then(() => iteratorFn(item, array))
// 保存新的异步任务
ret.push(p)
// 当poolLimit值小于或等于总任务个数时进行并发控制
if (poolLimit <= array.length) {
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
executing.push(e) // 保存正在执行的异步任务
if (executing.length >= poolLimit) {
// 等待较快的任务执行完成
await Promise.race(executing)
}
}
}
return Promise.all(ret)
},
// sleep
sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
},
// 获取默认值
def () {
for (let idx in arguments) {
if (!lodash.isUndefined(arguments[idx])) {
return arguments[idx]
}
}
},
// 循环字符串回调
eachStr: (arr, fn) => {
if (lodash.isString(arr)) {
arr = arr.replace(/\s*(;||、|)\s*/, ',')
arr = arr.split(',')
} else if (lodash.isNumber(arr)) {
arr = [arr.toString()]
}
lodash.forEach(arr, (str, idx) => {
if (!lodash.isUndefined(str)) {
fn(str.trim ? str.trim() : str, idx)
}
})
},
regRet (reg, txt, idx) {
if (reg && txt) {
let ret = reg.exec(txt)
if (ret && ret[idx]) {
return ret[idx]
}
}
return false
}
}
export default Data

View File

@@ -1,100 +0,0 @@
import fs from 'fs'
import lodash from 'lodash'
import cfg from '../../../lib/config/config.js'
const Plugin_Path = `${process.cwd()}/plugins/xiaofei-plugin`;
const README_path = `${Plugin_Path}/README.md`
const CHANGELOG_path = `${Plugin_Path}/CHANGELOG.md`
const yunzai_ver = `v${cfg.package.version}`;
let logs = {}
let changelogs = []
let currentVersion
let versionCount = 6
const getLine = function (line) {
line = line.replace(/(^\s*\*|\r)/g, '')
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1')
line = line.replace(/`\s*/g, '</span>')
line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '<span class="strong">$1')
line = line.replace(/\*\*\s*/g, '</span>')
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>')
return line
}
try {
if (fs.existsSync(CHANGELOG_path)) {
logs = fs.readFileSync(CHANGELOG_path, 'utf8') || ''
logs = logs.replace(/\t/g,' ').split('\n')
let temp = {};
let lastLine = {}
lodash.forEach(logs, (line) => {
if (versionCount <= -1) {
return false
}
let versionRet = /^#\s*([0-9a-zA-Z\\.~\s]+?)\s*$/.exec(line.trim())
if (versionRet && versionRet[1]) {
let v = versionRet[1].trim()
if (!currentVersion) {
currentVersion = v
} else {
changelogs.push(temp)
if (/0\s*$/.test(v) && versionCount > 0) {
//versionCount = 0
versionCount--
} else {
versionCount--
}
}
temp = {
version: v,
logs: []
}
} else {
if (!line.trim()) {
return
}
if (/^\*/.test(line)) {
lastLine = {
title: getLine(line),
logs: []
}
if(!temp.logs){
temp = {
version: line,
logs: []
}
}
temp.logs.push(lastLine)
} else if (/^\s{2,}\*/.test(line)) {
lastLine.logs.push(getLine(line))
}
}
})
}
} catch (e) {
logger.error(e);
// do nth
}
try{
if(fs.existsSync(README_path)){
let README = fs.readFileSync(README_path, 'utf8') || ''
let reg = /版本:(.*)/.exec(README)
if(reg){
currentVersion = reg[1]
}
}
}catch(err){}
let Version = {
get ver () {
return currentVersion;
},
get yunzai(){
return yunzai_ver;
},
get logs(){
return changelogs;
}
}
export default Version

View File

@@ -1,15 +0,0 @@
{
"sys": {
"help": true,
"scale": 100
},
"char": {
"wife": false,
"char": true
},
"wiki": {
"abyss": true,
"wiki": false,
"stat": true
}
}

View File

@@ -1,51 +0,0 @@
import { Data, Version, Plugin_Name} from '../index.js'
import Cfg from '../Cfg.js'
import fs from 'fs'
import puppeteer from '../../../../lib/puppeteer/puppeteer.js'
const _path = process.cwd()
export default async function (path, params, cfg) {
let [app, tpl] = path.split('/')
let { e } = cfg
let layoutPath = process.cwd() + `/plugins/${Plugin_Name}/resources/common/layout/`
let resPath = `../../../../../plugins/${Plugin_Name}/resources/`
Data.createDir(`data/html/${Plugin_Name}/${app}/${tpl}`, 'root')
let data = {
...params,
_plugin: Plugin_Name,
saveId: params.saveId || params.save_id || tpl,
tplFile: `./plugins/${Plugin_Name}/resources/${app}/${tpl}.html`,
pluResPath: resPath,
_res_path: resPath,
_layout_path: layoutPath,
_tpl_path: process.cwd() + `/plugins/${Plugin_Name}/resources/common/tpl/`,
defaultLayout: layoutPath + 'default.html',
elemLayout: layoutPath + 'elem.html',
pageGotoParams: {
waitUntil: 'networkidle0'
},
sys: {
scale: Cfg.scale(cfg.scale || 1),
copyright: `Created By Yunzai-Bot<span class="version">${Version.yunzai}</span> & xiaofei-Plugin<span class="version">${Version.ver}</span>`
},
quality: 100
}
if (process.argv.includes('web-debug')) {
// debug下保存当前页面的渲染数据方便模板编写与调试
// 由于只用于调试开发者只关注自己当时开发的文件即可暂不考虑app及plugin的命名冲突
let saveDir = _path + '/data/ViewData/'
if (!fs.existsSync(saveDir)) {
fs.mkdirSync(saveDir)
}
let file = saveDir + tpl + '.json'
data._app = app
fs.writeFileSync(file, JSON.stringify(data))
}
let base64 = await puppeteer.screenshot(`${Plugin_Name}/${app}/${tpl}`, data)
let ret = true
if (base64) {
ret = await e.reply(base64)
}
return cfg.retMsgId ? ret : true
}

View File

@@ -1,10 +0,0 @@
const Path = process.cwd();
const Plugin_Name = 'xiaofei-plugin'
const Plugin_Path = `${Path}/plugins/${Plugin_Name}`;
import Version from './Version.js'
import Data from './Data.js'
import Cfg from './Cfg.js'
import Common from './Common.js'
import Config from './Config.js'
export { Cfg, Common, Config, Data, Version, Path, Plugin_Name, Plugin_Path}

View File

@@ -1,87 +1,4 @@
import plugin from '../../lib/plugins/plugin.js'
import gsCfg from '../genshin/model/gsCfg.js'
import { segment } from 'oicq'
import fs from 'node:fs'
import common from '../../lib/common/common.js'
export class curve extends plugin {
constructor() {
super({
name: 'nga线',
dsc: '线',
event: 'message',
priority: 500,
rule: [
{
reg: '^#*(.*)线()?$',
fnc: 'curve'
},
]
})
this.path = './resources/线'
}
//
async init() {
if (!fs.existsSync(this.path)) {
fs.mkdirSync(this.path)
}
}
async curve() {
let role = {}
if (/#?线/.test(this.e.msg)) role.name = "帮助"
else role = gsCfg.getRole(this.e.msg, '线')
if (!role) return
/** */
if (['10000005', '10000007', '20000000'].includes(String(role.roleId))) {
if (!['', '', '', ''].includes(role.alias)) {
await this.e.reply('线线线线')
return
} else {
role.name = role.alias
}
}
if (!image[role.name]) return this.e.reply("暂时无该角色收益曲线~>_<")
this.imgPath = `${this.path}/${role.name}.png`
if (!fs.existsSync(this.imgPath)) {
await this.getImg(role.name)
}
if (fs.existsSync(this.imgPath)) {
await this.e.reply(segment.image(this.imgPath));
return true;
}
}
//
async getImg(name) {
logger.mark(`${this.e.logFnc} ${name}`)
if (!await common.downFile(image[name], this.imgPath)) {
return false
}
logger.mark(`${this.e.logFnc} ${name}`)
return true
}
}
const image = {
{
"帮助": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-j5voXxZ96T3cS1di-q9.png",
"烟绯": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-gz71XxZ96T3cS1di-q9.png",

17
config/noticecfg.json Normal file
View File

@@ -0,0 +1,17 @@
{
"privateMessage": true,
"groupMessage": false,
"grouptemporaryMessage": true,
"groupRecall": true,
"PrivateRecall": true,
"friendRequest": true,
"groupInviteRequest": true,
"groupAdminChange": true,
"friendNumberChange": true,
"groupNumberChange": true,
"groupMemberNumberChange": false,
"flashPhoto": true,
"botBeenBanned": true,
"notificationsAll": false,
"deltime": 600
}

View File

@@ -1,3 +0,0 @@
此目录为系统配置目录
请勿修改此目录下的文件,否则可能导致工作不正常
如需配置可配置上级目录复制对应_default.js 文件进行配置

View File

@@ -1,10 +1,13 @@
import fs from 'node:fs'
import common from '../../lib/common/common.js'
const files = fs.readdirSync('./plugins/suiyue/apps').filter(file => file.endsWith('.js'))
const files = fs.readdirSync('./plugins/yenai-plugin/apps').filter(file => file.endsWith('.js'))
let ret = []
logger.info('-----------')
logger.info('椰奶插件初始化~')
logger.info('-----------')
files.forEach((file) => {
ret.push(import(`./apps/${file}`))
})
@@ -20,23 +23,6 @@ for (let i in files) {
logger.error(ret[i].reason)
continue
}
apps[name] = ret[i].value[name]
apps[name] = ret[i].value[Object.keys(ret[i].value)[0]]
}
logger.info('-----------')
logger.info('加载碎月插件完成..[v1.0.0]')
logger.info('-----------')
let restart = await redis.get(`Yunzai:suiyue:restart`);
if (restart) {
restart = JSON.parse(restart);
if (restart.isGroup) {
Bot.pickGroup(restart.id).sendMsg(`重启成功`);
} else {
common.relpyPrivate(restart.id, `重启成功`);
}
redis.del(`Yunzai:suiyue:restart`);
}
export { apps }
export { apps }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB