diff --git a/apps/chat.js b/apps/chat.js index cd1fe42..a3e5299 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -61,6 +61,7 @@ import { SerpIkechan8370Tool } from '../utils/tools/SerpIkechan8370Tool.js' import { SendPictureTool } from '../utils/tools/SendPictureTool.js' import { SerpImageTool } from '../utils/tools/SearchImageTool.js' import { ImageCaptionTool } from '../utils/tools/ImageCaptionTool.js' +import {TTSTool} from "../utils/tools/TTSTool.js"; try { await import('emoji-strip') } catch (err) { @@ -1971,7 +1972,8 @@ export class chatgpt extends plugin { new SearchVideoTool(), new SerpImageTool(), new SerpIkechan8370Tool(), - new SerpTool() + new SerpTool(), + new TTSTool() ] // todo 3.0再重构tool的插拔和管理 let tools = [ @@ -1984,6 +1986,7 @@ export class chatgpt extends plugin { new KickOutTool(), new WeatherTool(), new SendPictureTool(), + new TTSTool(), serpTool ] let img = [] @@ -2044,7 +2047,16 @@ export class chatgpt extends plugin { logger.info(msg) while (msg.functionCall) { let { name, arguments: args } = msg.functionCall - let functionResult = await fullFuncMap[name].exec(Object.assign({ isAdmin, sender }, JSON.parse(args))) + args = JSON.parse(args) + if (!args.groupId) { + args.groupId = e.group_id || e.sender.user_id + } + try { + parseInt(args.groupId) + } catch (err) { + args.groupId = e.group_id || e.sender.user_id + } + let functionResult = await fullFuncMap[name].exec(Object.assign({ isAdmin, sender }, )) logger.mark(`function ${name} execution result: ${functionResult}`) option.parentMessageId = msg.id option.name = name diff --git a/utils/tools/ImageCaptionTool.js b/utils/tools/ImageCaptionTool.js index 59cc6bb..9075205 100644 --- a/utils/tools/ImageCaptionTool.js +++ b/utils/tools/ImageCaptionTool.js @@ -16,7 +16,7 @@ export class ImageCaptionTool extends AbstractTool { }, question: { type: 'string', - description: 'if you want to ask something about this picture, write your question in English here.' + description: 'when you need an answer for a question based on an image, write your question in English here.' } }, required: [] diff --git a/utils/tools/ProcessPictureTool.js b/utils/tools/ProcessPictureTool.js new file mode 100644 index 0000000..e69de29 diff --git a/utils/tools/TTSTool.js b/utils/tools/TTSTool.js new file mode 100644 index 0000000..d4c2aa5 --- /dev/null +++ b/utils/tools/TTSTool.js @@ -0,0 +1,56 @@ +import { AbstractTool } from './AbstractTool.js' +import { generateAudio } from '../tts.js' +import uploadRecord from '../uploadRecord.js' +import { Config } from '../config.js' + +export class TTSTool extends AbstractTool { + name = 'tts' + + parameters = { + properties: { + text: { + type: 'string', + description: 'the text will be turned into audio' + }, + role: { + type: 'string', + description: 'use whose voice', + enum: ['琴', '空', + '丽莎', '荧', '芭芭拉', '凯亚', '迪卢克', '雷泽', '安柏', '温迪', + '香菱', '北斗', '行秋', '魈', '凝光', '可莉', '钟离', '菲谢尔(皇女)', + '班尼特', '达达利亚(公子)', '诺艾尔(女仆)', '七七', '重云', '甘雨(椰羊)', + '阿贝多', '迪奥娜(猫猫)', '莫娜', '刻晴', '砂糖', '辛焱', '罗莎莉亚', + '胡桃', '枫原万叶(万叶)', '烟绯', '宵宫', '托马', '优菈', '雷电将军(雷神)', + '早柚', '珊瑚宫心海', '五郎', '九条裟罗', '荒泷一斗', + '埃洛伊', '申鹤', '八重神子', '神里绫人(绫人)', '夜兰', '久岐忍', + '鹿野苑平藏', '提纳里', '柯莱', '多莉', '云堇', '纳西妲(草神)', '深渊使徒', + '妮露', '赛诺'] + }, + groupId: { + type: 'string', + description: 'groupId' + } + }, + required: ['text', 'role', 'groupId'] + } + + description = 'Useful when you want to turn text into audio and send it' + + func = async function (opts) { + let { text, role, groupId } = opts + groupId = parseInt(groupId.trim()) + try { + let wav = await generateAudio(text, role, '中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)') + let sendable = await uploadRecord(wav, Config.ttsMode) + if (sendable) { + let group = await Bot.pickGroup(groupId) + await group.sendMsg(sendable) + } else { + return 'audio generation failed' + } + } catch (err) { + logger.error(err) + return 'audio generation failed' + } + } +}