miao-plugin/apps/character/character-img-upload.js
yoimiya-kokomi 3f98642a9e 添加 纳西妲、莱依拉 的图鉴信息
优化character的进入判定逻辑,防止一些额外的log触发
2022-09-30 20:20:04 +08:00

151 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'fs'
import { promisify } from 'util'
import { pipeline } from 'stream'
import { segment } from 'oicq'
import MD5 from 'md5'
import fetch from 'node-fetch'
import lodash from 'lodash'
import { Data } from '../../components/index.js'
import { Character } from '../../models/index.js'
const resPath = process.cwd() + '/plugins/miao-plugin/resources/'
let regex = /^#?\s*(?:喵喵)?(?:上传|添加)(.+)(?:照片|写真|图片|图像)\s*$/
export async function uploadCharacterImg (e) {
let promise = await isAllowedToUploadCharacterImage(e)
if (!promise) {
return false
}
let imageMessages = []
let msg = e.msg
let regRet = regex.exec(msg)
// 通过解析正则获取消息中的角色名
if (!regRet || !regRet[1]) {
return false
}
let char = Character.get(regRet[1])
if (!char || !char.name) {
return false
}
let name = char.name
for (let val of e.message) {
if (val.type === 'image') {
imageMessages.push(val)
}
}
let source
if (e.isGroup) {
// 支持at图片添加以及支持后发送
source = (await e.group.getChatHistory(e.source?.seq, 1)).pop()
} else {
source = (await e.friend.getChatHistory((e.source?.time + 1), 1)).pop()
}
if (source) {
for (let val of source.message) {
if (val.type === 'image') {
imageMessages.push(val)
}
}
}
if (imageMessages.length <= 0) {
e.reply('消息中未找到图片,请将要发送的图片与消息一同发送或引用要添加的图像..')
return true
}
await saveImages(e, name, imageMessages)
return true
}
async function saveImages (e, name, imageMessages) {
let imgMaxSize = e?.groupConfig?.imgMaxSize || 5
let pathSuffix = `character-img/${name}/upload`
let path = resPath + pathSuffix
if (!fs.existsSync(path)) {
Data.createDir(pathSuffix, resPath)
}
let senderName = lodash.truncate(e.sender.card, { length: 8 })
let imgCount = 0
let urlMap = {}
for (let val of imageMessages) {
if (!val.url || urlMap[val.url]) {
continue
}
urlMap[val.url] = true
const response = await fetch(val.url)
if (!response.ok) {
e.reply('图片下载失败。')
return true
}
if (response.headers.get('size') > 1024 * 1024 * imgMaxSize) {
e.reply([segment.at(e.user_id, senderName), '添加失败:图片太大了。'])
return true
}
let fileName = val.file.substring(0, val.file.lastIndexOf('.'))
let fileType = val.file.substring(val.file.lastIndexOf('.') + 1)
if (response.headers.get('content-type') === 'image/gif') {
fileType = 'gif'
}
let imgPath = `${path}/${fileName}.${fileType}`
const streamPipeline = promisify(pipeline)
await streamPipeline(response.body, fs.createWriteStream(imgPath))
// 使用md5作为文件名
let buffers = fs.readFileSync(imgPath)
let base64 = Buffer.from(buffers, 'base64').toString()
let md5 = MD5(base64)
let newImgPath = `${path}/${md5}.${fileType}`
if (fs.existsSync(newImgPath)) {
fs.unlink(newImgPath, (err) => {
console.log('unlink', err)
})
}
fs.rename(imgPath, newImgPath, () => {
})
imgCount++
Bot.logger.mark(`添加成功: ${path}/${fileName}`)
}
e.reply([segment.at(e.user_id, senderName), `\n成功添加${imgCount}${name}图片。`])
return true
}
async function isAllowedToUploadCharacterImage (e) {
if (!e.message) {
return false
}
if (!e.msg) {
return false
}
if (!e.isMaster) {
return false
}
// 由于添加角色图是全局,暂时屏蔽非管理员的添加
if (e.isPrivate) {
if (!e.isMaster) {
e.reply('只有主人才能添加。')
return false
}
return true
}
let groupId = e.group_id
if (!groupId) {
return false
}
if (e.groupConfig?.imgAddLimit === 2) {
if (!e.isMaster) {
e.reply('只有主人才能添加。')
return false
}
}
if (e.groupConfig?.imgAddLimit === 1 && !e.isMaster) {
if (!(e.sender.role === 'owner' || e.sender.role === 'admin')) {
e.reply('只有管理员才能添加。')
return false
}
}
return true
}