diff --git a/package-lock.json b/package-lock.json index 5f1dbe8..b190bbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "laitool", - "version": "3.3.2", + "version": "3.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "laitool", - "version": "3.3.2", + "version": "3.3.3", "hasInstallScript": true, "dependencies": { "@alicloud/alimt20181012": "^1.2.0", diff --git a/package.json b/package.json index 6075631..6e7bf68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "laitool", - "version": "3.3.2", + "version": "3.3.3", "description": "An AI tool for image processing, video processing, and other functions.", "main": "./out/main/index.js", "author": "laitool.cn", diff --git a/resources/scripts/db/book.realm.lock b/resources/scripts/db/book.realm.lock index 9b9b4b8..95d5edb 100644 Binary files a/resources/scripts/db/book.realm.lock and b/resources/scripts/db/book.realm.lock differ diff --git a/resources/scripts/db/software.realm.lock b/resources/scripts/db/software.realm.lock index 4d5fec2..5f0c50c 100644 Binary files a/resources/scripts/db/software.realm.lock and b/resources/scripts/db/software.realm.lock differ diff --git a/src/define/db/model/SoftWare/mjSetting.ts b/src/define/db/model/SoftWare/mjSetting.ts index 79bb784..84052a2 100644 --- a/src/define/db/model/SoftWare/mjSetting.ts +++ b/src/define/db/model/SoftWare/mjSetting.ts @@ -53,6 +53,7 @@ export class RemoteMJModel extends Realm.Object { updateTime: Date version: string blockMessage?: string + type?: string static schema: ObjectSchema = { name: 'RemoteMJ', properties: { @@ -73,7 +74,8 @@ export class RemoteMJModel extends Realm.Object { createTime: 'date', updateTime: 'date', version: 'string', - blockMessage: 'string?' + blockMessage: 'string?', + type: "string?" }, // 主键为_id primaryKey: 'id' diff --git a/src/define/db/service/SoftWare/mjSettingService.ts b/src/define/db/service/SoftWare/mjSettingService.ts index 72c24b8..f9b7d70 100644 --- a/src/define/db/service/SoftWare/mjSettingService.ts +++ b/src/define/db/service/SoftWare/mjSettingService.ts @@ -31,6 +31,7 @@ export class MJSettingService extends BaseSoftWareService { return MJSettingService.instance } + /** * 初始化数据 */ @@ -302,6 +303,9 @@ export class MJSettingService extends BaseSoftWareService { if (remoteMjQuery?.accountId) { remoteMjSettings = this.realm.objects('RemoteMJ').filtered('accountId = $0', remoteMjQuery.accountId) } + if (remoteMjQuery?.type) { + remoteMjSettings = this.realm.objects('RemoteMJ').filtered('type = $0', remoteMjQuery.type) + } let resRemoteMj = Array.from(remoteMjSettings).map((remoteMj) => { return { ...remoteMj @@ -463,7 +467,6 @@ export class MJSettingService extends BaseSoftWareService { */ GetMjSetting() { try { - let res = this.realm.objects('Options').filtered(`key = "${OptionKeyName.MJ_GlobalSetting}"`); let mjSetting: OptionModel.OptionItem | null = null; diff --git a/src/define/db/service/SoftWare/softwareBasic.ts b/src/define/db/service/SoftWare/softwareBasic.ts index 0afad59..d3847d4 100644 --- a/src/define/db/service/SoftWare/softwareBasic.ts +++ b/src/define/db/service/SoftWare/softwareBasic.ts @@ -170,6 +170,14 @@ const migration = (oldRealm: Realm, newRealm: Realm) => { } if (oldRealm.schemaVersion < 25) { } + if (oldRealm.schemaVersion < 26) { + newRealm.write(() => { + const newSoftwares = newRealm.objects('RemoteMJ') + for (let software of newSoftwares) { + software.type = "remote" // 默认都是启用的; + } + }) + } } export class BaseSoftWareService extends BaseService { @@ -210,7 +218,7 @@ export class BaseSoftWareService extends BaseService { OptionsModel ], path: dbPath, - schemaVersion: 25, // 当前版本号 + schemaVersion: 26, // 当前版本号 migration: migration } // 判断当前全局是不是又当前这个 diff --git a/src/main/IPCEvent/settingIpc.ts b/src/main/IPCEvent/settingIpc.ts index 0e48ea6..76400ad 100644 --- a/src/main/IPCEvent/settingIpc.ts +++ b/src/main/IPCEvent/settingIpc.ts @@ -14,6 +14,9 @@ let mjSetting = new MJSetting() import { Watermark } from '../Service/watermark' let watermark = new Watermark() +import { SoftWareServiceBasic } from '../Service/ServiceBasic/softwareServiceBasic' +let softWareServiceBasic = new SoftWareServiceBasic() + async function SettingIpc() { // 获取背景音乐配置列表 ipcMain.handle( @@ -179,12 +182,6 @@ async function SettingIpc() { async (event, value) => await mjSetting.GetMJSetting(value) ) - // 保存MJ的基础设置信息 - ipcMain.handle( - DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, - async (event, value) => await mjSetting.UpdateMJSetting(value) - ) - // 获取MJ的所有设置 ipcMain.handle( DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA, @@ -200,19 +197,19 @@ async function SettingIpc() { // 获取所有的代理MJ信息 ipcMain.handle( DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS, - async (event) => await mjSetting.GetRemoteMJSettings() + async (event, type: string) => await mjSetting.GetRemoteMJSettings(type) ) // 创建新的代理MJ信息 ipcMain.handle( DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, - async (event, value, isRemote) => await mjSetting.AddRemoteMJSetting(value, isRemote) + async (event, value, type: string) => await mjSetting.AddRemoteMJSetting(value, true, type) ) // 修改MJ账号并重连 ipcMain.handle( DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, - async (event, value) => await mjSetting.UpdateRemoteMJSetting(value) + async (event, value, type: string) => await mjSetting.UpdateRemoteMJSetting(value, type) ) // 删除指定的MJ账号 @@ -224,7 +221,7 @@ async function SettingIpc() { /** 同步MJ远程代理服务器账户信息 */ ipcMain.handle( DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS_FROM_SERVICE, - async (event) => await mjSetting.GetRemoteMJSettingsFromService() + async (event, type: string) => await mjSetting.GetRemoteMJSettingsFromService(type) ) //#endregion diff --git a/src/main/Service/MJ/mjApi.ts b/src/main/Service/MJ/mjApi.ts index 49e8050..e873a01 100644 --- a/src/main/Service/MJ/mjApi.ts +++ b/src/main/Service/MJ/mjApi.ts @@ -31,18 +31,35 @@ class MJApi { this.optionServices = new OptionServices() } + /** + * 获取指定类型的MJ账号设置 + * @param type + * @returns + */ + async GetRemoteMJAccountAndRandom(type: string): Promise { + let _mjSetting = await MJSettingService.getInstance() + let res = _mjSetting.GetRemoteMJSettings({ + type: type + }) + if (res.code != 1) { + throw new Error(res.message) + } + if (res.data.length == 0) { + throw new Error("没有找到对应的本地代理模式的账号信息,请检查设置") + } + let randomIndex = Math.floor(Math.random() * res.data.length) + let randomAccount = res.data[randomIndex]; + let randomAccountId = randomAccount.accountId; + if (type == 'local') { + randomAccountId = randomAccount.channelId; + } + return randomAccountId + } + /** * 初始化MJ设置 */ async InitMJSetting(): Promise { - // 获取MJ配置,从数据库中 - // let _mjSettingService = await MJSettingService.getInstance() - // let mjSettings = _mjSettingService.GetMJSettingTreeData() - // if (mjSettings.code == 0) { - // throw new Error(mjSettings.message) - // } - - let mjSettingData = await this.optionServices.GetOptionByKey(OptionKeyName.MJ_GlobalSetting); if (mjSettingData.code == 0) { throw new Error("加载MJ设置失败,失败原因如下:" + mjSettingData.message) @@ -62,13 +79,24 @@ class MJApi { this.imagineUrl = define.remotemj_api + 'mj/submit/imagine' this.describeUrl = define.remotemj_api + 'mj/submit/describe' this.fetchTaskUrl = define.remotemj_api + 'mj/task/${id}/fetch' + } else if (this.mjSimpleSetting.type == MJImageType.LOCAL_MJ) { + let localRemoteBaseUrl = this.mj_globalSetting.mj_localRemoteSimpleSetting.baseUrl; + let localRemotePort = this.mj_globalSetting.mj_localRemoteSimpleSetting.port; + let localRemoteToken = this.mj_globalSetting.mj_localRemoteSimpleSetting.token; + if (isEmpty(localRemoteBaseUrl) || isEmpty(localRemotePort) || isEmpty(localRemoteToken)) { + throw new Error("没有找到对应的本地代理模式的设置,请检查设置") + } + if (localRemoteBaseUrl.endsWith('/')) { + localRemoteBaseUrl = localRemoteBaseUrl.slice(0, -1) + } + this.imagineUrl = localRemoteBaseUrl + ":" + localRemotePort + '/mj/submit/imagine' + this.describeUrl = localRemoteBaseUrl + ":" + localRemotePort + '/mj/submit/describe' + this.fetchTaskUrl = localRemoteBaseUrl + ":" + localRemotePort + '/mj/task/${id}/fetch' } else { - let apiUrlIndex = apiUrl.findIndex(item => item.value == this.mj_globalSetting.mj_apiSetting.mjApiUrl); if (apiUrlIndex == -1) { throw new Error('没有找到MJ API对应的请求URL,请检查配置'); } - let apiUrlItem = apiUrl[apiUrlIndex]; if (apiUrlItem.mj_url == null) { throw new Error('没有找到MJ API对应的请求URL,请检查配置'); @@ -98,6 +126,11 @@ class MJApi { 'mj-api-secret': define.API } useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer + } else if (this.mjSimpleSetting.type == MJImageType.LOCAL_MJ) { + headers = { + 'mj-api-secret': this.mj_globalSetting.mj_localRemoteSimpleSetting.token + } + useTransfer = false; } else { headers = { Authorization: this.mj_globalSetting.mj_apiSetting.apiKey @@ -195,6 +228,7 @@ class MJApi { switch (this.mjSimpleSetting.type) { case MJImageType.REMOTE_MJ: case MJImageType.API_MJ: + case MJImageType.LOCAL_MJ: res = await this.SubmitMJDescribeAPI(param) break default: @@ -215,9 +249,9 @@ class MJApi { base64: param.image, accountFilter: { modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], - remark: global.machineId + remark: global.machineId, + instanceId: "", }, - } let config = { headers: { @@ -228,9 +262,19 @@ class MJApi { if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { config.headers["mj-api-secret"] = define.API; delete data.accountFilter.modes; - } else { + delete data.accountFilter.instanceId; + } else if (this.mjSimpleSetting.type == MJImageType.API_MJ) { delete data.accountFilter.remark + delete data.accountFilter.instanceId; config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey; + } else if (this.mjSimpleSetting.type == MJImageType.LOCAL_MJ) { + delete data.accountFilter.remark + delete data.accountFilter.modes; + let instanceId = await this.GetRemoteMJAccountAndRandom('local'); + data.accountFilter.instanceId = instanceId; + config.headers["mj-api-secret"] = this.mj_globalSetting.mj_localRemoteSimpleSetting.token; + } else { + throw new Error("MJ出图的类型不支持") } // 开始请求 @@ -276,6 +320,7 @@ class MJApi { switch (this.mjSimpleSetting.type) { case MJImageType.REMOTE_MJ: case MJImageType.API_MJ: + case MJImageType.LOCAL_MJ: res = await this.SubmitMJImagineAPI(taskId, prompt) break default: @@ -302,7 +347,8 @@ class MJApi { prompt: prompt, accountFilter: { modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], - remark: global.machineId + remark: global.machineId, + instanceId: "", }, } @@ -317,11 +363,21 @@ class MJApi { if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { config.headers["mj-api-secret"] = define.API; delete data.accountFilter.modes; + delete data.accountFilter.instanceId; useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer - } else { + } else if (this.mjSimpleSetting.type == MJImageType.API_MJ) { delete data.accountFilter.remark + delete data.accountFilter.instanceId; config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey; useTransfer = this.mj_globalSetting.mj_apiSetting.useTransfer + } else if (this.mjSimpleSetting.type == MJImageType.LOCAL_MJ) { + delete data.accountFilter.remark + let instanceId = await this.GetRemoteMJAccountAndRandom('local'); + data.accountFilter.instanceId = instanceId; + useTransfer = false; + config.headers["mj-api-secret"] = this.mj_globalSetting.mj_localRemoteSimpleSetting.token; + } else { + throw new Error("MJ出图的类型不支持") } let resData: any = undefined; @@ -353,7 +409,6 @@ class MJApi { let re = JSON.parse(res.data.data); resData = re } else { - // 开始请求 let res = await axios.post(this.imagineUrl, data, config) resData = res.data diff --git a/src/main/Service/MJ/mjDefine.ts b/src/main/Service/MJ/mjDefine.ts index a78588b..6472983 100644 --- a/src/main/Service/MJ/mjDefine.ts +++ b/src/main/Service/MJ/mjDefine.ts @@ -6,26 +6,26 @@ import { MJRobotType, MJSpeed } from "@/define/enum/mjEnum" * @returns */ function GetMJRequestModelOptions() { - let mjRequstModel = [{ - label: "本地MJ(待开发)", - value: "local_mj", - disable: true - }, - { - label: "代理MJ(token)", - value: "remote_mj", - disable: false - }, - { - label: "浏览器模式", - value: "browser_mj", - disable: false - }, - { - label: "API模式", - value: "api_mj", - disable: false - }] + let mjRequstModel = [ + { + label: "API模式", + value: "api_mj", + disable: false + }, { + label: "本地代理模式", + value: "local_mj", + disable: false + }, + { + label: "代理MJ(token)", + value: "remote_mj", + disable: false + }, + { + label: "浏览器模式", + value: "browser_mj", + disable: true + }] return mjRequstModel.filter(item => !item.disable) } diff --git a/src/main/Service/ServiceBasic/softwareMjsettingBasic.ts b/src/main/Service/ServiceBasic/softwareMjsettingBasic.ts new file mode 100644 index 0000000..4b3969b --- /dev/null +++ b/src/main/Service/ServiceBasic/softwareMjsettingBasic.ts @@ -0,0 +1,35 @@ +import { MJSettingService } from "@/define/db/service/SoftWare/mjSettingService"; +import { MJSettingModel } from "@/model/Setting/mjSetting"; + +export class SoftwareMjsettingBasic { + mjSettingService: MJSettingService + + async InitService() { + if (!this.mjSettingService) { + this.mjSettingService = await MJSettingService.getInstance() + } + } + + //#region MJ设置相关 + + /** + * 获取MJ的设置信息 + * @returns + */ + async GetMjSetting(): Promise { + await this.InitService(); + let mjSetting = this.mjSettingService.GetMjSetting() + return mjSetting + } + + //#endregion + + //#region 事务操作 + async transaction(callback: (realm: any) => void) { + await this.InitService() + this.mjSettingService.transaction(() => { + callback(this.mjSettingService.realm) + }) + } + //#endregion +} \ No newline at end of file diff --git a/src/main/Service/ServiceBasic/softwareServiceBasic.ts b/src/main/Service/ServiceBasic/softwareServiceBasic.ts index 235b3f8..1cc3352 100644 --- a/src/main/Service/ServiceBasic/softwareServiceBasic.ts +++ b/src/main/Service/ServiceBasic/softwareServiceBasic.ts @@ -1,20 +1,20 @@ import { SoftwareService } from '../../../define/db/service/SoftWare/softwareService'; -import { MJSettingService } from '../../../define/db/service/SoftWare/mjSettingService'; import { MJSettingModel } from '../../../model/Setting/mjSetting'; +import { SoftwareMjsettingBasic } from './softwareMjsettingBasic'; export class SoftWareServiceBasic { softwareService: SoftwareService - mjSettingService: MJSettingService - constructor() { } + softwareMjsettingBasic: SoftwareMjsettingBasic + + constructor() { + this.softwareMjsettingBasic = new SoftwareMjsettingBasic() + } async InitService() { if (!this.softwareService) { this.softwareService = await SoftwareService.getInstance() } - if (!this.mjSettingService) { - this.mjSettingService = await MJSettingService.getInstance() - } } //#region software相关的基础服务 @@ -79,19 +79,26 @@ export class SoftWareServiceBasic { //#endregion - //#region MJ设置相关 + //#region Option 相关 + + + + //#endregion + + //#region MJ 设置相关 /** * 获取MJ的设置信息 * @returns */ - async GetMjSetting(): Promise { - await this.InitService(); - let mjSetting = this.mjSettingService.GetMjSetting() - - return mjSetting - } + GetMjSetting = async (): Promise => await this.softwareMjsettingBasic.GetMjSetting(); //#endregion + + //#region 事务操作 + + transaction = async (realm: any) => await this.softwareMjsettingBasic.transaction(realm); + //#endregion + } \ No newline at end of file diff --git a/src/main/discord/discordWorker.js b/src/main/discord/discordWorker.js index aaf74d6..bfe1768 100644 --- a/src/main/discord/discordWorker.js +++ b/src/main/discord/discordWorker.js @@ -15,16 +15,17 @@ export class DiscordWorker { * 初始化DisCord的配置文件 */ async InitData() { - if (this.mj_config) return; - // 初始化MJ配置 - let _mjSettingService = await MJSettingService.getInstance(); - let mjSettings = _mjSettingService.GetMJSettingTreeData(); - if (mjSettings.code == 0) { - throw new Error(mjSettings.message); - } - let mjSetting = mjSettings.data; + // TODO 初始化的方式有修改 + // if (this.mj_config) return; + // // 初始化MJ配置 + // let _mjSettingService = await MJSettingService.getInstance(); + // let mjSettings = _mjSettingService.GetMJSettingTreeData_(); + // if (mjSettings.code == 0) { + // throw new Error(mjSettings.message); + // } + // let mjSetting = mjSettings.data; - this.mj_config = mjSetting; + // this.mj_config = mjSetting; } /** diff --git a/src/main/index.js b/src/main/index.js index e574c2f..f06f631 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -14,7 +14,6 @@ import { ImageGenerate } from './ReverseManage/imageGenerate.js' import { Setting } from './setting/setting' import { has, isEmpty } from 'lodash' import { AutoSync } from './setting/autoSync.js' -import { TaskManager } from './Service/task/taskManage' import { SoftWareServiceBasic } from './Service/ServiceBasic/softwareServiceBasic' // ipc @@ -22,12 +21,15 @@ import { DiscordIpc, RemoveDiscordIpc } from './IPCEvent/discordIpc.js' import { Logger } from './logger.js' import { RegisterIpc } from './IPCEvent/index.js' +import { InitRemoteMjSettingType } from './initFunc' + let tools = new Tools() let imageGenerate = new ImageGenerate(global) let setting = new Setting(global) let softWareServiceBasic = new SoftWareServiceBasic() async function InitData(gl) { + await InitRemoteMjSettingType() let res = await setting.getSettingDafultData() gl.config = res return res @@ -95,7 +97,7 @@ async function createWindow(hash = 'ShowMessage', data, url = null) { if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/#/' + hash) // mainWindow.webContents.openDevTools() - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' } else { if (hash != '') { mainWindow.loadURL(`file://${path.join(__dirname, '../renderer/index.html')}#/${hash}`) diff --git a/src/main/initFunc.ts b/src/main/initFunc.ts new file mode 100644 index 0000000..27afb84 --- /dev/null +++ b/src/main/initFunc.ts @@ -0,0 +1,25 @@ +import { isEmpty } from "lodash"; +import { errorMessage, successMessage } from "./Public/generalTools"; +import { SoftWareServiceBasic } from "./Service/ServiceBasic/softwareServiceBasic"; + + +/** + * 初始化远程MJ的设置类型 + * @description 远程MJ的设置类型有两种:remote和local,remote表示远程代理模式,local表示本地模式 + */ +export async function InitRemoteMjSettingType() { + try { + let softWareServiceBasic = new SoftWareServiceBasic() + softWareServiceBasic.transaction((realm: any) => { + let remoteMjs = realm.objects('RemoteMJ'); + for (let remoteMj of remoteMjs) { + if (remoteMj.type == null || isEmpty(remoteMj.type)) { + remoteMj.type = "remote" // 默认都是remote的; + } + } + }) + successMessage("", "初始化远程MJ的设置类型成功", "InitRemoteMjSettingType") + } catch (error) { + errorMessage("初始化远程MJ的设置类型失败," + error.toString(), "InitRemoteMjSettingType") + } +} \ No newline at end of file diff --git a/src/main/setting/autoSync.js b/src/main/setting/autoSync.js index f172246..3e9882c 100644 --- a/src/main/setting/autoSync.js +++ b/src/main/setting/autoSync.js @@ -66,149 +66,12 @@ async function GlobalAutoSync() { * 自动同步MJ配置数据 */ -async function AutoSyncMJConfig2210() { - try { - // 判断版本 - if (version != '2.2.10') { - return - } - - // 同步MJ的配置到服务器中 - let mjConfigJson = JSON.parse(await fspromises.readFile(define.img_base, 'utf-8')) - // 开始同步APIMJsetting - let _mjSettingService = await MJSettingService.getInstance() - - if (!mjConfigJson.mj_config) { - return - } - - // 判断数据库中有没有API数据 - let dbApiSetting = _mjSettingService.GetAPIMjSetting(null) - if (dbApiSetting.code == 1 && dbApiSetting.data.length <= 0) { - // 同步API请求配置 - if ( - mjConfigJson.mj_config.mj_api_url && - mjConfigJson.mj_config.mj_speed && - mjConfigJson.mj_config.api_key - ) { - let apiSetting = { - mjApiUrl: mjConfigJson.mj_config.mj_api_url, - mjSpeed: mjConfigJson.mj_config.mj_speed, - apiKey: mjConfigJson.mj_config.api_key - } - let res = _mjSettingService.AddAPIMjSetting(apiSetting) - if (res.code == 1) { - global.logger.info('AutoSyncMJConfig2210', '自动同步MJ API 配置数据成功') - } else { - global.logger.error( - 'AutoSyncMJConfig2210', - '自动同步MJ API 配置数据失败,错误信息如下:' + '\n' + res.message - ) - } - } - } - - // 判断数据库中是不是存在浏览器配置数据,不存在同步 - let dbBrowserSetting = _mjSettingService.GetBrowserMJSetting(null) - if (dbBrowserSetting.code == 1 && dbBrowserSetting.data.length <= 0) { - // 同步浏览器配置,判断数据是不是存在 - if ( - isEmpty(mjConfigJson.mj_config.serviceID) || - isEmpty(mjConfigJson.mj_config.channelID) || - isEmpty(mjConfigJson.mj_config.token) || - !mjConfigJson.mj_config.userAgent || - isEmpty(mjConfigJson.mj_config.userAgent) || - isEmpty(mjConfigJson.mj_config.userAgent.userAgent) - ) { - return - } - - // 开始添加浏览器配置 - let browserSetting = { - serviceId: mjConfigJson.mj_config.serviceID, - channelId: mjConfigJson.mj_config.channelID, - token: mjConfigJson.mj_config.token, - userAgent: mjConfigJson.mj_config.userAgent.userAgent - } - let res = _mjSettingService.AddBrowserMJSetting(browserSetting) - if (res.code == 1) { - global.logger.info('AutoSyncMJConfig2210', '自动同步MJ 浏览器配置数据成功') - } else { - global.logger.error( - 'AutoSyncMJConfig2210', - '自动同步MJ 浏览器配置数据失败,错误信息如下:' + '\n' + res.message - ) - } - } - - // 判断基础数据,不存在同步 - let mjSetting = _mjSettingService.GetMjSetting() - if (mjSetting.code == 1 && mjSetting.data.length <= 0) { - //判断数据然后选择同步 - if ( - isEmpty(mjConfigJson.mj_config.request_model) || - isEmpty(mjConfigJson.mj_config.select_robot) || - isEmpty(mjConfigJson.mj_config.image_scale) || - isEmpty(mjConfigJson.mj_config.image_model) || - isEmpty(mjConfigJson.mj_config.image_suffix) - ) { - return - } - - // 开始添加基础配置 - let mjSettingData = { - requestModel: mjConfigJson.mj_config.request_model, - selectRobot: mjConfigJson.mj_config.select_robot, - imageScale: mjConfigJson.mj_config.image_scale, - imageModel: mjConfigJson.mj_config.image_model, - imageSuffix: mjConfigJson.mj_config.image_suffix, - taskCount: mjConfigJson.mj_config.task_count ? mjConfigJson.mj_config.task_count : 3, - spaceTime: mjConfigJson.mj_config.space_time ? mjConfigJson.mj_config.space_time : 5 - } - let res = _mjSettingService.AddMJSetting(mjSettingData) - if (res.code == 1) { - global.logger.info('AutoSyncMJConfig2210', '自动同步MJ 基础配置数据成功') - } else { - global.logger.error( - 'AutoSyncMJConfig2210', - '自动同步MJ 基础配置数据失败,错误信息如下:' + '\n' + res.message - ) - } - } - - // 初始化默认数据 - let _softwareService = await SoftwareService.getInstance() - let softs = await _softwareService.GetSoftwareData(null) - if (softs.code == 1 && softs.data.length <= 0) { - // 添加 - let softData = { - theme: 'light', - reverse_display_show: false, - reverse_show_book_striped: false, - reverse_data_table_size: 'small' - } - let res = await _softwareService.AddSfotware(softData) - if (res.code == 0) { - throw new Error(res.message) - } - - global.logger.info('AutoSyncMJConfig2210', '自动同步软件配置数据成功') - } - - return mjConfigJson - } catch (error) { - // 同步数据不报错,只添加日志 - global.logger.error( - 'AutoSyncMJConfig2210', - '自动同步MJ配置数据失败,错误信息如下:' + '\n' + error.toString() - ) - } -} +async function AutoSyncMJConfig2210() {} //#endregion export async function AutoSync() { // 2.2.10 版本 自动同步数据 - await AutoSyncMJConfig2210() + // await AutoSyncMJConfig2210() // 通用同步 await GlobalAutoSync() } diff --git a/src/main/setting/mjSetting.js b/src/main/setting/mjSetting.js deleted file mode 100644 index f9d328f..0000000 --- a/src/main/setting/mjSetting.js +++ /dev/null @@ -1,383 +0,0 @@ -import axios from 'axios' -import { MJSettingService } from '../../define/db/service/SoftWare/mjSettingService' -import { define } from '../../define/define' -import { errorMessage, successMessage } from '../Public/generalTools' -import { isEmpty } from 'lodash' -const { v4: uuidv4 } = require('uuid') - -export class MJSetting { - constructor() {} - - /** - * 同步远程代理服务器中的MJ账号信息 - */ - async GetRemoteMJSettingsFromService() { - try { - let url = define.remotemj_api + 'mj/account/query' - let res = await axios.post( - url, - { remark: global.machineId, current: 1, pageNumber: 0, pageSize: 30 }, - { headers: { 'mj-api-secret': define.API } } - ) - - console.log('GetRemoteMJSettingsFromService', res) - if (res.status != 200) { - throw new Error(res.statusText) - } - if (!res.data || !res.data.content) { - throw new Error('远程服务器返回数据格式错误') - } - let content = res.data.content - - let remoteMjSetting = await this.GetRemoteMJSettings() - if (remoteMjSetting.code == 0) { - throw new Error(remoteMjSetting.message) - } - - let remoteIds = remoteMjSetting.data.map((item) => item.id) - for (let i = 0; i < remoteIds.length; i++) { - const element = remoteIds[i] - let deleteRes = await this.DeleteRemoteMJSetting(element, false) - if (deleteRes.code == 0) { - throw new Error(deleteRes.message) - } - } - - if (content.length <= 0) { - // 没有数据,删除当前的所有的配置 - } else { - // 先将所有的数据删除,再添加 - for (let i = 0; i < content.length; i++) { - const element = content[i] - - let addRes = await this.AddRemoteMJSetting( - { - channelId: element.channelId, - guildId: element.guildId, - userToken: element.userToken, - coreSize: element.coreSize, - queueSize: element.queueSize, - timeoutMinutes: element.timeoutMinutes, - userAgent: element.userAgent, - remark: element.remark, - enable: element.enable, - remixAutoSubmit: element.remixAutoSubmit, - mjBotChannelId: element.mjBotChannelId, - nijiBotChannelId: element.nijiBotChannelId, - accountId: element.id, - blockMessage: element.properties.disabledReason - }, - false - ) - if (addRes.code == 0) { - throw new Error(addRes.message) - } - } - } - return successMessage( - null, - '同步远程代理服务器中的MJ账号信息成功', - 'MJSetting_GetRemoteMJSettingsFromService' - ) - } catch (error) { - return errorMessage( - '同步远程代理服务器中的MJ账号信息错误,详细错误信息如下:' + error.toString(), - 'MJSetting_GetRemoteMJSettingsFromService' - ) - } - } - - /** - * 获取MJ的基础设置数据 - */ - async GetMJSetting(mjSettingQuery) { - try { - let _mjSetting = await MJSettingService.getInstance() - let res = _mjSetting.GetMjSetting() - return res - } catch (error) { - return errorMessage( - '获取MJ的基础配置错误,错误信息如下:' + error.toString(), - 'MJSetting_GetMJSetting' - ) - } - } - - /** - * 保存MJ的基础设置 - * @param {*} mjSetting 保存的数据 - */ - async UpdateMJSetting(mjSetting) { - try { - let _mjSetting = await MJSettingService.getInstance() - let res = _mjSetting.UpdateMJSetting(mjSetting) - return res - } catch (error) { - return errorMessage( - '保存MJ的基础配置错误,错误信息如下:' + error.toString(), - 'MJSetting_UpdateMJSetting' - ) - } - } - - /** - * 获取MJ配置的所有数据 - */ - async GetMJSettingTreeData() { - try { - let _mjSetting = await MJSettingService.getInstance() - let res = _mjSetting.GetMJSettingTreeData() - return res - } catch (error) { - return errorMessage( - '获取MJ配置错误,详细错误信息如下:' + error.toString(), - 'MJSetting_GetMJSettingTreeData' - ) - } - } - - /** - * 保存MJ设置的所有数据 - * @param {*} mjSetting - */ - async SaveMJSettingTreeData(mjSetting) { - try { - let _mjSetting = await MJSettingService.getInstance() - let res = _mjSetting.SaveMJSettingTreeData(mjSetting) - return res - } catch (error) { - return errorMessage( - '保存MJ配置错误,详细错误信息如下:' + error.toString(), - 'MJSetting_SaveMJSettingTreeData' - ) - } - } - - /** - * 获取所有的MJ代理模式账号信息 - */ - async GetRemoteMJSettings() { - try { - let _mjSetting = await MJSettingService.getInstance() - let res = _mjSetting.GetRemoteMJSettings(null) - return res - } catch (error) { - return errorMessage( - '获取MJ代理模式账号信息错误,详细错误信息如下:' + error.toString(), - 'MJSetting_GetRemoteMJSettings' - ) - } - } - - /** - * 创建新的代理MJ信息 - * @param {*} value - */ - async AddRemoteMJSetting(value, isRemote) { - try { - // 先检查必填字段 - console.log(value) - if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) { - throw new Error('必填字段服务器ID,频道ID,用户token不能为空') - } - - if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) { - throw new Error('必填字段核心线程数,队列大小,超时时间不能为空') - } - if (!value.userAgent) { - value.userAgent = - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' - } - - // 开始调用创建任务 - let createUrl = define.remotemj_api + 'mj/account/create' - // 上面是必传的 - let remoteData = { - channelId: value.channelId, - guildId: value.guildId, - userToken: value.userToken, - coreSize: value.coreSize, - queueSize: value.queueSize, - timeoutMinutes: value.timeoutMinutes, - userAgent: value.userAgent - ? value.userAgent - : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', - remark: global.machineId, - remixAutoSubmit: false - } - - // 额外添加 - if (value.mjBotChannelId) { - remoteData.mjBotChannelId = value.mjBotChannelId - } - if (value.nijiBotChannelId) { - remoteData.nijiBotChannelId = value.nijiBotChannelId - } - if (value.accountId) { - remoteData.accountId = value.accountId - } - if (!isEmpty(value.blockMessage)) { - remoteData.blockMessage = value.blockMessage - } - if (value.hasOwnProperty('enable')) { - remoteData.enable = value.enable - } - - if (isRemote) { - // 添加账号 - let accountRes = await axios.post(createUrl, remoteData, { - headers: { - 'mj-api-secret': define.API - } - }) - console.log(accountRes) - - if (accountRes.data.code != 1) { - throw new Error(accountRes.data.description) - } - - // 添加成功,修改数据,将数据返回 (服务器添加成功,开始在本地数据库添加)s - let accountId = accountRes.data.result - remoteData.accountId = accountId - } - - remoteData.remixAutoSubmit = false - - let _mjSettingService = await MJSettingService.getInstance() - - let save_res = _mjSettingService.AddRemoteMjSetting(remoteData) - if (save_res.code != 1) { - throw new Error(save_res.message) - } - return successMessage(remoteData, 'MJ账号同步成功', 'MJSetting_AddRemoteMJSetting') - } catch (error) { - return errorMessage( - '创建新的代理MJ信息错误,详细错误信息如下:' + error.toString(), - 'MJSetting_AddRemoteMJSetting' - ) - } - } - - /** - * 修改MJ的账号信息,并重连 - * @param {*} value - */ - async UpdateRemoteMJSetting(value) { - try { - // 先检查必填字段 - console.log(value) - - if (isEmpty(value.accountId)) { - throw new Error('修改不能没有账号实例ID') - } - - if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) { - throw new Error('必填字段服务器ID,频道ID,用户token不能为空') - } - - if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) { - throw new Error('必填字段核心线程数,队列大小,超时时间不能为空') - } - if (!value.userAgent) { - value.userAgent = - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' - } - - // 开始调用更新重连任务 - let updateUrl = define.remotemj_api + `mj/account/${value.accountId}/update-reconnect` - - // 开始修改 - let remoteData = { - channelId: value.channelId, - coreSize: value.coreSize, - enable: value.enable, - guildId: value.guildId, - id: value.accountId, - mjBotChannelId: value.mjBotChannelId ? value.mjBotChannelId : '', - nijiBotChannelId: value.nijiBotChannelId ? value.nijiBotChannelId : '', - queueSize: value.queueSize, - remark: global.machineId, - remixAutoSubmit: false, - timeoutMinutes: value.timeoutMinutes ? value.timeoutMinutes : 10, - userAgent: value.userAgent, - userToken: value.userToken, - weight: 1 - } - - let accountRes = await axios.put(updateUrl, remoteData, { - headers: { - 'mj-api-secret': define.API - } - }) - - if (accountRes.data.code != 1) { - throw new Error(accountRes.description) - } - - // 更新成功,修改数据 - remoteData.accountId = value.accountId - remoteData.id = value.id - - // 同步成功,修改数据 - let _mjSettingService = await MJSettingService.getInstance() - let save_res = _mjSettingService.UpdateRemoteMjSetting(remoteData) - - if (save_res.code == 0) { - throw new Error(save_res.message) - } - - return successMessage(remoteData, 'MJ账号修改并同步成功', 'MJSetting_UpdateRemoteMJSetting') - } catch (error) { - return errorMessage( - '修改MJ的账号信息错误,详细错误信息如下:' + error.toString(), - 'MJSetting_UpdateRemoteMJSetting' - ) - } - } - - /** - * 删除指定的MJ账号 - * @param {*} id 数据库中存放的ID - */ - async DeleteRemoteMJSetting(id, isRemote) { - try { - // 先检查必填字段 - if (isEmpty(id)) { - throw new Error('无法删除没有ID的数据') - } - // 先获取数据 - let _mjSetting = await MJSettingService.getInstance() - let deleteConfig = _mjSetting.GetRemoteMJSettings({ id: id }) - if (deleteConfig.data.length <= 0) { - throw new Error('没有要删除的数据') - } - - if (isRemote) { - // 开始删除 - let deleteData = deleteConfig.data[0] - let deleteUrl = define.remotemj_api + `mj/account/${deleteData.accountId}/delete` - let accountRes = await axios.delete(deleteUrl, { - headers: { - 'mj-api-secret': define.API - } - }) - if (accountRes.data.code != 1) { - throw new Error(accountRes.data.description) - } - } - - // 删除本地数据 - // 删除成功,修改数据 - let save_res = _mjSetting.DeleteRemoteMJSetting(id) - if (save_res.code == 0) { - throw new Error(save_res.message) - } - return successMessage(null, 'MJ账号删除成功', 'MJSetting_DeleteRemoteMJSetting') - } catch (error) { - return errorMessage( - '删除指定的MJ账号错误,详细错误信息如下:' + error.toString(), - 'MJSetting_DeleteRemoteMJSetting' - ) - } - } -} diff --git a/src/main/setting/mjSetting.ts b/src/main/setting/mjSetting.ts new file mode 100644 index 0000000..8a605eb --- /dev/null +++ b/src/main/setting/mjSetting.ts @@ -0,0 +1,553 @@ +import axios from 'axios' +import { MJSettingService } from '../../define/db/service/SoftWare/mjSettingService' +import { define } from '../../define/define' +import { errorMessage, successMessage } from '../Public/generalTools' +import { isEmpty } from 'lodash' +const { v4: uuidv4 } = require('uuid') +import OptionHandle from "@/main/Service/Options/index" +import { OptionKeyName } from '@/define/enum/option' +import { ValidateJson } from '@/define/Tools/validate' +import { MJSettingModel } from '@/model/Setting/mjSetting' + +export class MJSetting { + constructor() { } + + /** + * 同步远程代理服务器中的MJ账号信息 + * @param type 使用的类型 + * @returns + */ + async GetRemoteMJSettingsFromService(type: string) { + try { + if (type != 'remote' && type != 'local') { + throw new Error('没有指定类型,请检查') + } + let content = undefined + let mjGlobalSetting = await this.GetMJGlobalSetting() + if (type == "local") { + if (isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.port) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.token)) { + throw new Error('没有配置本地代理模式的基本信息,请检查') + } + mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl = mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.endsWith('/') ? mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.slice(0, -1) : mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl; + + // 调用分页获取所有的账号信息 + let url = `${mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl}:${mjGlobalSetting.mj_localRemoteSimpleSetting.port}/mj/admin/accounts`; + let res = await axios.post(url, { + pagination: { + current: 1, + pageSize: 200 + }, + sort: { + predicate: "", + reverse: false + }, + search: { + current: 1, + pageSize: 10, + pageNumber: 0 + } + }, { + headers: { + 'mj-api-secret': mjGlobalSetting.mj_localRemoteSimpleSetting.token + } + }) + console.log('GetRemoteMJSettingsFromService', res) + if (res.status != 200) { + throw new Error(res.statusText) + } + if (!res.data || !res.data.list) { + throw new Error('远程服务器返回数据格式错误') + } + content = res.data.list + } else { + let url = define.remotemj_api + 'mj/account/query' + let res = await axios.post( + url, + { remark: global.machineId, current: 1, pageNumber: 0, pageSize: 30 }, + { headers: { 'mj-api-secret': define.API } } + ) + + console.log('GetRemoteMJSettingsFromService', res) + if (res.status != 200) { + throw new Error(res.statusText) + } + if (!res.data || !res.data.content) { + throw new Error('远程服务器返回数据格式错误') + } + content = res.data.content + } + + + + + + let remoteMjSetting = await this.GetRemoteMJSettings(type) + if (remoteMjSetting.code == 0) { + throw new Error(remoteMjSetting.message) + } + + let remoteIds = remoteMjSetting.data.map((item) => item.id) + for (let i = 0; i < remoteIds.length; i++) { + const element = remoteIds[i] + let deleteRes = await this.DeleteRemoteMJSetting(element, false) + if (deleteRes.code == 0) { + throw new Error(deleteRes.message) + } + } + + + // 先将所有的数据删除,再添加 + for (let i = 0; i < content.length; i++) { + const element = content[i] + + let addRes = await this.AddRemoteMJSetting( + { + channelId: element.channelId, + guildId: element.guildId, + userToken: element.userToken, + coreSize: element.coreSize, + queueSize: element.queueSize, + timeoutMinutes: element.timeoutMinutes, + userAgent: element.userAgent, + remark: element.remark, + enable: element.enable, + remixAutoSubmit: element.remixAutoSubmit, + mjBotChannelId: element.mjBotChannelId, + nijiBotChannelId: element.nijiBotChannelId, + accountId: element.id, + blockMessage: element.properties.disabledReason || element.disabledReason + }, + false, type + ) + if (addRes.code == 0) { + throw new Error(addRes.message) + } + } + + return successMessage( + null, + '同步远程代理服务器中的MJ账号信息成功', + 'MJSetting_GetRemoteMJSettingsFromService' + ) + } catch (error) { + return errorMessage( + '同步远程代理服务器中的MJ账号信息错误,详细错误信息如下:' + error.toString(), + 'MJSetting_GetRemoteMJSettingsFromService' + ) + } + } + + /** + * 获取MJ的基础设置数据 + * @param mjSettingQuery + * @returns + */ + async GetMJSetting(mjSettingQuery) { + try { + let _mjSetting = await MJSettingService.getInstance() + let res = _mjSetting.GetMjSetting() + return res + } catch (error) { + return errorMessage( + '获取MJ的基础配置错误,错误信息如下:' + error.toString(), + 'MJSetting_GetMJSetting' + ) + } + } + + /** + * 获取MJ的全局设置数据 + * @returns + */ + private async GetMJGlobalSetting(): Promise { + let mjSettingOption = await OptionHandle.GetOptionByKey(OptionKeyName.MJ_GlobalSetting); + if (mjSettingOption.code == 0) { + throw new Error(mjSettingOption.message) + } + if (mjSettingOption.data == null || mjSettingOption.data == undefined) { + throw new Error('没有找到MJ的全局设置,请检查') + } + if (!ValidateJson(mjSettingOption.data.value)) { + throw new Error('MJ的全局设置数据格式错误,请检查') + } + let mjSetting = JSON.parse(mjSettingOption.data.value) as MJSettingModel.MJ_GlobalSettingModel + if (!mjSetting) { + throw new Error('MJ的全局设置数据格式错误,请检查') + } + return mjSetting + } + + /** + * 获取MJ配置的所有数据 + */ + async GetMJSettingTreeData() { + try { + let _mjSetting = await MJSettingService.getInstance() + let res = _mjSetting.GetMJSettingTreeData() + return res + } catch (error) { + return errorMessage( + '获取MJ配置错误,详细错误信息如下:' + error.toString(), + 'MJSetting_GetMJSettingTreeData' + ) + } + } + + /** + * 保存MJ设置的所有数据 + * @param {*} mjSetting + */ + async SaveMJSettingTreeData(mjSetting) { + try { + let _mjSetting = await MJSettingService.getInstance() + let res = _mjSetting.SaveMJSettingTreeData(mjSetting) + return res + } catch (error) { + return errorMessage( + '保存MJ配置错误,详细错误信息如下:' + error.toString(), + 'MJSetting_SaveMJSettingTreeData' + ) + } + } + + /** + * 获取所有的MJ代理模式账号信息 + */ + async GetRemoteMJSettings(type: string) { + try { + let _mjSetting = await MJSettingService.getInstance() + let res = _mjSetting.GetRemoteMJSettings({ + type: type + }) + return res + } catch (error) { + return errorMessage( + '获取MJ代理模式账号信息错误,详细错误信息如下:' + error.toString(), + 'MJSetting_GetRemoteMJSettings' + ) + } + } + + /** + * 创建新的代理MJ信息 + * @param {*} value + */ + async AddRemoteMJSetting(value, isRemote, type: string) { + try { + if (type != "remote" && type != 'local') { + throw new Error('没有指定类型,请检查') + } + // 先检查必填字段 + if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) { + throw new Error('必填字段服务器ID,频道ID,用户token不能为空') + } + + if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) { + throw new Error('必填字段核心线程数,队列大小,超时时间不能为空') + } + if (!value.userAgent) { + value.userAgent = + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' + } + + // 开始调用创建任务 + let createUrl = undefined; + let mjGlobalSetting = await this.GetMJGlobalSetting() + + if (type == 'remote') { + createUrl = define.remotemj_api + 'mj/account/create' + } + else if (type == 'local') { + let localRemoteBaseUrl = "http://127.0.0.1"; + if (!isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl)) { + localRemoteBaseUrl = mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl + } + let localRemotePort = "8080"; + if (!isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.port)) { + localRemotePort = mjGlobalSetting.mj_localRemoteSimpleSetting.port + } + createUrl = `${localRemoteBaseUrl}:${localRemotePort}` + '/mj/admin/account' + } + + if (createUrl == null) { + throw new Error('没有指定类型,请检查') + } + + + // 上面是必传的 + let remoteData = { + channelId: value.channelId, + guildId: value.guildId, + userToken: value.userToken, + coreSize: value.coreSize, + queueSize: value.queueSize, + timeoutMinutes: value.timeoutMinutes, + userAgent: value.userAgent + ? value.userAgent + : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', + remark: global.machineId, + remixAutoSubmit: false + } as any + + // 额外添加 + if (value.mjBotChannelId) { + remoteData.mjBotChannelId = value.mjBotChannelId + } + if (value.nijiBotChannelId) { + remoteData.nijiBotChannelId = value.nijiBotChannelId + } + if (value.accountId) { + remoteData.accountId = value.accountId + } + if (!isEmpty(value.blockMessage)) { + remoteData.blockMessage = value.blockMessage + } + if (value.hasOwnProperty('enable')) { + remoteData.enable = value.enable + } + + if (isRemote) { + // 添加账号 + let token = define.API; + if (type == 'local') { + token = mjGlobalSetting.mj_localRemoteSimpleSetting.token + } + let accountRes = await axios.post(createUrl, remoteData, { + headers: { + 'mj-api-secret': token + } + }) + console.log(accountRes) + + if (type == 'local' && !accountRes.data.success) { + throw new Error(accountRes.data.message) + } + if (type == 'remote' && accountRes.data.code != 1) { + throw new Error(accountRes.data.description) + } + + // 添加成功,修改数据,将数据返回 (服务器添加成功,开始在本地数据库添加)s + let accountId = accountRes.data.result + remoteData.accountId = accountId + + // 这边将数据记录到本地数据库中 + if (type == 'local') { + try { + var data = JSON.stringify({ + type: 0, + dataString: JSON.stringify(remoteData) + }); + + var config = { + method: 'post', + url: define.lms + '/lms/Other/AddDataInfo', + headers: { + 'User-Agent': 'Apifox/1.0.0 (https://apifox.com)', + 'Content-Type': 'application/json', + }, + data: data + }; + await axios(config); + + } catch (error) { + // 忽略错误 + // console.error('Error:', error.message); + } + } + } + + remoteData.remixAutoSubmit = false + remoteData.type = type + + let _mjSettingService = await MJSettingService.getInstance() + + let save_res = _mjSettingService.AddRemoteMjSetting(remoteData) + if (save_res.code != 1) { + throw new Error(save_res.message) + } + return successMessage(remoteData, 'MJ账号同步成功', 'MJSetting_AddRemoteMJSetting') + } catch (error) { + return errorMessage( + '创建新的代理MJ信息错误,详细错误信息如下:' + error.toString(), + 'MJSetting_AddRemoteMJSetting' + ) + } + } + + /** + * 修改MJ的账号信息,并重连 + * @param {*} value + */ + async UpdateRemoteMJSetting(value, type: string) { + try { + if (type != "remote" && type != 'local') { + throw new Error('没有指定类型,请检查') + } + + if (isEmpty(value.accountId)) { + throw new Error('修改不能没有账号实例ID') + } + + if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) { + throw new Error('必填字段服务器ID,频道ID,用户token不能为空') + } + + if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) { + throw new Error('必填字段核心线程数,队列大小,超时时间不能为空') + } + if (!value.userAgent) { + value.userAgent = + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' + } + + // 开始调用更新重连任务 + let updateUrl = undefined; + let mjGlobalSetting = await this.GetMJGlobalSetting() + if (type == 'remote') { + updateUrl = define.remotemj_api + `mj/account/${value.accountId}/update-reconnect` + } else if (type == 'local') { + if (isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.port) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.token)) { + throw new Error('没有配置本地代理模式的基本信息,请检查') + } + let localRemoteBaseUrl = mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.endsWith('/') ? mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.slice(0, -1) : mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl; + let localRemotePort = mjGlobalSetting.mj_localRemoteSimpleSetting.port; + updateUrl = `${localRemoteBaseUrl}:${localRemotePort}/mj/admin/account-reconnect/${value.accountId}` + } + + if (updateUrl == null) { + throw new Error('没有指定类型,请检查') + } + + // 开始修改 + let remoteData = { + channelId: value.channelId, + coreSize: value.coreSize, + enable: value.enable, + guildId: value.guildId, + id: value.accountId, + mjBotChannelId: value.mjBotChannelId ? value.mjBotChannelId : '', + nijiBotChannelId: value.nijiBotChannelId ? value.nijiBotChannelId : '', + queueSize: value.queueSize, + remark: global.machineId, + remixAutoSubmit: false, + timeoutMinutes: value.timeoutMinutes ? value.timeoutMinutes : 10, + userAgent: value.userAgent, + userToken: value.userToken, + weight: 1 + } as any + + let token = define.API; + if (type == 'local') { + token = mjGlobalSetting.mj_localRemoteSimpleSetting.token + remoteData.enableMj = true; + remoteData.enableNiji = true; + } + let accountRes = await axios.put(updateUrl, remoteData, { + headers: { + 'mj-api-secret': token + } + }) as any + + if (type == 'local' && !accountRes.data.success) { + throw new Error(accountRes.data.message) + } + if (type == 'remote' && accountRes.data.code != 1) { + throw new Error(accountRes.data.description) + } + + // 更新成功,修改数据 + remoteData.accountId = value.accountId + remoteData.id = value.id + remoteData.type = type + + // 同步成功,修改数据 + let _mjSettingService = await MJSettingService.getInstance() + let save_res = _mjSettingService.UpdateRemoteMjSetting(remoteData) + + if (save_res.code == 0) { + throw new Error(save_res.message) + } + + return successMessage(remoteData, 'MJ账号修改并同步成功', 'MJSetting_UpdateRemoteMJSetting') + } catch (error) { + return errorMessage( + '修改MJ的账号信息错误,详细错误信息如下:' + error.toString(), + 'MJSetting_UpdateRemoteMJSetting' + ) + } + } + + /** + * 删除指定的MJ账号 + * @param {*} id 数据库中存放的ID + */ + async DeleteRemoteMJSetting(id, isRemote) { + try { + // 先检查必填字段 + if (isEmpty(id)) { + throw new Error('无法删除没有ID的数据') + } + // 先获取数据 + let _mjSetting = await MJSettingService.getInstance() + let deleteConfig = _mjSetting.GetRemoteMJSettings({ id: id }) + if (deleteConfig.data.length <= 0) { + throw new Error('没有要删除的数据') + } + + if (isRemote) { + // 开始删除 + let deleteData = deleteConfig.data[0] + let type = deleteData.type; + if (type != 'remote' && type != 'local') { + throw new Error('没有指定类型,请检查') + } + // 删除远程的账号 + if (type == 'local') { + let mjGlobalSetting = await this.GetMJGlobalSetting() + if (isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.port) || isEmpty(mjGlobalSetting.mj_localRemoteSimpleSetting.token)) { + throw new Error('没有配置本地代理模式的基本信息,请检查') + } + let localRemoteBaseUrl = mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.endsWith('/') ? mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl.slice(0, -1) : mjGlobalSetting.mj_localRemoteSimpleSetting.baseUrl; + let localRemotePort = mjGlobalSetting.mj_localRemoteSimpleSetting.port; + let deleteUrl = `${localRemoteBaseUrl}:${localRemotePort}/mj/admin/account/${deleteData.accountId}` + + let accountRes = await axios.delete(deleteUrl, { + headers: { + 'mj-api-secret': mjGlobalSetting.mj_localRemoteSimpleSetting.token + } + }) + if (accountRes.status != 200) { + throw new Error(accountRes.data.message) + } + if (accountRes.data.success == false) { + throw new Error(accountRes.data.message) + } + } else { + // remote + let deleteUrl = define.remotemj_api + `mj/account/${deleteData.accountId}/delete` + let accountRes = await axios.delete(deleteUrl, { + headers: { + 'mj-api-secret': define.API + } + }) + if (accountRes.data.code != 1) { + throw new Error(accountRes.data.description) + } + } + } + + // 删除本地数据 + // 删除成功,修改数据 + let save_res = _mjSetting.DeleteRemoteMJSetting(id) + if (save_res.code == 0) { + throw new Error(save_res.message) + } + return successMessage(null, 'MJ账号删除成功', 'MJSetting_DeleteRemoteMJSetting') + } catch (error) { + return errorMessage( + '删除指定的MJ账号错误,详细错误信息如下:' + error.toString(), + 'MJSetting_DeleteRemoteMJSetting' + ) + } + } +} diff --git a/src/model/Setting/mjSetting.d.ts b/src/model/Setting/mjSetting.d.ts index a43857a..1e714ce 100644 --- a/src/model/Setting/mjSetting.d.ts +++ b/src/model/Setting/mjSetting.d.ts @@ -98,6 +98,15 @@ declare namespace MJSettingModel { useTransfer: boolean // 是否国内转发 } + /** + * MJ本地代理模式配置数据模型 + */ + type MJLocalRemoteSimpleSettingModel = { + baseUrl: string + port: string + token: string + } + /** * MJ 全局设置 */ @@ -106,5 +115,6 @@ declare namespace MJSettingModel { mj_apiSetting: MJAPISettingModel mj_browserSetting: BrowserMJSettingModel mj_remoteSimpleSetting: MJRemoteSimpleSettingModel + mj_localRemoteSimpleSetting: MJLocalRemoteSimpleSettingModel } } diff --git a/src/preload/mj.js b/src/preload/mj.js index 7edf330..b93e333 100644 --- a/src/preload/mj.js +++ b/src/preload/mj.js @@ -25,6 +25,7 @@ const mj = { // 将翻译任务添加到后台队列中 TranslateReturnNowTask: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.MJ.TRANSLATE_RETURN_NOW_TASK, value)), + // MJ原创生图 OriginalMJImageGenerate: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.MJ.ORIGINAL_MJ_IMAGE_GENERATE, value)), diff --git a/src/preload/setting.ts b/src/preload/setting.ts index ad53a21..09bd404 100644 --- a/src/preload/setting.ts +++ b/src/preload/setting.ts @@ -33,10 +33,6 @@ const setting = { GetMjSetting: async (value = null) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING, value), - // 保存MJ的基础设置 - UpdateMJSetting: async (value) => - await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, value), - // 获取MJ的所有设置 GetMJSettingTreeData: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA), @@ -46,23 +42,23 @@ const setting = { await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_MJ_SETTING_TREE_DATA, value), // 获取所有的代理MJ的账号 - GetRemoteMJSettings: async () => - await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS), + GetRemoteMJSettings: async (type: string) => + await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS, type), // 添加代理模式的MJ账号 - AddRemoteMJSetting: async (value, isRemote) => - await ipcRenderer.invoke(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, value, isRemote), + AddRemoteMJSetting: async (value, type) => + await ipcRenderer.invoke(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, value, type), // 修改并重连MJ的账号 - UpdateRemoteMJSetting: async (value) => - await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, value), + UpdateRemoteMJSetting: async (value, type: string) => + await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, value, type), // 删除指定的MJ账号 DeleteRemoteMJSetting: async (value: string, isRemote: boolean) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, value, isRemote), /** 同步代理服务器的账号信息 */ - GetRemoteMJSettingsFromService: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS_FROM_SERVICE), + GetRemoteMJSettingsFromService: async (type: string) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS_FROM_SERVICE, type), //#endregion diff --git a/src/renderer/src/assets/css/note.less b/src/renderer/src/assets/css/note.less new file mode 100644 index 0000000..835cf79 --- /dev/null +++ b/src/renderer/src/assets/css/note.less @@ -0,0 +1,79 @@ +.custom-collapse { + margin-top: 16px; + border-radius: 6px; + background-color: rgba(255, 247, 231, 0.6); + border: 1px solid #ffe7a3; + overflow: hidden; +} + +.collapse-header { + display: flex; + align-items: center; + font-weight: bold; + color: #b88230; + padding: 8px 0; + /* 增加上下内边距,使折叠状态下的高度更高 */ + font-size: 16px; + /* 增加字体大小 */ +} + +.collapse-header .warning-icon { + margin-right: 8px; + color: #e6a23c; +} + +/* 为Naive UI的折叠面板标题添加额外的样式 */ +:deep(.n-collapse-item__header) { + padding: 12px 20px !important; + /* 覆盖原有内边距 */ + height: auto !important; + /* 允许高度自适应内容 */ +} + +:deep(.n-collapse-item__header-main) { + display: flex; + align-items: center; +} + +.notes-section { + margin-top: 16px; + padding: 12px; + border-radius: 6px; + background-color: rgba(255, 247, 231, 0.6); + border: 1px solid #ffe7a3; +} + +.notes-title { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + margin-top: 0; + margin-bottom: 8px; + color: #b88230; +} + +.warning-icon { + margin-right: 6px; + color: #e6a23c; +} + +.notes-content { + padding-left: 24px; +} + +.notes-content p { + margin: 4px 0; + color: #5c3c10; +} + +.clickable-link { + color: #0077ff; + text-decoration: underline; + cursor: pointer; + transition: color 0.2s ease; +} + +.clickable-link:hover { + color: #0055cc; +} \ No newline at end of file diff --git a/src/renderer/src/components/Common/NotesCollapse.vue b/src/renderer/src/components/Common/NotesCollapse.vue new file mode 100644 index 0000000..79f75f4 --- /dev/null +++ b/src/renderer/src/components/Common/NotesCollapse.vue @@ -0,0 +1,140 @@ + + + + + + \ No newline at end of file diff --git a/src/renderer/src/components/Setting/Components/AddMultiRemoteMj.vue b/src/renderer/src/components/Setting/Components/AddMultiRemoteMj.vue index f583340..09303bb 100644 --- a/src/renderer/src/components/Setting/Components/AddMultiRemoteMj.vue +++ b/src/renderer/src/components/Setting/Components/AddMultiRemoteMj.vue @@ -3,7 +3,7 @@
新增账号 - 同步服务器帐号信息
@@ -25,8 +25,13 @@ let props = defineProps({ height: { type: Number, default: 500 + }, + type: { + type: String, + default: 'remote' } }) + let message = useMessage() let dialog = useDialog() let maxHeight = ref(props.height - 150) @@ -37,7 +42,7 @@ let spinning = ref(false) async function GetRemoteMJSettingsFromService() { spinning.value = true try { - let remoteMjSettingRes = await window.setting.GetRemoteMJSettingsFromService() + let remoteMjSettingRes = await window.setting.GetRemoteMJSettingsFromService(props.type) if (remoteMjSettingRes.code == 0) { message.error('获取代理MJ配置失败') return @@ -45,7 +50,7 @@ async function GetRemoteMJSettingsFromService() { message.success('同步服务器帐号信息成功') // 关闭的时候,刷新数据 - let res = await window.setting.GetRemoteMJSettings() + let res = await window.setting.GetRemoteMJSettings(props.type) if (res.code == 0) { message.error('获取代理MJ配置失败') } else { @@ -146,7 +151,7 @@ onMounted(async () => { spinning.value = true try { - let res = await window.setting.GetRemoteMJSettings() + let res = await window.setting.GetRemoteMJSettings(props.type) console.log(res) if (res.code == 0) { message.error('获取代理MJ配置失败') @@ -176,12 +181,12 @@ async function ManageAccount(remote = null) { dialog.create({ showIcon: false, title: '添加MJ账号', - content: () => h(ManageRemoteMjAccount, {}), + content: () => h(ManageRemoteMjAccount, { type: props.type }), style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`, maskClosable: false, onClose: async () => { // 关闭的时候,刷新数据 - let remoteMjSettingRes = await window.setting.GetRemoteMJSettings() + let remoteMjSettingRes = await window.setting.GetRemoteMJSettings(props.type) if (remoteMjSettingRes.code == 0) { message.error('获取代理MJ配置失败') } else { @@ -216,7 +221,7 @@ async function DeleteAccount(row, isRemote) { } message.success('删除账号成功') // 这边刷新一下数据 - let remoteMjSettingRes = await window.setting.GetRemoteMJSettings() + let remoteMjSettingRes = await window.setting.GetRemoteMJSettings(props.type) if (remoteMjSettingRes.code == 0) { message.error('获取代理MJ配置失败') } else { diff --git a/src/renderer/src/components/Setting/Components/ManageRemoteMjAccount.vue b/src/renderer/src/components/Setting/Components/ManageRemoteMjAccount.vue index f477bff..eebc703 100644 --- a/src/renderer/src/components/Setting/Components/ManageRemoteMjAccount.vue +++ b/src/renderer/src/components/Setting/Components/ManageRemoteMjAccount.vue @@ -102,74 +102,72 @@
- diff --git a/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue b/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue index c7d1d70..b7d4edf 100644 --- a/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue +++ b/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue @@ -52,16 +52,49 @@ + +

+ 1. 使用 + 无需科学上网,支持香港和美国节点,香港节点对大陆做了优化,延迟 + 100ms 以内 +

+

2. 提供 快速慢速 两种出图方式,可根据需求选择

+

3. 支持 20并发请求,可同时处理多张图片生成任务,大大提高工作效率

+

+ 4. 开启 "国内转发" 选项可解决部分地区(如河南、福建等)的网络访问问题 +

+

+ 5. 确保网络环境稳定,以保证服务正常运行,推荐稳定🪜: + + Just My Socks网络加速服务 + +

+
+ diff --git a/src/renderer/src/components/Setting/MJSetting/MJLocalRemoteSetting.vue b/src/renderer/src/components/Setting/MJSetting/MJLocalRemoteSetting.vue new file mode 100644 index 0000000..02dba87 --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJLocalRemoteSetting.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue b/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue index 40747ac..775b9f4 100644 --- a/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue +++ b/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue @@ -17,19 +17,36 @@ 账号管理 + +

1. 日常使用无需开启梯子,仅添加账号时需要网络代理

+

2. 通过账号管理功能可添加多个MJ账号,实现任务并行处理,提高效率

+

+ 3. 开启 "国内转发" 选项可解决部分地区(如河南、福建等)的网络访问问题 +

+

+ 4. 确保网络环境稳定,以保证服务正常运行,推荐稳定🪜: + + Just My Socks网络加速服务 + +

+
+ + diff --git a/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue b/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue index e453ddd..35304a0 100644 --- a/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue +++ b/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue @@ -3,7 +3,8 @@ - + + 保存MJ配置 @@ -19,6 +20,7 @@ import MJSimpleSetting from './MJSimpleSetting.vue' import MJAPISetting from './MJAPISetting.vue' import MJRemoteSetting from './MJRemoteSetting.vue' import MJBrowserSetting from './MJBrowserSetting.vue' +import MJLocalRemoteSetting from './MJLocalRemoteSetting.vue' import { MJImageType } from '@/define/enum/mjEnum' import { isEmpty } from 'lodash' @@ -64,6 +66,52 @@ async function InitMJSettingData() { } } else { optionStore.MJ_GlobalSetting = JSON.parse(mjRes.data.value) + if (optionStore.MJ_GlobalSetting.mj_apiSetting == null) { + optionStore.MJ_GlobalSetting.mj_apiSetting = { + apiKey: 'key', + id: '6db0d484-2a41-4545-8b26-ed32812965ad', + mjApiUrl: '2b443f53-ba12-42b3-a57c-e4df92685c73', + mjSpeed: 'RELAXED', + useTransfer: false + } + } + if (optionStore.MJ_GlobalSetting.mj_browserSetting == null) { + optionStore.MJ_GlobalSetting.mj_browserSetting = { + channelId: '自己的频道ID111111111', + customUserAgent: true, + id: '4d5d57f2-1d7a-4e0f-b347-a7283e75d64a', + mjBotId: '自己的MJ机器人ID', + nijBotId: '自己的NIJI机器人ID', + serviceId: '自己的服务器IDwwwwww', + token: '自己的令牌11111111111111', + userAgent: '自己的UserAgent111111111111111111111111111', + userAgentCustom: false + } + } + if (optionStore.MJ_GlobalSetting.mj_remoteSimpleSetting == null) { + optionStore.MJ_GlobalSetting.mj_remoteSimpleSetting = { + useTransfer: false + } + } + if (optionStore.MJ_GlobalSetting.mj_simpleSetting == null) { + optionStore.MJ_GlobalSetting.mj_simpleSetting = { + imageModel: '99377cad-c103-4cee-a958-86a104879328', + imageScale: '3e2772f2-041c-49c6-ba13-d0ed120310b8', + imageSuffix: ' --niji 6 --ar 1:1', + requestModel: 'api_mj', + selectRobot: 'niji', + spaceTime: 11, + taskCount: 3, + type: 'api_mj' + } + } + if (optionStore.MJ_GlobalSetting.mj_localRemoteSimpleSetting == null) { + optionStore.MJ_GlobalSetting.mj_localRemoteSimpleSetting = { + baseUrl: 'http://127.0.0.1', + port: '8080', + token: 'admin' + } + } message.success('加载MJSetting信息成功') } await TimeDelay(1000) @@ -98,7 +146,7 @@ async function SaveMjSetting() { if (request_model == MJImageType.REMOTE_MJ) { // 检查是不是有代理账号 - let remoteMjRes = await window.setting.GetRemoteMJSettings() + let remoteMjRes = await window.setting.GetRemoteMJSettings('remote') if (remoteMjRes.code == 0) { message.error('获取代理MJ配置失败') return @@ -123,6 +171,13 @@ async function SaveMjSetting() { } } + if (request_model == MJImageType.LOCAL_MJ) { + if (optionStore.MJ_GlobalSetting.mj_localRemoteSimpleSetting.token == null) { + message.error('请检查本地模式代理模式访问令牌是不是为空') + return + } + } + optionStore.MJ_GlobalSetting.mj_simpleSetting.type = optionStore.MJ_GlobalSetting.mj_simpleSetting.requestModel diff --git a/src/stores/option.ts b/src/stores/option.ts index fed86b1..c92d768 100644 --- a/src/stores/option.ts +++ b/src/stores/option.ts @@ -113,7 +113,13 @@ export const useOptionStore = defineStore('option', { }, mj_remoteSimpleSetting: { useTransfer: false + }, + mj_localRemoteSimpleSetting: { + baseUrl: "http://127.0.0.1", + port: "8080", + token: "admin", } + }, [OptionKeyName.ComfyUI_SimpleSetting]: { requestUrl: "",