This commit is contained in:
vastxie
2024-02-04 21:06:59 +08:00
parent 4aaa8d05f7
commit 435fc44522
180 changed files with 790 additions and 1476 deletions

View File

@@ -1,93 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendMessageFromBaidu = exports.getAccessToken = void 0;
const axios = require('axios');
const getApiModelMaps = () => {
let res = {};
const maps = {
'ERNIE-Bot': 'completions',
'ERNIE-Bot-turbo': 'eb-instant',
'BLOOMZ-7B': 'bloomz_7b1',
'ERNIE-Bot-4': 'completions_pro',
'Llama-2-7b-chat': 'llama_2_7b',
'Llama-2-13b-chat': 'llama_2_13b',
'ChatGLM2-6B-32K': 'chatglm2_6b_32k',
'Qianfan-Chinese-Llama-2-7B': 'qianfan_chinese_llama_2_7b',
};
Object.keys(maps).map(key => {
res[`${key.toLowerCase()}`] = maps[key];
});
return res;
};
function getAccessToken(key, secret) {
let url = `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${key}&client_secret=${secret}`;
return new Promise((resolve, reject) => {
axios
.post(url)
.then((response) => {
resolve(response.data.access_token);
})
.catch((error) => {
reject(error);
});
});
}
exports.getAccessToken = getAccessToken;
function sendMessageFromBaidu(messagesHistory, { onProgress, accessToken, model, temperature = 0.95 }) {
const endUrl = getApiModelMaps()[model.trim().toLowerCase()];
return new Promise((resolve, reject) => {
const url = `https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/${endUrl}?access_token=${accessToken}`;
var options = {
method: 'POST',
url,
responseType: 'stream',
headers: {
'Content-Type': 'application/json',
},
data: {
stream: true,
messages: messagesHistory,
},
};
axios(options)
.then((response) => {
const stream = response.data;
let resData = {};
let cacheChunk = '';
let cacheResText = '';
stream.on('data', (chunk) => {
const lines = chunk
.toString()
.split('\n\n')
.filter((line) => line.trim() !== '');
for (const line of lines) {
const message = line.replace('data: ', '');
try {
const msg = cacheChunk + message;
const parseData = JSON.parse(msg);
cacheChunk = '';
const { is_end, result } = parseData;
result && (cacheResText += result);
if (is_end) {
resData = parseData;
resData.text = cacheResText;
}
onProgress(parseData);
}
catch (error) {
cacheChunk = message;
}
}
});
stream.on('end', () => {
cacheResText = '';
cacheChunk = '';
resolve(resData);
});
})
.catch((error) => {
reject(new Error(error));
});
});
}
exports.sendMessageFromBaidu = sendMessageFromBaidu;

View File

