mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
fix: WIP
This commit is contained in:
parent
116479e34e
commit
54806ee6fb
6 changed files with 265 additions and 15 deletions
41
apps/chat.js
41
apps/chat.js
|
|
@ -1,9 +1,9 @@
|
|||
import Config from '../config/config.js'
|
||||
import { Chaite, SendMessageOption } from 'chaite'
|
||||
import { getPreset, intoUserMessage } from '../utils/message.js'
|
||||
|
||||
export class Chat extends plugin {
|
||||
constructor () {
|
||||
let toggleMode = Config.basic.toggleMode
|
||||
let prefix = Config.basic.togglePrefix
|
||||
super({
|
||||
name: 'ChatGPT-Plugin对话',
|
||||
dsc: 'ChatGPT-Plugin对话',
|
||||
|
|
@ -11,24 +11,39 @@ export class Chat extends plugin {
|
|||
priority: 0,
|
||||
rule: [
|
||||
{
|
||||
reg: toggleMode === 'at' ? '^[^#][sS]*' : `^#?(图片)?${prefix}[^gpt][sS]*`,
|
||||
fnc: 'chat'
|
||||
reg: '^[^#][sS]*',
|
||||
fnc: 'chat',
|
||||
log: false
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
async chat (e) {
|
||||
|
||||
const state = await Chaite.getInstance().getUserStateStorage().getItem(e.sender.user_id + '')
|
||||
const userSettings = state.settings
|
||||
const sendMessageOptions = SendMessageOption.create({
|
||||
model: userSettings.model,
|
||||
temperature: userSettings.temperature,
|
||||
max_tokens: userSettings.maxToken,
|
||||
systemOverride: userSettings.systemOverride,
|
||||
|
||||
const sendMessageOptions = SendMessageOption.create(state.settings)
|
||||
const preset = await getPreset(e, state.settings.preset, Config.basic.toggleMode, Config.basic.togglePrefix)
|
||||
if (!preset) {
|
||||
logger.debug('未找到预设,不进入对话')
|
||||
return false
|
||||
}
|
||||
const userMessage = await intoUserMessage(e, {
|
||||
handleReplyText: false,
|
||||
handleReplyImage: true,
|
||||
useRawMessage: false,
|
||||
handleAtMsg: true,
|
||||
excludeAtBot: false,
|
||||
toggleMode: Config.basic.toggleMode,
|
||||
togglePrefix: Config.basic.togglePrefix
|
||||
})
|
||||
Chaite.getInstance().sendMessage(msg, e, )
|
||||
const response = await Chaite.getInstance().sendMessage(userMessage, e, {
|
||||
...sendMessageOptions,
|
||||
chatPreset: preset
|
||||
})
|
||||
const responseText = response.contents
|
||||
.filter(c => c.type === 'text')
|
||||
.map(c => (/** @type {import('chaite').TextContent} **/ c).text)
|
||||
.reduce((a, b) => a + b, '')
|
||||
await this.reply(responseText)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
39
apps/management.js
Normal file
39
apps/management.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import ChatGPTConfig from '../config/config.js'
|
||||
import { createCRUDCommandRules, createSwitchCommandRules } from '../utils/command.js'
|
||||
|
||||
export class ChatGPTManagement extends plugin {
|
||||
constructor () {
|
||||
const cmdPrefix = ChatGPTConfig.basic.commandPrefix
|
||||
super({
|
||||
name: 'ChatGPT-Plugin管理',
|
||||
dsc: 'ChatGPT-Plugin管理',
|
||||
event: 'message',
|
||||
priority: 20,
|
||||
rule: [
|
||||
{
|
||||
reg: `^${cmdPrefix}管理面板$`,
|
||||
fnc: 'managementPanel',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: `^${cmdPrefix}结束(全部)?对话$`,
|
||||
fnc: 'destroyConversation'
|
||||
},
|
||||
...createCRUDCommandRules(cmdPrefix, '渠道', 'channels'),
|
||||
...createCRUDCommandRules(cmdPrefix, '预设', 'presets'),
|
||||
...createCRUDCommandRules(cmdPrefix, '工具', 'tools'),
|
||||
...createCRUDCommandRules(cmdPrefix, '处理器', 'processors'),
|
||||
createSwitchCommandRules(cmdPrefix, '(预设切换|其他人切换预设)', 'customPreset', 1),
|
||||
createSwitchCommandRules(cmdPrefix, '(调试|debug)(模式)?', 'debug'),
|
||||
...createCRUDCommandRules(cmdPrefix, '预设切换黑名单', 'blackCustomPreset', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '预设切换白名单', 'whiteCustomPreset', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '输入屏蔽词', 'blackPromptWords', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '输出屏蔽词', 'blackResponseWords', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '黑名单群', 'blackGroups', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '白名单群', 'whiteGroups', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '黑名单用户', 'blackUsers', false),
|
||||
...createCRUDCommandRules(cmdPrefix, '白名单用户', 'whiteUsers', false)
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,9 @@ class ChatGPTConfig {
|
|||
// 触发前缀,仅在前缀触发时有效
|
||||
togglePrefix: '#chat',
|
||||
// 是否开启调试模式
|
||||
debug: false
|
||||
debug: false,
|
||||
// 一般命令的开头
|
||||
commandPrefix: '^#chatgpt'
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export class LowDBChatPresetsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').ChatPreset>}
|
||||
*/
|
||||
async getItem (key) {
|
||||
|
||||
return this.collection.findOne({ id: key })
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
49
utils/command.js
Normal file
49
utils/command.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* 模板
|
||||
* @param cmdPrefix
|
||||
* @param name
|
||||
* @param variable
|
||||
* @param detail
|
||||
* @returns {{reg: string, fnc: string}[]}
|
||||
*/
|
||||
export function createCRUDCommandRules (cmdPrefix, name, variable, detail = true) {
|
||||
// make the first letter of variable capable
|
||||
variable = variable.charAt(0).toUpperCase() + variable.slice(1)
|
||||
const rules = [
|
||||
{
|
||||
reg: cmdPrefix + `${name}列表$`,
|
||||
fnc: `list${variable}`
|
||||
},
|
||||
{
|
||||
reg: cmdPrefix + `(编辑|修改)${name}`,
|
||||
fnc: `edit${variable}`
|
||||
},
|
||||
{
|
||||
reg: cmdPrefix + `(添加|新增)${name}$`,
|
||||
fnc: `add${variable}`
|
||||
},
|
||||
|
||||
{
|
||||
reg: cmdPrefix + `删除${name}`,
|
||||
fnc: `remove${variable}`
|
||||
}
|
||||
]
|
||||
if (detail) {
|
||||
rules.push({
|
||||
reg: cmdPrefix + `${name}详情$`,
|
||||
fnc: `detail${variable}`
|
||||
})
|
||||
}
|
||||
return rules
|
||||
}
|
||||
const switchCommandPreset = {
|
||||
0: ['开启', '关闭'],
|
||||
1: ['允许', '禁止']
|
||||
}
|
||||
export function createSwitchCommandRules (cmdPrefix, name, variable, preset = 0) {
|
||||
variable = variable.charAt(0).toUpperCase() + variable.slice(1)
|
||||
return {
|
||||
reg: cmdPrefix + `(${switchCommandPreset[preset][0]}|${switchCommandPreset[preset][1]})${name}$`,
|
||||
fnc: `switch${variable}`
|
||||
}
|
||||
}
|
||||
145
utils/message.js
Normal file
145
utils/message.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
import { Chaite } from 'chaite'
|
||||
|
||||
/**
|
||||
* 将e中的消息转换为chaite的UserMessage
|
||||
*
|
||||
* @param e
|
||||
* @param {{
|
||||
* handleReplyText: boolean,
|
||||
* handleReplyImage: boolean,
|
||||
* useRawMessage: boolean,
|
||||
* handleAtMsg: boolean,
|
||||
* excludeAtBot: boolean,
|
||||
* toggleMode: 'at' | 'prefix',
|
||||
* togglePrefix: string
|
||||
* }} options
|
||||
* @returns {Promise<import('chaite').UserMessage>}
|
||||
*/
|
||||
export async function intoUserMessage (e, options = {}) {
|
||||
const {
|
||||
handleReplyText = false,
|
||||
handleReplyImage = true,
|
||||
useRawMessage = false,
|
||||
handleAtMsg = true,
|
||||
excludeAtBot = false,
|
||||
toggleMode = 'at',
|
||||
togglePrefix = null
|
||||
} = options
|
||||
const contents = []
|
||||
let text = ''
|
||||
if (e.source && (handleReplyImage || handleReplyText)) {
|
||||
let seq = e.isGroup ? e.source.seq : e.source.time
|
||||
let reply = e.isGroup
|
||||
? (await e.group.getChatHistory(seq, 1)).pop()?.message
|
||||
: (await e.friend.getChatHistory(seq, 1)).pop()?.message
|
||||
if (reply) {
|
||||
for (let val of reply) {
|
||||
if (val.type === 'image' && handleReplyImage) {
|
||||
contents.push({
|
||||
type: 'image',
|
||||
url: val.url
|
||||
})
|
||||
} else if (val.type === 'text' && handleReplyText) {
|
||||
text = `本条消息对以下消息进行了引用回复:${val.text}\n\n本条消息内容:\n`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useRawMessage) {
|
||||
text += e.raw_message
|
||||
} else {
|
||||
for (let val of e.message) {
|
||||
switch (val.type) {
|
||||
case 'at': {
|
||||
if (handleAtMsg) {
|
||||
const { qq, text: atCard } = val
|
||||
if ((toggleMode === 'at' || excludeAtBot) && qq === e.bot.uin) {
|
||||
break
|
||||
}
|
||||
text += ` @${atCard || qq} `
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'text': {
|
||||
text += val.text
|
||||
break
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
e.message?.filter(element => element.type === 'image').forEach(element => {
|
||||
contents.push({
|
||||
type: 'image',
|
||||
url: element.url
|
||||
})
|
||||
})
|
||||
if (toggleMode === 'prefix') {
|
||||
const regex = new RegExp(`^#?(图片)?${togglePrefix}[^gpt]`)
|
||||
text = text.replace(regex, '')
|
||||
}
|
||||
if (text) {
|
||||
contents.push({
|
||||
type: 'text',
|
||||
content: text
|
||||
})
|
||||
}
|
||||
return {
|
||||
role: 'user',
|
||||
content: contents
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到本次对话使用的预设
|
||||
* @param e
|
||||
* @param {string} presetId
|
||||
* @param {'at' | 'prefix'} toggleMode
|
||||
* @param {string} togglePrefix
|
||||
* @returns {Promise<import('chaite').ChatPreset | null>}
|
||||
*/
|
||||
export async function getPreset (e, presetId, toggleMode, togglePrefix) {
|
||||
const isValidChat = checkChatMsg(e, toggleMode, togglePrefix)
|
||||
const manager = Chaite.getInstance().getChatPresetManager()
|
||||
const presets = await manager.getAllPresets()
|
||||
const prefixHitPresets = presets.filter(p => e.msg.startsWith(p.prefix))
|
||||
if (!isValidChat && prefixHitPresets.length === 0) {
|
||||
return null
|
||||
}
|
||||
let preset
|
||||
// 如果不是at且不满足通用前缀,查看是否满足其他预设
|
||||
if (!isValidChat) {
|
||||
// 找到其中prefix最长的
|
||||
if (prefixHitPresets.length > 1) {
|
||||
preset = prefixHitPresets.sort((a, b) => b.prefix.length - a.prefix.length)[0]
|
||||
} else {
|
||||
preset = prefixHitPresets[0]
|
||||
}
|
||||
} else {
|
||||
// 命中at或通用前缀,直接走用户默认预设
|
||||
preset = await manager.getInstance(presetId)
|
||||
}
|
||||
// 如果没找到再查一次
|
||||
if (!preset) {
|
||||
preset = await manager.getInstance(presetId)
|
||||
}
|
||||
return preset
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
* @param {'at' | 'prefix'} toggleMode
|
||||
* @param {string} togglePrefix
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function checkChatMsg (e, toggleMode, togglePrefix) {
|
||||
if (toggleMode === 'at' && e.atBot) {
|
||||
return true
|
||||
}
|
||||
const prefixReg = new RegExp(`^#?(图片)?${togglePrefix}[^gpt][sS]*`)
|
||||
if (toggleMode === 'prefix' && e.msg.startsWith(prefixReg)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue