diff --git a/apps/fun.js b/apps/fun.js index bfd17d5..8b82648 100644 --- a/apps/fun.js +++ b/apps/fun.js @@ -274,6 +274,7 @@ export class example extends plugin { let res = await fetch(api).then(res => res.json()).catch(err => console.log(err)) if (!res) return e.reply("接口失效") if (res.code != 200) return e.reply(`请求错误!,错误码:${res.code}`) + if (lodash.isEmpty(res.data)) return e.reply(`请求错误!无数据,请稍后再试`) let msg = []; for (let i of res.data) { msg.push(i.title); diff --git a/apps/gp_admin.js b/apps/gp_admin.js index e8a1c16..dfb5a87 100644 --- a/apps/gp_admin.js +++ b/apps/gp_admin.js @@ -412,6 +412,8 @@ export class Basics extends plugin { //修改头衔 async adminsetTitle(e) { + if (e.message.length < 2) return + if (e.message[1].type != 'at') return if (!e.group.is_owner) return e.reply("做不到,怎么想我都做不到吧!!!", true) @@ -424,6 +426,7 @@ export class Basics extends plugin { e.reply(`已经把这个小可爱的头衔设置为${e.message[2].text}辣`) } + //申请头衔 async SetGroupSpecialTitle(e) { if (!e.group.is_owner) return e.reply("做不到,怎么想我都做不到吧!!!", true) diff --git a/apps/groupverify.js b/apps/groupverify.js new file mode 100644 index 0000000..2a33b37 --- /dev/null +++ b/apps/groupverify.js @@ -0,0 +1,266 @@ +import plugin from '../../../lib/plugins/plugin.js' +import { segment } from "oicq"; +import common from '../../../lib/common/common.js' +import cfg from '../../../lib/config/config.js' +import { Config } from "../components/index.js" +import YamlReader from '../model/YamlReader.js' +//全局 +let temp = {}; +const ops = ["+", "-"]; +const Path = process.cwd(); +export class NEWCMD extends plugin { + constructor() { + super({ + name: 'cmd', + dsc: '重新验证和绕过验证', + event: 'message.group', + priority: 5, + rule: [ + { + reg: '^#重新验证.*$', + fnc: 'cmdReverify' + }, + { + reg: '^#绕过验证.*$', + fnc: 'cmdPass' + }, + { + reg: '^#开启验证$', + fnc: 'openverify' + }, + { + reg: '^#关闭验证$', + fnc: 'closeverify' + }, + { + reg: '^#切换验证模式$', + fnc: 'setmode' + } + ] + }) + this.verifypath = `./plugins/yenai-plugin/config/config/groupverify.yaml`; + } + //重新验证 + async cmdReverify(e) { + let verifycfg = Config.verifycfg + + if (!e.group.is_admin && !e.group.is_owner) return e.reply("做不到,怎么想我都做不到吧!!!", true); + + if (!verifycfg.openGroup.includes(e.group_id)) return e.reply("当前群未开启验证哦~", true); + + if (!e.isMaster && !e.member.is_owner && !e.member.is_admin) return e.reply("❎ 该命令仅限管理员可用", true); + + let qq = e.message[0].text.replace(/#|重新验证/g, "").trim(); + + if (e.message[1]) { + qq = e.message[1].qq; + } else { + qq = qq.match(/[1-9]\d*/g); + } + if (!(/\d{5,}/.test(qq))) return e.reply("❎ 请输入正确的QQ号"); + + if (qq == Bot.uin) return + + if (cfg.masterQQ.includes(qq)) return e.reply("❎ 该命令对机器人管理员无效"); + + if (temp[qq + e.group_id]) return e.reply("❎ 目标群成员处于验证状态"); + + await verify(qq, e.group_id, e) + } + //绕过验证 + async cmdPass(e) { + let verifycfg = Config.verifycfg + + if (!e.group.is_admin && !e.group.is_owner) return e.reply("做不到,怎么想我都做不到吧!!!", true); + + if (!verifycfg.openGroup.includes(e.group_id)) return e.reply("当前群未开启验证哦~", true); + + if (!e.isMaster && !e.member.is_owner && !e.member.is_admin) return e.reply("❎ 该命令仅限管理员可用", true); + + let qq = e.message[0].text.replace(/#|绕过验证/g, "").trim(); + + if (e.message[1]) { + qq = e.message[1].qq; + } else { + qq = qq.match(/[1-9]\d*/g); + } + if (!(/\d{5,}/.test(qq))) return e.reply("❎ 请输入正确的QQ号"); + + if (qq == Bot.uin) return + + if (!temp[qq + e.group_id]) return e.reply("❎ 目标群成员当前无需验证"); + + clearTimeout(temp[qq + e.group_id].kickTimer); + + clearTimeout(temp[qq + e.group_id].remindTimer); + + delete temp[qq + e.group_id]; + + return await e.reply(verifycfg.SuccessMsgs[e.group_id] || verifycfg.SuccessMsgs[0] || "✅ 验证成功,欢迎入群"); + } + + //开启验证 + async openverify(e) { + new YamlReader(this.verifypath).addIn('openGroup', e.group_id) + e.reply("✅ 已开启本群验证") + } + + //关闭验证 + async closeverify(e) { + let verifycfg = Config.verifycfg + let key = verifycfg.openGroup.indexOf(e.group_id) + if (key == -1) return e.reply("❎ 本群暂未开启验证") + new YamlReader(this.verifypath).delete(`openGroup.${key}`) + e.reply("✅ 已关闭本群验证") + } + //切换验证模式 + async setmode(e) { + let verifycfg = Config.verifycfg + let value = verifycfg.mode == "模糊" ? "精确" : "模糊" + new YamlReader(this.verifypath).set(`mode`, value) + e.reply(`✅ 已切换验证模式为${value}验证`) + } +} + + + + + +//监听事件 +Bot.on("notice.group.increase", async (e) => { + let verifycfg = Config.verifycfg + + if (!verifycfg.openGroup.includes(e.group_id)) return; + + if (!e.group.is_admin && !e.group.is_owner) return; + + if (e.user_id == Bot.uin) return + + if (cfg.masterQQ.includes(e.user_id)) return + + await verify(e.user_id, e.group_id, e) + + return true; +}) + + +Bot.on('message.group', async (e) => { + let verifycfg = Config.verifycfg + + if (!verifycfg.openGroup.includes(e.group_id)) return; + + if (!e.group.is_admin && !e.group.is_owner) return; + + if (!temp[e.user_id + e.group_id]) return; + + const { verifyCode, kickTimer, remindTimer } = temp[e.user_id + e.group_id]; + + const { nums, operator } = temp[e.user_id + e.group_id]; + + const isAccurateModeOK = verifycfg.mode === "精确" && e.raw_message == verifyCode; + + const isVagueModeOK = verifycfg.mode === "模糊" && e.raw_message.includes(verifyCode); + + const isOK = isAccurateModeOK || isVagueModeOK; + + if (isOK) { + delete temp[e.user_id + e.group_id]; + clearTimeout(kickTimer); + clearTimeout(remindTimer); + return await e.reply(verifycfg.SuccessMsgs[e.group_id] || verifycfg.SuccessMsgs[0] || "✅ 验证成功,欢迎入群"); + } else { + temp[e.user_id + e.group_id].remainTimes -= 1; + + const { remainTimes } = temp[e.user_id + e.group_id]; + + if (remainTimes > 0) { + await e.group.recallMsg(e.message_id) + + const msg = `❎ 验证失败,你还有「${remainTimes}」次机会,请发送「${nums[0]} ${operator} ${nums[1]}」的运算结果`; + return await e.reply([segment.at(e.user_id), msg]); + } + clearTimeout(kickTimer); + clearTimeout(remindTimer); + await e.reply([segment.at(e.user_id), `验证失败,请重新申请`]); + delete temp[e.user_id + e.group_id]; + return await e.group.kickMember(e.user_id, true) + } +}) + + +Bot.on('notice.group.decrease', async (e) => { + let verifycfg = Config.verifycfg + if (!e.group.is_admin && !e.group.is_owner) return; + + if (!temp[e.user_id + e.group_id]) return; + + clearTimeout(temp[e.user_id + e.group_id].kickTimer); + + clearTimeout(temp[e.user_id + e.group_id].remindTimer); + + delete temp[e.user_id + e.group_id]; + + return e.reply(`「${e.user_id}」主动退群,验证流程结束`); +}) + + + +async function verify(user_id, group_id, e) { + let verifycfg = Config.verifycfg + let { range } = verifycfg + if (!e.group.is_admin && !e.group.is_owner) return; + const remainTimes = verifycfg.times; + + const operator = ops[getRndInteger(0, 1)] + + let [m, n] = [getRndInteger(range.min, range.max), getRndInteger(range.min, range.max)] + while (m == n) { + n = Math.floor(Math.random() * (range.max - range.min + 1)) + range.min; + } + + [m, n] = [m >= n ? m : n, m >= n ? n : m]; + + const verifyCode = String(operator === "-" ? m - n : m + n); + logger.info(`[验证]答案:${verifyCode}`) + const kickTimer = setTimeout(async () => { + e.reply([segment.at(user_id), " 验证超时,移出群聊,请重新申请"]); + + delete temp[user_id + group_id]; + + clearTimeout(kickTimer); + + return await e.group.kickMember(user_id, true) + + }, verifycfg.time * 1000); + + const shouldRemind = verifycfg.remindAtLastMinute && verifycfg.time >= 120; + + const remindTimer = setTimeout(async () => { + + if (shouldRemind && temp[user_id + group_id].remindTimer) { + + const msg = ` 验证仅剩最后一分钟,请发送「${m}${operator}${n}」的运算结果,否则将会被移出群聊`; + + await e.reply([segment.at(user_id), msg]); + } + clearTimeout(remindTimer); + + }, Math.abs(verifycfg.time * 1000 - 60000)); + + temp[user_id + group_id] = { + remainTimes, + nums: [m, n], + operator, + verifyCode, + kickTimer, + remindTimer + }; + + const msg = ` 欢迎,请在「${verifycfg.time}」秒内发送「${m}${operator}${n}」的运算结果,否则将会被移出群聊`; + await common.sleep(600); + return await e.reply([segment.at(user_id), msg]); +} +//随机数 +function getRndInteger(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} \ No newline at end of file diff --git a/apps/setu.js b/apps/setu.js index b4e935d..3d75b7f 100644 --- a/apps/setu.js +++ b/apps/setu.js @@ -382,7 +382,6 @@ export class sese extends plugin { if (e.isGroup) { //获取CD if (cfgs[e.group_id]) { - time = cfgs[e.group_id].recall cd = cfgs[e.group_id].cd } diff --git a/components/Config.js b/components/Config.js index 3a72ef8..cf9a9c4 100644 --- a/components/Config.js +++ b/components/Config.js @@ -43,6 +43,17 @@ class Config { get Notice() { return this.getNotice() } + //进群验证配置 + get verifycfg() { + return this.getverifycfg(); + } + + + getverifycfg() { + let config = this.getConfig("groupverify") + let def = this.getdefSet("groupverify") + return { ...def, ...config } + } /** 通知配置 */ getNotice() { diff --git a/config/config/groupverify.yaml b/config/config/groupverify.yaml new file mode 100644 index 0000000..53ca6c7 --- /dev/null +++ b/config/config/groupverify.yaml @@ -0,0 +1,19 @@ +#开启的群聊 +openGroup: [] +# 如需要分群,请按照下列格式添加 <以群号为字段> 的成功提示即可,0 字段代表默认回复 +SuccessMsgs: + 254974507: ✅ 验证成功,欢迎入群,群里有非常多的大佬给你透哦~~ + 0: ✅ 验证成功,欢迎入群 + +# 答案验证模式,可选:精确、模糊 +mode: 精确 +# 最多允许尝试次数 +times: 7 +# 是否开启最后一分钟提醒(仅在超时时长大于等于 120 秒时有效,true 开启,false 关闭) +remindAtLastMinute: true +# 超时时长(秒),建议至少一分钟(60 秒) +time: 300 +# 随机算式的数字的随机范围 +range: + min: 10 + max: 100 diff --git a/config/default_config/groupverify.yaml b/config/default_config/groupverify.yaml new file mode 100644 index 0000000..53ca6c7 --- /dev/null +++ b/config/default_config/groupverify.yaml @@ -0,0 +1,19 @@ +#开启的群聊 +openGroup: [] +# 如需要分群,请按照下列格式添加 <以群号为字段> 的成功提示即可,0 字段代表默认回复 +SuccessMsgs: + 254974507: ✅ 验证成功,欢迎入群,群里有非常多的大佬给你透哦~~ + 0: ✅ 验证成功,欢迎入群 + +# 答案验证模式,可选:精确、模糊 +mode: 精确 +# 最多允许尝试次数 +times: 7 +# 是否开启最后一分钟提醒(仅在超时时长大于等于 120 秒时有效,true 开启,false 关闭) +remindAtLastMinute: true +# 超时时长(秒),建议至少一分钟(60 秒) +time: 300 +# 随机算式的数字的随机范围 +range: + min: 10 + max: 100 diff --git a/config/system/gpadmin_system.js b/config/system/gpadmin_system.js index d8df047..354368f 100644 --- a/config/system/gpadmin_system.js +++ b/config/system/gpadmin_system.js @@ -101,6 +101,33 @@ export const helpList = [{ "icon": 5 }, ] +}, { + "group": "进群验证(更多设置请在groupverify.yaml进行设置)", + "list": [ + { + "title": "#开启验证", + "desc": "开启本群验证", + "icon": 4 + }, + { + "title": "#关闭验证", + "desc": "关闭本群验证", + "icon": 15 + }, + { + "title": "#重新验证 <@群员>", + "desc": "重新发起验证", + "icon": 1 + }, { + "title": "#绕过验证 <@群员>", + "desc": "绕过本次验证", + "icon": 3 + }, + { + "title": "#切换验证模式", + "desc": "更换答案匹配模式", + "icon": 2 + },] }, { "group": "Bot为群主可用", "auth": "master", diff --git a/model/YamlReader.js b/model/YamlReader.js index cd604fe..497dab3 100644 --- a/model/YamlReader.js +++ b/model/YamlReader.js @@ -61,7 +61,11 @@ export default class YamlReader { this.document.deleteIn(keyPath.split('.')) this.save() } - + //数组添加数据 + addIn(keyPath, value) { + this.document.addIn(keyPath.split('.'), value) + this.save() + } /** * 设置 document 的数据(递归式) * @param data 要写入的数据