mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-17 22:07:10 +00:00
Merge branch 'v2' into v2
This commit is contained in:
commit
be91e25415
26 changed files with 1029 additions and 632 deletions
211
apps/chat.js
211
apps/chat.js
|
|
@ -7,11 +7,10 @@ import { ChatGPTAPI } from 'chatgpt'
|
|||
import { BingAIClient } from '@waylaidwanderer/chatgpt-api'
|
||||
import SydneyAIClient from '../utils/SydneyAIClient.js'
|
||||
import { PoeClient } from '../utils/poe/index.js'
|
||||
import AzureTTS from '../utils/tts/microsoft-azure.js'
|
||||
import AzureTTS, { supportConfigurations } from '../utils/tts/microsoft-azure.js'
|
||||
import VoiceVoxTTS from '../utils/tts/voicevox.js'
|
||||
import { translate } from '../utils/translate.js'
|
||||
import fs from 'fs'
|
||||
import { getImg, getImageOcrText } from './entertainment.js'
|
||||
import {
|
||||
render, renderUrl,
|
||||
getMessageById,
|
||||
|
|
@ -21,7 +20,7 @@ import {
|
|||
completeJSON,
|
||||
isImage,
|
||||
getUserData,
|
||||
getDefaultReplySetting, isCN, getMasterQQ
|
||||
getDefaultReplySetting, isCN, getMasterQQ, getUserReplySetting, getImageOcrText, getImg, processList
|
||||
} from '../utils/common.js'
|
||||
import { ChatGPTPuppeteer } from '../utils/browser.js'
|
||||
import { KeyvFile } from 'keyv-file'
|
||||
|
|
@ -544,12 +543,7 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async switch2Text (e) {
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (!userSetting) {
|
||||
userSetting = getDefaultReplySetting()
|
||||
} else {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
}
|
||||
let userSetting = await getUserReplySetting(this.e)
|
||||
userSetting.usePicture = false
|
||||
userSetting.useTTS = false
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
|
|
@ -577,12 +571,7 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
break
|
||||
}
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (!userSetting) {
|
||||
userSetting = getDefaultReplySetting()
|
||||
} else {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
}
|
||||
let userSetting = await getUserReplySetting(this.e)
|
||||
userSetting.useTTS = true
|
||||
userSetting.usePicture = false
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
|
|
@ -629,37 +618,35 @@ export class chatgpt extends plugin {
|
|||
let speaker = e.msg.replace(regex, '').trim() || '随机'
|
||||
switch (Config.ttsMode) {
|
||||
case 'vits-uma-genshin-honkai': {
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (!userSetting) {
|
||||
userSetting = getDefaultReplySetting()
|
||||
} else {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
}
|
||||
let userSetting = await getUserReplySetting(this.e)
|
||||
userSetting.ttsRole = convertSpeaker(speaker)
|
||||
if (speakers.indexOf(userSetting.ttsRole) >= 0) {
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
await this.reply(`您的默认语音角色已被设置为”${userSetting.ttsRole}“`)
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 "${userSetting.ttsRole}" `)
|
||||
} else if (speaker === '随机') {
|
||||
userSetting.ttsRole = '随机'
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 "随机" `)
|
||||
} else {
|
||||
await this.reply(`抱歉,"${userSetting.ttsRole}"我还不认识呢`)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'azure': {
|
||||
let userSetting = await getUserReplySetting(this.e)
|
||||
let chosen = AzureTTS.supportConfigurations.filter(s => s.name === speaker)
|
||||
if (chosen.length === 0) {
|
||||
if (speaker === '随机') {
|
||||
userSetting.ttsRoleAzure = '随机'
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 "随机" `)
|
||||
} else if (chosen.length === 0) {
|
||||
await this.reply(`抱歉,没有"${speaker}"这个角色,目前azure模式下支持的角色有${AzureTTS.supportConfigurations.map(item => item.name).join('、')}`)
|
||||
} else {
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (!userSetting) {
|
||||
userSetting = getDefaultReplySetting()
|
||||
} else {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
}
|
||||
userSetting.ttsRoleAzure = chosen[0].code
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
// Config.azureTTSSpeaker = chosen[0].code
|
||||
const supportEmotion = AzureTTS.supportConfigurations.find(config => config.name === speaker)?.emotion
|
||||
await this.reply(`您的默认语音角色已被设置为 ${speaker}-${chosen[0].gender}-${chosen[0].languageDetail} ${supportEmotion && Config.azureTTSEmotion ? ',此角色支持多情绪配置,建议重新使用设定并结束对话以获得最佳体验!' : ''}`)
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 ${speaker}-${chosen[0].gender}-${chosen[0].languageDetail} ${supportEmotion && Config.azureTTSEmotion ? ',此角色支持多情绪配置,建议重新使用设定并结束对话以获得最佳体验!' : ''}`)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
@ -671,6 +658,13 @@ export class chatgpt extends plugin {
|
|||
speaker = match[1]
|
||||
style = match[2]
|
||||
}
|
||||
let userSetting = await getUserReplySetting(e)
|
||||
if (speaker === '随机') {
|
||||
userSetting.ttsRoleVoiceVox = '随机'
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 "随机" `)
|
||||
break
|
||||
}
|
||||
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('、')}`)
|
||||
|
|
@ -680,15 +674,9 @@ export class chatgpt extends plugin {
|
|||
await this.reply(`抱歉,"${speaker}"这个角色没有"${style}"这个风格,目前支持的风格有${chosen[0].styles.map(item => item.name).join('、')}`)
|
||||
break
|
||||
}
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (!userSetting) {
|
||||
userSetting = getDefaultReplySetting()
|
||||
} else {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
}
|
||||
userSetting.ttsRoleVoiceVox = chosen[0].name + (style ? `-${style}` : '')
|
||||
await redis.set(`CHATGPT:USER:${e.sender.user_id}`, JSON.stringify(userSetting))
|
||||
await this.reply(`您的默认语音角色已被设置为”${userSetting.ttsRoleVoiceVox}“`)
|
||||
await this.reply(`当前语音模式为${Config.ttsMode},您的默认语音角色已被设置为 "${userSetting.ttsRoleVoiceVox}" `)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -698,23 +686,6 @@ export class chatgpt extends plugin {
|
|||
* #chatgpt
|
||||
*/
|
||||
async chatgpt (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
// await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (e.isGroup) {
|
||||
let cm = new ChatgptManagement()
|
||||
let [groupWhitelist, groupBlacklist] = await cm.processList(Config.groupWhitelist, Config.groupBlacklist)
|
||||
// logger.info('groupWhitelist:', Config.groupWhitelist, 'groupBlacklist', Config.groupBlacklist)
|
||||
const whitelist = groupWhitelist.filter(group => group.trim())
|
||||
if (whitelist.length > 0 && !whitelist.includes(e.group_id.toString())) {
|
||||
return false
|
||||
}
|
||||
const blacklist = groupBlacklist.filter(group => group.trim())
|
||||
if (blacklist.length > 0 && blacklist.includes(e.group_id.toString())) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
let prompt
|
||||
if (this.toggleMode === 'at') {
|
||||
if (!e.raw_message || e.msg?.startsWith('#')) {
|
||||
|
|
@ -781,15 +752,24 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async abstractChat (e, prompt, use) {
|
||||
let userSetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
if (userSetting) {
|
||||
userSetting = JSON.parse(userSetting)
|
||||
if (Object.keys(userSetting).indexOf('useTTS') < 0) {
|
||||
userSetting.useTTS = Config.defaultUseTTS
|
||||
}
|
||||
} else {
|
||||
userSetting = getDefaultReplySetting()
|
||||
// 关闭私聊通道后不回复
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
return false
|
||||
}
|
||||
// 黑白名单过滤对话
|
||||
let [whitelist, blacklist] = processList(Config.whitelist, Config.blacklist)
|
||||
if (whitelist.length > 0) {
|
||||
if (e.isGroup && !whitelist.includes(e.group_id.toString())) return false
|
||||
const list = whitelist.filter(elem => elem.startsWith('^')).map(elem => elem.slice(1))
|
||||
if (!list.includes(e.sender.user_id.toString())) return false
|
||||
}
|
||||
if (blacklist.length > 0) {
|
||||
if (e.isGroup && blacklist.includes(e.group_id.toString())) return false
|
||||
const list = blacklist.filter(elem => elem.startsWith('^')).map(elem => elem.slice(1))
|
||||
if (list.includes(e.sender.user_id.toString())) return false
|
||||
}
|
||||
|
||||
let userSetting = await getUserReplySetting(this.e)
|
||||
let useTTS = !!userSetting.useTTS
|
||||
let speaker
|
||||
if (Config.ttsMode === 'vits-uma-genshin-honkai') {
|
||||
|
|
@ -869,10 +849,7 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
}
|
||||
const emotionFlag = await redis.get(`CHATGPT:WRONG_EMOTION:${e.sender.user_id}`)
|
||||
let userReplySetting = await redis.get(`CHATGPT:USER:${e.sender.user_id}`)
|
||||
userReplySetting = !userReplySetting
|
||||
? getDefaultReplySetting()
|
||||
: JSON.parse(userReplySetting)
|
||||
let userReplySetting = await getUserReplySetting(this.e)
|
||||
// 图片模式就不管了,降低抱歉概率
|
||||
if (Config.ttsMode === 'azure' && Config.enhanceAzureTTSEmotion && userReplySetting.useTTS === true && await AzureTTS.getEmotionPrompt(e)) {
|
||||
switch (emotionFlag) {
|
||||
|
|
@ -1163,10 +1140,23 @@ export class chatgpt extends plugin {
|
|||
await this.reply('合成语音发生错误~')
|
||||
}
|
||||
} else if (Config.ttsMode === 'azure' && Config.azureTTSKey) {
|
||||
const ttsRoleAzure = userReplySetting.ttsRoleAzure
|
||||
const isEn = AzureTTS.supportConfigurations.find(config => config.code === ttsRoleAzure)?.language.includes('en')
|
||||
if (isEn) {
|
||||
ttsResponse = (await translate(ttsResponse, '英')).replace('\n', '')
|
||||
if (speaker !== '随机') {
|
||||
let languagePrefix = AzureTTS.supportConfigurations.find(config => config.code === speaker).languageDetail.charAt(0)
|
||||
languagePrefix = languagePrefix.startsWith('E') ? '英' : languagePrefix
|
||||
ttsResponse = (await translate(ttsResponse, languagePrefix)).replace('\n', '')
|
||||
} else {
|
||||
let role, languagePrefix
|
||||
role = AzureTTS.supportConfigurations[Math.floor(Math.random() * supportConfigurations.length)]
|
||||
speaker = role.code
|
||||
languagePrefix = role.languageDetail.charAt(0).startsWith('E') ? '英' : role.languageDetail.charAt(0)
|
||||
ttsResponse = (await translate(ttsResponse, languagePrefix)).replace('\n', '')
|
||||
if (role?.emotion) {
|
||||
const keys = Object.keys(role.emotion)
|
||||
emotion = keys[Math.floor(Math.random() * keys.length)]
|
||||
}
|
||||
logger.info('using speaker: ' + speaker)
|
||||
logger.info('using language: ' + languagePrefix)
|
||||
logger.info('using emotion: ' + emotion)
|
||||
}
|
||||
let ssml = AzureTTS.generateSsml(ttsResponse, {
|
||||
speaker,
|
||||
|
|
@ -1177,6 +1167,7 @@ export class chatgpt extends plugin {
|
|||
speaker
|
||||
}, await ssml)
|
||||
} else if (Config.ttsMode === 'voicevox' && Config.voicevoxSpace) {
|
||||
ttsResponse = (await translate(ttsResponse, '日')).replace('\n', '')
|
||||
wav = await VoiceVoxTTS.generateAudio(ttsResponse, {
|
||||
speaker
|
||||
})
|
||||
|
|
@ -1256,10 +1247,6 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async chatgpt1 (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (!Config.allowOtherMode) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1279,10 +1266,6 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async chatgpt3 (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (!Config.allowOtherMode) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1321,10 +1304,6 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async bing (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (!Config.allowOtherMode) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1344,10 +1323,6 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
|
||||
async claude (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
// await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (!Config.allowOtherMode) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1365,11 +1340,8 @@ export class chatgpt extends plugin {
|
|||
await this.abstractChat(e, prompt, 'claude')
|
||||
return true
|
||||
}
|
||||
|
||||
async xh (e) {
|
||||
if (!e.isMaster && e.isPrivate && !Config.enablePrivateChat) {
|
||||
// await this.reply('ChatGpt私聊通道已关闭。')
|
||||
return false
|
||||
}
|
||||
if (!Config.allowOtherMode) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1650,7 +1622,7 @@ export class chatgpt extends plugin {
|
|||
// 如果token曾经有异常,则清除异常
|
||||
let Tokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS'))
|
||||
const TokenIndex = Tokens.findIndex(element => element.Token === abtrs.bingToken)
|
||||
if (Tokens[TokenIndex].exception) {
|
||||
if (TokenIndex > 0 && Tokens[TokenIndex].exception) {
|
||||
delete Tokens[TokenIndex].exception
|
||||
await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(Tokens))
|
||||
}
|
||||
|
|
@ -1672,21 +1644,22 @@ export class chatgpt extends plugin {
|
|||
// 不减次数
|
||||
} else if (message && typeof message === 'string' && message.indexOf('UnauthorizedRequest') > -1) {
|
||||
// token过期了
|
||||
let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS'))
|
||||
const badBingToken = bingTokens.findIndex(element => element.Token === bingToken)
|
||||
// 可能是微软抽风,给三次机会
|
||||
if (bingTokens[badBingToken].exception) {
|
||||
if (bingTokens[badBingToken].exception <= 3) {
|
||||
bingTokens[badBingToken].exception += 1
|
||||
} else {
|
||||
bingTokens[badBingToken].exception = 0
|
||||
bingTokens[badBingToken].State = '过期'
|
||||
}
|
||||
} else {
|
||||
bingTokens[badBingToken].exception = 1
|
||||
}
|
||||
await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(bingTokens))
|
||||
logger.warn(`token${bingToken}已过期`)
|
||||
// let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS'))
|
||||
// const badBingToken = bingTokens.findIndex(element => element.Token === bingToken)
|
||||
// // 可能是微软抽风,给三次机会
|
||||
// if (bingTokens[badBingToken].exception) {
|
||||
// if (bingTokens[badBingToken].exception <= 3) {
|
||||
// bingTokens[badBingToken].exception += 1
|
||||
// } else {
|
||||
// bingTokens[badBingToken].exception = 0
|
||||
// bingTokens[badBingToken].State = '过期'
|
||||
// }
|
||||
// } else {
|
||||
// bingTokens[badBingToken].exception = 1
|
||||
// }
|
||||
// await redis.set('CHATGPT:BING_TOKENS', JSON.stringify(bingTokens))
|
||||
logger.warn(`token${bingToken}疑似不存在或已过期,再试试`)
|
||||
retry = retry - 0.1
|
||||
} else {
|
||||
retry--
|
||||
errorMessage = message === 'Timed out waiting for response. Try enabling debug mode to see more information.' ? (reply ? `${reply}\n不行了,我的大脑过载了,处理不过来了!` : '必应的小脑瓜不好使了,不知道怎么回答!') : message
|
||||
|
|
@ -1778,9 +1751,11 @@ export class chatgpt extends plugin {
|
|||
if (Config.slackClaudeEnableGlobalPreset && (useCast?.slack || Config.slackClaudeGlobalPreset)) {
|
||||
// 先发送设定
|
||||
let prompt = (useCast?.slack || Config.slackClaudeGlobalPreset)
|
||||
let emotion = await AzureTTS.getEmotionPrompt(e)
|
||||
if (emotion) {
|
||||
prompt = prompt + '\n' + emotion
|
||||
}
|
||||
await client.sendMessage(prompt, e)
|
||||
// 处理可能由情绪参数导致的设定超限问题
|
||||
await client.sendMessage(await AzureTTS.getEmotionPrompt(e), e)
|
||||
logger.info('claudeFirst:', prompt)
|
||||
}
|
||||
}
|
||||
|
|
@ -1829,10 +1804,10 @@ export class chatgpt extends plugin {
|
|||
timeoutMs: 120000
|
||||
// systemMessage: promptPrefix
|
||||
}
|
||||
if (Math.floor(Math.random() * 100) < 5) {
|
||||
// 小概率再次发送系统消息
|
||||
option.systemMessage = promptPrefix
|
||||
}
|
||||
// if (Math.floor(Math.random() * 100) < 5) {
|
||||
// // 小概率再次发送系统消息
|
||||
// option.systemMessage = promptPrefix
|
||||
// }
|
||||
if (conversation) {
|
||||
option = Object.assign(option, conversation)
|
||||
}
|
||||
|
|
@ -2098,7 +2073,11 @@ export class chatgpt extends plugin {
|
|||
async function getAvailableBingToken (conversation, throttled = []) {
|
||||
let allThrottled = false
|
||||
if (!await redis.get('CHATGPT:BING_TOKENS')) {
|
||||
throw new Error('未绑定Bing Cookie,请使用#chatgpt设置必应token命令绑定Bing Cookie')
|
||||
return {
|
||||
bingToken: null,
|
||||
allThrottled
|
||||
}
|
||||
// throw new Error('未绑定Bing Cookie,请使用#chatgpt设置必应token命令绑定Bing Cookie')
|
||||
}
|
||||
|
||||
let bingToken = ''
|
||||
|
|
@ -2128,7 +2107,11 @@ async function getAvailableBingToken (conversation, throttled = []) {
|
|||
})
|
||||
bingToken = minElement.Token
|
||||
} else {
|
||||
throw new Error('全部Token均已失效,暂时无法使用')
|
||||
// throw new Error('全部Token均已失效,暂时无法使用')
|
||||
return {
|
||||
bingToken: null,
|
||||
allThrottled
|
||||
}
|
||||
}
|
||||
if (Config.toneStyle != 'Sydney' && Config.toneStyle != 'Custom') {
|
||||
// bing 下,需要保证同一对话使用同一账号的token
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ export class dalle extends plugin {
|
|||
this.reply('请提供绘图prompt')
|
||||
return false
|
||||
}
|
||||
|
||||
this.reply('在画了,请稍等……')
|
||||
let bingToken = ''
|
||||
if (await redis.exists('CHATGPT:BING_TOKENS') != 0) {
|
||||
let bingTokens = JSON.parse(await redis.get('CHATGPT:BING_TOKENS'))
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@ import { generateAudio } from '../utils/tts.js'
|
|||
import fs from 'fs'
|
||||
import { emojiRegex, googleRequestUrl } from '../utils/emoj/index.js'
|
||||
import fetch from 'node-fetch'
|
||||
import { makeForwardMsg, mkdirs } from '../utils/common.js'
|
||||
import { getImageOcrText, getImg, makeForwardMsg, mkdirs } from '../utils/common.js'
|
||||
import uploadRecord from '../utils/uploadRecord.js'
|
||||
import { makeWordcloud } from '../utils/wordcloud/wordcloud.js'
|
||||
import { translate, translateLangSupports } from '../utils/translate.js'
|
||||
import AzureTTS from '../utils/tts/microsoft-azure.js'
|
||||
import VoiceVoxTTS from '../utils/tts/voicevox.js'
|
||||
|
||||
let useSilk = false
|
||||
try {
|
||||
await import('node-silk')
|
||||
|
|
@ -17,7 +20,7 @@ try {
|
|||
useSilk = false
|
||||
}
|
||||
export class Entertainment extends plugin {
|
||||
constructor(e) {
|
||||
constructor (e) {
|
||||
super({
|
||||
name: 'ChatGPT-Plugin 娱乐小功能',
|
||||
dsc: '让你的聊天更有趣!现已支持主动打招呼、表情合成、群聊词云统计、文本翻译与图片ocr小功能!',
|
||||
|
|
@ -42,6 +45,10 @@ export class Entertainment extends plugin {
|
|||
reg: '^#?(今日词云|群友在聊什么)$',
|
||||
fnc: 'wordcloud'
|
||||
},
|
||||
{
|
||||
reg: '^#(|最新)词云(\\d{1,2}h{0,1}|)$',
|
||||
fnc: 'wordcloud_latest'
|
||||
},
|
||||
{
|
||||
reg: '^#((寄批踢|gpt|GPT)?翻.*|chatgpt翻译帮助)',
|
||||
fnc: 'translate'
|
||||
|
|
@ -56,12 +63,13 @@ export class Entertainment extends plugin {
|
|||
{
|
||||
// 设置十分钟左右的浮动
|
||||
cron: '0 ' + Math.ceil(Math.random() * 10) + ' 7-23/' + Config.helloInterval + ' * * ?',
|
||||
// cron: '0 ' + '*/' + Config.helloInterval + ' * * * ?',
|
||||
// cron: '*/2 * * * *',
|
||||
name: 'ChatGPT主动随机说话',
|
||||
fnc: this.sendRandomMessage.bind(this)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
async ocr (e) {
|
||||
let replyMsg
|
||||
let imgOcrText = await getImageOcrText(e)
|
||||
|
|
@ -72,7 +80,8 @@ export class Entertainment extends plugin {
|
|||
replyMsg = await makeForwardMsg(e, imgOcrText, 'OCR结果')
|
||||
await this.reply(replyMsg, e.isGroup)
|
||||
}
|
||||
async translate(e) {
|
||||
|
||||
async translate (e) {
|
||||
const translateLangLabels = translateLangSupports.map(item => item.label).join(',')
|
||||
const translateLangLabelAbbrS = translateLangSupports.map(item => item.abbr).join(',')
|
||||
if (e.msg.trim() === '#chatgpt翻译帮助') {
|
||||
|
|
@ -167,7 +176,8 @@ ${translateLangLabels}
|
|||
await this.reply(result, e.isGroup)
|
||||
return true
|
||||
}
|
||||
async wordcloud(e) {
|
||||
|
||||
async wordcloud (e) {
|
||||
if (e.isGroup) {
|
||||
let groupId = e.group_id
|
||||
let lock = await redis.get(`CHATGPT:WORDCLOUD:${groupId}`)
|
||||
|
|
@ -176,7 +186,7 @@ ${translateLangLabels}
|
|||
return true
|
||||
}
|
||||
await e.reply('在统计啦,请稍等...')
|
||||
await redis.set(`CHATGPT:WORDCLOUD:${groupId}`, '1', {EX: 600})
|
||||
await redis.set(`CHATGPT:WORDCLOUD:${groupId}`, '1', { EX: 600 })
|
||||
try {
|
||||
await makeWordcloud(e, e.group_id)
|
||||
} catch (err) {
|
||||
|
|
@ -188,8 +198,39 @@ ${translateLangLabels}
|
|||
await e.reply('请在群里发送此命令')
|
||||
}
|
||||
}
|
||||
async wordcloud_latest(e) {
|
||||
if (e.isGroup) {
|
||||
let groupId = e.group_id
|
||||
let lock = await redis.get(`CHATGPT:WORDCLOUD:${groupId}`)
|
||||
if (lock) {
|
||||
await e.reply('别着急,上次统计还没完呢')
|
||||
return true
|
||||
}
|
||||
|
||||
async combineEmoj(e) {
|
||||
const regExp = /词云(\d{0,2})(|h)/
|
||||
const match = e.msg.trim().match(regExp)
|
||||
const duration = !match[1] ? 12 : parseInt(match[1]) // default 12h
|
||||
|
||||
if(duration > 24) {
|
||||
await e.reply('最多只能统计24小时内的记录哦')
|
||||
return false
|
||||
}
|
||||
await e.reply('在统计啦,请稍等...')
|
||||
|
||||
await redis.set(`CHATGPT:WORDCLOUD:${groupId}`, '1', {EX: 600})
|
||||
try {
|
||||
await makeWordcloud(e, e.group_id, duration)
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
await e.reply(err)
|
||||
}
|
||||
await redis.del(`CHATGPT:WORDCLOUD:${groupId}`)
|
||||
} else {
|
||||
await e.reply('请在群里发送此命令')
|
||||
}
|
||||
}
|
||||
|
||||
async combineEmoj (e) {
|
||||
let left = e.msg.codePointAt(0).toString(16).toLowerCase()
|
||||
let right = e.msg.codePointAt(2).toString(16).toLowerCase()
|
||||
if (left === right) {
|
||||
|
|
@ -237,7 +278,7 @@ ${translateLangLabels}
|
|||
return true
|
||||
}
|
||||
|
||||
async sendMessage(e) {
|
||||
async sendMessage (e) {
|
||||
if (e.msg.match(/^#chatgpt打招呼帮助/) !== null) {
|
||||
await this.reply('设置主动打招呼的群聊名单,群号之间以,隔开,参数之间空格隔开\n' +
|
||||
'#chatgpt打招呼+群号:立即在指定群聊发起打招呼' +
|
||||
|
|
@ -268,23 +309,71 @@ ${translateLangLabels}
|
|||
}
|
||||
}
|
||||
|
||||
async sendRandomMessage() {
|
||||
async sendRandomMessage () {
|
||||
if (Config.debug) {
|
||||
logger.info('开始处理:ChatGPT随机打招呼。')
|
||||
}
|
||||
let toSend = Config.initiativeChatGroups || []
|
||||
for (let i = 0; i < toSend.length; i++) {
|
||||
if (!toSend[i]) {
|
||||
for (const element of toSend) {
|
||||
if (!element) {
|
||||
continue
|
||||
}
|
||||
let groupId = parseInt(toSend[i])
|
||||
let groupId = parseInt(element)
|
||||
if (Bot.getGroupList().get(groupId)) {
|
||||
// 打招呼概率
|
||||
if (Math.floor(Math.random() * 100) < Config.helloProbability) {
|
||||
let message = await generateHello()
|
||||
logger.info(`打招呼给群聊${groupId}:` + message)
|
||||
if (Config.defaultUseTTS) {
|
||||
let audio = await generateAudio(message, Config.defaultTTSRole)
|
||||
let audio
|
||||
const [defaultVitsTTSRole, defaultAzureTTSRole, defaultVoxTTSRole] = [Config.defaultTTSRole, Config.azureTTSSpeaker, Config.voicevoxTTSSpeaker]
|
||||
let ttsSupportKinds = []
|
||||
if (Config.azureTTSKey) ttsSupportKinds.push(1)
|
||||
if (Config.ttsSpace) ttsSupportKinds.push(2)
|
||||
if (Config.voicevoxSpace) ttsSupportKinds.push(3)
|
||||
if (!ttsSupportKinds.length) {
|
||||
logger.warn('没有配置任何语音服务!')
|
||||
return false
|
||||
}
|
||||
const randomIndex = Math.floor(Math.random() * ttsSupportKinds.length)
|
||||
switch (ttsSupportKinds[randomIndex]) {
|
||||
case 1 : {
|
||||
const isEn = AzureTTS.supportConfigurations.find(config => config.code === defaultAzureTTSRole)?.language.includes('en')
|
||||
if (isEn) {
|
||||
message = (await translate(message, '英')).replace('\n', '')
|
||||
}
|
||||
audio = await AzureTTS.generateAudio(message, {
|
||||
defaultAzureTTSRole
|
||||
})
|
||||
break
|
||||
}
|
||||
case 2 : {
|
||||
if (Config.autoJapanese) {
|
||||
try {
|
||||
message = await translate(message, '日')
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
}
|
||||
}
|
||||
try {
|
||||
audio = await generateAudio(message, defaultVitsTTSRole, '中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)')
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 3 : {
|
||||
message = (await translate(message, '日')).replace('\n', '')
|
||||
try {
|
||||
audio = await VoiceVoxTTS.generateAudio(message, {
|
||||
speaker: defaultVoxTTSRole
|
||||
})
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (useSilk) {
|
||||
await Bot.sendGroupMsg(groupId, await uploadRecord(audio))
|
||||
} else {
|
||||
|
|
@ -302,7 +391,7 @@ ${translateLangLabels}
|
|||
}
|
||||
}
|
||||
|
||||
async handleSentMessage(e) {
|
||||
async handleSentMessage (e) {
|
||||
const addReg = /^#chatgpt设置打招呼[::]?\s?(\S+)(?:\s+(\d+))?(?:\s+(\d+))?$/
|
||||
const delReg = /^#chatgpt删除打招呼[::\s]?(\S+)/
|
||||
const checkReg = /^#chatgpt查看打招呼$/
|
||||
|
|
@ -360,8 +449,8 @@ ${translateLangLabels}
|
|||
return false
|
||||
} else {
|
||||
Config.initiativeChatGroups = Config.initiativeChatGroups
|
||||
.filter(group => group.trim() !== '')
|
||||
.concat(validGroups)
|
||||
.filter(group => group.trim() !== '')
|
||||
.concat(validGroups)
|
||||
}
|
||||
if (typeof paramArray[2] === 'undefined' && typeof paramArray[3] === 'undefined') {
|
||||
replyMsg = `已更新打招呼设置:\n${!e.isGroup ? '群号:' + Config.initiativeChatGroups.join(', ') + '\n' : ''}间隔时间:${Config.helloInterval}小时\n触发概率:${Config.helloProbability}%`
|
||||
|
|
@ -378,51 +467,3 @@ ${translateLangLabels}
|
|||
return false
|
||||
}
|
||||
}
|
||||
export async function getImg (e) {
|
||||
// 取消息中的图片、at的头像、回复的图片,放入e.img
|
||||
if (e.at && !e.source) {
|
||||
e.img = [`https://q1.qlogo.cn/g?b=qq&s=0&nk=${e.at}`]
|
||||
}
|
||||
if (e.source) {
|
||||
let reply
|
||||
if (e.isGroup) {
|
||||
reply = (await e.group.getChatHistory(e.source.seq, 1)).pop()?.message
|
||||
} else {
|
||||
reply = (await e.friend.getChatHistory(e.source.time, 1)).pop()?.message
|
||||
}
|
||||
if (reply) {
|
||||
let i = []
|
||||
for (let val of reply) {
|
||||
if (val.type === 'image') {
|
||||
i.push(val.url)
|
||||
}
|
||||
}
|
||||
e.img = i
|
||||
}
|
||||
}
|
||||
return e.img
|
||||
}
|
||||
export async function getImageOcrText (e) {
|
||||
const img = await getImg(e)
|
||||
if (img) {
|
||||
try {
|
||||
let resultArr = []
|
||||
let eachImgRes = ''
|
||||
for (let i in img) {
|
||||
const imgOCR = await Bot.imageOcr(img[i])
|
||||
for (let text of imgOCR.wordslist) {
|
||||
eachImgRes += (`${text?.words} \n`)
|
||||
}
|
||||
if (eachImgRes) resultArr.push(eachImgRes)
|
||||
eachImgRes = ''
|
||||
}
|
||||
// logger.warn('resultArr', resultArr)
|
||||
return resultArr
|
||||
} catch (err) {
|
||||
return false
|
||||
// logger.error(err)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,7 +331,11 @@ export class help extends plugin {
|
|||
}
|
||||
|
||||
async help (e) {
|
||||
if (!Config.oldview) { await renderUrl(e, `http://127.0.0.1:${Config.serverPort || 3321}/help/`, { Viewport: { width: 800, height: 600 } }) } else { await render(e, 'chatgpt-plugin', 'help/index', { helpData, version }) }
|
||||
if (Config.newhelp && !Config.oldview) {
|
||||
await renderUrl(e, `http://127.0.0.1:${Config.serverPort || 3321}/help/`, { Viewport: { width: 800, height: 600 } })
|
||||
} else {
|
||||
await render(e, 'chatgpt-plugin', 'help/index', { helpData, version })
|
||||
}
|
||||
}
|
||||
|
||||
async newHelp (e) {
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue