Miao-Yunzai/plugins/system/add.js

446 lines
11 KiB
JavaScript
Raw Normal View History

2023-07-26 22:53:43 +08:00
import cfg from "../../lib/config/config.js"
import plugin from "../../lib/plugins/plugin.js"
import common from "../../lib/common/common.js"
import fs from "node:fs"
import path from "node:path"
import lodash from "lodash"
import fetch from "node-fetch"
import { fileTypeFromBuffer } from "file-type"
let messageMap = {}
2023-05-11 16:03:18 +08:00
export class add extends plugin {
2023-07-25 00:24:52 +08:00
constructor() {
2023-05-11 16:03:18 +08:00
super({
2023-07-26 22:53:43 +08:00
name: "添加消息",
dsc: "添加消息",
event: "message",
2023-05-11 16:03:18 +08:00
priority: 50000,
rule: [
{
2023-07-26 22:53:43 +08:00
reg: "^#(全局)?添加",
fnc: "add"
2023-05-11 16:03:18 +08:00
},
{
2023-07-26 22:53:43 +08:00
reg: "^#(全局)?删除",
fnc: "del"
2023-05-11 16:03:18 +08:00
},
{
2023-07-26 22:53:43 +08:00
reg: "",
fnc: "getMessage",
2023-05-11 16:03:18 +08:00
log: false
},
{
2023-07-26 22:53:43 +08:00
reg: "^#(全局)?(消息|词条)",
fnc: "list"
2023-05-11 16:03:18 +08:00
}
]
})
2023-07-26 22:53:43 +08:00
this.path = "data/messageJson/"
2023-05-11 16:03:18 +08:00
}
2023-07-25 00:24:52 +08:00
async init() {
2023-07-26 22:53:43 +08:00
common.mkdirs(this.path)
2023-05-11 16:03:18 +08:00
}
/** 群号key */
2023-07-25 00:24:52 +08:00
get grpKey() {
2023-05-11 16:03:18 +08:00
return `Yz:group_id:${this.e.user_id}`
}
/** #添加 */
2023-07-25 00:24:52 +08:00
async add() {
2023-07-26 22:53:43 +08:00
this.isGlobal = Boolean(this.e.msg.match(/^#全局/))
2023-05-11 16:03:18 +08:00
await this.getGroupId()
if (!this.group_id) {
2023-07-26 22:53:43 +08:00
await this.reply("请先在群内触发消息,确定添加的群")
2023-05-11 16:03:18 +08:00
return
}
2023-07-26 22:53:43 +08:00
this.initMessageMap()
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (!this.checkAuth()) return false
2023-05-11 16:03:18 +08:00
/** 获取关键词 */
this.getKeyWord()
2023-07-26 22:53:43 +08:00
if (!this.e.keyWord) {
await this.reply("添加错误:没有关键词")
2023-05-11 16:03:18 +08:00
return
}
2023-07-26 22:53:43 +08:00
this.e.message = []
this.setContext("addContext")
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
return this.reply("请发送添加内容,完成后发送#结束添加", true, { at: true })
2023-05-11 16:03:18 +08:00
}
/** 获取群号 */
2023-07-25 00:24:52 +08:00
async getGroupId() {
2023-07-26 22:53:43 +08:00
/** 添加全局消息,存入到机器人文件中 */
2023-05-11 16:03:18 +08:00
if (this.isGlobal) {
2023-07-26 22:53:43 +08:00
this.group_id = "global"
return this.group_id
2023-05-11 16:03:18 +08:00
}
2023-07-25 00:24:52 +08:00
2023-05-11 16:03:18 +08:00
if (this.e.isGroup) {
this.group_id = this.e.group_id
redis.setEx(this.grpKey, 3600 * 24 * 30, String(this.group_id))
return this.group_id
}
// redis获取
let groupId = await redis.get(this.grpKey)
if (groupId) {
this.group_id = groupId
return this.group_id
}
return false
}
2023-07-25 00:24:52 +08:00
checkAuth() {
2023-05-11 16:03:18 +08:00
if (this.e.isMaster) return true
2023-07-26 22:53:43 +08:00
const groupCfg = cfg.getGroup(this.e.self_id, this.group_id)
if (groupCfg.addLimit == 2) {
this.reply("暂无权限,只有主人才能操作")
2023-05-11 16:03:18 +08:00
return false
}
2023-07-26 22:53:43 +08:00
if (groupCfg.addLimit == 1) {
2023-05-11 16:03:18 +08:00
if (!this.e.member.is_admin) {
2023-07-26 22:53:43 +08:00
this.reply("暂无权限,只有管理员才能操作")
2023-05-11 16:03:18 +08:00
return false
}
}
2023-07-26 22:53:43 +08:00
if (groupCfg.addPrivate != 1 && !this.e.isGroup) {
this.reply("禁止私聊添加")
2023-05-11 16:03:18 +08:00
return false
}
return true
}
/** 获取添加关键词 */
2023-07-25 00:24:52 +08:00
getKeyWord() {
2023-07-26 22:53:43 +08:00
this.e.isGlobal = Boolean(this.e.msg.match(/^#全局/))
this.keyWord = this.e.raw_message.replace(/#(全局)?(添加|删除)/, "").trim()
this.e.keyWord = this.trimAlias(this.keyWord)
2023-05-11 16:03:18 +08:00
}
/** 过滤别名 */
2023-07-25 00:24:52 +08:00
trimAlias(msg) {
2023-07-26 22:53:43 +08:00
const groupCfg = cfg.getGroup(this.e.self_id, this.group_id)
2023-05-11 16:03:18 +08:00
let alias = groupCfg.botAlias
2023-07-26 22:53:43 +08:00
if (!Array.isArray(alias))
2023-05-11 16:03:18 +08:00
alias = [alias]
2023-07-26 22:53:43 +08:00
for (const name of alias)
if (msg.startsWith(name))
2023-05-11 16:03:18 +08:00
msg = lodash.trimStart(msg, name).trim()
return msg
}
/** 添加内容 */
2023-07-25 00:24:52 +08:00
async addContext() {
2023-07-26 22:53:43 +08:00
const context = this.getContext()?.addContext
this.isGlobal = context.isGlobal
2023-05-11 16:03:18 +08:00
await this.getGroupId()
/** 关键词 */
2023-07-26 22:53:43 +08:00
this.keyWord = context.keyWord
if (!this.e.msg?.includes("#结束添加")) {
/** 添加内容 */
for (const i of this.e.message) {
2023-07-27 08:37:02 +08:00
if (i.url) i.file = await this.saveFile(i)
2023-07-26 22:53:43 +08:00
if (i.type == "at" && i.qq == this.e.self_id) continue
context.message.push(i)
}
return
}
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
this.finish("addContext")
if (!context.message?.length) {
this.reply("添加错误:没有添加内容")
return
2023-05-11 16:03:18 +08:00
}
2023-07-26 22:53:43 +08:00
if (!messageMap[this.group_id])
messageMap[this.group_id] = new Map()
2023-05-11 16:03:18 +08:00
/** 支持单个关键词添加多个 */
2023-07-26 22:53:43 +08:00
let message = messageMap[this.group_id].get(this.keyWord)
if (Array.isArray(message))
message.push(context.message)
else
message = [context.message]
messageMap[this.group_id].set(this.keyWord, message)
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (message.length > 1)
this.keyWord += String(message.length)
2023-05-11 16:03:18 +08:00
this.saveJson()
2023-07-26 22:53:43 +08:00
return this.reply(`添加成功:${this.keyWord}`)
2023-05-11 16:03:18 +08:00
}
2023-07-25 00:24:52 +08:00
saveJson() {
2023-05-11 16:03:18 +08:00
let obj = {}
2023-07-26 22:53:43 +08:00
for (let [k, v] of messageMap[this.group_id])
2023-05-11 16:03:18 +08:00
obj[k] = v
2023-07-26 22:53:43 +08:00
fs.writeFileSync(`${this.path}${this.group_id}.json`, JSON.stringify(obj, "", "\t"))
2023-05-11 16:03:18 +08:00
}
2023-07-26 22:53:43 +08:00
async makeBuffer(file) {
if (file.match(/^base64:\/\//))
return Buffer.from(file.replace(/^base64:\/\//, ""), "base64")
else if (file.match(/^https?:\/\//))
return Buffer.from(await (await fetch(file)).arrayBuffer())
else if (fs.existsSync(file))
return Buffer.from(fs.readFileSync(file))
return file
2023-05-11 16:03:18 +08:00
}
2023-07-26 22:53:43 +08:00
async fileType(data) {
2023-07-27 08:37:02 +08:00
const file = { name: `${this.group_id}/${data.type}/${Date.now()}` }
2023-07-26 22:53:43 +08:00
try {
2023-07-27 08:37:02 +08:00
file.url = data.url.replace(/^base64:\/\/.*/, "base64://...")
file.buffer = await this.makeBuffer(data.url)
2023-07-26 22:53:43 +08:00
file.type = await fileTypeFromBuffer(file.buffer)
2023-07-27 08:37:02 +08:00
file.name = `${file.name}.${file.type.ext}`
2023-07-26 22:53:43 +08:00
} catch (err) {
logger.error(`文件类型检测错误:${logger.red(err)}`)
2023-07-27 08:37:02 +08:00
file.name = `${file.name}-${path.basename(data.file || data.url)}`
2023-07-26 22:53:43 +08:00
}
return file
}
2023-05-11 16:03:18 +08:00
2023-07-27 08:37:02 +08:00
async saveFile(data) {
const file = await this.fileType(data)
if (file.name && Buffer.isBuffer(file.buffer) && common.mkdirs(path.dirname(`${this.path}${file.name}`))) {
2023-07-26 22:53:43 +08:00
fs.writeFileSync(`${this.path}${file.name}`, file.buffer)
return file.name
2023-05-11 16:03:18 +08:00
}
return data.url
2023-05-11 16:03:18 +08:00
}
2023-07-26 22:53:43 +08:00
async getMessage() {
2023-05-11 16:03:18 +08:00
if (!this.e.raw_message) return false
this.isGlobal = false
await this.getGroupId()
if (!this.group_id) return false
2023-07-26 22:53:43 +08:00
this.initMessageMap()
this.initGlobalMessageMap()
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
this.keyWord = this.trimAlias(this.e.raw_message.trim())
let keyWord = this.keyWord
2023-05-11 16:03:18 +08:00
let num = 0
if (isNaN(keyWord)) {
2023-07-26 22:53:43 +08:00
num = keyWord.charAt(keyWord.length-1)
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (!isNaN(num) && !messageMap[this.group_id].has(keyWord) && !messageMap.global.has(keyWord)) {
2023-05-11 16:03:18 +08:00
keyWord = lodash.trimEnd(keyWord, num).trim()
num--
}
}
2023-07-26 22:53:43 +08:00
let msg = [
...messageMap[this.group_id].get(keyWord) || [],
...messageMap.global.get(keyWord) || [],
]
if (lodash.isEmpty(msg)) return false
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (!msg[num])
num = lodash.random(0, msg.length-1)
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
msg = [...msg[num]]
for (const i in msg)
if (msg[i].file && fs.existsSync(`${this.path}${msg[i].file}`))
msg[i] = { ...msg[i], file: `base64://${fs.readFileSync(`${this.path}${msg[i].file}`).toString("base64")}` }
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
logger.mark(`[发送消息]${this.e.logText} ${this.keyWord}`)
const groupCfg = cfg.getGroup(this.e.self_id, this.group_id)
return this.reply(msg, Boolean(groupCfg.addReply), {
at: Boolean(groupCfg.addAt),
recallMsg: groupCfg.addRecall,
})
2023-05-11 16:03:18 +08:00
}
/** 初始化已添加内容 */
2023-07-26 22:53:43 +08:00
initMessageMap() {
if (messageMap[this.group_id]) return
messageMap[this.group_id] = new Map()
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
const path = `${this.path}${this.group_id}.json`
if (!fs.existsSync(path)) return
2023-05-11 16:03:18 +08:00
try {
2023-07-26 22:53:43 +08:00
const message = JSON.parse(fs.readFileSync(path, "utf8"))
for (const i in message)
messageMap[this.group_id].set(i, message[i])
} catch (err) {
logger.error(`JSON 格式错误:${path} ${err}`)
2023-05-11 16:03:18 +08:00
}
}
2023-07-25 00:24:52 +08:00
2023-05-11 16:03:18 +08:00
/** 初始化全局已添加内容 */
2023-07-26 22:53:43 +08:00
initGlobalMessageMap() {
if (messageMap.global) return
messageMap.global = new Map()
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
const globalPath = `${this.path}global.json`
if (!fs.existsSync(globalPath)) return
2023-05-11 16:03:18 +08:00
try {
2023-07-26 22:53:43 +08:00
const message = JSON.parse(fs.readFileSync(globalPath, "utf8"))
for (const i in message)
messageMap.global.set(i, message[i])
} catch (err) {
logger.error(`JSON 格式错误:${globalPath} ${err}`)
2023-05-11 16:03:18 +08:00
}
}
2023-07-25 00:24:52 +08:00
async del() {
2023-07-26 22:53:43 +08:00
this.isGlobal = this.e.msg.includes("全局")
2023-05-11 16:03:18 +08:00
await this.getGroupId()
2023-07-26 22:53:43 +08:00
if (!(this.group_id && this.checkAuth())) return false
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
this.initMessageMap()
2023-05-11 16:03:18 +08:00
2023-05-15 10:18:19 +08:00
this.getKeyWord()
if (!this.keyWord) {
2023-07-26 22:53:43 +08:00
await this.reply("删除错误:没有关键词")
return false
2023-05-15 10:18:19 +08:00
}
2023-07-26 22:53:43 +08:00
this.keyWord = this.trimAlias(this.keyWord)
let keyWord = this.keyWord
2023-05-11 16:03:18 +08:00
let num = false
let index = 0
if (isNaN(keyWord)) {
2023-07-26 22:53:43 +08:00
num = keyWord.charAt(keyWord.length-1)
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (!isNaN(num) && !messageMap[this.group_id].has(keyWord)) {
2023-05-11 16:03:18 +08:00
keyWord = lodash.trimEnd(keyWord, num).trim()
2023-07-26 22:53:43 +08:00
index = num-1
2023-05-11 16:03:18 +08:00
} else {
num = false
}
}
2023-07-26 22:53:43 +08:00
let arr = messageMap[this.group_id].get(keyWord)
2023-05-11 16:03:18 +08:00
if (!arr) {
2023-07-26 22:53:43 +08:00
// await this.reply(`暂无此消息:${keyWord}`)
2023-05-11 16:03:18 +08:00
return false
}
let tmp = []
if (num) {
if (!arr[index]) {
2023-07-26 22:53:43 +08:00
// await this.reply(`暂无此消息:${keyWord}${num}`)
2023-05-11 16:03:18 +08:00
return false
}
tmp = arr[index]
arr.splice(index, 1)
if (arr.length <= 0) {
2023-07-26 22:53:43 +08:00
messageMap[this.group_id].delete(keyWord)
2023-05-11 16:03:18 +08:00
} else {
2023-07-26 22:53:43 +08:00
messageMap[this.group_id].set(keyWord, arr)
2023-05-11 16:03:18 +08:00
}
} else {
2023-07-26 22:53:43 +08:00
if (this.e.msg.includes("删除全部")) {
2023-05-11 16:03:18 +08:00
tmp = arr
arr = []
} else {
tmp = arr.pop()
}
if (arr.length <= 0) {
2023-07-26 22:53:43 +08:00
messageMap[this.group_id].delete(keyWord)
2023-05-11 16:03:18 +08:00
} else {
2023-07-26 22:53:43 +08:00
messageMap[this.group_id].set(keyWord, arr)
2023-05-11 16:03:18 +08:00
}
}
this.saveJson()
2023-07-26 22:53:43 +08:00
return this.reply(`删除成功:${this.keyWord}`)
2023-05-11 16:03:18 +08:00
}
2023-07-25 00:24:52 +08:00
async list() {
2023-07-26 22:53:43 +08:00
this.isGlobal = Boolean(this.e.msg.match(/^#全局/))
2023-05-11 16:03:18 +08:00
let page = 1
let pageSize = 100
2023-07-26 22:53:43 +08:00
let type = "list"
2023-05-11 16:03:18 +08:00
await this.getGroupId()
if (!this.group_id) return false
2023-07-26 22:53:43 +08:00
this.initMessageMap()
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
const search = this.e.msg.replace(/^#(全局)?(消息|词条)/, "").trim()
if (search.match(/^列表/))
page = search.replace(/^列表/, "") || 1
else
type = "search"
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
let list = messageMap[this.group_id]
2023-05-11 16:03:18 +08:00
if (lodash.isEmpty(list)) {
2023-07-26 22:53:43 +08:00
await this.reply("暂无消息")
2023-05-11 16:03:18 +08:00
return
}
let arr = []
2023-07-26 22:53:43 +08:00
if (type == "list")
for (let [k, v] of messageMap[this.group_id])
arr.push({ key: k, val: v, num: arr.length+1 })
else
for (let [k, v] of messageMap[this.group_id])
if (k.includes(search))
arr.push({ key: k, val: v, num: arr.length+1 })
2023-05-11 16:03:18 +08:00
let count = arr.length
arr = arr.reverse()
2023-07-26 22:53:43 +08:00
if (type == "list")
2023-05-11 16:03:18 +08:00
arr = this.pagination(page, pageSize, arr)
2023-07-26 22:53:43 +08:00
if (lodash.isEmpty(arr)) return false
2023-05-11 16:03:18 +08:00
let msg = []
let num = 0
2023-07-26 22:53:43 +08:00
for (const i of arr) {
2023-05-11 16:03:18 +08:00
if (num >= page * pageSize) break
2023-07-26 22:53:43 +08:00
let keyWord = i.key
2023-05-11 16:03:18 +08:00
if (!keyWord) continue
2023-07-26 22:53:43 +08:00
msg.push(`${i.num}. ${keyWord}(${i.val.length})`)
2023-05-11 16:03:18 +08:00
num++
}
2023-07-26 22:53:43 +08:00
msg = [msg.join("\n")]
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
if (type == "list" && count > 100)
msg.push(`更多内容请翻页查看\n如:#消息列表${Number(page)+1}`)
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
let title = `消息列表:第${page}页,共${count}`
if (type == "search")
title = `消息${search}:共${count}`
2023-05-11 16:03:18 +08:00
2023-07-26 22:53:43 +08:00
return this.reply(await common.makeForwardMsg(this.e, msg, title))
2023-05-11 16:03:18 +08:00
}
/** 分页 */
2023-07-25 00:24:52 +08:00
pagination(pageNo, pageSize, array) {
2023-07-26 22:53:43 +08:00
let offset = (pageNo-1) * pageSize
return offset+pageSize >= array.length ? array.slice(offset, array.length) : array.slice(offset, offset+pageSize)
2023-05-11 16:03:18 +08:00
}
2023-07-25 00:24:52 +08:00
}