LaiTool/src/main/Service/Translate/TranslateService.ts

266 lines
10 KiB
TypeScript
Raw Normal View History

2024-08-03 12:46:12 +08:00
import { GeneralResponse } from "../../../model/generalResponse";
import { TranslateModel } from "../../../model/translate";
import { errorMessage, successMessage } from "../../Public/generalTools";
import { Translate } from "./Translate";
import { DEFINE_STRING } from "../../../define/define_string"
import { TranslateAPIType, TranslateType } from "../../../define/enum/translate";
import { Book } from "../../../model/book";
import { ResponseMessageType } from "../../../define/enum/softwareEnum";
import { isEmpty } from "lodash";
import { ValidateJson } from "../../../define/Tools/validate";
2024-08-18 16:22:19 +08:00
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
2024-09-12 14:13:09 +08:00
import { SoftWareServiceBasic } from "../ServiceBasic/softwareServiceBasic";
import { ExecuteConcurrently } from "../../../define/Tools/common";
2024-08-03 12:46:12 +08:00
/**
*
*/
export class TranslateService {
translate: Translate
2024-08-18 16:22:19 +08:00
bookServiceBasic: BookServiceBasic
2024-09-12 14:13:09 +08:00
softWareServiceBasic: SoftWareServiceBasic
2024-08-03 12:46:12 +08:00
constructor() {
2024-08-18 16:22:19 +08:00
this.bookServiceBasic = new BookServiceBasic();
2024-09-12 14:13:09 +08:00
this.translate = new Translate();
this.softWareServiceBasic = new SoftWareServiceBasic();
2024-08-03 12:46:12 +08:00
}
// 返回翻译结果。用于前端修改
2024-09-12 14:13:09 +08:00
private sendTranslateReturn(windowId: number, data: GeneralResponse.MessageResponse, message_name: string = DEFINE_STRING.BOOK.MAIN_DATA_RETURN): void {
2024-08-03 12:46:12 +08:00
let win = global.newWindow[0]
if (windowId) {
win = global.newWindow.filter(item => item.id == windowId)[0];
}
2024-09-12 14:13:09 +08:00
if (!message_name) {
message_name = DEFINE_STRING.BOOK.MAIN_DATA_RETURN
}
win.win.webContents.send(message_name, data)
2024-08-03 12:46:12 +08:00
}
//#region 翻译设置
/**
*
* @returns
*/
InitialTranslateSetting(): TranslateModel.TranslateModel {
return {
selectModel: TranslateAPIType.BAIDU,
2024-08-04 15:00:00 +08:00
translation_auto: true,
2024-08-03 12:46:12 +08:00
translates: [
2024-08-09 12:28:28 +08:00
{
name: TranslateAPIType.LAITOOL,
translation_business: "https://api.laitool.cc/v1/chat/completions",
translation_app_id: "gpt-4o-mini",
translation_secret: "LAI API 令牌"
},
2024-08-03 12:46:12 +08:00
{
name: TranslateAPIType.BAIDU,
translation_business: "https://fanyi-api.baidu.com/api/trans/vip/translate",
2024-08-04 15:00:00 +08:00
translation_app_id: "百度翻译的APP ID",
translation_secret: "百度翻译的密钥"
2024-08-03 12:46:12 +08:00
},
{
name: TranslateAPIType.TENCENT,
translation_business: "https://tmt.tencentcloudapi.com",
2024-08-04 15:00:00 +08:00
translation_app_id: '腾讯云的APP ID',
translation_secret: "腾讯云的密钥"
2024-08-03 12:46:12 +08:00
},
{
name: TranslateAPIType.VOLCENGINE,
translation_business: "https://translate.volcengineapi.com?",
2024-08-04 15:00:00 +08:00
translation_app_id: '火山引擎的APP ID',
translation_secret: '火山引擎的密钥'
2024-08-03 12:46:12 +08:00
},
{
name: TranslateAPIType.ALI,
translation_business: "https://mt.cn-hangzhou.aliyuncs.com",
2024-08-04 15:00:00 +08:00
translation_app_id: '阿里云的APP ID',
translation_secret: '阿里云的密钥'
2024-08-03 12:46:12 +08:00
}
]
}
}
/**
*
*/
async GetTranslateSetting(): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
let translateSetting = undefined as TranslateModel.TranslateModel
2024-09-12 14:13:09 +08:00
let translateSettingString = await this.softWareServiceBasic.GetSoftWarePropertyData('translationSetting');
2024-08-03 12:46:12 +08:00
if (isEmpty(translateSettingString)) {
// 初始化
2024-08-04 15:00:00 +08:00
translateSetting = this.InitialTranslateSetting();
await this.ResetTranslateSetting();
2024-09-12 14:13:09 +08:00
translateSettingString = await this.softWareServiceBasic.GetSoftWarePropertyData('translationSetting');
2024-08-04 15:00:00 +08:00
translateSetting = JSON.parse(translateSettingString);
2024-08-03 12:46:12 +08:00
} else {
// 解析
let tryParse = ValidateJson(translateSettingString)
if (!tryParse) {
2024-08-18 16:22:19 +08:00
throw new Error("翻译设置数据解析失败,请重置后重新配置")
2024-08-03 12:46:12 +08:00
}
translateSetting = JSON.parse(translateSettingString);
}
2024-08-09 12:28:28 +08:00
// v3.0.1 preview 4 版本新增laitool gpt翻译之前版本没有这边要检测下是不是有配置没有初始化
let index = translateSetting.translates.findIndex(item => item.name == TranslateAPIType.LAITOOL);
if (index < 0) {
// 初始化,将数据加在最前面
let laitool = {
name: TranslateAPIType.LAITOOL,
translation_business: "https://api.laitool.cc/v1/chat/completions",
translation_app_id: "gpt-4o-mini",
translation_secret: "LAI API 令牌"
}
translateSetting.translates.unshift(laitool)
}
2024-08-03 12:46:12 +08:00
return successMessage(translateSetting, "获取翻译设置成功", "TranslateService_GetTranslateSetting")
} catch (error) {
return errorMessage("获取翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_GetTranslateSetting")
}
}
/**
*
*/
async ResetTranslateSetting(): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
let translateSetting = this.InitialTranslateSetting()
2024-09-12 14:13:09 +08:00
let res = await this.softWareServiceBasic.SaveSoftwarePropertyData('translationSetting', JSON.stringify(translateSetting))
2024-08-03 12:46:12 +08:00
return successMessage(translateSetting, "重置翻译设置成功", "TranslateService_ResetTranslateSetting")
} catch (error) {
return errorMessage("重置翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_ResetTranslateSetting")
}
}
/**
*
* @param value
* @returns
*/
async SaveTranslateSetting(value: TranslateModel.TranslateModel): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
2024-09-12 14:13:09 +08:00
let res = await this.softWareServiceBasic.SaveSoftwarePropertyData('translationSetting', JSON.stringify(value))
2024-08-09 12:28:28 +08:00
// 这边要判断是不是用的laitool
let laitool = value.translates.filter(item => item.name == TranslateAPIType.LAITOOL)
if (laitool.length > 0) {
let laitoolData = laitool[0]
if (!laitoolData.translation_business.includes('laitool')) {
throw new Error("不允许修改laitool的地址为其他外站地址")
}
}
2024-08-03 12:46:12 +08:00
return successMessage(value, "保存翻译设置成功", "TranslateService_SaveTranslateSetting")
} catch (error) {
return errorMessage("保存翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_SaveTranslateSetting")
}
}
//#endregion
/**
2024-08-18 16:22:19 +08:00
*
2024-08-03 12:46:12 +08:00
* @param bookTaskDetailId ID
* @param reversePromptId ID
* @param to
* @param dstString
*/
private async TranslateProcessReversePrompt(bookTaskDetailId: string, reversePromptId: string, to: string, dstString: string): Promise<void> {
// 开始修改翻译后的数据
let updateData = {} as Book.ReversePrompt
if (to == "zh") {
updateData.promptCN = dstString
} else if (to == "en") {
updateData.prompt = dstString
updateData.promptCN = dstString
}
// 修改数据
2024-09-12 14:13:09 +08:00
await this.bookServiceBasic.UpdateBookTaskDetailReversePrompt(bookTaskDetailId, reversePromptId, updateData)
2024-08-03 12:46:12 +08:00
}
// 处理返回的数据
async TranslateReturnProcess(value: TranslateModel.TranslateNowIPCParams, to: string, dstString: string) {
switch (value.type) {
case TranslateType.REVERSE_PROMPT_TRANSLATE:
await this.TranslateProcessReversePrompt(value.bookTaskDetailId, value.reversePromptId, to, dstString)
break;
2024-08-18 16:22:19 +08:00
case TranslateType.GPT_PROMPT_TRANSLATE:
// 这个直接改就行
await this.bookServiceBasic.UpdateBookTaskDetail(value.bookTaskDetailId, {
gptPrompt: dstString
})
break;
2024-08-03 12:46:12 +08:00
default:
throw new Error("未知的翻译类型");
}
}
2024-09-12 14:13:09 +08:00
/**
*
* @param value
* @returns
*/
2024-08-03 12:46:12 +08:00
async TranslateNowReturn(value: TranslateModel.TranslateNowIPCParams[]): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
// 循环所有的数据,返回翻译结果
2024-09-12 14:13:09 +08:00
let tasks = []
2024-08-03 12:46:12 +08:00
for (let i = 0; i < value.length; i++) {
const element = value[i];
2024-09-12 14:13:09 +08:00
tasks.push(async () => {
let res = await this.translate.TranslateReturnNow(element)
// global.logger.info("断点写出", JSON.stringify(res))
// 单个翻译,将返回的数据写入到原数据中
2024-08-03 12:46:12 +08:00
2024-09-12 14:13:09 +08:00
// 添加一个对返回信息进行处理的函数
let data = res.data
// 先将数据进行拼接
let srcString = ""
if (element.isSplit) {
let dstStrs = []
} else {
// 没有拆分的,只有一句
srcString = data.data[0].dst
}
// 写回数据库
await this.TranslateReturnProcess(element, data.to, srcString);
2024-08-03 12:46:12 +08:00
2024-09-12 14:13:09 +08:00
let responseType = ResponseMessageType.REVERSE_PROMPT_TRANSLATE;
if (element.type == TranslateType.GPT_PROMPT_TRANSLATE) {
responseType = ResponseMessageType.GPT_PROMPT_TRANSLATE
2024-08-03 12:46:12 +08:00
}
2024-09-12 14:13:09 +08:00
// 做个返回数据
this.sendTranslateReturn(element.windowId, {
code: 1,
id: element.bookTaskDetailId,
type: responseType,
data: {
progress: i + 1,
total: value.length,
from: element.from,
to: data.to,
bookTaskDetailId: element.bookTaskDetailId,
reversePromptId: element.reversePromptId,
prompt: srcString,
promptCN: srcString
}
}, element.responseMessgeName)
2024-08-03 12:46:12 +08:00
})
}
2024-09-12 14:13:09 +08:00
let res = await ExecuteConcurrently(tasks, global.config.task_number)
// 将翻译后的数据返回,前端进行修改
2024-08-03 12:46:12 +08:00
return successMessage(null, "全部翻译完成", "TranslateService_TranslateNowReturn")
} catch (error) {
return errorMessage("翻译失败,失败信息如下:" + error.toString(), "TranslateService_TranslateNowReturn")
}
}
}