@@ -21,7 +21,7 @@ const chatLog_service_1 = require("../chatLog/chatLog.service");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const accountLog_entity_1 = require("../userBalance/accountLog.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const gptkeys_entity_1 = require("./gptkeys.entity");
const gptKeys_entity_1 = require("./gptKeys.entity");
const whiteList_entity_1 = require("./whiteList.entity");
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
@@ -48,7 +48,7 @@ ChatgptModule = __decorate([
chatLog_entity_1.ChatLogEntity,
accountLog_entity_1.AccountLogEntity,
config_entity_1.ConfigEntity,
gptkeys_entity_1.GptKeysEntity,
gptKeys_entity_1.GptKeysEntity,
whiteList_entity_1.WhiteListEntity,
user_entity_1.UserEntity,
cramiPackage_entity_1.CramiPackageEntity,

View File

@@ -29,7 +29,7 @@ const typeorm_1 = require("typeorm");
const typeorm_2 = require("@nestjs/typeorm");
const badwords_service_1 = require("../badwords/badwords.service");
const autoreply_service_1 = require("../autoreply/autoreply.service");
const gptkeys_entity_1 = require("./gptkeys.entity");
const gptKeys_entity_1 = require("./gptKeys.entity");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
const fanyi_service_1 = require("../fanyi/fanyi.service");
const app_entity_1 = require("../app/app.entity");
@@ -127,7 +127,7 @@ let ChatgptService = class ChatgptService {
}
}
async chatProcess(body, req, res) {
var _a, _b, _c;
var _a, _b, _c, _d;
const abortController = req.abortController;
const { options = {}, appId, cusromPrompt, systemMessage = '' } = body;
let setSystemMessage = systemMessage;
@@ -184,7 +184,6 @@ let ChatgptService = class ChatgptService {
setSystemMessage = systemPreMessage + `\n Current date: ${currentDate}`;
}
const mergedOptions = await this.getRequestParams(options, setSystemMessage, currentRequestModelKey, groupConfig.modelInfo);
const { maxModelTokens = 8000, maxResponseTokens = 4096, key } = currentRequestModelKey;
res && res.status(200);
let response = null;
let othersInfo = null;
@@ -270,6 +269,7 @@ let ChatgptService = class ChatgptService {
maxTokenRes,
apiKey: modelKey,
model,
prompt,
fileInfo,
temperature,
proxyUrl: proxyResUrl,
@@ -277,8 +277,8 @@ let ChatgptService = class ChatgptService {
res.write(firstChunk ? JSON.stringify(chat) : `\n${JSON.stringify(chat)}`);
lastChat = chat;
firstChunk = false;
},
});
}
}, this.uploadService);
isSuccess = true;
const userMessageData = {
id: this.nineStore.getUuid(),
@@ -297,7 +297,8 @@ let ChatgptService = class ChatgptService {
text: response.text,
role: 'assistant',
name: undefined,
usage: response.usage,
usage: response === null || response === void 0 ? void 0 : response.usage,
fileInfo: response === null || response === void 0 ? void 0 : response.fileInfo,
parentMessageId: userMessageData.id,
conversationId: response === null || response === void 0 ? void 0 : response.conversationId,
};
@@ -319,10 +320,11 @@ let ChatgptService = class ChatgptService {
temperature,
proxyUrl: proxyResUrl,
onProgress: null,
prompt,
});
}
let { usage } = response === null || response === void 0 ? void 0 : response.detail;
const { prompt_tokens = 0, completion_tokens = 0, total_tokens = 0 } = usage;
const usage = ((_a = response.detail) === null || _a === void 0 ? void 0 : _a.usage) || { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 };
const { prompt_tokens, completion_tokens, total_tokens } = usage;
let charge = deduct;
if (isTokenBased === true) {
charge = Math.ceil((deduct * total_tokens) / tokenFeeRatio);
@@ -355,6 +357,7 @@ let ChatgptService = class ChatgptService {
userId: req.user.id,
type: balance_constant_1.DeductionKey.CHAT_TYPE,
prompt: prompt,
fileInfo: response === null || response === void 0 ? void 0 : response.fileInfo,
answer: response.text,
promptTokens: prompt_tokens,
completionTokens: completion_tokens,
@@ -376,7 +379,7 @@ let ChatgptService = class ChatgptService {
temperature,
}),
});
common_1.Logger.debug(`本次调用: ${req.user.id} model: ${model} key -> ${key}, 模型名称: ${modelName}, 最大回复token: ${maxResponseTokens}`, 'ChatgptService');
common_1.Logger.debug(`户ID: ${req.user.id} 模型名称: ${modelName}-${model}, 消耗token: ${total_tokens}, 消耗积分: ${charge}`, 'ChatgptService');
const userBalance = await this.userBalanceService.queryUserBalance(req.user.id);
response.userBanance = Object.assign({}, userBalance);
response.result && (response.result = '');
@@ -391,8 +394,8 @@ let ChatgptService = class ChatgptService {
catch (error) {
console.log('chat-error <----------------------------------------->', modelKey, error);
const code = (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
const status = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) || (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
console.log('chat-error-detail <----------------------------------------->', 'code: ', code, 'message', error === null || error === void 0 ? void 0 : error.message, 'statusText:', (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.statusText, 'status', (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.status);
const status = ((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.status) || (error === null || error === void 0 ? void 0 : error.statusCode) || 400;
console.log('chat-error-detail <----------------------------------------->', 'code: ', code, 'message', error === null || error === void 0 ? void 0 : error.message, 'statusText:', (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.statusText, 'status', (_d = error === null || error === void 0 ? void 0 : error.response) === null || _d === void 0 ? void 0 : _d.status);
if (error.status && error.status === 402) {
const errMsg = { message: `Catch Error ${error.message}`, code: 402 };
if (res) {
@@ -452,7 +455,7 @@ let ChatgptService = class ChatgptService {
const money = (body === null || body === void 0 ? void 0 : body.quality) === 'hd' ? 4 : 2;
await this.userBalanceService.validateBalance(req, 'mjDraw', money);
let images = [];
const detailKeyInfo = await this.modelsService.getRandomDrawKey();
const detailKeyInfo = await this.modelsService.getCurrentModelKeyInfo('dall-e-3');
const keyId = detailKeyInfo === null || detailKeyInfo === void 0 ? void 0 : detailKeyInfo.id;
const { key, proxyResUrl } = await this.formatModelToken(detailKeyInfo);
common_1.Logger.log(`draw paompt info <==**==> ${body.prompt}, key ===> ${key}`, 'DrawService');
@@ -795,7 +798,7 @@ let ChatgptService = class ChatgptService {
};
ChatgptService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_2.InjectRepository)(gptkeys_entity_1.GptKeysEntity)),
__param(0, (0, typeorm_2.InjectRepository)(gptKeys_entity_1.GptKeysEntity)),
__param(1, (0, typeorm_2.InjectRepository)(config_entity_1.ConfigEntity)),
__param(2, (0, typeorm_2.InjectRepository)(chatBoxType_entity_1.ChatBoxTypeEntity)),
__param(3, (0, typeorm_2.InjectRepository)(chatBox_entity_1.ChatBoxEntity)),

View File

@@ -3,95 +3,168 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.getTokenCount = exports.sendMessageFromOpenAi = void 0;
const axios_1 = require("axios");
const tiktoken_1 = require("@dqbd/tiktoken");
const utils_1 = require("../../common/utils");
const common_1 = require("@nestjs/common");
const uuid = require("uuid");
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
function getFullUrl(proxyUrl) {
const processedUrl = proxyUrl.endsWith('/') ? proxyUrl.slice(0, -1) : proxyUrl;
const baseUrl = processedUrl || 'https://api.openai.com';
return `${baseUrl}/v1/chat/completions`;
}
function sendMessageFromOpenAi(messagesHistory, inputs) {
var _a;
const { onProgress, maxToken, apiKey, model, temperature = 0.95, proxyUrl } = inputs;
const max_tokens = compilerToken(model, maxToken);
const options = {
method: 'POST',
url: getFullUrl(proxyUrl),
responseType: 'stream',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${(0, utils_1.removeSpecialCharacters)(apiKey)}`,
},
data: {
max_tokens,
stream: true,
temperature,
model,
messages: messagesHistory
},
};
const prompt = (_a = messagesHistory[messagesHistory.length - 1]) === null || _a === void 0 ? void 0 : _a.content;
return new Promise(async (resolve, reject) => {
async function sendMessageFromOpenAi(messagesHistory, inputs, uploadService) {
var _a, _b, _c, _d;
const { onProgress, maxToken, apiKey, model, temperature = 0.8, proxyUrl, prompt } = inputs;
if (model.includes('dall')) {
let result = { text: '', fileInfo: '' };
try {
const options = {
method: 'POST',
url: `${proxyUrl}/v1/images/generations`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
data: {
prompt: prompt,
model: model,
response_format: 'b64_json'
},
};
const response = await (0, axios_1.default)(options);
const stream = response.data;
let result = { text: '' };
stream.on('data', (chunk) => {
var _a;
const splitArr = chunk.toString().split('\n\n').filter((line) => line.trim() !== '');
for (const line of splitArr) {
const data = line.replace('data:', '');
let ISEND = false;
try {
ISEND = JSON.parse(data).choices[0].finish_reason === 'stop';
}
catch (error) {
ISEND = false;
}
if (ISEND) {
result.text = result.text.trim();
return result;
}
try {
const parsedData = JSON.parse(data);
if (parsedData.id) {
result.id = parsedData.id;
}
if ((_a = parsedData.choices) === null || _a === void 0 ? void 0 : _a.length) {
const delta = parsedData.choices[0].delta;
result.delta = delta.content;
if (delta === null || delta === void 0 ? void 0 : delta.content)
result.text += delta.content;
if (delta.role) {
result.role = delta.role;
}
result.detail = parsedData;
}
onProgress && onProgress({ text: result.text });
}
catch (error) {
console.log('parse Error', data);
}
}
});
stream.on('end', () => {
if (result.detail && result.text) {
const promptTokens = getTokenCount(prompt);
const completionTokens = getTokenCount(result.text);
result.detail.usage = {
prompt_tokens: promptTokens,
completion_tokens: completionTokens,
total_tokens: promptTokens + completionTokens,
estimated: true
};
}
return resolve(result);
});
const { b64_json, revised_prompt } = response.data.data[0];
const buffer = Buffer.from(b64_json, 'base64');
let imgUrl = '';
try {
const filename = uuid.v4().slice(0, 10) + '.png';
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
const buffer = Buffer.from(b64_json, 'base64');
imgUrl = await uploadService.uploadFile({ filename, buffer });
common_1.Logger.debug(`图片上传成功URL: ${imgUrl}`, 'MidjourneyService');
}
catch (error) {
common_1.Logger.error(`上传图片过程中出现错误: ${error}`, 'MidjourneyService');
}
result.fileInfo = imgUrl;
result.text = revised_prompt;
onProgress && onProgress({ text: result.text });
return result;
}
catch (error) {
reject(error);
const status = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) || 500;
console.log('openai-draw error: ', JSON.stringify(error), status);
const message = (_d = (_c = (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.message;
if (status === 429) {
result.text = '当前请求已过载、请稍等会儿再试试吧!';
return result;
}
if (status === 400 && message.includes('This request has been blocked by our content filters')) {
result.text = '您的请求已被系统拒绝。您的提示可能存在一些非法的文本。';
return result;
}
if (status === 400 && message.includes('Billing hard limit has been reached')) {
result.text = '当前模型key已被封禁、已冻结当前调用Key、尝试重新对话试试吧';
return result;
}
if (status === 500) {
result.text = '绘制图片失败,请检查你的提示词是否有非法描述!';
return result;
}
if (status === 401) {
result.text = '绘制图片失败,此次绘画被拒绝了!';
return result;
}
result.text = '绘制图片失败,请稍后试试吧!';
return result;
}
});
}
else {
let result = { text: '' };
const options = {
method: 'POST',
url: getFullUrl(proxyUrl),
responseType: 'stream',
headers: {
'Content-Type': 'application/json',
Accept: "application/json",
Authorization: `Bearer ${apiKey}`,
},
data: {
stream: true,
temperature,
model,
messages: messagesHistory,
},
};
if (model === 'gpt-4-vision-preview') {
options.data.max_tokens = 2048;
}
return new Promise(async (resolve, reject) => {
try {
const response = await (0, axios_1.default)(options);
const stream = response.data;
stream.on('data', (chunk) => {
var _a;
const splitArr = chunk.toString().split('\n\n').filter((line) => line.trim() !== '');
for (const line of splitArr) {
const data = line.replace('data:', '');
let ISEND = false;
try {
ISEND = JSON.parse(data).choices[0].finish_reason === 'stop';
}
catch (error) {
ISEND = false;
}
if (ISEND) {
result.text = result.text.trim();
return result;
}
try {
if (data !== " [DONE]" && data !== "[DONE]" && data != "[DONE] ") {
const parsedData = JSON.parse(data);
if (parsedData.id) {
result.id = parsedData.id;
}
if ((_a = parsedData.choices) === null || _a === void 0 ? void 0 : _a.length) {
const delta = parsedData.choices[0].delta;
result.delta = delta.content;
if (delta === null || delta === void 0 ? void 0 : delta.content)
result.text += delta.content;
if (delta.role) {
result.role = delta.role;
}
result.detail = parsedData;
}
onProgress && onProgress({ text: result.text });
}
}
catch (error) {
console.log('parse Error', data);
}
}
});
let totalText = '';
messagesHistory.forEach(message => {
totalText += message.content + ' ';
});
stream.on('end', () => {
if (result.detail && result.text) {
const promptTokens = getTokenCount(totalText);
const completionTokens = getTokenCount(result.text);
result.detail.usage = {
prompt_tokens: promptTokens,
completion_tokens: completionTokens,
total_tokens: promptTokens + completionTokens,
estimated: true
};
}
return resolve(result);
});
}
catch (error) {
reject(error);
}
});
}
}
exports.sendMessageFromOpenAi = sendMessageFromOpenAi;
function getTokenCount(text) {
@@ -104,19 +177,3 @@ function getTokenCount(text) {
return tokenizer.encode(text).length;
}
exports.getTokenCount = getTokenCount;
function compilerToken(model, maxToken) {
let max = 0;
if (model.includes(3.5)) {
max = maxToken > 4096 ? 4096 : maxToken;
}
if (model.includes('gpt-4')) {
max = maxToken > 8192 ? 8192 : maxToken;
}
if (model.includes('preview')) {
max = maxToken > 4096 ? 4096 : maxToken;
}
if (model.includes('32k')) {
max = maxToken > 32768 ? 32768 : maxToken;
}
return max;
}

View File

@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.NineStore = void 0;
const uuid_1 = require("uuid");
const tiktoken_1 = require("@dqbd/tiktoken");
const common_1 = require("@nestjs/common");
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
class NineStore {
constructor(options) {
@@ -32,7 +31,7 @@ class NineStore {
let messages = [];
let nextNumTokensEstimate = 0;
if (systemMessage) {
const specialModels = ['gemini-pro', 'ERNIE', 'qwen', 'SparkDesk', 'hunyuan'];
const specialModels = ['gemini-pro', 'ERNIE', 'hunyuan'];
const isSpecialModel = model && specialModels.some(specialModel => model.includes(specialModel));
if (isSpecialModel) {
messages.push({ role: 'user', content: systemMessage, name });
@@ -65,7 +64,6 @@ class NineStore {
}
messages.push({ role: 'user', content: text, name });
}
common_1.Logger.debug(`发送的参数:${messages}`);
let nextMessages = messages;
do {
if (!parentMessageId) {
@@ -77,7 +75,7 @@ class NineStore {
}
const { text, name, role, fileInfo } = parentMessage;
let content = text;
if (role === 'user' && fileInfo) {
if (fileInfo) {
if (model === 'gpt-4-vision-preview') {
content = [
{ "type": "text", "text": text },

View File

@@ -1,101 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendMessageFromZhipu = exports.compilerStream = exports.compilerMetaJsonStr = exports.generateToken = void 0;
const axios = require('axios');
const jwt = require('jsonwebtoken');
function generateToken(apikey, expSeconds = 1000 * 60 * 60 * 24 * 360) {
const [id, secret] = apikey.split('.');
const payload = {
api_key: id,
exp: Math.round(Date.now()) + expSeconds * 1000,
timestamp: Math.round(Date.now()),
};
return jwt.sign(payload, secret, { algorithm: 'HS256', header: { alg: 'HS256', sign_type: 'SIGN' } });
}
exports.generateToken = generateToken;
function compilerMetaJsonStr(data) {
let jsonStr = {};
try {
jsonStr = JSON.parse(data);
}
catch (error) {
jsonStr = {
usage: {
completion_tokens: 49,
prompt_tokens: 333,
total_tokens: 399
},
};
console.error('json parse error from zhipu!', data);
}
return jsonStr;
}
exports.compilerMetaJsonStr = compilerMetaJsonStr;
function compilerStream(streamArr) {
var _a;
if (streamArr.length === 3) {
return {
event: streamArr[0].replace('event:', ''),
id: streamArr[1].replace('id:', ''),
is_end: false,
result: streamArr[2].replace('data:', '').trim()
};
}
if (streamArr.length === 4) {
return {
event: streamArr[0].replace('event:', ''),
id: streamArr[1].replace('id:', ''),
result: streamArr[2].replace('data:', '').trim(),
is_end: true,
usage: (_a = compilerMetaJsonStr(streamArr[3].replace('meta:', ''))) === null || _a === void 0 ? void 0 : _a.usage
};
}
}
exports.compilerStream = compilerStream;
async function sendMessageFromZhipu(messagesHistory, { onProgress, key, model, temperature = 0.95 }) {
const token = await generateToken(key);
return new Promise((resolve, reject) => {
const url = `https://open.bigmodel.cn/api/paas/v3/model-api/${model}/sse-invoke`;
const options = {
method: 'POST',
url,
responseType: 'stream',
headers: {
'Content-Type': 'application/json',
'Authorization': token
},
data: {
prompt: messagesHistory,
temperature
}
};
axios(options)
.then(response => {
const stream = response.data;
let resData;
let cacheResText = '';
stream.on('data', chunk => {
const stramArr = chunk.toString().split("\n").filter((line) => line.trim() !== "");
const parseData = compilerStream(stramArr);
if (!parseData)
return;
const { id, result, is_end } = parseData;
result && (cacheResText += result.trim());
if (is_end) {
parseData.is_end = false;
resData = parseData;
resData.text = cacheResText;
}
onProgress(parseData);
});
stream.on('end', () => {
resolve(resData);
cacheResText = '';
});
})
.catch(error => {
console.log('error: ', error);
});
});
}
exports.sendMessageFromZhipu = sendMessageFromZhipu;

View File

@@ -26,10 +26,10 @@ let DatabaseService = class DatabaseService {
if (!user || user.length === 0) {
const superPassword = bcrypt.hashSync('123456', 10);
const adminPassword = bcrypt.hashSync('123456', 10);
const superEmail = 'default@cooper.com';
const adminEmail = 'defaultAdmin@cooper.com';
const superEmail = 'super';
const adminEmail = 'admin';
const superUserinfo = { username: 'super', password: superPassword, status: 1, email: superEmail, sex: 1, role: 'super' };
const adminUserinfo = { username: 'admin', password: adminPassword, status: 1, email: adminEmail, sex: 1, role: 'admin' };
const adminUserinfo = { username: 'admin', password: adminPassword, status: 0, email: adminEmail, sex: 1, role: 'admin' };
await this.createDefaultUser(superUserinfo);
await this.createDefaultUser(adminUserinfo);
}
@@ -59,83 +59,70 @@ let DatabaseService = class DatabaseService {
}
async createBaseSiteConfig() {
try {
const code = `
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?cb8c9a3bcadbc200e950b05f9c61a385";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
`;
const code = ``;
const noticeInfo = `
#### NineAi 欢迎您
- NineAi唯一官方网站 https://ai.jiangly.com
- NineAi 作者VX J_longyan
- NineAi 作者QQ 927898639
- 欢迎使用Nine
- 初始管理员账号密码 super nine-super 【前台后台登录都可以修改】
#### AIWeb 欢迎您
- 欢迎使用 AIWeb
- 初始管理员账号密码 super 123456 【前台后台登录都可以修改】
- 初始预览账号密码 admin 123456 【为后台查看账号 仅可查看部分非敏感数据】
`;
const defaultConfig = [
{ configKey: 'siteName', configVal: 'Nine Ai', public: 1, encry: 0 },
{ configKey: 'qqNumber', configVal: '840814166', public: 1, encry: 0 },
{ configKey: 'vxNumber', configVal: 'wangpanzhu321', public: 1, encry: 0 },
{ configKey: 'siteName', configVal: '', public: 1, encry: 0 },
{ configKey: 'qqNumber', configVal: '', public: 1, encry: 0 },
{ configKey: 'vxNumber', configVal: '', public: 1, encry: 0 },
{ configKey: 'robotAvatar', configVal: '', public: 1, encry: 0 },
{
configKey: 'userDefautlAvatar',
configVal: 'https://public-1300678944.cos.ap-shanghai.myqcloud.com/blog/1682571295452image.png',
configVal: '',
public: 0,
encry: 0,
},
{ configKey: 'baiduCode', configVal: code, public: 1, encry: 0 },
{ configKey: 'baiduSiteId', configVal: '19024441', public: 0, encry: 0 },
{ configKey: 'baiduSiteId', configVal: '', public: 0, encry: 0 },
{
configKey: 'baiduToken',
configVal: '121.a1600b9b60910feea2ef627ea9776a6f.YGP_CWCOA2lNcIGJ27BwXGxa6nZhBQyLUS4XVaD.TWt9TA',
configVal: '',
public: 0,
encry: 0,
},
{ configKey: 'buyCramiAddress', configVal: '', public: 1, encry: 0 },
{ configKey: 'openaiBaseUrl', configVal: 'https://api.openai.com', public: 0, encry: 0 },
{ configKey: 'openaiBaseUrl', configVal: 'https://api.lightai.io', public: 0, encry: 0 },
{ configKey: 'noticeInfo', configVal: noticeInfo, public: 1, encry: 0 },
{ configKey: 'registerVerifyEmailTitle', configVal: 'NineTeam团队账号验证', public: 0, encry: 0 },
{ configKey: 'registerVerifyEmailTitle', configVal: 'AIWeb账号验证', public: 0, encry: 0 },
{
configKey: 'registerVerifyEmailDesc',
configVal: '欢迎使用Nine Team团队的产品服务,请在五分钟内完成你的账号激活,点击以下按钮激活您的账号,',
configVal: '欢迎使用AI Web团队的产品服务,请在五分钟内完成你的账号激活,点击以下按钮激活您的账号,',
public: 0,
encry: 0,
},
{ configKey: 'registerVerifyEmailFrom', configVal: 'NineTeam团队', public: 0, encry: 0 },
{ configKey: 'registerVerifyEmailFrom', configVal: 'AI Web团队', public: 0, encry: 0 },
{ configKey: 'registerVerifyExpir', configVal: '1800', public: 0, encry: 0 },
{ configKey: 'registerSuccessEmailTitle', configVal: 'NineTeam团队账号激活成功', public: 0, encry: 0 },
{ configKey: 'registerSuccessEmailTeamName', configVal: 'NineTeam团队', public: 0, encry: 0 },
{ configKey: 'registerSuccessEmailTitle', configVal: 'AIWeb账号激活成功', public: 0, encry: 0 },
{ configKey: 'registerSuccessEmailTeamName', configVal: 'AIWeb', public: 0, encry: 0 },
{
configKey: 'registerSuccessEmaileAppend',
configVal: ',请妥善保管您的账号,我们将为您赠送50次对话额度和5次绘画额度、祝您使用愉快',
configVal: ',请妥善保管您的账号,祝您使用愉快',
public: 0,
encry: 0,
},
{ configKey: 'registerFailEmailTitle', configVal: 'NineTeam账号激活失败', public: 0, encry: 0 },
{ configKey: 'registerFailEmailTeamName', configVal: 'NineTeam团队', public: 0, encry: 0 },
{ configKey: 'registerFailEmailTitle', configVal: 'AIWeb账号激活失败', public: 0, encry: 0 },
{ configKey: 'registerFailEmailTeamName', configVal: 'AIWeb团队', public: 0, encry: 0 },
{ configKey: 'registerSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'registerSendModel3Count', configVal: '30', public: 1, encry: 0 },
{ configKey: 'registerSendModel4Count', configVal: '3', public: 1, encry: 0 },
{ configKey: 'registerSendDrawMjCount', configVal: '3', public: 1, encry: 0 },
{ configKey: 'firstRegisterSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'firstRegisterSendRank', configVal: '500', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel3Count', configVal: '20', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel4Count', configVal: '2', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendDrawMjCount', configVal: '3', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel3Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel4Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
{ configKey: 'inviteSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel3Count', configVal: '30', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel4Count', configVal: '3', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendDrawMjCount', configVal: '1', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel3Count', configVal: '0', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel4Count', configVal: '0', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendDrawMjCount', configVal: '0', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendModel3Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendModel4Count', configVal: '1', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendDrawMjCount', configVal: '1', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendModel4Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
{ configKey: 'isVerifyEmail', configVal: '1', public: 1, encry: 0 },
];
const res = await this.connection.query(`INSERT INTO config (configKey, configVal, public, encry) VALUES ${defaultConfig

View File

@@ -38,10 +38,6 @@ __decorate([
(0, typeorm_1.Column)({ comment: '垫图图片 + 绘画描述词 + 额外参数 = 完整的prompt', type: 'text' }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "fullPrompt", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '随机产生的绘画ID用于拿取比对结果' }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "randomDrawId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '当前绘制任务的进度', nullable: true }),
__metadata("design:type", Number)
@@ -56,7 +52,7 @@ __decorate([
], MidjourneyEntity.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'mj绘画的动作、绘图、放大、变换、图生图' }),
__metadata("design:type", Number)
__metadata("design:type", String)
], MidjourneyEntity.prototype, "action", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '一组图片的第几张、放大或者变换的时候需要使用', nullable: true }),
@@ -66,18 +62,22 @@ __decorate([
(0, typeorm_1.Column)({ comment: '是否推荐0: 默认不推荐 1: 推荐', nullable: true, default: 0 }),
__metadata("design:type", Number)
], MidjourneyEntity.prototype, "rec", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '对图片操作的', nullable: true }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "customId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '绘画的ID每条不一样', nullable: true }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "message_id", void 0);
], MidjourneyEntity.prototype, "drawId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '图片放大或者变体的ID', nullable: true }),
(0, typeorm_1.Column)({ comment: '图片链接', nullable: true, type: 'text' }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "custom_id", void 0);
], MidjourneyEntity.prototype, "drawUrl", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '图片信息尺寸', nullable: true, type: 'text' }),
(0, typeorm_1.Column)({ comment: '图片比例', nullable: true, type: 'text' }),
__metadata("design:type", String)
], MidjourneyEntity.prototype, "fileInfo", void 0);
], MidjourneyEntity.prototype, "drawRatio", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '扩展参数', nullable: true, type: 'text' }),
__metadata("design:type", String)

View File

@@ -22,19 +22,18 @@ const axios_1 = require("axios");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
const upload_service_1 = require("../upload/upload.service");
const badwords_service_1 = require("../badwords/badwords.service");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const utils_1 = require("../../common/utils");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const prompt_entity_1 = require("./prompt.entity");
const image_size_1 = require("image-size");
let MidjourneyService = class MidjourneyService {
constructor(midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, badwordsService, userBalanceService, redisCacheService) {
constructor(midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, userBalanceService, redisCacheService) {
this.midjourneyEntity = midjourneyEntity;
this.userEntity = userEntity;
this.mjPromptsEntity = mjPromptsEntity;
this.globalConfigService = globalConfigService;
this.uploadService = uploadService;
this.badwordsService = badwordsService;
this.userBalanceService = userBalanceService;
this.redisCacheService = redisCacheService;
this.lockPrompt = [];
@@ -42,580 +41,191 @@ let MidjourneyService = class MidjourneyService {
async sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async getImageSizeFromUrl(imageUrl) {
try {
const response = await axios_1.default.get(imageUrl, { responseType: 'arraybuffer' });
const buffer = Buffer.from(response.data, 'binary');
const dimensions = (0, image_size_1.default)(buffer);
return { width: dimensions.width, height: dimensions.height };
}
catch (error) {
console.error('Error fetching image size:', error);
throw error;
}
}
async draw(jobData, jobId) {
const { id, action } = jobData;
const { id, action, drawId } = jobData;
const drawInfo = await this.midjourneyEntity.findOne({ where: { id } });
const { customId } = drawInfo;
try {
await this.bindJobId(id, jobId);
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWING);
if (action === midjourney_constant_1.MidjourneyActionEnum.DRAW || action === midjourney_constant_1.MidjourneyActionEnum.GENERATE) {
await this.sendDrawCommand(drawInfo, jobData);
const drawRes = await this.pollComparisonResultDraw(drawInfo);
await this.updateDrawData(jobData, drawRes);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
const { message_id, custom_id } = drawInfo;
await this.sendSmInteractions({ message_id, custom_id }, jobData);
common_1.Logger.debug(`记录${id}已经成功发送了图片放大指令`, 'MidjourneyService');
const drawRes = await this.pollComparisonResultUpscale(drawInfo);
await this.updateDrawData(jobData, drawRes);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
const { message_id, custom_id } = drawInfo;
await this.sendSmInteractions({ message_id, custom_id }, jobData);
common_1.Logger.debug(`记录${id}已经成功发送了图片变化指令`, 'MidjourneyService');
const drawRes = await this.pollComparisonResultVariation(drawInfo);
await this.updateDrawData(jobData, drawRes);
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
const { message_id, custom_id } = drawInfo;
await this.sendReGenerateInteractions({ message_id, custom_id }, jobData);
common_1.Logger.debug(`记录${id}已经成功发送了重新生成图片指令`, 'MidjourneyService');
const drawRes = await this.pollComparisonResultReGenerate(drawInfo);
await this.updateDrawData(jobData, drawRes);
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
const { message_id, custom_id } = drawInfo;
await this.sendVaryInteractions({ message_id, custom_id }, jobData);
common_1.Logger.debug(`记录${id}已经成功发送单张图片增强指令`, 'MidjourneyService');
const drawRes = await this.pollComparisonResultVary(drawInfo);
await this.updateDrawData(jobData, drawRes);
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
const { message_id, custom_id } = drawInfo;
await this.sendZoomInteractions({ message_id, custom_id }, jobData);
common_1.Logger.debug(`记录${id}已经成功发送单张图片缩放指令`, 'MidjourneyService');
const drawRes = await this.pollComparisonResultZoom(drawInfo);
await this.updateDrawData(jobData, drawRes);
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
}
const result = await this.sendDrawCommand(drawInfo, action);
drawInfo.drawId = result;
const drawRes = await this.pollComparisonResultDraw(id, drawInfo);
await this.updateDrawData(jobData, drawRes);
this.drawSuccess(jobData);
return true;
}
catch (error) {
this.lockPrompt = this.lockPrompt.filter((item) => item !== drawInfo.randomDrawId);
await this.drawFailed(jobData);
console.log('error: ', error);
return true;
}
}
async addDrawQueue(params) {
const { prompt, imgUrl = '', extraParam = '', action = 1, userId, randomDrawId, orderId, custom_id, message_id } = params;
const fullPrompt = imgUrl ? `${imgUrl} ${prompt} ${extraParam}` : `${prompt} ${extraParam}`;
await this.badwordsService.checkBadWords(fullPrompt, userId);
const drawInfo = {
userId,
extraParam,
prompt,
imgUrl,
fullPrompt,
randomDrawId,
status: midjourney_constant_1.MidjourneyStatusEnum.WAITING,
action: action,
orderId,
custom_id,
message_id,
};
const res = await this.midjourneyEntity.save(drawInfo);
return res;
try {
const { prompt, imgUrl = '', extraParam = '', action, userId, orderId, customId, drawId } = params;
const fullPrompt = imgUrl ? `${imgUrl} ${prompt} ${extraParam}` : `${prompt} ${extraParam}`;
const drawInfo = {
userId,
drawId,
extraParam,
prompt,
imgUrl,
fullPrompt,
status: midjourney_constant_1.MidjourneyStatusEnum.WAITING,
action,
orderId,
customId,
};
const res = await this.midjourneyEntity.save(drawInfo);
return res;
}
catch (error) {
console.error('Error in addDrawQueue:', error);
throw error;
}
}
async updateDrawStatus(id, status) {
await this.midjourneyEntity.update({ id }, { status });
}
async updateDrawData(jobData, drawRes) {
try {
const { id, content, channel_id, attachments = [], timestamp, durationSpent } = drawRes;
const { filename, url, proxy_url, width, height, size } = attachments[0];
const { id, imageUrl, action, submitTime, finishTime, progress } = drawRes;
const durationSpent = finishTime - submitTime;
let filename = `${Date.now()}-${id}.png`;
const mjNotSaveImg = await this.globalConfigService.getConfigs(['mjNotSaveImg']);
let cosUrl = '';
if (!Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0) {
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
const startDate = new Date();
cosUrl = await this.uploadService.uploadFileFromUrl({ filename, url });
const endDate = new Date();
common_1.Logger.debug(`本次图片上传耗时为${(endDate.getTime() - startDate.getTime()) / 1000}`, 'MidjourneyService');
let isSaveImg = true;
try {
if (!Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0) {
common_1.Logger.debug(`------> 开始上传图片!!!`, 'MidjourneyService');
cosUrl = await this.uploadService.uploadFileFromUrl({ filename, url: imageUrl });
}
else {
cosUrl = imageUrl;
isSaveImg = false;
common_1.Logger.debug('本次不存图片了', 'MidjourneyService');
}
}
else {
console.log('本次不存图片了');
catch (uploadError) {
common_1.Logger.error('存储图片失败,使用原始图片链接', 'MidjourneyService');
cosUrl = imageUrl;
isSaveImg = false;
}
const cosType = await this.uploadService.getUploadType();
const { width, height } = await this.getImageSizeFromUrl(imageUrl);
const drawInfo = {
status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED,
message_id: id,
drawId: id,
action: action,
drawUrl: cosUrl,
drawRatio: `${width}x${height}`,
progress: 100,
fileInfo: JSON.stringify({ width, height, size, filename, cosUrl, cosType }),
extend: this.removeEmoji(JSON.stringify(drawRes)),
durationSpent,
isSaveImg: !Number(mjNotSaveImg) || Number(mjNotSaveImg) === 0,
isSaveImg,
};
await this.midjourneyEntity.update({ id: jobData.id }, drawInfo);
}
catch (error) {
console.log('TODO->存储图片失败, ', jobData, error);
throw new common_1.HttpException('更新绘画数据失败', common_1.HttpStatus.BAD_REQUEST);
}
}
async getHistroyMessageIds(randomDrawId) {
const res = await this.midjourneyEntity.find({ where: { randomDrawId, status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED } });
return res.map((item) => item.message_id);
}
async sendDrawCommand(drawInfo, jobData) {
const { fullPrompt, randomDrawId, imgUrl } = drawInfo;
const prompt = imgUrl ? `[${randomDrawId}] ${imgUrl} ${fullPrompt}` : `[${randomDrawId}] ${fullPrompt}`;
common_1.Logger.debug(`本次绘图指令为${prompt}`, 'MidjourneyService');
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const payloadJson = {
type: 2,
application_id,
guild_id,
channel_id,
session_id,
data: { version, id, name: 'imagine', type: 1, options: [{ type: 3, name: 'prompt', value: prompt }], attachments: [] },
};
try {
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
const headers = { authorization };
const res = await axios_1.default.post(url, payloadJson, { headers });
return false;
}
catch (error) {
common_1.Logger.error(`发送绘画指令失败`, 'MidjourneyService');
throw new common_1.HttpException('发送绘图指令失败、请联系管理员检测绘画配置!', common_1.HttpStatus.BAD_REQUEST);
}
}
async sendSmInteractions(params, jobData) {
const { message_id, custom_id } = params;
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
const headers = { authorization };
const body = {
type: 3,
guild_id,
channel_id,
message_flags: 0,
message_id,
application_id,
session_id,
data: {
component_type: 2,
custom_id,
},
};
try {
await axios_1.default.post(url, body, { headers });
}
catch (error) {
console.log('发送放大变幻指令失败: ', error);
common_1.Logger.error(`发送放大变幻指令失败`, 'MidjourneyService');
throw new common_1.HttpException('对图片放大变幻失败...', common_1.HttpStatus.BAD_REQUEST);
}
}
async sendReGenerateInteractions(params, jobData) {
const { message_id, custom_id } = params;
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
const headers = { authorization };
const body = {
type: 3,
guild_id,
channel_id,
message_id,
application_id,
session_id,
data: {
component_type: 2,
custom_id,
},
};
try {
await axios_1.default.post(url, body, { headers });
}
catch (error) {
console.log('发送重新生成指令失败: ', error);
common_1.Logger.error(`发送放大变幻指令失败`, 'MidjourneyService');
throw new common_1.HttpException('对图片放大变幻失败...', common_1.HttpStatus.BAD_REQUEST);
}
}
async sendVaryInteractions(params, jobData) {
const { message_id, custom_id } = params;
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
const headers = { authorization };
const body = {
type: 3,
guild_id,
channel_id,
message_id,
application_id,
session_id,
data: {
component_type: 2,
custom_id,
},
};
try {
await axios_1.default.post(url, body, { headers });
}
catch (error) {
console.log('发送对单张图片增强指令失败: ', error);
common_1.Logger.error(`发送单张图片增强指令失败`, 'MidjourneyService');
throw new common_1.HttpException('对图片单张增强失败...', common_1.HttpStatus.BAD_REQUEST);
}
}
async sendZoomInteractions(params, jobData) {
const { message_id, custom_id } = params;
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/draw` : 'https://discord.com/api/v9/interactions';
const headers = { authorization };
const body = {
type: 3,
guild_id,
channel_id,
message_id,
application_id,
session_id,
data: {
component_type: 2,
custom_id,
},
};
try {
await axios_1.default.post(url, body, { headers });
}
catch (error) {
console.log('发送对单张图片增强指令失败: ', error);
common_1.Logger.error(`发送单张图片增强指令失败`, 'MidjourneyService');
throw new common_1.HttpException('对图片单张增强失败...', common_1.HttpStatus.BAD_REQUEST);
}
}
async pollComparisonResultDraw(drawInfo) {
common_1.Logger.debug(`开始查询绘画结果`, 'MidjourneyService');
const startTime = Date.now();
const INTERVAL_BEFORE_90S = 10000;
const INTERVAL_AFTER_90S = 30000;
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
const TIMEOUT = timeout;
let pollingCount = 0;
let drawRes = null;
let isMatchSuccessful = false;
try {
while (!isMatchSuccessful && Date.now() - startTime < TIMEOUT) {
let interval;
if (Date.now() - startTime < 90000) {
interval = INTERVAL_BEFORE_90S;
async sendDrawCommand(drawInfo, action) {
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl']));
const mjKey = (await this.globalConfigService.getConfigs(['mjKey']));
const { id, fullPrompt, imgUrl, drawId, customId } = drawInfo;
const prompt = imgUrl ? `${imgUrl} ${fullPrompt}` : `${fullPrompt}`;
let url = '';
let payloadJson = {};
const MAX_RETRIES = 3;
let retryCount = 0;
while (retryCount < MAX_RETRIES) {
try {
if (action === 'IMAGINE') {
url = `${mjProxyUrl}/mj/submit/imagine`;
payloadJson = { prompt: prompt };
}
else {
interval = INTERVAL_AFTER_90S;
url = `${mjProxyUrl}/mj/submit/action`;
payloadJson = { taskId: drawId, customId: customId };
}
await this.sleep(interval);
common_1.Logger.debug(`【绘制图片】第 ${pollingCount + 1} 次开始查询`, 'MidjourneyService');
drawRes = await this.findCurrentPromptResult(drawInfo.randomDrawId);
if (drawRes) {
const { content } = drawRes;
const progress = await this.parseProgress(content);
common_1.Logger.debug(`【绘制图片】第 ${pollingCount + 1} 次、 当前绘画进度为${progress}%`, 'MidjourneyService');
await this.midjourneyEntity.update({ id: drawInfo.id }, { progress: progress !== null && progress !== void 0 ? progress : 100 });
const headers = { "mj-api-secret": mjKey };
const res = await axios_1.default.post(url, payloadJson, { headers });
const { result } = res.data;
if (result) {
common_1.Logger.log(`绘画ID: ${result}`, 'MidjourneyService');
return result;
}
else {
throw new Error('未能获取结果数据');
}
}
catch (error) {
retryCount++;
if (retryCount >= MAX_RETRIES) {
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
throw new common_1.HttpException('发送绘图指令失败、请联系管理员检测绘画配置!', common_1.HttpStatus.BAD_REQUEST);
}
}
}
}
async pollComparisonResultDraw(id, drawInfo) {
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl']));
const mjKey = (await this.globalConfigService.getConfigs(['mjKey']));
const startTime = Date.now();
const POLL_INTERVAL = 5000;
const TIMEOUT = 150000;
let pollingCount = 0;
let retryCount = 0;
const MAX_RETRIES = 5;
const { drawId } = drawInfo;
try {
while (Date.now() - startTime < TIMEOUT && retryCount < MAX_RETRIES) {
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
try {
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
"mj-api-secret": mjKey
};
const url = `${mjProxyUrl}/mj/task/${drawId}/fetch`;
const res = await axios_1.default.get(url, { headers });
const responses = res.data;
const progress = responses.process;
await this.midjourneyEntity.update({ id }, { progress: progress });
if (responses.status === 'SUCCESS') {
common_1.Logger.log(`绘制成功, URL: ${responses.imageUrl}`, 'MidjourneyService');
return responses;
}
}
catch (error) {
retryCount++;
common_1.Logger.error(`轮询过程中发生错误: ${error}`, 'MidjourneyService');
}
isMatchSuccessful = drawRes && !drawRes.edited_timestamp;
pollingCount++;
}
if (!drawRes) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('绘画超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
if (retryCount >= MAX_RETRIES) {
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
throw new common_1.HttpException('轮询失败次数过多,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
const endTime = Date.now();
return Object.assign(Object.assign({}, drawRes), { durationSpent: Math.floor((endTime - startTime) / 1000) });
common_1.Logger.error('绘画超时,请稍后再试!', 'MidjourneyService');
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
throw new common_1.HttpException('绘画超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
catch (error) {
console.log('获取图片列表结果失败: ', error);
}
}
async pollComparisonResultUpscale(drawInfo) {
common_1.Logger.debug(`开始查询放大图片信息`, 'MidjourneyService');
const startTime = Date.now();
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
let enlargeImgDetail = null;
let pollingCount = 0;
while (!enlargeImgDetail && pollingCount < 10) {
common_1.Logger.debug(`开始比对放大图片第${pollingCount + 1}`, 'MidjourneyService');
enlargeImgDetail = await this.findCurrentEnlargeImgResult(randomDrawId, orderId);
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000));
pollingCount++;
}
if (!enlargeImgDetail) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('放大图片超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
const endTime = Date.now();
return Object.assign(Object.assign({}, enlargeImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
}
async pollComparisonResultReGenerate(drawInfo) {
common_1.Logger.debug(`开始查询重复绘制的图片信息`, 'MidjourneyService');
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
const startTime = Date.now();
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
let reGenerateImgDetail = null;
let pollingTime = 0;
let count = 0;
while (!reGenerateImgDetail && pollingTime < TIMEOUT) {
common_1.Logger.debug(`开始比对重新绘制图片第${count + 1}`, 'MidjourneyService');
reGenerateImgDetail = await this.findCurrentReGenerateImgResult(randomDrawId, message_id);
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
await new Promise((resolve) => setTimeout(resolve, t));
pollingTime += t;
count++;
}
if (!reGenerateImgDetail) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('重新绘制图片超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
const endTime = Date.now();
return Object.assign(Object.assign({}, reGenerateImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
}
async pollComparisonResultVary(drawInfo) {
common_1.Logger.debug(`开始查询单张图片增强的图片信息`, 'MidjourneyService');
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
const startTime = Date.now();
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
let varyImgDetail = null;
let pollingTime = 0;
let count = 0;
while (!varyImgDetail && pollingTime < TIMEOUT) {
common_1.Logger.debug(`开始单张图片增强第${count + 1}`, 'MidjourneyService');
varyImgDetail = await this.findCurrentVaryImgResult(randomDrawId, message_id);
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
await new Promise((resolve) => setTimeout(resolve, t));
pollingTime += t;
count++;
}
if (!varyImgDetail) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('单张图片增强超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
const endTime = Date.now();
return Object.assign(Object.assign({}, varyImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
}
async pollComparisonResultZoom(drawInfo) {
common_1.Logger.debug(`开始查询单张图片缩放的图片信息`, 'MidjourneyService');
const TIMEOUT = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
const startTime = Date.now();
const { message_id, custom_id, randomDrawId, orderId } = drawInfo;
let zoomImgDetail = null;
let pollingTime = 0;
let count = 0;
while (!zoomImgDetail && pollingTime < TIMEOUT) {
common_1.Logger.debug(`开始单张图片缩放第${count + 1}`, 'MidjourneyService');
zoomImgDetail = await this.findCurrentZoomImgResult(randomDrawId, message_id);
const t = Math.floor(Math.random() * (5000 - 3000 + 1)) + 8000;
await new Promise((resolve) => setTimeout(resolve, t));
pollingTime += t;
count++;
}
if (!zoomImgDetail) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('单张图片缩放超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
const endTime = Date.now();
return Object.assign(Object.assign({}, zoomImgDetail), { durationSpent: Math.floor((endTime - startTime) / 1000) });
}
async pollComparisonResultVariation(drawInfo) {
common_1.Logger.debug(`开始轮询单张变换图片结果`, 'MidjourneyService');
let variationImgDetail = null;
const startTime = Date.now();
while (!variationImgDetail) {
common_1.Logger.debug(`变换图片获取中------>`, 'MidjourneyService');
variationImgDetail = await this.findCurrentVariationImgResult(drawInfo.randomDrawId);
const nextPollingDelay = 10000;
await this.sleep(nextPollingDelay);
const endTime = Date.now();
const durationSpent = Math.floor(endTime - startTime);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 150000;
const TIMEOUT = timeout;
if (durationSpent >= TIMEOUT) {
await this.updateDrawStatus(drawInfo.id, midjourney_constant_1.MidjourneyStatusEnum.DRAWTIMEOUT);
throw new common_1.HttpException('变换当前图片超时!', common_1.HttpStatus.BAD_REQUEST);
}
}
return Object.assign(Object.assign({}, variationImgDetail), { durationSpent: Math.floor(Date.now() - startTime) });
}
async findCurrentEnlargeImgResult(randomDrawId, orderId) {
const messageList = await this.getMessageList();
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const enlargeImgDetail = messageList.find((item) => {
const { content } = item;
if (!this.extractContent(content))
return false;
const { prompt, order } = this.extractContent(content);
return content.includes(randomDrawId) && orderId === order && !histroyMessageIds.includes(item.id);
});
return enlargeImgDetail;
}
async findCurrentVariationImgResult(randomDrawId) {
const messageList = await this.getMessageList();
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const variationImgDetail = messageList.find((item) => {
const { content } = item;
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && this.isVariationsImage(content);
});
if (variationImgDetail) {
if (this.lockPrompt.includes(randomDrawId)) {
common_1.Logger.debug(`【变体图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
return null;
}
else {
this.lockPrompt.push(randomDrawId);
}
}
return variationImgDetail;
}
async findCurrentReGenerateImgResult(randomDrawId, message_id) {
const messageList = await this.getMessageList();
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const reGenerateImgDetail = messageList.find((item) => {
const { content } = item;
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isReGenerateImage(content);
});
if (reGenerateImgDetail) {
if (this.lockPrompt.includes(randomDrawId)) {
common_1.Logger.debug(`【重新生成图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
return null;
}
else {
this.lockPrompt.push(randomDrawId);
}
}
return reGenerateImgDetail;
}
async findCurrentZoomImgResult(randomDrawId, message_id) {
const messageList = await this.getMessageList();
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const reGenerateImgDetail = messageList.find((item) => {
const { content } = item;
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isZoomImage(content);
});
if (reGenerateImgDetail) {
if (this.lockPrompt.includes(randomDrawId)) {
common_1.Logger.debug(`【重新生成图片】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
return null;
}
else {
this.lockPrompt.push(randomDrawId);
}
}
return reGenerateImgDetail;
}
async findCurrentVaryImgResult(randomDrawId, message_id) {
const messageList = await this.getMessageList();
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const varyImgDetail = messageList.find((item) => {
const { content } = item;
return content.includes(randomDrawId) && !histroyMessageIds.includes(item.id) && item.id !== message_id && this.isVaryImage(content);
});
if (varyImgDetail) {
if (this.lockPrompt.includes(randomDrawId)) {
common_1.Logger.debug(`【单张图片增强】当前图片已经被锁定,等待同任务完成`, 'MidjourneyService');
return null;
}
else {
this.lockPrompt.push(randomDrawId);
}
}
return varyImgDetail;
}
extractContent(str) {
const promptMatch = str.match(/\*\*(.+?)\*\*/);
const orderMatch = str.match(/- Image #(\d+)/);
if (!promptMatch || !orderMatch) {
return null;
}
const prompt = promptMatch[1];
const order = parseInt(orderMatch[1]);
return { prompt, order };
}
async findCurrentPromptResult(randomDrawId) {
const histroyMessageIds = await this.getHistroyMessageIds(randomDrawId);
const messageList = await this.getMessageList();
if (!messageList || !messageList.length)
return;
const matchingItem = messageList.find((item) => {
const { attachments = [], content, edited_timestamp } = item;
return content.includes(randomDrawId) && attachments.length > 0 && !histroyMessageIds.includes(item === null || item === void 0 ? void 0 : item.id);
});
return matchingItem || null;
}
isVariationsImage(str) {
const regex = /- Variations/;
return regex.test(str);
}
isSingleImage(str) {
const regex = /Image #\d+/;
return regex.test(str);
}
isReGenerateImage(str) {
return !this.isVariationsImage(str) && !this.isSingleImage(str);
}
isVaryImage(str) {
const regex = /- Variations \(.*?\)/;
return regex.test(str);
}
isZoomImage(str) {
const regex = /- Zoom Out/;
return regex.test(str);
}
async getMjDefaultParams() {
const configs = await this.globalConfigService.getConfigs([
'mjId',
'mjApplicationId',
'mjGuildId',
'mjChannelId',
'mjSessionId',
'mjVersion',
'mjAuthorization',
'mjRateLimit',
'mjProxy',
]);
const params = {
application_id: configs.mjApplicationId,
guild_id: configs.mjGuildId,
channel_id: configs.mjChannelId,
session_id: configs.mjSessionId,
version: configs.mjVersion,
id: configs.mjId,
authorization: configs.mjAuthorization,
mjRateLimit: configs.mjRateLimit,
mjProxy: configs.mjProxy || 0,
};
return params;
}
async getMessageList() {
try {
const { application_id, guild_id, channel_id, session_id, version, id, authorization, mjProxy } = await this.getMjDefaultParams();
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const url = mjProxy == 1 ? `${mjProxyUrl}/mj/list?channel_id=${channel_id}` : `https://discord.com/api/v9/channels/${channel_id}/messages?limit=50`;
const headers = { authorization };
const response = await axios_1.default.get(url, { headers });
return response.data;
}
catch (error) {
common_1.Logger.error('查询绘制结果失败: getMessageList', error, 'MidjourneyService');
return [];
}
}
parseProgress(content) {
const regex = /\((\d+)%\)/;
const match = content.match(regex);
if (match) {
return parseInt(match[1], 10);
}
else {
return null;
common_1.Logger.error('获取图片结果失败: ', error, 'MidjourneyService');
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWFAIL);
throw error;
}
}
removeEmoji(str) {
@@ -633,19 +243,7 @@ let MidjourneyService = class MidjourneyService {
order: { id: 'DESC' },
take: size,
skip: (page - 1) * size,
});
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
rows.forEach((item) => {
var _a, _b, _c, _d;
try {
const { extend, isSaveImg, fileInfo } = item;
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
item.originUrl = originUrl;
}
catch (error) {
}
select: ['id', 'userId', 'prompt', 'extraParam', 'fullPrompt', 'rec', 'orderId', 'drawId', 'drawUrl', 'drawRatio', 'isDelete', 'status', 'action']
});
const countQueue = await this.midjourneyEntity.count({ where: { isDelete: 0, status: (0, typeorm_2.In)([1, 2]) } });
const data = { rows: (0, utils_1.formatCreateOrUpdateDate)(rows), count, countQueue };
@@ -655,78 +253,40 @@ let MidjourneyService = class MidjourneyService {
throw new common_1.HttpException('获取我得绘制列表失败', common_1.HttpStatus.BAD_REQUEST);
}
}
formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl) {
if (!fileInfo)
return {};
let parseFileInfo = null;
try {
parseFileInfo = JSON.parse(fileInfo);
}
catch (error) {
parseFileInfo = null;
}
if (!parseFileInfo)
return;
const { url, filename, size, cosUrl, width, height } = parseFileInfo;
const targetSize = 310;
const imgType = cosUrl.includes('cos') ? 'tencent' : cosUrl.includes('oss') ? 'ali' : 'chevereto';
let compress;
let thumbImg;
if (imgType === 'tencent') {
const ratio = width / height;
const targetHeight = Math.round(targetSize / ratio);
thumbImg = cosUrl + `?imageView2/1/w/${targetSize}/h/${targetHeight}/q/55`;
}
if (imgType === 'ali') {
const ratio = height / width;
const targetWidth = Math.round(targetSize / ratio);
thumbImg = cosUrl + `?x-oss-process=image/resize,w_${targetWidth}`;
}
if (imgType === 'chevereto') {
thumbImg = cosUrl.replace(/\.png$/, '.md.png');
}
parseFileInfo.thumbImg = thumbImg;
if (!isSaveImg) {
const proxyImgUrl = `${mjProxyImgUrl}/mj/pipe?url=${originUrl}`;
parseFileInfo.thumbImg = proxyImgUrl;
parseFileInfo.cosUrl = proxyImgUrl;
}
return parseFileInfo;
}
async getDrawActionDetail(action, drawId, orderId) {
const detailInfo = await this.midjourneyEntity.findOne({ where: { id: drawId } });
if (!detailInfo)
throw new common_1.HttpException('当前绘画信息不存在!', common_1.HttpStatus.BAD_REQUEST);
const { extend, message_id, prompt, imgUrl, extraParam, randomDrawId } = detailInfo;
const historyDetailDrawInfo = JSON.parse(extend);
const { components = [] } = historyDetailDrawInfo;
if (!components.length) {
throw new common_1.HttpException('当前图片没有绘画信息、无法放大!', common_1.HttpStatus.BAD_REQUEST);
const detailInfo = await this.midjourneyEntity.findOne({ where: { drawId: drawId } });
const { extend, prompt, imgUrl, extraParam } = detailInfo;
const extendObj = JSON.parse(extend);
const buttons = extendObj.buttons || [];
let currentButton;
if (action === 'UPSCALE') {
currentButton = buttons.find(button => {
const isStandardUpscale = button.label.startsWith(`U${orderId}`);
const isUpscaleUpscale = (orderId === 1 && /(Redo )?Upscale \(Subtle\)/.test(button.label)) ||
(orderId === 2 && /(Redo )?Upscale \(Creative\)/.test(button.label));
return isStandardUpscale || isUpscaleUpscale;
});
}
let currentImgComponent = {};
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
currentImgComponent = components[0]['components'][orderId - 1];
if (action === 'VARIATION') {
currentButton = buttons.find(button => {
const isStandardVariation = button.label.startsWith(`V${orderId}`);
const isVaryVariation = (orderId === 1 && /Vary \(Strong\)/.test(button.label)) ||
(orderId === 2 && /Vary \(Region\)/.test(button.label));
return isStandardVariation || isVaryVariation;
});
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
currentImgComponent = components[1]['components'][orderId - 1];
if (action === 'REGENERATE') {
currentButton = buttons.find(button => button.customId.startsWith("MJ::JOB::reroll::0::") && button.label === "");
}
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
currentImgComponent = components[0]['components'][orderId - 1];
if (action === 'ZOOM') {
currentButton = buttons.find(button => (orderId === 1 && button.label === "Zoom Out 2x") ||
(orderId === 2 && button.label === "Zoom Out 1.5x"));
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
currentImgComponent = components[0]['components'][orderId - 1];
}
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
currentImgComponent = components[1]['components'][orderId - 1];
}
const { custom_id } = currentImgComponent;
return { custom_id, message_id, prompt, imgUrl, extraParam, randomDrawId };
}
async checkIsUpscale(custom_id) {
const count = await this.midjourneyEntity.count({ where: { custom_id, status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED } });
if (count > 0) {
throw new common_1.HttpException('当前图片已经放大过了!', common_1.HttpStatus.BAD_REQUEST);
if (!currentButton) {
throw new common_1.HttpException('所需绘画操作信息不存在!', common_1.HttpStatus.BAD_REQUEST);
}
const { customId } = currentButton;
return { customId, prompt, extraParam, drawId };
}
async deleteDraw(id, req) {
const d = await this.midjourneyEntity.findOne({ where: { id, userId: req.user.id, isDelete: 0 } });
@@ -759,7 +319,7 @@ let MidjourneyService = class MidjourneyService {
}
async drawSuccess(jobData) {
const { id, userId, action } = jobData;
const amount = action === 2 ? 1 : 4;
const amount = action === "UPSCALE" ? 1 : 4;
common_1.Logger.debug(`绘画完成,执行扣费,扣除费用:${amount}积分。`);
await this.userBalanceService.refundMjBalance(userId, -amount);
await this.midjourneyEntity.update({ id }, { status: 3 });
@@ -786,26 +346,13 @@ let MidjourneyService = class MidjourneyService {
order: { id: 'DESC' },
take: size,
skip: (page - 1) * size,
select: ['fileInfo', 'extend', 'prompt', 'createdAt', 'id', 'extend', 'fullPrompt', 'rec', 'isSaveImg'],
});
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
rows.forEach((item) => {
var _a, _b, _c, _d;
try {
const { extend, isSaveImg, fileInfo } = item;
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
item.originUrl = originUrl;
}
catch (error) {
}
select: ['id', 'drawId', 'drawUrl', 'drawRatio', 'prompt', 'fullPrompt', 'rec', 'createdAt', 'action', 'status'],
});
if (Number(size) === 999) {
const data = {
rows: rows.map((item) => {
const { fileInfo, prompt, createdAt, id, fullPrompt, rec, originUrl } = item;
return { fileInfo, prompt, createdAt, id, fullPrompt, rec, originUrl };
const { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status } = item;
return { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status };
}),
count,
};
@@ -840,19 +387,6 @@ let MidjourneyService = class MidjourneyService {
rows.forEach((item) => {
item.userInfo = userInfos.find((user) => user.id === item.userId);
});
const mjProxyImgUrl = await this.globalConfigService.getConfigs(['mjProxyImgUrl']);
rows.forEach((item) => {
var _a, _b, _c, _d;
try {
const { extend, isSaveImg, fileInfo } = item;
const originUrl = (_b = (_a = JSON.parse(extend)) === null || _a === void 0 ? void 0 : _a.attachments[0]) === null || _b === void 0 ? void 0 : _b.url;
item.fileInfo = this.formatFileInfo(fileInfo, isSaveImg, mjProxyImgUrl, originUrl);
item.isGroup = ((_d = (_c = JSON.parse(extend)) === null || _c === void 0 ? void 0 : _c.components[0]) === null || _d === void 0 ? void 0 : _d.components[0].label) === "U1";
item.originUrl = originUrl;
}
catch (error) {
}
});
if (req.user.role !== 'super') {
rows.forEach((item) => {
if (item.userInfo && item.userInfo.email) {
@@ -944,7 +478,6 @@ MidjourneyService = __decorate([
typeorm_2.Repository,
globalConfig_service_1.GlobalConfigService,
upload_service_1.UploadService,
badwords_service_1.BadwordsService,
userBalance_service_1.UserBalanceService,
redisCache_service_1.RedisCacheService])
], MidjourneyService);

View File

@@ -45,6 +45,10 @@ __decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: 'key的权重' }),
__metadata("design:type", Number)
], SetModelDto.prototype, "keyWeight", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '模型排序' }),
__metadata("design:type", Number)
], SetModelDto.prototype, "modelOrder", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 4096, description: '模型支持的最大TOken数量', required: true }),
__metadata("design:type", Number)

View File

@@ -42,6 +42,10 @@ __decorate([
(0, typeorm_1.Column)({ comment: '模型总计使用的token数量', default: 0 }),
__metadata("design:type", Number)
], ModelsTypeEntity.prototype, "useToken", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '模型排序', default: 1 }),
__metadata("design:type", Number)
], ModelsTypeEntity.prototype, "modelOrder", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '单词调用扣除的次数', default: 1 }),
__metadata("design:type", Number)

View File

@@ -50,6 +50,10 @@ __decorate([
(0, typeorm_1.Column)({ comment: 'key权重', default: 1 }),
__metadata("design:type", Number)
], ModelsEntity.prototype, "keyWeight", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'key权重', default: 1 }),
__metadata("design:type", Number)
], ModelsEntity.prototype, "modelOrder", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'key的使用次数', default: 0 }),
__metadata("design:type", Number)

View File

@@ -18,7 +18,6 @@ const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const models_entity_1 = require("./models.entity");
const status_constant_1 = require("../../common/constants/status.constant");
const baidu_1 = require("../chatgpt/baidu");
const utils_1 = require("../../common/utils");
const modelType_entity_1 = require("./modelType.entity");
let ModelsService = class ModelsService {
@@ -33,7 +32,6 @@ let ModelsService = class ModelsService {
}
async onModuleInit() {
await this.initCalcKey();
this.refreshBaiduAccesstoken();
}
async initCalcKey() {
this.keyPoolMap = {};
@@ -114,9 +112,6 @@ let ModelsService = class ModelsService {
if (Number(keyType !== 1)) {
const res = await this.modelsEntity.save(params);
await this.initCalcKey();
if (keyType === 2) {
this.refreshBaiduAccesstoken();
}
return res;
}
else {
@@ -162,6 +157,9 @@ let ModelsService = class ModelsService {
key && (where.key = (0, typeorm_2.Like)(`%${key}%`));
const [rows, count] = await this.modelsEntity.findAndCount({
where: where,
order: {
modelOrder: 'ASC'
},
skip: (page - 1) * size,
take: size,
});
@@ -176,10 +174,13 @@ let ModelsService = class ModelsService {
async modelsList() {
const cloneModelMaps = JSON.parse(JSON.stringify(this.modelMaps));
Object.keys(cloneModelMaps).forEach(key => {
cloneModelMaps[key] = Array.from(cloneModelMaps[key].map(t => {
cloneModelMaps[key] = cloneModelMaps[key].sort((a, b) => a.modelOrder - b.modelOrder);
cloneModelMaps[key] = Array.from(cloneModelMaps[key]
.map(t => {
const { modelName, model, deduct, deductType, maxRounds } = t;
return { modelName, model, deduct, deductType, maxRounds };
}).reduce((map, obj) => map.set(obj.modelName, obj), new Map()).values());
})
.reduce((map, obj) => map.set(obj.modelName, obj), new Map()).values());
});
return {
modelTypeList: this.modelTypes,
@@ -194,27 +195,6 @@ let ModelsService = class ModelsService {
.where('id = :id', { id })
.execute();
}
async refreshBaiduAccesstoken() {
const allKeys = await this.modelsEntity.find({ where: { keyType: 2 } });
const keysMap = {};
allKeys.forEach(keyInfo => {
const { key, secret } = keyInfo;
if (!keysMap.key) {
keysMap[key] = [{ keyInfo }];
}
else {
keysMap[key].push(keyInfo);
}
});
Object.keys(keysMap).forEach(async (key) => {
const { secret, id } = keysMap[key][0]['keyInfo'];
const accessToken = await (0, baidu_1.getAccessToken)(key, secret);
await this.modelsEntity.update({ key }, { accessToken });
});
setTimeout(() => {
this.initCalcKey();
}, 1000);
}
async getRandomDrawKey() {
const drawkeys = await this.modelsEntity.find({ where: { isDraw: true, status: true } });
if (!drawkeys.length) {

View File

@@ -34,9 +34,9 @@ __decorate([
__metadata("design:type", String)
], MjDrawDto.prototype, "imgUrl", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '绘画动作 绘图、放大、变换、图生图' }),
(0, swagger_1.ApiProperty)({ example: 'IMAGINE', description: '任务类型,可用值:IMAGINE,UPSCALE,VARIATION,ZOOM,PAN,DESCRIBE,BLEND,SHORTEN,SWAP_FACE' }),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", Number)
__metadata("design:type", String)
], MjDrawDto.prototype, "action", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '变体或者放大的序号' }),
@@ -48,4 +48,9 @@ __decorate([
(0, class_validator_1.IsOptional)(),
__metadata("design:type", Number)
], MjDrawDto.prototype, "drawId", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '任务ID' }),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", Number)
], MjDrawDto.prototype, "taskId", void 0);
exports.MjDrawDto = MjDrawDto;

View File

@@ -17,7 +17,6 @@ const common_1 = require("@nestjs/common");
const bull_1 = require("@nestjs/bull");
const utils_1 = require("../../common/utils");
const midjourney_service_1 = require("../midjourney/midjourney.service");
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
let QueueService = class QueueService {
@@ -33,68 +32,31 @@ let QueueService = class QueueService {
await this.midjourneyService.cleanQueue();
}
async addMjDrawQueue(body, req) {
const { prompt, imgUrl, extraParam, orderId, action = 1, drawId } = body;
const { imgUrl, orderId, action, drawId } = body;
await this.midjourneyService.checkLimit(req);
await this.userBalanceService.validateBalance(req, 'mjDraw', action === 2 ? 1 : 4);
if (action === midjourney_constant_1.MidjourneyActionEnum.DRAW || action === midjourney_constant_1.MidjourneyActionEnum.GENERATE) {
await this.userBalanceService.validateBalance(req, 'mjDraw', action === 'UPSCALE' ? 1 : 4);
if (action === 'IMAGINE') {
const randomDrawId = `${(0, utils_1.createRandomUid)()}`;
const params = Object.assign(Object.assign({}, body), { userId: req.user.id, randomDrawId });
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action: imgUrl ? 4 : 1, userId: req.user.id }, { delay: 1000, timeout: +timeout });
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action: action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return true;
}
else {
const { orderId, action, drawId } = body;
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
if (!drawId || !orderId) {
throw new common_1.HttpException('缺少必要参数!', common_1.HttpStatus.BAD_REQUEST);
}
if (action === midjourney_constant_1.MidjourneyActionEnum.UPSCALE) {
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const { custom_id } = actionDetail;
await this.midjourneyService.checkIsUpscale(custom_id);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARIATION) {
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
if (action === midjourney_constant_1.MidjourneyActionEnum.REGENERATE) {
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
if (action === midjourney_constant_1.MidjourneyActionEnum.VARY) {
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
if (action === midjourney_constant_1.MidjourneyActionEnum.ZOOM) {
const actionDetail = await this.midjourneyService.getDrawActionDetail(action, drawId, orderId);
const params = Object.assign(Object.assign(Object.assign({}, body), { userId: req.user.id }), actionDetail);
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
}
async getQueue() {
return { jobIds: this.jobIds };

View File

@@ -44,9 +44,6 @@ let TaskService = class TaskService {
});
});
}
refreshBaiduAccesstoken() {
this.modelsService.refreshBaiduAccesstoken();
}
};
__decorate([
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_HOUR),
@@ -60,12 +57,6 @@ __decorate([
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], TaskService.prototype, "checkUserMemerExpire", null);
__decorate([
(0, schedule_1.Cron)('0 0 */5 * *'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TaskService.prototype, "refreshBaiduAccesstoken", null);
TaskService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(userBalance_entity_1.UserBalanceEntity)),

View File

@@ -27,19 +27,30 @@ let UploadService = class UploadService {
const { filename: name, originalname, buffer, dir = 'ai', mimetype } = file;
const fileTyle = mimetype ? mimetype.split('/')[1] : '';
const filename = originalname || name;
common_1.Logger.debug(`准备上传文件: ${filename}, 类型: ${fileTyle}`, 'UploadService');
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs(['tencentCosStatus', 'aliOssStatus', 'cheveretoStatus']);
common_1.Logger.debug(`上传配置状态 - 腾讯云: ${tencentCosStatus}, 阿里云: ${aliOssStatus}, Chevereto: ${cheveretoStatus}`, 'UploadService');
if (!Number(tencentCosStatus) && !Number(aliOssStatus) && !Number(cheveretoStatus)) {
throw new common_1.HttpException('请先前往后台配置上传图片的方式', common_1.HttpStatus.BAD_REQUEST);
}
if (Number(tencentCosStatus)) {
return this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle });
try {
if (Number(tencentCosStatus)) {
common_1.Logger.debug(`使用腾讯云COS上传`, 'UploadService');
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle });
}
if (Number(aliOssStatus)) {
common_1.Logger.debug(`使用阿里云OSS上传`, 'UploadService');
return await this.uploadFileByAliOss({ filename, buffer, dir, fileTyle });
}
if (Number(cheveretoStatus)) {
common_1.Logger.debug(`使用Chevereto上传`, 'UploadService');
const { filename, buffer: fromBuffer, dir } = file;
return await this.uploadFileByChevereto({ filename, buffer: fromBuffer.toString('base64'), dir, fileTyle });
}
}
if (Number(aliOssStatus)) {
return await this.uploadFileByAliOss({ filename, buffer, dir, fileTyle });
}
if (Number(cheveretoStatus)) {
const { filename, buffer: fromBuffer, dir } = file;
return await this.uploadFileByChevereto({ filename, buffer: fromBuffer.toString('base64'), dir, fileTyle });
catch (error) {
common_1.Logger.error(`上传失败: ${error.message}`, 'UploadService');
throw error;
}
}
async getUploadType() {
@@ -108,24 +119,8 @@ let UploadService = class UploadService {
this.tencentCos = new TENCENTCOS({ SecretId, SecretKey, FileParallelLimit: 10 });
try {
const proxyMj = (await this.globalConfigService.getConfigs(['mjProxy'])) || 0;
if (Number(proxyMj) === 1) {
const data = { cosType: 'tencent', url, cosParams: { Bucket, Region, SecretId, SecretKey } };
const mjProxyUrl = (await this.globalConfigService.getConfigs(['mjProxyUrl'])) || 'http://172.247.48.137:8000';
const res = await axios_1.default.post(`${mjProxyUrl}/mj/replaceUpload`, data);
if (!res.data)
throw new common_1.HttpException('上传图片失败[ten][url]', common_1.HttpStatus.BAD_REQUEST);
let locationUrl = res.data.replace(/^(http:\/\/|https:\/\/|\/\/|)(.*)/, 'https://$2');
const { acceleratedDomain } = await this.getUploadConfig('tencent');
if (acceleratedDomain) {
locationUrl = locationUrl.replace(/^(https:\/\/[^/]+)(\/.*)$/, `https://${acceleratedDomain}$2`);
console.log('当前已开启全球加速----------------->');
}
return locationUrl;
}
else {
const buffer = await this.getBufferFromUrl(url);
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle: '' });
}
const buffer = await this.getBufferFromUrl(url);
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle: '' });
}
catch (error) {
console.log('TODO->error: ', error);