🎨 优化文件结构 修复删群公告序号无效, close #112

This commit is contained in:
yeyang
2024-04-11 20:32:37 +08:00
parent 6fdf3ac96e
commit 432b108e27
12 changed files with 507 additions and 427 deletions

View File

@@ -9,10 +9,10 @@ import md5 from "md5"
let Vote = {}
let time = 180 // 投票超时时间 单位秒
export class NewGroupVerify extends plugin {
export class GroupVoteBan extends plugin {
constructor() {
super({
name: "椰奶投票禁言",
name: "椰奶群管-投票禁言",
dsc: "投票禁言某人",
event: "message.group",
priority: 5000,

View File

@@ -1,12 +1,9 @@
import _ from "lodash"
import moment from "moment"
import { Config } from "../../components/index.js"
import { Time_unit } from "../../constants/other.js"
import { GroupAdmin as Ga, GroupBannedWords, QQApi, common, puppeteer } from "../../model/index.js"
import { GroupAdmin as Ga, GroupBannedWords, common } from "../../model/index.js"
import { cronValidate, translateChinaNum } from "../../tools/index.js"
// API请求错误文案
const API_ERROR = "❎ 出错辣,请稍后重试"
// 正则
const Numreg = "[零一壹二两三四五六七八九十百千万亿\\d]+"
const TimeUnitReg = Object.keys(Time_unit).join("|")
@@ -20,7 +17,7 @@ const redisTask = await Ga.getRedisMuteTask() || false
export class GroupAdmin extends plugin {
constructor() {
super({
name: "椰奶群管",
name: "椰奶群管-基础",
event: "message.group",
priority: 500,
rule: [
@@ -44,18 +41,6 @@ export class GroupAdmin extends plugin {
reg: "^#(设置|取消)管理(\\d+)?$",
fnc: "SetAdmin"
},
{
reg: "^#发群公告",
fnc: "AddAnnounce"
},
{
reg: "^#删群公告(\\d+)$",
fnc: "DelAnnounce"
},
{
reg: "^#查群公告$",
fnc: "GetAnnounce"
},
{
reg: "^#(修改|设置)头衔",
fnc: "adminsetTitle"
@@ -64,22 +49,6 @@ export class GroupAdmin extends plugin {
reg: "^#申请头衔",
fnc: "SetGroupSpecialTitle"
},
{
reg: "^#(查)?(幸运)?字符(列表)?$",
fnc: "qun_luckylist"
},
{
reg: "^#抽(幸运)?字符$",
fnc: "qun_lucky"
},
{
reg: "^#替换(幸运)?字符(\\d+)$",
fnc: "qun_luckyuse"
},
{
reg: "^#(开启|关闭)(幸运)?字符$",
fnc: "qun_luckyset"
},
{
reg: "^#(获取|查看)?禁言列表$",
fnc: "Mutelist"
@@ -116,26 +85,6 @@ export class GroupAdmin extends plugin {
reg: "^#(查看|获取)?群?发言(榜单|排行)((7|七)天)?",
fnc: "SpeakRank"
},
{
reg: "^#?(谁|哪个吊毛|哪个屌毛|哪个叼毛)是龙王$",
fnc: "dragonKing"
},
{
reg: "^#群星级$",
fnc: "Group_xj"
},
{
reg: "^#群数据((7|七)天)?$",
fnc: "groupData"
},
{
reg: "^#今日打卡$",
fnc: "DaySigned"
},
{
reg: "^#((今|昨|前|明|后)天|\\d{4}-\\d{1,2}-\\d{1,2})谁生日$",
fnc: "groupBirthday"
},
{
reg: "^#?(开启|关闭)加群通知$",
fnc: "handleGroupAdd"
@@ -144,14 +93,6 @@ export class GroupAdmin extends plugin {
reg: "^#?(加|设|移)精$",
fnc: "essenceMessage"
},
{
reg: "^#?群管(加|删)白(名单)?",
fnc: "whiteQQ"
},
{
reg: "^#?(开启|关闭)白名单(自动)?解禁",
fnc: "noBan"
},
{
reg: Autisticreg, // 我要自闭
fnc: "Autistic"
@@ -235,44 +176,6 @@ export class GroupAdmin extends plugin {
type ? e.reply(`✅ 已经把「${name}」设置为管理啦!!`) : e.reply(`✅ 已取消「${name}」的管理`)
}
// 发群公告
async AddAnnounce(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
// 获取发送的内容
let msg = e.msg.replace(/#|发群公告/g, "").trim()
if (!msg) return e.reply("❎ 公告不能为空")
let result = await new QQApi(e).setAnnounce(e.group_id, msg)
if (!result) return e.reply(API_ERROR)
if (result.ec != 0) {
e.reply("❎ 发送失败\n" + JSON.stringify(result, null, "\t"))
}
}
// 查群公告
async GetAnnounce(e) {
let res = await new QQApi(e).getAnnouncelist(e.group_id)
if (!res) return e.reply(API_ERROR)
return e.reply(res)
}
// 删群公告
async DelAnnounce(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let msg = e.msg.replace(/#|删群公告/, "").trim()
if (!msg) return e.reply("❎ 序号不可为空")
let result = await new QQApi(e).delAnnounce(e.group_id, msg)
if (!result) return e.reply(API_ERROR)
if (result.ec == 0) {
e.reply(`✅ 已删除「${result.text}`)
} else {
e.reply("❎ 删除失败\n" + JSON.stringify(result, null, "\t"))
}
}
// 修改头衔
async adminsetTitle(e) {
if (!common.checkPermission(e, "master", "owner")) return
@@ -313,58 +216,6 @@ export class GroupAdmin extends plugin {
e.reply(`✅ 已将你的头衔更换为「${Title}`, true)
}
// 字符列表
async qun_luckylist(e) {
let data = await new QQApi(e).luckylist(e.group_id)
if (!data) return e.reply(API_ERROR)
if (data.retcode != 0) return e.reply("❎ 获取数据失败\n" + JSON.stringify(data))
let msg = data.data.word_list.map((item, index) => {
let { wording, word_id, word_desc } = item.word_info
return `${word_id}:${wording}\n寓意:${word_desc}`
}).join("\n")
e.reply(msg)
}
// 抽幸运字符
async qun_lucky(e) {
let res = await new QQApi(e).drawLucky(e.group_id)
if (!res) return e.reply(API_ERROR)
if (res.retcode == 11004) return e.reply("❎ 今天已经抽过了,明天再来抽取吧")
if (res.retcode != 0) return e.reply("❎ 错误\n" + JSON.stringify(res.data))
if (res.data.word_info) {
let { wording, word_desc } = res.data.word_info.word_info
e.reply(`恭喜您抽中了${wording}\n寓意为:${word_desc}`)
} else {
e.reply("恭喜您抽了中了个寂寞")
}
}
// 替换幸运字符
async qun_luckyuse(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let id = e.msg.replace(/#|替换(幸运)?字符/g, "")
let res = await new QQApi(e).equipLucky(e.group_id, id)
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply("❎替换失败\n" + JSON.stringify(res))
e.reply("✅ OK")
}
// 开启或关闭群字符
async qun_luckyset(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let res = await new QQApi(e).swichLucky(e.group_id, /开启/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode == 11111) return e.reply("❎ 重复开启或关闭")
if (res.retcode != 0) return e.reply("❎ 错误\n" + JSON.stringify(res))
e.reply("✅ OK")
}
// 获取禁言列表
async Mutelist(e) {
new Ga(e).getMuteList(e.group_id, true)
@@ -519,163 +370,6 @@ export class GroupAdmin extends plugin {
: e.reply(`❎ 该群定时${type ? "禁言" : "解禁"}已存在不可重复设置`)
}
// 谁是龙王
async dragonKing(e) {
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/interactive/honorlist?gc=${e.group_id}&type=1&_wv=3&_wwv=129`,
headers: { Cookie: this.Bot.cookies["qun.qq.com"] },
font: true
})
if (screenshot) return e.reply(screenshot)
// 数据版
let res = await new QQApi(e).dragon(e.group_id)
if (!res) return e.reply(API_ERROR)
e.reply([
`本群龙王:${res.nick}`,
segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${res.uin}`),
`蝉联天数:${res.avatar_size}`
])
}
/**
* 群星级
* @param e
*/
async Group_xj(e) {
let screenshot = await puppeteer.Webpage({
url: `https://qqweb.qq.com/m/business/qunlevel/index.html?gc=${e.group_id}&from=0&_wv=1027`,
cookie: common.getck("qun.qq.com", this.Bot, true),
emulate: "QQTheme",
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后发送数据
let result = await new QQApi(e).getCreditLevelInfo(e.group_id)
if (!result) return e.reply(API_ERROR)
if (result.ec != 0) return e.reply("❎ 查询错误\n" + JSON.stringify(result))
let { uiGroupLevel, group_name, group_uin } = result.info
let str = "⭐"
str = str.repeat(uiGroupLevel)
e.reply([
`群名:${group_name}\n`,
`群号:${group_uin}\n`,
`群星级:${str}`
])
}
// 群发言榜单
async SpeakRank(e) {
if (!common.checkPermission(e, "all", "admin")) return
// 图片截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/m/qun/activedata/speaking.html?gc=${e.group_id}&time=${/(7|)/.test(e.msg) ? 1 : 0}`,
headers: { Cookie: this.Bot.cookies["qun.qq.com"] },
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后发送文字数据
let res = await new QQApi(e).SpeakRank(e.group_id, /(7|七)天/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply("❎ 未知错误\n" + JSON.stringify(res))
let msg = _.take(res.data.speakRank.map((item, index) =>
`${index + 1}:${item.nickname}-${item.uin}\n连续活跃${item.active}天:发言${item.msgCount}`
), 10).join("\n")
e.reply(msg)
}
// 今日打卡
async DaySigned(e) {
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/v2/signin/list?gc=${e.group_id}`,
emulate: "iPhone 6",
cookie: common.getck("qun.qq.com", this.Bot, true),
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后使用接口
let res = await new QQApi(e).signInToday(e.group_id)
if (!res) return e.reply(API_ERROR)
if (res.retCode != 0) return e.reply("❎ 未知错误\n" + JSON.stringify(res))
let list = res.response.page[0]
if (list.total == 0) return e.reply("❎ 今天还没有人打卡")
// 发送消息
let msg = list.infos.map((item, index) => `${index + 1}:${item.uidGroupNick}-${item.uid}\n打卡时间:${moment(item.signedTimeStamp * 1000).format("YYYY-MM-DD HH:mm:ss")}`).join("\n")
e.reply(msg)
}
// 查看某天谁生日
async groupBirthday(e) {
let date = e.msg.match(/^#?(今天|昨天|明天|后天|\d{4}-\d{1,2}-\d{1,2})谁生日$/)[1]
if (date == "昨天") {
date = moment().subtract(1, "days").format("YYYY-MM-DD")
} else if (date == "前天") {
date = moment().subtract(2, "days").format("YYYY-MM-DD")
} else if (date == "明天") {
date = moment().add(1, "days").format("YYYY-MM-DD")
} else if (date == "后天") {
date = moment().add(2, "days").format("YYYY-MM-DD")
} else if (date == "今天") {
date = moment().format("YYYY-MM-DD")
}
e.reply(
await puppeteer.Webpage({
url: `https://qun.qq.com/qqweb/m/qun/calendar/detail.html?_wv=1031&_bid=2340&src=3&gc=${e.group_id}&type=2&date=${date}`,
cookie: common.getck("qun.qq.com", this.Bot, true),
emulate: "iPhone 6",
font: true
})
)
}
// 群数据
async groupData(e) {
if (!common.checkPermission(e, "all", "admin")) return
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/m/qun/activedata/active.html?_wv=3&_wwv=128&gc=${e.group_id}&src=2`,
cookie: common.getck("qun.qq.com", this.Bot, true),
click: /(7|七)天/.test(e.msg)
? [
{
selector: "#app > div.tabbar > div.tabbar__time > div.tabbar__time__date",
time: 500
},
{
selector: "#app > div.tabbar > div.tabbar__date-selector > div > div:nth-child(3)",
time: 1000
}
]
: false,
font: true
})
if (screenshot) return e.reply(screenshot)
// 数据
let res = await new QQApi(e).groupData(e.group_id, /(7|七)天/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply(res.msg || JSON.stringify(res))
let { groupInfo, activeData, msgInfo, joinData, exitData, applyData } = res.data
e.reply(
[
`${groupInfo.groupName}(${groupInfo.groupCode})${/(7|)/.test(e.msg) ? "七天" : "昨天"}的群数据\n`,
"------------消息条数---------\n",
`消息条数:${msgInfo.total}\n`,
"------------活跃人数---------\n",
`活跃人数:${activeData.activeData}\n`,
`总人数:${activeData.groupMember}\n`,
`活跃比例:${activeData.ratio}%\n`,
"-----------加退群人数--------\n",
`申请人数:${joinData.total}\n`,
`入群人数:${applyData.total}\n`,
`退群人数:${exitData.total}\n`
]
)
}
/**
* 开启或关闭加群通知
* @param e
@@ -724,38 +418,4 @@ export class GroupAdmin extends plugin {
await e.group.muteMember(e.user_id, TabooTime * Company)
e.reply("那我就不手下留情了~", true)
}
/**
* 加白名单
*/
async whiteQQ() {
if (!common.checkPermission(this.e, "master")) return
let type = /加/.test(this.e.msg) ? "add" : "del"
let qq = this.e.at || (this.e.msg.match(/\d+/)?.[0] || "")
qq = Number(qq) || String(qq)
if (!qq) return this.reply("❎ 请艾特或输入需要加白的QQ")
const { whiteQQ } = Config.groupAdmin
const isWhite = whiteQQ.includes(qq)
if (isWhite && type === "add") return this.reply("❎ 此人已在群管白名单内")
if (!isWhite && type === "del") return this.reply("❎ 此人未在群管白名单中")
Config.modifyarr("groupAdmin", "whiteQQ", qq, type)
this.reply(`✅ 已${type === "add" ? "加入" : "删除"}${qq}到群管白名单`)
}
async noBan() {
if (!common.checkPermission(this.e, "master")) return
let type = !!/开启/.test(this.e.msg)
const { noBan } = Config.groupAdmin
if (noBan && type) return this.reply("❎ 白名单自动解禁已处于开启状态")
if (!noBan && !type) return this.reply("❎ 白名单自动解禁已处于关闭状态")
Config.modify("groupAdmin", "noBan", type)
this.reply(`✅ 已${type ? "开启" : "关闭"}白名单自动解禁`)
}
}

View File

@@ -0,0 +1,193 @@
import moment from "moment"
import _ from "lodash"
import { QQApi, common, puppeteer } from "../../model/index.js"
// API请求错误文案
const API_ERROR = "❎ 出错辣,请稍后重试"
export class GroupAdminOther extends plugin {
constructor() {
super({
name: "椰奶群管-其他",
event: "message.group",
priority: 500,
rule: [
{
reg: "^#?(谁|哪个吊毛|哪个屌毛|哪个叼毛)是龙王$",
fnc: "dragonKing"
},
{
reg: "^#群星级$",
fnc: "Group_xj"
},
{
reg: "^#群数据((7|七)天)?$",
fnc: "groupData"
},
{
reg: "^#今日打卡$",
fnc: "DaySigned"
},
{
reg: "^#((今|昨|前|明|后)天|\\d{4}-\\d{1,2}-\\d{1,2})谁生日$",
fnc: "groupBirthday"
}
]
})
}
// 谁是龙王
async dragonKing(e) {
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/interactive/honorlist?gc=${e.group_id}&type=1&_wv=3&_wwv=129`,
headers: { Cookie: this.Bot.cookies["qun.qq.com"] },
font: true
})
if (screenshot) return e.reply(screenshot)
// 数据版
let res = await new QQApi(e).dragon(e.group_id)
if (!res) return e.reply(API_ERROR)
e.reply([
`本群龙王:${res.nick}`,
segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${res.uin}`),
`蝉联天数:${res.avatar_size}`
])
}
/**
* 群星级
* @param e
*/
async Group_xj(e) {
let screenshot = await puppeteer.Webpage({
url: `https://qqweb.qq.com/m/business/qunlevel/index.html?gc=${e.group_id}&from=0&_wv=1027`,
cookie: common.getck("qun.qq.com", this.Bot, true),
emulate: "QQTheme",
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后发送数据
let result = await new QQApi(e).getCreditLevelInfo(e.group_id)
if (!result) return e.reply(API_ERROR)
if (result.ec != 0) return e.reply("❎ 查询错误\n" + JSON.stringify(result))
let { uiGroupLevel, group_name, group_uin } = result.info
let str = "⭐"
str = str.repeat(uiGroupLevel)
e.reply([
`群名:${group_name}\n`,
`群号:${group_uin}\n`,
`群星级:${str}`
])
}
// 群发言榜单
async SpeakRank(e) {
if (!common.checkPermission(e, "all", "admin")) return
// 图片截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/m/qun/activedata/speaking.html?gc=${e.group_id}&time=${/(7|)/.test(e.msg) ? 1 : 0}`,
headers: { Cookie: this.Bot.cookies["qun.qq.com"] },
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后发送文字数据
let res = await new QQApi(e).SpeakRank(e.group_id, /(7|七)天/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply("❎ 未知错误\n" + JSON.stringify(res))
let msg = _.take(res.data.speakRank.map((item, index) =>
`${index + 1}:${item.nickname}-${item.uin}\n连续活跃${item.active}天:发言${item.msgCount}`
), 10).join("\n")
e.reply(msg)
}
// 今日打卡
async DaySigned(e) {
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/v2/signin/list?gc=${e.group_id}`,
emulate: "iPhone 6",
cookie: common.getck("qun.qq.com", this.Bot, true),
font: true
})
if (screenshot) return e.reply(screenshot)
// 出错后使用接口
let res = await new QQApi(e).signInToday(e.group_id)
if (!res) return e.reply(API_ERROR)
if (res.retCode != 0) return e.reply("❎ 未知错误\n" + JSON.stringify(res))
let list = res.response.page[0]
if (list.total == 0) return e.reply("❎ 今天还没有人打卡")
// 发送消息
let msg = list.infos.map((item, index) => `${index + 1}:${item.uidGroupNick}-${item.uid}\n打卡时间:${moment(item.signedTimeStamp * 1000).format("YYYY-MM-DD HH:mm:ss")}`).join("\n")
e.reply(msg)
}
// 查看某天谁生日
async groupBirthday(e) {
let date = e.msg.match(/^#?(今天|昨天|明天|后天|\d{4}-\d{1,2}-\d{1,2})谁生日$/)[1]
if (date == "昨天") {
date = moment().subtract(1, "days").format("YYYY-MM-DD")
} else if (date == "前天") {
date = moment().subtract(2, "days").format("YYYY-MM-DD")
} else if (date == "明天") {
date = moment().add(1, "days").format("YYYY-MM-DD")
} else if (date == "后天") {
date = moment().add(2, "days").format("YYYY-MM-DD")
} else if (date == "今天") {
date = moment().format("YYYY-MM-DD")
}
e.reply(
await puppeteer.Webpage({
url: `https://qun.qq.com/qqweb/m/qun/calendar/detail.html?_wv=1031&_bid=2340&src=3&gc=${e.group_id}&type=2&date=${date}`,
cookie: common.getck("qun.qq.com", this.Bot, true),
emulate: "iPhone 6",
font: true
})
)
}
// 群数据
async groupData(e) {
if (!common.checkPermission(e, "all", "admin")) return
// 浏览器截图
let screenshot = await puppeteer.Webpage({
url: `https://qun.qq.com/m/qun/activedata/active.html?_wv=3&_wwv=128&gc=${e.group_id}&src=2`,
cookie: common.getck("qun.qq.com", this.Bot, true),
click: /(7|七)天/.test(e.msg)
? [
{
selector: "#app > div.tabbar > div.tabbar__time > div.tabbar__time__date",
time: 500
},
{
selector: "#app > div.tabbar > div.tabbar__date-selector > div > div:nth-child(3)",
time: 1000
}
]
: false,
font: true
})
if (screenshot) return e.reply(screenshot)
// 数据
let res = await new QQApi(e).groupData(e.group_id, /(7|七)天/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply(res.msg || JSON.stringify(res))
let { groupInfo, activeData, msgInfo, joinData, exitData, applyData } = res.data
e.reply(
[
`${groupInfo.groupName}(${groupInfo.groupCode})${/(7|)/.test(e.msg) ? "七天" : "昨天"}的群数据\n`,
"------------消息条数---------\n",
`消息条数:${msgInfo.total}\n`,
"------------活跃人数---------\n",
`活跃人数:${activeData.activeData}\n`,
`总人数:${activeData.groupMember}\n`,
`活跃比例:${activeData.ratio}%\n`,
"-----------加退群人数--------\n",
`申请人数:${joinData.total}\n`,
`入群人数:${applyData.total}\n`,
`退群人数:${exitData.total}\n`
]
)
}
}

View File

@@ -0,0 +1,63 @@
import { QQApi, common } from "../../model/index.js"
// API请求错误文案
const API_ERROR = "❎ 出错辣,请稍后重试"
export class GroupAnnounce extends plugin {
constructor() {
super({
name: "椰奶群管-群公告",
event: "message.group",
priority: 500,
rule: [
{
reg: "^#发群公告",
fnc: "AddAnnounce"
},
{
reg: "^#删群公告(\\d+)$",
fnc: "DelAnnounce"
},
{
reg: "^#查群公告$",
fnc: "GetAnnounce"
}
]
})
}
// 发群公告
async AddAnnounce(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
// 获取发送的内容
let msg = e.msg.replace(/#|发群公告/g, "").trim()
if (!msg) return e.reply("❎ 公告不能为空")
let result = await new QQApi(e).setAnnounce(e.group_id, msg)
if (!result) return e.reply(API_ERROR)
if (result.ec != 0) {
e.reply("❎ 发送失败\n" + JSON.stringify(result, null, "\t"))
}
}
// 查群公告
async GetAnnounce(e) {
let res = await new QQApi(e).getAnnouncelist(e.group_id)
if (!res) return e.reply(API_ERROR)
return e.reply(res)
}
// 删群公告
async DelAnnounce(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let msg = e.msg.replace(/#|删群公告/g, "").trim()
if (!msg) return e.reply("❎ 序号不可为空")
let result = await new QQApi(e).delAnnounce(e.group_id, msg)
if (!result) return e.reply(API_ERROR)
if (result.ec == 0) {
e.reply(`✅ 已删除「${result.text}`)
} else {
e.reply("❎ 删除失败\n" + JSON.stringify(result, null, "\t"))
}
}
}

View File

@@ -1,11 +1,11 @@
import { common, GroupBannedWords } from "../../model/index.js"
import { common, GroupBannedWords as groupBannedWords } from "../../model/index.js"
import { Config } from "../../components/index.js"
import _ from "lodash"
export class NewGroupBannedWords extends plugin {
export class GroupBannedWords extends plugin {
constructor() {
super({
name: "椰奶群违禁词",
name: "椰奶群管-违禁词",
event: "message.group",
priority: 1,
rule: [
@@ -47,21 +47,21 @@ export class NewGroupBannedWords extends plugin {
if (!e.message || e.isMaster || e.member?.is_owner || e.member?.is_admin || isWhite) {
return false
}
const groupBannedWords = GroupBannedWords.initTextArr(e.group_id)
if (_.isEmpty(groupBannedWords)) {
const bannedWords = groupBannedWords.initTextArr(e.group_id)
if (_.isEmpty(bannedWords)) {
return false
}
const KeyWord = e.raw_message.trim()
const trimmedKeyWord = this.#trimAlias(KeyWord)
let data = null
for (const [ k, v ] of groupBannedWords) {
for (const [ k, v ] of bannedWords) {
if (k.test(trimmedKeyWord)) {
data = v
break
}
}
if (!data) return false
const muteTime = GroupBannedWords.getMuteTime(e.group_id)
const muteTime = groupBannedWords.getMuteTime(e.group_id)
const punishments = {
1: () => e.member.kick(),
2: () => this.#mute(muteTime),
@@ -84,7 +84,7 @@ export class NewGroupBannedWords extends plugin {
}
if (punishments[data.penaltyType]) {
punishments[data.penaltyType]()
const keyWordTran = await GroupBannedWords.keyWordTran(data.rawItem)
const keyWordTran = await groupBannedWords.keyWordTran(data.rawItem)
const senderCard = e.sender.card || e.sender.nickname
const wordNum = keyWordTran.length - 2
const replaceWord = "*".repeat(wordNum < 0 ? 0 : wordNum)
@@ -139,7 +139,7 @@ export class NewGroupBannedWords extends plugin {
}
}
try {
let res = GroupBannedWords.addBannedWords(
let res = groupBannedWords.addBannedWords(
e.group_id, word[3].trim(), word[1], word[2], e.user_id
)
e.reply([
@@ -160,7 +160,7 @@ export class NewGroupBannedWords extends plugin {
word = word.replace(/#?删除违禁词/, "").trim()
if (!word) return e.reply("需要删除的屏蔽词为空")
try {
let msg = await GroupBannedWords.delBannedWords(e.group_id, word)
let msg = await groupBannedWords.delBannedWords(e.group_id, word)
e.reply([ "✅ 成功删除:", msg ])
} catch (error) {
common.handleException(e, error)
@@ -172,7 +172,7 @@ export class NewGroupBannedWords extends plugin {
word = word.replace(/#?查看违禁词/, "").trim()
if (!word) return e.reply("需要查询的屏蔽词为空")
try {
const { words, matchType, penaltyType, addedBy, date } = GroupBannedWords.queryBannedWords(e.group_id, word)
const { words, matchType, penaltyType, addedBy, date } = groupBannedWords.queryBannedWords(e.group_id, word)
e.reply([
"✅ 查询屏蔽词\n",
"屏蔽词:",
@@ -188,19 +188,19 @@ export class NewGroupBannedWords extends plugin {
}
async list(e) {
const groupBannedWords = GroupBannedWords.initTextArr(e.group_id)
if (_.isEmpty(groupBannedWords)) {
const bannedWords = groupBannedWords.initTextArr(e.group_id)
if (_.isEmpty(bannedWords)) {
return e.reply("❎ 没有违禁词")
}
let isRaw = /(原始)|(raw)/.test(e.msg)
const msg = []
for (const [ , v ] of groupBannedWords) {
for (const [ , v ] of bannedWords) {
const { matchType, penaltyType, addedBy, date, rawItem } = v
msg.push([
"屏蔽词:",
isRaw ? rawItem : await GroupBannedWords.keyWordTran(rawItem),
`\n匹配模式:${GroupBannedWords.matchTypeMap[matchType]}\n`,
`处理方式:${GroupBannedWords.penaltyTypeMap[penaltyType]}\n`,
isRaw ? rawItem : await bannedWords.keyWordTran(rawItem),
`\n匹配模式:${bannedWords.matchTypeMap[matchType]}\n`,
`处理方式:${bannedWords.penaltyTypeMap[penaltyType]}\n`,
`添加人:${addedBy ?? "未知"}\n`,
`添加时间:${date ?? "未知"}`
])
@@ -211,14 +211,14 @@ export class NewGroupBannedWords extends plugin {
async muteTime(e) {
if (!common.checkPermission(e, "admin", "admin")) return false
let time = e.msg.match(/\d+/)[0]
GroupBannedWords.setMuteTime(e.group_id, time)
groupBannedWords.setMuteTime(e.group_id, time)
e.reply(`✅ 群${e.group_id}违禁词禁言时间已设置为${time}s`)
}
// 增删查头衔屏蔽词
async ProhibitedTitle(e) {
// 获取现有的头衔屏蔽词
let shieldingWords = GroupBannedWords.getTitleBannedWords(e.group_id)
let shieldingWords = groupBannedWords.getTitleBannedWords(e.group_id)
// 判断是否需要查看头衔屏蔽词
if (/查看/.test(e.msg)) {
// 返回已有的头衔屏蔽词列表
@@ -249,7 +249,7 @@ export class NewGroupBannedWords extends plugin {
if (isAddition) {
// 添加新的屏蔽词
if (!_.isEmpty(newWords)) {
GroupBannedWords.addTitleBannedWords(e.group_id, newWords)
groupBannedWords.addTitleBannedWords(e.group_id, newWords)
e.reply(`✅ 成功添加:${newWords.join(",")}`)
}
// 提示已有的屏蔽词
@@ -259,7 +259,7 @@ export class NewGroupBannedWords extends plugin {
} else {
// 删除已有的屏蔽词
if (!_.isEmpty(existingWords)) {
GroupBannedWords.delTitleBannedWords(e.group_id, existingWords)
groupBannedWords.delTitleBannedWords(e.group_id, existingWords)
e.reply(`✅ 成功删除:${existingWords.join(",")}`)
}
// 提示不在屏蔽词中的词
@@ -272,7 +272,7 @@ export class NewGroupBannedWords extends plugin {
// 修改头衔匹配模式
async ProhibitedTitlePattern(e) {
if (!common.checkPermission(e, "admin", "admin")) return false
let res = GroupBannedWords.setTitleFilterModeChange(e.group_id)
let res = groupBannedWords.setTitleFilterModeChange(e.group_id)
e.reply(`✅ 已修改匹配模式为${res ? "精确" : "模糊"}匹配`)
}
}

View File

@@ -0,0 +1,82 @@
import { QQApi, common } from "../../model/index.js"
// API请求错误文案
const API_ERROR = "❎ 出错辣,请稍后重试"
export class GroupLuckyword extends plugin {
constructor() {
super({
name: "椰奶群管-幸运字符",
event: "message.group",
priority: 500,
rule: [
{
reg: "^#(查)?(幸运)?字符(列表)?$",
fnc: "qun_luckylist"
},
{
reg: "^#抽(幸运)?字符$",
fnc: "qun_lucky"
},
{
reg: "^#替换(幸运)?字符(\\d+)$",
fnc: "qun_luckyuse"
},
{
reg: "^#(开启|关闭)(幸运)?字符$",
fnc: "qun_luckyset"
}
]
})
}
// 字符列表
async qun_luckylist(e) {
let data = await new QQApi(e).luckylist(e.group_id)
if (!data) return e.reply(API_ERROR)
if (data.retcode != 0) return e.reply("❎ 获取数据失败\n" + JSON.stringify(data))
let msg = data.data.word_list.map((item, index) => {
let { wording, word_id, word_desc } = item.word_info
return `${word_id}:${wording}\n寓意:${word_desc}`
}).join("\n")
e.reply(msg)
}
// 抽幸运字符
async qun_lucky(e) {
let res = await new QQApi(e).drawLucky(e.group_id)
if (!res) return e.reply(API_ERROR)
if (res.retcode == 11004) return e.reply("❎ 今天已经抽过了,明天再来抽取吧")
if (res.retcode != 0) return e.reply("❎ 错误\n" + JSON.stringify(res.data))
if (res.data.word_info) {
let { wording, word_desc } = res.data.word_info.word_info
e.reply(`恭喜您抽中了${wording}\n寓意为:${word_desc}`)
} else {
e.reply("恭喜您抽了中了个寂寞")
}
}
// 替换幸运字符
async qun_luckyuse(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let id = e.msg.replace(/#|替换(幸运)?字符/g, "")
let res = await new QQApi(e).equipLucky(e.group_id, id)
if (!res) return e.reply(API_ERROR)
if (res.retcode != 0) return e.reply("❎替换失败\n" + JSON.stringify(res))
e.reply("✅ OK")
}
// 开启或关闭群字符
async qun_luckyset(e) {
if (!common.checkPermission(e, "admin", "admin")) { return true }
let res = await new QQApi(e).swichLucky(e.group_id, /开启/.test(e.msg))
if (!res) return e.reply(API_ERROR)
if (res.retcode == 11111) return e.reply("❎ 重复开启或关闭")
if (res.retcode != 0) return e.reply("❎ 错误\n" + JSON.stringify(res))
e.reply("✅ OK")
}
}

View File

@@ -5,11 +5,10 @@ import { sleep } from "../../tools/index.js"
// 全局
let temp = {}
const ops = [ "+", "-" ]
export class NewGroupVerify extends plugin {
export class GroupVerify extends plugin {
constructor() {
super({
name: "椰奶入群验证",
dsc: "重新验证和绕过验证",
name: "椰奶群管-入群验证",
event: "message.group",
priority: 5,
rule: [

View File

@@ -0,0 +1,56 @@
import { common } from "../../model/index.js"
import { Config } from "../../components/index.js"
export class groupWhiteListCtrl extends plugin {
constructor() {
super({
name: "椰奶群管-白名单",
event: "message.group",
priority: 500,
rule: [
{
reg: "^#?群管(加|删)白(名单)?",
fnc: "whiteQQ"
},
{
reg: "^#?(开启|关闭)白名单(自动)?解禁",
fnc: "noBan"
}
]
})
}
/**
* 加白名单
*/
async whiteQQ() {
if (!common.checkPermission(this.e, "master")) return
let type = /加/.test(this.e.msg) ? "add" : "del"
let qq = this.e.at || (this.e.msg.match(/\d+/)?.[0] || "")
qq = Number(qq) || String(qq)
if (!qq) return this.reply("❎ 请艾特或输入需要加白的QQ")
const { whiteQQ } = Config.groupAdmin
const isWhite = whiteQQ.includes(qq)
if (isWhite && type === "add") return this.reply("❎ 此人已在群管白名单内")
if (!isWhite && type === "del") return this.reply("❎ 此人未在群管白名单中")
Config.modifyarr("groupAdmin", "whiteQQ", qq, type)
this.reply(`✅ 已${type === "add" ? "加入" : "删除"}${qq}到群管白名单`)
}
async noBan() {
if (!common.checkPermission(this.e, "master")) return
let type = !!/开启/.test(this.e.msg)
const { noBan } = Config.groupAdmin
if (noBan && type) return this.reply("❎ 白名单自动解禁已处于开启状态")
if (!noBan && !type) return this.reply("❎ 白名单自动解禁已处于关闭状态")
Config.modify("groupAdmin", "noBan", type)
this.reply(`✅ 已${type ? "开启" : "关闭"}白名单自动解禁`)
}
}

View File

@@ -175,4 +175,4 @@ export default new class {
Data.writeJSON(`${groupId}.json`, data, this.root)
this.groupTitleCach.delete(groupId)
}
}
}()

View File

@@ -3,23 +3,22 @@ import os from "os"
/** 获取当前内存占用 */
export default function getMemUsage() {
// 内存使用率
let MemUsage = (1 - os.freemem() / os.totalmem()).toFixed(2)
// 空闲内存
let freemem = getFileSize(os.freemem())
// 总共内存
let totalmem = getFileSize(os.totalmem())
// 使用内存
let Usingmemory = getFileSize((os.totalmem() - os.freemem()))
const freeMemory = os.freemem()
const totalMemory = os.totalmem()
const memoryUsagePercentage = (1 - freeMemory / totalMemory).toFixed(2)
const freeMem = getFileSize(freeMemory)
const totalMem = getFileSize(totalMemory)
const usingMemory = getFileSize(totalMemory - freeMemory)
return {
...Circle(MemUsage),
inner: Math.round(MemUsage * 100) + "%",
...Circle(memoryUsagePercentage),
inner: `${Math.round(memoryUsagePercentage * 100)}%`,
title: "RAM",
info: [
`总共 ${totalmem}`,
`已用 ${Usingmemory}`,
`空闲 ${freemem}`
`总共 ${totalMem}`,
`已用 ${usingMemory}`,
`空闲 ${freeMem}`
]
}
}

View File

@@ -20,21 +20,21 @@ export function addData(arr, data, maxLen = 60) {
/**
* 将文件大小从字节转化为可读性更好的格式例如B、KB、MB、GB、TB。
* @param {number} size - 带转化的字节数。
* @param {boolean} [isByte] - 如果为 true则最终的文件大小显示保留 B 的后缀.
* @param {boolean} [isSuffix] - 如果为 true则在所得到的大小后面加上 kb、mb、gb、tb 等后缀.
* @param {boolean} [showByte] - 如果为 true则最终的文件大小显示保留 B 的后缀.
* @param {boolean} [showSuffix] - 如果为 true则在所得到的大小后面加上 kb、mb、gb、tb 等后缀.
* @returns {string} 文件大小格式转换后的字符串.
*/
export function getFileSize(size, isByte = true, isSuffix = true) { // 把字节转换成正常文件大小
export function getFileSize(size, showByte = true, showSuffix = true) { // 把字节转换成正常文件大小
if (size == null || size == undefined) return 0
let num = 1024.00 // byte
if (isByte && size < num) {
if (showByte && size < num) {
return size.toFixed(2) + "B"
}
if (size < Math.pow(num, 2)) {
return (size / num).toFixed(2) + `K${isSuffix ? "b" : ""}`
return (size / num).toFixed(2) + `K${showSuffix ? "b" : ""}`
} // kb
if (size < Math.pow(num, 3)) {
return (size / Math.pow(num, 2)).toFixed(2) + `M${isSuffix ? "b" : ""}`
return (size / Math.pow(num, 2)).toFixed(2) + `M${showSuffix ? "b" : ""}`
} // M
if (size < Math.pow(num, 4)) {
return (size / Math.pow(num, 3)).toFixed(2) + "G"

View File

@@ -25,47 +25,75 @@
* // 输出: "1h 1m 5s"
*/
export default function formatDuration(time, format, repair = true) {
const second = parseInt(time % 60)
const minute = parseInt((time / 60) % 60)
const hour = parseInt((time / (60 * 60)) % 24)
const day = parseInt(time / (24 * 60 * 60))
const timeObj = {
const timeObj = computeTimeObject(time, repair)
if (typeof format === "function") {
return format(timeObj)
}
if (format === "default") {
return formatDefault(timeObj)
}
if (typeof format === "string") {
return formatTemplate(format, timeObj)
}
return timeObj
}
// 默认格式化逻辑拆分到单独的函数,提高代码可维护性
function formatDefault(timeObj) {
const { day, hour, minute, second } = timeObj
let result = ""
if (day > 0) {
result += `${day}`
}
if (hour > 0) {
result += `${hour}小时`
}
if (minute > 0) {
result += `${minute}`
}
if (second > 0) {
result += `${second}`
}
return result
}
// 字符串模板格式化逻辑拆分到单独的函数
function formatTemplate(format, timeObj) {
const replaceRegexes = [
{ pattern: /dd/g, value: timeObj.day },
{ pattern: /hh/g, value: timeObj.hour },
{ pattern: /mm/g, value: timeObj.minute },
{ pattern: /ss/g, value: timeObj.second }
]
// 优化字符串替换逻辑
for (const { pattern, value } of replaceRegexes) {
format = format.replace(pattern, value)
}
return format
}
/**
* 计算并返回表示时间的对象。
* @param {number} time - 要计算的时间(以秒为单位)。
* @param {boolean} [repair] - 修复小时、分钟和秒的显示格式的可选参数。如果设置为true并且小时、分钟或秒小于10则在值前面添加零。
* @returns {{day: string, hour: string, minute: string, second: string}} - 包含天、小时、分钟和秒的时间对象。
*/
function computeTimeObject(time, repair = true) {
const second = parseInt(time % 60, 10)
const minute = Math.floor(time / 60)
const hour = Math.floor(minute / 60)
const day = Math.floor(time / (24 * 60 * 60))
return {
day,
hour: repair && hour < 10 ? `0${hour}` : hour,
minute: repair && minute < 10 ? `0${minute}` : minute,
second: repair && second < 10 ? `0${second}` : second
}
if (typeof format === "function") {
return format(timeObj)
}
if (format == "default") {
let result = ""
if (day > 0) {
result += `${day}`
}
if (hour > 0) {
result += `${timeObj.hour}小时`
}
if (minute > 0) {
result += `${timeObj.minute}`
}
if (second > 0) {
result += `${timeObj.second}`
}
return result
}
if (typeof format === "string") {
format = format
.replace(/dd/g, day)
.replace(/hh/g, timeObj.hour)
.replace(/mm/g, timeObj.minute)
.replace(/ss/g, timeObj.second)
return format
}
return timeObj
}