Merge branch 'v2' into v2

This commit is contained in:
ifeif 2023-06-06 14:34:59 +08:00 committed by GitHub
commit be91e25415
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1029 additions and 632 deletions

View file

@ -4,11 +4,14 @@ import { exec } from 'child_process'
import {
checkPnpm,
formatDuration,
parseDuration,
getAzureRoleList,
getPublicIP,
renderUrl,
getUserReplySetting,
getVitsRoleList,
getVoicevoxRoleList,
makeForwardMsg,
getDefaultReplySetting
parseDuration, processList,
renderUrl
} from '../utils/common.js'
import SydneyAIClient from '../utils/SydneyAIClient.js'
import { convertSpeaker, speakers as vitsRoleList } from '../utils/tts.js'
@ -16,9 +19,11 @@ import md5 from 'md5'
import path from 'path'
import fs from 'fs'
import loader from '../../../lib/plugins/loader.js'
import { supportConfigurations as voxRoleList } from '../utils/tts/voicevox.js'
import VoiceVoxTTS, { supportConfigurations as voxRoleList } from '../utils/tts/voicevox.js'
import { supportConfigurations as azureRoleList } from '../utils/tts/microsoft-azure.js'
let isWhiteList = true
let isSetGroup = true
export class ChatgptManagement extends plugin {
constructor (e) {
super({
@ -130,17 +135,17 @@ export class ChatgptManagement extends plugin {
fnc: 'versionChatGPTPlugin'
},
{
reg: '^#chatgpt(本群)?(群\\d+)?闭嘴',
reg: '^#chatgpt(本群)?(群\\d+)?(关闭|闭嘴|关机|休眠|下班)',
fnc: 'shutUp',
permission: 'master'
},
{
reg: '^#chatgpt(本群)?(群\\d+)?(张嘴|开口|说话|上班)',
reg: '^#chatgpt(本群)?(群\\d+)?(开启|启动|激活|张嘴|开口|说话|上班)',
fnc: 'openMouth',
permission: 'master'
},
{
reg: '^#chatgpt查看闭嘴',
reg: '^#chatgpt查看?(关闭|闭嘴|关机|休眠|下班|休眠)列表',
fnc: 'listShutUp',
permission: 'master'
},
@ -180,7 +185,7 @@ export class ChatgptManagement extends plugin {
permission: 'master'
},
{
reg: '^#chatgpt(打开|关闭|设置)?全局((图片模式|语音模式|(语音角色|角色语音|角色).*)|回复帮助)$',
reg: '^#chatgpt(打开|关闭|设置)?全局((文本模式|图片模式|语音模式|((azure|vits|vox)?语音角色|角色语音|角色).*)|回复帮助)$',
fnc: 'setDefaultReplySetting',
permission: 'master'
},
@ -202,18 +207,18 @@ export class ChatgptManagement extends plugin {
permission: 'master'
},
{
reg: '^#chatgpt(设置|添加)群聊[白黑]名单$',
reg: '^#chatgpt(设置|添加)对话[白黑]名单$',
fnc: 'setList',
permission: 'master'
},
{
reg: '^#chatgpt查看群聊[白黑]名单$',
fnc: 'checkGroupList',
reg: '^#chatgpt(查看)?对话[白黑]名单(帮助)?$',
fnc: 'checkList',
permission: 'master'
},
{
reg: '^#chatgpt(删除|移除)群聊[白黑]名单$',
fnc: 'delGroupList',
reg: '^#chatgpt(删除|移除)对话[白黑]名单$',
fnc: 'delList',
permission: 'master'
},
{
@ -244,48 +249,89 @@ export class ChatgptManagement extends plugin {
permission: 'master'
},
{
reg: '^#chatgpt角色列表$',
reg: '^#(chatgpt)?(vits|azure|vox)?语音(角色列表|服务)$',
fnc: 'getTTSRoleList'
},
{
reg: '^#chatgpt设置后台(刷新|refresh)(t|T)oken$',
fnc: 'setOpenAIPlatformToken'
},
{
reg: '^#(chatgpt)?查看回复设置$',
fnc: 'viewUserSetting'
}
]
})
}
async viewUserSetting (e) {
const userSetting = await getUserReplySetting(this.e)
const replyMsg = `${this.e.sender.user_id}的回复设置:
图片模式: ${userSetting.usePicture === true ? '开启' : '关闭'}
语音模式: ${userSetting.useTTS === true ? '开启' : '关闭'}
Vits语音角色: ${userSetting.ttsRole}
Azure语音角色: ${userSetting.ttsRoleAzure}
VoiceVox语音角色: ${userSetting.ttsRoleVoiceVox}
${userSetting.useTTS === true ? '当前语音模式为' + Config.ttsMode : ''}`
await this.reply(replyMsg.replace(/\n\s*$/, ''), e.isGroup)
return true
}
async getTTSRoleList (e) {
let userReplySetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
userReplySetting = !userReplySetting
? getDefaultReplySetting()
: JSON.parse(userReplySetting)
if (!userReplySetting.useTTS) return
const matchCommand = e.msg.match(/^#(chatgpt)?(vits|azure|vox)?语音(服务|角色列表)/)
if (matchCommand[3] === '服务') {
await this.reply(`当前支持vox、vits、azure语音服务可使用'#(vox|azure|vits)语音角色列表'查看支持的语音角色。
vits语音主要有赛马娘原神中文原神日语崩坏 3 的音色结果有随机性语调可能很奇怪
vox语音Voicevox 是一款由日本 DeNA 开发的语音合成软件它可以将文本转换为自然流畅的语音Voicevox 支持多种语言和声音可以用于制作各种语音内容如动画游戏广告等Voicevox 还提供了丰富的调整选项可以调整声音的音调速度音量等参数以满足不同需求除了桌面版软件外Voicevox 还提供了 Web 版本和 API 接口方便开发者在各种平台上使用
azure语音Azure 语音是微软 Azure 平台提供的一项语音服务它可以帮助开发者将语音转换为文本将文本转换为语音实现自然语言理解和对话等功能Azure 语音支持多种语言和声音可以用于构建各种语音应用程序如智能客服语音助手自动化电话系统等Azure 语音还提供了丰富的 API SDK方便开发者在各种平台上集成使用
`)
return true
}
let userReplySetting = await getUserReplySetting(this.e)
if (!userReplySetting.useTTS && matchCommand[2] === undefined) {
await this.reply('当前不是语音模式,如果想查看不同语音模式下支持的角色列表,可使用"#(vox|azure|vits)语音角色列表"查看')
return false
}
let ttsMode = Config.ttsMode
let roleList = []
if (ttsMode === 'vits-uma-genshin-honkai') {
const [firstHalf, secondHalf] = [vitsRoleList.slice(0, Math.floor(vitsRoleList.length / 2)).join('、'), vitsRoleList.slice(Math.floor(vitsRoleList.length / 2)).join('、')]
const [chunk1, chunk2] = [firstHalf.match(/[^、]+(?:、[^、]+){0,30}/g), secondHalf.match(/[^、]+(?:、[^、]+){0,30}/g)]
const list = [await makeForwardMsg(e, chunk1, `${Config.ttsMode}角色列表1`), await makeForwardMsg(e, chunk2, `${Config.ttsMode}角色列表2`)]
roleList = await makeForwardMsg(e, list, `${Config.ttsMode}角色列表`)
await this.reply(roleList)
return
} else if (ttsMode === 'voicevox') {
roleList = voxRoleList.map(item => item.name).join('、')
} else if (ttsMode === 'azure') {
roleList = azureRoleList.map(item => item.name).join('、')
if (matchCommand[2] === 'vits') {
roleList = getVitsRoleList(this.e)
} else if (matchCommand[2] === 'vox') {
roleList = getVoicevoxRoleList()
} else if (matchCommand[2] === 'azure') {
roleList = getAzureRoleList()
} else if (matchCommand[2] === undefined) {
switch (ttsMode) {
case 'vits-uma-genshin-honkai':
roleList = getVitsRoleList(this.e)
break
case 'voicevox':
roleList = getVoicevoxRoleList()
break
case 'azure':
if (matchCommand[2] === 'azure') {
roleList = getAzureRoleList()
}
break
default:
break
}
} else {
await this.reply('设置错误,请使用"#chatgpt语音服务"查看支持的语音配置')
return false
}
if (roleList.length > 300) {
let chunks = roleList.match(/[^、]+(?:、[^、]+){0,30}/g)
roleList = await makeForwardMsg(e, chunks, `${Config.ttsMode}角色列表`)
roleList = await makeForwardMsg(e, chunks, `${Config.ttsMode}语音角色列表`)
}
await this.reply(roleList)
}
async ttsSwitch (e) {
let userReplySetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
userReplySetting = !userReplySetting
? getDefaultReplySetting()
: JSON.parse(userReplySetting)
let userReplySetting = await getUserReplySetting(this.e)
if (!userReplySetting.useTTS) {
let replyMsg
if (userReplySetting.usePicture) {
@ -312,7 +358,6 @@ export class ChatgptManagement extends plugin {
}
async commandHelp (e) {
if (!this.e.isMaster) { return this.reply('你没有权限') }
if (/^#(chatgpt)?指令表帮助$/.exec(e.msg.trim())) {
await this.reply('#chatgpt指令表: 查看本插件的所有指令\n' +
'#chatgpt(对话|管理|娱乐|绘图|人物设定|聊天记录)指令表: 查看对应功能分类的指令表\n' +
@ -346,8 +391,8 @@ export class ChatgptManagement extends plugin {
commandSet.push({ name, dsc: plugin.dsc, rule })
}
}
if (e.msg.includes('搜索')) {
let cmd = e.msg.trim().match(/^#(chatgpt)?(对话|管理|娱乐|绘图|人物设定|聊天记录)?指令表(帮助|搜索(.+))?/)[4]
if (/^#(chatgpt)?指令表搜索(.+)/.test(e.msg.trim())) {
let cmd = e.msg.trim().match(/#(chatgpt)?指令表搜索(.+)/)[2]
if (!cmd) {
await this.reply('(⊙ˍ⊙)')
return 0
@ -393,134 +438,124 @@ export class ChatgptManagement extends plugin {
return true
}
/**
* 对原始黑白名单进行去重和去除无效群号处理
* @param whitelist
* @param blacklist
* @returns {Promise<any[][]>}
*/
async processList (whitelist, blacklist) {
let groupWhitelist = Array.isArray(whitelist)
? whitelist
: String(whitelist).split(/[,]/)
let groupBlacklist = !Array.isArray(blacklist)
? blacklist
: String(blacklist).split(/[,]/)
groupWhitelist = Array.from(new Set(groupWhitelist)).filter(value => /^[1-9]\d{8,9}$/.test(value))
groupBlacklist = Array.from(new Set(groupBlacklist)).filter(value => /^[1-9]\d{8,9}$/.test(value))
return [groupWhitelist, groupBlacklist]
}
async setList (e) {
this.setContext('saveList')
isWhiteList = e.msg.includes('白')
const listType = isWhiteList ? '白名单' : '黑名单'
await this.reply(`请发送需要设置的群聊${listType},群号间使用,隔开`, e.isGroup)
const listType = isWhiteList ? '对话白名单' : '对话黑名单'
await this.reply(`请发送需要添加的${listType}号码默认设置为添加群号需要添加QQ号时在前面添加^(例如:^123456)。`, e.isGroup)
return false
}
async saveList (e) {
if (!this.e.msg) return
const listType = isWhiteList ? '白名单' : '黑名单'
const inputMatch = this.e.msg.match(/\d+/g)
let [groupWhitelist, groupBlacklist] = await this.processList(Config.groupWhitelist, Config.groupBlacklist)
let inputList = Array.isArray(inputMatch) ? this.e.msg.match(/\d+/g).filter(value => /^[1-9]\d{8,9}$/.test(value)) : []
const listType = isWhiteList ? '对话白名单' : '对话黑名单'
const regex = /^\^?[1-9]\d{5,9}$/
const wrongInput = []
const inputSet = new Set()
const inputList = this.e.msg.split(/[,]/).reduce((acc, value) => {
if (value.length > 11 || !regex.test(value)) {
wrongInput.push(value)
} else if (!inputSet.has(value)) {
inputSet.add(value)
acc.push(value)
}
return acc
}, [])
if (!inputList.length) {
await this.reply('无效输入,请在检查群号是否正确后重新输入', e.isGroup)
let replyMsg = '名单更新失败,请在检查输入是否正确后重新输入。'
if (wrongInput.length) replyMsg += `\n${wrongInput.length ? '检测到以下错误输入:"' + wrongInput.join('') + '",已自动忽略。' : ''}`
await this.reply(replyMsg, e.isGroup)
return false
}
inputList = Array.from(new Set(inputList))
let whitelist = []
let blacklist = []
for (const element of inputList) {
if (listType === '白名单') {
groupWhitelist = groupWhitelist.filter(item => item !== element)
whitelist.push(element)
} else {
groupBlacklist = groupBlacklist.filter(item => item !== element)
blacklist.push(element)
}
}
if (!(whitelist.length || blacklist.length)) {
await this.reply('无效输入,请在检查群号是否正确或重复添加后重新输入', e.isGroup)
return false
let [whitelist, blacklist] = processList(Config.whitelist, Config.blacklist)
whitelist = [...inputList, ...whitelist]
blacklist = [...inputList, ...blacklist]
if (listType === '对话白名单') {
Config.whitelist = Array.from(new Set(whitelist))
} else {
if (listType === '白名单') {
Config.groupWhitelist = groupWhitelist
.filter(group => group !== '')
.concat(whitelist)
} else {
Config.groupBlacklist = groupBlacklist
.filter(group => group !== '')
.concat(blacklist)
}
Config.blacklist = Array.from(new Set(blacklist))
}
let replyMsg = `群聊${listType}已更新,可通过\n'#chatgpt查看群聊${listType}'查看最新名单\n'#chatgpt移除群聊${listType}'管理名单`
let replyMsg = `${listType}已更新,可通过\n"#chatgpt查看${listType}" 查看最新名单\n"#chatgpt移除${listType}" 管理名单${wrongInput.length ? '\n检测到以下错误输入"' + wrongInput.join('') + '",已自动忽略。' : ''}`
if (e.isPrivate) {
replyMsg += `\n当前群聊${listType}为:${listType === '白名单' ? Config.groupWhitelist : Config.groupBlacklist}`
replyMsg += `\n当前${listType}为:${listType === '对话白名单' ? Config.whitelist : Config.blacklist}`
}
await this.reply(replyMsg, e.isGroup)
this.finish('saveList')
}
async checkGroupList (e) {
async checkList (e) {
if (e.msg.includes('帮助')) {
await this.reply('默认设置为添加群号需要拉黑QQ号时在前面添加^(例如:^123456),可一次性混合输入多个配置号码,错误项会自动忽略。具体使用指令可通过 "#指令表搜索名单" 查看,白名单优先级高于黑名单。')
return true
}
isWhiteList = e.msg.includes('白')
const list = isWhiteList ? Config.groupWhitelist : Config.groupBlacklist
const list = isWhiteList ? Config.whitelist : Config.blacklist
const listType = isWhiteList ? '白名单' : '黑名单'
const replyMsg = list.length ? `当前群聊${listType}为:${list}` : `当前没有设置任何群聊${listType}`
const replyMsg = list.length ? `当前${listType}为:${list}` : `当前没有设置任何${listType}`
await this.reply(replyMsg, e.isGroup)
return false
}
async delGroupList (e) {
async delList (e) {
isWhiteList = e.msg.includes('白')
const listType = isWhiteList ? '白名单' : '黑名单'
const listType = isWhiteList ? '对话白名单' : '对话黑名单'
let replyMsg = ''
if (Config.groupWhitelist.length === 0 && Config.groupBlacklist.length === 0) {
replyMsg = `当前群聊(白|黑)名单为空,请先添加${listType}吧~`
} else if ((listType === '白名单' && !Config.groupWhitelist.length) || (listType === '黑名单' && !Config.groupBlacklist.length)) {
replyMsg = `当前群聊${listType}为空,请先添加吧~`
if (Config.whitelist.length === 0 && Config.blacklist.length === 0) {
replyMsg = '当前对话(白|黑)名单都是空哒,请先添加吧~'
} else if ((listType === '对话白名单' && !Config.whitelist.length) || (listType === '对话黑名单' && !Config.blacklist.length)) {
replyMsg = `当前${listType}为空,请先添加吧~`
}
if (replyMsg) {
await this.reply(replyMsg, e.isGroup)
return false
}
this.setContext('confirmDelGroup')
await this.reply(`请发送需要删除的群聊${listType},群号间使用,隔开。输入‘全部删除’清空${listType}`, e.isGroup)
this.setContext('confirmDelList')
await this.reply(`请发送需要删除的${listType}码,号码间使用,隔开。输入‘全部删除’清空${listType}${e.isPrivate ? '\n当前' + listType + '为:' + (listType === '对话白名单' ? Config.whitelist : Config.blacklist) : ''}`, e.isGroup)
return false
}
async confirmDelGroup (e) {
async confirmDelList (e) {
if (!this.e.msg) return
const isAllDeleted = this.e.msg.trim() === '全部删除'
const groupNumRegex = /^[1-9]\d{8,9}$/
const inputMatch = this.e.msg.match(/\d+/g)
const validGroups = Array.isArray(inputMatch) ? inputMatch.filter(groupNum => groupNumRegex.test(groupNum)) : []
let [groupWhitelist, groupBlacklist] = await this.processList(Config.groupWhitelist, Config.groupBlacklist)
const regex = /^\^?[1-9]\d{5,9}$/
const wrongInput = []
const inputSet = new Set()
const inputList = this.e.msg.split(/[,]/).reduce((acc, value) => {
if (value.length > 11 || !regex.test(value)) {
wrongInput.push(value)
} else if (!inputSet.has(value)) {
inputSet.add(value)
acc.push(value)
}
return acc
}, [])
if (!inputList.length && !isAllDeleted) {
let replyMsg = '名单更新失败,请在检查输入是否正确后重新输入。'
if (wrongInput.length) replyMsg += `${wrongInput.length ? '\n检测到以下错误输入"' + wrongInput.join('') + '",已自动忽略。' : ''}`
await this.reply(replyMsg, e.isGroup)
return false
}
let [whitelist, blacklist] = processList(Config.whitelist, Config.blacklist)
if (isAllDeleted) {
Config.groupWhitelist = isWhiteList ? [] : groupWhitelist
Config.groupBlacklist = !isWhiteList ? [] : groupBlacklist
Config.whitelist = isWhiteList ? [] : whitelist
Config.blacklist = !isWhiteList ? [] : blacklist
} else {
if (!validGroups.length) {
await this.reply('无效输入,请在检查群号是否正确后重新输入', e.isGroup)
return false
} else {
for (const element of validGroups) {
if (isWhiteList) {
Config.groupWhitelist = groupWhitelist.filter(item => item !== element)
} else {
Config.groupBlacklist = groupBlacklist.filter(item => item !== element)
}
for (const element of inputList) {
if (isWhiteList) {
Config.whitelist = whitelist.filter(item => item !== element)
} else {
Config.blacklist = blacklist.filter(item => item !== element)
}
}
}
const listType = isWhiteList ? '白名单' : '黑名单'
let replyMsg = `群聊${listType}已更新,可通过'#chatgpt查看群聊${listType}'命令查看最新名单`
const listType = isWhiteList ? '对话白名单' : '对话黑名单'
let replyMsg = `${listType}已更新,可通过 "#chatgpt查看${listType}" 命令查看最新名单${wrongInput.length ? '\n检测到以下错误输入"' + wrongInput.join('') + '",已自动忽略。' : ''}`
if (e.isPrivate) {
replyMsg += `\n当前群聊${listType}为:${listType === '白名单' ? Config.groupWhitelist : Config.groupBlacklist}`
const list = isWhiteList ? Config.whitelist : Config.blacklist
replyMsg = list.length ? `\n当前${listType}为:${list}` : `当前没有设置任何${listType}`
}
await this.reply(replyMsg, e.isGroup)
this.finish('confirmDelGroup')
this.finish('confirmDelList')
}
async enablePrivateChat (e) {
@ -553,10 +588,14 @@ export class ChatgptManagement extends plugin {
}
async setDefaultReplySetting (e) {
const reg = /^#chatgpt(打开|关闭|设置)?全局((文本模式|图片模式|语音模式|(语音角色|角色语音|角色).*)|回复帮助)/
const reg = /^#chatgpt(打开|关闭|设置)?全局((文本模式|图片模式|语音模式|((azure|vits|vox)?语音角色|角色语音|角色)(.*))|回复帮助)/
const matchCommand = e.msg.match(reg)
const settingType = matchCommand[2]
let replyMsg = ''
let ttsSupportKinds = []
if (Config.azureTTSKey) ttsSupportKinds.push(1)
if (Config.ttsSpace) ttsSupportKinds.push(2)
if (Config.voicevoxSpace) ttsSupportKinds.push(3)
switch (settingType) {
case '图片模式':
if (matchCommand[1] === '打开') {
@ -591,8 +630,8 @@ export class ChatgptManagement extends plugin {
replyMsg = '请使用“#chatgpt打开全局文本模式”或“#chatgpt关闭全局文本模式”命令来设置回复模式'
} break
case '语音模式':
if (!Config.ttsSpace) {
replyMsg = '您没有配置VITS API,请前往锅巴面板进行配置'
if (!ttsSupportKinds.length) {
replyMsg = '您没有配置任何语音服务,请前往锅巴面板进行配置'
break
}
if (matchCommand[1] === '打开') {
@ -610,25 +649,68 @@ export class ChatgptManagement extends plugin {
replyMsg = '请使用“#chatgpt打开全局语音模式”或“#chatgpt关闭全局语音模式”命令来设置回复模式'
} break
case '回复帮助':
replyMsg = '可使用以下命令配置全局回复:\n#chatgpt(打开/关闭)全局(语音/图片/文本)模式\n#chatgpt设置全局(语音角色|角色语音|角色)+角色名称(留空则为随机)'
replyMsg = '可使用以下命令配置全局回复:\n#chatgpt(打开/关闭)全局(语音/图片/文本)模式\n#chatgpt设置全局(vox|azure|vits)语音角色+角色名称(留空则为随机)\n'
break
default:
if (!Config.ttsSpace) {
replyMsg = '您没有配置VITS API,请前往锅巴面板进行配置'
if (!ttsSupportKinds) {
replyMsg = '您没有配置任何语音服务,请前往锅巴面板进行配置'
break
}
if (settingType.match(/(语音角色|角色语音|角色)/)) {
const speaker = matchCommand[2].replace(/(语音角色|角色语音|角色)/, '').trim() || ''
if (!speaker.length) {
replyMsg = 'ChatGpt将随机挑选角色回复'
Config.defaultTTSRole = ''
const voiceKind = matchCommand[5]
let speaker = matchCommand[6] || ''
if (voiceKind === undefined) {
await this.reply('请选择需要设置的语音类型。使用"#chatgpt语音服务"查看支持的语音类型')
return false
}
if (!speaker.length || speaker === '随机') {
replyMsg = `设置成功,ChatGpt将在${voiceKind}语音模式下随机挑选角色进行回复`
if (voiceKind === 'vits') Config.defaultTTSRole = '随机'
if (voiceKind === 'azure') Config.azureTTSSpeaker = '随机'
if (voiceKind === 'vox') Config.voicevoxTTSSpeaker = '随机'
} else {
const ttsRole = convertSpeaker(speaker)
if (vitsRoleList.includes(ttsRole)) {
Config.defaultTTSRole = ttsRole
replyMsg = `ChatGPT默认语音角色已被设置为“${ttsRole}`
if (ttsSupportKinds.includes(1) && voiceKind === 'azure') {
if (getAzureRoleList().includes(speaker)) {
Config.defaultUseTTS = azureRoleList.filter(s => s.name === speaker)[0].code
replyMsg = `ChatGPT默认语音角色已被设置为“${speaker}`
} else {
await this.reply(`抱歉,没有"${speaker}"这个角色目前azure模式下支持的角色有${azureRoleList.map(item => item.name).join('、')}`)
return false
}
} else if (ttsSupportKinds.includes(2) && voiceKind === 'vits') {
const ttsRole = convertSpeaker(speaker)
if (vitsRoleList.includes(ttsRole)) {
Config.defaultTTSRole = ttsRole
replyMsg = `ChatGPT默认语音角色已被设置为“${ttsRole}`
} else {
replyMsg = `抱歉,我还不认识“${ttsRole}”这个语音角色,可使用'#vits角色列表'查看可配置的角色`
}
} else if (ttsSupportKinds.includes(3) && voiceKind === 'vox') {
if (getVoicevoxRoleList().includes(speaker)) {
let regex = /^(.*?)-(.*)$/
let match = regex.exec(speaker)
let style = null
if (match) {
speaker = match[1]
style = match[2]
}
let chosen = VoiceVoxTTS.supportConfigurations.filter(s => s.name === speaker)
if (chosen.length === 0) {
await this.reply(`抱歉,没有"${speaker}"这个角色目前voicevox模式下支持的角色有${VoiceVoxTTS.supportConfigurations.map(item => item.name).join('、')}`)
break
}
if (style && !chosen[0].styles.find(item => item.name === style)) {
await this.reply(`抱歉,"${speaker}"这个角色没有"${style}"这个风格,目前支持的风格有${chosen[0].styles.map(item => item.name).join('、')}`)
break
}
Config.ttsRoleVoiceVox = chosen[0].name + (style ? `-${style}` : '')
replyMsg = `ChatGPT默认语音角色已被设置为“${speaker}`
} else {
await this.reply(`抱歉,没有"${speaker}"这个角色目前voicevox模式下支持的角色有${voxRoleList.map(item => item.name).join('、')}`)
return false
}
} else {
replyMsg = `抱歉,我还不认识“${ttsRole}”这个语音角色`
replyMsg = `${voiceKind}语音角色设置错误,请检查语音配置~`
}
}
} else {
@ -1004,32 +1086,32 @@ export class ChatgptManagement extends plugin {
poe: 'Poe'
}
let modeText = modeMap[mode || 'api']
let message = ` API模式和浏览器模式如何选择
let message = `API模式和浏览器模式如何选择
// eslint-disable-next-line no-irregular-whitespace
API模式会调用OpenAI官方提供的gpt-3.5-turbo API只需要提供API Key一般情况下该种方式响应速度更快不会像chatGPT官网一样总出现不可用的现象但注意gpt-3.5-turbo的API调用是收费的新用户有18美元试用金可用于支付价格为$0.0020/1K tokens.(问题和回答加起来算token)
API3模式会调用官网反代API他会帮你绕过CF防护需要提供ChatGPT的Token效果与官网和浏览器一致设置token指令#chatgpt设置token
API模式会调用 OpenAI 官方提供的 gpt-3.5-turbo API只需要提供 API Key一般情况下该种方式响应速度更快不会像 chatGPT 官网一样总出现不可用的现象但要注意 gpt-3.5-turbo API 调用是收费的新用户有 $5 的试用金可用于支付价格为 $0.0020/1K tokens问题和回答加起来算 token
浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站使得获得和官方以及API2模式一模一样的回复质量同时保证安全性缺点是本方法对环境要求较高需要提供桌面环境和一个可用的代理能够访问ChatGPT的IP地址且响应速度不如API而且高峰期容易无法使用
API3 模式会调用官网反代 API它会帮你绕过 CF 防护需要提供 ChatGPT Token效果与官网和浏览器一致设置 Token 指令#chatgpt设置token
必应Bing将调用微软新必应接口进行对话需要在必应网页能够正常使用新必应且设置有效的Bing 登录Cookie方可使用#chatgpt设置必应token
自建ChatGLM模式会调用自建的ChatGLM-6B服务器API进行对话需要自建参考https://github.com/ikechan8370/SimpleChatGLM6BAPI
Claude模式会调用Slack中的Claude机器人进行对话与其他模式不同的是全局共享一个对话配置参考https://ikechan8370.com/archives/chatgpt-plugin-for-yunzaipei-zhi-slack-claude
Poe模式会调用Poe中的Claude-instant进行对话需要提供cookie#chatgpt设置PoeToken
浏览器模式通过在本地启动 Chrome 等浏览器模拟用户访问 ChatGPT 网站使得获得和官方以及 API2 模式一模一样的回复质量同时保证安全性缺点是本方法对环境要求较高需要提供桌面环境和一个可用的代理能够访问 ChatGPT IP 地址且响应速度不如 API而且高峰期容易无法使用
您可以使用#chatgpt切换浏览器/API/API3/Bing/ChatGLM/Claude/Poe来切换到指定模式
必应Bing将调用微软新必应接口进行对话需要在必应网页能够正常使用新必应且设置有效的 Bing 登录 Cookie 方可使用#chatgpt设置必应 Token
当前为${modeText}模式
`
自建 ChatGLM 模式会调用自建的 ChatGLM-6B 服务器 API 进行对话需要自建参考 https://github.com/ikechan8370/SimpleChatGLM6BAPI。
Claude 模式会调用 Slack 中的 Claude 机器人进行对话与其他模式不同的是全局共享一个对话配置参考 https://ikechan8370.com/archives/chatgpt-plugin-for-yunzaipei-zhi-slack-claude。
Poe 模式会调用 Poe 中的 Claude-instant 进行对话需要提供 Cookie#chatgpt设置 Poe Token
星火 模式会调用科大讯飞推出的新一代认知智能大模型 '星火认知大模型' 进行对话需要提供Cookie#chatgpt设置星火token
您可以使用 "#chatgpt切换浏览器/API/API3/Bing/ChatGLM/Claude/Poe/星火" 来切换到指定模式
当前为 ${modeText} 模式`
await this.reply(message)
}
async shutUp (e) {
let duration = e.msg.replace(/^#chatgpt(本群)?(群\d+)?闭嘴/, '')
let duration = e.msg.replace(/^#chatgpt(本群)?(群\d+)?(关闭|闭嘴|关机|休眠|下班)/, '')
let scope
let time = 3600000
if (duration === '永久') {
@ -1037,20 +1119,20 @@ export class ChatgptManagement extends plugin {
} else if (duration) {
time = parseDuration(duration)
}
const match = e.msg.match(/#chatgpt群(\d+)闭嘴(.*)/)
const match = e.msg.match(/#chatgpt群(\d+)?(关闭|闭嘴|关机|休眠|下班)(.*)/)
if (e.msg.indexOf('本群') > -1) {
if (e.isGroup) {
scope = e.group.group_id
if (await redis.get(`CHATGPT:SHUT_UP:${scope}`)) {
await redis.del(`CHATGPT:SHUT_UP:${scope}`)
await redis.set(`CHATGPT:SHUT_UP:${scope}`, '1', { EX: time })
await e.reply(`好的,从现在开始我会在当前群聊闭嘴${formatDuration(time)}`)
await e.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`)
} else {
await redis.set(`CHATGPT:SHUT_UP:${scope}`, '1', { EX: time })
await e.reply(`好的,从现在开始我会在当前群聊闭嘴${formatDuration(time)}`)
await e.reply(`好的,已切换休眠状态:倒计时${formatDuration(time)}`)
}
} else {
await e.reply('本群是指?你也没在群聊里让我闭嘴啊?')
await e.reply('主人,这里好像不是群哦')
return false
}
} else if (match) {
@ -1059,23 +1141,23 @@ export class ChatgptManagement extends plugin {
if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) {
await redis.del(`CHATGPT:SHUT_UP:${groupId}`)
await redis.set(`CHATGPT:SHUT_UP:${groupId}`, '1', { EX: time })
await e.reply(`好的,从现在开始我会在群聊${groupId}闭嘴${formatDuration(time)}`)
await e.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`)
} else {
await redis.set(`CHATGPT:SHUT_UP:${groupId}`, '1', { EX: time })
await e.reply(`好的,从现在开始我会在群聊${groupId}闭嘴${formatDuration(time)}`)
await e.reply(`好的,即将在群${groupId}中休眠${formatDuration(time)}`)
}
} else {
await e.reply('这是什么群?')
await e.reply('主人还没告诉我群号呢')
return false
}
} else {
if (await redis.get('CHATGPT:SHUT_UP:ALL')) {
await redis.del('CHATGPT:SHUT_UP:ALL')
await redis.set('CHATGPT:SHUT_UP:ALL', '1', { EX: time })
await e.reply(`好的,我会再闭嘴${formatDuration(time)}`)
await e.reply(`好的,我会延长休眠时间${formatDuration(time)}`)
} else {
await redis.set('CHATGPT:SHUT_UP:ALL', '1', { EX: time })
await e.reply(`好的,我会闭嘴${formatDuration(time)}`)
await e.reply(`好的,我会延长休眠时间${formatDuration(time)}`)
}
}
}
@ -1084,36 +1166,36 @@ export class ChatgptManagement extends plugin {
const match = e.msg.match(/^#chatgpt群(\d+)/)
if (e.msg.indexOf('本群') > -1) {
if (await redis.get('CHATGPT:SHUT_UP:ALL')) {
await e.reply('主人,我现在全局闭嘴呢,你让我在这个群张嘴咱也不敢张啊')
await e.reply('当前为休眠模式,没办法做出回应呢')
return false
}
if (e.isGroup) {
let scope = e.group.group_id
if (await redis.get(`CHATGPT:SHUT_UP:${scope}`)) {
await redis.del(`CHATGPT:SHUT_UP:${scope}`)
await e.reply('好的主人,我终于又可以在本群说话了')
await e.reply('好的主人,我又可以和大家聊天啦')
} else {
await e.reply('啊?我也没闭嘴啊?')
await e.reply('主人,我已经启动过了哦')
}
} else {
await e.reply('本群是指?你也没在群聊里让我张嘴啊?')
await e.reply('主人,这里好像不是群哦')
return false
}
} else if (match) {
if (await redis.get('CHATGPT:SHUT_UP:ALL')) {
await e.reply('主人,我现在全局闭嘴呢,你让我在那个群张嘴咱也不敢张啊')
await e.reply('当前为休眠模式,没办法做出回应呢')
return false
}
const groupId = parseInt(match[1], 10)
if (Bot.getGroupList().get(groupId)) {
if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) {
await redis.del(`CHATGPT:SHUT_UP:${groupId}`)
await e.reply(`好的主人,我终于又可以在群${groupId}说话`)
await e.reply(`好的主人,我终于又可以在群${groupId}和大家聊天`)
} else {
await e.reply(`啊?我也没在群${groupId}闭嘴啊?`)
await e.reply(`主人,我在群${groupId}中已经是启动状态了哦`)
}
} else {
await e.reply('这是什么群?')
await e.reply('主人还没告诉我群号呢')
return false
}
} else {
@ -1123,14 +1205,14 @@ export class ChatgptManagement extends plugin {
for (let i = 0; i < keys.length; i++) {
await redis.del(keys[i])
}
await e.reply('好的,我会结束所有闭嘴')
await e.reply('好的,我会开启所有群聊响应')
} else if (keys || keys.length > 0) {
for (let i = 0; i < keys.length; i++) {
await redis.del(keys[i])
}
await e.reply('好的,我会结束所有闭嘴?')
await e.reply('已经开启过全群响应啦')
} else {
await e.reply('我没有在任何地方闭嘴啊?')
await e.reply('我没有在任何群休眠哦')
}
}
}
@ -1138,7 +1220,7 @@ export class ChatgptManagement extends plugin {
async listShutUp () {
let keys = await redis.keys('CHATGPT:SHUT_UP:*')
if (!keys || keys.length === 0) {
await this.reply('我没有在任何群闭嘴', true)
await this.reply('已经开启过全群响应啦', true)
} else {
let list = []
for (let i = 0; i < keys.length; i++) {