mirror of
https://github.com/vastxie/99AI.git
synced 2025-11-13 20:23:43 +08:00
v3.7.0
This commit is contained in:
34
dist/modules/ai/lumaVideo.service.js
vendored
34
dist/modules/ai/lumaVideo.service.js
vendored
@@ -13,9 +13,13 @@ exports.LumaVideoService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const axios_1 = require("axios");
|
||||
const chatLog_service_1 = require("../chatLog/chatLog.service");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
const upload_service_1 = require("../upload/upload.service");
|
||||
let LumaVideoService = class LumaVideoService {
|
||||
constructor(chatLogService) {
|
||||
constructor(chatLogService, globalConfigService, uploadService) {
|
||||
this.chatLogService = chatLogService;
|
||||
this.globalConfigService = globalConfigService;
|
||||
this.uploadService = uploadService;
|
||||
}
|
||||
async lumaVideo(inputs) {
|
||||
var _a, _b, _c;
|
||||
@@ -32,12 +36,15 @@ let LumaVideoService = class LumaVideoService {
|
||||
let payloadJson = {};
|
||||
const headers = { Authorization: `Bearer ${apiKey}` };
|
||||
url = `${proxyUrl}/luma/generations/`;
|
||||
const aspectRatio = '16:9';
|
||||
const aspectRatio = extraParam.size || '16:9';
|
||||
payloadJson = {
|
||||
user_prompt: prompt,
|
||||
aspect_ratio: aspectRatio,
|
||||
expand_prompt: true,
|
||||
};
|
||||
if (fileInfo) {
|
||||
payloadJson['image_url'] = fileInfo;
|
||||
}
|
||||
common_1.Logger.log(`正在准备发送请求到 ${url},payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`, 'LumaService');
|
||||
try {
|
||||
response = await axios_1.default.post(url, payloadJson, { headers });
|
||||
@@ -150,6 +157,25 @@ let LumaVideoService = class LumaVideoService {
|
||||
result.taskId = responses.id;
|
||||
result.taskData = JSON.stringify(responses);
|
||||
result.fileInfo = responses.video.url;
|
||||
try {
|
||||
const localStorageStatus = await this.globalConfigService.getConfigs([
|
||||
'localStorageStatus',
|
||||
]);
|
||||
if (Number(localStorageStatus)) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const currentDate = `${year}${month}/${day}`;
|
||||
result.fileInfo = await this.uploadService.uploadFileFromUrl({
|
||||
url: responses.video.download_url,
|
||||
dir: `video/luma/${currentDate}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传文件失败: ${error.message}`, 'LumaService');
|
||||
}
|
||||
result.answer = `提示词: "${responses.prompt}"`;
|
||||
onSuccess(result);
|
||||
clearInterval(interval);
|
||||
@@ -180,6 +206,8 @@ let LumaVideoService = class LumaVideoService {
|
||||
};
|
||||
LumaVideoService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService])
|
||||
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService,
|
||||
globalConfig_service_1.GlobalConfigService,
|
||||
upload_service_1.UploadService])
|
||||
], LumaVideoService);
|
||||
exports.LumaVideoService = LumaVideoService;
|
||||
|
||||
54
dist/modules/ai/midjourneyDraw.service.js
vendored
54
dist/modules/ai/midjourneyDraw.service.js
vendored
@@ -22,8 +22,8 @@ let MidjourneyService = class MidjourneyService {
|
||||
this.chatLogService = chatLogService;
|
||||
}
|
||||
async midjourneyDraw(inputs) {
|
||||
var _a, _b;
|
||||
const { id, apiKey, proxyUrl, action, drawId, prompt, usePrompt, customId, timeout, assistantLogId, } = inputs;
|
||||
var _a, _b, _c, _d;
|
||||
const { id, apiKey, proxyUrl, action, drawId, prompt, usePrompt, customId, timeout, fileInfo, assistantLogId, } = inputs;
|
||||
let result = {
|
||||
text: '',
|
||||
fileInfo: '',
|
||||
@@ -34,6 +34,8 @@ let MidjourneyService = class MidjourneyService {
|
||||
let response;
|
||||
let retryCount = 0;
|
||||
let url = '';
|
||||
const headers = { 'mj-api-secret': apiKey };
|
||||
common_1.Logger.debug(`当前任务类型: ${action}`, 'MidjourneyService');
|
||||
while (retryCount < 3) {
|
||||
let payloadJson = {};
|
||||
try {
|
||||
@@ -41,15 +43,40 @@ let MidjourneyService = class MidjourneyService {
|
||||
url = `${proxyUrl}/mj/submit/imagine`;
|
||||
payloadJson = { prompt: usePrompt };
|
||||
}
|
||||
else if (action === 'DESCRIBE') {
|
||||
url = `${proxyUrl}/mj/submit/describe`;
|
||||
if (fileInfo) {
|
||||
const response = await fetch(fileInfo);
|
||||
const blob = await response.blob();
|
||||
const buffer = Buffer.from(await blob.arrayBuffer());
|
||||
const base64String = buffer.toString('base64');
|
||||
payloadJson = { base64: `data:image/png;base64,${base64String}` };
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (action === 'PICREADER') {
|
||||
url = `${proxyUrl}/mj/submit/action`;
|
||||
payloadJson = { taskId: drawId, customId: customId };
|
||||
response = await axios_1.default.post(url, payloadJson, { headers });
|
||||
if ((response === null || response === void 0 ? void 0 : response.status) === 200 && ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.result)) {
|
||||
url = `${proxyUrl}/mj/submit/modal`;
|
||||
payloadJson = { taskId: (_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.result };
|
||||
}
|
||||
}
|
||||
else {
|
||||
url = `${proxyUrl}/mj/submit/action`;
|
||||
payloadJson = { taskId: drawId, customId: customId };
|
||||
}
|
||||
const headers = { 'mj-api-secret': apiKey };
|
||||
common_1.Logger.log(`正在准备发送请求到 ${url},payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`, 'MidjourneyService');
|
||||
response = await axios_1.default.post(url, payloadJson, { headers });
|
||||
if ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.result) {
|
||||
result.drawId = (_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.result;
|
||||
if ((response === null || response === void 0 ? void 0 : response.status) === 200 && ((_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.result)) {
|
||||
common_1.Logger.debug(`收到响应: ${JSON.stringify(response.data)}`, 'MidjourneyService');
|
||||
result.drawId = (_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.result;
|
||||
result.state = 2;
|
||||
result.answer = '绘画任务提交成功';
|
||||
common_1.Logger.log(`绘画任务提交成功, 绘画ID: ${response.data.result}`, 'MidjourneyService');
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@@ -59,6 +86,8 @@ let MidjourneyService = class MidjourneyService {
|
||||
catch (error) {
|
||||
retryCount++;
|
||||
if (retryCount >= 3) {
|
||||
result.answer = '任务提交失败,请检查提示词后重试';
|
||||
result.status = 5;
|
||||
common_1.Logger.log(`绘画任务提交失败, 请检查后台配置或者稍后重试! ${error}`, 'MidjourneyService');
|
||||
}
|
||||
}
|
||||
@@ -66,7 +95,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
this.pollMjDrawingResult({
|
||||
proxyUrl,
|
||||
apiKey,
|
||||
drawId: response.data.result,
|
||||
drawId: result.drawId,
|
||||
timeout,
|
||||
prompt,
|
||||
onSuccess: async (data) => {
|
||||
@@ -78,7 +107,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
drawId: data === null || data === void 0 ? void 0 : data.drawId,
|
||||
customId: data === null || data === void 0 ? void 0 : data.customId,
|
||||
});
|
||||
common_1.Logger.log('绘图成功!');
|
||||
common_1.Logger.log('绘图成功!', 'MidjourneyService');
|
||||
},
|
||||
onDrawing: async (data) => {
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
@@ -86,19 +115,18 @@ let MidjourneyService = class MidjourneyService {
|
||||
progress: data === null || data === void 0 ? void 0 : data.progress,
|
||||
status: 2,
|
||||
});
|
||||
common_1.Logger.log(`绘制中!绘制进度${data === null || data === void 0 ? void 0 : data.progress}`);
|
||||
common_1.Logger.log(`绘制中!绘制进度${data === null || data === void 0 ? void 0 : data.progress}`, 'MidjourneyService');
|
||||
},
|
||||
onFailure: async (data) => {
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
answer: '绘图失败',
|
||||
status: data.status,
|
||||
});
|
||||
common_1.Logger.log('绘图失败');
|
||||
common_1.Logger.log('绘图失败', 'MidjourneyService');
|
||||
},
|
||||
}).catch((error) => {
|
||||
common_1.Logger.error('查询绘图结果时发生错误:', error, 'MidjourneyService');
|
||||
});
|
||||
common_1.Logger.log(`绘画任务提交成功, 绘画ID: ${response.data.result}`, 'MidjourneyService');
|
||||
return result;
|
||||
}
|
||||
async pollMjDrawingResult(inputs) {
|
||||
@@ -108,7 +136,6 @@ let MidjourneyService = class MidjourneyService {
|
||||
'mjProxyImgUrl',
|
||||
'mjNotUseProxy',
|
||||
]);
|
||||
let response;
|
||||
let result = {
|
||||
fileInfo: '',
|
||||
drawId: '',
|
||||
@@ -117,11 +144,9 @@ let MidjourneyService = class MidjourneyService {
|
||||
progress: 0,
|
||||
answer: '',
|
||||
};
|
||||
let payloadJson = {};
|
||||
const startTime = Date.now();
|
||||
const POLL_INTERVAL = 5000;
|
||||
let retryCount = 0;
|
||||
let pollingCount = 0;
|
||||
try {
|
||||
while (Date.now() - startTime < timeout) {
|
||||
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
|
||||
@@ -133,6 +158,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
const url = `${proxyUrl}/mj/task/${drawId}/fetch`;
|
||||
const res = await axios_1.default.get(url, { headers });
|
||||
const responses = res.data;
|
||||
common_1.Logger.debug(`查询结果: ${JSON.stringify(responses)}`, 'MidjourneyService');
|
||||
if (responses.status === 'SUCCESS') {
|
||||
common_1.Logger.log(`绘制成功, 获取到的URL: ${responses.imageUrl}`, 'MidjourneyService');
|
||||
let processedUrl = responses.imageUrl;
|
||||
@@ -150,7 +176,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
}
|
||||
if (mjNotSaveImg !== '1') {
|
||||
try {
|
||||
common_1.Logger.log(`------> 开始上传图片!!!`);
|
||||
common_1.Logger.log(`------> 开始上传图片!!!`, 'MidjourneyService');
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
|
||||
30
dist/modules/ai/openaiDraw.service.js
vendored
30
dist/modules/ai/openaiDraw.service.js
vendored
@@ -25,10 +25,34 @@ let OpenAIDrawService = OpenAIDrawService_1 = class OpenAIDrawService {
|
||||
this.openAIChatService = openAIChatService;
|
||||
this.logger = new common_1.Logger(OpenAIDrawService_1.name);
|
||||
}
|
||||
async dalleDraw(inputs, messagesHistory) {
|
||||
async dalleDraw(inputs, buildMessageFromParentMessageId) {
|
||||
var _a, _b, _c, _d;
|
||||
common_1.Logger.log('开始提交 Dalle 绘图任务 ', 'DrawService');
|
||||
const { apiKey, model, proxyUrl, prompt, extraParam, timeout, onSuccess, onFailure, } = inputs;
|
||||
const { apiKey, model, proxyUrl, prompt, extraParam, timeout, onSuccess, onFailure, groupId, } = inputs;
|
||||
const isDalleChat = await this.globalConfigService.getConfigs([
|
||||
'isDalleChat',
|
||||
]);
|
||||
let drawPrompt;
|
||||
if (isDalleChat === '1') {
|
||||
try {
|
||||
common_1.Logger.log('已开启连续绘画模式', 'DalleDraw');
|
||||
const { messagesHistory } = await buildMessageFromParentMessageId(`参考上文,结合我的需求,给出绘画描述。我的需求是:${prompt}`, {
|
||||
groupId,
|
||||
systemMessage: '你是一个绘画提示词生成工具,请根据用户的要求,结合上下文,用一段文字,描述用户需要的绘画需求,不用包含任何礼貌性的寒暄,只需要场景的描述,可以适当联想',
|
||||
maxModelTokens: 8000,
|
||||
maxRounds: 5,
|
||||
fileInfo: '',
|
||||
}, this.chatLogService);
|
||||
drawPrompt = await this.openAIChatService.chatFree(prompt, undefined, messagesHistory);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('调用chatFree失败:', error);
|
||||
drawPrompt = prompt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawPrompt = prompt;
|
||||
}
|
||||
const size = (extraParam === null || extraParam === void 0 ? void 0 : extraParam.size) || '1024x1024';
|
||||
let result = { answer: '', fileInfo: '', status: 2 };
|
||||
try {
|
||||
@@ -42,7 +66,7 @@ let OpenAIDrawService = OpenAIDrawService_1 = class OpenAIDrawService {
|
||||
},
|
||||
data: {
|
||||
model: model,
|
||||
prompt: prompt,
|
||||
prompt: drawPrompt,
|
||||
size,
|
||||
},
|
||||
};
|
||||
|
||||
20
dist/modules/ai/stableDiffusion.service.js
vendored
20
dist/modules/ai/stableDiffusion.service.js
vendored
@@ -24,7 +24,7 @@ let StableDiffusionService = StableDiffusionService_1 = class StableDiffusionSer
|
||||
this.logger = new common_1.Logger(StableDiffusionService_1.name);
|
||||
}
|
||||
async sdxl(messagesHistory, inputs) {
|
||||
const { onGenerate, onSuccess, onFailure, apiKey, model, proxyUrl, modelName, timeout, chatId, isFileUpload, prompt, } = inputs;
|
||||
const { onSuccess, onFailure, apiKey, model, proxyUrl, modelName, timeout, chatId, prompt, } = inputs;
|
||||
let result = {
|
||||
answer: '',
|
||||
model: model,
|
||||
@@ -58,12 +58,28 @@ let StableDiffusionService = StableDiffusionService_1 = class StableDiffusionSer
|
||||
const match = content.match(regex);
|
||||
if (match && match[1]) {
|
||||
result.fileInfo = match[1];
|
||||
try {
|
||||
const localStorageStatus = await this.globalConfigService.getConfigs(['localStorageStatus']);
|
||||
if (Number(localStorageStatus)) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const currentDate = `${year}${month}/${day}`;
|
||||
result.fileInfo = await this.uploadService.uploadFileFromUrl({
|
||||
url: result.fileInfo,
|
||||
dir: `images/stable-diffusion/${currentDate}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传文件失败: ${error.message}`, 'StableDiffusionService');
|
||||
}
|
||||
console.log('找到链接', match[1]);
|
||||
}
|
||||
else {
|
||||
console.log('没有找到链接');
|
||||
}
|
||||
let revised_prompt_cn;
|
||||
result.answer = `${prompt} 绘制成功`;
|
||||
if (result.fileInfo) {
|
||||
onSuccess(result);
|
||||
|
||||
118
dist/modules/ai/suno.service.js
vendored
118
dist/modules/ai/suno.service.js
vendored
@@ -13,9 +13,13 @@ exports.SunoService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const axios_1 = require("axios");
|
||||
const chatLog_service_1 = require("../chatLog/chatLog.service");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
const upload_service_1 = require("../upload/upload.service");
|
||||
let SunoService = class SunoService {
|
||||
constructor(chatLogService) {
|
||||
constructor(chatLogService, uploadService, globalConfigService) {
|
||||
this.chatLogService = chatLogService;
|
||||
this.uploadService = uploadService;
|
||||
this.globalConfigService = globalConfigService;
|
||||
}
|
||||
async suno(inputs) {
|
||||
var _a, _b, _c;
|
||||
@@ -46,7 +50,7 @@ let SunoService = class SunoService {
|
||||
throw new Error('taskData格式错误');
|
||||
}
|
||||
}
|
||||
common_1.Logger.log(`正在准备发送请求到 ${url},payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`);
|
||||
common_1.Logger.log(`正在准备发送请求到 ${url},payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`, 'SunoService');
|
||||
try {
|
||||
response = await axios_1.default.post(url, payloadJson, { headers });
|
||||
}
|
||||
@@ -164,6 +168,7 @@ let SunoService = class SunoService {
|
||||
try {
|
||||
const res = await axios_1.default.get(url, { headers });
|
||||
const responses = res.data.data;
|
||||
common_1.Logger.debug(`轮询结果: ${JSON.stringify(responses)}`, 'SunoService');
|
||||
if (action === 'LYRICS') {
|
||||
if (responses.status === 'SUCCESS') {
|
||||
result.taskId = responses.data.id;
|
||||
@@ -179,7 +184,6 @@ let SunoService = class SunoService {
|
||||
}
|
||||
}
|
||||
if (action === 'MUSIC') {
|
||||
const data = responses.data;
|
||||
if (responses.data) {
|
||||
const data = responses.data;
|
||||
result.taskData = JSON.stringify(data);
|
||||
@@ -195,30 +199,100 @@ let SunoService = class SunoService {
|
||||
.filter((url) => url);
|
||||
const titles = data.map((item) => item.title);
|
||||
const firstTitle = titles.length > 0 ? titles[0] : '音乐已生成';
|
||||
const audioUrls = validAudioUrls.join(',');
|
||||
const videoUrls = validVideoUrls.join(',');
|
||||
const imageUrls = validImageUrls.join(',');
|
||||
result.audioUrl = audioUrls;
|
||||
result.videoUrl = videoUrls;
|
||||
result.fileInfo = imageUrls;
|
||||
if (validAudioUrls.length === 2) {
|
||||
result.status = 3;
|
||||
result.answer = firstTitle;
|
||||
if (responses.status === 'SUCCESS') {
|
||||
let audioUrls = [];
|
||||
let videoUrls = [];
|
||||
let imageUrls = [];
|
||||
try {
|
||||
const localStorageStatus = await this.globalConfigService.getConfigs([
|
||||
'localStorageStatus',
|
||||
]);
|
||||
if (Number(localStorageStatus)) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const currentDate = `${year}${month}/${day}`;
|
||||
for (const url of validAudioUrls) {
|
||||
try {
|
||||
const uploadedUrl = await this.uploadService.uploadFileFromUrl({
|
||||
url: url,
|
||||
dir: `audio/suno-music/${currentDate}`,
|
||||
});
|
||||
audioUrls.push(uploadedUrl);
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传音频文件失败: ${error.message}`, 'SunoService');
|
||||
audioUrls.push(url);
|
||||
}
|
||||
}
|
||||
for (const url of validVideoUrls) {
|
||||
try {
|
||||
const uploadedUrl = await this.uploadService.uploadFileFromUrl({
|
||||
url: url,
|
||||
dir: `video/suno-music/${currentDate}`,
|
||||
});
|
||||
videoUrls.push(uploadedUrl);
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传视频文件失败: ${error.message}`, 'SunoService');
|
||||
videoUrls.push(url);
|
||||
}
|
||||
}
|
||||
for (const url of validImageUrls) {
|
||||
try {
|
||||
const uploadedUrl = await this.uploadService.uploadFileFromUrl({
|
||||
url: url,
|
||||
dir: `images/suno-music/${currentDate}`,
|
||||
});
|
||||
imageUrls.push(uploadedUrl);
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`上传图片文件失败: ${error.message}`, 'SunoService');
|
||||
imageUrls.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
audioUrls = validAudioUrls;
|
||||
videoUrls = validVideoUrls;
|
||||
imageUrls = validImageUrls;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`获取配置失败: ${error.message}`, 'LumaService');
|
||||
audioUrls = validAudioUrls;
|
||||
videoUrls = validVideoUrls;
|
||||
imageUrls = validImageUrls;
|
||||
}
|
||||
result.audioUrl = audioUrls.join(',');
|
||||
result.videoUrl = videoUrls.join(',');
|
||||
result.fileInfo = imageUrls.join(',');
|
||||
if (validAudioUrls.length === 2) {
|
||||
result.status = 3;
|
||||
result.answer = firstTitle;
|
||||
}
|
||||
else {
|
||||
result.status = 2;
|
||||
result.progress = responses === null || responses === void 0 ? void 0 : responses.progress;
|
||||
result.answer = `当前生成进度 ${responses === null || responses === void 0 ? void 0 : responses.progress}`;
|
||||
}
|
||||
common_1.Logger.debug(`音乐生成成功: ${JSON.stringify(data)}`, 'SunoService');
|
||||
onSuccess(result);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
result.audioUrl = validAudioUrls.join(',');
|
||||
result.videoUrl = validVideoUrls.join(',');
|
||||
result.fileInfo = validImageUrls.join(',');
|
||||
result.status = 2;
|
||||
result.progress = responses === null || responses === void 0 ? void 0 : responses.progress;
|
||||
result.answer = `当前生成进度 ${responses === null || responses === void 0 ? void 0 : responses.progress}`;
|
||||
result.answer = firstTitle;
|
||||
onAudioSuccess(result);
|
||||
}
|
||||
onAudioSuccess(result);
|
||||
}
|
||||
}
|
||||
if (responses.status === 'SUCCESS') {
|
||||
common_1.Logger.debug(`音乐生成成功: ${JSON.stringify(data)}`, 'SunoService');
|
||||
onSuccess(result);
|
||||
return;
|
||||
}
|
||||
if (result.progress && result.status === 2) {
|
||||
if (!result.audioUrl && result.progress && result.status === 2) {
|
||||
onGenerating(result);
|
||||
}
|
||||
}
|
||||
@@ -242,6 +316,8 @@ let SunoService = class SunoService {
|
||||
};
|
||||
SunoService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService])
|
||||
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService,
|
||||
upload_service_1.UploadService,
|
||||
globalConfig_service_1.GlobalConfigService])
|
||||
], SunoService);
|
||||
exports.SunoService = SunoService;
|
||||
|
||||
2
dist/modules/app/app.service.js
vendored
2
dist/modules/app/app.service.js
vendored
@@ -300,7 +300,6 @@ let AppService = class AppService {
|
||||
}
|
||||
async updateSystemApp(body) {
|
||||
const { id, name } = body;
|
||||
common_1.Logger.log(`尝试更新应用: ${name} (ID: ${id})`);
|
||||
const existingApp = await this.appEntity.findOne({
|
||||
where: { name, id: (0, typeorm_2.Not)(id) },
|
||||
});
|
||||
@@ -310,7 +309,6 @@ let AppService = class AppService {
|
||||
}
|
||||
const res = await this.appEntity.update({ id }, body);
|
||||
if (res.affected > 0) {
|
||||
common_1.Logger.log(`修改系统应用信息成功: ${name}`);
|
||||
return '修改系统应用信息成功';
|
||||
}
|
||||
common_1.Logger.error(`修改系统应用信息失败:${name}`);
|
||||
|
||||
11
dist/modules/auth/auth.controller.js
vendored
11
dist/modules/auth/auth.controller.js
vendored
@@ -43,9 +43,6 @@ let AuthController = class AuthController {
|
||||
async getInfo(req) {
|
||||
return this.authService.getInfo(req);
|
||||
}
|
||||
async captcha(parmas) {
|
||||
return this.authService.captcha(parmas);
|
||||
}
|
||||
async sendCode(parmas) {
|
||||
return this.authService.sendCode(parmas);
|
||||
}
|
||||
@@ -109,14 +106,6 @@ __decorate([
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "getInfo", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('captcha'),
|
||||
(0, swagger_1.ApiOperation)({ summary: '获取一个图形验证码' }),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "captcha", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('sendCode'),
|
||||
(0, swagger_1.ApiOperation)({ summary: '发送验证码' }),
|
||||
|
||||
33
dist/modules/auth/auth.service.js
vendored
33
dist/modules/auth/auth.service.js
vendored
@@ -21,7 +21,6 @@ const jwt_1 = require("@nestjs/jwt");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const bcrypt = require("bcryptjs");
|
||||
const os = require("os");
|
||||
const svgCaptcha = require("svg-captcha");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const config_entity_1 = require("../globalConfig/config.entity");
|
||||
const mailer_service_1 = require("../mailer/mailer.service");
|
||||
@@ -44,7 +43,6 @@ let AuthService = class AuthService {
|
||||
this.getIp();
|
||||
}
|
||||
async register(body, req) {
|
||||
await this.verificationService.verifyCaptcha(body);
|
||||
const { password, contact, code, invitedBy } = body;
|
||||
let email = '', phone = '';
|
||||
const isEmail = /\S+@\S+\.\S+/.test(contact);
|
||||
@@ -99,11 +97,11 @@ let AuthService = class AuthService {
|
||||
throw new common_1.HttpException('请输入验证码', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (!redisCode) {
|
||||
common_1.Logger.log(`验证码过期: ${contact}`);
|
||||
common_1.Logger.log(`验证码过期: ${contact}`, 'authService');
|
||||
throw new common_1.HttpException('验证码已过期,请重新发送!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (code !== redisCode) {
|
||||
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`);
|
||||
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`, 'authService');
|
||||
throw new common_1.HttpException('验证码填写错误,请重新输入!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -197,11 +195,11 @@ let AuthService = class AuthService {
|
||||
const key = `${nameSpace}:CODE:${contact}`;
|
||||
const redisCode = await this.redisCacheService.get({ key });
|
||||
if (!redisCode) {
|
||||
common_1.Logger.log(`验证码过期: ${contact}`);
|
||||
common_1.Logger.log(`验证码过期: ${contact}`, 'authService');
|
||||
throw new common_1.HttpException('验证码已过期,请重新发送!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (code !== redisCode) {
|
||||
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`);
|
||||
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`, 'authService');
|
||||
throw new common_1.HttpException('验证码填写错误,请重新输入!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
let u;
|
||||
@@ -292,28 +290,6 @@ let AuthService = class AuthService {
|
||||
});
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
async captcha(parmas) {
|
||||
const nameSpace = await this.globalConfigService.getNamespace();
|
||||
const { color = '#fff' } = parmas;
|
||||
const captcha = svgCaptcha.create({
|
||||
size: 4,
|
||||
ignoreChars: '0o1i',
|
||||
noise: 4,
|
||||
color: true,
|
||||
background: color,
|
||||
height: 35,
|
||||
width: 120,
|
||||
charPreset: 'abcdefghijklmnopqrstuvwxyz',
|
||||
});
|
||||
const text = captcha.text;
|
||||
const randomId = Math.random().toString(36).substr(2, 9);
|
||||
const key = `${nameSpace}:CAPTCHA:${randomId}`;
|
||||
await this.redisCacheService.set({ key, val: text }, 5 * 60);
|
||||
return {
|
||||
svgCode: captcha.data,
|
||||
code: randomId,
|
||||
};
|
||||
}
|
||||
async sendCode(body) {
|
||||
const { contact, isLogin } = body;
|
||||
let email = '', phone = '';
|
||||
@@ -324,7 +300,6 @@ let AuthService = class AuthService {
|
||||
throw new common_1.HttpException('请提供有效的邮箱地址或手机号码。', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (!isLogin) {
|
||||
await this.verificationService.verifyCaptcha(body);
|
||||
if (isEmail) {
|
||||
email = contact;
|
||||
const isAvailable = await this.userService.verifyUserRegister({
|
||||
|
||||
10
dist/modules/auth/dto/authRegister.dto.js
vendored
10
dist/modules/auth/dto/authRegister.dto.js
vendored
@@ -29,16 +29,6 @@ __decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 'ai@aiweb.com', description: '用户邮箱' }),
|
||||
__metadata("design:type", String)
|
||||
], UserRegisterDto.prototype, "email", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: '5k3n', description: '图形验证码' }),
|
||||
(0, class_validator_1.IsNotEmpty)({ message: '验证码为空!' }),
|
||||
__metadata("design:type", String)
|
||||
], UserRegisterDto.prototype, "captchaCode", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: '2313ko423ko', description: '图形验证码KEY' }),
|
||||
(0, class_validator_1.IsNotEmpty)({ message: '验证ID不能为空!' }),
|
||||
__metadata("design:type", String)
|
||||
], UserRegisterDto.prototype, "captchaId", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({
|
||||
example: 'FRJDLJHFNV',
|
||||
|
||||
@@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UserRegisterByPhoneDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const class_validator_1 = require("class-validator");
|
||||
class UserRegisterByPhoneDto {
|
||||
}
|
||||
__decorate([
|
||||
|
||||
16
dist/modules/autoreply/autoreply.controller.js
vendored
16
dist/modules/autoreply/autoreply.controller.js
vendored
@@ -13,15 +13,15 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AutoreplyController = void 0;
|
||||
const autoreply_service_1 = require("./autoreply.service");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const queryAutoReply_dto_1 = require("./dto/queryAutoReply.dto");
|
||||
const addAutoReply_dto_1 = require("./dto/addAutoReply.dto");
|
||||
const updateAutoReply_dto_1 = require("./dto/updateAutoReply.dto");
|
||||
const delBadWords_dto_1 = require("./dto/delBadWords.dto");
|
||||
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
|
||||
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const autoreply_service_1 = require("./autoreply.service");
|
||||
const addAutoReply_dto_1 = require("./dto/addAutoReply.dto");
|
||||
const delBadWords_dto_1 = require("./dto/delBadWords.dto");
|
||||
const queryAutoReply_dto_1 = require("./dto/queryAutoReply.dto");
|
||||
const updateAutoReply_dto_1 = require("./dto/updateAutoReply.dto");
|
||||
let AutoreplyController = class AutoreplyController {
|
||||
constructor(autoreplyService) {
|
||||
this.autoreplyService = autoreplyService;
|
||||
@@ -66,7 +66,7 @@ __decorate([
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [updateAutoReply_dto_1.UpdateAutpReplyDto]),
|
||||
__metadata("design:paramtypes", [updateAutoReply_dto_1.UpdateAutoReplyDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], AutoreplyController.prototype, "updateAutoreply", null);
|
||||
__decorate([
|
||||
|
||||
@@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AutoReplyEntity = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const baseEntity_1 = require("../../common/entity/baseEntity");
|
||||
const typeorm_1 = require("typeorm");
|
||||
let AutoReplyEntity = class AutoReplyEntity extends baseEntity_1.BaseEntity {
|
||||
};
|
||||
__decorate([
|
||||
@@ -22,6 +22,10 @@ __decorate([
|
||||
(0, typeorm_1.Column)({ comment: '定义的答案', type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
], AutoReplyEntity.prototype, "answer", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: 1, comment: '是否开启AI回复,0:关闭 1:启用' }),
|
||||
__metadata("design:type", Number)
|
||||
], AutoReplyEntity.prototype, "isAIReplyEnabled", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: 1, comment: '启用当前自动回复状态, 0:关闭 1:启用' }),
|
||||
__metadata("design:type", Number)
|
||||
8
dist/modules/autoreply/autoreply.module.js
vendored
8
dist/modules/autoreply/autoreply.module.js
vendored
@@ -8,16 +8,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AutoreplyModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const autoreply_controller_1 = require("./autoreply.controller");
|
||||
const autoreply_service_1 = require("./autoreply.service");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const autoreplay_entity_1 = require("./autoreplay.entity");
|
||||
const autoreply_controller_1 = require("./autoreply.controller");
|
||||
const autoreply_entity_1 = require("./autoreply.entity");
|
||||
const autoreply_service_1 = require("./autoreply.service");
|
||||
let AutoreplyModule = class AutoreplyModule {
|
||||
};
|
||||
AutoreplyModule = __decorate([
|
||||
(0, common_1.Global)(),
|
||||
(0, common_1.Module)({
|
||||
imports: [typeorm_1.TypeOrmModule.forFeature([autoreplay_entity_1.AutoReplyEntity])],
|
||||
imports: [typeorm_1.TypeOrmModule.forFeature([autoreply_entity_1.AutoReplyEntity])],
|
||||
controllers: [autoreply_controller_1.AutoreplyController],
|
||||
providers: [autoreply_service_1.AutoreplyService],
|
||||
exports: [autoreply_service_1.AutoreplyService],
|
||||
|
||||
60
dist/modules/autoreply/autoreply.service.js
vendored
60
dist/modules/autoreply/autoreply.service.js
vendored
@@ -16,7 +16,7 @@ exports.AutoreplyService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const autoreplay_entity_1 = require("./autoreplay.entity");
|
||||
const autoreply_entity_1 = require("./autoreply.entity");
|
||||
let AutoreplyService = class AutoreplyService {
|
||||
constructor(autoReplyEntity) {
|
||||
this.autoReplyEntity = autoReplyEntity;
|
||||
@@ -25,20 +25,57 @@ let AutoreplyService = class AutoreplyService {
|
||||
this.autoReplyFuzzyMatch = true;
|
||||
}
|
||||
async onModuleInit() {
|
||||
this.loadAutoReplyList();
|
||||
await this.loadAutoReplyList();
|
||||
}
|
||||
async loadAutoReplyList() {
|
||||
const res = await this.autoReplyEntity.find({ where: { status: 1 }, select: ['prompt', 'answer'] });
|
||||
const res = await this.autoReplyEntity.find({
|
||||
where: { status: 1 },
|
||||
select: ['prompt', 'answer', 'isAIReplyEnabled'],
|
||||
});
|
||||
this.autoReplyMap = {};
|
||||
res.forEach((t) => (this.autoReplyMap[t.prompt] = t.answer));
|
||||
this.autoReplyKes = Object.keys(this.autoReplyMap);
|
||||
this.autoReplyKes = [];
|
||||
res.forEach((t) => {
|
||||
this.autoReplyMap[t.prompt] = {
|
||||
answer: t.answer,
|
||||
isAIReplyEnabled: t.isAIReplyEnabled,
|
||||
};
|
||||
const keywords = t.prompt.split(' ').map((k) => k.trim());
|
||||
this.autoReplyKes.push({ prompt: t.prompt, keywords });
|
||||
});
|
||||
}
|
||||
async checkAutoReply(prompt) {
|
||||
let question = prompt;
|
||||
let answers = [];
|
||||
let isAIReplyEnabled = 0;
|
||||
const seenGroups = new Set();
|
||||
if (this.autoReplyFuzzyMatch) {
|
||||
question = this.autoReplyKes.find((item) => item.includes(prompt));
|
||||
for (const item of this.autoReplyKes) {
|
||||
if (item.keywords.some((keyword) => prompt.includes(keyword))) {
|
||||
if (!seenGroups.has(item.prompt)) {
|
||||
answers.push(this.autoReplyMap[item.prompt].answer);
|
||||
seenGroups.add(item.prompt);
|
||||
if (this.autoReplyMap[item.prompt].isAIReplyEnabled === 1) {
|
||||
isAIReplyEnabled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return question ? this.autoReplyMap[question] : '';
|
||||
else {
|
||||
const matches = this.autoReplyKes.filter((item) => item.prompt === prompt);
|
||||
for (const match of matches) {
|
||||
if (!seenGroups.has(match.prompt)) {
|
||||
answers.push(this.autoReplyMap[match.prompt].answer);
|
||||
seenGroups.add(match.prompt);
|
||||
if (this.autoReplyMap[match.prompt].isAIReplyEnabled === 1) {
|
||||
isAIReplyEnabled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
answer: answers.join('\n'),
|
||||
isAIReplyEnabled,
|
||||
};
|
||||
}
|
||||
async queryAutoreply(query) {
|
||||
const { page = 1, size = 10, prompt, status } = query;
|
||||
@@ -54,11 +91,6 @@ let AutoreplyService = class AutoreplyService {
|
||||
return { rows, count };
|
||||
}
|
||||
async addAutoreply(body) {
|
||||
const { prompt } = body;
|
||||
const a = await this.autoReplyEntity.findOne({ where: { prompt } });
|
||||
if (a) {
|
||||
throw new common_1.HttpException('该问题已存在,请检查您的提交信息', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
await this.autoReplyEntity.save(body);
|
||||
await this.loadAutoReplyList();
|
||||
return '添加问题成功!';
|
||||
@@ -88,7 +120,7 @@ let AutoreplyService = class AutoreplyService {
|
||||
};
|
||||
AutoreplyService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(autoreplay_entity_1.AutoReplyEntity)),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(autoreply_entity_1.AutoReplyEntity)),
|
||||
__metadata("design:paramtypes", [typeorm_2.Repository])
|
||||
], AutoreplyService);
|
||||
exports.AutoreplyService = AutoreplyService;
|
||||
|
||||
@@ -9,29 +9,33 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpdateAutpReplyDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
exports.UpdateAutoReplyDto = void 0;
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
class UpdateAutpReplyDto {
|
||||
const class_validator_1 = require("class-validator");
|
||||
class UpdateAutoReplyDto {
|
||||
}
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 1, description: '自动回复id', required: true }),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", Number)
|
||||
], UpdateAutpReplyDto.prototype, "id", void 0);
|
||||
], UpdateAutoReplyDto.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: '你可以干嘛', description: '问题', required: false }),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", String)
|
||||
], UpdateAutpReplyDto.prototype, "prompt", void 0);
|
||||
], UpdateAutoReplyDto.prototype, "prompt", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: '我可以干很多事情.......', description: '答案', required: false }),
|
||||
(0, swagger_1.ApiProperty)({
|
||||
example: '我可以干很多事情.......',
|
||||
description: '答案',
|
||||
required: false,
|
||||
}),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", String)
|
||||
], UpdateAutpReplyDto.prototype, "answer", void 0);
|
||||
], UpdateAutoReplyDto.prototype, "answer", void 0);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiProperty)({ example: 0, description: '状态', required: false }),
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
__metadata("design:type", Number)
|
||||
], UpdateAutpReplyDto.prototype, "status", void 0);
|
||||
exports.UpdateAutpReplyDto = UpdateAutpReplyDto;
|
||||
], UpdateAutoReplyDto.prototype, "status", void 0);
|
||||
exports.UpdateAutoReplyDto = UpdateAutoReplyDto;
|
||||
|
||||
256
dist/modules/chat/chat.service.js
vendored
256
dist/modules/chat/chat.service.js
vendored
@@ -13,13 +13,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ChatService = void 0;
|
||||
const errorMessage_constant_1 = require("../../common/constants/errorMessage.constant");
|
||||
const utils_1 = require("../../common/utils");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const axios_1 = require("axios");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const uuid = require("uuid");
|
||||
const lumaVideo_service_1 = require("../ai/lumaVideo.service");
|
||||
const midjourneyDraw_service_1 = require("../ai/midjourneyDraw.service");
|
||||
const openaiChat_service_1 = require("../ai/openaiChat.service");
|
||||
@@ -60,7 +58,6 @@ let ChatService = class ChatService {
|
||||
this.lumaVideoService = lumaVideoService;
|
||||
}
|
||||
async chatProcess(body, req, res) {
|
||||
var _a, _b, _c;
|
||||
const { options = {}, usingPluginId, appId = null, specialModel, prompt, fileInfo, modelType, extraParam, model, drawId, customId, action, modelName, modelAvatar, } = body;
|
||||
let appInfo;
|
||||
if (specialModel) {
|
||||
@@ -77,15 +74,15 @@ let ChatService = class ChatService {
|
||||
}
|
||||
}
|
||||
const { groupId, fileParsing } = options;
|
||||
const { openaiTimeout, openaiBaseUrl, openaiBaseKey, systemPreMessage, isMjTranslate, mjTranslatePrompt, isDalleChat, openaiTemperature, } = await this.globalConfigService.getConfigs([
|
||||
const { openaiTimeout, openaiBaseUrl, openaiBaseKey, systemPreMessage, isMjTranslate, mjTranslatePrompt, openaiTemperature, openaiBaseModel, } = await this.globalConfigService.getConfigs([
|
||||
'openaiTimeout',
|
||||
'openaiBaseUrl',
|
||||
'openaiBaseKey',
|
||||
'systemPreMessage',
|
||||
'isMjTranslate',
|
||||
'mjTranslatePrompt',
|
||||
'isDalleChat',
|
||||
'openaiTemperature',
|
||||
'openaiBaseModel',
|
||||
]);
|
||||
await this.userService.checkUserStatus(req.user);
|
||||
res &&
|
||||
@@ -97,9 +94,7 @@ let ChatService = class ChatService {
|
||||
res && res.status(200);
|
||||
let response = null;
|
||||
const curIp = (0, utils_1.getClientIp)(req);
|
||||
let isStop = true;
|
||||
let usePrompt;
|
||||
let isSuccess = false;
|
||||
let useModelAvatar = '';
|
||||
let usingPlugin;
|
||||
if (usingPluginId) {
|
||||
@@ -114,14 +109,12 @@ let ChatService = class ChatService {
|
||||
if (isGPTs) {
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo('gpts');
|
||||
await this.chatLogService.checkModelLimits(req.user, 'gpts');
|
||||
currentRequestModelKey.model = `gpt-4-gizmo-${gizmoID}`;
|
||||
}
|
||||
else if (!isGPTs && isFixedModel && appModel) {
|
||||
appInfo.preset && (setSystemMessage = appInfo.preset);
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo(appModel);
|
||||
await this.chatLogService.checkModelLimits(req.user, appModel);
|
||||
currentRequestModelKey.model = appModel;
|
||||
if (fileParsing) {
|
||||
setSystemMessage = `${setSystemMessage}以下是我提供给你的知识库:【${fileParsing}】,在回答问题之前,先检索知识库内有没有相关的内容,尽量使用知识库中获取到的信息来回答我的问题,以知识库中的为准。`;
|
||||
@@ -132,7 +125,6 @@ let ChatService = class ChatService {
|
||||
appInfo.preset && (setSystemMessage = appInfo.preset);
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
await this.chatLogService.checkModelLimits(req.user, model);
|
||||
if (fileParsing) {
|
||||
setSystemMessage = `${setSystemMessage}以下是我提供给你的知识库:【${fileParsing}】,在回答问题之前,先检索知识库内有没有相关的内容,尽量使用知识库中获取到的信息来回答我的问题,以知识库中的为准。`;
|
||||
}
|
||||
@@ -153,14 +145,12 @@ let ChatService = class ChatService {
|
||||
setSystemMessage = pluginPrompt;
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
await this.chatLogService.checkModelLimits(req.user, model);
|
||||
common_1.Logger.log(`使用插件预设: ${setSystemMessage}`, 'ChatService');
|
||||
}
|
||||
else if (fileParsing) {
|
||||
setSystemMessage = `以下是我提供给你的知识库:【${fileParsing}】,在回答问题之前,先检索知识库内有没有相关的内容,尽量使用知识库中获取到的信息来回答我的问题,以知识库中的为准。`;
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
await this.chatLogService.checkModelLimits(req.user, model);
|
||||
common_1.Logger.log(`使用文件解析: ${setSystemMessage}`, 'ChatService');
|
||||
}
|
||||
else {
|
||||
@@ -168,17 +158,54 @@ let ChatService = class ChatService {
|
||||
setSystemMessage = systemPreMessage + `\n Current date: ${currentDate}`;
|
||||
currentRequestModelKey =
|
||||
await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
await this.chatLogService.checkModelLimits(req.user, model);
|
||||
common_1.Logger.log(`使用全局预设: ${setSystemMessage}`, 'ChatService');
|
||||
}
|
||||
}
|
||||
if (!currentRequestModelKey) {
|
||||
common_1.Logger.debug('未找到当前模型key,切换至全局模型', 'ChatService');
|
||||
currentRequestModelKey = await this.modelsService.getCurrentModelKeyInfo(openaiBaseModel);
|
||||
const groupInfo = await this.chatGroupService.getGroupInfoFromId(groupId);
|
||||
let updatedConfig = groupInfo.config;
|
||||
try {
|
||||
const parsedConfig = JSON.parse(groupInfo.config);
|
||||
if (parsedConfig.modelInfo) {
|
||||
parsedConfig.modelInfo.modelName = currentRequestModelKey.modelName;
|
||||
parsedConfig.modelInfo.model = currentRequestModelKey.model;
|
||||
updatedConfig = JSON.stringify(parsedConfig);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.debug('模型切换错误,请检查全局模型配置!', 'ChatService');
|
||||
throw new common_1.HttpException('配置解析错误!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
await this.chatGroupService.update({
|
||||
groupId,
|
||||
title: groupInfo.title,
|
||||
isSticky: false,
|
||||
config: updatedConfig,
|
||||
}, req);
|
||||
}
|
||||
const { deduct, isTokenBased, tokenFeeRatio, deductType, key, id: keyId, maxRounds, proxyUrl, maxModelTokens, timeout, model: useModel, isFileUpload, } = currentRequestModelKey;
|
||||
if (isMjTranslate === '1' && mjTranslatePrompt && model === 'midjourney') {
|
||||
const translatePrompt = await this.openAIChatService.chatFree(prompt, mjTranslatePrompt);
|
||||
usePrompt =
|
||||
isFileUpload === '1' && fileInfo
|
||||
? fileInfo + ' ' + translatePrompt
|
||||
: translatePrompt;
|
||||
if (await this.chatLogService.checkModelLimits(req.user, useModel)) {
|
||||
throw new common_1.HttpException('1 小时内对话次数过多,请切换模型或稍后再试!', common_1.HttpStatus.TOO_MANY_REQUESTS);
|
||||
}
|
||||
common_1.Logger.debug(`原始用户提问: ${prompt}, 是否翻译: ${isMjTranslate}, 翻译提示: ${mjTranslatePrompt}, 模型: ${model}, 是否文件上传: ${isFileUpload}, 文件信息: ${fileInfo}`);
|
||||
if (isMjTranslate === '1' &&
|
||||
action === 'IMAGINE' &&
|
||||
model === 'midjourney') {
|
||||
const [beforeArgs, afterArgs] = prompt.split(/(?= --)/);
|
||||
const urlPattern = /(https?:\/\/[^\s]+)/g;
|
||||
const urls = beforeArgs.match(urlPattern) || [];
|
||||
let textToTranslate = beforeArgs.replace(urlPattern, '').trim();
|
||||
const translatedText = await this.openAIChatService.chatFree(textToTranslate, mjTranslatePrompt ||
|
||||
"Translate any given phrase from any language into English. For instance, when I input '{可爱的熊猫}', you should output '{cute panda}', with no period at the end.");
|
||||
const finalTranslatedPrompt = [...urls, translatedText].join(' ').trim();
|
||||
usePrompt = afterArgs
|
||||
? `${finalTranslatedPrompt}${afterArgs}`
|
||||
: finalTranslatedPrompt;
|
||||
if (isFileUpload === '1' && fileInfo) {
|
||||
usePrompt = `${fileInfo} ${usePrompt}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
usePrompt =
|
||||
@@ -190,32 +217,11 @@ let ChatService = class ChatService {
|
||||
const modelKey = key || openaiBaseKey;
|
||||
const modelTimeout = (timeout || openaiTimeout || 300) * 1000;
|
||||
const temperature = Number(openaiTemperature) || 1;
|
||||
common_1.Logger.log(`\n` +
|
||||
`超时设置: ${modelTimeout / 1000} s\n` +
|
||||
`请求地址: ${proxyResUrl}\n` +
|
||||
`使用的模型名称: ${useModeName}\n` +
|
||||
`使用的模型: ${useModel}`, 'ChatService');
|
||||
if (!currentRequestModelKey) {
|
||||
throw new common_1.HttpException('当前流程所需要的模型已被管理员下架、请联系管理员上架专属模型!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (groupId) {
|
||||
const groupInfo = await this.chatGroupService.getGroupInfoFromId(groupId);
|
||||
this.updateChatTitle(groupId, groupInfo, modelType, prompt, req);
|
||||
await this.chatGroupService.updateTime(groupId);
|
||||
}
|
||||
const { messagesHistory } = await this.buildMessageFromParentMessageId(prompt, {
|
||||
groupId,
|
||||
systemMessage: setSystemMessage,
|
||||
maxModelTokens,
|
||||
maxRounds: (usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.parameters) === 'net-search' ||
|
||||
(usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.parameters) === 'mind-map' ||
|
||||
useModel.includes('suno')
|
||||
? 0
|
||||
: maxRounds,
|
||||
fileInfo: fileInfo,
|
||||
model: useModel,
|
||||
isFileUpload,
|
||||
}, this.chatLogService);
|
||||
const userSaveLog = await this.chatLogService.saveChatLog({
|
||||
appId: appId,
|
||||
curIp,
|
||||
@@ -251,31 +257,23 @@ let ChatService = class ChatService {
|
||||
groupId: groupId ? groupId : null,
|
||||
status: 2,
|
||||
modelAvatar: (usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.pluginImg) || useModelAvatar || modelAvatar || '',
|
||||
pluginParam: (usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.parameters) ? usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.parameters : null,
|
||||
pluginParam: (usingPlugin === null || usingPlugin === void 0 ? void 0 : usingPlugin.parameters)
|
||||
? usingPlugin.parameters
|
||||
: modelType === 2
|
||||
? useModel
|
||||
: null,
|
||||
});
|
||||
common_1.Logger.log('开始处理对话!', 'ChatService');
|
||||
const userLogId = userSaveLog.id;
|
||||
const assistantLogId = assistantSaveLog.id;
|
||||
const autoReplyRes = await this.autoreplyService.checkAutoReply(prompt);
|
||||
if (autoReplyRes && res) {
|
||||
const msg = { text: autoReplyRes };
|
||||
const chars = autoReplyRes.split('');
|
||||
const sendCharByChar = (index) => {
|
||||
if (index < chars.length) {
|
||||
const msg = { text: chars[index] };
|
||||
res.write(`${JSON.stringify(msg)}\n`);
|
||||
setTimeout(() => sendCharByChar(index + 1), 10);
|
||||
}
|
||||
else {
|
||||
res.end();
|
||||
}
|
||||
};
|
||||
sendCharByChar(0);
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
answer: autoReplyRes,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { messagesHistory } = await this.buildMessageFromParentMessageId(prompt, {
|
||||
groupId,
|
||||
systemMessage: setSystemMessage,
|
||||
maxModelTokens,
|
||||
maxRounds: maxRounds,
|
||||
fileInfo: fileInfo,
|
||||
model: useModel,
|
||||
isFileUpload,
|
||||
}, this.chatLogService);
|
||||
let charge = action !== 'UPSCALE' && useModel === 'midjourney' ? deduct * 4 : deduct;
|
||||
const abortController = new AbortController();
|
||||
try {
|
||||
@@ -292,36 +290,15 @@ let ChatService = class ChatService {
|
||||
useModel === 'luma-video' ||
|
||||
useModel.includes('stable-diffusion')) {
|
||||
if (useModel === 'dall-e-3') {
|
||||
let drawPrompt;
|
||||
if (isDalleChat === '1') {
|
||||
try {
|
||||
common_1.Logger.log('已开启连续绘画模式', 'DalleDraw');
|
||||
const { messagesHistory } = await this.buildMessageFromParentMessageId(`参考上文,结合我的需求,给出绘画描述。我的需求是:${prompt}`, {
|
||||
groupId,
|
||||
systemMessage: '你是一个绘画提示词生成工具,请根据用户的要求,结合上下文,用一段文字,描述用户需要的绘画需求,不用包含任何礼貌性的寒暄,只需要场景的描述,可以适当联想',
|
||||
maxModelTokens: 8000,
|
||||
maxRounds: 5,
|
||||
fileInfo: '',
|
||||
isFileUpload,
|
||||
}, this.chatLogService);
|
||||
drawPrompt = await this.openAIChatService.chatFree(prompt, undefined, messagesHistory);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('调用chatFree失败:', error);
|
||||
drawPrompt = prompt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawPrompt = prompt;
|
||||
}
|
||||
response = this.openAIDrawService.dalleDraw({
|
||||
prompt: drawPrompt,
|
||||
prompt: prompt,
|
||||
extraParam: extraParam,
|
||||
apiKey: modelKey,
|
||||
proxyUrl: proxyResUrl,
|
||||
model: useModel,
|
||||
timeout: modelTimeout,
|
||||
modelName: useModeName,
|
||||
groupId: groupId,
|
||||
onSuccess: async (data) => {
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
|
||||
@@ -329,16 +306,14 @@ let ChatService = class ChatService {
|
||||
progress: '100%',
|
||||
status: data.status,
|
||||
});
|
||||
common_1.Logger.log('绘图成功! ', 'DalleDraw');
|
||||
},
|
||||
onFailure: async (data) => {
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
answer: '绘图失败',
|
||||
status: data.status,
|
||||
});
|
||||
common_1.Logger.log('绘图失败', 'DalleDraw');
|
||||
},
|
||||
}, messagesHistory);
|
||||
}, this.buildMessageFromParentMessageId);
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
answer: '绘制中',
|
||||
});
|
||||
@@ -383,7 +358,6 @@ let ChatService = class ChatService {
|
||||
progress: '100%',
|
||||
status: 3,
|
||||
});
|
||||
common_1.Logger.log('视频生成成功', 'LumaVideo');
|
||||
},
|
||||
onFailure: async (data) => {
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
@@ -429,7 +403,7 @@ let ChatService = class ChatService {
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = this.midjourneyService.midjourneyDraw({
|
||||
response = await this.midjourneyService.midjourneyDraw({
|
||||
usePrompt: usePrompt,
|
||||
prompt: prompt,
|
||||
apiKey: modelKey,
|
||||
@@ -439,21 +413,26 @@ let ChatService = class ChatService {
|
||||
drawId,
|
||||
customId,
|
||||
action,
|
||||
fileInfo,
|
||||
timeout: modelTimeout,
|
||||
assistantLogId,
|
||||
});
|
||||
await this.chatLogService.updateChatLog(assistantLogId, {
|
||||
answer: '绘制中',
|
||||
answer: response.answer,
|
||||
status: response.status,
|
||||
});
|
||||
}
|
||||
await this.modelsService.saveUseLog(keyId, 1);
|
||||
await this.userBalanceService.deductFromBalance(req.user.id, deductType, charge);
|
||||
if (response.status !== 5) {
|
||||
await this.modelsService.saveUseLog(keyId, 1);
|
||||
await this.userBalanceService.deductFromBalance(req.user.id, deductType, charge);
|
||||
}
|
||||
else {
|
||||
common_1.Logger.log('任务提交失败,不执行扣费', 'ChatService');
|
||||
}
|
||||
const userBalance = await this.userBalanceService.queryUserBalance(req.user.id);
|
||||
response.userBalance = Object.assign({}, userBalance);
|
||||
response.text = '提交成功';
|
||||
isStop = false;
|
||||
isSuccess = true;
|
||||
response.status = 2;
|
||||
response.text = response.answer;
|
||||
response.status = response.status || 2;
|
||||
response.model = model;
|
||||
response.modelName = modelName;
|
||||
return res.write(`\n${JSON.stringify(response)}`);
|
||||
@@ -488,8 +467,6 @@ let ChatService = class ChatService {
|
||||
abortController,
|
||||
});
|
||||
if (response.errMsg) {
|
||||
isStop = false;
|
||||
isSuccess = true;
|
||||
common_1.Logger.error(`用户ID: ${req.user.id} 模型名称: ${useModeName} 模型: ${model} 回复出错,本次不扣除积分`, 'ChatService');
|
||||
return res.write(`\n${JSON.stringify(response)}`);
|
||||
}
|
||||
@@ -522,8 +499,6 @@ let ChatService = class ChatService {
|
||||
common_1.Logger.log(`用户ID: ${req.user.id} 模型名称: ${useModeName} 模型: ${model} 消耗token: ${promptTokens + completionTokens}, 消耗积分: ${charge}`, 'ChatService');
|
||||
const userBalance = await this.userBalanceService.queryUserBalance(req.user.id);
|
||||
response.userBalance = Object.assign({}, userBalance);
|
||||
isStop = false;
|
||||
isSuccess = true;
|
||||
return res.write(`\n${JSON.stringify(response)}`);
|
||||
}
|
||||
}
|
||||
@@ -533,7 +508,6 @@ let ChatService = class ChatService {
|
||||
status: 5,
|
||||
});
|
||||
response = { error: '处理请求时发生错误' };
|
||||
isStop = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -558,68 +532,11 @@ let ChatService = class ChatService {
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error('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;
|
||||
common_1.Logger.error('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);
|
||||
if (error.status && error.status === 402) {
|
||||
const errMsg = { message: `Catch Error ${error.message}`, code: 402 };
|
||||
if (res) {
|
||||
return res.write(JSON.stringify(errMsg));
|
||||
}
|
||||
else {
|
||||
throw new common_1.HttpException(error.message, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
if (res) {
|
||||
return res.write(JSON.stringify({ message: error.message, code: 500 }));
|
||||
}
|
||||
else {
|
||||
throw new common_1.HttpException(error.message, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
let message = errorMessage_constant_1.OpenAiErrorCodeMessage[status]
|
||||
? errorMessage_constant_1.OpenAiErrorCodeMessage[status]
|
||||
: '服务异常、请重新试试吧!!!';
|
||||
if ((error === null || error === void 0 ? void 0 : error.message.includes('The OpenAI account associated with this API key has been deactivated.')) &&
|
||||
Number(modelType) === 1) {
|
||||
await this.modelsService.lockKey(keyId, '当前模型key已被封禁、已冻结当前调用Key、尝试重新对话试试吧!', -1);
|
||||
message = '当前模型key已被封禁';
|
||||
}
|
||||
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 429 &&
|
||||
error.message.includes('billing') &&
|
||||
Number(modelType) === 1) {
|
||||
await this.modelsService.lockKey(keyId, '当前模型key余额已耗尽、已冻结当前调用Key、尝试重新对话试试吧!', -3);
|
||||
message = '当前模型key余额已耗尽';
|
||||
}
|
||||
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 429 &&
|
||||
(error === null || error === void 0 ? void 0 : error.statusText) === 'Too Many Requests') {
|
||||
message = '当前模型调用过于频繁、请重新试试吧!';
|
||||
}
|
||||
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 401 &&
|
||||
error.message.includes('Incorrect API key provided') &&
|
||||
Number(modelType) === 1) {
|
||||
await this.modelsService.lockKey(keyId, '提供了错误的模型秘钥', -2);
|
||||
message = '提供了错误的模型秘钥、已冻结当前调用Key、请重新尝试对话!';
|
||||
}
|
||||
if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404 &&
|
||||
error.message.includes('This is not a chat model and thus not supported') &&
|
||||
Number(modelType) === 1) {
|
||||
await this.modelsService.lockKey(keyId, '当前模型不是聊天模型', -4);
|
||||
message = '当前模型不是聊天模型、已冻结当前调用Key、请重新尝试对话!';
|
||||
}
|
||||
if (code === 400) {
|
||||
common_1.Logger.error('400 error', error, error.message);
|
||||
}
|
||||
const errMsg = {
|
||||
message: message || 'Please check the back-end console',
|
||||
code: code === 401 ? 400 : code || 500,
|
||||
};
|
||||
if (res) {
|
||||
return res.write(JSON.stringify(errMsg));
|
||||
return res.write('发生未知错误,请稍后再试');
|
||||
}
|
||||
else {
|
||||
throw new common_1.HttpException(errMsg.message, common_1.HttpStatus.BAD_REQUEST);
|
||||
throw new common_1.HttpException('发生未知错误,请稍后再试', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -660,7 +577,7 @@ let ChatService = class ChatService {
|
||||
try {
|
||||
chatTitle = await this.openAIChatService.chatFree(`根据用户提问{${prompt}},给这个对话取一个名字,不超过10个字`);
|
||||
if (chatTitle.length > 15) {
|
||||
chatTitle = chatTitle.slice(0, 15);
|
||||
chatTitle = chatTitle.slice(0, 15);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -684,6 +601,10 @@ let ChatService = class ChatService {
|
||||
}
|
||||
async buildMessageFromParentMessageId(text, options, chatLogService) {
|
||||
let { systemMessage = '', fileInfo, groupId, maxRounds = 5, maxModelTokens = 8000, isFileUpload = 0, } = options;
|
||||
if (systemMessage.length > maxModelTokens) {
|
||||
common_1.Logger.log('系统消息超过最大长度,将被截断', 'ChatService');
|
||||
systemMessage = systemMessage.slice(0, maxModelTokens);
|
||||
}
|
||||
let messages = [];
|
||||
if (systemMessage) {
|
||||
messages.push({ role: 'system', content: systemMessage });
|
||||
@@ -694,7 +615,9 @@ let ChatService = class ChatService {
|
||||
history.forEach((record) => {
|
||||
try {
|
||||
let content;
|
||||
if (isFileUpload === 2 && record.fileInfo && record.role === 'user') {
|
||||
if ((isFileUpload === 2 || isFileUpload === 3) &&
|
||||
record.fileInfo &&
|
||||
record.role === 'user') {
|
||||
content = [
|
||||
{ type: 'text', text: record.text },
|
||||
{ type: 'image_url', image_url: { url: record.fileInfo } },
|
||||
@@ -728,7 +651,7 @@ let ChatService = class ChatService {
|
||||
});
|
||||
}
|
||||
let currentMessageContent;
|
||||
if (isFileUpload === 2 && fileInfo) {
|
||||
if ((isFileUpload === 2 || isFileUpload === 3) && fileInfo) {
|
||||
currentMessageContent = [
|
||||
{ type: 'text', text },
|
||||
{ type: 'image_url', image_url: { url: fileInfo } },
|
||||
@@ -816,15 +739,12 @@ let ChatService = class ChatService {
|
||||
const response = await (0, axios_1.default)(options);
|
||||
common_1.Logger.log('TTS 请求获取成功', 'TTSService');
|
||||
const buffer = Buffer.from(response.data);
|
||||
const filename = `${uuid.v4().slice(0, 10)}.mp3`;
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const currentDate = `${year}${month}/${day}`;
|
||||
common_1.Logger.log('开始上传语音', 'TTSService');
|
||||
const ttsUrl = await this.uploadService.uploadFile({ filename, buffer }, `audio/openai/${currentDate}`);
|
||||
common_1.Logger.log(`文件上传成功,URL: ${ttsUrl}`, 'TTSService');
|
||||
const ttsUrl = await this.uploadService.uploadFile({ buffer, mimetype: 'audio/mpeg' }, `audio/openai/${currentDate}`);
|
||||
await Promise.all([
|
||||
this.chatLogService.updateChatLog(chatId, { ttsUrl }),
|
||||
this.userBalanceService.deductFromBalance(req.user.id, deductType, deduct),
|
||||
|
||||
25
dist/modules/chatGroup/chatGroup.service.js
vendored
25
dist/modules/chatGroup/chatGroup.service.js
vendored
@@ -28,7 +28,7 @@ let ChatGroupService = class ChatGroupService {
|
||||
async create(body, req) {
|
||||
const { id } = req.user;
|
||||
const { appId, modelConfig: bodyModelConfig } = body;
|
||||
let modelConfig = bodyModelConfig || await this.modelsService.getBaseConfig(appId);
|
||||
let modelConfig = bodyModelConfig || (await this.modelsService.getBaseConfig());
|
||||
if (!modelConfig) {
|
||||
throw new common_1.HttpException('管理员未配置任何AI模型、请先联系管理员开通聊天模型配置!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ let ChatGroupService = class ChatGroupService {
|
||||
isGPTs,
|
||||
isFixedModel,
|
||||
modelAvatar: coverImg,
|
||||
modelName: name
|
||||
modelName: name,
|
||||
});
|
||||
if (isGPTs === 1 || isFixedModel === 1) {
|
||||
const appModelKey = await this.modelsService.getCurrentModelKeyInfo(isFixedModel === 1 ? appModel : 'gpts');
|
||||
@@ -52,7 +52,7 @@ let ChatGroupService = class ChatGroupService {
|
||||
deductType: appModelKey.deductType,
|
||||
deduct: appModelKey.deduct,
|
||||
model: appModel,
|
||||
isFileUpload: appModelKey.isFileUpload
|
||||
isFileUpload: appModelKey.isFileUpload,
|
||||
});
|
||||
}
|
||||
if (![1, 3, 4, 5].includes(status)) {
|
||||
@@ -69,13 +69,16 @@ let ChatGroupService = class ChatGroupService {
|
||||
try {
|
||||
const { id } = req.user;
|
||||
const params = { userId: id, isDelete: false };
|
||||
const res = await this.chatGroupEntity.find({ where: params, order: { isSticky: 'DESC', updatedAt: 'DESC' } });
|
||||
const res = await this.chatGroupEntity.find({
|
||||
where: params,
|
||||
order: { isSticky: 'DESC', updatedAt: 'DESC' },
|
||||
});
|
||||
return res;
|
||||
const appIds = res.filter(t => t.appId).map(t => t.appId);
|
||||
const appIds = res.filter((t) => t.appId).map((t) => t.appId);
|
||||
const appInfos = await this.appEntity.find({ where: { id: (0, typeorm_2.In)(appIds) } });
|
||||
return res.map((item) => {
|
||||
var _a;
|
||||
item.appLogo = (_a = appInfos.find(t => t.id === item.appId)) === null || _a === void 0 ? void 0 : _a.coverImg;
|
||||
item.appLogo = (_a = appInfos.find((t) => t.id === item.appId)) === null || _a === void 0 ? void 0 : _a.coverImg;
|
||||
return item;
|
||||
});
|
||||
}
|
||||
@@ -86,7 +89,9 @@ let ChatGroupService = class ChatGroupService {
|
||||
async update(body, req) {
|
||||
const { title, isSticky, groupId, config } = body;
|
||||
const { id } = req.user;
|
||||
const g = await this.chatGroupEntity.findOne({ where: { id: groupId, userId: id } });
|
||||
const g = await this.chatGroupEntity.findOne({
|
||||
where: { id: groupId, userId: id },
|
||||
});
|
||||
if (!g) {
|
||||
throw new common_1.HttpException('请先选择一个对话或者新加一个对话再操作!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -115,13 +120,15 @@ let ChatGroupService = class ChatGroupService {
|
||||
}
|
||||
async updateTime(groupId) {
|
||||
await this.chatGroupEntity.update(groupId, {
|
||||
updatedAt: new Date()
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
}
|
||||
async del(body, req) {
|
||||
const { groupId } = body;
|
||||
const { id } = req.user;
|
||||
const g = await this.chatGroupEntity.findOne({ where: { id: groupId, userId: id } });
|
||||
const g = await this.chatGroupEntity.findOne({
|
||||
where: { id: groupId, userId: id },
|
||||
});
|
||||
if (!g) {
|
||||
throw new common_1.HttpException('非法操作、您在删除一个非法资源!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
30
dist/modules/chatLog/chatLog.controller.js
vendored
30
dist/modules/chatLog/chatLog.controller.js
vendored
@@ -13,21 +13,21 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ChatLogController = void 0;
|
||||
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
|
||||
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
|
||||
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
|
||||
const chatLog_service_1 = require("./chatLog.service");
|
||||
const queryAllDrawLog_dto_1 = require("./dto/queryAllDrawLog.dto");
|
||||
const queryAllChatLog_dto_1 = require("./dto/queryAllChatLog.dto");
|
||||
const recDrawImg_dto_1 = require("./dto/recDrawImg.dto");
|
||||
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
|
||||
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
|
||||
const queryMyChatLog_dto_1 = require("./dto/queryMyChatLog.dto");
|
||||
const exportExcelChatlog_dto_1 = require("./dto/exportExcelChatlog.dto");
|
||||
const chatList_dto_1 = require("./dto/chatList.dto");
|
||||
const del_dto_1 = require("./dto/del.dto");
|
||||
const delByGroup_dto_1 = require("./dto/delByGroup.dto");
|
||||
const exportExcelChatlog_dto_1 = require("./dto/exportExcelChatlog.dto");
|
||||
const queryAllChatLog_dto_1 = require("./dto/queryAllChatLog.dto");
|
||||
const queryAllDrawLog_dto_1 = require("./dto/queryAllDrawLog.dto");
|
||||
const queryByAppId_dto_1 = require("./dto/queryByAppId.dto");
|
||||
const queryMyChatLog_dto_1 = require("./dto/queryMyChatLog.dto");
|
||||
const recDrawImg_dto_1 = require("./dto/recDrawImg.dto");
|
||||
let ChatLogController = class ChatLogController {
|
||||
constructor(chatLogService) {
|
||||
this.chatLogService = chatLogService;
|
||||
@@ -56,6 +56,9 @@ let ChatLogController = class ChatLogController {
|
||||
delByGroupId(req, body) {
|
||||
return this.chatLogService.delByGroupId(req, body);
|
||||
}
|
||||
deleteChatsAfterId(req, body) {
|
||||
return this.chatLogService.deleteChatsAfterId(req, body);
|
||||
}
|
||||
byAppId(req, params) {
|
||||
return this.chatLogService.byAppId(req, params);
|
||||
}
|
||||
@@ -143,6 +146,17 @@ __decorate([
|
||||
__metadata("design:paramtypes", [Object, delByGroup_dto_1.DelByGroupDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ChatLogController.prototype, "delByGroupId", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('deleteChatsAfterId'),
|
||||
(0, swagger_1.ApiOperation)({ summary: '删除对话组中某条对话及其后的所有对话' }),
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
(0, common_1.UseGuards)(jwtAuth_guard_1.JwtAuthGuard),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ChatLogController.prototype, "deleteChatsAfterId", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('byAppId'),
|
||||
(0, swagger_1.ApiOperation)({ summary: '查询某个应用的问答记录' }),
|
||||
|
||||
44
dist/modules/chatLog/chatLog.service.js
vendored
44
dist/modules/chatLog/chatLog.service.js
vendored
@@ -283,7 +283,6 @@ let ChatLogService = class ChatLogService {
|
||||
return record;
|
||||
})
|
||||
.reverse();
|
||||
common_1.Logger.debug('处理后的结果:', JSON.stringify(result, null, 2));
|
||||
return result;
|
||||
}
|
||||
async deleteChatLog(req, body) {
|
||||
@@ -318,6 +317,22 @@ let ChatLogService = class ChatLogService {
|
||||
throw new common_1.HttpException('当前页面已经没有东西可以删除了!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async deleteChatsAfterId(req, body) {
|
||||
const { id } = body;
|
||||
const { id: userId } = req.user;
|
||||
const chatLog = await this.chatLogEntity.findOne({ where: { id, userId } });
|
||||
if (!chatLog) {
|
||||
throw new common_1.HttpException('你删除的对话记录不存在、请检查!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const { groupId } = chatLog;
|
||||
const result = await this.chatLogEntity.update({ groupId, id: (0, typeorm_2.MoreThanOrEqual)(id) }, { isDelete: true });
|
||||
if (result.affected > 0) {
|
||||
return '删除对话记录成功!';
|
||||
}
|
||||
else {
|
||||
throw new common_1.HttpException('当前页面已经没有东西可以删除了!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async byAppId(req, body) {
|
||||
const { id } = req.user;
|
||||
const { appId, page = 1, size = 10 } = body;
|
||||
@@ -330,8 +345,8 @@ let ChatLogService = class ChatLogService {
|
||||
return { rows, count };
|
||||
}
|
||||
async checkModelLimits(userId, model) {
|
||||
const oneHourAgo = new Date(Date.now() - 3600 * 1000);
|
||||
let adjustedUsageCount;
|
||||
const ONE_HOUR_IN_MS = 3600 * 1000;
|
||||
const oneHourAgo = new Date(Date.now() - ONE_HOUR_IN_MS);
|
||||
try {
|
||||
const usageCount = await this.chatLogEntity.count({
|
||||
where: {
|
||||
@@ -340,15 +355,24 @@ let ChatLogService = class ChatLogService {
|
||||
createdAt: (0, typeorm_2.MoreThan)(oneHourAgo),
|
||||
},
|
||||
});
|
||||
adjustedUsageCount = Math.ceil(usageCount / 2);
|
||||
common_1.Logger.debug(`用户ID: ${userId.id} 模型: ${model} 一小时内已调用: ${adjustedUsageCount} 次`);
|
||||
const adjustedUsageCount = Math.ceil(usageCount / 2);
|
||||
common_1.Logger.log(`用户ID: ${userId.id} 一小时内调用 ${model} 模型 ${adjustedUsageCount + 1} 次`, 'ChatLogService');
|
||||
let modelInfo;
|
||||
if (model.startsWith('gpt-4-gizmo')) {
|
||||
modelInfo = await this.modelsService.getCurrentModelKeyInfo('gpts');
|
||||
}
|
||||
else {
|
||||
modelInfo = await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
}
|
||||
const modelLimits = Number(modelInfo.modelLimits);
|
||||
common_1.Logger.log(`模型 ${model} 的使用次数限制为 ${modelLimits}`, 'ChatLogService');
|
||||
if (adjustedUsageCount > modelLimits) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (error) {
|
||||
common_1.Logger.error(`查询数据库出错 - 用户ID: ${userId}, 模型: ${model}, 错误信息: ${error.message}`);
|
||||
}
|
||||
const modelInfo = await this.modelsService.getCurrentModelKeyInfo(model);
|
||||
if (adjustedUsageCount > modelInfo.modelLimits) {
|
||||
throw new common_1.HttpException('1 小时内请求次数过多,请稍后再试!', common_1.HttpStatus.TOO_MANY_REQUESTS);
|
||||
common_1.Logger.error(`查询数据库出错 - 用户ID: ${userId.id}, 模型: ${model}, 错误信息: ${error.message}`, error.stack, 'ChatLogService');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
2
dist/modules/database/database.service.js
vendored
2
dist/modules/database/database.service.js
vendored
@@ -54,7 +54,7 @@ let DatabaseService = class DatabaseService {
|
||||
const { username, password, status, email, role } = userInfo;
|
||||
const user = await this.connection.query(`INSERT INTO users (username, password, status, email, role) VALUES ('${username}', '${password}', '${status}', '${email}', '${role}')`);
|
||||
const userId = user.insertId;
|
||||
const balance = await this.connection.query(`INSERT INTO balance (userId, balance, usesLeft, paintCount) VALUES ('${userId}', 0, 1000, 100)`);
|
||||
await this.connection.query(`INSERT INTO balance (userId, balance, usesLeft, paintCount) VALUES ('${userId}', 0, 1000, 100)`);
|
||||
common_1.Logger.log(`初始化创建${role}用户成功、用户名为[${username}]、初始密码为[${username === 'super' ? 'super' : '123456'}] ==============> 请注意查阅`, 'DatabaseService');
|
||||
}
|
||||
catch (error) {
|
||||
|
||||
@@ -8,11 +8,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.GlobalConfigModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
|
||||
const config_entity_1 = require("./config.entity");
|
||||
const globalConfig_controller_1 = require("./globalConfig.controller");
|
||||
const globalConfig_service_1 = require("./globalConfig.service");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const config_entity_1 = require("./config.entity");
|
||||
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
|
||||
let GlobalConfigModule = class GlobalConfigModule {
|
||||
};
|
||||
GlobalConfigModule = __decorate([
|
||||
|
||||
@@ -188,15 +188,20 @@ let GlobalConfigService = class GlobalConfigService {
|
||||
'mjHideWorkIn',
|
||||
'isVerifyEmail',
|
||||
'isHideSidebar',
|
||||
'showWatermark',
|
||||
'isHideTts',
|
||||
'isHideDefaultPreset',
|
||||
'isHideModel3Point',
|
||||
'isHideModel4Point',
|
||||
'isHideDrawMjPoint',
|
||||
'isHidePlugin',
|
||||
'model3Name',
|
||||
'model4Name',
|
||||
'drawMjName',
|
||||
'isModelInherited',
|
||||
'noVerifyRegister',
|
||||
'noticeInfo',
|
||||
'homeHtml',
|
||||
];
|
||||
const data = await this.configEntity.find({
|
||||
where: { configKey: (0, typeorm_2.In)(allowKeys) },
|
||||
|
||||
26
dist/modules/midjourney/midjourney.service.js
vendored
26
dist/modules/midjourney/midjourney.service.js
vendored
@@ -68,7 +68,9 @@ let MidjourneyService = class MidjourneyService {
|
||||
else {
|
||||
let resultPromise;
|
||||
if (action === 'MODAL') {
|
||||
resultPromise = this.getDrawActionDetail(action, drawId, customId).then((res) => res.drawId);
|
||||
common_1.Logger.debug('customId:', customId);
|
||||
drawInfo.drawId = (await this.getDrawActionDetail(drawId, customId)).drawId;
|
||||
resultPromise = this.sendDrawCommand(drawInfo, modelInfo);
|
||||
}
|
||||
else {
|
||||
resultPromise = this.sendDrawCommand(drawInfo, modelInfo);
|
||||
@@ -83,7 +85,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
common_1.Logger.error('Error in other draw operation:', error);
|
||||
});
|
||||
}
|
||||
common_1.Logger.log(`执行预扣费,扣除费用:${action === 'UPSCALE' ? deduct : deduct * 4}积分。`);
|
||||
common_1.Logger.log(`执行预扣费,扣除费用:${action === 'UPSCALE' ? deduct : deduct * 4}积分。`, 'MidjourneyService');
|
||||
await this.userBalanceService.deductFromBalance(req.user.id, deductType, action === 'UPSCALE' ? deduct : deduct * 4);
|
||||
return true;
|
||||
}
|
||||
@@ -106,7 +108,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
}
|
||||
async addDrawQueue(params) {
|
||||
try {
|
||||
const { prompt, imgUrl = '', extraParam = '', action, userId, customId, drawId, } = params;
|
||||
const { prompt, imgUrl = '', extraParam = '', action, userId, customId, drawId, base64, } = params;
|
||||
const fullPrompt = imgUrl
|
||||
? `${imgUrl} ${prompt} ${extraParam}`
|
||||
: `${prompt} ${extraParam}`;
|
||||
@@ -120,6 +122,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
status: midjourney_constant_1.MidjourneyStatusEnum.WAITING,
|
||||
action,
|
||||
customId,
|
||||
base64,
|
||||
};
|
||||
const res = await this.midjourneyEntity.save(drawInfo);
|
||||
return res;
|
||||
@@ -231,6 +234,7 @@ let MidjourneyService = class MidjourneyService {
|
||||
else if (action === 'MODAL') {
|
||||
url = `${mjProxyUrl}/mj/submit/modal`;
|
||||
payloadJson = { maskBase64: base64, taskId: drawId, prompt: prompt };
|
||||
console.log('提交参数', payloadJson);
|
||||
}
|
||||
else {
|
||||
url = `${mjProxyUrl}/mj/submit/action`;
|
||||
@@ -354,24 +358,22 @@ let MidjourneyService = class MidjourneyService {
|
||||
throw new common_1.HttpException('获取我得绘制列表失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async getDrawActionDetail(action, drawId, customId) {
|
||||
async getDrawActionDetail(drawId, customId) {
|
||||
const modelInfo = await this.modelsService.getSpecialModelKeyInfo('midjourney');
|
||||
const { openaiBaseUrl, openaiBaseKey } = await this.globalConfigService.getConfigs([
|
||||
'openaiBaseUrl',
|
||||
'openaiBaseKey',
|
||||
]);
|
||||
const { deduct, isTokenBased, tokenFeeRatio, deductType, key, modelName, id: keyId, maxRounds, proxyUrl, maxModelTokens, timeout, model: useModel, } = modelInfo;
|
||||
const { key, id: keyId, maxRounds, proxyUrl, maxModelTokens, timeout, model: useModel, } = modelInfo;
|
||||
const mjProxyUrl = proxyUrl;
|
||||
const mjKey = key || openaiBaseKey;
|
||||
const headers = { 'mj-api-secret': mjKey || openaiBaseUrl };
|
||||
let resultId;
|
||||
if (action === 'MODAL') {
|
||||
const payloadJson = { taskId: drawId, customId: customId };
|
||||
const url = `${mjProxyUrl}/mj/submit/action`;
|
||||
const res = await axios_1.default.post(url, payloadJson, { headers });
|
||||
resultId = res.data.result;
|
||||
console.log('Received response from action submission:', resultId);
|
||||
}
|
||||
const payloadJson = { taskId: drawId, customId: customId };
|
||||
const url = `${mjProxyUrl}/mj/submit/action`;
|
||||
const res = await axios_1.default.post(url, payloadJson, { headers });
|
||||
resultId = res.data.result;
|
||||
console.log('Received response from action submission:', resultId);
|
||||
return { drawId: resultId };
|
||||
}
|
||||
async deleteDraw(id, req) {
|
||||
|
||||
6
dist/modules/models/models.service.js
vendored
6
dist/modules/models/models.service.js
vendored
@@ -72,11 +72,11 @@ let ModelsService = class ModelsService {
|
||||
this.initCalcKey();
|
||||
}
|
||||
async getCurrentModelKeyInfo(model) {
|
||||
const modelKeyInfo = await this.modelsEntity.findOne({
|
||||
let modelKeyInfo = await this.modelsEntity.findOne({
|
||||
where: { model: model },
|
||||
});
|
||||
if (!modelKeyInfo) {
|
||||
throw new common_1.HttpException('当前调用模型的key未找到,请重新选择模型!', common_1.HttpStatus.BAD_REQUEST);
|
||||
return null;
|
||||
}
|
||||
return modelKeyInfo;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ let ModelsService = class ModelsService {
|
||||
const modifiedModel = Object.assign(Object.assign({}, firstMatchModel), { model: modifiedModelName });
|
||||
return modifiedModel;
|
||||
}
|
||||
async getBaseConfig(appId) {
|
||||
async getBaseConfig() {
|
||||
if (!this.modelTypes.length || !Object.keys(this.modelMaps).length)
|
||||
return;
|
||||
const { keyType, modelName, model, deductType, deduct, isFileUpload, modelAvatar, modelDescription, } = this.modelMaps[1][0];
|
||||
|
||||
4
dist/modules/official/official.service.js
vendored
4
dist/modules/official/official.service.js
vendored
@@ -109,13 +109,13 @@ let OfficialService = class OfficialService {
|
||||
}
|
||||
async scan(openID, sceneStr) {
|
||||
try {
|
||||
common_1.Logger.log(`Scanning with openID: ${openID}, sceneStr: ${sceneStr}`);
|
||||
common_1.Logger.log(`Scanning with openID: ${openID}, sceneStr: ${sceneStr}`, 'OfficialService');
|
||||
if (!this.sceneStrMap[sceneStr]) {
|
||||
common_1.Logger.error(`非法参数: 未找到的 sceneStr ${sceneStr}`);
|
||||
throw new common_1.HttpException('非法参数', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const user = await this.userService.getUserFromOpenId(openID, sceneStr);
|
||||
common_1.Logger.log(`User found: ${user ? user.id : 'No user found'}`);
|
||||
common_1.Logger.log(`User found: ${user ? user.id : 'No user found'}`, 'OfficialService');
|
||||
this.scanedSceneStrMap[sceneStr] = user.id;
|
||||
}
|
||||
catch (error) {
|
||||
|
||||
211
dist/modules/pay/pay.service.js
vendored
211
dist/modules/pay/pay.service.js
vendored
@@ -52,13 +52,17 @@ let PayService = class PayService {
|
||||
return this.notifyMpay(params);
|
||||
}
|
||||
async pay(userId, orderId, payType = 'wxpay') {
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
console.log('本次支付类型: ', order.payPlatform);
|
||||
common_1.Logger.log('本次支付类型: ', order.payPlatform);
|
||||
try {
|
||||
if (order.payPlatform == 'wechat') {
|
||||
return this.payWeChat(userId, orderId, payType);
|
||||
@@ -77,7 +81,7 @@ let PayService = class PayService {
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log('支付请求失败: ', error);
|
||||
common_1.Logger.log('支付请求失败: ', error);
|
||||
throw new common_1.HttpException('支付请求失败!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -88,12 +92,16 @@ let PayService = class PayService {
|
||||
return order;
|
||||
}
|
||||
async notifyHupi(params) {
|
||||
const payHupiSecret = await this.globalConfigService.getConfigs(['payHupiSecret']);
|
||||
const payHupiSecret = await this.globalConfigService.getConfigs([
|
||||
'payHupiSecret',
|
||||
]);
|
||||
const hash = params['hash'];
|
||||
delete params['hash'];
|
||||
if (this.sign(params, payHupiSecret) != hash)
|
||||
return 'failed';
|
||||
const order = await this.orderEntity.findOne({ where: { orderId: params['trade_order_id'], status: 0 } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { orderId: params['trade_order_id'], status: 0 },
|
||||
});
|
||||
if (!order)
|
||||
return 'failed';
|
||||
await this.userBalanceService.addBalanceToOrder(order);
|
||||
@@ -103,18 +111,22 @@ let PayService = class PayService {
|
||||
return 'success';
|
||||
}
|
||||
async payHupi(userId, orderId, payType = 'wxpay') {
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { payHupiAppId, payHupiSecret, payHupiNotifyUrl, payHupiReturnUrl, payHupiGatewayUrl } = await this.globalConfigService.getConfigs([
|
||||
const { payHupiAppId, payHupiSecret, payHupiNotifyUrl, payHupiReturnUrl, payHupiGatewayUrl, } = await this.globalConfigService.getConfigs([
|
||||
'payHupiAppId',
|
||||
'payHupiSecret',
|
||||
'payHupiNotifyUrl',
|
||||
'payHupiReturnUrl',
|
||||
'payHupiGatewayUrl'
|
||||
'payHupiGatewayUrl',
|
||||
]);
|
||||
const params = {};
|
||||
params['version'] = '1.1';
|
||||
@@ -134,7 +146,10 @@ let PayService = class PayService {
|
||||
return { url_qrcode, url };
|
||||
}
|
||||
async queryHupi(orderId) {
|
||||
const { payHupiAppId, payHupiSecret } = await this.globalConfigService.getConfigs(['payHupiAppId', 'payHupiSecret']);
|
||||
const { payHupiAppId, payHupiSecret } = await this.globalConfigService.getConfigs([
|
||||
'payHupiAppId',
|
||||
'payHupiSecret',
|
||||
]);
|
||||
const params = {};
|
||||
params['version'] = '1.1';
|
||||
params['appid'] = payHupiAppId;
|
||||
@@ -151,11 +166,15 @@ let PayService = class PayService {
|
||||
const sign = params['sign'];
|
||||
delete params['sign'];
|
||||
delete params['sign_type'];
|
||||
const payEpaySecret = await this.globalConfigService.getConfigs(['payEpaySecret']);
|
||||
const payEpaySecret = await this.globalConfigService.getConfigs([
|
||||
'payEpaySecret',
|
||||
]);
|
||||
if (this.sign(params, payEpaySecret) != sign)
|
||||
return 'failed';
|
||||
console.log('校验签名通过');
|
||||
const order = await this.orderEntity.findOne({ where: { orderId: params['out_trade_no'], status: 0 } });
|
||||
common_1.Logger.log('校验签名通过');
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { orderId: params['out_trade_no'], status: 0 },
|
||||
});
|
||||
if (!order)
|
||||
return 'failed';
|
||||
const status = params['trade_status'] == 'TRADE_SUCCESS' ? 1 : 2;
|
||||
@@ -168,13 +187,17 @@ let PayService = class PayService {
|
||||
return 'success';
|
||||
}
|
||||
async payEpay(userId, orderId, payType = 'alipay') {
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { payEpayPid, payEpaySecret, payEpayNotifyUrl, payEpayReturnUrl, payEpayApiPayUrl } = await this.globalConfigService.getConfigs([
|
||||
const { payEpayPid, payEpaySecret, payEpayNotifyUrl, payEpayReturnUrl, payEpayApiPayUrl, } = await this.globalConfigService.getConfigs([
|
||||
'payEpayPid',
|
||||
'payEpaySecret',
|
||||
'payEpayNotifyUrl',
|
||||
@@ -204,15 +227,30 @@ let PayService = class PayService {
|
||||
const queryParams = new URLSearchParams(params).toString();
|
||||
const apiUrl = `${payEpayApiPayUrl}?${queryParams}`;
|
||||
if (payEpayApiPayUrl.includes('submit.php')) {
|
||||
return { url_qrcode: null, redirectUrl: apiUrl, channel: payType, isRedirect: true };
|
||||
return {
|
||||
url_qrcode: null,
|
||||
redirectUrl: apiUrl,
|
||||
channel: payType,
|
||||
isRedirect: true,
|
||||
};
|
||||
}
|
||||
else {
|
||||
const res = await axios_1.default.get(payEpayApiPayUrl, { params });
|
||||
console.log('epay ---> res: ', res.data);
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
};
|
||||
const res = await axios_1.default.post(payEpayApiPayUrl, params, config);
|
||||
common_1.Logger.log('epay ---> res: ', res.data);
|
||||
const { data: { code, msg, qrcode: url_qrcode }, } = res;
|
||||
if (code != 1)
|
||||
throw new common_1.HttpException(msg, common_1.HttpStatus.BAD_REQUEST);
|
||||
return { url_qrcode, redirectUrl: null, channel: payType, isRedirect: false };
|
||||
return {
|
||||
url_qrcode,
|
||||
redirectUrl: null,
|
||||
channel: payType,
|
||||
isRedirect: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
async queryEpay(orderId) {
|
||||
@@ -235,16 +273,20 @@ let PayService = class PayService {
|
||||
const sign = params['sign'];
|
||||
delete params['sign'];
|
||||
delete params['sign_type'];
|
||||
const payMpaySecret = await this.globalConfigService.getConfigs(['payMpaySecret']);
|
||||
console.log('校验签名');
|
||||
const payMpaySecret = await this.globalConfigService.getConfigs([
|
||||
'payMpaySecret',
|
||||
]);
|
||||
common_1.Logger.log('校验签名');
|
||||
if (this.sign(params, payMpaySecret) != sign)
|
||||
return 'failed';
|
||||
console.log('校验签名通过');
|
||||
const order = await this.orderEntity.findOne({ where: { orderId: params['out_trade_no'], status: 0 } });
|
||||
common_1.Logger.log('校验签名通过');
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { orderId: params['out_trade_no'], status: 0 },
|
||||
});
|
||||
if (!order)
|
||||
return 'failed';
|
||||
const status = params['trade_status'] == 'TRADE_SUCCESS' ? 1 : 2;
|
||||
console.log('status: ', status);
|
||||
common_1.Logger.log('status: ', status);
|
||||
const result = await this.orderEntity.update({ orderId: params['out_trade_no'] }, { status, paydAt: new Date() });
|
||||
if (status === 1) {
|
||||
await this.userBalanceService.addBalanceToOrder(order);
|
||||
@@ -254,13 +296,17 @@ let PayService = class PayService {
|
||||
return 'success';
|
||||
}
|
||||
async payMpay(userId, orderId, payType = 'wxpay') {
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { payMpayPid, payMpaySecret, payMpayNotifyUrl, payMpayReturnUrl, payMpayApiPayUrl } = await this.globalConfigService.getConfigs([
|
||||
const { payMpayPid, payMpaySecret, payMpayNotifyUrl, payMpayReturnUrl, payMpayApiPayUrl, } = await this.globalConfigService.getConfigs([
|
||||
'payMpayPid',
|
||||
'payMpaySecret',
|
||||
'payMpayNotifyUrl',
|
||||
@@ -279,11 +325,20 @@ let PayService = class PayService {
|
||||
params['sign_type'] = 'MD5';
|
||||
const queryParams = new URLSearchParams(params).toString();
|
||||
const apiUrl = `${payMpayApiPayUrl}?${queryParams}`;
|
||||
return { url_qrcode: null, redirectUrl: apiUrl, channel: payType, isRedirect: true };
|
||||
return {
|
||||
url_qrcode: null,
|
||||
redirectUrl: apiUrl,
|
||||
channel: payType,
|
||||
isRedirect: true,
|
||||
};
|
||||
const res = await axios_1.default.get(payMpayApiPayUrl, { params });
|
||||
}
|
||||
async queryMpay(orderId) {
|
||||
const { payMpayApiQueryUrl } = await this.globalConfigService.getConfigs(['payMpayPid', 'payMpaySecret', 'payMpayApiQueryUrl']);
|
||||
const { payMpayApiQueryUrl } = await this.globalConfigService.getConfigs([
|
||||
'payMpayPid',
|
||||
'payMpaySecret',
|
||||
'payMpayApiQueryUrl',
|
||||
]);
|
||||
const params = {};
|
||||
params['type'] = 2;
|
||||
params['order_no'] = orderId;
|
||||
@@ -293,8 +348,8 @@ let PayService = class PayService {
|
||||
return result;
|
||||
}
|
||||
async notifyWeChat(params) {
|
||||
console.log('微信支付通知params: ', params);
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatSecret, payWeChatPublicKey, payWeChatPrivateKey } = await this.globalConfigService.getConfigs([
|
||||
common_1.Logger.log('微信支付通知params: ', params);
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatSecret, payWeChatPublicKey, payWeChatPrivateKey, } = await this.globalConfigService.getConfigs([
|
||||
'payWeChatAppId',
|
||||
'payWeChatMchId',
|
||||
'payWeChatSecret',
|
||||
@@ -311,7 +366,9 @@ let PayService = class PayService {
|
||||
if (params['event_type'] == 'TRANSACTION.SUCCESS') {
|
||||
const { ciphertext, associated_data, nonce } = params['resource'];
|
||||
const resource = pay.decipher_gcm(ciphertext, associated_data, nonce, payWeChatSecret);
|
||||
const order = await this.orderEntity.findOne({ where: { orderId: resource['out_trade_no'], status: 0 } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { orderId: resource['out_trade_no'], status: 0 },
|
||||
});
|
||||
if (!order)
|
||||
return 'failed';
|
||||
const status = resource['trade_state'] == 'SUCCESS' ? 1 : 2;
|
||||
@@ -325,28 +382,30 @@ let PayService = class PayService {
|
||||
return 'success';
|
||||
}
|
||||
catch (error) {
|
||||
console.log('error: ', error);
|
||||
console.log('支付通知验证失败: ', error);
|
||||
common_1.Logger.log('error: ', error);
|
||||
common_1.Logger.log('支付通知验证失败: ', error);
|
||||
return 'failed';
|
||||
}
|
||||
}
|
||||
async payWeChat(userId, orderId, payType = 'native') {
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
console.log('payType: ', payType);
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
common_1.Logger.log('payType: ', payType);
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatPublicKey, payWeChatPrivateKey, payWeChatNotifyUrl, payWeChatH5Name, payWeChatH5Url } = await this.globalConfigService.getConfigs([
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatPublicKey, payWeChatPrivateKey, payWeChatNotifyUrl, } = await this.globalConfigService.getConfigs([
|
||||
'payWeChatAppId',
|
||||
'payWeChatMchId',
|
||||
'payWeChatPublicKey',
|
||||
'payWeChatPrivateKey',
|
||||
'payWeChatNotifyUrl',
|
||||
'payWeChatH5Name',
|
||||
'payWeChatH5Url',
|
||||
]);
|
||||
const pay = new this.WxPay({
|
||||
appid: payWeChatAppId,
|
||||
@@ -364,17 +423,17 @@ let PayService = class PayService {
|
||||
total: Math.round(order.total * 100),
|
||||
},
|
||||
};
|
||||
console.log('wechat-pay: ', params);
|
||||
common_1.Logger.log('wechat-pay: ', params);
|
||||
if (payType == 'jsapi') {
|
||||
console.log(`[WeChat Pay JSAPI] 开始JSAPI支付流程,用户ID: ${userId}, 订单ID: ${orderId}`);
|
||||
common_1.Logger.log(`[WeChat Pay JSAPI] 开始JSAPI支付流程,用户ID: ${userId}, 订单ID: ${orderId}`);
|
||||
const openid = await this.userService.getOpenIdByUserId(userId);
|
||||
console.log(`[WeChat Pay JSAPI] 用户OpenID: ${openid}`);
|
||||
common_1.Logger.log(`[WeChat Pay JSAPI] 用户OpenID: ${openid}`);
|
||||
params['payer'] = { openid: openid };
|
||||
console.log(`[WeChat Pay JSAPI] 发送支付请求参数: `, JSON.stringify(params, null, 2));
|
||||
common_1.Logger.log(`[WeChat Pay JSAPI] 发送支付请求参数: `, JSON.stringify(params, null, 2));
|
||||
try {
|
||||
const response = await pay.transactions_jsapi(params);
|
||||
const result = response.data ? response.data : response;
|
||||
console.log(`[WeChat Pay JSAPI] 支付请求成功,返回结果: `, JSON.stringify(result, null, 2));
|
||||
common_1.Logger.log(`[WeChat Pay JSAPI] 支付请求成功,返回结果: `, JSON.stringify(result, null, 2));
|
||||
return {
|
||||
status: response.status || 'unknown',
|
||||
appId: result.appId || ((_a = result.data) === null || _a === void 0 ? void 0 : _a.appId),
|
||||
@@ -382,7 +441,7 @@ let PayService = class PayService {
|
||||
nonceStr: result.nonceStr || ((_c = result.data) === null || _c === void 0 ? void 0 : _c.nonceStr),
|
||||
package: result.package || ((_d = result.data) === null || _d === void 0 ? void 0 : _d.package),
|
||||
signType: result.signType || ((_e = result.data) === null || _e === void 0 ? void 0 : _e.signType),
|
||||
paySign: result.paySign || ((_f = result.data) === null || _f === void 0 ? void 0 : _f.paySign)
|
||||
paySign: result.paySign || ((_f = result.data) === null || _f === void 0 ? void 0 : _f.paySign),
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
@@ -392,16 +451,16 @@ let PayService = class PayService {
|
||||
}
|
||||
}
|
||||
if (payType == 'native') {
|
||||
console.log(`开始进行微信Native支付流程,订单ID: ${orderId}, 用户ID: ${userId}`);
|
||||
common_1.Logger.log(`开始进行微信Native支付流程,订单ID: ${orderId}, 用户ID: ${userId}`);
|
||||
try {
|
||||
const res = await pay.transactions_native(params);
|
||||
console.log(`微信Native支付响应数据: `, JSON.stringify(res, null, 2));
|
||||
common_1.Logger.log(`微信Native支付响应数据: `, JSON.stringify(res, null, 2));
|
||||
let url_qrcode = res.code_url || ((_g = res.data) === null || _g === void 0 ? void 0 : _g.code_url);
|
||||
if (!url_qrcode) {
|
||||
console.error(`微信Native支付请求成功,但未返回code_url,响应数据: `, JSON.stringify(res, null, 2));
|
||||
}
|
||||
else {
|
||||
console.log(`微信Native支付请求成功,code_url: ${url_qrcode}`);
|
||||
common_1.Logger.log(`微信Native支付请求成功,code_url: ${url_qrcode}`);
|
||||
}
|
||||
return { url_qrcode, isRedirect: false };
|
||||
}
|
||||
@@ -417,7 +476,12 @@ let PayService = class PayService {
|
||||
}
|
||||
}
|
||||
async queryWeChat(orderId) {
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatPublicKey, payWeChatPrivateKey, payWeChatNotifyUrl, payWeChatH5Name, payWeChatH5Url } = await this.globalConfigService.getConfigs(['payWeChatAppId', 'payWeChatMchId', 'payWeChatPublicKey', 'payWeChatPrivateKey']);
|
||||
const { payWeChatAppId, payWeChatMchId, payWeChatPublicKey, payWeChatPrivateKey, payWeChatNotifyUrl, } = await this.globalConfigService.getConfigs([
|
||||
'payWeChatAppId',
|
||||
'payWeChatMchId',
|
||||
'payWeChatPublicKey',
|
||||
'payWeChatPrivateKey',
|
||||
]);
|
||||
const pay = new this.WxPay({
|
||||
appid: payWeChatAppId,
|
||||
mchid: payWeChatMchId,
|
||||
@@ -438,21 +502,25 @@ let PayService = class PayService {
|
||||
const paramsArr = Object.keys(params);
|
||||
paramsArr.sort();
|
||||
const stringArr = [];
|
||||
paramsArr.map(key => {
|
||||
paramsArr.map((key) => {
|
||||
stringArr.push(key + '=' + params[key]);
|
||||
});
|
||||
stringArr.push("key=" + secret);
|
||||
stringArr.push('key=' + secret);
|
||||
const str = stringArr.join('&');
|
||||
return crypto.createHash('md5').update(str).digest('hex').toUpperCase();
|
||||
}
|
||||
async payLtzf(userId, orderId, payType = 'wxpay') {
|
||||
const order = await this.orderEntity.findOne({ where: { userId, orderId } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { userId, orderId },
|
||||
});
|
||||
if (!order)
|
||||
throw new common_1.HttpException('订单不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const goods = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId } });
|
||||
const goods = await this.cramiPackageEntity.findOne({
|
||||
where: { id: order.goodsId },
|
||||
});
|
||||
if (!goods)
|
||||
throw new common_1.HttpException('套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
|
||||
const { payLtzfMchId, payLtzfSecret, payLtzfNotifyUrl, payLtzfReturnUrl, } = await this.globalConfigService.getConfigs([
|
||||
const { payLtzfMchId, payLtzfSecret, payLtzfNotifyUrl, payLtzfReturnUrl } = await this.globalConfigService.getConfigs([
|
||||
'payLtzfMchId',
|
||||
'payLtzfSecret',
|
||||
'payLtzfNotifyUrl',
|
||||
@@ -468,11 +536,13 @@ let PayService = class PayService {
|
||||
params['sign'] = this.ltzfSign(params, payLtzfSecret);
|
||||
params['attach'] = 'ltzf';
|
||||
params['return_url'] = payLtzfReturnUrl;
|
||||
const formBody = Object.keys(params).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key])).join('&');
|
||||
const formBody = Object.keys(params)
|
||||
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
|
||||
.join('&');
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
};
|
||||
const response = await axios_1.default.post('https://api.ltzf.cn/api/wxpay/jsapi_convenient', formBody, config);
|
||||
const { code, data, msg } = response.data;
|
||||
@@ -483,17 +553,22 @@ let PayService = class PayService {
|
||||
return { url_qrcode, url };
|
||||
}
|
||||
async queryLtzf(orderId) {
|
||||
const { payLtzfMchId, payLtzfSecret } = await this.globalConfigService.getConfigs(['payLtzfMchId', 'payLtzfSecret']);
|
||||
const { payLtzfMchId, payLtzfSecret } = await this.globalConfigService.getConfigs([
|
||||
'payLtzfMchId',
|
||||
'payLtzfSecret',
|
||||
]);
|
||||
const params = {};
|
||||
params['mch_id'] = payLtzfMchId;
|
||||
params['timestamp'] = (Date.now() / 1000).toFixed(0);
|
||||
params['out_trade_no'] = orderId;
|
||||
params['sign'] = this.ltzfSign(params, payLtzfSecret);
|
||||
const formBody = Object.keys(params).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key])).join('&');
|
||||
const formBody = Object.keys(params)
|
||||
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
|
||||
.join('&');
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
};
|
||||
const { data: { code, msg, data: result }, } = await axios_1.default.post('https://api.ltzf.cn/api/wxpay/get_pay_order', formBody, config);
|
||||
if (code != 0)
|
||||
@@ -501,7 +576,9 @@ let PayService = class PayService {
|
||||
return result;
|
||||
}
|
||||
async notifyLtzf(params) {
|
||||
const payLtzfSecret = await this.globalConfigService.getConfigs(['payLtzfSecret']);
|
||||
const payLtzfSecret = await this.globalConfigService.getConfigs([
|
||||
'payLtzfSecret',
|
||||
]);
|
||||
const hash = params['sign'];
|
||||
delete params['sign'];
|
||||
delete params['pay_channel'];
|
||||
@@ -511,7 +588,9 @@ let PayService = class PayService {
|
||||
delete params['openid'];
|
||||
if (this.ltzfSign(params, payLtzfSecret) != hash)
|
||||
return 'FAIL';
|
||||
const order = await this.orderEntity.findOne({ where: { orderId: params['out_trade_no'], status: 0 } });
|
||||
const order = await this.orderEntity.findOne({
|
||||
where: { orderId: params['out_trade_no'], status: 0 },
|
||||
});
|
||||
if (!order)
|
||||
return 'FAIL';
|
||||
await this.userBalanceService.addBalanceToOrder(order);
|
||||
|
||||
27
dist/modules/plugin/plugin.service.js
vendored
27
dist/modules/plugin/plugin.service.js
vendored
@@ -16,19 +16,37 @@ exports.PluginService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const models_service_1 = require("../models/models.service");
|
||||
const plugin_entity_1 = require("./plugin.entity");
|
||||
let PluginService = class PluginService {
|
||||
constructor(PluginEntity) {
|
||||
constructor(PluginEntity, modelsService) {
|
||||
this.PluginEntity = PluginEntity;
|
||||
this.modelsService = modelsService;
|
||||
}
|
||||
async pluginList(query) {
|
||||
const { page = 1, size = 1000 } = query;
|
||||
const { page = 1, size = 100 } = query;
|
||||
const rows = await this.PluginEntity.find({
|
||||
order: { sortOrder: 'ASC', id: 'DESC' },
|
||||
skip: (page - 1) * size,
|
||||
take: size,
|
||||
});
|
||||
return { rows, count: rows.length };
|
||||
const processedRows = await Promise.all(rows.map(async (plugin) => {
|
||||
if (plugin.isSystemPlugin === 1) {
|
||||
try {
|
||||
const parameters = await this.modelsService.getCurrentModelKeyInfo(plugin.parameters);
|
||||
const deductType = parameters.deductType;
|
||||
return Object.assign(Object.assign({}, plugin), { deductType });
|
||||
}
|
||||
catch (error) {
|
||||
return Object.assign(Object.assign({}, plugin), { deductType: 0 });
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Object.assign(Object.assign({}, plugin), { deductType: 0 });
|
||||
}
|
||||
}));
|
||||
const filteredRows = processedRows.filter((plugin) => plugin !== null);
|
||||
return { rows: filteredRows, count: filteredRows.length };
|
||||
}
|
||||
async createPlugin(body) {
|
||||
const { name, pluginImg, description, isEnabled, isSystemPlugin, parameters, sortOrder, } = body;
|
||||
@@ -98,6 +116,7 @@ let PluginService = class PluginService {
|
||||
PluginService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(plugin_entity_1.PluginEntity)),
|
||||
__metadata("design:paramtypes", [typeorm_2.Repository])
|
||||
__metadata("design:paramtypes", [typeorm_2.Repository,
|
||||
models_service_1.ModelsService])
|
||||
], PluginService);
|
||||
exports.PluginService = PluginService;
|
||||
|
||||
94
dist/modules/statistic/statistic.service.js
vendored
94
dist/modules/statistic/statistic.service.js
vendored
@@ -220,6 +220,36 @@ let StatisticService = class StatisticService {
|
||||
}
|
||||
return dailyData;
|
||||
}
|
||||
async getNewAccessToken(baiduApiKey, baiduSecretKey, baiduRefreshToken) {
|
||||
const tokenUrl = `http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token=${baiduRefreshToken}&client_id=${baiduApiKey}&client_secret=${baiduSecretKey}`;
|
||||
common_1.Logger.log('获取新 accessToken', tokenUrl);
|
||||
try {
|
||||
const tokenRes = await axios_1.default.get(tokenUrl);
|
||||
if (tokenRes.status === 200 && tokenRes.data.access_token) {
|
||||
return {
|
||||
accessToken: tokenRes.data.access_token,
|
||||
refreshToken: tokenRes.data.refresh_token,
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error('Failed to get new access token');
|
||||
}
|
||||
}
|
||||
catch (tokenError) {
|
||||
common_1.Logger.error('获取新 accessToken 失败', {
|
||||
message: tokenError.message,
|
||||
stack: tokenError.stack,
|
||||
response: tokenError.response
|
||||
? tokenError.response.data
|
||||
: 'No response data',
|
||||
});
|
||||
throw new common_1.HttpException('获取新 accessToken 失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async updateAccessTokenInDatabase(accessToken, refreshToken, configEntity) {
|
||||
await configEntity.update({ configKey: 'baiduToken' }, { configVal: accessToken });
|
||||
await configEntity.update({ configKey: 'baiduRefreshToken' }, { configVal: refreshToken });
|
||||
}
|
||||
async getBaiduStatistics(days) {
|
||||
const end_date = (0, date_1.formatDate)(new Date(), 'YYYYMMDD');
|
||||
const start_date = (0, date_1.formatDate)(new Date(Date.now() - Number(days - 1) * 24 * 60 * 60 * 1000), 'YYYYMMDD');
|
||||
@@ -232,58 +262,34 @@ let StatisticService = class StatisticService {
|
||||
'baiduSecretKey',
|
||||
'baiduRefreshToken',
|
||||
]);
|
||||
if (!baiduApiKey ||
|
||||
!baiduToken ||
|
||||
!baiduSiteId ||
|
||||
!baiduRefreshToken ||
|
||||
!baiduSecretKey) {
|
||||
if (!baiduApiKey || !baiduSiteId || !baiduRefreshToken || !baiduSecretKey) {
|
||||
return [];
|
||||
}
|
||||
let accessToken = baiduToken;
|
||||
let url = `https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=${accessToken}&site_id=${baiduSiteId}&method=${method}&start_date=${start_date}&end_date=${end_date}&metrics=${metrics}`;
|
||||
let res;
|
||||
try {
|
||||
res = await axios_1.default.get(url);
|
||||
}
|
||||
catch (error) {
|
||||
res = {
|
||||
data: {
|
||||
error_code: 111,
|
||||
message: 'Access token invalid or no longer valid',
|
||||
},
|
||||
};
|
||||
}
|
||||
let { error_code, message } = res.data;
|
||||
if (error_code === 111) {
|
||||
const tokenUrl = `http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token=${baiduRefreshToken}&client_id=${baiduApiKey}&client_secret=${baiduSecretKey}`;
|
||||
common_1.Logger.log('获取新 accessToken', tokenUrl);
|
||||
let tokenRes;
|
||||
let url;
|
||||
const fetchData = async (token) => {
|
||||
url = `https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${baiduSiteId}&method=${method}&start_date=${start_date}&end_date=${end_date}&metrics=${metrics}`;
|
||||
try {
|
||||
tokenRes = await axios_1.default.get(tokenUrl);
|
||||
return await axios_1.default.get(url);
|
||||
}
|
||||
catch (tokenError) {
|
||||
common_1.Logger.error('获取新 accessToken 失败', {
|
||||
message: tokenError.message,
|
||||
stack: tokenError.stack,
|
||||
response: tokenError.response
|
||||
? tokenError.response.data
|
||||
: 'No response data',
|
||||
});
|
||||
throw new common_1.HttpException('获取新 accessToken 失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (tokenRes.status === 200 && tokenRes.data.access_token) {
|
||||
accessToken = tokenRes.data.access_token;
|
||||
await this.configEntity.update({ configKey: 'baiduToken' }, {
|
||||
configVal: accessToken,
|
||||
});
|
||||
url = `https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=${accessToken}&site_id=${baiduSiteId}&method=${method}&start_date=${start_date}&end_date=${end_date}&metrics=${metrics}`;
|
||||
res = await axios_1.default.get(url);
|
||||
({ error_code, message } = res.data);
|
||||
}
|
||||
else {
|
||||
throw new common_1.HttpException('获取新 accessToken 失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
catch (error) {
|
||||
return {
|
||||
data: {
|
||||
error_code: 111,
|
||||
message: 'Access token invalid or no longer valid',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
res = await fetchData(accessToken);
|
||||
if (res.data.error_code === 111 || !baiduToken) {
|
||||
const { accessToken: newAccessToken, refreshToken: newRefreshToken } = await this.getNewAccessToken(baiduApiKey, baiduSecretKey, baiduRefreshToken);
|
||||
accessToken = newAccessToken;
|
||||
await this.updateAccessTokenInDatabase(accessToken, newRefreshToken, this.configEntity);
|
||||
res = await fetchData(accessToken);
|
||||
}
|
||||
const { error_code, message } = res.data;
|
||||
if (error_code && error_code !== 200) {
|
||||
throw new common_1.HttpException(message || '获取百度统计数据失败', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
233
dist/modules/upload/upload.service.js
vendored
233
dist/modules/upload/upload.service.js
vendored
@@ -16,66 +16,75 @@ const ALIOSS = require("ali-oss");
|
||||
const axios_1 = require("axios");
|
||||
const TENCENTCOS = require("cos-nodejs-sdk-v5");
|
||||
const FormData = require("form-data");
|
||||
const fs = require("fs");
|
||||
const path_1 = require("path");
|
||||
const fs_1 = require("fs");
|
||||
const mime = require("mime-types");
|
||||
const path = require("path");
|
||||
const streamToBuffer = require("stream-to-buffer");
|
||||
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
|
||||
const blacklist = ['exe', 'sh', 'bat', 'js', 'php', 'py'];
|
||||
let UploadService = class UploadService {
|
||||
constructor(globalConfigService) {
|
||||
this.globalConfigService = globalConfigService;
|
||||
}
|
||||
onModuleInit() { }
|
||||
async uploadFile(file, dir = 'others') {
|
||||
const { filename: name, originalname, buffer, mimetype, } = file;
|
||||
if (process.env.ISDEV) {
|
||||
const { buffer, mimetype } = file;
|
||||
if (process.env.ISDEV === 'TRUE') {
|
||||
dir = `dev/${dir}`;
|
||||
}
|
||||
common_1.Logger.debug(`准备上传文件: ${dir}`, 'UploadService');
|
||||
const fileExtension = mime.extension(mimetype) || '';
|
||||
if (!fileExtension) {
|
||||
common_1.Logger.error('无法识别文件类型,请检查文件', 'UploadService');
|
||||
}
|
||||
if (blacklist.includes(fileExtension.toLowerCase())) {
|
||||
common_1.Logger.error('不允许上传此类型的文件', 'UploadService');
|
||||
throw new Error('不允许上传此类型的文件');
|
||||
}
|
||||
const now = new Date();
|
||||
const timestamp = now.getTime();
|
||||
const randomString = Math.random().toString(36).substring(2, 6);
|
||||
const fileType = mimetype ? mimetype.split('/')[1] : '';
|
||||
const filename = `${timestamp}_${randomString}.${fileType}`;
|
||||
common_1.Logger.debug(`准备上传文件: ${filename}, 类型: ${fileType}`, 'UploadService');
|
||||
const filename = `${timestamp}_${randomString}.${fileExtension}`;
|
||||
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs([
|
||||
'tencentCosStatus',
|
||||
'aliOssStatus',
|
||||
'cheveretoStatus',
|
||||
]);
|
||||
common_1.Logger.debug(`上传配置状态 - 腾讯云: ${tencentCosStatus}, 阿里云: ${aliOssStatus}, Chevereto: ${cheveretoStatus}`, 'UploadService');
|
||||
common_1.Logger.log(`上传配置状态 - 腾讯云: ${tencentCosStatus}, 阿里云: ${aliOssStatus}, Chevereto: ${cheveretoStatus}`, 'UploadService');
|
||||
if (!Number(tencentCosStatus) &&
|
||||
!Number(aliOssStatus) &&
|
||||
!Number(cheveretoStatus)) {
|
||||
common_1.Logger.error('未配置任何上传方式', 'UploadService');
|
||||
throw new common_1.HttpException('请先前往后台配置上传图片的方式', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
try {
|
||||
if (Number(tencentCosStatus)) {
|
||||
common_1.Logger.debug(`使用腾讯云COS上传`, 'UploadService');
|
||||
return await this.uploadFileByTencentCos({
|
||||
common_1.Logger.log('使用腾讯云 COS 上传文件', 'UploadService');
|
||||
const result = await this.uploadFileByTencentCos({
|
||||
filename,
|
||||
buffer,
|
||||
dir,
|
||||
fileType,
|
||||
});
|
||||
common_1.Logger.log(`文件已上传到腾讯云 COS。访问 URL: ${result}`, 'UploadService');
|
||||
return result;
|
||||
}
|
||||
if (Number(aliOssStatus)) {
|
||||
common_1.Logger.debug(`使用阿里云OSS上传`, 'UploadService');
|
||||
return await this.uploadFileByAliOss({
|
||||
common_1.Logger.log('使用阿里云 OSS 上传文件', 'UploadService');
|
||||
const result = await this.uploadFileByAliOss({
|
||||
filename,
|
||||
buffer,
|
||||
dir,
|
||||
fileType,
|
||||
});
|
||||
common_1.Logger.log(`文件已上传到阿里云 OSS。访问 URL: ${result}`, 'UploadService');
|
||||
return result;
|
||||
}
|
||||
if (Number(cheveretoStatus)) {
|
||||
common_1.Logger.debug(`使用Chevereto上传`, 'UploadService');
|
||||
const { filename, buffer: fromBuffer, dir } = file;
|
||||
return await this.uploadFileByChevereto({
|
||||
common_1.Logger.log('使用 Chevereto 上传文件', 'UploadService');
|
||||
const result = await this.uploadFileByChevereto({
|
||||
filename,
|
||||
buffer: fromBuffer.toString('base64'),
|
||||
dir,
|
||||
fileType,
|
||||
buffer: buffer.toString('base64'),
|
||||
});
|
||||
common_1.Logger.log(`文件已上传到 Chevereto。访问 URL: ${result}`, 'UploadService');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -100,85 +109,13 @@ let UploadService = class UploadService {
|
||||
}
|
||||
}
|
||||
async uploadFileFromUrl({ url, dir = 'others' }) {
|
||||
if (process.env.ISDEV) {
|
||||
if (process.env.ISDEV === 'TRUE') {
|
||||
dir = `dev/${dir}`;
|
||||
}
|
||||
const now = new Date();
|
||||
const timestamp = now.getTime();
|
||||
const randomString = Math.random().toString(36).substring(2, 6);
|
||||
const response = await axios_1.default.head(url);
|
||||
const mimeType = response.headers['content-type'];
|
||||
let fileExtension = '';
|
||||
if (mimeType) {
|
||||
const mimeTypeMap = {
|
||||
'image/jpeg': 'jpg',
|
||||
'image/png': 'png',
|
||||
'image/gif': 'gif',
|
||||
'image/webp': 'webp',
|
||||
'image/bmp': 'bmp',
|
||||
'image/svg+xml': 'svg',
|
||||
'image/tiff': 'tiff',
|
||||
'image/x-icon': 'ico',
|
||||
'video/mp4': 'mp4',
|
||||
'video/mpeg': 'mpeg',
|
||||
'video/ogg': 'ogv',
|
||||
'video/webm': 'webm',
|
||||
'video/quicktime': 'mov',
|
||||
'video/x-msvideo': 'avi',
|
||||
'video/x-flv': 'flv',
|
||||
'audio/mpeg': 'mp3',
|
||||
'audio/ogg': 'ogg',
|
||||
'audio/wav': 'wav',
|
||||
'audio/x-wav': 'wav',
|
||||
'audio/webm': 'weba',
|
||||
'application/pdf': 'pdf',
|
||||
'application/msword': 'doc',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
|
||||
'application/vnd.ms-excel': 'xls',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
|
||||
'application/vnd.ms-powerpoint': 'ppt',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
|
||||
'application/zip': 'zip',
|
||||
'application/x-rar-compressed': 'rar',
|
||||
'application/x-7z-compressed': '7z',
|
||||
'text/plain': 'txt',
|
||||
'text/html': 'html',
|
||||
'text/css': 'css',
|
||||
'text/javascript': 'js',
|
||||
'application/json': 'json',
|
||||
'application/xml': 'xml',
|
||||
'application/octet-stream': 'bin',
|
||||
'application/vnd.android.package-archive': 'apk',
|
||||
'application/x-sh': 'sh',
|
||||
};
|
||||
fileExtension = mimeTypeMap[mimeType] || '';
|
||||
}
|
||||
const filename = fileExtension
|
||||
? `${timestamp}_${randomString}.${fileExtension}`
|
||||
: `${timestamp}_${randomString}`;
|
||||
common_1.Logger.debug(`准备上传文件: ${filename}, URL: ${url}, 目录: ${dir}`, 'UploadService');
|
||||
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs([
|
||||
'tencentCosStatus',
|
||||
'aliOssStatus',
|
||||
'cheveretoStatus',
|
||||
]);
|
||||
if (!Number(tencentCosStatus) &&
|
||||
!Number(aliOssStatus) &&
|
||||
!Number(cheveretoStatus)) {
|
||||
throw new common_1.HttpException('请先前往后台配置上传图片的方式', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (Number(tencentCosStatus)) {
|
||||
return this.uploadFileByTencentCosFromUrl({ filename, url, dir });
|
||||
}
|
||||
if (Number(aliOssStatus)) {
|
||||
const res = await this.uploadFileByAliOssFromUrl({ filename, url, dir });
|
||||
return res;
|
||||
}
|
||||
if (Number(cheveretoStatus)) {
|
||||
return await this.uploadFileByCheveretoFromUrl({ filename, url, dir });
|
||||
}
|
||||
const { buffer, mimeType } = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFile({ buffer, mimetype: mimeType }, dir);
|
||||
}
|
||||
async uploadFileByTencentCos({ filename, buffer, dir, fileType }) {
|
||||
async uploadFileByTencentCos({ filename, buffer, dir }) {
|
||||
const { Bucket, Region, SecretId, SecretKey } = await this.getUploadConfig('tencent');
|
||||
this.tencentCos = new TENCENTCOS({
|
||||
SecretId,
|
||||
@@ -187,11 +124,10 @@ let UploadService = class UploadService {
|
||||
});
|
||||
try {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const type = fileType || 'png';
|
||||
this.tencentCos.putObject({
|
||||
Bucket: (0, utils_1.removeSpecialCharacters)(Bucket),
|
||||
Region: (0, utils_1.removeSpecialCharacters)(Region),
|
||||
Key: `${dir}/${filename || `${(0, utils_1.createRandomUid)()}.${fileType}`}`,
|
||||
Key: `${dir}/${filename}`,
|
||||
StorageClass: 'STANDARD',
|
||||
Body: buffer,
|
||||
}, async (err, data) => {
|
||||
@@ -214,28 +150,7 @@ let UploadService = class UploadService {
|
||||
throw new common_1.HttpException('上传图片失败[ten]', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async uploadFileByTencentCosFromUrl({ filename, url, dir }) {
|
||||
const { Bucket, Region, SecretId, SecretKey } = await this.getUploadConfig('tencent');
|
||||
this.tencentCos = new TENCENTCOS({
|
||||
SecretId,
|
||||
SecretKey,
|
||||
FileParallelLimit: 10,
|
||||
});
|
||||
try {
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileByTencentCos({
|
||||
filename,
|
||||
buffer,
|
||||
dir,
|
||||
fileType: '',
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log('TODO->error: ', error);
|
||||
throw new common_1.HttpException('上传图片失败[ten][url]', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async uploadFileByAliOss({ filename, buffer, dir, fileType = 'png' }) {
|
||||
async uploadFileByAliOss({ filename, buffer, dir }) {
|
||||
const { region, bucket, accessKeyId, accessKeySecret } = await this.getUploadConfig('ali');
|
||||
const client = new ALIOSS({
|
||||
region: (0, utils_1.removeSpecialCharacters)(region),
|
||||
@@ -247,7 +162,7 @@ let UploadService = class UploadService {
|
||||
console.log('ali 开始上传');
|
||||
return new Promise((resolve, reject) => {
|
||||
client
|
||||
.put(`${dir}/${filename || `${(0, utils_1.createRandomUid)()}.${fileType}`}`, buffer)
|
||||
.put(`${dir}/${filename}`, buffer)
|
||||
.then(async (result) => {
|
||||
const { acceleratedDomain } = await this.getUploadConfig('ali');
|
||||
if (acceleratedDomain) {
|
||||
@@ -265,46 +180,38 @@ let UploadService = class UploadService {
|
||||
throw new common_1.HttpException('上传图片失败[ali]', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async uploadFileToLocalFromUrl({ filename, url, dir }) {
|
||||
async uploadFileToLocal({ filename, buffer, dir = 'others' }) {
|
||||
const normalizedDir = path.normalize(dir).replace(/^(\.\.(\/|\\|$))+/, '');
|
||||
const normalizedFilename = path.basename(filename);
|
||||
const projectRoot = process.cwd();
|
||||
const uploadDir = path.join(projectRoot, 'public', 'file', normalizedDir);
|
||||
const filePath = path.join(uploadDir, normalizedFilename);
|
||||
if (!filePath.startsWith(path.join(projectRoot, 'public', 'file'))) {
|
||||
throw new Error('非法路径,禁止访问目录之外的位置');
|
||||
}
|
||||
try {
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileToLocal({ filename, buffer, dir });
|
||||
await fs_1.promises.mkdir(uploadDir, { recursive: true });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('TODO->error: ', error);
|
||||
throw new common_1.HttpException('上传图片失败[ten][url]', common_1.HttpStatus.BAD_REQUEST);
|
||||
catch (err) {
|
||||
common_1.Logger.error(`创建目录失败: ${uploadDir}`, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async uploadFileToLocal({ filename, buffer, dir = 'ai' }) {
|
||||
if (!filename || !buffer) {
|
||||
throw new Error('必须提供文件名和文件内容');
|
||||
try {
|
||||
await fs_1.promises.writeFile(filePath, buffer, { mode: 0o444 });
|
||||
}
|
||||
const appRoot = require('app-root-path');
|
||||
const uploadDir = path_1.default.join(appRoot.path, 'service', 'public', 'file');
|
||||
const filePath = path_1.default.join(uploadDir, filename);
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true });
|
||||
common_1.Logger.log(`创建目录: ${uploadDir}`);
|
||||
catch (err) {
|
||||
common_1.Logger.error(`文件保存失败: ${filePath}`, err);
|
||||
throw err;
|
||||
}
|
||||
let fileUrl = `file/${normalizedDir}/${normalizedFilename}`;
|
||||
const siteUrl = await this.globalConfigService.getConfigs(['siteUrl']);
|
||||
if (siteUrl) {
|
||||
const url = (0, utils_1.formatUrl)(siteUrl);
|
||||
fileUrl = `${url}/${fileUrl}`;
|
||||
}
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
common_1.Logger.log(`文件已保存: ${filePath}`);
|
||||
const baseUrl = process.env.BASE_URL || 'http://127.0.0.1:9520';
|
||||
const fileUrl = `${baseUrl}/file/${filename}`;
|
||||
common_1.Logger.log(`文件可访问于: ${fileUrl}`);
|
||||
return fileUrl;
|
||||
}
|
||||
async uploadFileByAliOssFromUrl({ filename, url, dir }) {
|
||||
const { region, bucket, accessKeyId, accessKeySecret } = await this.getUploadConfig('ali');
|
||||
const client = new ALIOSS({ region, accessKeyId, accessKeySecret, bucket });
|
||||
try {
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileByAliOss({ filename, buffer, dir });
|
||||
}
|
||||
catch (error) {
|
||||
throw new common_1.HttpException('上传图片失败[ALI][url]', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async uploadFileByChevereto({ filename = '', buffer, dir = 'ai', fileType = 'png', }) {
|
||||
async uploadFileByChevereto({ filename = '', buffer }) {
|
||||
var _a;
|
||||
const { key, uploadPath } = await this.getUploadConfig('chevereto');
|
||||
let url = uploadPath.endsWith('/') ? uploadPath.slice(0, -1) : uploadPath;
|
||||
@@ -330,16 +237,6 @@ let UploadService = class UploadService {
|
||||
throw new common_1.HttpException(`上传图片失败[Chevereto|buffer] --> ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.data.error.message}`, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async uploadFileByCheveretoFromUrl({ filename, url, dir }) {
|
||||
try {
|
||||
const buffer = await this.getBufferFromUrl(url);
|
||||
return await this.uploadFileByChevereto({ filename, buffer, dir });
|
||||
}
|
||||
catch (error) {
|
||||
console.log('error: ', error);
|
||||
throw new common_1.HttpException(error.response, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async getUploadConfig(type) {
|
||||
if (type === 'ali') {
|
||||
const { aliOssRegion: region, aliOssBucket: bucket, aliOssAccessKeyId: accessKeyId, aliOssAccessKeySecret: accessKeySecret, aliOssAcceleratedDomain: acceleratedDomain, } = await this.globalConfigService.getConfigs([
|
||||
@@ -377,16 +274,18 @@ let UploadService = class UploadService {
|
||||
}
|
||||
async getBufferFromUrl(url) {
|
||||
const response = await axios_1.default.get(url, { responseType: 'stream' });
|
||||
return new Promise((resolve, reject) => {
|
||||
const buffer = await new Promise((resolve, reject) => {
|
||||
streamToBuffer(response.data, (err, buffer) => {
|
||||
if (err) {
|
||||
throw new common_1.HttpException('获取图片资源失败、请重新试试吧!', common_1.HttpStatus.BAD_REQUEST);
|
||||
reject(new common_1.HttpException('获取图片资源失败,请重新试试吧!', common_1.HttpStatus.BAD_REQUEST));
|
||||
}
|
||||
else {
|
||||
resolve(buffer);
|
||||
}
|
||||
});
|
||||
});
|
||||
const mimeType = response.headers['content-type'];
|
||||
return { buffer, mimeType };
|
||||
}
|
||||
};
|
||||
UploadService = __decorate([
|
||||
|
||||
5
dist/modules/user/user.service.js
vendored
5
dist/modules/user/user.service.js
vendored
@@ -207,6 +207,11 @@ let UserService = class UserService {
|
||||
userInfo.isBindWx = !!(userInfo === null || userInfo === void 0 ? void 0 : userInfo.openId);
|
||||
delete userInfo.openId;
|
||||
const userBalance = await this.userBalanceService.queryUserBalance(userId);
|
||||
const processedId = (userId * 123 + 100000000)
|
||||
.toString(36)
|
||||
.toUpperCase()
|
||||
.slice(-6);
|
||||
userInfo.id = processedId;
|
||||
return { userInfo, userBalance: Object.assign({}, userBalance) };
|
||||
}
|
||||
async getUserById(id) {
|
||||
|
||||
@@ -171,11 +171,11 @@ let UserBalanceService = class UserBalanceService {
|
||||
: null;
|
||||
if (b.packageId && b[memberKey] + b[baseKey] < amount) {
|
||||
if (b[baseKey] < amount) {
|
||||
throw new common_1.HttpException(`您的账户余额不足,如果想继续体验服务,请联系管理员或购买专属套餐 !`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
throw new common_1.HttpException(`积分不足,继续体验服务,请按需选购套餐!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
}
|
||||
if (!b.packageId && b[baseKey] < amount) {
|
||||
throw new common_1.HttpException(`您的账户余额不足,如果想继续体验服务,请联系管理员或购买专属套餐 !`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
throw new common_1.HttpException(`积分不足,继续体验服务,请按需选购套餐!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ let UserBalanceService = class UserBalanceService {
|
||||
};
|
||||
data[baseKey] = data[baseKey] + amount;
|
||||
if (data[baseKey] > settings[baseKey]) {
|
||||
throw new common_1.HttpException(`今日当前类型免费额度已经使用完毕、建议您注册账户体验更加完整的服务内容!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
throw new common_1.HttpException(`今日体验额度使用完毕,请注册使用完整服务!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
else {
|
||||
await this.fingerprintLogEntity.save(data);
|
||||
@@ -239,7 +239,7 @@ let UserBalanceService = class UserBalanceService {
|
||||
data[baseKey] = data[baseKey] + amount;
|
||||
}
|
||||
if (data[baseKey] > settings[baseKey]) {
|
||||
throw new common_1.HttpException(`今日当前类型免费额度已经使用完毕、建议您注册账户体验更加完整的服务内容!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
throw new common_1.HttpException(`今日体验额度使用完毕,请注册使用完整服务!`, common_1.HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
else {
|
||||
await this.fingerprintLogEntity.update({ fingerprint: id }, data);
|
||||
|
||||
@@ -29,8 +29,12 @@ let VerificationService = class VerificationService {
|
||||
this.redisCacheService = redisCacheService;
|
||||
}
|
||||
async createVerification(user, type, expir = 30 * 60) {
|
||||
const historyVerify = await this.verifycationEntity.findOne({ where: { userId: user.id, type }, order: { createdAt: 'DESC' } });
|
||||
if (historyVerify && historyVerify.createdAt.getTime() + 1 * 60 * 1000 > Date.now()) {
|
||||
const historyVerify = await this.verifycationEntity.findOne({
|
||||
where: { userId: user.id, type },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
if (historyVerify &&
|
||||
historyVerify.createdAt.getTime() + 1 * 60 * 1000 > Date.now()) {
|
||||
const diffS = Math.ceil((historyVerify.createdAt.getTime() + 1 * 60 * 1000 - Date.now()) / 1000);
|
||||
throw new common_1.HttpException(`${diffS}S内不得重新发送`, common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -41,7 +45,10 @@ let VerificationService = class VerificationService {
|
||||
return await this.verifycationEntity.save(verifycation);
|
||||
}
|
||||
async verifyCode({ code, id }, type) {
|
||||
const v = await this.verifycationEntity.findOne({ where: { id, type }, order: { createdAt: 'DESC' } });
|
||||
const v = await this.verifycationEntity.findOne({
|
||||
where: { id, type },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
if (!v) {
|
||||
throw new common_1.HttpException('验证码不存在', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
@@ -60,29 +67,26 @@ let VerificationService = class VerificationService {
|
||||
}
|
||||
return v;
|
||||
}
|
||||
async verifyCaptcha(body) {
|
||||
const { captchaId, captchaCode } = body;
|
||||
const nameSpace = await this.globalConfigService.getNamespace();
|
||||
const key = `${nameSpace}:CAPTCHA:${captchaId}`;
|
||||
const code = await this.redisCacheService.get({ key });
|
||||
await this.redisCacheService.del({ key });
|
||||
if (!code) {
|
||||
throw new common_1.HttpException('图形验证码已过期、请重新输入!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (!code || code !== captchaCode) {
|
||||
throw new common_1.HttpException('图形验证码错误、请检查填写!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
async sendPhoneCode(messageInfo) {
|
||||
var _a;
|
||||
const { accessKeyId, accessKeySecret, SignName, TemplateCode } = await this.globalConfigService.getPhoneVerifyConfig();
|
||||
console.log("Received messageInfo:", messageInfo);
|
||||
console.log('Received messageInfo:', messageInfo);
|
||||
const { phone, code } = messageInfo;
|
||||
if (!phone || !code) {
|
||||
throw new common_1.HttpException('确实必要参数错误!', common_1.HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
const client = new Core({ accessKeyId, accessKeySecret, endpoint: 'https://dysmsapi.aliyuncs.com', apiVersion: '2017-05-25' });
|
||||
const params = { PhoneNumbers: phone, SignName, TemplateCode, TemplateParam: JSON.stringify({ code }) };
|
||||
const client = new Core({
|
||||
accessKeyId,
|
||||
accessKeySecret,
|
||||
endpoint: 'https://dysmsapi.aliyuncs.com',
|
||||
apiVersion: '2017-05-25',
|
||||
});
|
||||
const params = {
|
||||
PhoneNumbers: phone,
|
||||
SignName,
|
||||
TemplateCode,
|
||||
TemplateParam: JSON.stringify({ code }),
|
||||
};
|
||||
const requestOption = { method: 'POST', formatParams: false };
|
||||
try {
|
||||
const response = await client.request('SendSms', params, requestOption);
|
||||
|
||||
Reference in New Issue
Block a user