2024-05-15 12:57:15 +08:00
|
|
|
|
import { DEFINE_STRING } from "../../define/define_string";
|
|
|
|
|
|
import { AsyncQueue } from '../quene'
|
|
|
|
|
|
import { PublicMethod } from '../Public/publicMethod'
|
|
|
|
|
|
import { ImageStyleDefine } from '../../define/iamgeStyleDefine'
|
|
|
|
|
|
import { DiscordSimple } from "../discord/discordSimple";
|
|
|
|
|
|
import { DiscordWorker } from "../discord/discordWorker";
|
|
|
|
|
|
import { Tools } from "../tools";
|
|
|
|
|
|
import path from 'path'
|
|
|
|
|
|
import sharp from 'sharp'
|
|
|
|
|
|
import { define } from "../../define/define";
|
2024-06-13 00:37:31 +08:00
|
|
|
|
import { AwesomeHelp } from "awesome-js";
|
2024-06-01 15:08:22 +08:00
|
|
|
|
import { checkStringValueAddSuffix, errorMessage, successMessage } from "../generalTools";
|
|
|
|
|
|
import { ImageSetting } from "../../define/setting/imageSetting";
|
|
|
|
|
|
import { DiscordAPI } from "../../api/discordApi";
|
|
|
|
|
|
import { GPT } from "../Public/GPT";
|
2024-06-13 00:37:31 +08:00
|
|
|
|
import { TagDefine } from "../../define/tagDefine";
|
|
|
|
|
|
import { cloneDeep } from "lodash";
|
|
|
|
|
|
import { LOGGER_DEFINE } from "../../define/logger_define";
|
2024-06-24 13:11:19 +08:00
|
|
|
|
import { MJImageType } from "../../define/enum/mjEnum";
|
|
|
|
|
|
import { MJSettingService } from "../../define/db/service/SoftWare/mjSettingService";
|
2024-06-01 15:08:22 +08:00
|
|
|
|
const { v4: uuidv4 } = require('uuid');
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* MJ原创生图的类
|
|
|
|
|
|
*/
|
|
|
|
|
|
export class MJOriginalImageGenerate {
|
|
|
|
|
|
constructor(global) {
|
|
|
|
|
|
this.global = global;
|
|
|
|
|
|
this.pm = new PublicMethod(global);
|
|
|
|
|
|
this.discordWorker = new DiscordWorker();
|
|
|
|
|
|
this.tools = new Tools();
|
2024-06-01 15:08:22 +08:00
|
|
|
|
this.discordAPI = new DiscordAPI();
|
|
|
|
|
|
this.gpt = new GPT(global);
|
2024-06-13 00:37:31 +08:00
|
|
|
|
this.tagDefine = new TagDefine(global);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 返回指定的人物到前端
|
|
|
|
|
|
* @param {*} data
|
|
|
|
|
|
*/
|
2024-06-13 00:37:31 +08:00
|
|
|
|
sendChangeMessage(data, message_name = DEFINE_STRING.DISCORD.MAIN_DISCORD_MESSAGE_CHANGE) {
|
|
|
|
|
|
this.global.newWindow[0].win.webContents.send(message_name, data);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-13 00:37:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 通过文本自动匹配数据
|
|
|
|
|
|
* @param {*} value
|
|
|
|
|
|
*/
|
|
|
|
|
|
async AutoMatchUser(value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
value = JSON.parse(value);
|
|
|
|
|
|
// 获取所有的角色数据,包括别名
|
|
|
|
|
|
// 获取所有的角色数据
|
|
|
|
|
|
let character_tags = await this.tagDefine.getTagDataByTypeAndProperty("dynamic", "character_tags");
|
|
|
|
|
|
if (character_tags.code == 0) {
|
|
|
|
|
|
return errorMessage("获取角色数据错误,错误信息如下:" + character_tags.message, LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
|
|
|
|
|
|
}
|
|
|
|
|
|
character_tags = character_tags.data;
|
|
|
|
|
|
if (character_tags.length == 0) {
|
|
|
|
|
|
return errorMessage("请先添加角色数据", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
|
|
|
|
|
|
}
|
|
|
|
|
|
let character_tags_data = [];
|
|
|
|
|
|
for (let i = 0; i < character_tags.length; i++) {
|
|
|
|
|
|
let item = character_tags[i];
|
|
|
|
|
|
// 这边还要判断是不是显示(只有显示的才hi自动匹配)
|
|
|
|
|
|
if (!item.hasOwnProperty("isShow") || !item.isShow) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let temp_name = [item.label];
|
|
|
|
|
|
// 判断当前的数是不是存在别名
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
for (let j = 0; j < item.children.length; j++) {
|
|
|
|
|
|
const element = item.children[j];
|
|
|
|
|
|
temp_name.push(element.label);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
character_tags_data.push({
|
|
|
|
|
|
key: item.key,
|
|
|
|
|
|
value: item.value,
|
|
|
|
|
|
names: temp_name
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
if (character_tags_data.length == 0) {
|
|
|
|
|
|
return errorMessage("当前没有显示的角色数据,请先选择哪些是要显示的角色数据", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
|
|
|
|
const element = value[i];
|
|
|
|
|
|
|
|
|
|
|
|
let res_data = {
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
id: element.id, // 当前 data 的ID
|
|
|
|
|
|
match_character: [],
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前的字幕数据
|
|
|
|
|
|
let temp_sub = [];
|
|
|
|
|
|
for (let j = 0; element.suValue && j < element.suValue.length; j++) {
|
|
|
|
|
|
const element = array[j];
|
|
|
|
|
|
temp_sub.push(element.srt_value);
|
|
|
|
|
|
}
|
|
|
|
|
|
let word = "";
|
|
|
|
|
|
if (temp_sub.length == 0) {
|
|
|
|
|
|
word = element.after_gpt;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
word = temp_sub.join(",");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let match_keys = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 开始循环判断,只要又一个满足就跳出新婚换
|
|
|
|
|
|
for (let j = 0; j < character_tags_data.length; j++) {
|
|
|
|
|
|
const item = character_tags_data[j];
|
|
|
|
|
|
let names = AwesomeHelp.makeSensitiveMap(item.names);
|
|
|
|
|
|
// 开始判断
|
|
|
|
|
|
let name_res = AwesomeHelp.checkSensitiveWord(word, false, names);
|
|
|
|
|
|
if (name_res.size > 0) {
|
|
|
|
|
|
match_keys.push(item.key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断是不是又匹配到的数据
|
|
|
|
|
|
if (match_keys.length > 0) {
|
|
|
|
|
|
// 进行数据的处理,通过对应的key,获取对应的数据,将所有的数进行返回
|
|
|
|
|
|
for (let i = 0; i < match_keys.length; i++) {
|
|
|
|
|
|
const item = match_keys[i];
|
|
|
|
|
|
let index = character_tags.findIndex(x => x.key == item);
|
|
|
|
|
|
if (index == -1) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
let temp_item_data = cloneDeep(character_tags[index]);
|
|
|
|
|
|
if (temp_item_data.children) {
|
|
|
|
|
|
delete temp_item_data.children
|
|
|
|
|
|
}
|
|
|
|
|
|
res_data.match_character.push(temp_item_data)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开始往前端传递数据
|
|
|
|
|
|
this.sendChangeMessage(res_data, DEFINE_STRING.MJ.MACTH_USER_RETURN);
|
|
|
|
|
|
}
|
|
|
|
|
|
return successMessage(null, "人物标签自动匹配完成", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("通过文本自动匹配数据错误,错误信息如下:" + error.message, LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-06-01 15:08:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 初始化MJ设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async InitMjSetting() {
|
|
|
|
|
|
let mjSetting_res = await ImageSetting.GetDefineConfigJsonByProperty(JSON.stringify(['img_base', 'mj_config', false, null]));
|
|
|
|
|
|
if (mjSetting_res.code == 0 || !mjSetting_res.data) {
|
|
|
|
|
|
throw new Error("请先添加MJ配置")
|
|
|
|
|
|
}
|
|
|
|
|
|
let mjSetting = mjSetting_res.data;
|
|
|
|
|
|
return mjSetting;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化MJ API的URL
|
|
|
|
|
|
*/
|
|
|
|
|
|
async InitMJAPIUrl(id) {
|
|
|
|
|
|
let mj_api = (await this.gpt.GetGPTBusinessOption("all", (value) => value.mj_url)).data;
|
|
|
|
|
|
let mj_api_url_index = mj_api.findIndex(item => item.value == id);
|
|
|
|
|
|
if (mj_api_url_index == -1) {
|
|
|
|
|
|
throw new Error("没有找到对应的MJ API的配置,请先检查配置")
|
|
|
|
|
|
}
|
|
|
|
|
|
return mj_api[mj_api_url_index];
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 下载指定的图片地址并且分割
|
|
|
|
|
|
* @param {*} value
|
|
|
|
|
|
*/
|
|
|
|
|
|
async DownloadImageUrlAndSplit(value) {
|
|
|
|
|
|
try {
|
2024-06-01 15:08:22 +08:00
|
|
|
|
console.log(value)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
value = JSON.parse(value);
|
|
|
|
|
|
let element = value[0];
|
|
|
|
|
|
let iamge_url = value[1];
|
|
|
|
|
|
let image_path = "";
|
|
|
|
|
|
if (value.length > 2) {
|
|
|
|
|
|
image_path = value[2];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
image_path = path.join(global.config.project_path, `data\\MJOriginalImage\\${element.id}.png`);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 判断是不是一个链接
|
|
|
|
|
|
const urlRegex = /^(http|https):\/\/[^ "]+$/;
|
|
|
|
|
|
if (!urlRegex.test(iamge_url)) {
|
|
|
|
|
|
throw new Error("指定的图片地址不是一个链接");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 这边开始下载对应的图片
|
|
|
|
|
|
await this.tools.downloadFileUrl(iamge_url, image_path);
|
|
|
|
|
|
|
|
|
|
|
|
// 将下载的图片进行分割
|
|
|
|
|
|
let split_res = await this.ImageSplit(JSON.stringify([image_path, element.name]));
|
|
|
|
|
|
if (split_res.code == 0) {
|
|
|
|
|
|
throw new Error(split_res.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
element.image_click = iamge_url;
|
|
|
|
|
|
element.subImagePath = split_res.data.subImagePath;
|
|
|
|
|
|
element.outImagePath = split_res.data.outImagePath;
|
|
|
|
|
|
element['image_path'] = image_path
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
data: element
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: "下载指定的图片地址并且分割错误,错误信息如下:" + error.message
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取已经生图完成的数据,并获取图片
|
|
|
|
|
|
* @param {*} value
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
|
|
|
|
|
async GetGeneratedMJImageAndSplit(value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
value = JSON.parse(value);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let mjSetting = await this.InitMjSetting();
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let request_model = mjSetting.requestModel;
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let result = [];
|
|
|
|
|
|
// 浏览器生图模式
|
|
|
|
|
|
if (request_model == "browser_mj") {
|
|
|
|
|
|
let param = [];
|
|
|
|
|
|
// 循环数据,直传需要的数据
|
|
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
|
|
|
|
const element = value[i];
|
|
|
|
|
|
// 一般进度大于 50 会出现图片,
|
|
|
|
|
|
if (!element.mj_message) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (element.mj_message.progress && element.mj_message.progress == 100) {
|
|
|
|
|
|
// 判断 image_path 是不是存在。
|
|
|
|
|
|
if (item.mj_message.image_id && !element.mj_message.image_path) {
|
|
|
|
|
|
// 通过当前的image_id获取图片
|
|
|
|
|
|
param.push({
|
|
|
|
|
|
id: element.id,
|
|
|
|
|
|
image_id: element.mj_message.image_id,
|
|
|
|
|
|
name: element.name,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断窗口是不是开启
|
|
|
|
|
|
let discordWin = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad();
|
|
|
|
|
|
// 执行采集图片的脚本
|
|
|
|
|
|
// 开始写入
|
|
|
|
|
|
let discordSimple = new DiscordSimple(discordWin);
|
|
|
|
|
|
// 开始执行脚本
|
|
|
|
|
|
result = await discordSimple.ExecuteScript(define.discordScript, `GetGeneratedMJImageAndSplit(${JSON.stringify(param)})`);
|
|
|
|
|
|
|
|
|
|
|
|
} else if (request_model == "api_mj") {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let mj_api = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let once_get_task = mj_api.mj_url.once_get_task;
|
|
|
|
|
|
|
|
|
|
|
|
// 请求
|
|
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
|
|
|
|
const element = value[i];
|
|
|
|
|
|
if (element.mj_message.progress == 100) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if (element.mj_message.progress.status == "success") {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let task_res = await this.discordAPI.GetMJAPITaskByID(element.mj_message.message_id, once_get_task, mjSetting.apiSetting.apiKey);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
if (task_res.code == 0) {
|
|
|
|
|
|
task_res["id"] = element.id;
|
2024-06-24 13:11:19 +08:00
|
|
|
|
task_res["mj_api_url"] = mjSetting.apiSetting.mjApiUrl;
|
2024-06-01 15:08:22 +08:00
|
|
|
|
this.sendChangeMessage()
|
|
|
|
|
|
}
|
|
|
|
|
|
// 判断进度是不是百分百
|
|
|
|
|
|
if (task_res.progress != 100) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result.push({
|
|
|
|
|
|
id: element.id,
|
|
|
|
|
|
image_id: null,
|
|
|
|
|
|
result: task_res.image_click,
|
|
|
|
|
|
name: element.name
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
let res = [];
|
2024-06-01 15:08:22 +08:00
|
|
|
|
// 判断返回的数据是不是一个字符串
|
|
|
|
|
|
if (typeof result == "string") {
|
|
|
|
|
|
result = JSON.parse(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-15 12:57:15 +08:00
|
|
|
|
// 将返回的数据进行分割
|
|
|
|
|
|
for (let i = 0; i < result.length; i++) {
|
|
|
|
|
|
const element = result[i];
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let image_path = path.join(global.config.project_path, `data\\MJOriginalImage\\${uuidv4()}.png`);
|
|
|
|
|
|
let ds = await this.DownloadImageUrlAndSplit(JSON.stringify([element, element.result, image_path]));
|
2024-05-15 12:57:15 +08:00
|
|
|
|
if (ds.code == 0) {
|
|
|
|
|
|
throw new Error(ds.message);
|
|
|
|
|
|
}
|
2024-06-01 15:08:22 +08:00
|
|
|
|
// 修改数据。
|
|
|
|
|
|
ds.data["progress"] = 100;
|
|
|
|
|
|
ds.data["status"] = "success";
|
2024-05-15 12:57:15 +08:00
|
|
|
|
res.push(ds.data);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 全部分割完毕,返回
|
2024-06-01 15:08:22 +08:00
|
|
|
|
return successMessage(res);
|
2024-05-15 12:57:15 +08:00
|
|
|
|
} catch (error) {
|
2024-06-01 15:08:22 +08:00
|
|
|
|
return errorMessage("获取已经生图完成的数据,并获取图片错误,错误信息如下" + error.message)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MJ生成的图片分割
|
|
|
|
|
|
async ImageSplit(value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
value = JSON.parse(value);
|
|
|
|
|
|
let inputPath = value[0];
|
|
|
|
|
|
let r_name = value[1];
|
|
|
|
|
|
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`);
|
|
|
|
|
|
const metadata = await sharp(inputPath).metadata();
|
|
|
|
|
|
const smallWidth = metadata.width / 2;
|
|
|
|
|
|
const smallHeight = metadata.height / 2;
|
|
|
|
|
|
let times = new Date().getTime();
|
|
|
|
|
|
let imgs = [];
|
|
|
|
|
|
let first_p = path.join(this.global.config.project_path, `tmp\\output_crop_00001\\${r_name}`);
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 4; i++) {
|
|
|
|
|
|
const xOffset = i % 2 === 0 ? 0 : smallWidth;
|
|
|
|
|
|
const yOffset = Math.floor(i / 2) * smallHeight;
|
|
|
|
|
|
let out_file = path.join(outputDir, `/${r_name}_${times}_${i}.png`);
|
|
|
|
|
|
await sharp(inputPath)
|
|
|
|
|
|
.extract({
|
|
|
|
|
|
left: xOffset,
|
|
|
|
|
|
top: yOffset,
|
|
|
|
|
|
width: smallWidth,
|
|
|
|
|
|
height: smallHeight
|
|
|
|
|
|
})
|
|
|
|
|
|
.resize(smallWidth, smallHeight)
|
|
|
|
|
|
.toFile(out_file);
|
|
|
|
|
|
|
|
|
|
|
|
imgs.push(out_file);
|
|
|
|
|
|
|
|
|
|
|
|
// 将第一个图片复制一个到指定的位置
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
|
await this.tools.copyFileOrDirectory(out_file, first_p);
|
|
|
|
|
|
// 复制一份到input
|
|
|
|
|
|
let input_p = path.join(this.global.config.project_path, `tmp\\input_crop\\${r_name}`);
|
|
|
|
|
|
await this.tools.copyFileOrDirectory(out_file, input_p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
subImagePath: imgs,
|
|
|
|
|
|
outImagePath: first_p
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: "MJ图片切割错误,错误信息如下" + err.message
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-01 15:08:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 调用API生图的方法
|
|
|
|
|
|
* @param {*} element
|
|
|
|
|
|
* @param {*} mjSetting
|
|
|
|
|
|
*/
|
2024-06-24 13:11:19 +08:00
|
|
|
|
async MJImagineRequest(element, mjSetting, prompt, tasK_id = null, batch = null) {
|
2024-06-01 15:08:22 +08:00
|
|
|
|
try {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
if (mjSetting.apiSetting == null) {
|
|
|
|
|
|
throw new Error("没有API设置,请先设置API设置");
|
|
|
|
|
|
}
|
|
|
|
|
|
let apiUrl;
|
|
|
|
|
|
if (mjSetting.requestModel == MJImageType.API_MJ) {
|
|
|
|
|
|
// 获取当前的API url
|
|
|
|
|
|
apiUrl = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl);
|
|
|
|
|
|
} else if (mjSetting.requestModel == MJImageType.REMOTE_MJ) {
|
|
|
|
|
|
apiUrl = {
|
|
|
|
|
|
mj_url: {
|
|
|
|
|
|
imagine: define.remotemj_api + 'mj/submit/imagine',
|
|
|
|
|
|
once_get_task: define.remotemj_api + "mj/task/${id}/fetch"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error("未知的生图模式,请检查配置")
|
|
|
|
|
|
}
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let imagine_url = apiUrl.mj_url.imagine;
|
|
|
|
|
|
let once_get_task = apiUrl.mj_url.once_get_task;
|
2024-06-24 13:11:19 +08:00
|
|
|
|
|
|
|
|
|
|
let task_count = mjSetting.taskCount ? mjSetting.taskCount : 3;
|
|
|
|
|
|
let mj_speed = mjSetting.apiSetting.mjSpeed ? mjSetting.apiSetting.mjSpeed : "relaxed";
|
2024-06-01 15:08:22 +08:00
|
|
|
|
let res;
|
|
|
|
|
|
// 判断当前的API是哪个
|
|
|
|
|
|
if (imagine_url.includes("mjapi.deepwl.net")) {
|
|
|
|
|
|
// DrawAPI(MJ)
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
prompt: prompt,
|
2024-06-08 16:56:04 +08:00
|
|
|
|
mode: mj_speed == "fast" ? "FAST" : "RELAX",
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
let headers = {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
"Authorization": mjSetting.apiSetting.apiKey
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
|
2024-06-13 00:37:31 +08:00
|
|
|
|
|
|
|
|
|
|
if (res.code == 24) {
|
|
|
|
|
|
throw new Error("提示词包含敏感词,请修改后重试");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-01 15:08:22 +08:00
|
|
|
|
} else if (imagine_url.includes("api.ephone.ai")) {
|
|
|
|
|
|
// ePhoneAPI
|
|
|
|
|
|
let headers = {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
"Authorization": mjSetting.apiSetting.apiKey
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
prompt: prompt,
|
|
|
|
|
|
botType: "MID_JOURNEY",
|
|
|
|
|
|
accountFilter: {
|
|
|
|
|
|
modes: [
|
2024-06-08 16:56:04 +08:00
|
|
|
|
mj_speed == "fast" ? "FAST" : "RELAX"
|
2024-06-01 15:08:22 +08:00
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
|
2024-06-24 13:11:19 +08:00
|
|
|
|
} else if (imagine_url.includes(define.remotemj_api)) {
|
|
|
|
|
|
// 代理模式
|
|
|
|
|
|
let headers = {
|
|
|
|
|
|
"mj-api-secret": define.API
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断数据是不是存在
|
|
|
|
|
|
if (!mjSetting.remoteSetting.channelId) {
|
|
|
|
|
|
throw new Error("请先设置channelId")
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!mjSetting.remoteSetting.accountId) {
|
|
|
|
|
|
throw new Error("请先同步账号")
|
|
|
|
|
|
}
|
|
|
|
|
|
let data = {
|
|
|
|
|
|
prompt: prompt,
|
|
|
|
|
|
botType: "MID_JOURNEY",
|
|
|
|
|
|
accountFilter: {
|
|
|
|
|
|
channelId: mjSetting.remoteSetting.channelId,
|
|
|
|
|
|
instanceId: mjSetting.remoteSetting.accountId,
|
|
|
|
|
|
remark: this.global.machineId,
|
|
|
|
|
|
modes: [
|
|
|
|
|
|
mj_speed == "fast" ? "FAST" : "RELAX"
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}
|
2024-06-13 00:37:31 +08:00
|
|
|
|
|
2024-06-24 13:11:19 +08:00
|
|
|
|
this.global.mjGenerateQuene.setCurrentCreateItem(null);
|
2024-06-13 00:37:31 +08:00
|
|
|
|
// 错误检查
|
|
|
|
|
|
if (res.code == 23) {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
// 任务队列已满,及结束该任务,然后开始下一个任务,并将该任务重新排序
|
|
|
|
|
|
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
|
|
|
|
|
|
return taskProgress.filter(item => item?.id != element.id)
|
|
|
|
|
|
});
|
|
|
|
|
|
this.sendChangeMessage({
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
status: "error",
|
|
|
|
|
|
message: "任务队列已满,任务结束会重新排序,并等待3分钟,开始后面的任务",
|
|
|
|
|
|
id: element.id
|
|
|
|
|
|
})
|
|
|
|
|
|
await this.tools.delay(40000);
|
|
|
|
|
|
// 重新将当前任务加入队列
|
|
|
|
|
|
this.global.mjGenerateQuene.enqueue(async () => {
|
|
|
|
|
|
this.global.mjGenerateQuene.setCurrentCreateItem(element)
|
|
|
|
|
|
await this.MJImagineRequest(element, mjSetting, prompt)
|
|
|
|
|
|
}, tasK_id, batch)
|
|
|
|
|
|
|
|
|
|
|
|
this.global.mjGenerateQuene.startNextTask(task_count);
|
|
|
|
|
|
return;
|
2024-06-13 00:37:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (res.code != 1 && res.code != 22) {
|
2024-06-24 13:11:19 +08:00
|
|
|
|
// 未知错误,将当前任务删除,开始下一个任务
|
|
|
|
|
|
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
|
|
|
|
|
|
return taskProgress.filter(item => item?.id != element.id)
|
|
|
|
|
|
});
|
|
|
|
|
|
this.global.mjGenerateQuene.startNextTask(task_count);
|
|
|
|
|
|
this.sendChangeMessage({
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
status: "error",
|
|
|
|
|
|
message: "未知错误,可联系管理员排查," + res.description,
|
|
|
|
|
|
id: element.id
|
|
|
|
|
|
})
|
|
|
|
|
|
return;
|
2024-06-13 00:37:31 +08:00
|
|
|
|
}
|
2024-06-01 15:08:22 +08:00
|
|
|
|
// 创建成功,开始下一个
|
|
|
|
|
|
this.sendChangeMessage({
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
type: "created",
|
|
|
|
|
|
category: "api_mj",
|
|
|
|
|
|
message_id: res.result,
|
|
|
|
|
|
image_click: null,
|
|
|
|
|
|
image_show: null,
|
|
|
|
|
|
id: element.id,
|
|
|
|
|
|
progress: 0,
|
2024-06-24 13:11:19 +08:00
|
|
|
|
mj_api_url: mjSetting.apiSetting.mjApiUrl
|
2024-06-01 15:08:22 +08:00
|
|
|
|
});
|
|
|
|
|
|
// 开始监听当前ID是不是的生图任务完成
|
|
|
|
|
|
// 这边设置一个循环监听,每隔一段时间去请求一次
|
|
|
|
|
|
let timeoutId;
|
|
|
|
|
|
let startInterval = () => {
|
|
|
|
|
|
timeoutId = setTimeout(async () => {
|
|
|
|
|
|
// 执行你的操作
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let task_res = await this.discordAPI.GetMJAPITaskByID(res.result, once_get_task, mjSetting.apiSetting.apiKey)
|
2024-06-01 15:08:22 +08:00
|
|
|
|
console.log(task_res)
|
|
|
|
|
|
// 判断他的状态是不是成功
|
|
|
|
|
|
if (task_res.code == 0) {
|
|
|
|
|
|
// 将但钱任务删除
|
|
|
|
|
|
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
|
|
|
|
|
|
return taskProgress.filter(item => item?.id != element.id)
|
|
|
|
|
|
});
|
|
|
|
|
|
// 停止当前循环
|
|
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (task_res.progress == 100) {
|
|
|
|
|
|
// 将但钱任务删除
|
|
|
|
|
|
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
|
|
|
|
|
|
return taskProgress.filter(item => item?.id != element.id)
|
|
|
|
|
|
});
|
|
|
|
|
|
task_res.type = "finished";
|
|
|
|
|
|
// 下载对应的图片
|
|
|
|
|
|
let image_path = path.join(this.global.config.project_path, `data\\MJOriginalImage\\${task_res.message_id}.png`);
|
|
|
|
|
|
// 这边开始下载对应的图片
|
|
|
|
|
|
await this.tools.downloadFileUrl(task_res.image_click, image_path);
|
|
|
|
|
|
task_res["image_path"] = image_path;
|
|
|
|
|
|
// 开始下一个任务
|
|
|
|
|
|
this.global.mjGenerateQuene.startNextTask(task_count);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 当获取的图片的进度小于100的时候,继续监听
|
|
|
|
|
|
startInterval();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
task_res['id'] = element.id;
|
2024-06-24 13:11:19 +08:00
|
|
|
|
task_res["mj_api_url"] = mjSetting.apiSetting.mjApiUrl;
|
2024-06-01 15:08:22 +08:00
|
|
|
|
this.sendChangeMessage(task_res);
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
}
|
|
|
|
|
|
startInterval();
|
|
|
|
|
|
this.global.mjGenerateQuene.startNextTask(task_count);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
this.sendChangeMessage({
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
status: "error",
|
|
|
|
|
|
message: error.message,
|
|
|
|
|
|
id: element.id
|
|
|
|
|
|
})
|
|
|
|
|
|
throw new Error("MJ API 出图错误,错误信息如下:" + error.message)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-15 12:57:15 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* MJ 原创生图
|
|
|
|
|
|
* @param {*} value
|
|
|
|
|
|
*/
|
|
|
|
|
|
async OriginalMJImageGenerate(value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let data = value[0];
|
|
|
|
|
|
if (value[1]) {
|
|
|
|
|
|
data = JSON.parse(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
let show_global_message = value[2];
|
|
|
|
|
|
let batch = DEFINE_STRING.QUEUE_BATCH.MJ_ORIGINAL_GENERATE_IMAGE;
|
|
|
|
|
|
|
|
|
|
|
|
// 判断存放的文件夹是不是存在,不存在的话创建
|
|
|
|
|
|
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`);
|
|
|
|
|
|
await this.tools.checkFolderExistsOrCreate(outputDir);
|
|
|
|
|
|
let fileExist = await this.tools.checkExists(outputDir);
|
|
|
|
|
|
if (!fileExist) {
|
|
|
|
|
|
await this.tools.createDirectory(outputDir);
|
|
|
|
|
|
}
|
2024-05-24 13:46:19 +08:00
|
|
|
|
// 判断该当前tmp\output_crop_00001文件夹是不是存在,不存在创建
|
|
|
|
|
|
let output_crop_00001 = path.join(this.global.config.project_path, `tmp\\output_crop_00001`);
|
|
|
|
|
|
await this.tools.checkFolderExistsOrCreate(output_crop_00001);
|
|
|
|
|
|
|
2024-06-24 13:11:19 +08:00
|
|
|
|
// 获取MJ配置,从数据库中
|
|
|
|
|
|
let _mjSettingService = await MJSettingService.getInstance()
|
|
|
|
|
|
let mjSettings = _mjSettingService.GetMJSettingTreeData();
|
|
|
|
|
|
if (mjSettings.code == 0) {
|
|
|
|
|
|
throw new Error(mjSettings.message)
|
|
|
|
|
|
}
|
|
|
|
|
|
let mjSetting = mjSettings.data;
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查this.global中是不是又mj队列,没有的话创建一个
|
|
|
|
|
|
if (!this.global.mjGenerateQuene) {
|
|
|
|
|
|
this.global.mjGenerateQuene = new AsyncQueue(this.global, 1, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 替换风格的逻辑
|
|
|
|
|
|
let current_task = null;
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
|
|
const element = data[i];
|
|
|
|
|
|
let tasK_id = `${batch}_${element.name}_${element.id}`;
|
|
|
|
|
|
|
2024-05-24 13:46:19 +08:00
|
|
|
|
let old_prompt = element.prompt;
|
|
|
|
|
|
// 拼接提示词
|
|
|
|
|
|
// 图生图的链接
|
2024-06-01 15:08:22 +08:00
|
|
|
|
// 获取风格词 + 命令后缀
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let prompt = old_prompt + (mjSetting.imageSuffix ? mjSetting.imageSuffix : "");
|
2024-06-01 15:08:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 判断当前生图模式
|
2024-06-24 13:11:19 +08:00
|
|
|
|
let request_model = mjSetting.requestModel
|
2024-06-01 15:08:22 +08:00
|
|
|
|
switch (request_model) {
|
|
|
|
|
|
case "api_mj":
|
|
|
|
|
|
this.global.mjGenerateQuene.enqueue(async () => {
|
|
|
|
|
|
this.global.mjGenerateQuene.setCurrentCreateItem(element)
|
2024-06-24 13:11:19 +08:00
|
|
|
|
await this.MJImagineRequest(element, mjSetting, prompt, tasK_id, batch)
|
|
|
|
|
|
}, tasK_id, batch)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MJImageType.REMOTE_MJ:
|
|
|
|
|
|
this.global.mjGenerateQuene.enqueue(async () => {
|
|
|
|
|
|
this.global.mjGenerateQuene.setCurrentCreateItem(element)
|
|
|
|
|
|
await this.MJImagineRequest(element, mjSetting, prompt, tasK_id, batch)
|
2024-06-01 15:08:22 +08:00
|
|
|
|
}, tasK_id, batch)
|
|
|
|
|
|
break;
|
2024-06-24 13:11:19 +08:00
|
|
|
|
|
2024-06-01 15:08:22 +08:00
|
|
|
|
case "browser_mj":
|
|
|
|
|
|
this.global.mjGenerateQuene.enqueue(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.global.mjGenerateQuene.setCurrentCreateItem(element)
|
|
|
|
|
|
// 开始进行mj生图
|
|
|
|
|
|
current_task = element.name;
|
|
|
|
|
|
// 判断窗口是不是开启
|
|
|
|
|
|
let discordW = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad();
|
|
|
|
|
|
// 开始写入
|
|
|
|
|
|
let discordSimple = new DiscordSimple(discordW, mjSetting);
|
|
|
|
|
|
await discordSimple.WritePromptToInput(prompt);
|
|
|
|
|
|
// 发送命令完成(删除当前正在执行。开始下一个任务)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, tasK_id, batch);
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断该当前正在执行的人物队列数(小于设置的数量,开始一个任务)
|
2024-06-24 13:11:19 +08:00
|
|
|
|
this.global.mjGenerateQuene.startNextTask(mjSetting.taskCount ? mjSetting.taskCount : 3);
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
this.global.requestQuene.setBatchCompletionCallback(batch, (failedTasks) => {
|
|
|
|
|
|
if (failedTasks.length > 0) {
|
|
|
|
|
|
let message = `
|
|
|
|
|
|
MJ生图任务都已完成。
|
|
|
|
|
|
但是以下任务执行失败:
|
|
|
|
|
|
`
|
|
|
|
|
|
failedTasks.forEach(({ taskId, error }) => {
|
|
|
|
|
|
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2024-06-01 15:08:22 +08:00
|
|
|
|
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, errorMessage(message))
|
2024-05-15 12:57:15 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
if (show_global_message) {
|
2024-06-01 15:08:22 +08:00
|
|
|
|
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, successMessage(null, '所有MJ生图任务完成'))
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-06-01 15:08:22 +08:00
|
|
|
|
return successMessage(null)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
} catch (error) {
|
2024-06-01 15:08:22 +08:00
|
|
|
|
return errorMessage("MJ生图错误,错误信息如下" + error.message)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|