This commit is contained in:
vastxie 2024-07-07 13:09:08 +08:00
parent 086e5aed3c
commit 4fef3663e4
1131 changed files with 11143 additions and 10769 deletions

View File

@ -1,7 +1,5 @@
# server base
PORT=9520
PREFIX=/docs
APIPREFIX=/api
DB_HOST=mysql
DB_PORT=3306
@ -10,17 +8,17 @@ DB_PASS=123456
DB_DATABASE=chatgpt
DB_SYNC=true
# jwt key token过期时间
JWT_SECRET=chat-cooper
JWT_EXPIRESIN=7d
# Redis
REDIS_PORT=6379
REDIS_HOST=redis
REDIS_PASSWORD=
REDIS_USER=
REDIS_DB=0
# 是否测试环境
ISDEV=FALSE
NAMESPACE=AIWEB
# 自定义微信URL
weChatOpenUrl=https://open.weixin.qq.com
weChatApiUrl=https://api.weixin.qq.com
weChatMpUrl=https://mp.weixin.qq.com

View File

@ -1,33 +1,25 @@
# server base
# 端口
PORT=9520
PREFIX=/docs
APIPREFIX=/api
# MySQL
# MySQL数据库主机地址
DB_HOST=localhost
# MySQL数据库端口号
DB_HOST=127.0.0.1
DB_PORT=3306
# MySQL数据库用户名
DB_USER=root
# MySQL数据库密码
DB_PASS=
# 要使用的MySQL数据库名称
DB_DATABASE=chatgpt
DB_SYNC=true
# jwt key token过期时间
JWT_SECRET=chat-cooper
JWT_EXPIRESIN=7d
# Redis
REDIS_PORT=6379
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=
REDIS_USER=
REDIS_DB=0
# 是否测试环境
ISDEV=FALSE
NAMESPACE=AIWEB
# 自定义微信URL
weChatOpenUrl=https://open.weixin.qq.com
weChatApiUrl=https://api.weixin.qq.com
weChatMpUrl=https://mp.weixin.qq.com

View File

@ -1,23 +1,29 @@
# 编译阶段
FROM node:18-alpine AS base
FROM base AS build
FROM node:20.14.0-alpine AS build
WORKDIR /app
COPY package.json ./
# 使用腾讯源(国内服务器可取消下方注释以提升安装速度)
# RUN npm config set registry https://mirrors.cloud.tencent.com/npm/
COPY package*.json ./
# 如遇到提示网站证书无效取消下方注释禁止严格SS策略
# RUN npm config set strict-ssl false
# 使用淘宝源安装项目依赖(国内用户居多)
RUN npm config set registry https://registry.npmmirror.com && \
npm install --omit=dev
# 设置环境变量来忽略一些警告
ENV NPM_CONFIG_LOGLEVEL=error
ENV NODE_OPTIONS=--max-old-space-size=4096
# 合并RUN命令更新依赖设置镜像源安装依赖然后清理
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
npm config set registry https://registry.npmmirror.com && \
apk add --no-cache --virtual .build-deps git && \
npm install -g npm@latest && \
npm install --production --no-optional --legacy-peer-deps && \
npm cache clean --force && \
apk del .build-deps && \
rm -rf /var/cache/apk/* /tmp/*
# 运行阶段
FROM base AS runner
ENV TZ="Asia/Shanghai"
FROM node:20.14.0-alpine AS runner
ENV TZ="Asia/Shanghai" \
NODE_ENV=production
WORKDIR /app
@ -26,4 +32,4 @@ COPY . .
EXPOSE 9520
CMD ["node", "./dist/main.js"]
CMD ["node", "--max-old-space-size=4096", "./dist/main.js"]

186
README.md
View File

@ -1,54 +1,110 @@
# 99 AI 稳定版
基于 NineAI 2.4.2 二开的可商业化 AI Web 应用,已编译为前后端整合包,支持快速部署。
旨在提供一个易部署的集成化人工智能服务站点。
可商业化的 AI Web 应用,旨在提供一个易部署的集成化人工智能服务站点。已编译为前后端整合包,支持快速部署。
## 版本说明
| 特性 | 稳定版 | 开发版 |
| :--- | :--- | :--- |
| 项目功能 | 详见项目介绍 | 有一定的保留功能 |
| 更新频率 | 月更 | 周更 |
| 商用许可 | 可直接商用 | 可直接商用 |
| 部署方式 | Node.js / Docker-compose | Node.js / Docker-compose |
| 编译状态 | 前端混淆编译,后端非混淆编译 | 前端混淆编译,后端非混淆编译 |
| 未编译源码 | 暂不开源 | 暂不开源 |
| 授权要求 | 无需授权 | 无需授权 |
| 获取方式 | 本项目即为稳定版 | 赞助获取 |
| 特性 | 稳定版 | 开发版 |
| :--------- | :--------------------------- | :--------------------------- |
| 项目功能 | 详见项目介绍 | 有一定的保留功能 |
| 更新频率 | 月更 | 周更 |
| 商用许可 | 可直接商用 | 可直接商用 |
| 部署方式 | Node.js / Docker-compose | Node.js / Docker-compose |
| 编译状态 | 前端混淆编译,后端非混淆编译 | 前端混淆编译,后端非混淆编译 |
| 未编译源码 | 暂不开源 | 暂不开源 |
| 授权要求 | 无需授权 | 无需授权 |
| 获取方式 | 本项目即为稳定版 | 赞助获取 |
## 项目介绍
**应用广场**
### 基础对话
![应用广场](https://github.com/vastxie/99AI/assets/24899308/2cbeab33-0b6b-4f56-81a6-1e15e097023f)
**AI 对话**
支持 OpenAI Chat 格式后台可自定义模型名称、头像、介绍、代理、key、积分扣除方式、文件上传模式等参数。
**支持多模态**
使用`gpt-4o`、`claude-3`等视觉模型,或`gpt-4-all`等逆向模型,完成图像、文件的识别分析。
### 插件系统
对接[插件系统](https://github.com/vastxie/99AIPlugin),拓展 AI 功能边界。
**联网搜索**
**思维导图**
**AI 绘画**
![AI 绘画](https://github.com/vastxie/99AI/assets/24899308/1155d39a-aeed-481e-9f80-127500bf59e7)
对接 `midjourney` 、`dall-e`、`stable-diffusion` 等绘画模型。
**AI 音乐**
![screenshot-1713627618821](https://github.com/vastxie/99AI/assets/24899308/f6966ae8-8be6-4ba5-8d06-c89b4c864f88)
对接 `suno-music` 完成音乐创作。
**文件分析**(开发版支持)
**AI 视频**
![文件分析](https://github.com/vastxie/99AI/assets/24899308/68e80920-6b54-4a50-8b76-2c8c946e8717)
对接 `luma-video` 文生视频。
**绘画广场**
### 开发版已 / 将支持
![绘画广场](https://github.com/vastxie/99AI/assets/24899308/4eb3954e-489d-48f6-9d9d-4de6d2fcce83)
**AI 音乐弹窗**
支持调整歌词,选择音乐类型及风格。
**更丰富 AI 视频选项**
支持图生视频,视频尺寸的选择。
**代码预览**
支持 `HTML` 代码的预览与编辑。
**全模型文件分析**
更多功能持续开发中 ··· ···
### 不再维护的页面
**专业绘图**
![绘画页](https://github.com/vastxie/99AI/assets/24899308/148fb1fa-820c-4fe1-9dbe-e967ee41fd8b)
**绘画广场**
![绘画广场](https://github.com/vastxie/99AI/assets/24899308/4eb3954e-489d-48f6-9d9d-4de6d2fcce83)
**分销邀请**
![分销推荐](https://github.com/vastxie/99AI/assets/24899308/cc280beb-d0cb-43d1-984e-4a7b3a61b807)
![分销邀请](https://github.com/vastxie/99AI/assets/24899308/cc280beb-d0cb-43d1-984e-4a7b3a61b807)
## 更新日志
### 稳定版 v3.5.0
主要更新内容:
- 对话 UI 参考 ChatGPT 官网调整为左右布局。
- 全新的[插件系统](https://github.com/vastxie/99AIPlugin)
- 普通插件:联网搜索、思维导图。
- 内置插件Midjourney 绘图、Dalle 绘图、Stable-Diffusion 绘图、Suno 音乐、Luma 视频。
- 优化调整多处 UI 界面显示。
- 新增模型自定义图标及介绍。
- 提问输入框支持通过剪切板粘贴图片,文件。
- 对话显示公式渲染适配 `/[ /]`、`/( /)` 格式。
- 新增对话中使用 `@` 调用应用功能。
- 优化首页“九宫格”显示(使用内置对话预设、不再依赖后端配置)
- Midjourney 绘图支持 `图生图`、`人脸一致性`、`风格一致性`、`MJ版本`自定义参数等自定义选择。
<details>
<summary>历史日志</summary>
<details>
<summary>历史日志</summary>
### 稳定版 v3.3.0
- 重构流式回复逻辑,加入错误反馈并优化用户端等待动画。
@ -68,43 +124,29 @@
- 重构应用逻辑,翻译及导图特殊模型不再需配置,已整合至【模型管理-系统应用】。
- 新增模型配置选项,允许设置模型调用频率限制,确保用户体验。
### 开发版已/将支持
- 对话页 Midjourney 绘图支持 `图生图` `人脸一致性` `风格一致性` 以及更多自定义参数选择。
- 全模型文件分析功能(只支持带文字的 pdfwordppttxtmd 等文件)。
- 全新的插件系统——联网搜索、思维导图等 ··· ···
- `SD3` / `SD3 Turbo` 绘图模型,`Stable Video` 图生视频模型(`stability.ai` API 格式)。
- Azure TTS 模型支持,语音播报更生动自然。
- 临时文件支持本地存储并自动清空。
- 更多功能持续开发中 ··· ···
<details>
<summary>历史日志</summary>
### v3.0.0
**前端改进**
- 对话页UI重构参考ChatGPT风格增加美观度。
- 新增对话页 Midjourney 绘图功能,包括绘画进度反馈及点按操作。
- Dalle绘图支持模型绘画比例选择方形/宽屏/垂直)。
- 绘图页面新增区域重绘功能。
- 全局字体优先使用系统默认,优化阅读体验。
- 适配ALL模型及GPTs返回图片修正显示过大的问题。
- 对话页根据模型自动展示AI头像可手动替换文件。
- 对话页 UI 重构,参考 ChatGPT 风格,增加美观度。
- 新增对话页 Midjourney 绘图功能,包括绘画进度反馈及点按操作。
- Dalle 绘图支持模型绘画比例选择(方形/宽屏/垂直)。
- 绘图页面新增区域重绘功能。
- 全局字体优先使用系统默认,优化阅读体验。
- 适配 ALL 模型及 GPTs 返回图片,修正显示过大的问题。
- 对话页根据模型自动展示 AI 头像,可手动替换文件。
**后台配置调整**
- 模型配置迁移到模型管理,分普通对话/绘画/特殊模型。
- 后台支持模型文件上传模块开关区分ALL/4V格式。
- 后台新增 Midjourney 提示词优化开关及优化词配置。
- 模型配置迁移到模型管理,分普通对话/绘画/特殊模型。
- 后台支持模型文件上传模块开关,区分 ALL/4V 格式。
- 后台新增 Midjourney 提示词优化开关及优化词配置。
**注意**
- 重要:旧版 Midjourney 配置不再生效,需在模型配置绘画模型中重新配置。
- 模型配置支持扣除积分类型选择。
- 后台管理菜单重新排版,精简非必要配置。
- 重要:旧版 Midjourney 配置不再生效,需在模型配置绘画模型中重新配置。
- 模型配置支持扣除积分类型选择。
- 后台管理菜单重新排版,精简非必要配置。
### v2.6.0
@ -146,14 +188,14 @@
- 按照仓库中的安装说明进行操作,安装完成后,可能需要添加环境变量或重启终端。
- 安装 Node.js 版本 18 或更高版本:
```shell
nvm install 18
nvm use 18
```
- 验证 Node.js 是否安装成功:
```shell
node -v
```
@ -161,19 +203,19 @@
**2. 安装 PM2 / PNPMYARN**
- 使用 npm 安装 PM2
```shell
npm install pm2 -g
```
- 使用 npm 安装 pnpm
```shell
npm install -g pnpm
```
- 确认 `PM2``pnpm` 都已正确安装并且可以运行:
```
pm2 -v
pnpm -v
@ -182,7 +224,6 @@
**3. 其他配置**
- 需配置 Redis 数据库以及新建一个 MySQL 数据库。
- 配置环境变量:
- 复制 `.env.example` 文件为 `.env`
- 根据需要修改 `.env` 文件中的配置项。
@ -229,7 +270,15 @@
- **添加快捷执行脚本**
- 后续仅需在服务器执行 `99ai` 即可再次进入脚本
**2. Shell执行脚本**
**2. Shell 执行脚本**
请在项目的根目录下执行以下命令:
```bash
./deploy.sh
```
或使用:
```bash
bash <(curl -sL https://js.kengro.cn/99ai/onekey-cn-99ai.sh)
@ -240,35 +289,35 @@ bash <(curl -sL https://js.kengro.cn/99ai/onekey-cn-99ai.sh)
**1. 安装 Docker 及 Docker-compose**
- 使用 [Docker 官网](https://www.docker.com/) 提供的一键安装链接安装 Docker 及 Docker-compose。
```bash
curl -fsSL https://get.docker.com | bash -s docker
```
- 也可以使用其他方式自行安装 Docker 及 Docker-compose。
**2. 服务管理**
- **后台启动服务**
```shell
docker-compose up -d
```
- **查看日志**
```shell
docker-compose logs
```
- **停止服务**
```shell
docker-compose down
```
- **重新构建并启动服务**
```shell
docker-compose up -d --build
```
@ -285,7 +334,6 @@ bash <(curl -sL https://js.kengro.cn/99ai/onekey-cn-99ai.sh)
- **密码**`123456`
## 学习交流
扫码添加微信备注 `99`,拉交流群。(不接受私聊技术咨询,有问题优先群内交流)

405
deploy.sh Executable file
View File

@ -0,0 +1,405 @@
#!/usr/bin/env bash
export LANG=zh_CN.UTF-8
# Set up color variables for output
red='\033[0;31m'
green='\033[0;32m'
plain='\033[0m'
# Default values
NVM_URL="https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh"
default_node_version="18.16.0"
CHATGPT_PORT=9520
CONFIG_FILE=docker-compose.yml
# Welcome message
echo -e "${green}欢迎使用99AI一键部署和升级脚本${plain}"
echo -e "${green}----------------------------------------${plain}"
echo -e "${green}注意:${plain}"
echo -e "${green}1. Node.js 部署方式需要提前安装好 MySQL 和 Redis。${plain}"
echo -e "${green}2. Docker 部署方式可以选择新建 MySQL 和 Redis 容器。${plain}"
echo -e "${green}3. 从旧版本升级 Docker 时,请确保 data 和 SQL 文件已备份到根目录。${plain}"
echo -e "${green}----------------------------------------${plain}"
check_cpu_arch() {
case "$(uname -m)" in
aarch64) arch=linux_arm64 ;;
i686) arch=linux_386 ;;
arm) arch=linux_arm ;;
x86_64) arch=linux_amd64 ;;
esac
}
check_os() {
if [[ "$(uname)" == "Darwin" ]]; then
os_name="macOS"
InstallMethod="brew"
else
if command -v lsb_release >/dev/null; then
DISTRO=$(lsb_release -i -s)
else
DISTRO=$(grep -oP '^ID=\K.*' /etc/*-release)
fi
case "$DISTRO" in
Debian|Ubuntu) os_name="${DISTRO}-based Linux"; InstallMethod="sudo apt-get" ;;
centos)
if [[ "$(grep -oP '^VERSION_ID="\K[0-9]+' /etc/*-release)" == "7" ]]; then
os_name="CentOS 7"; InstallMethod="yum"
else
os_name="CentOS 8"; InstallMethod="dnf"
fi ;;
fedora) os_name="Fedora"; InstallMethod="dnf" ;;
opensuse-leap) os_name="openSUSE Leap"; InstallMethod="sudo zypper" ;;
*) echo "未知操作系统,脚本不支持"; exit 1 ;;
esac
fi
}
install_if_missing() {
if ! command -v "$1" >/dev/null; then
echo -e "${red}$1 未安装,正在安装 $1...${plain}"
${InstallMethod} install -y "$1"
echo -e "${green}$1 已安装${plain}"
else
echo -e "${green}$1 已安装${plain}"
fi
}
install_nvm_and_node() {
if ! command -v node >/dev/null; then
echo -e "${red}node 未安装${plain}"
echo -e "${red}开始安装NVM${plain}"
curl -o- $NVM_URL | bash || wget -qO- $NVM_URL | bash
source ~/.bashrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
echo -e "${green}列出node可用版本${plain}"
nvm ls-remote
read -p "请输入要安装的 Node.js 版本号 ,不知道安装啥的请回车[默认版本:$default_node_version]" node_version
node_version="${node_version:-$default_node_version}"
echo -e "${red}正在安装 node-v$node_version${plain}"
nvm install $node_version
nvm use $node_version
source ~/.bashrc
if ! command -v node >/dev/null; then
echo -e "${red}Node.js 安装失败,请检查错误信息!${plain}"
exit 1
fi
installed_version=$(node -v)
if [[ "$installed_version" != "v$node_version" ]]; then
echo -e "${red}Node.js 安装失败,当前安装版本为 $installed_version, 期望安装版本为 v$node_version ${plain}"
exit 1
fi
echo -e "${green}Node.js 安装完成!${plain}"
else
echo -e "${green}node 已安装${plain}"
fi
}
install_add_docker() {
if [ -f "/etc/alpine-release" ]; then
echo -e "${red}docker 未安装,正在安装 docker...${plain}"
apk update
apk add docker docker-compose
echo -e "${green}docker 和 docker-compose 已安装${plain}"
rc-update add docker default
service docker start
else
echo -e "${red}docker 未安装,正在安装 docker...${plain}"
curl -fsSL https://get.docker.com | sh
echo -e "${green}docker 已安装${plain}"
ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin
echo -e "${green}docker-compose 已安装${plain}"
systemctl start docker
systemctl enable docker
fi
echo -e "${green}docker 和 docker-compose 已安装${plain}"
sleep 2
}
docker_install() {
if ! command -v docker &>/dev/null; then
install_add_docker
else
echo "Docker 已经安装"
fi
}
check_dependencies() {
check_cpu_arch
check_os
${InstallMethod} update -y >/dev/null 2>&1
install_if_missing git
install_if_missing cat
install_if_missing curl
if [[ "$operation_choice" == "1" || "$operation_choice" == "2" ]]; then
install_nvm_and_node
install_if_missing npm
if ! command -v pm2 >/dev/null; then
echo -e "${red}pm2 未安装,正在安装 pm2...${plain}"
npm install -g pm2
echo -e "${green}pm2 已安装${plain}"
else
echo -e "${green}pm2 已安装${plain}"
fi
elif [[ "$operation_choice" == "3" || "$operation_choice" == "4" ]]; then
docker_install
fi
}
# Node.js 部署任务
node_deploy() {
# 选择依赖管理工具
read -p "请选择依赖管理工具1. pnpm 2. yarn输入q退出[默认: 1]: " package_manager_choice
package_manager_choice=${package_manager_choice:-1}
if [[ "$package_manager_choice" == "q" ]]; then
echo "退出脚本"
exit
fi
if [[ "$package_manager_choice" == "2" ]]; then
if ! command -v yarn >/dev/null; then
echo -e "${red}yarn 未安装,正在安装 yarn...${plain}"
npm install -g yarn
echo -e "${green}yarn 已安装${plain}"
else
echo -e "${green}yarn 已安装${plain}"
fi
package_manager="yarn"
else
if ! command -v pnpm >/dev/null; then
echo -e "${red}pnpm 未安装,正在安装 pnpm...${plain}"
npm install -g pnpm
echo -e "${green}pnpm 已安装${plain}"
else
echo -e "${green}pnpm 已安装${plain}"
fi
package_manager="pnpm"
fi
# 选择安装方式
read -p "请选择安装方式1. 全新安装 2. 更新输入q退出[默认: 1]: " install_choice
install_choice=${install_choice:-1}
if [[ "$install_choice" == "q" ]]; then
echo "退出脚本"
exit
fi
if [[ "$install_choice" == "2" ]]; then
echo "开始安装依赖包"
$package_manager install
echo "安装完成开始运行99AI"
$package_manager start
pm2 save
exit
fi
echo -e "${green}请确保已安装MySQL和Redis${plain}"
echo -e "${green}正在进行运行配置${plain}"
read -p "设置PORT程序访问端口为[回车默认: 9520]: " input_port
PORT=${input_port:-9520}
read -p "设置DB_HOST为数据库地址[回车默认: 127.0.0.1]: " input_db_host
DB_HOST=${input_db_host:-127.0.0.1}
read -p "设置DB_PORT为数据库端口[回车默认: 3306]: " input_db_port
DB_PORT=${input_db_port:-3306}
read -p "设置DB_USER为数据库用户名[回车默认: root]: " input_db_user
DB_USER=${input_db_user:-root}
read -p "设置DB_PASS数据库密码为[回车默认: 空]: " input_db_pass
DB_PASS=${input_db_pass:-""}
read -p "设置DB_DATABASE数据库名为: " input_db_database
DB_DATABASE=${input_db_database:-""}
read -p "设置REDIS_PORTredis端口为[回车默认: 6379]: " input_redis_port
REDIS_PORT=${input_redis_port:-6379}
read -p "设置REDIS_HOSTredis地址为[回车默认: 127.0.0.1]: " input_redis_host
REDIS_HOST=${input_redis_host:-127.0.0.1}
read -p "设置REDIS_PASSWORDredis密码为[回车默认: 空]: " input_redis_password
REDIS_PASSWORD=${input_redis_password:-""}
read -p "设置REDIS_DBredis数据库为[回车默认: 0]: " input_redis_db
REDIS_DB=${input_redis_db:-"0"}
cat >.env <<EOF
# server base
PORT=$PORT
PREFIX=/docs
APIPREFIX=/api
# MySQL
DB_HOST=$DB_HOST
DB_PORT=$DB_PORT
DB_USER=$DB_USER
DB_PASS=$DB_PASS
DB_DATABASE=$DB_DATABASE
DB_SYNC=true
# Redis
REDIS_PORT=$REDIS_PORT
REDIS_HOST=$REDIS_HOST
REDIS_PASSWORD=$REDIS_PASSWORD
REDIS_DB=$REDIS_DB
# 是否测试环境
ISDEV=FALSE
NAMESPACE=AIWEB
EOF
declare -a NPM_MIRRORS=(
"淘宝镜像" "https://registry.npmmirror.com"
"阿里云镜像" "https://npm.aliyun.com"
"腾讯云镜像" "https://mirrors.cloud.tencent.com/npm/"
"华为云镜像" "https://mirrors.huaweicloud.com/repository/npm/"
"网易镜像" "https://mirrors.163.com/npm/"
"中科院大学开源镜像站" "http://mirrors.ustc.edu.cn/"
"清华大学开源镜像站" "https://mirrors.tuna.tsinghua.edu.cn/"
)
echo -e "${green}请选择要使用的npm源${plain}"
for ((i=0; i<${#NPM_MIRRORS[@]}; i+=2)); do
echo "$((i / 2 + 1))) ${NPM_MIRRORS[i]}"
done
echo "8) 不使用国内源"
echo "9) 退出"
read -p "请输入数字1-9: " selection
case $selection in
1 | 2 | 3 | 4 | 5 | 6 | 7)
echo "设置npm源为${NPM_MIRRORS[$(($selection * 2 - 1))]} ..."
$package_manager config set registry ${NPM_MIRRORS[$(($selection * 2 - 1))]}
echo "设置完成."
;;
8)
echo "您选择了不使用国内源."
;;
9)
echo "退出设置."
exit
;;
*)
echo "无效选择"
;;
esac
echo "开始安装依赖包"
$package_manager install
echo "安装完成开始运行99AI"
$package_manager start
pm2 save
echo -e "=================================================================="
echo -e "\033[32m安装成功!\033[0m"
echo -e "=================================================================="
quit
}
# Docker-compose 启动任务
start_compose() {
echo "配置阶段完成启动docker-compose up -d。"
docker-compose up -d
echo "已启动docker-compose并使用默认配置启动了以下服务"
docker-compose ps
}
# Docker-compose 配置任务
config_compose() {
echo "开始配置……"
source .env.docker
read -p "是否修改端口[默认 9520]y/n输入q退出: " change_port
if [[ $change_port == "y" ]]; then
read -p "输入您想修改的端口: " CHATGPT_PORT
elif [[ $change_port == "q" ]]; then
echo "退出脚本"
exit
fi
check_port() {
netstat -tlpn | grep "\b$1\b" &> /dev/null
}
if [[ $change_port == "y" ]]; then
while check_port $CHATGPT_PORT; do
read -p "端口 $CHATGPT_PORT 被占用,请重新输入端口: " CHATGPT_PORT
done
echo -e "\e[34m恭喜端口 $CHATGPT_PORT 可用\e[0m"
sed -E -i "s/[0-9]+:9520/$CHATGPT_PORT:9520/" docker-compose.yml
fi
start_compose
}
# Docker-compose 升级任务
upgrade_compose() {
echo "停止当前服务..."
docker-compose down
echo "重新构建并启动服务..."
docker-compose up -d --build
echo "服务已启动。"
docker-compose ps
}
# 选择操作
echo "请选择操作:"
echo "1. Node.js 全新部署"
echo "2. Node.js 升级"
echo "3. Docker-compose 部署"
echo "4. Docker-compose 升级"
read -p "请输入数字1-4输入q退出[默认: 1]: " operation_choice
operation_choice=${operation_choice:-1}
if [[ "$operation_choice" == "q" ]]; then
echo "退出脚本"
exit
fi
check_dependencies
case $operation_choice in
1)
echo "Node.js 全新部署选择"
node_deploy
;;
2)
echo "Node.js 升级选择"
node_deploy
;;
3)
echo "Docker-compose 部署选择"
config_compose
;;
4)
echo "Docker-compose 升级选择"
upgrade_compose
;;
*)
echo "无效选择,退出。"
quit
;;
esac
echo -e "=================================================================="
echo -e "\033[32m安装成功!\033[0m"
echo -e "=================================================================="

52
dist/app.module.js vendored
View File

@ -8,39 +8,38 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppModule = void 0;
const abort_interceptor_1 = require("./common/interceptors/abort.interceptor");
const custom_logger_service_1 = require("./common/logger/custom-logger.service");
const common_1 = require("@nestjs/common");
const nestjs_config_1 = require("nestjs-config");
const path_1 = require("path");
const auth_module_1 = require("./modules/auth/auth.module");
const chat_module_1 = require("./modules/chat/chat.module");
const chatLog_module_1 = require("./modules/chatLog/chatLog.module");
const crami_module_1 = require("./modules/crami/crami.module");
const database_module_1 = require("./modules/database/database.module");
const upload_module_1 = require("./modules/upload/upload.module");
const user_module_1 = require("./modules/user/user.module");
const userBalance_module_1 = require("./modules/userBalance/userBalance.module");
const verification_module_1 = require("./modules/verification/verification.module");
const app_module_1 = require("./modules/app/app.module");
const autoreply_module_1 = require("./modules/autoreply/autoreply.module");
const badwords_module_1 = require("./modules/badwords/badwords.module");
const globalConfig_module_1 = require("./modules/globalConfig/globalConfig.module");
const redisCache_module_1 = require("./modules/redisCache/redisCache.module");
const statistic_module_1 = require("./modules/statistic/statistic.module");
const order_module_1 = require("./modules/order/order.module");
const pay_module_1 = require("./modules/pay/pay.module");
const core_1 = require("@nestjs/core");
const serve_static_1 = require("@nestjs/serve-static");
const fetch = require("isomorphic-fetch");
const path_2 = require("path");
const path_1 = require("path");
const app_module_1 = require("./modules/app/app.module");
const auth_module_1 = require("./modules/auth/auth.module");
const autoreply_module_1 = require("./modules/autoreply/autoreply.module");
const badwords_module_1 = require("./modules/badwords/badwords.module");
const chat_module_1 = require("./modules/chat/chat.module");
const chatGroup_module_1 = require("./modules/chatGroup/chatGroup.module");
const chatLog_module_1 = require("./modules/chatLog/chatLog.module");
const crami_module_1 = require("./modules/crami/crami.module");
const database_module_1 = require("./modules/database/database.module");
const globalConfig_module_1 = require("./modules/globalConfig/globalConfig.module");
const menu_module_1 = require("./modules/menu/menu.module");
const midjourney_module_1 = require("./modules/midjourney/midjourney.module");
const models_module_1 = require("./modules/models/models.module");
const official_module_1 = require("./modules/official/official.module");
const queue_module_1 = require("./modules/queue/queue.module");
const order_module_1 = require("./modules/order/order.module");
const pay_module_1 = require("./modules/pay/pay.module");
const plugin_module_1 = require("./modules/plugin/plugin.module");
const redisCache_module_1 = require("./modules/redisCache/redisCache.module");
const sales_module_1 = require("./modules/sales/sales.module");
const signin_module_1 = require("./modules/signin/signin.module");
const statistic_module_1 = require("./modules/statistic/statistic.module");
const task_module_1 = require("./modules/task/task.module");
const upload_module_1 = require("./modules/upload/upload.module");
const user_module_1 = require("./modules/user/user.module");
const userBalance_module_1 = require("./modules/userBalance/userBalance.module");
const verification_module_1 = require("./modules/verification/verification.module");
global.fetch = fetch;
let AppModule = class AppModule {
};
@ -48,12 +47,12 @@ AppModule = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({
imports: [
serve_static_1.ServeStaticModule.forRoot({
rootPath: (0, path_2.join)(__dirname, '..', 'public'),
}),
nestjs_config_1.ConfigModule.load((0, path_1.resolve)(__dirname, 'config', '**/!(*.d).{ts,js}')),
database_module_1.DatabaseModule,
serve_static_1.ServeStaticModule.forRoot({
rootPath: (0, path_1.join)(__dirname, '..', 'public'),
}),
user_module_1.UserModule,
plugin_module_1.PluginModule,
auth_module_1.AuthModule,
verification_module_1.VerificationModule,
chat_module_1.ChatModule,
@ -71,7 +70,6 @@ AppModule = __decorate([
order_module_1.OrderModule,
official_module_1.OfficialModule,
task_module_1.TaskModule,
queue_module_1.QueueModule,
midjourney_module_1.MidjourneyModule,
chatGroup_module_1.ChatGroupModule,
sales_module_1.SalesModule,
@ -84,7 +82,9 @@ AppModule = __decorate([
provide: core_1.APP_INTERCEPTOR,
useClass: abort_interceptor_1.AbortInterceptor,
},
custom_logger_service_1.CustomLoggerService,
],
exports: [custom_logger_service_1.CustomLoggerService],
})
], AppModule);
exports.AppModule = AppModule;

View File

@ -10,17 +10,17 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtStrategy = void 0;
const nestjs_config_1 = require("nestjs-config");
const passport_jwt_1 = require("passport-jwt");
const passport_1 = require("@nestjs/passport");
const common_1 = require("@nestjs/common");
const passport_1 = require("@nestjs/passport");
const passport_jwt_1 = require("passport-jwt");
const redisCache_service_1 = require("../../modules/redisCache/redisCache.service");
let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(passport_jwt_1.Strategy) {
constructor(configService) {
constructor(redisService) {
super({
jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get('jwt').secret,
secretOrKey: redisService.getJwtSecret(),
});
this.configService = configService;
this.redisService = redisService;
}
async validate(payload) {
return payload;
@ -28,6 +28,6 @@ let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(pas
};
JwtStrategy = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [nestjs_config_1.ConfigService])
__metadata("design:paramtypes", [redisCache_service_1.RedisCacheService])
], JwtStrategy);
exports.JwtStrategy = JwtStrategy;

View File

@ -10,12 +10,12 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtAuthGuard = void 0;
const globalConfig_service_1 = require("../../modules/globalConfig/globalConfig.service");
const redisCache_service_1 = require("../../modules/redisCache/redisCache.service");
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const passport_1 = require("@nestjs/passport");
const jwt = require("jsonwebtoken");
const core_1 = require("@nestjs/core");
const globalConfig_service_1 = require("../../modules/globalConfig/globalConfig.service");
const auth_service_1 = require("../../modules/auth/auth.service");
let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)('jwt') {
constructor(redisCacheService, moduleRef, globalConfigService, authService) {
@ -27,13 +27,14 @@ let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)('jwt') {
}
async canActivate(context) {
if (!this.redisCacheService) {
this.redisCacheService = this.moduleRef.get(redisCache_service_1.RedisCacheService, { strict: false });
this.redisCacheService = this.moduleRef.get(redisCache_service_1.RedisCacheService, {
strict: false,
});
}
const request = context.switchToHttp().getRequest();
const domain = request.headers['x-website-domain'];
const token = this.extractToken(request);
request.user = this.validateToken(token);
const auth = this.globalConfigService.getNineAiToken();
request.user = await this.validateToken(token);
await this.redisCacheService.checkTokenAuth(token, request);
return true;
}
@ -56,9 +57,11 @@ let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)('jwt') {
}
return parts[1];
}
validateToken(token) {
async validateToken(token) {
try {
return jwt.verify(token, process.env.JWT_SECRET);
const secret = await this.redisCacheService.getJwtSecret();
const decoded = await jwt.verify(token, secret);
return decoded;
}
catch (error) {
throw new common_1.HttpException('亲爱的用户,请登录后继续操作,我们正在等您的到来!', common_1.HttpStatus.UNAUTHORIZED);

View File

@ -0,0 +1,45 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.CustomLoggerService = void 0;
const common_1 = require("@nestjs/common");
let CustomLoggerService = class CustomLoggerService extends common_1.ConsoleLogger {
constructor() {
super();
this.isDev = process.env.ISDEV === 'TRUE';
}
log(message, context) {
super.log(message, context);
}
error(message, trace, context) {
super.error(message, trace, context);
}
warn(message, context) {
if (this.isDev) {
super.warn(message, context);
}
}
debug(message, context) {
if (this.isDev) {
super.debug(message, context);
}
}
verbose(message, context) {
if (this.isDev) {
super.verbose(message, context);
}
}
};
CustomLoggerService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [])
], CustomLoggerService);
exports.CustomLoggerService = CustomLoggerService;

View File

@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.createSwagger = void 0;
const swagger_1 = require("@nestjs/swagger");
const swaggerOptions = new swagger_1.DocumentBuilder()
.setTitle('Nine Team api document')
.setDescription('Nine Team api document')
.setTitle('AIWeb Team api document')
.setDescription('AIWeb Team api document')
.setVersion('1.0.0')
.addBearerAuth()
.build();
function createSwagger(app) {
const document = swagger_1.SwaggerModule.createDocument(app, swaggerOptions);
swagger_1.SwaggerModule.setup('/nineai/swagger/docs', app, document);
swagger_1.SwaggerModule.setup('/swagger/docs', app, document);
}
exports.createSwagger = createSwagger;

View File

@ -1,41 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compileNetwork = void 0;
const axios_1 = require("axios");
function formatSearchData(searchData, question) {
const formatStr = searchData.results.map(({ title, body, href }) => `'${title}' : ${body} ; (${href})`).join('\n\n');
const currentDate = new Date().toISOString().split('T')[0];
const instructions = '你的任务是优先利用网络搜索结果来回答问题,并使用提问时的语言风格进行回复。你应该提供一个全面而有条理的回答,在每条答案后面明确指出来源于哪个链接,使用 [[数字](链接)] 格式进行标注。以下是搜索结果:';
return `${instructions}\n今天是${currentDate}\n${formatStr}`;
}
async function compileNetwork(question) {
const currentDate = new Date().toISOString().split('T')[0];
console.log(`Current date: ${currentDate}`);
console.log(`开始对问题“${question}”进行网络编译`);
const datedQuestion = `${currentDate} ${question}`;
let searchData = { results: [] };
try {
const url = ``;
console.log(`正在向搜索API发送请求URL为${url}`);
const responseData = await axios_1.default.get(url);
searchData = responseData.data;
console.log(`已成功接收问题“${question}”的搜索结果,结果数量:${searchData.results.length}`);
searchData.results.forEach((result, index) => {
console.log(`结果 ${index + 1}: 标题: ${result.title}, 链接: ${result.href}, 摘要: ${result.body.substring(0, 100)}...`);
});
}
catch (error) {
console.log(`在对问题“${question}”进行网络编译时出错:`, error);
}
let formattedData = "";
if (searchData.results.length === 0) {
console.log(`未找到问题“${question}”的搜索结果,将返回原问题`);
return question;
}
else {
formattedData = formatSearchData(searchData, question);
console.log(`格式化后的搜索结果为:\n${formattedData}`);
return formattedData;
}
}
exports.compileNetwork = compileNetwork;

11
dist/common/utils/fromatUrl.js vendored Normal file
View File

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatUrl = void 0;
function formatUrl(url) {
let formattedUrl = url.replace(/\s+/g, '');
if (formattedUrl.endsWith('/')) {
formattedUrl = formattedUrl.slice(0, -1);
}
return formattedUrl;
}
exports.formatUrl = formatUrl;

View File

@ -1,43 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClientIp = void 0;
function getClientIp(request) {
let ipAddress = '';
const headerList = [
'X-Client-IP',
'X-Real-IP',
'X-Forwarded-For',
'CF-Connecting-IP',
'True-Client-IP',
'X-Cluster-Client-IP',
'Proxy-Client-IP',
'WL-Proxy-Client-IP',
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
];
for (const header of headerList) {
const value = request.headers[header];
if (value && typeof value === 'string') {
const ips = value.split(',');
ipAddress = ips[0].trim();
break;
}
function getFirstValidIp(ipString) {
const ips = ipString.split(',').map(ip => ip.trim());
return ips.find(ip => isValidIp(ip)) || '';
}
function isValidIp(ip) {
return /^\d{1,3}(\.\d{1,3}){3}$/.test(ip) || /^::ffff:\d{1,3}(\.\d{1,3}){3}$/.test(ip);
}
function getClientIp(req) {
const forwardedFor = req.header('x-forwarded-for');
let clientIp = forwardedFor ? getFirstValidIp(forwardedFor) : '';
if (!clientIp) {
clientIp = req.connection.remoteAddress || req.socket.remoteAddress || '';
}
if (!ipAddress) {
ipAddress = request.connection.remoteAddress || '';
if (clientIp.startsWith('::ffff:')) {
clientIp = clientIp.substring(7);
}
if (ipAddress && ipAddress.includes('::')) {
const isLocal = /^(::1|fe80(:1)?::1(%.*)?)$/i.test(ipAddress);
if (isLocal) {
ipAddress = '';
}
else if (ipAddress.includes('::ffff:')) {
ipAddress = ipAddress.split(':').pop() || '';
}
}
if (!ipAddress || !/\d+\.\d+\.\d+\.\d+/.test(ipAddress)) {
ipAddress = '';
}
return ipAddress;
return clientIp;
}
exports.getClientIp = getClientIp;

31
dist/common/utils/getTokenCount.js vendored Normal file
View File

@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTokenCount = void 0;
const tiktoken_1 = require("@dqbd/tiktoken");
const getTokenCount = async (input) => {
let text = '';
if (Array.isArray(input)) {
text = input.reduce((pre, cur) => {
if (Array.isArray(cur.content)) {
const contentText = cur.content
.filter((item) => item.type === 'text')
.map((item) => item.text)
.join(' ');
return pre + contentText;
}
else {
return pre + (cur.content || '');
}
}, '');
}
else if (typeof input === 'string') {
text = input;
}
else if (input) {
text = String(input);
}
text = text.replace(/<\|endoftext\|>/g, '');
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
return tokenizer.encode(text).length;
};
exports.getTokenCount = getTokenCount;

43
dist/common/utils/handleError.js vendored Normal file
View File

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleError = void 0;
const axios_1 = require("axios");
function handleError(error) {
let message = '发生未知错误,请稍后再试';
if (axios_1.default.isAxiosError(error) && error.response) {
switch (error.response.status) {
case 400:
message =
'发生错误400 Bad Request - 请求因格式错误无法被服务器处理。';
break;
case 401:
message = '发生错误401 Unauthorized - 请求要求进行身份验证。';
break;
case 403:
message = '发生错误403 Forbidden - 服务器拒绝执行请求。';
break;
case 404:
message = '发生错误404 Not Found - 请求的资源无法在服务器上找到。';
break;
case 500:
message =
'发生错误500 Internal Server Error - 服务器内部错误,无法完成请求。';
break;
case 502:
message =
'发生错误502 Bad Gateway - 作为网关或代理工作的服务器从上游服务器收到无效响应。';
break;
case 503:
message =
'发生错误503 Service Unavailable - 服务器暂时处于超负载或维护状态,无法处理请求。';
break;
default:
break;
}
}
else {
message = error.message || message;
}
return message;
}
exports.handleError = handleError;

View File

@ -14,25 +14,26 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./date"), exports);
__exportStar(require("./createRandomCode"), exports);
__exportStar(require("./tools"), exports);
__exportStar(require("./createRandomInviteCode"), exports);
__exportStar(require("./maskEmail"), exports);
__exportStar(require("./createRandomUid"), exports);
__exportStar(require("./generateCrami"), exports);
__exportStar(require("./base"), exports);
__exportStar(require("./hideString"), exports);
__exportStar(require("./createOrderId"), exports);
__exportStar(require("./createRandomCode"), exports);
__exportStar(require("./createRandomInviteCode"), exports);
__exportStar(require("./createRandomNonceStr"), exports);
__exportStar(require("./createRandomUid"), exports);
__exportStar(require("./date"), exports);
__exportStar(require("./encrypt"), exports);
__exportStar(require("./fromatUrl"), exports);
__exportStar(require("./generateCrami"), exports);
__exportStar(require("./getClientIp"), exports);
__exportStar(require("./getDiffArray"), exports);
__exportStar(require("./getRandomItem"), exports);
__exportStar(require("./getClientIp"), exports);
__exportStar(require("./maskIpAddress"), exports);
__exportStar(require("./maskCrami"), exports);
__exportStar(require("./selectKeyWithWeight"), exports);
__exportStar(require("./createOrderId"), exports);
__exportStar(require("./createRandomNonceStr"), exports);
__exportStar(require("./utcformatTime"), exports);
__exportStar(require("./removeSpecialCharacters"), exports);
__exportStar(require("./encrypt"), exports);
__exportStar(require("./compileNetwork"), exports);
__exportStar(require("./getRandomItemFromArray"), exports);
__exportStar(require("./getTokenCount"), exports);
__exportStar(require("./handleError"), exports);
__exportStar(require("./hideString"), exports);
__exportStar(require("./maskCrami"), exports);
__exportStar(require("./maskEmail"), exports);
__exportStar(require("./maskIpAddress"), exports);
__exportStar(require("./removeSpecialCharacters"), exports);
__exportStar(require("./tools"), exports);
__exportStar(require("./utcformatTime"), exports);

View File

@ -1,17 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectKeyWithWeight = void 0;
function selectKeyWithWeight(data) {
if (data.length === 0)
return undefined;
const totalWeight = data.reduce((sum, item) => sum + item.weight, 0);
let randomWeight = Math.random() * totalWeight;
for (const item of data) {
randomWeight -= item.weight;
if (randomWeight < 0) {
return item;
}
}
return data[data.length - 1];
}
exports.selectKeyWithWeight = selectKeyWithWeight;

11
dist/config/cos.js vendored
View File

@ -1,11 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Dotenv = require("dotenv");
Dotenv.config({ path: '.env' });
const config = {
SecretId: process.env.TENTCENT_SECRET_ID,
SecretKey: process.env.TENTCENT_SECRET_KEY,
Bucket: process.env.COS_BUCKET_PUBLIC,
Region: process.env.COS_REGION,
};
exports.default = config;

View File

@ -1,16 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const config = {
type: 'mysql',
port: parseInt(process.env.DB_PORT),
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE,
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
logging: false,
synchronize: true,
charset: 'utf8mb4',
timezone: '+08:00',
};
exports.default = config;

9
dist/config/jwt.js vendored
View File

@ -1,9 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const config = {
secret: process.env.JWT_SECRET,
signOptions: {
expiresIn: process.env.JWT_EXPIRESIN || '7d',
},
};
exports.default = config;

9
dist/config/main.js vendored
View File

@ -1,9 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.APIPREFIX = exports.SWAGGERPREFIX = exports.PORT = void 0;
const PORT = process.env.PORT || 3000;
exports.PORT = PORT;
const SWAGGERPREFIX = process.env.SWAGGERPREFIX || '/docs';
exports.SWAGGERPREFIX = SWAGGERPREFIX;
const APIPREFIX = process.env.APIPREFIX || '/api';
exports.APIPREFIX = APIPREFIX;

View File

@ -1,9 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const config = {
port: parseInt(process.env.REDIS_PORT),
host: process.env.REDIS_HOST,
password: process.env.REDIS_PASSWORD,
username: process.env.REDIS_USER,
};
exports.default = config;

View File

@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

38
dist/main.js vendored
View File

@ -1,36 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Dotenv = require("dotenv");
Dotenv.config({ path: '.env' });
const core_1 = require("@nestjs/core");
const app_module_1 = require("./app.module");
const swagger_1 = require("./common/swagger");
const allExceptions_filter_1 = require("./common/filters/allExceptions.filter");
const typeOrmQueryFailed_filter_1 = require("./common/filters/typeOrmQueryFailed.filter");
const common_1 = require("@nestjs/common");
const transform_interceptor_1 = require("./common/interceptors/transform.interceptor");
const main_1 = require("./config/main");
const custom_logger_service_1 = require("./common/logger/custom-logger.service");
const initDatabase_1 = require("./modules/database/initDatabase");
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const compression = require("compression");
const crypto_1 = require("crypto");
const Dotenv = require("dotenv");
const xmlBodyParser = require("express-xml-bodyparser");
const ioredis_1 = require("ioredis");
const path_1 = require("path");
const app_module_1 = require("./app.module");
Dotenv.config({ path: '.env' });
async function bootstrap() {
await (0, initDatabase_1.initDatabase)();
const redis = new ioredis_1.default({
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
db: Number(process.env.REDIS_DB || 0),
});
const existingSecret = await redis.get('JWT_SECRET');
if (!existingSecret) {
const jwtSecret = (0, crypto_1.randomBytes)(256).toString('base64');
common_1.Logger.log('Generating and setting new JWT_SECRET');
await redis.set('JWT_SECRET', jwtSecret);
}
const app = await core_1.NestFactory.create(app_module_1.AppModule);
await (0, initDatabase_1.initDatabase)();
app.useLogger(app.get(custom_logger_service_1.CustomLoggerService));
app.use(compression());
const www = (0, path_1.resolve)(__dirname, './public');
app.use(xmlBodyParser());
app.enableCors();
app.setGlobalPrefix(main_1.APIPREFIX);
app.setGlobalPrefix('/api');
app.useGlobalInterceptors(new transform_interceptor_1.TransformInterceptor());
app.useGlobalFilters(new typeOrmQueryFailed_filter_1.TypeOrmQueryFailedFilter());
app.useGlobalFilters(new allExceptions_filter_1.AllExceptionsFilter());
app.useGlobalPipes(new common_1.ValidationPipe());
app.getHttpAdapter().getInstance().set('views', 'templates/pages');
app.getHttpAdapter().getInstance().set('view engine', 'hbs');
(0, swagger_1.createSwagger)(app);
const server = await app.listen(main_1.PORT, () => {
common_1.Logger.log(`服务启动成功: http://localhost:${main_1.PORT}/nineai/swagger/docs`, 'Main');
const PORT = process.env.PORT || 3000;
const server = await app.listen(PORT, () => {
common_1.Logger.log(`服务启动成功: http://localhost:${PORT}`, 'Main');
});
server.timeout = 5 * 60 * 1000;
}

32
dist/modules/ai/azureTts.service.js vendored Normal file
View File

@ -0,0 +1,32 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var AzureTtsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AzureTtsService = void 0;
const common_1 = require("@nestjs/common");
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 AzureTtsService = AzureTtsService_1 = class AzureTtsService {
constructor(uploadService, globalConfigService, chatLogService) {
this.uploadService = uploadService;
this.globalConfigService = globalConfigService;
this.chatLogService = chatLogService;
this.logger = new common_1.Logger(AzureTtsService_1.name);
}
};
AzureTtsService = AzureTtsService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [upload_service_1.UploadService,
globalConfig_service_1.GlobalConfigService,
chatLog_service_1.ChatLogService])
], AzureTtsService);
exports.AzureTtsService = AzureTtsService;

185
dist/modules/ai/lumaVideo.service.js vendored Normal file
View File

@ -0,0 +1,185 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.LumaVideoService = void 0;
const common_1 = require("@nestjs/common");
const axios_1 = require("axios");
const chatLog_service_1 = require("../chatLog/chatLog.service");
let LumaVideoService = class LumaVideoService {
constructor(chatLogService) {
this.chatLogService = chatLogService;
}
async lumaVideo(inputs) {
var _a, _b, _c;
const { apiKey, proxyUrl, fileInfo, prompt, timeout, assistantLogId, extraParam, } = inputs;
let result = {
text: '',
fileInfo: '',
taskId: '',
taskData: '',
status: 2,
};
let response = null;
let url = '';
let payloadJson = {};
const headers = { Authorization: `Bearer ${apiKey}` };
url = `${proxyUrl}/luma/generations/`;
const aspectRatio = '16:9';
payloadJson = {
user_prompt: prompt,
aspect_ratio: aspectRatio,
expand_prompt: true,
};
common_1.Logger.log(`正在准备发送请求到 ${url}payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`, 'LumaService');
try {
response = await axios_1.default.post(url, payloadJson, { headers });
}
catch (error) {
common_1.Logger.error(`任务提交失败: ${error.message}`, 'LumaService');
throw new Error('任务提交失败');
}
if ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.id) {
result.taskId = (_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.id;
common_1.Logger.log(`任务提交成功, 任务ID: ${(_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.id}`, 'LumaService');
}
else {
throw new Error('未能获取结果数据, 即将重试');
}
try {
await this.pollLumaVideoResult({
proxyUrl,
apiKey,
taskId: response.data.id,
timeout,
prompt,
onSuccess: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
videoUrl: data === null || data === void 0 ? void 0 : data.videoUrl,
audioUrl: data === null || data === void 0 ? void 0 : data.audioUrl,
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || prompt,
progress: '100%',
status: 3,
taskId: data === null || data === void 0 ? void 0 : data.taskId,
taskData: data === null || data === void 0 ? void 0 : data.taskData,
});
common_1.Logger.log('视频任务已完成', 'LumaService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'LumaService');
}
},
onGenerating: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
videoUrl: data === null || data === void 0 ? void 0 : data.videoUrl,
audioUrl: data === null || data === void 0 ? void 0 : data.audioUrl,
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || '视频生成中...',
progress: data === null || data === void 0 ? void 0 : data.progress,
status: data.status,
});
common_1.Logger.log('视频生成中...', 'LumaService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'LumaService');
}
},
onFailure: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
answer: '视频生成失败',
status: data.status,
});
common_1.Logger.log('生成失败', 'Lum aService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'LumaService');
}
},
});
}
catch (error) {
common_1.Logger.error('查询生成结果时发生错误:', error.message, 'LumaService');
throw new Error('查询生成结果时发生错误');
}
return result;
}
async pollLumaVideoResult(inputs) {
const { proxyUrl, apiKey, taskId, timeout, onSuccess, onFailure, onGenerating, action, } = inputs;
let result = {
videoUrl: '',
audioUrl: '',
fileInfo: '',
drawId: '',
taskData: '',
status: 2,
progress: 0,
answer: '',
};
const headers = { Authorization: `Bearer ${apiKey}` };
const url = `${proxyUrl}/luma/generations/${taskId}`;
const startTime = Date.now();
const totalDuration = 300000;
const POLL_INTERVAL = 5000;
let retryCount = 0;
try {
while (Date.now() - startTime < timeout) {
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
try {
const res = await axios_1.default.get(url, { headers });
const interval = setInterval(() => {
const elapsed = Date.now() - startTime;
let percentage = Math.floor((elapsed / totalDuration) * 100);
if (percentage >= 99)
percentage = 99;
result.answer = `视频生成中 ${percentage}%`;
}, 1000);
const responses = res.data;
common_1.Logger.debug(`轮询结果: ${JSON.stringify(responses)}`, 'LumaService');
if (responses.state === 'completed') {
result.taskId = responses.id;
result.taskData = JSON.stringify(responses);
result.fileInfo = responses.video.url;
result.answer = `提示词: "${responses.prompt}"`;
onSuccess(result);
clearInterval(interval);
return;
}
else {
onGenerating(result);
}
if (result.progress) {
}
}
catch (error) {
retryCount++;
common_1.Logger.error(`轮询失败,重试次数: ${retryCount}`, 'LumaService');
}
}
common_1.Logger.error('轮询超时,请稍后再试!', 'LumaService');
result.status = 4;
onFailure(result);
throw new Error('查询超时,请稍后再试!');
}
catch (error) {
common_1.Logger.error(`轮询过程中发生错误: ${error}`, 'LumaService');
result.status = 5;
onFailure(result);
}
}
};
LumaVideoService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService])
], LumaVideoService);
exports.LumaVideoService = LumaVideoService;

View File

@ -0,0 +1,211 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.MidjourneyService = 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 MidjourneyService = class MidjourneyService {
constructor(uploadService, globalConfigService, chatLogService) {
this.uploadService = uploadService;
this.globalConfigService = globalConfigService;
this.chatLogService = chatLogService;
}
async midjourneyDraw(inputs) {
var _a, _b;
const { id, apiKey, proxyUrl, action, drawId, prompt, usePrompt, customId, timeout, assistantLogId, } = inputs;
let result = {
text: '',
fileInfo: '',
drawId: '',
customId: '',
status: 2,
};
let response;
let retryCount = 0;
let url = '';
while (retryCount < 3) {
let payloadJson = {};
try {
if (action === 'IMAGINE') {
url = `${proxyUrl}/mj/submit/imagine`;
payloadJson = { prompt: usePrompt };
}
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;
break;
}
else {
throw new Error('未能获取结果数据, 即将重试');
}
}
catch (error) {
retryCount++;
if (retryCount >= 3) {
common_1.Logger.log(`绘画任务提交失败, 请检查后台配置或者稍后重试! ${error}`, 'MidjourneyService');
}
}
}
this.pollMjDrawingResult({
proxyUrl,
apiKey,
drawId: response.data.result,
timeout,
prompt,
onSuccess: async (data) => {
await this.chatLogService.updateChatLog(assistantLogId, {
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || prompt,
progress: '100%',
status: 3,
drawId: data === null || data === void 0 ? void 0 : data.drawId,
customId: data === null || data === void 0 ? void 0 : data.customId,
});
common_1.Logger.log('绘图成功!');
},
onDrawing: async (data) => {
await this.chatLogService.updateChatLog(assistantLogId, {
answer: (data === null || data === void 0 ? void 0 : data.answer) || '绘制中',
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}`);
},
onFailure: async (data) => {
await this.chatLogService.updateChatLog(assistantLogId, {
answer: '绘图失败',
status: data.status,
});
common_1.Logger.log('绘图失败');
},
}).catch((error) => {
common_1.Logger.error('查询绘图结果时发生错误:', error, 'MidjourneyService');
});
common_1.Logger.log(`绘画任务提交成功, 绘画ID: ${response.data.result}`, 'MidjourneyService');
return result;
}
async pollMjDrawingResult(inputs) {
const { proxyUrl, apiKey, drawId, timeout, onSuccess, prompt, onFailure, onDrawing, } = inputs;
const { mjNotSaveImg, mjProxyImgUrl, mjNotUseProxy } = await this.globalConfigService.getConfigs([
'mjNotSaveImg',
'mjProxyImgUrl',
'mjNotUseProxy',
]);
let response;
let result = {
fileInfo: '',
drawId: '',
customId: '',
status: 2,
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));
try {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'mj-api-secret': apiKey,
};
const url = `${proxyUrl}/mj/task/${drawId}/fetch`;
const res = await axios_1.default.get(url, { headers });
const responses = res.data;
if (responses.status === 'SUCCESS') {
common_1.Logger.log(`绘制成功, 获取到的URL: ${responses.imageUrl}`, 'MidjourneyService');
let processedUrl = responses.imageUrl;
const shouldReplaceUrl = mjNotUseProxy === '0' && mjProxyImgUrl;
let logMessage = '';
if (shouldReplaceUrl) {
const newUrlBase = new URL(mjProxyImgUrl);
const parsedUrl = new URL(responses.imageUrl);
parsedUrl.protocol = newUrlBase.protocol;
parsedUrl.hostname = newUrlBase.hostname;
parsedUrl.port = newUrlBase.port ? newUrlBase.port : '';
processedUrl = parsedUrl.toString();
logMessage = `使用代理替换后的 URL: ${processedUrl}`;
common_1.Logger.log(logMessage, 'MidjourneyService');
}
if (mjNotSaveImg !== '1') {
try {
common_1.Logger.log(`------> 开始上传图片!!!`);
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}`;
processedUrl = await this.uploadService.uploadFileFromUrl({
url: processedUrl,
dir: `images/midjourney/${currentDate}`,
});
logMessage = `上传成功 URL: ${processedUrl}`;
}
catch (uploadError) {
common_1.Logger.error('存储图片失败,使用原始/代理图片链接');
logMessage = `存储图片失败,使用原始/代理图片链接 ${processedUrl}`;
}
common_1.Logger.log(logMessage, 'MidjourneyService');
}
else {
logMessage = `不保存图片,使用 URL: ${processedUrl}`;
common_1.Logger.log(logMessage, 'MidjourneyService');
}
result.fileInfo = processedUrl;
result.drawId = responses.id;
result.customId = JSON.stringify(responses.buttons);
result.answer = `${prompt}\n${responses.finalPrompt || responses.properties.finalPrompt || ''}`;
onSuccess(result);
return;
}
result.progress = responses === null || responses === void 0 ? void 0 : responses.progress;
result.answer = `当前绘制进度 ${responses === null || responses === void 0 ? void 0 : responses.progress}`;
if (result.progress) {
onDrawing(result);
}
}
catch (error) {
retryCount++;
common_1.Logger.error(`轮询过程中发生错误: ${error}`, 'MidjourneyService');
}
}
common_1.Logger.error(`超过 ${startTime / 1000} s 未完成绘画, 请稍后再试! MidjourneyService`);
result.status = 4;
onFailure(result);
throw new common_1.HttpException('绘画超时,请稍后再试!', common_1.HttpStatus.BAD_REQUEST);
}
catch (error) {
common_1.Logger.error(`绘画失败: ${error} MidjourneyService`);
result.status = 5;
onFailure(result);
}
}
};
MidjourneyService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [upload_service_1.UploadService,
globalConfig_service_1.GlobalConfigService,
chatLog_service_1.ChatLogService])
], MidjourneyService);
exports.MidjourneyService = MidjourneyService;

145
dist/modules/ai/openaiChat.service.js vendored Normal file
View File

@ -0,0 +1,145 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.OpenAIChatService = void 0;
const utils_1 = require("../../common/utils");
const common_1 = require("@nestjs/common");
const axios_1 = require("axios");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
let OpenAIChatService = class OpenAIChatService {
constructor(globalConfigService) {
this.globalConfigService = globalConfigService;
}
async openAIChat(messagesHistory, inputs) {
const { onFailure, onProgress, apiKey, model, proxyUrl, modelName, timeout, chatId, isFileUpload, modelAvatar, temperature, abortController, } = inputs;
let result = {
text: '',
model: '',
modelName: modelName,
chatId: chatId,
answer: '',
errMsg: '',
modelAvatar: modelAvatar,
};
const options = {
method: 'POST',
url: `${proxyUrl}/v1/chat/completions`,
responseType: 'stream',
timeout: timeout,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
data: Object.assign({ stream: true, model, temperature: temperature, messages: messagesHistory }, (isFileUpload === 2 && { max_tokens: 2048 })),
};
console.log('请求配置:', JSON.stringify(options, null, 2), 'ChatService');
try {
const response = await (0, axios_1.default)(options);
const stream = response.data;
let buffer = '';
await new Promise((resolve, reject) => {
stream.on('data', (chunk) => {
buffer += chunk.toString();
let lines = buffer.split('\n');
buffer = lines.pop();
lines.forEach((line) => {
var _a, _b;
if (line.trim() === 'data: [DONE]') {
console.log('处理结束信号 [DONE]');
resolve(result);
return;
}
if (line.startsWith('data: ')) {
try {
const cleanedLine = line.slice(6).trim();
if (cleanedLine) {
const jsonLine = JSON.parse(cleanedLine);
const content = ((_b = (_a = jsonLine.choices[0]) === null || _a === void 0 ? void 0 : _a.delta) === null || _b === void 0 ? void 0 : _b.content) || '';
result.answer += content;
onProgress === null || onProgress === void 0 ? void 0 : onProgress({ text: content, answer: result.answer });
}
}
catch (error) {
console.error('Error parsing line:', line, error);
}
}
});
});
stream.on('end', () => {
resolve(result);
});
stream.on('error', (error) => {
reject(error);
});
abortController.signal.addEventListener('abort', () => {
resolve(result);
});
});
return result;
}
catch (error) {
result.errMsg = (0, utils_1.handleError)(error);
common_1.Logger.error(result.errMsg);
onFailure(result);
return result;
}
}
async chatFree(prompt, systemMessage, messagesHistory) {
const { openaiBaseUrl = '', openaiBaseKey = '', openaiBaseModel, } = await this.globalConfigService.getConfigs([
'openaiBaseKey',
'openaiBaseUrl',
'openaiBaseModel',
]);
const key = openaiBaseKey;
const proxyUrl = openaiBaseUrl;
let requestData = [];
if (systemMessage) {
requestData.push({
role: 'system',
content: systemMessage,
});
}
if (messagesHistory && messagesHistory.length > 0) {
requestData = requestData.concat(messagesHistory);
}
else {
requestData.push({
role: 'user',
content: prompt,
});
}
const options = {
method: 'POST',
url: `${proxyUrl}/v1/chat/completions`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${key}`,
},
data: {
model: openaiBaseModel || 'gpt-3.5-turbo-0125',
messages: requestData,
},
};
try {
const response = await (0, axios_1.default)(options);
common_1.Logger.log(`全局模型调用成功, 返回结果: ${response === null || response === void 0 ? void 0 : response.data.choices[0].message.content}`, 'ChatService');
return response === null || response === void 0 ? void 0 : response.data.choices[0].message.content;
}
catch (error) {
console.log('error: ', error);
}
}
};
OpenAIChatService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [globalConfig_service_1.GlobalConfigService])
], OpenAIChatService);
exports.OpenAIChatService = OpenAIChatService;

View File

@ -8,69 +8,27 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var ApiDataService_1;
var OpenAIDrawService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiDataService = void 0;
exports.OpenAIDrawService = void 0;
const common_1 = require("@nestjs/common");
const axios_1 = require("axios");
const uuid = require("uuid");
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 ApiDataService = ApiDataService_1 = class ApiDataService {
constructor(uploadService, globalConfigService) {
const openaiChat_service_1 = require("./openaiChat.service");
let OpenAIDrawService = OpenAIDrawService_1 = class OpenAIDrawService {
constructor(uploadService, globalConfigService, chatLogService, openAIChatService) {
this.uploadService = uploadService;
this.globalConfigService = globalConfigService;
this.logger = new common_1.Logger(ApiDataService_1.name);
}
async chatFree(prompt, systemMessage, messagesHistory) {
const { openaiBaseUrl = '', openaiBaseKey = '', openaiBaseModel, } = await this.globalConfigService.getConfigs([
'openaiBaseKey',
'openaiBaseUrl',
'openaiBaseModel',
]);
const key = openaiBaseKey;
const proxyUrl = openaiBaseUrl;
let requestData = [];
if (systemMessage) {
requestData.push({
"role": "system",
"content": systemMessage
});
}
if (messagesHistory && messagesHistory.length > 0) {
requestData = requestData.concat(messagesHistory);
}
else {
requestData.push({
"role": "user",
"content": prompt
});
}
const options = {
method: 'POST',
url: `${proxyUrl}/v1/chat/completions`,
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${key}`,
},
data: {
model: openaiBaseModel || 'gpt-3.5-turbo-0125',
messages: requestData,
},
};
try {
const response = await (0, axios_1.default)(options);
common_1.Logger.log(`全局模型调用成功, 返回结果: ${response === null || response === void 0 ? void 0 : response.data.choices[0].message.content}`);
return response === null || response === void 0 ? void 0 : response.data.choices[0].message.content;
}
catch (error) {
console.log('error: ', error);
}
this.chatLogService = chatLogService;
this.openAIChatService = openAIChatService;
this.logger = new common_1.Logger(OpenAIDrawService_1.name);
}
async dalleDraw(inputs, messagesHistory) {
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, } = inputs;
const size = (extraParam === null || extraParam === void 0 ? void 0 : extraParam.size) || '1024x1024';
let result = { answer: '', fileInfo: '', status: 2 };
try {
@ -89,25 +47,30 @@ let ApiDataService = ApiDataService_1 = class ApiDataService {
},
};
const response = await (0, axios_1.default)(options);
common_1.Logger.debug(`请求成功${JSON.stringify(response.data.data[0])}`);
common_1.Logger.debug(`请求状态${JSON.stringify(response.status)}`);
const url = response.data.data[0].url;
try {
const filename = `${Date.now()}-${uuid.v4().slice(0, 4)}.png`;
common_1.Logger.debug(`------> 开始上传图片!!!`, 'DrawService');
result.fileInfo = await this.uploadService.uploadFileFromUrl({ filename, url: url });
common_1.Logger.debug(`图片上传成功URL: ${result.fileInfo}`, 'DrawService');
common_1.Logger.log(`------> 开始上传图片!!!`, 'DrawService');
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: url,
dir: `images/dalle/${currentDate}`,
});
common_1.Logger.log(`图片上传成功URL: ${result.fileInfo}`, 'DrawService');
}
catch (error) {
common_1.Logger.error(`上传图片过程中出现错误: ${error}`, 'DrawService');
}
let revised_prompt_cn;
try {
revised_prompt_cn = await this.chatFree(`根据提示词{${response.data.data[0].revised_prompt}}, 模拟AI绘画机器人的语气用中文回复告诉用户已经画好了`);
revised_prompt_cn = await this.openAIChatService.chatFree(`根据提示词{${response.data.data[0].revised_prompt}}, 模拟AI绘画机器人的语气用中文回复告诉用户已经画好了`);
}
catch (error) {
revised_prompt_cn = `${prompt} 绘制成功`;
common_1.Logger.error("翻译失败: ", error);
common_1.Logger.error('翻译失败: ', error);
}
result.answer = revised_prompt_cn;
result.status = 3;
@ -124,12 +87,15 @@ let ApiDataService = ApiDataService_1 = class ApiDataService {
result.text = '当前请求已过载、请稍等会儿再试试吧!';
return result;
}
if (status === 400 && message.includes('This request has been blocked by our content filters')) {
if (status === 400 &&
message.includes('This request has been blocked by our content filters')) {
result.text = '您的请求已被系统拒绝。您的提示可能存在一些非法的文本。';
return result;
}
if (status === 400 && message.includes('Billing hard limit has been reached')) {
result.text = '当前模型key已被封禁、已冻结当前调用Key、尝试重新对话试试吧';
if (status === 400 &&
message.includes('Billing hard limit has been reached')) {
result.text =
'当前模型key已被封禁、已冻结当前调用Key、尝试重新对话试试吧';
return result;
}
if (status === 500) {
@ -145,9 +111,11 @@ let ApiDataService = ApiDataService_1 = class ApiDataService {
}
}
};
ApiDataService = ApiDataService_1 = __decorate([
OpenAIDrawService = OpenAIDrawService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [upload_service_1.UploadService,
globalConfig_service_1.GlobalConfigService])
], ApiDataService);
exports.ApiDataService = ApiDataService;
globalConfig_service_1.GlobalConfigService,
chatLog_service_1.ChatLogService,
openaiChat_service_1.OpenAIChatService])
], OpenAIDrawService);
exports.OpenAIDrawService = OpenAIDrawService;

View File

@ -0,0 +1,91 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var StableDiffusionService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StableDiffusionService = 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 StableDiffusionService = StableDiffusionService_1 = class StableDiffusionService {
constructor(uploadService, globalConfigService, chatLogService) {
this.uploadService = uploadService;
this.globalConfigService = globalConfigService;
this.chatLogService = chatLogService;
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;
let result = {
answer: '',
model: model,
modelName: modelName,
chatId: chatId,
fileInfo: '',
status: 2,
};
console.log('开始处理', { model, modelName, prompt });
const options = {
method: 'POST',
url: `${proxyUrl}/v1/chat/completions`,
timeout: timeout,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
data: {
model,
messages: [{ role: 'user', content: prompt }],
},
};
try {
const response = await (0, axios_1.default)(options);
console.log('API响应接收', response.data);
if (response.data.choices && response.data.choices.length > 0) {
const choice = response.data.choices[0];
const content = choice.message.content;
console.log('处理内容', content);
const regex = /\]\((https?:\/\/[^\)]+)\)/;
const match = content.match(regex);
if (match && match[1]) {
result.fileInfo = match[1];
console.log('找到链接', match[1]);
}
else {
console.log('没有找到链接');
}
let revised_prompt_cn;
result.answer = `${prompt} 绘制成功`;
if (result.fileInfo) {
onSuccess(result);
return;
}
else {
onFailure('No link found.');
}
}
else {
onFailure('No choices returned.');
}
}
catch (error) {
common_1.Logger.error('服务器错误,请求失败:', error);
}
}
};
StableDiffusionService = StableDiffusionService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [upload_service_1.UploadService,
globalConfig_service_1.GlobalConfigService,
chatLog_service_1.ChatLogService])
], StableDiffusionService);
exports.StableDiffusionService = StableDiffusionService;

247
dist/modules/ai/suno.service.js vendored Normal file
View File

@ -0,0 +1,247 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.SunoService = void 0;
const common_1 = require("@nestjs/common");
const axios_1 = require("axios");
const chatLog_service_1 = require("../chatLog/chatLog.service");
let SunoService = class SunoService {
constructor(chatLogService) {
this.chatLogService = chatLogService;
}
async suno(inputs) {
var _a, _b, _c;
const { apiKey, proxyUrl, action, prompt, timeout, assistantLogId, taskData, extraParam, } = inputs;
let result = {
text: '',
fileInfo: '',
taskId: '',
taskData: '',
status: 2,
};
common_1.Logger.log('开始生成音乐', 'SunoService');
let response = null;
let url = '';
let payloadJson = {};
const headers = { Authorization: `Bearer ${apiKey}` };
if (action === 'LYRICS') {
url = `${proxyUrl}/task/suno/v1/submit/lyrics`;
payloadJson = { prompt: prompt };
}
if (action === 'MUSIC') {
url = `${proxyUrl}/task/suno/v1/submit/music`;
try {
payloadJson = JSON.parse(taskData);
}
catch (error) {
common_1.Logger.error(`解析taskData失败: ${error.message}`, 'SunoService');
throw new Error('taskData格式错误');
}
}
common_1.Logger.log(`正在准备发送请求到 ${url}payload: ${JSON.stringify(payloadJson)}, headers: ${JSON.stringify(headers)}`);
try {
response = await axios_1.default.post(url, payloadJson, { headers });
}
catch (error) {
common_1.Logger.error(`任务提交失败: ${error.message}`, 'SunoService');
throw new Error('任务提交失败');
}
if ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.data) {
result.taskId = (_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.data;
common_1.Logger.log(`任务提交成功, 任务ID: ${(_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.data}`, 'SunoService');
}
else {
throw new Error('未能获取结果数据, 即将重试');
}
try {
await this.pollSunoMusicResult({
proxyUrl,
apiKey,
taskId: response.data.data,
timeout,
prompt,
action,
onSuccess: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
videoUrl: data === null || data === void 0 ? void 0 : data.videoUrl,
audioUrl: data === null || data === void 0 ? void 0 : data.audioUrl,
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || prompt,
progress: '100%',
status: 3,
taskId: data === null || data === void 0 ? void 0 : data.taskId,
taskData: data === null || data === void 0 ? void 0 : data.taskData,
});
common_1.Logger.log('音乐任务已完成', 'SunoService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'SunoService');
}
},
onAudioSuccess: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
videoUrl: data === null || data === void 0 ? void 0 : data.videoUrl,
audioUrl: data === null || data === void 0 ? void 0 : data.audioUrl,
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || prompt,
progress: data === null || data === void 0 ? void 0 : data.progress,
status: data.status,
taskId: data === null || data === void 0 ? void 0 : data.taskId,
taskData: data === null || data === void 0 ? void 0 : data.taskData,
});
common_1.Logger.log('音频生成成功,等待视频生成...', 'SunoService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'SunoService');
}
},
onGenerating: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
videoUrl: data === null || data === void 0 ? void 0 : data.videoUrl,
audioUrl: data === null || data === void 0 ? void 0 : data.audioUrl,
fileInfo: data === null || data === void 0 ? void 0 : data.fileInfo,
answer: (data === null || data === void 0 ? void 0 : data.answer) || '音乐生成中...',
progress: data === null || data === void 0 ? void 0 : data.progress,
status: data.status,
});
common_1.Logger.log('音乐生成中...', 'SunoService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'SunoService');
}
},
onFailure: async (data) => {
try {
await this.chatLogService.updateChatLog(assistantLogId, {
answer: '音乐生成失败',
status: data.status,
});
common_1.Logger.log('生成失败', 'SunoService');
}
catch (error) {
common_1.Logger.error(`更新日志失败: ${error.message}`, 'SunoService');
}
},
});
}
catch (error) {
common_1.Logger.error('查询生成结果时发生错误:', error.message, 'SunoService');
throw new Error('查询生成结果时发生错误');
}
return result;
}
async pollSunoMusicResult(inputs) {
const { proxyUrl, apiKey, taskId, timeout, onSuccess, onAudioSuccess, onFailure, onGenerating, action, } = inputs;
let result = {
videoUrl: '',
audioUrl: '',
fileInfo: '',
drawId: '',
taskData: '',
status: 2,
progress: 0,
answer: '',
};
const headers = { Authorization: `Bearer ${apiKey}` };
const url = `${proxyUrl}/task/suno/v1/fetch/${taskId}`;
const startTime = Date.now();
const POLL_INTERVAL = 5000;
let retryCount = 0;
try {
while (Date.now() - startTime < timeout) {
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
try {
const res = await axios_1.default.get(url, { headers });
const responses = res.data.data;
if (action === 'LYRICS') {
if (responses.status === 'SUCCESS') {
result.taskId = responses.data.id;
result.taskData = JSON.stringify(responses.data);
result.answer = responses.data.text;
onSuccess(result);
return;
}
result.progress = responses === null || responses === void 0 ? void 0 : responses.progress;
result.answer = `歌词生成中`;
if (result.progress) {
onGenerating(result);
}
}
if (action === 'MUSIC') {
const data = responses.data;
if (responses.data) {
const data = responses.data;
result.taskData = JSON.stringify(data);
if (Array.isArray(data)) {
const validAudioUrls = data
.map((item) => item.audio_url)
.filter((url) => url);
const validVideoUrls = data
.map((item) => item.video_url)
.filter((url) => url);
const validImageUrls = data
.map((item) => item.image_url)
.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;
}
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}`;
}
onAudioSuccess(result);
}
}
if (responses.status === 'SUCCESS') {
common_1.Logger.debug(`音乐生成成功: ${JSON.stringify(data)}`, 'SunoService');
onSuccess(result);
return;
}
if (result.progress && result.status === 2) {
onGenerating(result);
}
}
}
catch (error) {
retryCount++;
common_1.Logger.error(`轮询失败,重试次数: ${retryCount}`, 'SunoService');
}
}
common_1.Logger.error('轮询超时,请稍后再试!', 'SunoService');
result.status = 4;
onFailure(result);
throw new Error('查询超时,请稍后再试!');
}
catch (error) {
common_1.Logger.error(`轮询过程中发生错误: ${error}`, 'SunoService');
result.status = 5;
onFailure(result);
}
}
};
SunoService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [chatLog_service_1.ChatLogService])
], SunoService);
exports.SunoService = SunoService;

View File

@ -13,22 +13,22 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppController = void 0;
const app_service_1 = require("./app.service");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const createCats_dto_1 = require("./dto/createCats.dto");
const updateCats_dto_1 = require("./dto/updateCats.dto");
const deleteCats_dto_1 = require("./dto/deleteCats.dto");
const queryCats_dto_1 = require("./dto/queryCats.dto");
const createApp_dto_1 = require("./dto/createApp.dto");
const updateApp_dto_1 = require("./dto/updateApp.dto");
const deleteApp_dto_1 = require("./dto/deleteApp.dto");
const queryApp_dto_1 = require("./dto/queryApp.dto");
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
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 app_service_1 = require("./app.service");
const collectApp_dto_1 = require("./dto/collectApp.dto");
const createApp_dto_1 = require("./dto/createApp.dto");
const createCats_dto_1 = require("./dto/createCats.dto");
const custonApp_dto_1 = require("./dto/custonApp.dto");
const deleteApp_dto_1 = require("./dto/deleteApp.dto");
const deleteCats_dto_1 = require("./dto/deleteCats.dto");
const queryApp_dto_1 = require("./dto/queryApp.dto");
const queryCats_dto_1 = require("./dto/queryCats.dto");
const updateApp_dto_1 = require("./dto/updateApp.dto");
const updateCats_dto_1 = require("./dto/updateCats.dto");
let AppController = class AppController {
constructor(appService) {
this.appService = appService;
@ -61,6 +61,9 @@ let AppController = class AppController {
list(req, query) {
return this.appService.frontAppList(req, query);
}
async searchList(body) {
return this.appService.searchAppList(body);
}
createApp(body) {
return this.appService.createApp(body);
}
@ -176,6 +179,14 @@ __decorate([
__metadata("design:paramtypes", [Object, queryApp_dto_1.QuerAppDto]),
__metadata("design:returntype", void 0)
], AppController.prototype, "list", null);
__decorate([
(0, common_1.Post)('searchList'),
(0, swagger_1.ApiOperation)({ summary: '客户端获取App' }),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AppController.prototype, "searchList", null);
__decorate([
(0, common_1.Post)('createApp'),
(0, swagger_1.ApiOperation)({ summary: '添加App' }),

View File

@ -50,7 +50,9 @@ let AppService = class AppService {
}
async updateAppCats(body) {
const { id, name } = body;
const c = await this.appCatsEntity.findOne({ where: { name, id: (0, typeorm_2.Not)(id) } });
const c = await this.appCatsEntity.findOne({
where: { name, id: (0, typeorm_2.Not)(id) },
});
if (c) {
throw new common_1.HttpException('该分类名称已存在!', common_1.HttpStatus.BAD_REQUEST);
}
@ -65,7 +67,7 @@ let AppService = class AppService {
throw new common_1.HttpException('缺失必要参数!', common_1.HttpStatus.BAD_REQUEST);
}
const app = await this.appEntity.findOne({ where: { id } });
const { demoData: demo, coverImg, des, name, isFixedModel, isGPTs, appModel } = app;
const { demoData: demo, coverImg, des, name, isFixedModel, isGPTs, appModel, } = app;
return {
demoData: demo ? demo.split('\n') : [],
coverImg,
@ -140,7 +142,12 @@ let AppService = class AppService {
var _a;
const { page = 1, size = 1000, name, catId, role } = query;
const where = [
{ status: (0, typeorm_2.In)([1, 4]), userId: (0, typeorm_2.IsNull)(), public: false, isSystemReserved: 0 },
{
status: (0, typeorm_2.In)([1, 4]),
userId: (0, typeorm_2.IsNull)(),
public: false,
isSystemReserved: 0,
},
{ userId: (0, typeorm_2.MoreThan)(0), public: true },
];
const [rows, count] = await this.appEntity.findAndCount({
@ -162,6 +169,42 @@ let AppService = class AppService {
}
return { rows, count };
}
async searchAppList(body) {
console.log('搜索App列表', body);
const { page = 1, size = 1000, keyword } = body;
console.log(`搜索关键词:${keyword}`);
let baseWhere = [
{
status: (0, typeorm_2.In)([1, 4]),
userId: (0, typeorm_2.IsNull)(),
public: false,
isSystemReserved: 0,
},
{ userId: (0, typeorm_2.MoreThan)(0), public: true },
];
console.log('初始查询条件:', JSON.stringify(baseWhere));
if (keyword) {
baseWhere = baseWhere.map((condition) => (Object.assign(Object.assign({}, condition), { name: (0, typeorm_2.Like)(`%${keyword}%`) })));
console.log('更新后的查询条件:', JSON.stringify(baseWhere));
}
try {
const [rows, count] = await this.appEntity.findAndCount({
where: baseWhere,
skip: (page - 1) * size,
take: size,
});
console.log(`查询返回 ${count} 条结果,显示第 ${page} 页的结果。`);
rows.forEach((item) => {
delete item.preset;
});
console.log('完成查询,准备返回结果');
return { rows, count };
}
catch (error) {
console.error('查询数据库时出错:', error);
throw new Error('Database query failed');
}
}
async createApp(body) {
const { name, catId } = body;
body.role = 'system';
@ -177,13 +220,24 @@ let AppService = class AppService {
}
async customApp(body, req) {
const { id } = req.user;
const { name, catId, des, preset, coverImg, demoData, public: isPublic, appId } = body;
const { name, catId, des, preset, coverImg, demoData, public: isPublic, appId, } = body;
if (appId) {
const a = await this.appEntity.findOne({ where: { id: appId, userId: id } });
const a = await this.appEntity.findOne({
where: { id: appId, userId: id },
});
if (!a) {
throw new common_1.HttpException('您正在编辑一个不存在的应用!', common_1.HttpStatus.BAD_REQUEST);
}
const data = { name, catId, des, preset, coverImg, demoData, public: isPublic, status: isPublic ? 3 : 1 };
const data = {
name,
catId,
des,
preset,
coverImg,
demoData,
public: isPublic,
status: isPublic ? 3 : 1,
};
const res = await this.appEntity.update({ id: appId, userId: id }, data);
if (res.affected) {
return '修改成功';
@ -201,9 +255,27 @@ let AppService = class AppService {
if (a) {
throw new common_1.HttpException('该应用名称已存在!', common_1.HttpStatus.BAD_REQUEST);
}
const data = { name, catId, des, preset, coverImg, status: isPublic ? 3 : 1, demoData, public: isPublic, role: 'user', userId: id };
const data = {
name,
catId,
des,
preset,
coverImg,
status: isPublic ? 3 : 1,
demoData,
public: isPublic,
role: 'user',
userId: id,
};
const res = await this.appEntity.save(data);
const params = { appId: res.id, userId: id, appType: 'user', public: isPublic, status: isPublic ? 3 : 1, catId };
const params = {
appId: res.id,
userId: id,
appType: 'user',
public: isPublic,
status: isPublic ? 3 : 1,
catId,
};
return this.userAppsEntity.save(params);
}
}
@ -229,7 +301,9 @@ 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) } });
const existingApp = await this.appEntity.findOne({
where: { name, id: (0, typeorm_2.Not)(id) },
});
if (existingApp) {
common_1.Logger.warn(`应用名称已存在:${name}`);
throw new common_1.HttpException('该应用名称已存在!', common_1.HttpStatus.BAD_REQUEST);
@ -249,9 +323,6 @@ let AppService = class AppService {
throw new common_1.HttpException('该应用不存在!', common_1.HttpStatus.BAD_REQUEST);
}
const useApp = await this.userAppsEntity.count({ where: { appId: id } });
if (useApp > 0) {
throw new common_1.HttpException('该应用已被用户关联使用中,不可删除!', common_1.HttpStatus.BAD_REQUEST);
}
const res = await this.appEntity.delete(id);
if (res.affected > 0)
return '删除App成功';
@ -279,7 +350,9 @@ let AppService = class AppService {
}
async delMineApp(body, req) {
const { id } = body;
const a = await this.appEntity.findOne({ where: { id, userId: req.user.id } });
const a = await this.appEntity.findOne({
where: { id, userId: req.user.id },
});
if (!a) {
throw new common_1.HttpException('您正在操作一个不存在的资源!', common_1.HttpStatus.BAD_REQUEST);
}
@ -290,7 +363,9 @@ let AppService = class AppService {
async collect(body, req) {
const { appId } = body;
const { id: userId } = req.user;
const historyApp = await this.userAppsEntity.findOne({ where: { appId, userId } });
const historyApp = await this.userAppsEntity.findOne({
where: { appId, userId },
});
if (historyApp) {
const r = await this.userAppsEntity.delete({ appId, userId });
if (r.affected > 0) {
@ -302,7 +377,14 @@ let AppService = class AppService {
}
const app = await this.appEntity.findOne({ where: { id: appId } });
const { id, role: appRole, catId } = app;
const collectInfo = { userId, appId: id, catId, appRole, public: true, status: 1 };
const collectInfo = {
userId,
appId: id,
catId,
appRole,
public: true,
status: 1,
};
await this.userAppsEntity.save(collectInfo);
return '已将应用加入到我的收藏!';
}

View File

@ -10,22 +10,14 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppCatsEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
const typeorm_1 = require("typeorm");
let AppCatsEntity = class AppCatsEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ unique: true, comment: 'App分类名称' }),
__metadata("design:type", String)
], AppCatsEntity.prototype, "name", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'App分类描述信息' }),
__metadata("design:type", String)
], AppCatsEntity.prototype, "des", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'App分类封面图片', nullable: true }),
__metadata("design:type", String)
], AppCatsEntity.prototype, "coverImg", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'App分类排序、数字越大越靠前', default: 100 }),
__metadata("design:type", Number)

View File

@ -10,37 +10,35 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateCatsDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class CreateCatsDto {
}
__decorate([
(0, swagger_1.ApiProperty)({ example: '编程助手', description: 'app分类名称', required: true }),
(0, swagger_1.ApiProperty)({
example: '编程助手',
description: 'app分类名称',
required: true,
}),
(0, class_validator_1.IsDefined)({ message: 'app分类名称是必传参数' }),
__metadata("design:type", String)
], CreateCatsDto.prototype, "name", void 0);
__decorate([
(0, swagger_1.ApiProperty)({
example: '适用于编程编码、期望成为您的编程助手',
description: 'app分类名称详情描述',
example: 100,
description: '分类排序、数字越大越靠前',
required: false,
}),
(0, class_validator_1.IsDefined)({ message: 'app分类名称描述是必传参数' }),
__metadata("design:type", String)
], CreateCatsDto.prototype, "des", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'https://xxxx.png', description: '套餐封面图片' }),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], CreateCatsDto.prototype, "coverImg", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 100, description: '套餐排序、数字越大越靠前', required: false }),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", Number)
], CreateCatsDto.prototype, "order", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '套餐状态 0禁用 1启用', required: true }),
(0, class_validator_1.IsNumber)({}, { message: '套餐状态必须是Number' }),
(0, swagger_1.ApiProperty)({
example: 1,
description: '分类状态 0禁用 1启用',
required: true,
}),
(0, class_validator_1.IsNumber)({}, { message: '状态必须是Number' }),
(0, class_validator_1.IsIn)([0, 1, 3, 4, 5], { message: '套餐状态错误' }),
__metadata("design:type", Number)
], CreateCatsDto.prototype, "status", void 0);

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuerAppDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class QuerAppDto {
}
__decorate([
@ -44,4 +44,9 @@ __decorate([
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], QuerAppDto.prototype, "role", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: '关键词', description: '搜索关键词', required: false }),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], QuerAppDto.prototype, "keyword", void 0);
exports.QuerAppDto = QuerAppDto;

View File

@ -18,6 +18,7 @@ const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const auth_service_1 = require("./auth.service");
const authLogin_dto_1 = require("./dto/authLogin.dto");
const authRegister_dto_1 = require("./dto/authRegister.dto");
const updatePassByOther_dto_1 = require("./dto/updatePassByOther.dto");
const updatePassword_dto_1 = require("./dto/updatePassword.dto");
let AuthController = class AuthController {
@ -30,6 +31,9 @@ let AuthController = class AuthController {
async login(body, req) {
return this.authService.login(body, req);
}
async loginWithCaptcha(body, req) {
return this.authService.loginWithCaptcha(body, req);
}
async updatePassword(req, body) {
return this.authService.updatePassword(req, body);
}
@ -52,7 +56,7 @@ __decorate([
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:paramtypes", [authRegister_dto_1.UserRegisterDto, Object]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "register", null);
__decorate([
@ -64,6 +68,15 @@ __decorate([
__metadata("design:paramtypes", [authLogin_dto_1.UserLoginDto, Object]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "login", null);
__decorate([
(0, common_1.Post)('loginWithCaptcha'),
(0, swagger_1.ApiOperation)({ summary: '用户使用验证码登录' }),
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "loginWithCaptcha", null);
__decorate([
(0, common_1.Post)('updatePassword'),
(0, swagger_1.ApiOperation)({ summary: '用户更改密码' }),

View File

@ -13,8 +13,6 @@ const common_1 = require("@nestjs/common");
const jwt_1 = require("@nestjs/jwt");
const passport_1 = require("@nestjs/passport");
const typeorm_1 = require("@nestjs/typeorm");
const nestjs_config_1 = require("nestjs-config");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
@ -42,10 +40,14 @@ AuthModule = __decorate([
(0, common_1.Module)({
imports: [
user_module_1.UserModule,
redisCache_module_1.RedisCacheModule,
passport_1.PassportModule.register({ defaultStrategy: 'jwt' }),
jwt_1.JwtModule.registerAsync({
useFactory: async (configService) => configService.get('jwt'),
inject: [nestjs_config_1.ConfigService],
inject: [redisCache_service_1.RedisCacheService],
useFactory: async (redisService) => ({
secret: await redisService.getJwtSecret(),
signOptions: { expiresIn: '7d' },
}),
}),
typeorm_1.TypeOrmModule.forFeature([
verifycation_entity_1.VerifycationEntity,
@ -53,19 +55,25 @@ AuthModule = __decorate([
accountLog_entity_1.AccountLogEntity,
config_entity_1.ConfigEntity,
cramiPackage_entity_1.CramiPackageEntity,
redisCache_module_1.RedisCacheModule,
userBalance_entity_1.UserBalanceEntity,
salesUsers_entity_1.SalesUsersEntity,
user_entity_1.UserEntity,
whiteList_entity_1.WhiteListEntity,
fingerprint_entity_1.FingerprintLogEntity,
chatLog_entity_1.ChatLogEntity,
chatGroup_entity_1.ChatGroupEntity,
midjourney_entity_1.MidjourneyEntity
midjourney_entity_1.MidjourneyEntity,
]),
],
controllers: [auth_controller_1.AuthController],
providers: [auth_service_1.AuthService, jwt_strategy_1.JwtStrategy, jwtAuth_guard_1.JwtAuthGuard, mailer_service_1.MailerService, verification_service_1.VerificationService, userBalance_service_1.UserBalanceService, redisCache_service_1.RedisCacheService],
providers: [
auth_service_1.AuthService,
jwt_strategy_1.JwtStrategy,
jwtAuth_guard_1.JwtAuthGuard,
mailer_service_1.MailerService,
verification_service_1.VerificationService,
userBalance_service_1.UserBalanceService,
redisCache_service_1.RedisCacheService,
],
exports: [auth_service_1.AuthService],
})
], AuthModule);

View File

@ -44,57 +44,109 @@ let AuthService = class AuthService {
this.getIp();
}
async register(body, req) {
const { username, password, contact, code, invitedBy } = body;
await this.verificationService.verifyCaptcha(body);
const { password, contact, code, invitedBy } = body;
let email = '', phone = '';
const isEmail = /\S+@\S+\.\S+/.test(contact);
const isPhone = /^\d{10,}$/.test(contact);
common_1.Logger.debug(`Contact: ${contact}, isEmail: ${isEmail}, isPhone: ${isPhone}`);
let username = (0, utils_1.createRandomUid)();
while (true) {
const usernameTaken = await this.userService.verifyUserRegister({
username,
});
common_1.Logger.debug(`Checking if username ${username} is taken: ${usernameTaken}`);
if (usernameTaken) {
break;
}
username = (0, utils_1.createRandomUid)();
}
if (isEmail) {
email = contact;
await this.userService.verifyUserRegister({ username, email });
const isAvailable = await this.userService.verifyUserRegister({
username,
email,
});
common_1.Logger.debug(`Email ${email} is available: ${isAvailable}`);
if (!isAvailable) {
throw new common_1.HttpException('当前邮箱已注册,请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
}
}
else if (isPhone) {
phone = contact;
await this.userService.verifyUserRegister({ username, phone });
const isAvailable = await this.userService.verifyUserRegister({
username,
phone,
});
common_1.Logger.debug(`Phone ${phone} is available: ${isAvailable}`);
if (!isAvailable) {
throw new common_1.HttpException('当前手机号已注册,请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
}
}
else {
throw new common_1.HttpException('请提供有效的邮箱地址或手机号码。', common_1.HttpStatus.BAD_REQUEST);
}
const nameSpace = await this.globalConfigService.getNamespace();
const key = `${nameSpace}:CODE:${contact}`;
const redisCode = await this.redisCacheService.get({ key });
if (!redisCode) {
common_1.Logger.log(`验证码过期: ${contact}`);
throw new common_1.HttpException('验证码已过期,请重新发送!', common_1.HttpStatus.BAD_REQUEST);
const noVerifyRegister = await this.globalConfigService.getConfigs([
'noVerifyRegister',
]);
common_1.Logger.debug(`noVerifyRegister: ${noVerifyRegister}`);
if (noVerifyRegister !== '1') {
const nameSpace = await this.globalConfigService.getNamespace();
const key = `${nameSpace}:CODE:${contact}`;
const redisCode = await this.redisCacheService.get({ key });
common_1.Logger.debug(`Retrieved redisCode for ${contact}: ${redisCode}`);
if (code === '') {
throw new common_1.HttpException('请输入验证码', common_1.HttpStatus.BAD_REQUEST);
}
if (!redisCode) {
common_1.Logger.log(`验证码过期: ${contact}`);
throw new common_1.HttpException('验证码已过期,请重新发送!', common_1.HttpStatus.BAD_REQUEST);
}
if (code !== redisCode) {
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`);
throw new common_1.HttpException('验证码填写错误,请重新输入!', common_1.HttpStatus.BAD_REQUEST);
}
}
if (code !== redisCode) {
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`);
throw new common_1.HttpException('验证码填写错误,请重新输入!', common_1.HttpStatus.BAD_REQUEST);
}
console.log('开始创建用户...');
let newUser;
if (isEmail) {
newUser = { username, password, email: contact, invitedBy, status: user_constant_1.UserStatusEnum.ACTIVE };
newUser = {
username,
password,
email: contact,
invitedBy,
status: user_constant_1.UserStatusEnum.ACTIVE,
};
}
else {
const email = `${(0, utils_1.createRandomUid)()}@aiweb.com`;
newUser = { username, password, email, phone: contact, invitedBy, status: user_constant_1.UserStatusEnum.ACTIVE };
newUser = {
username,
password,
email,
phone: contact,
invitedBy,
status: user_constant_1.UserStatusEnum.ACTIVE,
};
}
;
console.log('获取默认用户头像...');
const userDefautlAvatar = await this.globalConfigService.getConfigs(['userDefautlAvatar']);
console.log(`使用默认用户头像: ${userDefautlAvatar}`);
common_1.Logger.debug('获取默认用户头像...');
const userDefautlAvatar = await this.globalConfigService.getConfigs([
'userDefautlAvatar',
]);
common_1.Logger.debug(`使用默认用户头像: ${userDefautlAvatar}`);
newUser.avatar = userDefautlAvatar;
console.log('加密用户密码...');
common_1.Logger.debug('加密用户密码...');
const hashedPassword = bcrypt.hashSync(password, 10);
newUser.password = hashedPassword;
console.log('保存新用户到数据库...');
common_1.Logger.debug('保存新用户到数据库...');
const u = await this.userService.createUser(newUser);
console.log(`用户创建成功用户ID: ${u.id}`);
common_1.Logger.debug(`用户创建成功用户ID: ${u.id}`);
let inviteUser;
if (invitedBy) {
inviteUser = await this.userService.qureyUserInfoByInviteCode(invitedBy);
common_1.Logger.debug(`邀请人信息: ${inviteUser}`);
}
await this.userBalanceService.addBalanceToNewUser(u.id, inviteUser === null || inviteUser === void 0 ? void 0 : inviteUser.id);
common_1.Logger.debug('完成新用户余额处理');
return { success: true, message: '注册成功' };
}
async login(user, req) {
@ -109,7 +161,73 @@ let AuthService = class AuthService {
const ip = (0, utils_1.getClientIp)(req);
await this.userService.savaLoginIp(id, ip);
console.log(`保存登录IP: ${ip} - 用户ID: ${id}`);
const token = await this.jwtService.sign({ username, id, email, role, openId, client, phone });
const token = await this.jwtService.sign({
username,
id,
email,
role,
openId,
client,
phone,
});
console.log(`JWT令牌生成成功 - 用户ID: ${id}`);
await this.redisCacheService.saveToken(id, token);
console.log(`令牌已保存到Redis - 用户ID: ${id}`);
return token;
}
async loginWithCaptcha(body, req) {
const { contact, code } = body;
let email = '', phone = '';
const isEmail = /\S+@\S+\.\S+/.test(contact);
const isPhone = /^\d{10,}$/.test(contact);
if (isEmail) {
email = contact;
}
else if (isPhone) {
phone = contact;
}
else {
throw new common_1.HttpException('请提供有效的邮箱地址或手机号码。', common_1.HttpStatus.BAD_REQUEST);
}
const isAvailable = await this.userService.verifyUserRegister({
email,
phone,
});
const nameSpace = await this.globalConfigService.getNamespace();
const key = `${nameSpace}:CODE:${contact}`;
const redisCode = await this.redisCacheService.get({ key });
if (!redisCode) {
common_1.Logger.log(`验证码过期: ${contact}`);
throw new common_1.HttpException('验证码已过期,请重新发送!', common_1.HttpStatus.BAD_REQUEST);
}
if (code !== redisCode) {
common_1.Logger.log(`验证码错误: ${contact} 输入的验证码: ${code}, 期望的验证码: ${redisCode}`);
throw new common_1.HttpException('验证码填写错误,请重新输入!', common_1.HttpStatus.BAD_REQUEST);
}
let u;
if (isAvailable) {
u = await this.userService.createUserFromContact({ email, phone });
}
else {
u = await this.userService.getUserByContact({ email, phone });
}
if (!u) {
throw new common_1.HttpException('登录失败,用户凭证无效。', common_1.HttpStatus.UNAUTHORIZED);
}
const { username, id, role, openId, client } = u;
console.log(`用户凭证验证成功用户ID: ${id}, 用户名: ${username}`);
const ip = (0, utils_1.getClientIp)(req);
await this.userService.savaLoginIp(id, ip);
console.log(`保存登录IP: ${ip} - 用户ID: ${id}`);
const token = await this.jwtService.sign({
username,
id,
email,
role,
openId,
client,
phone,
});
console.log(`JWT令牌生成成功 - 用户ID: ${id}`);
await this.redisCacheService.saveToken(id, token);
console.log(`令牌已保存到Redis - 用户ID: ${id}`);
@ -123,7 +241,14 @@ let AuthService = class AuthService {
const { username, id, email, role, openId, client } = user;
const ip = (0, utils_1.getClientIp)(req);
await this.userService.savaLoginIp(id, ip);
const token = await this.jwtService.sign({ username, id, email, role, openId, client });
const token = await this.jwtService.sign({
username,
id,
email,
role,
openId,
client,
});
await this.redisCacheService.saveToken(id, token);
return token;
}
@ -139,10 +264,6 @@ let AuthService = class AuthService {
if (role === 'admin') {
throw new common_1.HttpException('非法操作、请联系管理员!', common_1.HttpStatus.BAD_REQUEST);
}
const bool = await this.userService.verifyUserPassword(id, body.oldPassword);
if (!bool) {
throw new common_1.HttpException('旧密码错误、请检查提交', common_1.HttpStatus.BAD_REQUEST);
}
this.userService.updateUserPassword(id, body.password);
return '密码修改成功';
}
@ -161,7 +282,9 @@ let AuthService = class AuthService {
const interfaceInfo = interfaces[interfaceName];
for (let i = 0; i < interfaceInfo.length; i++) {
const alias = interfaceInfo[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
if (alias.family === 'IPv4' &&
alias.address !== '127.0.0.1' &&
!alias.internal) {
ipAddress = alias.address;
break;
}
@ -172,34 +295,54 @@ let AuthService = class AuthService {
async captcha(parmas) {
const nameSpace = await this.globalConfigService.getNamespace();
const { color = '#fff' } = parmas;
const captcha = svgCaptcha.createMathExpr({ background: color, height: 30, width: 120, noise: 5 });
const captcha = svgCaptcha.create({
size: 5,
ignoreChars: '0o1i',
noise: 4,
color: true,
background: color,
height: 33,
width: 150,
});
const text = captcha.text;
const randomId = (0, utils_1.createRandomUid)();
const randomId = Math.random().toString(36).substr(2, 9);
const key = `${nameSpace}:CAPTCHA:${randomId}`;
await this.redisCacheService.set({ key, val: captcha.text }, 5 * 60);
await this.redisCacheService.set({ key, val: text }, 5 * 60);
return {
svgCode: captcha.data,
code: randomId,
};
}
async sendCode(body) {
await this.verificationService.verifyCaptcha(body);
const { contact, username } = body;
const { contact, isLogin } = body;
let email = '', phone = '';
const code = (0, utils_1.createRandomCode)();
const isEmail = /\S+@\S+\.\S+/.test(contact);
const isPhone = /^\d{10,}$/.test(contact);
if (isEmail) {
email = contact;
await this.userService.verifyUserRegister({ username, email });
}
else if (isPhone) {
phone = contact;
await this.userService.verifyUserRegister({ username, phone });
}
else {
if (!isEmail && !isPhone) {
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({
email,
});
if (!isAvailable) {
throw new common_1.HttpException('当前邮箱已注册,请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
}
}
else if (isPhone) {
phone = contact;
const isAvailable = await this.userService.verifyUserRegister({
phone,
});
if (!isAvailable) {
throw new common_1.HttpException('当前手机号已注册,请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
}
}
}
const nameSpace = await this.globalConfigService.getNamespace();
const key = `${nameSpace}:CODE:${contact}`;
const ttl = await this.redisCacheService.ttl(key);

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserLoginDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class UserLoginDto {
}
__decorate([

View File

@ -10,15 +10,12 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserRegisterDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class UserRegisterDto {
}
__decorate([
(0, swagger_1.ApiProperty)({ example: 'cooper', description: '用户名称' }),
(0, class_validator_1.IsNotEmpty)({ message: '用户名不能为空!' }),
(0, class_validator_1.MinLength)(2, { message: '用户名最低需要大于2位数' }),
(0, class_validator_1.MaxLength)(12, { message: '用户名不得超过12位' }),
__metadata("design:type", String)
], UserRegisterDto.prototype, "username", void 0);
__decorate([
@ -29,9 +26,7 @@ __decorate([
__metadata("design:type", String)
], UserRegisterDto.prototype, "password", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'J_longyan@163.com', description: '用户邮箱' }),
(0, class_validator_1.IsEmail)({}, { message: '请填写正确格式的邮箱!' }),
(0, class_validator_1.IsNotEmpty)({ message: '邮箱不能为空!' }),
(0, swagger_1.ApiProperty)({ example: 'ai@aiweb.com', description: '用户邮箱' }),
__metadata("design:type", String)
], UserRegisterDto.prototype, "email", void 0);
__decorate([
@ -45,7 +40,11 @@ __decorate([
__metadata("design:type", String)
], UserRegisterDto.prototype, "captchaId", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'FRJDLJHFNV', description: '用户填写的别人邀请码', required: false }),
(0, swagger_1.ApiProperty)({
example: 'FRJDLJHFNV',
description: '用户填写的别人邀请码',
required: false,
}),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], UserRegisterDto.prototype, "invitedBy", void 0);
@ -59,7 +58,11 @@ __decorate([
__metadata("design:type", String)
], UserRegisterDto.prototype, "avatar", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'default', description: '用户注册来源', required: false }),
(0, swagger_1.ApiProperty)({
example: 'default',
description: '用户注册来源',
required: false,
}),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], UserRegisterDto.prototype, "client", void 0);

View File

@ -10,17 +10,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdatePasswordDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class UpdatePasswordDto {
}
__decorate([
(0, swagger_1.ApiProperty)({ example: '123456', description: '用户旧密码' }),
(0, class_validator_1.IsNotEmpty)({ message: '用户密码不能为空!' }),
(0, class_validator_1.MinLength)(6, { message: '用户密码最低需要大于6位数' }),
(0, class_validator_1.MaxLength)(30, { message: '用户密码最长不能超过30位数' }),
__metadata("design:type", String)
], UpdatePasswordDto.prototype, "oldPassword", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: '666666', description: '用户更新新密码' }),
(0, class_validator_1.IsNotEmpty)({ message: '用户密码不能为空!' }),

View File

@ -14,9 +14,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
Object.defineProperty(exports, "__esModule", { value: true });
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 typeorm_1 = require("typeorm");
const typeorm_2 = require("@nestjs/typeorm");
let AutoreplyService = class AutoreplyService {
constructor(autoReplyEntity) {
this.autoReplyEntity = autoReplyEntity;
@ -44,7 +44,7 @@ let AutoreplyService = class AutoreplyService {
const { page = 1, size = 10, prompt, status } = query;
const where = {};
[0, 1, '0', '1'].includes(status) && (where.status = status);
prompt && (where.prompt = (0, typeorm_1.Like)(`%${prompt}%`));
prompt && (where.prompt = (0, typeorm_2.Like)(`%${prompt}%`));
const [rows, count] = await this.autoReplyEntity.findAndCount({
where,
skip: (page - 1) * size,
@ -88,7 +88,7 @@ let AutoreplyService = class AutoreplyService {
};
AutoreplyService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_2.InjectRepository)(autoreplay_entity_1.AutoReplyEntity)),
__metadata("design:paramtypes", [typeorm_1.Repository])
__param(0, (0, typeorm_1.InjectRepository)(autoreplay_entity_1.AutoReplyEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository])
], AutoreplyService);
exports.AutoreplyService = AutoreplyService;

View File

@ -18,7 +18,11 @@ __decorate([
__metadata("design:type", String)
], AddAutoReplyDto.prototype, "prompt", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: '我是NineAi提供的Ai服务机器人', description: '回答的答案', required: true }),
(0, swagger_1.ApiProperty)({
example: '我是AIWeb提供的Ai服务机器人',
description: '回答的答案',
required: true,
}),
__metadata("design:type", String)
], AddAutoReplyDto.prototype, "answer", void 0);
exports.AddAutoReplyDto = AddAutoReplyDto;

View File

@ -13,15 +13,15 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BadwordsService = void 0;
const globalConfig_service_1 = require("./../globalConfig/globalConfig.service");
const common_1 = require("@nestjs/common");
const badwords_entity_1 = require("./badwords.entity");
const typeorm_1 = require("typeorm");
const typeorm_2 = require("@nestjs/typeorm");
const axios_1 = require("axios");
const violationLog_entity_1 = require("./violationLog.entity");
const user_entity_1 = require("../user/user.entity");
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 user_entity_1 = require("../user/user.entity");
const globalConfig_service_1 = require("./../globalConfig/globalConfig.service");
const badwords_entity_1 = require("./badwords.entity");
const violationLog_entity_1 = require("./violationLog.entity");
let BadwordsService = class BadwordsService {
constructor(badWordsEntity, violationLogEntity, userEntity, globalConfigService) {
this.badWordsEntity = badWordsEntity;
@ -56,8 +56,8 @@ let BadwordsService = class BadwordsService {
}
async checkBadWordsByConfig(content, config, userId) {
const { useType } = config;
useType === 'baidu' && (await this.baiduCheckBadWords(content, config.baiduTextAccessToken, userId));
useType === 'nineai' && (await this.nineaiCheckBadWords(content, config, userId));
useType === 'baidu' &&
(await this.baiduCheckBadWords(content, config.baiduTextAccessToken, userId));
}
extractContent(str) {
const pattern = /存在(.*?)不合规/;
@ -78,46 +78,31 @@ let BadwordsService = class BadwordsService {
console.log('百度文本检测出现错误、请查看配置信息: ', error_msg);
}
if (conclusionType !== 1) {
const types = [...new Set(data.map((item) => this.extractContent(item.msg)))];
const types = [
...new Set(data.map((item) => this.extractContent(item.msg))),
];
await this.recordUserBadWords(userId, content, ['***'], types, '百度云检测');
const tips = `您提交的信息中包含${types.join(',')}的内容、我们已对您的账户进行标记、请合规使用!`;
throw new common_1.HttpException(tips, common_1.HttpStatus.BAD_REQUEST);
}
}
async nineaiCheckBadWords(content, config, userId) {
var _a;
const { nineaiBuiltInSensitiveApiBase, nineaiBuiltInSensitiveAuthKey } = config;
if (!nineaiBuiltInSensitiveApiBase || !nineaiBuiltInSensitiveAuthKey)
return;
const res = await axios_1.default.post(nineaiBuiltInSensitiveApiBase, { content }, { headers: { 'Content-Type': 'application/json', Authorization: nineaiBuiltInSensitiveAuthKey } });
if (!res.data)
return;
if (res.data.code !== '0') {
const { msg = '检测失败' } = res.data;
throw new common_1.HttpException(`敏感词检测 | ${msg}`, common_1.HttpStatus.BAD_REQUEST);
}
if (res.data.word_list && ((_a = res.data.word_list) === null || _a === void 0 ? void 0 : _a.length)) {
const words = [...new Set(res.data.word_list.map((t) => t.keyword))];
const types = [...new Set(res.data.word_list.map((t) => t.category))];
await this.recordUserBadWords(userId, content, words, types, 'NineAi检测');
const tips = this.formarTips(res.data.word_list);
throw new common_1.HttpException(tips, common_1.HttpStatus.BAD_REQUEST);
}
}
formarTips(wordList) {
const categorys = wordList.map((t) => t.category);
const unSet = [...new Set(categorys)];
return `您提交的内容中包含${unSet.join(',')}的信息、我们已对您账号进行标记、请合规使用!`;
}
async loadBadWords() {
const data = await this.badWordsEntity.find({ where: { status: 1 }, select: ['word'] });
const data = await this.badWordsEntity.find({
where: { status: 1 },
select: ['word'],
});
this.badWords = data.map((t) => t.word);
}
async queryBadWords(query) {
const { page = 1, size = 500, word, status } = query;
const where = {};
[0, 1, '0', '1'].includes(status) && (where.status = status);
word && (where.word = (0, typeorm_1.Like)(`%${word}%`));
word && (where.word = (0, typeorm_2.Like)(`%${word}%`));
const [rows, count] = await this.badWordsEntity.findAndCount({
where,
skip: (page - 1) * size,
@ -200,7 +185,7 @@ let BadwordsService = class BadwordsService {
});
const userIds = [...new Set(rows.map((t) => t.userId))];
const usersInfo = await this.userEntity.find({
where: { id: (0, typeorm_1.In)(userIds) },
where: { id: (0, typeorm_2.In)(userIds) },
select: ['id', 'avatar', 'username', 'email', 'violationCount', 'status'],
});
rows.forEach((t) => {
@ -213,12 +198,12 @@ let BadwordsService = class BadwordsService {
};
BadwordsService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_2.InjectRepository)(badwords_entity_1.BadWordsEntity)),
__param(1, (0, typeorm_2.InjectRepository)(violationLog_entity_1.ViolationLogEntity)),
__param(2, (0, typeorm_2.InjectRepository)(user_entity_1.UserEntity)),
__metadata("design:paramtypes", [typeorm_1.Repository,
typeorm_1.Repository,
typeorm_1.Repository,
__param(0, (0, typeorm_1.InjectRepository)(badwords_entity_1.BadWordsEntity)),
__param(1, (0, typeorm_1.InjectRepository)(violationLog_entity_1.ViolationLogEntity)),
__param(2, (0, typeorm_1.InjectRepository)(user_entity_1.UserEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
globalConfig_service_1.GlobalConfigService])
], BadwordsService);
exports.BadwordsService = BadwordsService;

View File

@ -18,8 +18,6 @@ const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
const chat_service_1 = require("./chat.service");
const common_1 = require("@nestjs/common");
const chatProcess_dto_1 = require("./dto/chatProcess.dto");
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
let ChatController = class ChatController {
constructor(chatService, globalConfigService) {
@ -32,56 +30,14 @@ let ChatController = class ChatController {
chatProcessSync(body, req) {
return this.chatService.chatProcess(Object.assign({}, body), req);
}
ttsProcess(body, req, res) {
return this.chatService.ttsProcess(body, req, res);
}
async mjFanyi(body, req) {
return this.chatService.chatProcess(Object.assign(Object.assign({}, body), { specialModel: 'PromptOptimization' }), req);
}
async chatmind(body, req, res) {
return this.chatService.chatProcess(Object.assign(Object.assign({}, body), { specialModel: 'MindMap' }), req, res);
}
async setChatBoxType(req, body) {
return await this.chatService.setChatBoxType(req, body);
}
async delChatBoxType(req, body) {
return await this.chatService.delChatBoxType(req, body);
}
async queryChatBoxType() {
return await this.chatService.queryChatBoxType();
}
async setChatBox(req, body) {
return await this.chatService.setChatBox(req, body);
}
async delChatBox(req, body) {
return await this.chatService.delChatBox(req, body);
}
async queryChatBox() {
return await this.chatService.queryChatBox();
}
async queryChatBoxFrontend() {
return await this.chatService.queryChatBoxFrontend();
}
async setChatPreType(req, body) {
return await this.chatService.setChatPreType(req, body);
}
async delChatPreType(req, body) {
return await this.chatService.delChatPreType(req, body);
}
async queryChatPreType() {
return await this.chatService.queryChatPreType();
}
async setChatPre(req, body) {
return await this.chatService.setChatPre(req, body);
}
async delChatPre(req, body) {
return await this.chatService.delChatPre(req, body);
}
async queryChatPre() {
return await this.chatService.queryChatPre();
}
async queryChatPreList() {
return await this.chatService.queryChatPreList();
ttsProcess(body, req, res) {
return this.chatService.ttsProcess(body, req, res);
}
};
__decorate([
@ -107,18 +63,6 @@ __decorate([
__metadata("design:paramtypes", [chatProcess_dto_1.ChatProcessDto, Object]),
__metadata("design:returntype", void 0)
], ChatController.prototype, "chatProcessSync", null);
__decorate([
(0, common_1.Post)('tts-process'),
(0, swagger_1.ApiOperation)({ summary: 'tts语音播报' }),
(0, common_1.UseGuards)(jwtAuth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__param(2, (0, common_1.Res)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [chatProcess_dto_1.ChatProcessDto, Object, Object]),
__metadata("design:returntype", void 0)
], ChatController.prototype, "ttsProcess", null);
__decorate([
(0, common_1.Post)('mj-fy'),
(0, swagger_1.ApiOperation)({ summary: 'gpt描述词绘画翻译' }),
@ -143,142 +87,21 @@ __decorate([
__metadata("design:returntype", Promise)
], ChatController.prototype, "chatmind", null);
__decorate([
(0, common_1.Post)('setChatBoxType'),
(0, swagger_1.ApiOperation)({ summary: '添加修改分类类型' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, common_1.Post)('tts-process'),
(0, swagger_1.ApiOperation)({ summary: 'tts语音播报' }),
(0, common_1.UseGuards)(jwtAuth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__param(2, (0, common_1.Res)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "setChatBoxType", null);
__decorate([
(0, common_1.Post)('delChatBoxType'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatBoxType' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "delChatBoxType", null);
__decorate([
(0, common_1.Get)('queryChatBoxTypes'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatBoxType' }),
(0, common_1.UseGuards)(adminAuth_guard_1.AdminAuthGuard),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatBoxType", null);
__decorate([
(0, common_1.Post)('setChatBox'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatBox' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "setChatBox", null);
__decorate([
(0, common_1.Post)('delChatBox'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatBox提示词' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "delChatBox", null);
__decorate([
(0, common_1.Get)('queryChatBoxs'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatBox列表' }),
(0, common_1.UseGuards)(adminAuth_guard_1.AdminAuthGuard),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatBox", null);
__decorate([
(0, common_1.Get)('queryChatBoxFrontend'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatBox分类加详细' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatBoxFrontend", null);
__decorate([
(0, common_1.Post)('setChatPreType'),
(0, swagger_1.ApiOperation)({ summary: '添加修改预设分类类型' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "setChatPreType", null);
__decorate([
(0, common_1.Post)('delChatPretype'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatPretype' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "delChatPreType", null);
__decorate([
(0, common_1.Get)('queryChatPretypes'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatPretype' }),
(0, common_1.UseGuards)(adminAuth_guard_1.AdminAuthGuard),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatPreType", null);
__decorate([
(0, common_1.Post)('setChatPre'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatPre' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "setChatPre", null);
__decorate([
(0, common_1.Post)('delChatPre'),
(0, swagger_1.ApiOperation)({ summary: '添加修改ChatPre提示词' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Req)()),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", Promise)
], ChatController.prototype, "delChatPre", null);
__decorate([
(0, common_1.Get)('queryChatPres'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatPre列表' }),
(0, common_1.UseGuards)(adminAuth_guard_1.AdminAuthGuard),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatPre", null);
__decorate([
(0, common_1.Get)('queryChatPreList'),
(0, swagger_1.ApiOperation)({ summary: '查询ChatPre列表' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], ChatController.prototype, "queryChatPreList", null);
__metadata("design:paramtypes", [Object, Object, Object]),
__metadata("design:returntype", void 0)
], ChatController.prototype, "ttsProcess", null);
ChatController = __decorate([
(0, swagger_1.ApiTags)('chatgpt'),
(0, common_1.Controller)('chatgpt'),
__metadata("design:paramtypes", [chat_service_1.ChatService, globalConfig_service_1.GlobalConfigService])
__metadata("design:paramtypes", [chat_service_1.ChatService,
globalConfig_service_1.GlobalConfigService])
], ChatController);
exports.ChatController = ChatController;

View File

@ -9,6 +9,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatModule = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const lumaVideo_service_1 = require("../ai/lumaVideo.service");
const midjourneyDraw_service_1 = require("../ai/midjourneyDraw.service");
const openaiChat_service_1 = require("../ai/openaiChat.service");
const openaiDraw_service_1 = require("../ai/openaiDraw.service");
const stableDiffusion_service_1 = require("../ai/stableDiffusion.service");
const suno_service_1 = require("../ai/suno.service");
const app_entity_1 = require("../app/app.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
@ -17,6 +23,7 @@ const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const mailer_service_1 = require("../mailer/mailer.service");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
const plugin_entity_1 = require("../plugin/plugin.entity");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const user_entity_1 = require("../user/user.entity");
@ -28,14 +35,8 @@ const userBalance_entity_1 = require("../userBalance/userBalance.entity");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const verification_service_1 = require("../verification/verification.service");
const verifycation_entity_1 = require("../verification/verifycation.entity");
const apiDataService_service_1 = require("./apiDataService.service");
const chat_controller_1 = require("./chat.controller");
const chat_service_1 = require("./chat.service");
const chatBox_entity_1 = require("./chatBox.entity");
const chatBoxType_entity_1 = require("./chatBoxType.entity");
const chatPre_entity_1 = require("./chatPre.entity");
const chatPreType_entity_1 = require("./chatPreType.entity");
const whiteList_entity_1 = require("./whiteList.entity");
let ChatModule = class ChatModule {
};
ChatModule = __decorate([
@ -45,11 +46,11 @@ ChatModule = __decorate([
typeorm_1.TypeOrmModule.forFeature([
balance_entity_1.BalanceEntity,
user_entity_1.UserEntity,
plugin_entity_1.PluginEntity,
verifycation_entity_1.VerifycationEntity,
chatLog_entity_1.ChatLogEntity,
accountLog_entity_1.AccountLogEntity,
config_entity_1.ConfigEntity,
whiteList_entity_1.WhiteListEntity,
user_entity_1.UserEntity,
cramiPackage_entity_1.CramiPackageEntity,
chatGroup_entity_1.ChatGroupEntity,
@ -58,15 +59,25 @@ ChatModule = __decorate([
salesUsers_entity_1.SalesUsersEntity,
fingerprint_entity_1.FingerprintLogEntity,
midjourney_entity_1.MidjourneyEntity,
chatBoxType_entity_1.ChatBoxTypeEntity,
chatBox_entity_1.ChatBoxEntity,
chatPreType_entity_1.ChatPreTypeEntity,
chatPre_entity_1.ChatPreEntity,
]),
],
controllers: [chat_controller_1.ChatController],
providers: [chat_service_1.ChatService, userBalance_service_1.UserBalanceService, user_service_1.UserService, verification_service_1.VerificationService, chatLog_service_1.ChatLogService, redisCache_service_1.RedisCacheService, apiDataService_service_1.ApiDataService, mailer_service_1.MailerService],
exports: [chat_service_1.ChatService]
providers: [
chat_service_1.ChatService,
userBalance_service_1.UserBalanceService,
user_service_1.UserService,
verification_service_1.VerificationService,
chatLog_service_1.ChatLogService,
redisCache_service_1.RedisCacheService,
mailer_service_1.MailerService,
suno_service_1.SunoService,
openaiChat_service_1.OpenAIChatService,
stableDiffusion_service_1.StableDiffusionService,
midjourneyDraw_service_1.MidjourneyService,
openaiDraw_service_1.OpenAIDrawService,
lumaVideo_service_1.LumaVideoService,
],
exports: [chat_service_1.ChatService],
})
], ChatModule);
exports.ChatModule = ChatModule;

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.ChatBoxTypeEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
let ChatBoxTypeEntity = class ChatBoxTypeEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ comment: '分类名称' }),
__metadata("design:type", String)
], ChatBoxTypeEntity.prototype, "name", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'icon图标' }),
__metadata("design:type", String)
], ChatBoxTypeEntity.prototype, "icon", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '排序ID', default: 10 }),
__metadata("design:type", Number)
], ChatBoxTypeEntity.prototype, "order", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '是否打开', default: true }),
__metadata("design:type", Boolean)
], ChatBoxTypeEntity.prototype, "status", void 0);
ChatBoxTypeEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'chat_box_type' })
], ChatBoxTypeEntity);
exports.ChatBoxTypeEntity = ChatBoxTypeEntity;

View File

@ -1,40 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.ChatPreEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
let ChatPreEntity = class ChatPreEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ comment: '分类ID' }),
__metadata("design:type", Number)
], ChatPreEntity.prototype, "typeId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '预设问题描述词', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatPreEntity.prototype, "prompt", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '标题名称' }),
__metadata("design:type", String)
], ChatPreEntity.prototype, "title", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '排序ID', default: 100 }),
__metadata("design:type", Number)
], ChatPreEntity.prototype, "order", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '开启状态', default: true }),
__metadata("design:type", Boolean)
], ChatPreEntity.prototype, "status", void 0);
ChatPreEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'chat_pre' })
], ChatPreEntity);
exports.ChatPreEntity = ChatPreEntity;

View File

@ -1,36 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.ChatPreTypeEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
let ChatPreTypeEntity = class ChatPreTypeEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ comment: '分类名称' }),
__metadata("design:type", String)
], ChatPreTypeEntity.prototype, "name", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'icon图标', nullable: true }),
__metadata("design:type", String)
], ChatPreTypeEntity.prototype, "icon", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '排序ID', default: 10 }),
__metadata("design:type", Number)
], ChatPreTypeEntity.prototype, "order", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '是否打开', default: true }),
__metadata("design:type", Boolean)
], ChatPreTypeEntity.prototype, "status", void 0);
ChatPreTypeEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'chat_pre_type' })
], ChatPreTypeEntity);
exports.ChatPreTypeEntity = ChatPreTypeEntity;

View File

@ -1,137 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NineStore = void 0;
const tiktoken_1 = require("@dqbd/tiktoken");
const uuid_1 = require("uuid");
const tokenizer = (0, tiktoken_1.get_encoding)('cl100k_base');
class NineStore {
constructor(options) {
const { store, namespace, expires } = this.formatOptions(options);
this.store = store;
this.namespace = namespace;
this.expires = expires;
}
formatOptions(options) {
const { store, expires = 1000 * 60 * 60 * 24 * 3, namespace = 'chat' } = options;
return { store, namespace, expires };
}
generateKey(key) {
return this.namespace ? `${this.namespace}-${key}` : key;
}
async getData(id) {
const res = await this.store.get(id);
return res;
}
async setData(message, expires = this.expires) {
await this.store.set(message.id, message, expires);
}
async buildMessageFromParentMessageId(text, options, chatLogService) {
let { systemMessage = '', fileInfo, model, groupId, maxRounds = 5, maxModelTokens = 4000, isFileUpload = 0 } = options;
let messages = [];
if (systemMessage) {
console.log('Adding system message:', systemMessage);
messages.push({ role: 'system', content: systemMessage });
}
if (groupId) {
console.log('Querying chat history for groupId:', groupId, 'with maxRounds:', maxRounds);
const history = await chatLogService.chatHistory(groupId, maxRounds);
console.log('Received history records:', history.length);
let tempUserMessage = null;
history.forEach((record) => {
let content;
if (isFileUpload === 2 && record.fileInfo) {
content = [
{ type: "text", text: record.text },
{ type: "image_url", image_url: { url: record.fileInfo } }
];
}
else if (isFileUpload === 1 && record.fileInfo) {
content = record.fileInfo + "\n" + record.text;
}
else {
content = record.text;
}
if (record.role === 'user') {
tempUserMessage = { role: record.role, content };
}
else if (record.role === 'assistant' && tempUserMessage && content.trim() !== '') {
messages.push(tempUserMessage);
messages.push({ role: record.role, content });
tempUserMessage = null;
}
});
}
let currentMessageContent;
if (isFileUpload === 2 && fileInfo) {
currentMessageContent = [
{ type: "text", text },
{ type: "image_url", image_url: { url: fileInfo } }
];
}
else if (isFileUpload === 1 && fileInfo) {
currentMessageContent = fileInfo + "\n" + text;
}
else {
currentMessageContent = text;
}
messages.push({ role: 'user', content: currentMessageContent });
let totalTokens = await this._getTokenCount(messages);
while (totalTokens > maxModelTokens / 2) {
if (messages.length === 2 && messages[0].role === 'system' && messages[1].role === 'user') {
break;
}
let foundPairToDelete = false;
for (let i = 0; i < messages.length; i++) {
if (messages[i].role !== 'system' && messages[i + 1] && messages[i + 1].role === 'assistant') {
messages.splice(i, 2);
foundPairToDelete = true;
break;
}
}
if (!foundPairToDelete) {
for (let i = 0; i < messages.length; i++) {
if (messages[i].role === 'user') {
messages.splice(i, 1);
break;
}
}
}
totalTokens = await this._getTokenCount(messages);
if (messages.length <= 2) {
break;
}
}
return {
messagesHistory: messages,
round: messages.length
};
}
_getTokenCount(messages) {
let text = messages.reduce((pre, cur) => {
if (Array.isArray(cur.content)) {
const contentText = cur.content
.filter((item) => item.type === 'text')
.map((item) => item.text)
.join(' ');
return pre + contentText;
}
else {
return pre + (cur.content || '');
}
}, '');
text = text.replace(/<\|endoftext\|>/g, '');
return tokenizer.encode(text).length;
}
_recursivePruning(messages, maxNumTokens, systemMessage) {
const currentTokens = this._getTokenCount(messages);
if (currentTokens <= maxNumTokens) {
return messages;
}
messages.splice(systemMessage ? 1 : 0, 1);
return this._recursivePruning(messages, maxNumTokens, systemMessage);
}
getUuid() {
return (0, uuid_1.v4)();
}
}
exports.NineStore = NineStore;

View File

@ -1,36 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.WhiteListEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
let WhiteListEntity = class WhiteListEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ unique: true, comment: '用户ID' }),
__metadata("design:type", Number)
], WhiteListEntity.prototype, "userId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '使用次数限制', default: 0 }),
__metadata("design:type", Number)
], WhiteListEntity.prototype, "count", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '当前用户状态', default: 1 }),
__metadata("design:type", Number)
], WhiteListEntity.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '已经使用的次数', default: 0 }),
__metadata("design:type", Number)
], WhiteListEntity.prototype, "useCount", void 0);
WhiteListEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'white_list' })
], WhiteListEntity);
exports.WhiteListEntity = WhiteListEntity;

View File

@ -23,13 +23,21 @@ __decorate([
__metadata("design:type", String)
], ChatLogEntity.prototype, "model", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '使用类型1: 普通对话 2: 绘图 3: 拓展性对话', nullable: true, default: 1 }),
(0, typeorm_1.Column)({
comment: '使用类型1: 普通对话 2: 绘图 3: 拓展性对话',
nullable: true,
default: 1,
}),
__metadata("design:type", Number)
], ChatLogEntity.prototype, "type", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '自定义的模型名称', nullable: true, default: 'AI' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "modelName", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '自定义的模型名称', nullable: false, default: '' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "modelAvatar", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'Ip地址', nullable: true }),
__metadata("design:type", String)
@ -67,19 +75,15 @@ __decorate([
__metadata("design:type", String)
], ChatLogEntity.prototype, "role", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '当前绘制任务进度', nullable: true }),
(0, typeorm_1.Column)({ comment: '任务进度', nullable: true }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "progress", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '当前绘制任务的耗时', nullable: true }),
__metadata("design:type", Number)
], ChatLogEntity.prototype, "durationSpent", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '当前绘制任务的状态', nullable: true, default: 3 }),
(0, typeorm_1.Column)({ comment: '任务状态', nullable: true, default: 3 }),
__metadata("design:type", Number)
], ChatLogEntity.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'mj绘画的动作、绘图、放大、变换、图生图', nullable: true }),
(0, typeorm_1.Column)({ comment: '任务类型', nullable: true }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "action", void 0);
__decorate([
@ -91,11 +95,7 @@ __decorate([
__metadata("design:type", String)
], ChatLogEntity.prototype, "drawId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '图片比例', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "drawRatio", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '对话或绘图附带的链接', nullable: true, type: 'text' }),
(0, typeorm_1.Column)({ comment: '文件信息', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "fileInfo", void 0);
__decorate([
@ -118,6 +118,22 @@ __decorate([
(0, typeorm_1.Column)({ comment: '是否删除', default: false }),
__metadata("design:type", Boolean)
], ChatLogEntity.prototype, "isDelete", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '任务ID', nullable: true }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "taskId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '任务数据', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "taskData", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '视频Url', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "videoUrl", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '音频Url', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatLogEntity.prototype, "audioUrl", void 0);
ChatLogEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'chatlog' })
], ChatLogEntity);

View File

@ -8,19 +8,26 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatLogModule = void 0;
const common_1 = require("@nestjs/common");
const chatLog_service_1 = require("./chatLog.service");
const typeorm_1 = require("@nestjs/typeorm");
const chatLog_entity_1 = require("./chatLog.entity");
const chatLog_controller_1 = require("./chatLog.controller");
const user_entity_1 = require("../user/user.entity");
const badwords_entity_1 = require("../badwords/badwords.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const user_entity_1 = require("../user/user.entity");
const chatLog_controller_1 = require("./chatLog.controller");
const chatLog_entity_1 = require("./chatLog.entity");
const chatLog_service_1 = require("./chatLog.service");
let ChatLogModule = class ChatLogModule {
};
ChatLogModule = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({
imports: [typeorm_1.TypeOrmModule.forFeature([chatLog_entity_1.ChatLogEntity, user_entity_1.UserEntity, badwords_entity_1.BadWordsEntity, chatGroup_entity_1.ChatGroupEntity])],
imports: [
typeorm_1.TypeOrmModule.forFeature([
chatLog_entity_1.ChatLogEntity,
user_entity_1.UserEntity,
badwords_entity_1.BadWordsEntity,
chatGroup_entity_1.ChatGroupEntity,
]),
],
controllers: [chatLog_controller_1.ChatLogController],
providers: [chatLog_service_1.ChatLogService],
exports: [chatLog_service_1.ChatLogService],

View File

@ -59,7 +59,9 @@ let ChatLogService = class ChatLogService {
if (r.type === 'paintCount') {
const w = r.model === 'mj' ? 310 : 160;
const imgType = r.answer.includes('cos') ? 'tencent' : 'ali';
const compress = imgType === 'tencent' ? `?imageView2/1/w/${w}/q/55` : `?x-oss-process=image/resize,w_${w}`;
const compress = imgType === 'tencent'
? `?imageView2/1/w/${w}/q/55`
: `?x-oss-process=image/resize,w_${w}`;
r.thumbImg = r.answer + compress;
try {
r.fileInfo = r.fileInfo ? JSON.parse(r.fileInfo) : null;
@ -73,23 +75,43 @@ let ChatLogService = class ChatLogService {
}
async querAllDrawLog(params) {
const { page = 1, size = 20, rec, userId, model } = params;
const where = { type: 2, prompt: (0, typeorm_2.Not)(''), answer: (0, typeorm_2.Not)(''), fileInfo: (0, typeorm_2.Not)(''), };
const where = {
type: 2,
prompt: (0, typeorm_2.Not)(''),
answer: (0, typeorm_2.Not)(''),
fileInfo: (0, typeorm_2.Not)(''),
};
rec && Object.assign(where, { rec });
userId && Object.assign(where, { userId });
if (model) {
where.model = model;
}
else {
where.model = (0, typeorm_2.In)(['midjourney', 'dall-e-3', 'stable-diffusion']);
}
const [rows, count] = await this.chatLogEntity.findAndCount({
order: { id: 'DESC' },
skip: (page - 1) * size,
take: size,
where,
});
const userIds = rows
.map((item) => item.userId)
.filter((id) => id < 100000);
const userInfos = await this.userEntity.find({
where: { id: (0, typeorm_2.In)(userIds) },
select: ['id', 'username', 'avatar', 'email'],
});
rows.forEach((item) => {
item.userInfo = userInfos.find((user) => user.id === item.userId);
});
rows.forEach((r) => {
var _a;
const w = r.model === 'midjourney' ? 310 : 160;
const imgType = r.answer.includes('cos') ? 'tencent' : 'ali';
const compress = imgType === 'tencent' ? `?imageView2/1/w/${w}/q/55` : `?x-oss-process=image/resize,w_${w}`;
const compress = imgType === 'tencent'
? `?imageView2/1/w/${w}/q/55`
: `?x-oss-process=image/resize,w_${w}`;
r.thumbImg = r.answer + compress;
try {
const detailInfo = r.extend ? JSON.parse(r.extend) : null;
@ -115,7 +137,9 @@ let ChatLogService = class ChatLogService {
}
async recDrawImg(body) {
const { id } = body;
const l = await this.chatLogEntity.findOne({ where: { id, type: balance_constant_1.ChatType.PAINT } });
const l = await this.chatLogEntity.findOne({
where: { id, type: balance_constant_1.ChatType.PAINT },
});
if (!l) {
throw new common_1.HttpException('你推荐的图片不存在、请检查!', common_1.HttpStatus.BAD_REQUEST);
}
@ -141,7 +165,9 @@ let ChatLogService = class ChatLogService {
where,
});
const userIds = rows.map((r) => r.userId);
const userInfos = await this.userEntity.find({ where: { id: (0, typeorm_2.In)(userIds) } });
const userInfos = await this.userEntity.find({
where: { id: (0, typeorm_2.In)(userIds) },
});
const data = rows.map((r) => {
const userInfo = userInfos.find((u) => u.id === r.userId);
return {
@ -179,15 +205,19 @@ let ChatLogService = class ChatLogService {
where,
});
const userIds = rows.map((item) => item.userId);
const userInfo = await this.userEntity.find({ where: { id: (0, typeorm_2.In)(userIds) }, select: ['id', 'username', 'email'] });
const userInfo = await this.userEntity.find({
where: { id: (0, typeorm_2.In)(userIds) },
select: ['id', 'username', 'email'],
});
rows.forEach((item) => {
const { username, email } = userInfo.find((u) => u.id === item.userId) || {};
item.username = username;
item.email = email;
});
req.user.role !== 'super' && rows.forEach((t) => (t.email = (0, utils_1.maskEmail)(t.email)));
req.user.role !== 'super' &&
rows.forEach((t) => (t.email = (0, utils_1.maskEmail)(t.email)));
rows.forEach((item) => {
!item.email && (item.email = `${item === null || item === void 0 ? void 0 : item.userId}@nine.com`);
!item.email && (item.email = `${item === null || item === void 0 ? void 0 : item.userId}@aiweb.com`);
!item.username && (item.username = `游客${item === null || item === void 0 ? void 0 : item.userId}`);
});
return { rows, count };
@ -198,13 +228,15 @@ let ChatLogService = class ChatLogService {
const where = { userId: id, isDelete: false };
groupId && Object.assign(where, { groupId });
if (groupId) {
const count = await this.chatGroupEntity.count({ where: { isDelete: false } });
const count = await this.chatGroupEntity.count({
where: { isDelete: false },
});
if (count === 0)
return [];
}
const list = await this.chatLogEntity.find({ where });
return list.map((item) => {
const { prompt, role, answer, createdAt, model, modelName, type, status, action, drawId, id, fileInfo, ttsUrl, customId, pluginParam } = item;
const { prompt, role, answer, createdAt, model, modelName, type, status, action, drawId, id, fileInfo, ttsUrl, videoUrl, audioUrl, customId, pluginParam, modelAvatar, taskData, } = item;
return {
chatId: id,
dateTime: (0, utils_1.formatDate)(createdAt),
@ -218,9 +250,13 @@ let ChatLogService = class ChatLogService {
error: false,
fileInfo: fileInfo,
ttsUrl: ttsUrl,
videoUrl: videoUrl,
audioUrl: audioUrl,
model: model,
modelName: modelName,
pluginParam: pluginParam,
modelAvatar: modelAvatar,
taskData: taskData,
};
});
}
@ -232,18 +268,23 @@ let ChatLogService = class ChatLogService {
const list = await this.chatLogEntity.find({
where,
order: {
createdAt: 'DESC'
createdAt: 'DESC',
},
take: rounds * 2
take: rounds * 2,
});
return list.map((item) => {
const result = list
.map((item) => {
const { role, prompt, answer, fileInfo } = item;
return {
const record = {
role: role,
text: role === 'user' ? prompt : answer,
fileInfo: fileInfo,
};
}).reverse();
return record;
})
.reverse();
common_1.Logger.debug('处理后的结果:', JSON.stringify(result, null, 2));
return result;
}
async deleteChatLog(req, body) {
const { id: userId } = req.user;
@ -263,7 +304,9 @@ let ChatLogService = class ChatLogService {
async delByGroupId(req, body) {
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);
}
@ -295,7 +338,7 @@ let ChatLogService = class ChatLogService {
userId: userId.id,
model,
createdAt: (0, typeorm_2.MoreThan)(oneHourAgo),
}
},
});
adjustedUsageCount = Math.ceil(usageCount / 2);
common_1.Logger.debug(`用户ID: ${userId.id} 模型: ${model} 一小时内已调用: ${adjustedUsageCount}`);

View File

@ -8,23 +8,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
Object.defineProperty(exports, "__esModule", { value: true });
exports.CramiModule = void 0;
const common_1 = require("@nestjs/common");
const crami_service_1 = require("./crami.service");
const crami_controller_1 = require("./crami.controller");
const typeorm_1 = require("@nestjs/typeorm");
const crami_entity_1 = require("./crami.entity");
const cramiPackage_entity_1 = require("./cramiPackage.entity");
const user_entity_1 = require("../user/user.entity");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const balance_entity_1 = require("../userBalance/balance.entity");
const accountLog_entity_1 = require("../userBalance/accountLog.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const userBalance_entity_1 = require("../userBalance/userBalance.entity");
const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const fingerprint_entity_1 = require("../userBalance/fingerprint.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const user_entity_1 = require("../user/user.entity");
const accountLog_entity_1 = require("../userBalance/accountLog.entity");
const balance_entity_1 = require("../userBalance/balance.entity");
const fingerprint_entity_1 = require("../userBalance/fingerprint.entity");
const userBalance_entity_1 = require("../userBalance/userBalance.entity");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const crami_controller_1 = require("./crami.controller");
const crami_entity_1 = require("./crami.entity");
const crami_service_1 = require("./crami.service");
const cramiPackage_entity_1 = require("./cramiPackage.entity");
let CramiModule = class CramiModule {
};
CramiModule = __decorate([
@ -40,11 +39,10 @@ CramiModule = __decorate([
accountLog_entity_1.AccountLogEntity,
config_entity_1.ConfigEntity,
userBalance_entity_1.UserBalanceEntity,
whiteList_entity_1.WhiteListEntity,
fingerprint_entity_1.FingerprintLogEntity,
chatLog_entity_1.ChatLogEntity,
chatGroup_entity_1.ChatGroupEntity,
midjourney_entity_1.MidjourneyEntity
midjourney_entity_1.MidjourneyEntity,
]),
],
providers: [crami_service_1.CramiService, userBalance_service_1.UserBalanceService],

View File

@ -13,13 +13,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.DatabaseModule = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const nestjs_config_1 = require("nestjs-config");
const typeorm_2 = require("typeorm");
const database_service_1 = require("./database.service");
let DatabaseModule = DatabaseModule_1 = class DatabaseModule {
constructor(connection, config) {
constructor(connection) {
this.connection = connection;
this.config = config;
this.logger = new common_1.Logger(DatabaseModule_1.name);
}
onModuleInit() {
@ -31,12 +29,22 @@ DatabaseModule = DatabaseModule_1 = __decorate([
(0, common_1.Module)({
imports: [
typeorm_1.TypeOrmModule.forRootAsync({
useFactory: (config) => config.get('database'),
inject: [nestjs_config_1.ConfigService],
useFactory: () => ({
type: 'mysql',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT, 10),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE,
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
logging: false,
charset: 'utf8mb4',
timezone: '+08:00',
}),
}),
],
providers: [database_service_1.DatabaseService],
}),
__metadata("design:paramtypes", [typeorm_2.Connection, nestjs_config_1.ConfigService])
__metadata("design:paramtypes", [typeorm_2.DataSource])
], DatabaseModule);
exports.DatabaseModule = DatabaseModule;

View File

@ -29,8 +29,22 @@ let DatabaseService = class DatabaseService {
const adminPassword = bcrypt.hashSync('123456', 10);
const superEmail = 'super';
const adminEmail = 'admin';
const superUserinfo = { username: 'super', password: superPassword, status: 1, email: superEmail, sex: 1, role: 'super' };
const adminUserinfo = { username: 'admin', password: adminPassword, status: 0, email: adminEmail, sex: 1, role: 'admin' };
const superUserinfo = {
username: 'super',
password: superPassword,
status: 1,
email: superEmail,
sex: 1,
role: 'super',
};
const adminUserinfo = {
username: 'admin',
password: adminPassword,
status: 0,
email: adminEmail,
sex: 1,
role: 'admin',
};
await this.createDefaultUser(superUserinfo);
await this.createDefaultUser(adminUserinfo);
}
@ -41,7 +55,7 @@ let DatabaseService = class DatabaseService {
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)`);
common_1.Logger.log(`初始化创建${role}用户成功、用户名为[${username}]、初始密码为[${username === 'super' ? 'nine-super' : '123456'}] ==============> 请注意查阅`, 'DatabaseService');
common_1.Logger.log(`初始化创建${role}用户成功、用户名为[${username}]、初始密码为[${username === 'super' ? 'super' : '123456'}] ==============> 请注意查阅`, 'DatabaseService');
}
catch (error) {
console.log('error: ', error);
@ -49,9 +63,17 @@ let DatabaseService = class DatabaseService {
}
}
async checkSiteBaseConfig() {
const keys = ['siteName', 'qqNumber', 'vxNumber', 'robotAvatar', 'userDefautlAvatar'];
const keys = [
'siteName',
'qqNumber',
'vxNumber',
'robotAvatar',
'userDefautlAvatar',
];
const result = await this.connection.query(`
SELECT COUNT(*) AS count FROM config WHERE \`configKey\` IN (${keys.map((k) => `'${k}'`).join(',')})
SELECT COUNT(*) AS count FROM config WHERE \`configKey\` IN (${keys
.map((k) => `'${k}'`)
.join(',')})
`);
const count = parseInt(result[0].count);
if (count === 0) {
@ -87,27 +109,112 @@ let DatabaseService = class DatabaseService {
encry: 0,
},
{ configKey: 'buyCramiAddress', configVal: '', public: 1, encry: 0 },
{ configKey: 'openaiBaseUrl', configVal: 'https://api.lightai.io', public: 0, encry: 0 },
{
configKey: 'openaiBaseUrl',
configVal: 'https://api.lightai.io',
public: 0,
encry: 0,
},
{ configKey: 'openaiTimeout', configVal: '300', public: 0, encry: 0 },
{ configKey: 'openaiBaseKey', configVal: 'sk-', public: 0, encry: 0 },
{ configKey: 'mjTranslatePrompt', configVal: `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.`, public: 0, encry: 0 },
{
configKey: 'mjTranslatePrompt',
configVal: `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.`,
public: 0,
encry: 0,
},
{ configKey: 'noticeInfo', configVal: noticeInfo, public: 1, encry: 0 },
{ configKey: 'registerSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'registerSendModel3Count', configVal: '30', public: 1, encry: 0 },
{ configKey: 'registerSendModel4Count', configVal: '3', public: 1, encry: 0 },
{ configKey: 'registerSendDrawMjCount', configVal: '3', public: 1, encry: 0 },
{ configKey: 'firstRegisterSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'firstRegisterSendRank', configVal: '500', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel3Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendModel4Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'firstRregisterSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
{
configKey: 'registerSendStatus',
configVal: '1',
public: 1,
encry: 0,
},
{
configKey: 'registerSendModel3Count',
configVal: '30',
public: 1,
encry: 0,
},
{
configKey: 'registerSendModel4Count',
configVal: '3',
public: 1,
encry: 0,
},
{
configKey: 'registerSendDrawMjCount',
configVal: '3',
public: 1,
encry: 0,
},
{
configKey: 'firstRegisterSendStatus',
configVal: '1',
public: 1,
encry: 0,
},
{
configKey: 'firstRegisterSendRank',
configVal: '500',
public: 1,
encry: 0,
},
{
configKey: 'firstRregisterSendModel3Count',
configVal: '10',
public: 1,
encry: 0,
},
{
configKey: 'firstRregisterSendModel4Count',
configVal: '10',
public: 1,
encry: 0,
},
{
configKey: 'firstRregisterSendDrawMjCount',
configVal: '10',
public: 1,
encry: 0,
},
{ configKey: 'inviteSendStatus', configVal: '1', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel3Count', configVal: '0', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendModel4Count', configVal: '0', public: 1, encry: 0 },
{ configKey: 'inviteGiveSendDrawMjCount', configVal: '0', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendModel3Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendModel4Count', configVal: '10', public: 1, encry: 0 },
{ configKey: 'invitedGuestSendDrawMjCount', configVal: '10', public: 1, encry: 0 },
{
configKey: 'inviteGiveSendModel3Count',
configVal: '0',
public: 1,
encry: 0,
},
{
configKey: 'inviteGiveSendModel4Count',
configVal: '0',
public: 1,
encry: 0,
},
{
configKey: 'inviteGiveSendDrawMjCount',
configVal: '0',
public: 1,
encry: 0,
},
{
configKey: 'invitedGuestSendModel3Count',
configVal: '10',
public: 1,
encry: 0,
},
{
configKey: 'invitedGuestSendModel4Count',
configVal: '10',
public: 1,
encry: 0,
},
{
configKey: 'invitedGuestSendDrawMjCount',
configVal: '10',
public: 1,
encry: 0,
},
{ configKey: 'isVerifyEmail', configVal: '1', public: 1, encry: 0 },
];
const res = await this.connection.query(`INSERT INTO config (configKey, configVal, public, encry) VALUES ${defaultConfig
@ -122,15 +229,39 @@ let DatabaseService = class DatabaseService {
}
async createSystemReservedApps() {
const systemApps = [
{ name: "提示词优化PromptOptimization", catId: 9900, des: "PromptOptimization", preset: "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.", appModel: "gpt-3.5-turbo", isFixedModel: 1, isSystemReserved: 1 },
{ name: "思维导图MindMap", catId: 9900, des: "MindMap", preset: "我希望你使用markdown格式回答我得问题、我的需求是得到一份markdown格式的大纲、尽量做的精细、层级多一点、不管我问你什么、都需要您回复我一个大纲出来、我想使用大纲做思维导图、除了大纲之外、不要无关内容和总结。", appModel: "gpt-3.5-turbo", isFixedModel: 1, isSystemReserved: 1 },
{
name: '提示词优化PromptOptimization',
catId: 9900,
des: 'PromptOptimization',
preset: "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.",
appModel: 'gpt-3.5-turbo',
isFixedModel: 1,
isSystemReserved: 1,
},
{
name: '思维导图MindMap',
catId: 9900,
des: 'MindMap',
preset: '我希望你使用markdown格式回答我得问题、我的需求是得到一份markdown格式的大纲、尽量做的精细、层级多一点、不管我问你什么、都需要您回复我一个大纲出来、我想使用大纲做思维导图、除了大纲之外、不要无关内容和总结。',
appModel: 'gpt-3.5-turbo',
isFixedModel: 1,
isSystemReserved: 1,
},
];
try {
for (const app of systemApps) {
const result = await this.connection.query(`SELECT COUNT(*) AS count FROM app WHERE name = ? AND des = ? AND isSystemReserved = ?`, [app.name, app.des, app.isSystemReserved]);
const count = parseInt(result[0].count, 10);
if (count === 0) {
await this.connection.query(`INSERT INTO app (name, catId, des, preset, appModel, isFixedModel, isSystemReserved) VALUES (?, ?, ?, ?, ?, ?, ?)`, [app.name, app.catId, app.des, app.preset, app.appModel, app.isFixedModel, app.isSystemReserved]);
await this.connection.query(`INSERT INTO app (name, catId, des, preset, appModel, isFixedModel, isSystemReserved) VALUES (?, ?, ?, ?, ?, ?, ?)`, [
app.name,
app.catId,
app.des,
app.preset,
app.appModel,
app.isFixedModel,
app.isSystemReserved,
]);
common_1.Logger.log(`系统预留应用${app.name}创建成功`, 'DatabaseService');
}
}

View File

@ -1,23 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initDatabase = void 0;
const mysql = require("mysql2/promise");
const common_1 = require("@nestjs/common");
function initDatabase() {
mysql
.createConnection({
const dotenv_1 = require("dotenv");
const mysql = require("mysql2/promise");
const typeorm_1 = require("typeorm");
(0, dotenv_1.config)();
const dataSourceOptions = {
type: 'mysql',
port: parseInt(process.env.DB_PORT, 10),
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE,
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
logging: false,
synchronize: true,
charset: 'utf8mb4',
timezone: '+08:00',
};
async function validateDatabase() {
const conn = await mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
port: parseInt(process.env.DB_PORT),
})
.then(async (conn) => {
const [rows] = await conn.execute(`SHOW DATABASES LIKE '${process.env.DB_DATABASE}'`);
port: parseInt(process.env.DB_PORT, 10),
});
try {
const [rows] = (await conn.execute(`SHOW DATABASES LIKE '${process.env.DB_DATABASE}'`));
if (Array.isArray(rows) && rows.length === 0) {
await conn.execute(`CREATE DATABASE ${process.env.DB_DATABASE}`);
common_1.Logger.log(`数据库创建成功[${process.env.DB_DATABASE}]`);
common_1.Logger.log(`数据库创建成功[${process.env.DB_DATABASE}]`, 'Database');
}
else {
common_1.Logger.log(`数据库已存在[${process.env.DB_DATABASE}]`, 'Database');
}
}
catch (error) {
common_1.Logger.error('Error during database validation:', error, 'Database');
}
finally {
await conn.end();
}
}
async function updateColumnType() {
const conn = await mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
port: parseInt(process.env.DB_PORT, 10),
database: process.env.DB_DATABASE,
});
async function checkAndUpdateColumnType(tableName, columnName) {
try {
const [rows] = (await conn.execute(`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ?`, [tableName, columnName]));
if (rows.length > 0 && rows[0].DATA_TYPE !== 'text') {
await conn.execute(`ALTER TABLE ?? MODIFY COLUMN ?? TEXT`, [
tableName,
columnName,
]);
common_1.Logger.log(`Column ${columnName} type updated to TEXT in table ${tableName}`, 'Database');
}
else {
common_1.Logger.log(`Column ${columnName} is already of type TEXT in table ${tableName}`, 'Database');
}
}
catch (error) {
common_1.Logger.error(`Error updating column type in table ${tableName}:`, error);
}
}
try {
await checkAndUpdateColumnType('config', 'configVal');
await checkAndUpdateColumnType('app', 'coverImg');
}
finally {
await conn.end();
}
}
async function initDatabase() {
await validateDatabase();
await updateColumnType();
const dataSource = new typeorm_1.DataSource(dataSourceOptions);
try {
await dataSource.initialize();
common_1.Logger.log('Database connected and synchronized successfully', 'Database');
}
catch (error) {
common_1.Logger.error('Error during TypeORM initialization:', error);
}
finally {
await dataSource.destroy();
}
}
exports.initDatabase = initDatabase;

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
const typeorm_1 = require("typeorm");
let ConfigEntity = class ConfigEntity extends baseEntity_1.BaseEntity {
};
__decorate([
@ -19,15 +19,21 @@ __decorate([
__metadata("design:type", String)
], ConfigEntity.prototype, "configKey", void 0);
__decorate([
(0, typeorm_1.Column)({ length: 3000, comment: '配置内容', nullable: true }),
(0, typeorm_1.Column)({ type: 'text', comment: '配置内容', nullable: true }),
__metadata("design:type", String)
], ConfigEntity.prototype, "configVal", void 0);
__decorate([
(0, typeorm_1.Column)({ default: 0, comment: '配置是否公开,公开内容对前端项目展示 0不公开 1公开' }),
(0, typeorm_1.Column)({
default: 0,
comment: '配置是否公开,公开内容对前端项目展示 0不公开 1公开',
}),
__metadata("design:type", Number)
], ConfigEntity.prototype, "public", void 0);
__decorate([
(0, typeorm_1.Column)({ default: 0, comment: '配置是否加密加密内容仅仅super权限可看 0不加 1加' }),
(0, typeorm_1.Column)({
default: 0,
comment: '配置是否加密加密内容仅仅super权限可看 0不加 1加',
}),
__metadata("design:type", Number)
], ConfigEntity.prototype, "encry", void 0);
__decorate([

View File

@ -10,13 +10,16 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SetConfigDto = void 0;
const class_validator_1 = require("class-validator");
const class_transformer_1 = require("class-transformer");
const swagger_1 = require("@nestjs/swagger");
const class_transformer_1 = require("class-transformer");
const class_validator_1 = require("class-validator");
class SetConfigDto {
}
__decorate([
(0, swagger_1.ApiProperty)({ example: [{ configKey: 'siteName', configVal: 'NineAI' }], description: '设置配置信息' }),
(0, swagger_1.ApiProperty)({
example: [{ configKey: 'siteName', configVal: 'AIWeb' }],
description: '设置配置信息',
}),
(0, class_validator_1.IsArray)(),
(0, class_validator_1.ArrayNotEmpty)(),
(0, class_validator_1.ValidateNested)({ each: true }),

View File

@ -10,13 +10,16 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SetConfigCustomDto = void 0;
const class_validator_1 = require("class-validator");
const class_transformer_1 = require("class-transformer");
const swagger_1 = require("@nestjs/swagger");
const class_transformer_1 = require("class-transformer");
const class_validator_1 = require("class-validator");
class SetConfigCustomDto {
}
__decorate([
(0, swagger_1.ApiProperty)({ example: { configKey: 'siteName', configVal: 'NineAI', infoKey: 'NineAI' }, description: '设置更新配置信息' }),
(0, swagger_1.ApiProperty)({
example: { configKey: 'siteName', configVal: 'AIWeb', infoKey: 'AIWeb' },
description: '设置更新配置信息',
}),
(0, class_validator_1.ValidateNested)({ each: true }),
(0, class_transformer_1.Type)(() => Object),
__metadata("design:type", Object)

View File

@ -32,7 +32,6 @@ let GlobalConfigService = class GlobalConfigService {
this.chatLogEntity = chatLogEntity;
this.modelsService = modelsService;
this.globalConfigs = {};
this.nineAiToken = true;
}
async onModuleInit() {
await this.initGetAllConfig();
@ -64,11 +63,17 @@ let GlobalConfigService = class GlobalConfigService {
this.initBaiduSensitive();
}
async initBaiduSensitive(isInit = true) {
const { baiduTextApiKey, baiduTextSecretKey } = await this.getConfigs(['baiduTextApiKey', 'baiduTextSecretKey']);
const { baiduTextApiKey, baiduTextSecretKey } = await this.getConfigs([
'baiduTextApiKey',
'baiduTextSecretKey',
]);
if (!baiduTextApiKey || !baiduTextSecretKey) {
return;
}
const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
const headers = {
'Content-Type': 'application/json',
Accept: 'application/json',
};
const url = `https://aip.baidubce.com/oauth/2.0/token?client_id=${baiduTextApiKey}&client_secret=${baiduTextSecretKey}&grant_type=client_credentials`;
try {
const response = await axios_1.default.post(url, { headers });
@ -96,7 +101,8 @@ let GlobalConfigService = class GlobalConfigService {
this.wechatAccessToken = '';
return;
}
const { data: { errmsg, access_token }, } = await axios_1.default.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}`);
const Url = (0, utils_1.formatUrl)(process.env.weChatApiUrl || 'https://api.weixin.qq.com');
const { data: { errmsg, access_token }, } = await axios_1.default.get(`${Url}/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}`);
if (errmsg) {
if (isInit) {
common_1.Logger.error(`获取微信access_token失败、错误信息${errmsg}`, 'OfficialService');
@ -114,7 +120,8 @@ let GlobalConfigService = class GlobalConfigService {
this.wechatJsapiTicket = '';
return;
}
const res = await axios_1.default.get(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`);
const Url = (0, utils_1.formatUrl)(process.env.weChatApiUrl || 'https://api.weixin.qq.com');
const res = await axios_1.default.get(`${Url}/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`);
return (_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.ticket;
}
async queryAllConfig(req) {
@ -166,8 +173,6 @@ let GlobalConfigService = class GlobalConfigService {
'salesAllowDrawMoney',
'companyName',
'filingNumber',
'phoneRegisterStatus',
'emailRegisterStatus',
'emailLoginStatus',
'phoneLoginStatus',
'wechatRegisterStatus',
@ -177,17 +182,33 @@ let GlobalConfigService = class GlobalConfigService {
'signInModel4Count',
'signInMjDrawToken',
'appMenuHeaderTips',
'appMenuHeaderBgUrl',
'pluginFirst',
'mjUseBaiduFy',
'mjHideNotBlock',
'mjHideWorkIn',
'isVerifyEmail',
'isHideSidebar',
'isHideTts',
'isHideModel3Point',
'isHideModel4Point',
'isHideDrawMjPoint',
'model3Name',
'model4Name',
'drawMjName',
'isModelInherited',
'noVerifyRegister',
];
const data = await this.configEntity.find({ where: { configKey: (0, typeorm_2.In)(allowKeys) } });
const data = await this.configEntity.find({
where: { configKey: (0, typeorm_2.In)(allowKeys) },
});
const { domain } = query;
const domainDb = this.globalConfigs['domain'];
if (domainDb !== domain) {
this.createOrUpdate({ configKey: `domain`, configVal: domain, status: 1 });
this.createOrUpdate({
configKey: `domain`,
configVal: domain,
status: 1,
});
await this.initGetAllConfig();
}
const publicConfig = data.reduce((prev, cur) => {
@ -200,7 +221,9 @@ let GlobalConfigService = class GlobalConfigService {
}
async queryGptKeys(req) {
const { role } = req.user;
const data = await this.configEntity.find({ where: { configKey: (0, typeorm_2.Like)(`%${'chatGptKey'}%`) } });
const data = await this.configEntity.find({
where: { configKey: (0, typeorm_2.Like)(`%${'chatGptKey'}%`) },
});
if (role === 'super')
return data;
return data.map((t) => {
@ -213,9 +236,15 @@ let GlobalConfigService = class GlobalConfigService {
const keys = effectiveConfig.map((t) => t.configKey);
for (const [index, value] of effectiveConfig.entries()) {
const { configKey, configVal, status } = value;
await this.createOrUpdate({ configKey: `chatGptKey:${index + 1}`, configVal, status });
await this.createOrUpdate({
configKey: `chatGptKey:${index + 1}`,
configVal,
status,
});
}
const likeChatGptKeys = await this.configEntity.find({ where: { configKey: (0, typeorm_2.Like)(`%${'chatGptKey'}%`) } });
const likeChatGptKeys = await this.configEntity.find({
where: { configKey: (0, typeorm_2.Like)(`%${'chatGptKey'}%`) },
});
const allKey = likeChatGptKeys.map((t) => t.configKey);
if (allKey.length > keys.length) {
const diffKey = (0, utils_1.getDiffArray)(allKey.length, keys.length, 'chatGptKey:');
@ -229,7 +258,9 @@ let GlobalConfigService = class GlobalConfigService {
async queryConfig(body, req) {
const { role } = req.user;
const { keys } = body;
const data = await this.configEntity.find({ where: { configKey: (0, typeorm_2.In)(keys) } });
const data = await this.configEntity.find({
where: { configKey: (0, typeorm_2.In)(keys) },
});
if (role !== 'super') {
data.forEach((item) => {
if (item.configKey.includes('mj') ||
@ -247,8 +278,14 @@ let GlobalConfigService = class GlobalConfigService {
if (longKeys.includes(item.configKey)) {
return (item.configVal = (0, utils_1.hideString)(item.configVal, '隐私内容、非超级管理员无权查看'));
}
const whiteListKey = ['payEpayStatus', 'payHupiStatus', 'mjProxy', 'payLtzfStatus'];
if (!whiteListKey.includes(item.configKey) && !item.configKey.includes('Status')) {
const whiteListKey = [
'payEpayStatus',
'payHupiStatus',
'mjProxy',
'payLtzfStatus',
];
if (!whiteListKey.includes(item.configKey) &&
!item.configKey.includes('Status')) {
item.configVal = (0, utils_1.hideString)(item.configVal);
}
}
@ -259,11 +296,6 @@ let GlobalConfigService = class GlobalConfigService {
return prev;
}, {});
}
getNineAiToken() {
const MjdrawCount = this.globalConfigs['MjdrawCount'];
const auth = this.nineAiToken;
return !auth || Number(MjdrawCount) === 1;
}
async setConfig(body) {
try {
const { settings } = body;
@ -272,10 +304,12 @@ let GlobalConfigService = class GlobalConfigService {
}
await this.initGetAllConfig();
const keys = settings.map((t) => t.configKey);
if (keys.includes('baiduTextApiKey') || keys.includes('baiduTextSecretKey')) {
if (keys.includes('baiduTextApiKey') ||
keys.includes('baiduTextSecretKey')) {
await this.initBaiduSensitive(false);
}
if (keys.includes('wechatOfficialAppId') || keys.includes('wechatOfficialAppSecret')) {
if (keys.includes('wechatOfficialAppId') ||
keys.includes('wechatOfficialAppSecret')) {
await this.getWechatAccessToken();
}
return '设置完成!';
@ -292,7 +326,11 @@ let GlobalConfigService = class GlobalConfigService {
const res = await this.configEntity.update({ configKey }, { configVal, status });
}
else {
const save = await this.configEntity.save({ configKey, configVal, status });
const save = await this.configEntity.save({
configKey,
configVal,
status,
});
}
}
catch (error) {
@ -307,8 +345,20 @@ let GlobalConfigService = class GlobalConfigService {
return await this.getConfigs(['copyrightUrl', 'copyrightTitle']);
}
async queryPayType() {
const { payHupiStatus = 0, payEpayStatus = 0, payWechatStatus = 0, payMpayStatus = 0, payLtzfStatus = 0, } = await this.getConfigs(['payHupiStatus', 'payEpayStatus', 'payMpayStatus', 'payWechatStatus', 'payLtzfStatus']);
if ([payHupiStatus, payEpayStatus, payWechatStatus, payMpayStatus, payLtzfStatus].every((status) => status === 0)) {
const { payHupiStatus = 0, payEpayStatus = 0, payWechatStatus = 0, payMpayStatus = 0, payLtzfStatus = 0, } = await this.getConfigs([
'payHupiStatus',
'payEpayStatus',
'payMpayStatus',
'payWechatStatus',
'payLtzfStatus',
]);
if ([
payHupiStatus,
payEpayStatus,
payWechatStatus,
payMpayStatus,
payLtzfStatus,
].every((status) => status === 0)) {
throw new common_1.HttpException('支付功能暂未开放!', common_1.HttpStatus.BAD_REQUEST);
}
if (Number(payWechatStatus) === 1) {
@ -338,7 +388,7 @@ let GlobalConfigService = class GlobalConfigService {
return { siteName, qqNumber, vxNumber, registerBaseUrl, domain };
}
async getPhoneVerifyConfig() {
const { phoneRegisterStatus, aliPhoneAccessKeyId, aliPhoneAccessKeySecret, aliPhoneSignName, aliPhoneTemplateCode } = await this.getConfigs([
const { phoneRegisterStatus, aliPhoneAccessKeyId, aliPhoneAccessKeySecret, aliPhoneSignName, aliPhoneTemplateCode, } = await this.getConfigs([
'phoneRegisterStatus',
'aliPhoneAccessKeyId',
'aliPhoneAccessKeySecret',
@ -359,7 +409,12 @@ let GlobalConfigService = class GlobalConfigService {
return process.env.NAMESPACE || 'AIWeb';
}
async getSignatureGiftConfig() {
const { signInStatus = 0, signInModel3Count = 0, signInModel4Count = 0, signInMjDrawToken = 0, } = await this.getConfigs(['signInStatus', 'signInModel3Count', 'signInModel4Count', 'signInMjDrawToken']);
const { signInStatus = 0, signInModel3Count = 0, signInModel4Count = 0, signInMjDrawToken = 0, } = await this.getConfigs([
'signInStatus',
'signInModel3Count',
'signInModel4Count',
'signInMjDrawToken',
]);
if (Number(signInStatus) !== 1) {
throw new common_1.HttpException('签到功能暂未开放!', common_1.HttpStatus.BAD_REQUEST);
}
@ -374,18 +429,10 @@ let GlobalConfigService = class GlobalConfigService {
const response = await fetch(api, {});
const responseData = await response.json();
const { success = true, message } = responseData;
common_1.Logger.error('请按要求填写正确的授权信息');
common_1.Logger.error('请填写您的授权码');
common_1.Logger.error('缺失ip信息');
common_1.Logger.error('缺失ip信息');
common_1.Logger.debug('感谢您使用NineAi、祝您使用愉快~');
common_1.Logger.debug('感谢您使用AIWeb祝您使用愉快~');
}
async getSensitiveConfig() {
const { baiduTextStatus = 0, baiduTextAccessToken, nineaiBuiltInSensitiveAuthKey, } = await this.getConfigs([
'baiduTextStatus',
'baiduTextAccessToken',
'nineaiBuiltInSensitiveAuthKey',
]);
const { baiduTextStatus = 0, baiduTextAccessToken } = await this.getConfigs(['baiduTextStatus', 'baiduTextAccessToken']);
if (Number(baiduTextStatus) === 1) {
return {
useType: 'baidu',

View File

@ -1,16 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KnowledgeBaseController = void 0;
const common_1 = require("@nestjs/common");
let KnowledgeBaseController = class KnowledgeBaseController {
};
KnowledgeBaseController = __decorate([
(0, common_1.Controller)('knowledgeBase')
], KnowledgeBaseController);
exports.KnowledgeBaseController = KnowledgeBaseController;

View File

@ -1,17 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KnowledgeBaseEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
let KnowledgeBaseEntity = class KnowledgeBaseEntity extends baseEntity_1.BaseEntity {
};
KnowledgeBaseEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'knowledge_base' })
], KnowledgeBaseEntity);
exports.KnowledgeBaseEntity = KnowledgeBaseEntity;

View File

@ -1,26 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KnowledgeBaseModule = void 0;
const common_1 = require("@nestjs/common");
const knowledgeBase_controller_1 = require("./knowledgeBase.controller");
const knowledgeBase_service_1 = require("./knowledgeBase.service");
const typeorm_1 = require("@nestjs/typeorm");
const knowledgeBase_entity_1 = require("./knowledgeBase.entity");
let KnowledgeBaseModule = class KnowledgeBaseModule {
};
KnowledgeBaseModule = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({
imports: [typeorm_1.TypeOrmModule.forFeature([knowledgeBase_entity_1.KnowledgeBaseEntity])],
providers: [knowledgeBase_service_1.KnowledgeBaseService],
controllers: [knowledgeBase_controller_1.KnowledgeBaseController],
exports: [knowledgeBase_service_1.KnowledgeBaseService],
})
], KnowledgeBaseModule);
exports.KnowledgeBaseModule = KnowledgeBaseModule;

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MjDrawDto = void 0;
const class_validator_1 = require("class-validator");
const swagger_1 = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class MjDrawDto {
}
__decorate([
@ -24,17 +24,26 @@ __decorate([
__metadata("design:type", String)
], MjDrawDto.prototype, "prompt", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: '--ar 16:9 --c 0', description: '除了prompt的额外参数' }),
(0, swagger_1.ApiProperty)({
example: '--ar 16:9 --c 0',
description: '除了prompt的额外参数',
}),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], MjDrawDto.prototype, "extraParam", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'https://xsdasdasd.com', description: '垫图图片地址' }),
(0, swagger_1.ApiProperty)({
example: 'https://xsdasdasd.com',
description: '垫图图片地址',
}),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], MjDrawDto.prototype, "imgUrl", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'IMAGINE', description: '任务类型,可用值:IMAGINE,UPSCALE,VARIATION,ZOOM,PAN,DESCRIBE,BLEND,SHORTEN,SWAP_FACE' }),
(0, swagger_1.ApiProperty)({
example: 'IMAGINE',
description: '任务类型,可用值:IMAGINE,UPSCALE,VARIATION,ZOOM,PAN,DESCRIBE,BLEND,SHORTEN,SWAP_FACE',
}),
(0, class_validator_1.IsOptional)(),
__metadata("design:type", String)
], MjDrawDto.prototype, "action", void 0);

View File

@ -13,14 +13,15 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MidjourneyController = void 0;
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
const midjourney_service_1 = require("./midjourney.service");
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 axios_1 = require("axios");
const getList_dto_1 = require("./dto/getList.dto");
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
const mjDraw_dto_1 = require("./dto/mjDraw.dto");
const midjourney_service_1 = require("./midjourney.service");
let MidjourneyController = class MidjourneyController {
constructor(midjourneyService) {
this.midjourneyService = midjourneyService;
@ -64,6 +65,9 @@ let MidjourneyController = class MidjourneyController {
async proxyImg(params) {
return await this.midjourneyService.proxyImg(params);
}
async mjDraw(body, req) {
return await this.midjourneyService.addMjDrawQueue(body, req);
}
};
__decorate([
(0, common_1.Get)('drawList'),
@ -182,6 +186,17 @@ __decorate([
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], MidjourneyController.prototype, "proxyImg", null);
__decorate([
(0, common_1.Post)('addMjDrawQueue'),
(0, swagger_1.ApiOperation)({ summary: '提交绘制图片任务' }),
(0, common_1.UseGuards)(jwtAuth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [mjDraw_dto_1.MjDrawDto, Object]),
__metadata("design:returntype", Promise)
], MidjourneyController.prototype, "mjDraw", null);
MidjourneyController = __decorate([
(0, common_1.Controller)('midjourney'),
__metadata("design:paramtypes", [midjourney_service_1.MidjourneyService])

View File

@ -7,20 +7,38 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MidjourneyModule = void 0;
const bull_1 = require("@nestjs/bull");
const common_1 = require("@nestjs/common");
const midjourney_controller_1 = require("./midjourney.controller");
const midjourney_service_1 = require("./midjourney.service");
const typeorm_1 = require("@nestjs/typeorm");
const midjourney_entity_1 = require("./midjourney.entity");
const user_entity_1 = require("../user/user.entity");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const user_entity_1 = require("../user/user.entity");
const midjourney_controller_1 = require("./midjourney.controller");
const midjourney_entity_1 = require("./midjourney.entity");
const midjourney_service_1 = require("./midjourney.service");
const prompt_entity_1 = require("./prompt.entity");
let MidjourneyModule = class MidjourneyModule {
};
MidjourneyModule = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({
imports: [typeorm_1.TypeOrmModule.forFeature([midjourney_entity_1.MidjourneyEntity, user_entity_1.UserEntity, prompt_entity_1.mjPromptEntity])],
imports: [
bull_1.BullModule.registerQueueAsync({
name: 'MJDRAW',
useFactory: () => {
const config = {
port: +process.env.REDIS_PORT,
host: process.env.REDIS_HOST,
db: Number(process.env.REDIS_DB || 0),
};
process.env.REDIS_PASSWORD &&
(config.password = process.env.REDIS_PASSWORD);
return {
redis: config,
};
},
}),
typeorm_1.TypeOrmModule.forFeature([midjourney_entity_1.MidjourneyEntity, user_entity_1.UserEntity, prompt_entity_1.mjPromptEntity]),
],
controllers: [midjourney_controller_1.MidjourneyController],
providers: [midjourney_service_1.MidjourneyService, redisCache_service_1.RedisCacheService],
exports: [midjourney_service_1.MidjourneyService],

View File

@ -25,12 +25,13 @@ const user_entity_1 = require("./../user/user.entity");
const midjourney_entity_1 = require("./midjourney.entity");
const utils_1 = require("../../common/utils");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const bull_1 = require("@nestjs/bull");
const image_size_1 = require("image-size");
const uuid = require("uuid");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const prompt_entity_1 = require("./prompt.entity");
let MidjourneyService = class MidjourneyService {
constructor(midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, userBalanceService, redisCacheService, modelsService) {
constructor(mjDrawQueue, midjourneyEntity, userEntity, mjPromptsEntity, globalConfigService, uploadService, userBalanceService, redisCacheService, modelsService) {
this.mjDrawQueue = mjDrawQueue;
this.midjourneyEntity = midjourneyEntity;
this.userEntity = userEntity;
this.mjPromptsEntity = mjPromptsEntity;
@ -41,12 +42,59 @@ let MidjourneyService = class MidjourneyService {
this.modelsService = modelsService;
this.lockPrompt = [];
}
async onApplicationBootstrap() {
await this.mjDrawQueue.clean(0, 'active');
await this.cleanQueue();
}
async addMjDrawQueue(body, req) {
const { prompt = '', imgUrl = '', base64 = '', extraParam = '', drawId = null, action = '', orderId = null, customId = '', } = body;
await this.checkLimit(req);
const modelInfo = await this.modelsService.getCurrentModelKeyInfo('midjourney');
const { deduct, deductType, proxyUrl, timeout } = modelInfo;
await this.userBalanceService.validateBalance(req, deductType, action === 'UPSCALE' ? deduct : deduct * 4);
const params = Object.assign(Object.assign({}, body), { userId: req.user.id });
const drawInfo = await this.addDrawQueue(params);
if (action === 'IMAGINE') {
this.sendDrawCommand(drawInfo, modelInfo)
.then((result) => this.pollComparisonResultDraw(result, modelInfo))
.then((drawRes) => {
console.log('drawRes', drawRes);
return this.updateDrawData(drawInfo, drawRes);
})
.catch((error) => {
common_1.Logger.error('Error in IMAGINE draw operation:', error);
});
}
else {
let resultPromise;
if (action === 'MODAL') {
resultPromise = this.getDrawActionDetail(action, drawId, customId).then((res) => res.drawId);
}
else {
resultPromise = this.sendDrawCommand(drawInfo, modelInfo);
}
resultPromise
.then((result) => this.pollComparisonResultDraw(result, modelInfo))
.then((drawRes) => {
console.log('drawRes', drawRes);
return this.updateDrawData(drawInfo, drawRes);
})
.catch((error) => {
common_1.Logger.error('Error in other draw operation:', error);
});
}
common_1.Logger.log(`执行预扣费,扣除费用:${action === 'UPSCALE' ? deduct : deduct * 4}积分。`);
await this.userBalanceService.deductFromBalance(req.user.id, deductType, action === 'UPSCALE' ? deduct : deduct * 4);
return true;
}
async sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async getImageSizeFromUrl(imageUrl) {
try {
const response = await axios_1.default.get(imageUrl, { responseType: 'arraybuffer' });
const response = await axios_1.default.get(imageUrl, {
responseType: 'arraybuffer',
});
const buffer = Buffer.from(response.data, 'binary');
const dimensions = (0, image_size_1.default)(buffer);
return { width: dimensions.width, height: dimensions.height };
@ -56,34 +104,12 @@ let MidjourneyService = class MidjourneyService {
throw error;
}
}
async draw(jobData, jobId) {
const { id, action, base64, userId } = jobData;
const drawInfo = await this.midjourneyEntity.findOne({ where: { id } });
const modelInfo = await this.modelsService.getSpecialModelKeyInfo('midjourney');
const { deduct, isTokenBased, tokenFeeRatio, deductType, key, modelName, id: keyId, maxRounds, proxyUrl, maxModelTokens, timeout, model: useModel } = modelInfo;
try {
await this.bindJobId(id, jobId);
await this.updateDrawStatus(id, midjourney_constant_1.MidjourneyStatusEnum.DRAWING);
const result = await this.sendDrawCommand(drawInfo, action, modelInfo, base64);
drawInfo.drawId = result;
const drawRes = await this.pollComparisonResultDraw(id, modelInfo, drawInfo);
await this.updateDrawData(jobData, drawRes);
const amount = action === "UPSCALE" ? deduct : deduct * 4;
common_1.Logger.log(`绘画完成,执行扣费,扣除费用:${amount}积分。`);
await this.userBalanceService.deductFromBalance(userId, deductType, amount);
await this.midjourneyEntity.update({ id }, { status: 3 });
return true;
}
catch (error) {
await this.midjourneyEntity.update({ id }, { status: 4 });
console.log('error: ', error);
return true;
}
}
async addDrawQueue(params) {
try {
const { prompt, imgUrl = '', extraParam = '', action, userId, customId, drawId } = params;
const fullPrompt = imgUrl ? `${imgUrl} ${prompt} ${extraParam}` : `${prompt} ${extraParam}`;
const { prompt, imgUrl = '', extraParam = '', action, userId, customId, drawId, } = params;
const fullPrompt = imgUrl
? `${imgUrl} ${prompt} ${extraParam}`
: `${prompt} ${extraParam}`;
const drawInfo = {
userId,
drawId,
@ -110,7 +136,7 @@ let MidjourneyService = class MidjourneyService {
try {
const { id, imageUrl, action, submitTime, finishTime, progress } = drawRes;
const durationSpent = finishTime - submitTime;
const { mjNotSaveImg, mjProxyImgUrl, mjNotUseProxy, } = await this.globalConfigService.getConfigs([
const { mjNotSaveImg, mjProxyImgUrl, mjNotUseProxy } = await this.globalConfigService.getConfigs([
'mjNotSaveImg',
'mjProxyImgUrl',
'mjNotUseProxy',
@ -134,13 +160,28 @@ let MidjourneyService = class MidjourneyService {
if (mjNotSaveImg !== '1') {
try {
common_1.Logger.debug(`------> 开始上传图片!!!`);
const filename = `${Date.now()}-${uuid.v4().slice(0, 4)}.png`;
processedUrl = await this.uploadService.uploadFileFromUrl({ filename, url: processedUrl });
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.debug(`------> 上传图片的URL: ${processedUrl}`);
if (!processedUrl) {
throw new Error('processedUrl is undefined or empty');
}
processedUrl = await this.uploadService.uploadFileFromUrl({
url: processedUrl,
dir: `midjourney/${currentDate}`,
});
logMessage = `上传成功 URL: ${processedUrl}`;
common_1.Logger.debug(logMessage);
}
catch (uploadError) {
common_1.Logger.error('存储图片失败,使用原始/代理图片链接');
common_1.Logger.error(uploadError.message);
common_1.Logger.error(uploadError.stack);
logMessage = `存储图片失败,使用原始/代理图片链接 ${processedUrl}`;
common_1.Logger.debug(logMessage);
}
common_1.Logger.log(logMessage, 'MidjourneyService');
}
@ -166,15 +207,15 @@ let MidjourneyService = class MidjourneyService {
throw new common_1.HttpException('更新绘画数据失败', common_1.HttpStatus.BAD_REQUEST);
}
}
async sendDrawCommand(drawInfo, action, modelInfo, base64) {
const { openaiBaseUrl, openaiBaseKey, } = await this.globalConfigService.getConfigs([
async sendDrawCommand(drawInfo, modelInfo) {
const { openaiBaseUrl, openaiBaseKey } = await this.globalConfigService.getConfigs([
'openaiBaseUrl',
'openaiBaseKey',
]);
const { key, proxyUrl } = modelInfo;
const mjProxyUrl = proxyUrl || openaiBaseUrl;
const mjKey = key || openaiBaseKey;
const { id, fullPrompt, imgUrl, drawId, customId } = drawInfo;
const { id, fullPrompt, imgUrl, drawId, customId, action, base64 } = drawInfo;
const prompt = imgUrl ? `${imgUrl} ${fullPrompt}` : `${fullPrompt}`;
let url = '';
let payloadJson = {};
@ -215,9 +256,9 @@ let MidjourneyService = class MidjourneyService {
}
}
}
async pollComparisonResultDraw(id, modelInfo, drawInfo) {
const { key, proxyUrl, timeout } = modelInfo;
const { openaiTimeout, openaiBaseUrl, openaiBaseKey, } = await this.globalConfigService.getConfigs([
async pollComparisonResultDraw(drawId, modelInfo) {
const { key, proxyUrl, timeout, id } = modelInfo;
const { openaiTimeout, openaiBaseUrl, openaiBaseKey } = await this.globalConfigService.getConfigs([
'openaiTimeout',
'openaiBaseUrl',
'openaiBaseKey',
@ -231,15 +272,14 @@ let MidjourneyService = class MidjourneyService {
let pollingCount = 0;
let retryCount = 0;
const MAX_RETRIES = 5;
const { drawId } = drawInfo;
try {
while (Date.now() - startTime < TIMEOUT && retryCount < MAX_RETRIES) {
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
common_1.Logger.log(`【绘制图片】第 ${pollingCount + 1} 次开始查询, 使用 drawId: ${drawId}`, 'MidjourneyService');
try {
const headers = {
"Content-Type": "application/x-www-form-urlencoded",
"mj-api-secret": mjKey
'Content-Type': 'application/x-www-form-urlencoded',
'mj-api-secret': mjKey,
};
const url = `${mjProxyUrl}/mj/task/${drawId}/fetch`;
const res = await axios_1.default.get(url, { headers });
@ -283,10 +323,31 @@ let MidjourneyService = class MidjourneyService {
order: { id: 'DESC' },
take: size,
skip: (page - 1) * size,
select: ['id', 'userId', 'prompt', 'extraParam', 'fullPrompt', 'rec', 'orderId', 'drawId', 'drawUrl', 'drawRatio', 'isDelete', 'status', 'action', 'extend']
select: [
'id',
'userId',
'prompt',
'extraParam',
'fullPrompt',
'rec',
'orderId',
'drawId',
'drawUrl',
'drawRatio',
'isDelete',
'status',
'action',
'extend',
],
});
const countQueue = await this.midjourneyEntity.count({ where: { isDelete: 0, status: (0, typeorm_2.In)([1, 2]) } });
const data = { rows: (0, utils_1.formatCreateOrUpdateDate)(rows), count, countQueue };
const countQueue = await this.midjourneyEntity.count({
where: { isDelete: 0, status: (0, typeorm_2.In)([1, 2]) },
});
const data = {
rows: (0, utils_1.formatCreateOrUpdateDate)(rows),
count,
countQueue,
};
return data;
}
catch (error) {
@ -295,11 +356,11 @@ let MidjourneyService = class MidjourneyService {
}
async getDrawActionDetail(action, drawId, customId) {
const modelInfo = await this.modelsService.getSpecialModelKeyInfo('midjourney');
const { openaiBaseUrl, openaiBaseKey, } = await this.globalConfigService.getConfigs([
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 { deduct, isTokenBased, tokenFeeRatio, deductType, key, modelName, id: keyId, maxRounds, proxyUrl, maxModelTokens, timeout, model: useModel, } = modelInfo;
const mjProxyUrl = proxyUrl;
const mjKey = key || openaiBaseKey;
const headers = { 'mj-api-secret': mjKey || openaiBaseUrl };
@ -314,7 +375,9 @@ let MidjourneyService = class MidjourneyService {
return { drawId: resultId };
}
async deleteDraw(id, req) {
const d = await this.midjourneyEntity.findOne({ where: { id, userId: req.user.id, isDelete: 0 } });
const d = await this.midjourneyEntity.findOne({
where: { id, userId: req.user.id, isDelete: 0 },
});
if (!d) {
throw new common_1.HttpException('当前图片不存在!', common_1.HttpStatus.BAD_REQUEST);
}
@ -331,8 +394,12 @@ let MidjourneyService = class MidjourneyService {
}
async checkLimit(req) {
const { role, id } = req.user;
const count = await this.midjourneyEntity.count({ where: { userId: id, isDelete: 0, status: (0, typeorm_2.In)([1, 2]) } });
const mjLimitCount = await this.globalConfigService.getConfigs(['mjLimitCount']);
const count = await this.midjourneyEntity.count({
where: { userId: id, isDelete: 0, status: (0, typeorm_2.In)([1, 2]) },
});
const mjLimitCount = await this.globalConfigService.getConfigs([
'mjLimitCount',
]);
const max = mjLimitCount ? Number(mjLimitCount) : 2;
if (count >= max) {
throw new common_1.HttpException(`当前管理员限制单用户同时最多能执行${max}个任务`, common_1.HttpStatus.BAD_REQUEST);
@ -342,17 +409,12 @@ let MidjourneyService = class MidjourneyService {
const { id, userId, action } = jobData;
await this.midjourneyEntity.update({ id }, { status: 4 });
}
async drawSuccess(jobData) {
const { id, userId, action } = jobData;
const amount = action === "UPSCALE" ? 1 : 4;
common_1.Logger.debug(`绘画完成,执行扣费,扣除费用:${amount}积分。`);
await this.userBalanceService.deductFromBalance(userId, 3, 3);
await this.midjourneyEntity.update({ id }, { status: 3 });
}
async getList(params) {
const { page = 1, size = 20, rec, userId, status } = params;
if (Number(size) === 999) {
const cache = await this.redisCacheService.get({ key: 'midjourney:getList' });
const cache = await this.redisCacheService.get({
key: 'midjourney:getList',
});
if (cache) {
try {
return JSON.parse(cache);
@ -371,13 +433,37 @@ let MidjourneyService = class MidjourneyService {
order: { id: 'DESC' },
take: size,
skip: (page - 1) * size,
select: ['id', 'drawId', 'drawUrl', 'drawRatio', 'prompt', 'fullPrompt', 'rec', 'createdAt', 'action', 'status', 'extend'],
select: [
'id',
'drawId',
'drawUrl',
'drawRatio',
'prompt',
'fullPrompt',
'rec',
'createdAt',
'action',
'status',
'extend',
],
});
if (Number(size) === 999) {
const data = {
rows: rows.map((item) => {
const { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status, extend } = item;
return { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status, extend };
const { id, drawId, drawUrl, drawRatio, prompt, fullPrompt, createdAt, rec, action, status, extend, } = item;
return {
id,
drawId,
drawUrl,
drawRatio,
prompt,
fullPrompt,
createdAt,
rec,
action,
status,
extend,
};
}),
count,
};
@ -407,8 +493,13 @@ let MidjourneyService = class MidjourneyService {
take: size,
skip: (page - 1) * size,
});
const userIds = rows.map((item) => item.userId).filter(id => id < 100000);
const userInfos = await this.userEntity.find({ where: { id: (0, typeorm_2.In)(userIds) }, select: ['id', 'username', 'avatar', 'email'] });
const userIds = rows
.map((item) => item.userId)
.filter((id) => id < 100000);
const userInfos = await this.userEntity.find({
where: { id: (0, typeorm_2.In)(userIds) },
select: ['id', 'username', 'avatar', 'email'],
});
rows.forEach((item) => {
item.userInfo = userInfos.find((user) => user.id === item.userId);
});
@ -427,7 +518,9 @@ let MidjourneyService = class MidjourneyService {
}
async recDraw(params) {
const { id } = params;
const draw = await this.midjourneyEntity.findOne({ where: { id, status: 3, isDelete: 0 } });
const draw = await this.midjourneyEntity.findOne({
where: { id, status: 3, isDelete: 0 },
});
if (!draw) {
throw new common_1.HttpException('当前图片不存在!', common_1.HttpStatus.BAD_REQUEST);
}
@ -465,7 +558,14 @@ let MidjourneyService = class MidjourneyService {
return await this.mjPromptsEntity.update({ id }, { prompt, status, isCarryParams, order, aspect });
}
else {
return await this.mjPromptsEntity.save({ prompt, status, isCarryParams, title, order, aspect });
return await this.mjPromptsEntity.save({
prompt,
status,
isCarryParams,
title,
order,
aspect,
});
}
}
catch (error) {
@ -495,10 +595,11 @@ let MidjourneyService = class MidjourneyService {
};
MidjourneyService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(midjourney_entity_1.MidjourneyEntity)),
__param(1, (0, typeorm_1.InjectRepository)(user_entity_1.UserEntity)),
__param(2, (0, typeorm_1.InjectRepository)(prompt_entity_1.mjPromptEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository,
__param(0, (0, bull_1.InjectQueue)('MJDRAW')),
__param(1, (0, typeorm_1.InjectRepository)(midjourney_entity_1.MidjourneyEntity)),
__param(2, (0, typeorm_1.InjectRepository)(user_entity_1.UserEntity)),
__param(3, (0, typeorm_1.InjectRepository)(prompt_entity_1.mjPromptEntity)),
__metadata("design:paramtypes", [Object, typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
globalConfig_service_1.GlobalConfigService,

View File

@ -30,17 +30,21 @@ __decorate([
__metadata("design:type", Object)
], SetModelDto.prototype, "key", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '是否开启当前key对应的模型', required: true }),
(0, swagger_1.ApiProperty)({
example: true,
description: '是否开启当前key对应的模型',
required: true,
}),
__metadata("design:type", Boolean)
], SetModelDto.prototype, "status", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 'gpt-3.5', description: '当前key绑定的模型是多少 需要调用的模型', required: true }),
(0, swagger_1.ApiProperty)({
example: 'gpt-3.5',
description: '当前key绑定的模型是多少 需要调用的模型',
required: true,
}),
__metadata("design:type", String)
], SetModelDto.prototype, "model", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: 'key的权重' }),
__metadata("design:type", Number)
], SetModelDto.prototype, "keyWeight", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 1, description: '模型排序' }),
__metadata("design:type", Number)
@ -50,11 +54,19 @@ __decorate([
__metadata("design:type", String)
], SetModelDto.prototype, "modelAvatar", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: 4096, description: '模型支持的最大TOken数量', required: false }),
(0, swagger_1.ApiProperty)({
example: 4096,
description: '模型支持的最大TOken数量',
required: false,
}),
__metadata("design:type", Number)
], SetModelDto.prototype, "maxModelTokens", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '模型的代理地址', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '模型的代理地址',
required: false,
}),
__metadata("design:type", String)
], SetModelDto.prototype, "proxyUrl", void 0);
__decorate([
@ -66,7 +78,11 @@ __decorate([
__metadata("design:type", Number)
], SetModelDto.prototype, "keyStatus", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '扣费类型 1 普通 2 高级余额', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '扣费类型 1 普通 2 高级余额',
required: false,
}),
__metadata("design:type", Number)
], SetModelDto.prototype, "deductType", void 0);
__decorate([
@ -74,19 +90,35 @@ __decorate([
__metadata("design:type", Number)
], SetModelDto.prototype, "deduct", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '最大上下文轮次', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '最大上下文轮次',
required: false,
}),
__metadata("design:type", Number)
], SetModelDto.prototype, "maxRounds", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '是否设置为绘画Key', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '是否设置为绘画Key',
required: false,
}),
__metadata("design:type", Boolean)
], SetModelDto.prototype, "isDraw", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '是否支持文件上传', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '是否支持文件上传',
required: false,
}),
__metadata("design:type", Number)
], SetModelDto.prototype, "isFileUpload", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ example: true, description: '是否使用token计费', required: false }),
(0, swagger_1.ApiProperty)({
example: true,
description: '是否使用token计费',
required: false,
}),
__metadata("design:type", Boolean)
], SetModelDto.prototype, "isTokenBased", void 0);
__decorate([

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelsEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
const typeorm_1 = require("typeorm");
let ModelsEntity = class ModelsEntity extends baseEntity_1.BaseEntity {
};
__decorate([
@ -27,7 +27,7 @@ __decorate([
__metadata("design:type", String)
], ModelsEntity.prototype, "model", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '模型头像', nullable: true }),
(0, typeorm_1.Column)({ length: 1024, comment: '模型头像', nullable: true }),
__metadata("design:type", String)
], ModelsEntity.prototype, "modelAvatar", void 0);
__decorate([
@ -35,7 +35,11 @@ __decorate([
__metadata("design:type", Number)
], ModelsEntity.prototype, "modelOrder", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '模型上下文支持的最大Token', default: 2000, nullable: true }),
(0, typeorm_1.Column)({
comment: '模型上下文支持的最大Token',
default: 2000,
nullable: true,
}),
__metadata("design:type", Number)
], ModelsEntity.prototype, "maxModelTokens", void 0);
__decorate([
@ -59,7 +63,10 @@ __decorate([
__metadata("design:type", Boolean)
], ModelsEntity.prototype, "isTokenBased", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '是否支持文件上传: 0:不是 1: 附件链接格式 2: 4V格式', default: 0 }),
(0, typeorm_1.Column)({
comment: '是否支持文件上传: 0:不是 1: 附件链接格式 2: 4V格式',
default: 0,
}),
__metadata("design:type", Number)
], ModelsEntity.prototype, "isFileUpload", void 0);
__decorate([
@ -79,13 +86,12 @@ __decorate([
__metadata("design:type", Boolean)
], ModelsEntity.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'key的状态: 1:有效 -1:被封号 -2: 错误的秘钥 -3: 余额使用完了', default: 1 }),
(0, typeorm_1.Column)({
comment: 'key的状态: 1:有效 -1:被封号 -2: 错误的秘钥 -3: 余额使用完了',
default: 1,
}),
__metadata("design:type", Number)
], ModelsEntity.prototype, "keyStatus", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'key权重', default: 1 }),
__metadata("design:type", Number)
], ModelsEntity.prototype, "keyWeight", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: 'key的使用次数', default: 0 }),
__metadata("design:type", Number)
@ -102,6 +108,10 @@ __decorate([
(0, typeorm_1.Column)({ comment: '模型频率限制 次/小时', default: 999 }),
__metadata("design:type", Number)
], ModelsEntity.prototype, "modelLimits", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '模型介绍', nullable: true }),
__metadata("design:type", String)
], ModelsEntity.prototype, "modelDescription", void 0);
ModelsEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'models' })
], ModelsEntity);

View File

@ -47,18 +47,16 @@ let ModelsService = class ModelsService {
}
return pre;
}, {});
this.modelTypes = Object.keys(keyTypes).map(keyType => {
this.modelTypes = Object.keys(keyTypes).map((keyType) => {
return { label: status_constant_1.ModelsMapCn[keyType], val: keyType };
});
this.modelMaps = keyTypes;
this.keyList = {};
allKeys.forEach(keyDetail => {
const { keyType, model, keyWeight } = keyDetail;
allKeys.forEach((keyDetail) => {
const { keyType, model } = keyDetail;
if (!this.keyPoolMap[model])
this.keyPoolMap[model] = [];
for (let index = 0; index < keyWeight; index++) {
this.keyPoolMap[model].push(keyDetail);
}
this.keyPoolMap[model].push(keyDetail);
if (!this.keyPoolIndexMap[model])
this.keyPoolIndexMap[model] = 0;
if (!this.keyList[keyType])
@ -74,7 +72,9 @@ let ModelsService = class ModelsService {
this.initCalcKey();
}
async getCurrentModelKeyInfo(model) {
const modelKeyInfo = await this.modelsEntity.findOne({ where: { model: model } });
const modelKeyInfo = await this.modelsEntity.findOne({
where: { model: model },
});
if (!modelKeyInfo) {
throw new common_1.HttpException('当前调用模型的key未找到请重新选择模型', common_1.HttpStatus.BAD_REQUEST);
}
@ -82,7 +82,7 @@ let ModelsService = class ModelsService {
}
async getSpecialModelKeyInfo(modelPrefix) {
const matchingModels = await this.modelsEntity.find({
where: { model: (0, typeorm_2.Like)(`${modelPrefix}%`) }
where: { model: (0, typeorm_2.Like)(`${modelPrefix}%`) },
});
if (matchingModels.length === 0) {
throw new common_1.HttpException('未找到匹配的模型,请重新选择模型!', common_1.HttpStatus.BAD_REQUEST);
@ -95,9 +95,18 @@ let ModelsService = class ModelsService {
async getBaseConfig(appId) {
if (!this.modelTypes.length || !Object.keys(this.modelMaps).length)
return;
const { keyType, modelName, model, deductType, deduct, isFileUpload } = this.modelMaps[1][0];
const { keyType, modelName, model, deductType, deduct, isFileUpload, modelAvatar, modelDescription, } = this.modelMaps[1][0];
return {
modelInfo: { keyType, modelName, model, deductType, deduct, isFileUpload }
modelInfo: {
keyType,
modelName,
model,
deductType,
deduct,
isFileUpload,
modelAvatar,
modelDescription,
},
};
}
async setModel(params) {
@ -120,7 +129,7 @@ let ModelsService = class ModelsService {
return res;
}
else {
const data = key.map(k => {
const data = key.map((k) => {
try {
const data = JSON.parse(JSON.stringify(params));
data.key = k;
@ -166,13 +175,13 @@ let ModelsService = class ModelsService {
const [rows, count] = await this.modelsEntity.findAndCount({
where: where,
order: {
modelOrder: 'ASC'
modelOrder: 'ASC',
},
skip: (page - 1) * size,
take: size,
});
if (role !== 'super') {
rows.forEach(item => {
rows.forEach((item) => {
item.key && (item.key = (0, utils_1.hideString)(item.key));
});
}
@ -180,22 +189,37 @@ let ModelsService = class ModelsService {
}
async modelsList() {
const cloneModelMaps = JSON.parse(JSON.stringify(this.modelMaps));
Object.keys(cloneModelMaps).forEach(key => {
cloneModelMaps[key] = cloneModelMaps[key].sort((a, b) => a.modelOrder - b.modelOrder);
Object.keys(cloneModelMaps).forEach((key) => {
cloneModelMaps[key] = cloneModelMaps[key]
.filter((t) => t.keyStatus === 1)
.sort((a, b) => a.modelOrder - b.modelOrder);
cloneModelMaps[key] = Array.from(cloneModelMaps[key]
.map(t => {
const { modelName, keyType, model, deduct, deductType, maxRounds, modelAvatar, isFileUpload } = t;
return { modelName, keyType, model, deduct, deductType, maxRounds, modelAvatar, isFileUpload };
.map((t) => {
const { modelName, keyType, model, deduct, deductType, maxRounds, modelAvatar, isFileUpload, modelDescription, } = t;
return {
modelName,
keyType,
model,
deduct,
deductType,
maxRounds,
modelAvatar,
isFileUpload,
modelDescription,
};
})
.reduce((map, obj) => map.set(obj.modelName, obj), new Map()).values());
.reduce((map, obj) => map.set(obj.modelName, obj), new Map())
.values());
});
return {
modelTypeList: this.modelTypes,
modelMaps: cloneModelMaps
modelMaps: cloneModelMaps,
};
}
async getMjInfo() {
const modelInfo = await this.modelsEntity.findOne({ where: { model: "midjourney" } });
const modelInfo = await this.modelsEntity.findOne({
where: { model: 'midjourney' },
});
if (modelInfo) {
return {
modelName: modelInfo.modelName,
@ -212,7 +236,10 @@ let ModelsService = class ModelsService {
await this.modelsEntity
.createQueryBuilder()
.update(models_entity_1.ModelsEntity)
.set({ useCount: () => 'useCount + 1', useToken: () => `useToken + ${useToken}` })
.set({
useCount: () => 'useCount + 1',
useToken: () => `useToken + ${useToken}`,
})
.where('id = :id', { id })
.execute();
}

View File

@ -13,12 +13,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OfficialController = void 0;
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
const utils_1 = require("../../common/utils");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
const official_service_1 = require("./official.service");
const getQrCode_dto_1 = require("./dto/getQrCode.dto");
const getQrSceneStr_dto_1 = require("./dto/getQrSceneStr.dto");
const official_service_1 = require("./official.service");
let OfficialController = class OfficialController {
constructor(officialService) {
this.officialService = officialService;
@ -85,7 +86,8 @@ let OfficialController = class OfficialController {
if (process.env.ISDEV === 'TRUE')
return '';
const ticket = await this.officialService.getQRCodeTicket(query.sceneStr);
return `https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${encodeURIComponent(ticket)}`;
const Url = (0, utils_1.formatUrl)(process.env.weChatMpUrl || 'https://mp.weixin.qq.com');
return `${Url}/cgi-bin/showqrcode?ticket=${encodeURIComponent(ticket)}`;
}
async loginBySceneStr(req, body) {
return this.officialService.loginBySceneStr(req, body.sceneStr);

View File

@ -49,17 +49,24 @@ let OfficialService = class OfficialService {
return this.fetchQRCodeTicket(sceneStr);
}
async getRedirectUrl(url) {
const appId = await this.globalConfigService.getConfigs(['wechatOfficialAppId']);
const res = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${encodeURIComponent(url)}&response_type=code&scope=snsapi_base&state=weChatLogin#wechat_redirect`;
const appId = await this.globalConfigService.getConfigs([
'wechatOfficialAppId',
]);
const Url = (0, utils_1.formatUrl)(process.env.weChatOpenUrl || 'https://open.weixin.qq.com');
const res = `${Url}/connect/oauth2/authorize?appid=${appId}&redirect_uri=${encodeURIComponent(url)}&response_type=code&scope=snsapi_base&state=weChatLogin#wechat_redirect`;
console.log('回跳跳转地址: ', res);
return res;
}
async getJsapiTicket(url) {
const nonceStr = (0, utils_1.createRandomNonceStr)(32);
const timestamp = (Date.now() / 1000).toFixed(0);
const jsapiTicket = await this.globalConfigService.getConfigs(['wechatJsapiTicket']);
const jsapiTicket = await this.globalConfigService.getConfigs([
'wechatJsapiTicket',
]);
console.log('jsapiTicket: ', jsapiTicket);
const appId = await this.globalConfigService.getConfigs(['wechatOfficialAppId']);
const appId = await this.globalConfigService.getConfigs([
'wechatOfficialAppId',
]);
console.log('appId: ', appId);
const str = `jsapi_ticket=${jsapiTicket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`;
console.log('str: ', str);
@ -67,18 +74,29 @@ let OfficialService = class OfficialService {
return { appId, nonceStr, timestamp, signature };
}
async fetchQRCodeTicket(sceneStr) {
const accessToken = await this.globalConfigService.getConfigs(['wechatAccessToken']);
const params = { action_name: 'QR_STR_SCENE', action_info: { scene: { scene_str: sceneStr } } };
const res = await axios_1.default.post(`https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=${accessToken}`, params);
const accessToken = await this.globalConfigService.getConfigs([
'wechatAccessToken',
]);
const Url = (0, utils_1.formatUrl)(process.env.weChatApiUrl || 'https://api.weixin.qq.com');
const params = {
action_name: 'QR_STR_SCENE',
action_info: { scene: { scene_str: sceneStr } },
};
const res = await axios_1.default.post(`${Url}/cgi-bin/qrcode/create?access_token=${accessToken}`, params);
const { data: { errmsg, ticket }, } = res;
if (errmsg)
throw new common_1.HttpException(errmsg, common_1.HttpStatus.BAD_REQUEST);
return ticket;
}
async loginByCode(req, code) {
const appId = await this.globalConfigService.getConfigs(['wechatOfficialAppId']);
const secret = await this.globalConfigService.getConfigs(['wechatOfficialAppSecret']);
const res = await axios_1.default.get(`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${secret}&code=${code}&grant_type=authorization_code`);
const appId = await this.globalConfigService.getConfigs([
'wechatOfficialAppId',
]);
const secret = await this.globalConfigService.getConfigs([
'wechatOfficialAppSecret',
]);
const Url = (0, utils_1.formatUrl)(process.env.weChatApiUrl || 'https://api.weixin.qq.com');
const res = await axios_1.default.get(`${Url}/sns/oauth2/access_token?appid=${appId}&secret=${secret}&code=${code}&grant_type=authorization_code`);
const { data: { errmsg, openid }, } = res;
if (errmsg)
throw new common_1.HttpException(errmsg, common_1.HttpStatus.BAD_REQUEST);
@ -90,10 +108,21 @@ let OfficialService = class OfficialService {
return this.authService.loginByOpenId(user, req);
}
async scan(openID, sceneStr) {
if (!this.sceneStrMap[sceneStr])
throw new common_1.HttpException('非法参数', common_1.HttpStatus.BAD_REQUEST);
const user = await this.userService.getUserFromOpenId(openID, sceneStr);
this.scanedSceneStrMap[sceneStr] = user.id;
try {
common_1.Logger.log(`Scanning with openID: ${openID}, sceneStr: ${sceneStr}`);
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'}`);
this.scanedSceneStrMap[sceneStr] = user.id;
}
catch (error) {
common_1.Logger.error('Error in scan method:', error.message);
common_1.Logger.error('Stack trace:', error.stack);
throw new common_1.HttpException('处理扫码事件时发生错误', common_1.HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async loginBySceneStr(req, sceneStr) {
if (!this.sceneStrMap[sceneStr])
@ -123,8 +152,9 @@ let OfficialService = class OfficialService {
return res;
}
async verify(signature, nonce, timestamp) {
const token = (await this.globalConfigService.getConfigs(['wechatOfficialToken'])) || '';
return (await this.sha1([token, nonce, timestamp].sort().join(''))) == signature;
const token = (await this.globalConfigService.getConfigs(['wechatOfficialToken'])) ||
'';
return ((await this.sha1([token, nonce, timestamp].sort().join(''))) == signature);
}
sha1(data) {
return crypto.createHash('sha1').update(data).digest('hex');
@ -149,7 +179,8 @@ let OfficialService = class OfficialService {
reject(new Error('请求超时'));
}, 4800);
});
let question = (await this.globalConfigService.getConfigs(['officialAutoReplyText'])) || '由于公众号的回复限制、过长的问题我们可能无法回复、您可以前往我们的官方站点享受更加完善的服务、如果您有更多问题、欢迎像我提问!';
let question = (await this.globalConfigService.getConfigs(['officialAutoReplyText'])) ||
'由于公众号的回复限制、过长的问题我们可能无法回复、您可以前往我们的官方站点享受更加完善的服务、如果您有更多问题、欢迎像我提问!';
return question;
}
};

View File

@ -0,0 +1,80 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginController = void 0;
const superAuth_guard_1 = require("../../common/auth/superAuth.guard");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const plugin_service_1 = require("./plugin.service");
let PluginController = class PluginController {
constructor(pluginService) {
this.pluginService = pluginService;
}
pluginList(req) {
return this.pluginService.pluginList(req);
}
createPlugin(body) {
return this.pluginService.createPlugin(body);
}
updatePlugin(body) {
return this.pluginService.updatePlugin(body);
}
delPlugin(body) {
return this.pluginService.delPlugin(body);
}
};
__decorate([
(0, common_1.Get)('pluginList'),
(0, swagger_1.ApiOperation)({ summary: '获取Plugin' }),
__param(0, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PluginController.prototype, "pluginList", null);
__decorate([
(0, common_1.Post)('createPlugin'),
(0, swagger_1.ApiOperation)({ summary: '创建Plugin' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PluginController.prototype, "createPlugin", null);
__decorate([
(0, common_1.Post)('updatePlugin'),
(0, swagger_1.ApiOperation)({ summary: '修改插件' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PluginController.prototype, "updatePlugin", null);
__decorate([
(0, common_1.Post)('delPlugin'),
(0, swagger_1.ApiOperation)({ summary: '删除插件' }),
(0, common_1.UseGuards)(superAuth_guard_1.SuperAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PluginController.prototype, "delPlugin", null);
PluginController = __decorate([
(0, swagger_1.ApiTags)('Plugin'),
(0, common_1.Controller)('plugin'),
__metadata("design:paramtypes", [plugin_service_1.PluginService])
], PluginController);
exports.PluginController = PluginController;

View File

@ -9,40 +9,40 @@ 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.ChatBoxEntity = void 0;
const typeorm_1 = require("typeorm");
exports.PluginEntity = void 0;
const baseEntity_1 = require("../../common/entity/baseEntity");
let ChatBoxEntity = class ChatBoxEntity extends baseEntity_1.BaseEntity {
const typeorm_1 = require("typeorm");
let PluginEntity = class PluginEntity extends baseEntity_1.BaseEntity {
};
__decorate([
(0, typeorm_1.Column)({ comment: '分类ID' }),
__metadata("design:type", Number)
], ChatBoxEntity.prototype, "typeId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '应用ID', nullable: true }),
__metadata("design:type", Number)
], ChatBoxEntity.prototype, "appId", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '快速描述词', nullable: true, type: 'text' }),
(0, typeorm_1.Column)({ unique: true, comment: '插件名称' }),
__metadata("design:type", String)
], ChatBoxEntity.prototype, "prompt", void 0);
], PluginEntity.prototype, "name", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '标题名称' }),
(0, typeorm_1.Column)({ comment: '插件封面', nullable: true, type: 'text' }),
__metadata("design:type", String)
], ChatBoxEntity.prototype, "title", void 0);
], PluginEntity.prototype, "pluginImg", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '排序ID', default: 100 }),
(0, typeorm_1.Column)({ comment: '插件描述' }),
__metadata("design:type", String)
], PluginEntity.prototype, "description", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '插件是否启用 0禁用 1启用', default: 1 }),
__metadata("design:type", Number)
], ChatBoxEntity.prototype, "order", void 0);
], PluginEntity.prototype, "isEnabled", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '开启状态', default: true }),
__metadata("design:type", Boolean)
], ChatBoxEntity.prototype, "status", void 0);
(0, typeorm_1.Column)({ comment: '插件是否为系统插件 0否 1是', default: 0 }),
__metadata("design:type", Number)
], PluginEntity.prototype, "isSystemPlugin", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '跳转地址' }),
(0, typeorm_1.Column)({ comment: '调用参数', type: 'text' }),
__metadata("design:type", String)
], ChatBoxEntity.prototype, "url", void 0);
ChatBoxEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'chat_box' })
], ChatBoxEntity);
exports.ChatBoxEntity = ChatBoxEntity;
], PluginEntity.prototype, "parameters", void 0);
__decorate([
(0, typeorm_1.Column)({ comment: '排序值', default: 0 }),
__metadata("design:type", Number)
], PluginEntity.prototype, "sortOrder", void 0);
PluginEntity = __decorate([
(0, typeorm_1.Entity)({ name: 'plugin' })
], PluginEntity);
exports.PluginEntity = PluginEntity;

View File

@ -6,11 +6,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KnowledgeBaseService = void 0;
exports.PluginModule = void 0;
const common_1 = require("@nestjs/common");
let KnowledgeBaseService = class KnowledgeBaseService {
const typeorm_1 = require("@nestjs/typeorm");
const plugin_controller_1 = require("./plugin.controller");
const plugin_entity_1 = require("./plugin.entity");
const plugin_service_1 = require("./plugin.service");
let PluginModule = class PluginModule {
};
KnowledgeBaseService = __decorate([
(0, common_1.Injectable)()
], KnowledgeBaseService);
exports.KnowledgeBaseService = KnowledgeBaseService;
PluginModule = __decorate([
(0, common_1.Module)({
imports: [typeorm_1.TypeOrmModule.forFeature([plugin_entity_1.PluginEntity])],
controllers: [plugin_controller_1.PluginController],
providers: [plugin_service_1.PluginService],
})
], PluginModule);
exports.PluginModule = PluginModule;

103
dist/modules/plugin/plugin.service.js vendored Normal file
View File

@ -0,0 +1,103 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const plugin_entity_1 = require("./plugin.entity");
let PluginService = class PluginService {
constructor(PluginEntity) {
this.PluginEntity = PluginEntity;
}
async pluginList(query) {
const { page = 1, size = 1000 } = query;
const rows = await this.PluginEntity.find({
order: { sortOrder: 'ASC', id: 'DESC' },
skip: (page - 1) * size,
take: size,
});
return { rows, count: rows.length };
}
async createPlugin(body) {
const { name, pluginImg, description, isEnabled, isSystemPlugin, parameters, sortOrder, } = body;
const existingPlugin = await this.PluginEntity.findOne({
where: { name },
});
if (existingPlugin) {
throw new common_1.HttpException('该插件名称已存在!', common_1.HttpStatus.BAD_REQUEST);
}
const newPlugin = this.PluginEntity.create({
name,
pluginImg,
description,
isEnabled: isEnabled !== undefined ? isEnabled : 1,
isSystemPlugin: isSystemPlugin !== undefined ? isSystemPlugin : 0,
parameters,
sortOrder: sortOrder !== undefined ? sortOrder : 0,
});
return await this.PluginEntity.save(newPlugin);
}
async updatePlugin(body) {
const { id, name, pluginImg, description, isEnabled, isSystemPlugin, parameters, sortOrder, } = body;
const existingPlugin = await this.PluginEntity.findOne({
where: { id },
});
if (!existingPlugin) {
throw new common_1.HttpException('插件不存在!', common_1.HttpStatus.BAD_REQUEST);
}
const duplicatePlugin = await this.PluginEntity.findOne({
where: { name, id: (0, typeorm_2.Not)(id) },
});
if (duplicatePlugin) {
throw new common_1.HttpException('该插件名称已存在!', common_1.HttpStatus.BAD_REQUEST);
}
existingPlugin.name = name;
existingPlugin.pluginImg = pluginImg;
existingPlugin.description = description;
existingPlugin.isEnabled =
isEnabled !== undefined ? isEnabled : existingPlugin.isEnabled;
existingPlugin.isSystemPlugin =
isSystemPlugin !== undefined
? isSystemPlugin
: existingPlugin.isSystemPlugin;
existingPlugin.parameters = parameters;
existingPlugin.sortOrder =
sortOrder !== undefined ? sortOrder : existingPlugin.sortOrder;
await this.PluginEntity.save(existingPlugin);
return '修改插件信息成功';
}
async delPlugin(body) {
const { id } = body;
const existingPlugin = await this.PluginEntity.findOne({
where: { id },
});
if (!existingPlugin) {
throw new common_1.HttpException('该插件不存在!', common_1.HttpStatus.BAD_REQUEST);
}
const deleteResult = await this.PluginEntity.delete(id);
if (deleteResult.affected > 0) {
return '删除插件成功';
}
else {
throw new common_1.HttpException('删除插件失败!', common_1.HttpStatus.BAD_REQUEST);
}
}
};
PluginService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(plugin_entity_1.PluginEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository])
], PluginService);
exports.PluginService = PluginService;

View File

@ -1,55 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueController = void 0;
const queue_service_1 = require("./queue.service");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const mjDraw_dto_1 = require("./dto/mjDraw.dto");
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
let QueueController = class QueueController {
constructor(queueService) {
this.queueService = queueService;
}
async mjDraw(body, req) {
return await this.queueService.addMjDrawQueue(body, req);
}
async getQueue() {
return await this.queueService.getQueue();
}
};
__decorate([
(0, common_1.Post)('addMjDrawQueue'),
(0, swagger_1.ApiOperation)({ summary: '提交绘制图片任务' }),
(0, common_1.UseGuards)(jwtAuth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
__param(0, (0, common_1.Body)()),
__param(1, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [mjDraw_dto_1.MjDrawDto, Object]),
__metadata("design:returntype", Promise)
], QueueController.prototype, "mjDraw", null);
__decorate([
(0, common_1.Get)('getQueue'),
(0, swagger_1.ApiOperation)({ summary: '查询任务队列' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], QueueController.prototype, "getQueue", null);
QueueController = __decorate([
(0, swagger_1.ApiTags)('Queue'),
(0, common_1.Controller)('queue'),
__metadata("design:paramtypes", [queue_service_1.QueueService])
], QueueController);
exports.QueueController = QueueController;

View File

@ -1,38 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueModule = void 0;
const common_1 = require("@nestjs/common");
const queue_controller_1 = require("./queue.controller");
const queue_service_1 = require("./queue.service");
const bull_1 = require("@nestjs/bull");
const queue_process_1 = require("./queue.process");
let QueueModule = class QueueModule {
};
QueueModule = __decorate([
(0, common_1.Module)({
imports: [
bull_1.BullModule.registerQueueAsync({
name: 'MJDRAW',
useFactory: () => {
const config = {
port: +process.env.REDIS_PORT,
host: process.env.REDIS_HOST,
};
process.env.REDIS_PASSWORD && (config.password = process.env.REDIS_PASSWORD);
return {
redis: config,
};
},
}),
],
controllers: [queue_controller_1.QueueController],
providers: [queue_service_1.QueueService, queue_process_1.QueueProcessor],
})
], QueueModule);
exports.QueueModule = QueueModule;

View File

@ -1,119 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var QueueProcessor_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueProcessor = void 0;
const bull_1 = require("@nestjs/bull");
const common_1 = require("@nestjs/common");
const midjourney_service_1 = require("../midjourney/midjourney.service");
let QueueProcessor = QueueProcessor_1 = class QueueProcessor {
constructor(midjourneyService) {
this.midjourneyService = midjourneyService;
this.logger = new common_1.Logger(QueueProcessor_1.name);
}
async handleJob(job) {
const res = await this.midjourneyService.draw(job.data, job.id);
return res;
}
onQueueActive(job) {
}
onQueueError(error) {
console.log('队列发生错误', error);
}
onQueueProgress(job, progress) {
console.log('队列任务的一个回调用于通知当前进度', job.id, progress);
}
onQueueCompleted(job, result) {
}
onQueueFailed(job, err) {
common_1.Logger.error(`Queue failed: ${err.message}: 绘画失败 ${job.id}`, 'QueueProcessor');
this.midjourneyService.drawFailed(job.data);
}
onQueuePaused() {
console.log('队列暂停的时候调用');
}
onQueueResumed() {
console.log('队列恢复的时候调用');
}
onQueueCleaned(jobs, type) {
common_1.Logger.log(`Queue cleaned: ${jobs.length} jobs of type ${type} were cleaned.`, 'QueueProcessor');
}
onQueueDrained() {
}
};
__decorate([
(0, bull_1.Process)({
name: 'mjDraw',
concurrency: process.env.CONCURRENCY ? +process.env.CONCURRENCY : 3,
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], QueueProcessor.prototype, "handleJob", null);
__decorate([
(0, bull_1.OnQueueActive)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueActive", null);
__decorate([
(0, bull_1.OnQueueError)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Error]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueError", null);
__decorate([
(0, bull_1.OnQueueProgress)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Number]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueProgress", null);
__decorate([
(0, bull_1.OnQueueCompleted)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueCompleted", null);
__decorate([
(0, bull_1.OnQueueFailed)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Error]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueFailed", null);
__decorate([
(0, bull_1.OnQueuePaused)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueuePaused", null);
__decorate([
(0, bull_1.OnQueueResumed)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueResumed", null);
__decorate([
(0, bull_1.OnQueueCleaned)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array, String]),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueCleaned", null);
__decorate([
(0, bull_1.OnQueueDrained)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], QueueProcessor.prototype, "onQueueDrained", null);
QueueProcessor = QueueProcessor_1 = __decorate([
(0, bull_1.Processor)('MJDRAW'),
__metadata("design:paramtypes", [midjourney_service_1.MidjourneyService])
], QueueProcessor);
exports.QueueProcessor = QueueProcessor;

View File

@ -1,77 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueService = void 0;
const utils_1 = require("../../common/utils");
const bull_1 = require("@nestjs/bull");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
const midjourney_service_1 = require("../midjourney/midjourney.service");
const models_service_1 = require("../models/models.service");
const userBalance_service_1 = require("../userBalance/userBalance.service");
let QueueService = class QueueService {
constructor(mjDrawQueue, midjourneyService, userBalanceService, globalConfigService, modelsService) {
this.mjDrawQueue = mjDrawQueue;
this.midjourneyService = midjourneyService;
this.userBalanceService = userBalanceService;
this.globalConfigService = globalConfigService;
this.modelsService = modelsService;
this.jobIds = [];
}
async onApplicationBootstrap() {
await this.mjDrawQueue.clean(0, 'active');
await this.midjourneyService.cleanQueue();
}
async addMjDrawQueue(body, req) {
const { orderId, action, drawId } = body;
await this.midjourneyService.checkLimit(req);
const detailKeyInfo = await this.modelsService.getCurrentModelKeyInfo('midjourney');
const keyId = detailKeyInfo === null || detailKeyInfo === void 0 ? void 0 : detailKeyInfo.id;
const { key, proxyUrl, deduct, deductType, timeout } = detailKeyInfo;
await this.userBalanceService.validateBalance(req, deductType, action === 'UPSCALE' ? deduct : deduct * 4);
if (action === 'IMAGINE') {
const randomDrawId = `${(0, utils_1.createRandomUid)()}`;
const params = Object.assign(Object.assign({}, body), { userId: req.user.id, randomDrawId });
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 200000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action: action, userId: req.user.id }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return true;
}
else {
const { action, customId, base64 } = body;
let { drawId } = body;
if (action === 'MODAL') {
const result = await this.midjourneyService.getDrawActionDetail(action, drawId, customId);
drawId = result.drawId;
}
const params = Object.assign(Object.assign({}, body), { userId: req.user.id, drawId });
const res = await this.midjourneyService.addDrawQueue(params);
const timeout = (await this.globalConfigService.getConfigs(['mjTimeoutMs'])) || 300000;
const job = await this.mjDrawQueue.add('mjDraw', { id: res.id, action, userId: req.user.id, base64 }, { delay: 1000, timeout: +timeout });
this.jobIds.push(job.id);
return;
}
}
async getQueue() {
return { jobIds: this.jobIds };
}
};
QueueService = __decorate([
__param(0, (0, bull_1.InjectQueue)('MJDRAW')),
__metadata("design:paramtypes", [Object, midjourney_service_1.MidjourneyService,
userBalance_service_1.UserBalanceService,
globalConfig_service_1.GlobalConfigService,
models_service_1.ModelsService])
], QueueService);
exports.QueueService = QueueService;

View File

@ -8,48 +8,51 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisCacheModule = void 0;
const common_1 = require("@nestjs/common");
const redisCache_service_1 = require("./redisCache.service");
const redisCache_controller_1 = require("./redisCache.controller");
const nestjs_config_1 = require("nestjs-config");
const redis_1 = require("redis");
const redisCache_controller_1 = require("./redisCache.controller");
const redisCache_service_1 = require("./redisCache.service");
let RedisCacheModule = class RedisCacheModule {
};
RedisCacheModule = __decorate([
(0, common_1.Global)(),
(0, common_1.Module)({
imports: [nestjs_config_1.ConfigModule],
imports: [],
controllers: [redisCache_controller_1.RedisCacheController],
providers: [
{
provide: 'REDIS_CLIENT',
useFactory: async (redisConfig) => {
const port = +process.env.REDIS_PORT;
useFactory: async () => {
const host = process.env.REDIS_HOST;
const port = parseInt(process.env.REDIS_PORT, 10);
const password = process.env.REDIS_PASSWORD;
const username = process.env.REDIS_USER;
const database = parseInt(process.env.REDIS_DB, 10) || 0;
if (!host || !port) {
common_1.Logger.error(`Please config Redis config | 未配置 Redis 配置信息 请确认配置redis服务以获得更好的体验`, 'RedistCacheModule');
common_1.Logger.error(`Please configure Redis config | 未配置 Redis 配置信息,请确认配置 Redis 服务以获得更好的体验`, 'RedisCacheModule');
return;
}
const client = (0, redis_1.createClient)({
socket: { host, port },
socket: {
host,
port,
},
username,
password,
database,
});
const res = await client.connect();
client.on('ready', () => {
common_1.Logger.debug(`Your Redis connection successful`, 'RedistCacheModule');
common_1.Logger.log(`Redis connection successful`, 'RedisCacheModule');
});
client.on('error', () => {
common_1.Logger.error(`Your Redis connection failed | 您的 Redist 连接失败`, 'RedistCacheModule');
client.on('error', (err) => {
common_1.Logger.error(`Redis connection failed: ${err}`, 'RedisCacheModule');
});
await client.connect();
return client;
},
inject: [nestjs_config_1.ConfigService],
},
redisCache_service_1.RedisCacheService,
],
exports: ['REDIS_CLIENT'],
exports: ['REDIS_CLIENT', redisCache_service_1.RedisCacheService],
})
], RedisCacheModule);
exports.RedisCacheModule = RedisCacheModule;

View File

@ -18,12 +18,6 @@ let RedisCacheService = class RedisCacheService {
constructor(redisClient) {
this.redisClient = redisClient;
}
async onModuleInit() {
}
test() {
this.redisClient.set('aaa', 111);
return 1;
}
async get(body) {
const { key } = body;
const res = await this.redisClient.get(key);
@ -40,6 +34,13 @@ let RedisCacheService = class RedisCacheService {
throw new common_1.HttpException(error, common_1.HttpStatus.BAD_REQUEST);
}
}
async getJwtSecret() {
const secret = await this.redisClient.get('JWT_SECRET');
if (!secret) {
throw new Error('JWT secret not found in Redis');
}
return secret;
}
async ttl(key) {
return await this.redisClient.ttl(key);
}

View File

@ -13,25 +13,27 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StatisticService = void 0;
const balance_constant_1 = require("../../common/constants/balance.constant");
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
const date_1 = require("../../common/utils/date");
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const user_entity_1 = require("../user/user.entity");
const axios_1 = require("axios");
const typeorm_2 = require("typeorm");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const balance_constant_1 = require("../../common/constants/balance.constant");
const date_1 = require("../../common/utils/date");
const axios_1 = require("axios");
const config_entity_1 = require("../globalConfig/config.entity");
const order_entity_1 = require("../order/order.entity");
const globalConfig_service_1 = require("../globalConfig/globalConfig.service");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
const midjourney_constant_1 = require("../../common/constants/midjourney.constant");
const order_entity_1 = require("../order/order.entity");
const user_entity_1 = require("../user/user.entity");
let StatisticService = class StatisticService {
constructor(userEntity, chatLogEntity, configEntity, orderEntity, midjourneyEntity) {
constructor(userEntity, chatLogEntity, configEntity, orderEntity, midjourneyEntity, globalConfigService) {
this.userEntity = userEntity;
this.chatLogEntity = chatLogEntity;
this.configEntity = configEntity;
this.orderEntity = orderEntity;
this.midjourneyEntity = midjourneyEntity;
this.globalConfigService = globalConfigService;
}
async getBaseStatistic() {
const userCount = await this.countUsers();
@ -79,11 +81,16 @@ let StatisticService = class StatisticService {
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
const queryBuilder = this.userEntity.createQueryBuilder('user');
const userCount = await queryBuilder.where('user.createdAt >= :today', { today }).andWhere('user.createdAt < :tomorrow', { tomorrow }).getCount();
const userCount = await queryBuilder
.where('user.createdAt >= :today', { today })
.andWhere('user.createdAt < :tomorrow', { tomorrow })
.getCount();
return userCount;
}
async countChats() {
const chatCount = await this.chatLogEntity.count({ where: { type: balance_constant_1.ChatType.NORMAL_CHAT } });
const chatCount = await this.chatLogEntity.count({
where: { type: balance_constant_1.ChatType.NORMAL_CHAT },
});
return chatCount;
}
async countNewChatsToday() {
@ -99,7 +106,9 @@ let StatisticService = class StatisticService {
return chatCount;
}
async countDraws() {
const drawCount = await this.chatLogEntity.count({ where: { type: balance_constant_1.ChatType.PAINT } });
const drawCount = await this.chatLogEntity.count({
where: { type: balance_constant_1.ChatType.PAINT },
});
return drawCount;
}
async countNewDrawsToday() {
@ -189,7 +198,9 @@ let StatisticService = class StatisticService {
const queryBuilder = this.midjourneyEntity.createQueryBuilder('midjourney');
const result = await queryBuilder
.select(`DATE(midjourney.createdAt) as date, COUNT(*) as count`)
.where(`midjourney.status = :status`, { status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED })
.where(`midjourney.status = :status`, {
status: midjourney_constant_1.MidjourneyStatusEnum.DRAWED,
})
.andWhere('midjourney.createdAt >= :startDate', { startDate })
.groupBy('date')
.orderBy('date')
@ -210,28 +221,68 @@ let StatisticService = class StatisticService {
return dailyData;
}
async getBaiduStatistics(days) {
var _a, _b;
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');
const metrics = 'pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time';
const method = 'overview/getTimeTrendRpt';
const configInfo = await this.configEntity.find({ where: { configKey: (0, typeorm_2.In)(['baiduToken', 'baiduSiteId']) } });
const siteId = (_a = configInfo.find((c) => c.configKey === 'baiduSiteId')) === null || _a === void 0 ? void 0 : _a.configVal;
const accessToken = (_b = configInfo.find((c) => c.configKey === 'baiduToken')) === null || _b === void 0 ? void 0 : _b.configVal;
if (!siteId || !accessToken) {
const { baiduToken, baiduSiteId, baiduApiKey, baiduSecretKey, baiduRefreshToken, } = await this.globalConfigService.getConfigs([
'baiduToken',
'baiduSiteId',
'baiduApiKey',
'baiduSecretKey',
'baiduRefreshToken',
]);
if (!baiduApiKey ||
!baiduToken ||
!baiduSiteId ||
!baiduRefreshToken ||
!baiduSecretKey) {
return [];
}
if (!siteId) {
throw new common_1.HttpException('请先配置百度统计siteId', common_1.HttpStatus.BAD_REQUEST);
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);
}
if (!accessToken) {
throw new common_1.HttpException('请先配置百度统计accessToken', common_1.HttpStatus.BAD_REQUEST);
catch (error) {
res = {
data: {
error_code: 111,
message: 'Access token invalid or no longer valid',
},
};
}
const url = `https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=${accessToken}&site_id=${siteId}&method=${method}&start_date=${start_date}&end_date=${end_date}&metrics=${metrics}`;
const res = await axios_1.default.get(url);
const { error_code, message } = res.data;
let { error_code, message } = res.data;
if (error_code === 111) {
throw new common_1.HttpException(message || '百度授权码过期', common_1.HttpStatus.BAD_REQUEST);
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;
try {
tokenRes = await axios_1.default.get(tokenUrl);
}
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);
}
}
if (error_code && error_code !== 200) {
throw new common_1.HttpException(message || '获取百度统计数据失败', common_1.HttpStatus.BAD_REQUEST);
@ -265,6 +316,7 @@ StatisticService = __decorate([
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository])
typeorm_2.Repository,
globalConfig_service_1.GlobalConfigService])
], StatisticService);
exports.StatisticService = StatisticService;

View File

@ -21,11 +21,11 @@ let UploadController = class UploadController {
constructor(uploadService) {
this.uploadService = uploadService;
}
async uploadFile(file) {
return this.uploadService.uploadFile(file);
async uploadFile(file, dir) {
return this.uploadService.uploadFile(file, dir);
}
async uploadFileFromUrl({ filename, url, dir = 'ai' }) {
return this.uploadService.uploadFileFromUrl({ filename, url, dir });
async uploadFileFromUrl({ url, dir = 'ai' }) {
return this.uploadService.uploadFileFromUrl({ url, dir });
}
};
__decorate([
@ -33,8 +33,9 @@ __decorate([
(0, swagger_1.ApiOperation)({ summary: '上传文件' }),
(0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)('file')),
__param(0, (0, common_1.UploadedFile)()),
__param(1, (0, common_1.Query)('dir')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:paramtypes", [Object, String]),
__metadata("design:returntype", Promise)
], UploadController.prototype, "uploadFile", null);
__decorate([

View File

@ -25,29 +25,57 @@ let UploadService = class UploadService {
this.globalConfigService = globalConfigService;
}
onModuleInit() { }
async uploadFile(file) {
const { filename: name, originalname, buffer, dir = 'ai', mimetype } = file;
const fileTyle = mimetype ? mimetype.split('/')[1] : '';
const filename = originalname || name;
common_1.Logger.debug(`准备上传文件: ${filename}, 类型: ${fileTyle}`, 'UploadService');
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs(['tencentCosStatus', 'aliOssStatus', 'cheveretoStatus']);
async uploadFile(file, dir = 'others') {
const { filename: name, originalname, buffer, mimetype, } = file;
if (process.env.ISDEV) {
dir = `dev/${dir}`;
}
common_1.Logger.debug(`准备上传文件: ${dir}`, 'UploadService');
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 { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs([
'tencentCosStatus',
'aliOssStatus',
'cheveretoStatus',
]);
common_1.Logger.debug(`上传配置状态 - 腾讯云: ${tencentCosStatus}, 阿里云: ${aliOssStatus}, Chevereto: ${cheveretoStatus}`, 'UploadService');
if (!Number(tencentCosStatus) && !Number(aliOssStatus) && !Number(cheveretoStatus)) {
if (!Number(tencentCosStatus) &&
!Number(aliOssStatus) &&
!Number(cheveretoStatus)) {
throw new common_1.HttpException('请先前往后台配置上传图片的方式', common_1.HttpStatus.BAD_REQUEST);
}
try {
if (Number(tencentCosStatus)) {
common_1.Logger.debug(`使用腾讯云COS上传`, 'UploadService');
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle });
return await this.uploadFileByTencentCos({
filename,
buffer,
dir,
fileType,
});
}
if (Number(aliOssStatus)) {
common_1.Logger.debug(`使用阿里云OSS上传`, 'UploadService');
return await this.uploadFileByAliOss({ filename, buffer, dir, fileTyle });
return await this.uploadFileByAliOss({
filename,
buffer,
dir,
fileType,
});
}
if (Number(cheveretoStatus)) {
common_1.Logger.debug(`使用Chevereto上传`, 'UploadService');
const { filename, buffer: fromBuffer, dir } = file;
return await this.uploadFileByChevereto({ filename, buffer: fromBuffer.toString('base64'), dir, fileTyle });
return await this.uploadFileByChevereto({
filename,
buffer: fromBuffer.toString('base64'),
dir,
fileType,
});
}
}
catch (error) {
@ -56,7 +84,11 @@ let UploadService = class UploadService {
}
}
async getUploadType() {
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs(['tencentCosStatus', 'aliOssStatus', 'cheveretoStatus']);
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs([
'tencentCosStatus',
'aliOssStatus',
'cheveretoStatus',
]);
if (Number(tencentCosStatus)) {
return 'tencent';
}
@ -67,10 +99,72 @@ let UploadService = class UploadService {
return 'chevereto';
}
}
async uploadFileFromUrl({ filename, url, dir = 'ai' }) {
dir = process.env.ISDEV ? 'mjdev' : dir;
const { tencentCosStatus = 0, aliOssStatus = 0, cheveretoStatus = 0, } = await this.globalConfigService.getConfigs(['tencentCosStatus', 'aliOssStatus', 'cheveretoStatus']);
if (!Number(tencentCosStatus) && !Number(aliOssStatus) && !Number(cheveretoStatus)) {
async uploadFileFromUrl({ url, dir = 'others' }) {
if (process.env.ISDEV) {
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)) {
@ -84,16 +178,20 @@ let UploadService = class UploadService {
return await this.uploadFileByCheveretoFromUrl({ filename, url, dir });
}
}
async uploadFileByTencentCos({ filename, buffer, dir, fileTyle }) {
async uploadFileByTencentCos({ filename, buffer, dir, fileType }) {
const { Bucket, Region, SecretId, SecretKey } = await this.getUploadConfig('tencent');
this.tencentCos = new TENCENTCOS({ SecretId, SecretKey, FileParallelLimit: 10 });
this.tencentCos = new TENCENTCOS({
SecretId,
SecretKey,
FileParallelLimit: 10,
});
try {
return new Promise(async (resolve, reject) => {
const type = fileTyle || 'png';
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)()}.${fileTyle}`}`,
Key: `${dir}/${filename || `${(0, utils_1.createRandomUid)()}.${fileType}`}`,
StorageClass: 'STANDARD',
Body: buffer,
}, async (err, data) => {
@ -118,25 +216,44 @@ let UploadService = class UploadService {
}
async uploadFileByTencentCosFromUrl({ filename, url, dir }) {
const { Bucket, Region, SecretId, SecretKey } = await this.getUploadConfig('tencent');
this.tencentCos = new TENCENTCOS({ SecretId, SecretKey, FileParallelLimit: 10 });
this.tencentCos = new TENCENTCOS({
SecretId,
SecretKey,
FileParallelLimit: 10,
});
try {
const buffer = await this.getBufferFromUrl(url);
return await this.uploadFileByTencentCos({ filename, buffer, dir, fileTyle: '' });
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, fileTyle = 'png' }) {
async uploadFileByAliOss({ filename, buffer, dir, fileType = 'png' }) {
const { region, bucket, accessKeyId, accessKeySecret } = await this.getUploadConfig('ali');
const client = new ALIOSS({ region: (0, utils_1.removeSpecialCharacters)(region), accessKeyId, accessKeySecret, bucket: (0, utils_1.removeSpecialCharacters)(bucket) });
const client = new ALIOSS({
region: (0, utils_1.removeSpecialCharacters)(region),
accessKeyId,
accessKeySecret,
bucket: (0, utils_1.removeSpecialCharacters)(bucket),
});
try {
console.log('ali 开始上传');
return new Promise((resolve, reject) => {
client
.put(`${dir}/${filename || `${(0, utils_1.createRandomUid)()}.${fileTyle}`}`, buffer)
.then((result) => {
.put(`${dir}/${filename || `${(0, utils_1.createRandomUid)()}.${fileType}`}`, buffer)
.then(async (result) => {
const { acceleratedDomain } = await this.getUploadConfig('ali');
if (acceleratedDomain) {
result.url = result.url.replace(/^(https:\/\/[^/]+)(\/.*)$/, `https://${acceleratedDomain}$2`);
console.log('当前已开启全球加速----------------->', result.url);
}
resolve(result.url);
})
.catch((err) => {
@ -160,7 +277,7 @@ let UploadService = class UploadService {
}
async uploadFileToLocal({ filename, buffer, dir = 'ai' }) {
if (!filename || !buffer) {
throw new Error("必须提供文件名和文件内容");
throw new Error('必须提供文件名和文件内容');
}
const appRoot = require('app-root-path');
const uploadDir = path_1.default.join(appRoot.path, 'service', 'public', 'file');
@ -187,7 +304,7 @@ let UploadService = class UploadService {
throw new common_1.HttpException('上传图片失败[ALI][url]', common_1.HttpStatus.BAD_REQUEST);
}
}
async uploadFileByChevereto({ filename = '', buffer, dir = 'ai', fileTyle = 'png' }) {
async uploadFileByChevereto({ filename = '', buffer, dir = 'ai', fileType = 'png', }) {
var _a;
const { key, uploadPath } = await this.getUploadConfig('chevereto');
let url = uploadPath.endsWith('/') ? uploadPath.slice(0, -1) : uploadPath;
@ -225,11 +342,29 @@ let UploadService = class UploadService {
}
async getUploadConfig(type) {
if (type === 'ali') {
const { aliOssRegion: region, aliOssBucket: bucket, aliOssAccessKeyId: accessKeyId, aliOssAccessKeySecret: accessKeySecret, } = await this.globalConfigService.getConfigs(['aliOssRegion', 'aliOssBucket', 'aliOssAccessKeyId', 'aliOssAccessKeySecret']);
return { region, bucket, accessKeyId, accessKeySecret };
const { aliOssRegion: region, aliOssBucket: bucket, aliOssAccessKeyId: accessKeyId, aliOssAccessKeySecret: accessKeySecret, aliOssAcceleratedDomain: acceleratedDomain, } = await this.globalConfigService.getConfigs([
'aliOssRegion',
'aliOssBucket',
'aliOssAccessKeyId',
'aliOssAccessKeySecret',
'acceleratedDomain',
]);
return {
region,
bucket,
accessKeyId,
accessKeySecret,
acceleratedDomain,
};
}
if (type === 'tencent') {
const { cosBucket: Bucket, cosRegion: Region, cosSecretId: SecretId, cosSecretKey: SecretKey, tencentCosAcceleratedDomain: acceleratedDomain, } = await this.globalConfigService.getConfigs(['cosBucket', 'cosRegion', 'cosSecretId', 'cosSecretKey', 'tencentCosAcceleratedDomain']);
const { cosBucket: Bucket, cosRegion: Region, cosSecretId: SecretId, cosSecretKey: SecretKey, tencentCosAcceleratedDomain: acceleratedDomain, } = await this.globalConfigService.getConfigs([
'cosBucket',
'cosRegion',
'cosSecretId',
'cosSecretKey',
'tencentCosAcceleratedDomain',
]);
return { Bucket, Region, SecretId, SecretKey, acceleratedDomain };
}
if (type === 'chevereto') {

View File

@ -10,8 +10,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserEntity = void 0;
const typeorm_1 = require("typeorm");
const baseEntity_1 = require("../../common/entity/baseEntity");
const typeorm_1 = require("typeorm");
let UserEntity = class UserEntity extends baseEntity_1.BaseEntity {
};
__decorate([
@ -61,7 +61,12 @@ __decorate([
__metadata("design:type", String)
], UserEntity.prototype, "registerIp", void 0);
__decorate([
(0, typeorm_1.Column)({ length: 64, default: '', comment: '最后一次登录IP', nullable: true }),
(0, typeorm_1.Column)({
length: 64,
default: '',
comment: '最后一次登录IP',
nullable: true,
}),
__metadata("design:type", String)
], UserEntity.prototype, "lastLoginIp", void 0);
__decorate([

View File

@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.UserModule = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
@ -41,17 +40,22 @@ UserModule = __decorate([
accountLog_entity_1.AccountLogEntity,
config_entity_1.ConfigEntity,
cramiPackage_entity_1.CramiPackageEntity,
whiteList_entity_1.WhiteListEntity,
userBalance_entity_1.UserBalanceEntity,
salesUsers_entity_1.SalesUsersEntity,
fingerprint_entity_1.FingerprintLogEntity,
chatLog_entity_1.ChatLogEntity,
chatGroup_entity_1.ChatGroupEntity,
midjourney_entity_1.MidjourneyEntity
midjourney_entity_1.MidjourneyEntity,
]),
],
controllers: [user_controller_1.UserController],
providers: [user_service_1.UserService, verification_service_1.VerificationService, userBalance_service_1.UserBalanceService, redisCache_service_1.RedisCacheService, mailer_service_1.MailerService,],
providers: [
user_service_1.UserService,
verification_service_1.VerificationService,
userBalance_service_1.UserBalanceService,
redisCache_service_1.RedisCacheService,
mailer_service_1.MailerService,
],
exports: [user_service_1.UserService],
})
], UserModule);

View File

@ -22,7 +22,6 @@ const typeorm_1 = require("@nestjs/typeorm");
const bcrypt = require("bcryptjs");
const _ = require("lodash");
const typeorm_2 = require("typeorm");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const userBalance_service_1 = require("../userBalance/userBalance.service");
const user_constant_1 = require("./../../common/constants/user.constant");
@ -30,9 +29,8 @@ const globalConfig_service_1 = require("./../globalConfig/globalConfig.service")
const verification_service_1 = require("./../verification/verification.service");
const user_entity_1 = require("./user.entity");
let UserService = class UserService {
constructor(userEntity, whiteListEntity, connection, verificationService, mailerService, userBalanceService, globalConfigService, configEntity) {
constructor(userEntity, connection, verificationService, mailerService, userBalanceService, globalConfigService, configEntity) {
this.userEntity = userEntity;
this.whiteListEntity = whiteListEntity;
this.connection = connection;
this.verificationService = verificationService;
this.mailerService = mailerService;
@ -43,7 +41,9 @@ let UserService = class UserService {
async createUserAndVerifycation(user, req) {
const { username, email, password, invitedBy, client = 0 } = user;
if (invitedBy) {
const b = await this.userEntity.findOne({ where: { inviteCode: invitedBy } });
const b = await this.userEntity.findOne({
where: { inviteCode: invitedBy },
});
if (!b) {
throw new common_1.HttpException('无效的邀请码!', common_1.HttpStatus.BAD_REQUEST);
}
@ -62,7 +62,9 @@ let UserService = class UserService {
userInput.client = client;
let n;
if (!u) {
const userDefautlAvatar = await this.globalConfigService.getConfigs(['userDefautlAvatar']);
const userDefautlAvatar = await this.globalConfigService.getConfigs([
'userDefautlAvatar',
]);
userInput.avatar = userDefautlAvatar;
n = await this.userEntity.save(userInput);
}
@ -85,9 +87,13 @@ let UserService = class UserService {
pre[cur.configKey] = cur.configVal;
return pre;
}, {});
const isVerifyEmail = configMap['isVerifyEmail'] ? Number(configMap['isVerifyEmail']) : 1;
const isVerifyEmail = configMap['isVerifyEmail']
? Number(configMap['isVerifyEmail'])
: 1;
if (isVerifyEmail) {
const expir = configMap['registerVerifyExpir'] ? Number(configMap['registerVerifyExpir']) : 30 * 60;
const expir = configMap['registerVerifyExpir']
? Number(configMap['registerVerifyExpir'])
: 30 * 60;
const v = await this.verificationService.createVerification(n, verification_constant_1.VerificationEnum.Registration, expir);
const { code, email, id } = v;
const { registerVerifyEmailFrom } = configMap;
@ -127,7 +133,11 @@ let UserService = class UserService {
}
}
if (username && password) {
const where = [{ username }, { email: username }, { phone: username }];
const where = [
{ username },
{ email: username },
{ phone: username },
];
u = await this.userEntity.findOne({ where: where });
if (!u) {
throw new common_1.HttpException('当前账户不存在!', common_1.HttpStatus.BAD_REQUEST);
@ -180,7 +190,16 @@ let UserService = class UserService {
async getUserInfo(userId) {
const userInfo = await this.userEntity.findOne({
where: { id: userId },
select: ['username', 'avatar', 'role', 'email', 'sign', 'inviteCode', 'openId', 'consecutiveDays'],
select: [
'username',
'avatar',
'role',
'email',
'sign',
'inviteCode',
'openId',
'consecutiveDays',
],
});
if (!userInfo) {
throw new common_1.HttpException('当前用户信息失效、请重新登录!', common_1.HttpStatus.UNAUTHORIZED);
@ -206,8 +225,8 @@ let UserService = class UserService {
throw new common_1.HttpException('没有变更,无需更改!', common_1.HttpStatus.BAD_REQUEST);
}
if (body.username) {
const u = await this.userEntity.findOne({ where: { username: body.username, id: (0, typeorm_2.Not)(id) } });
if (u) {
const usernameTaken = await this.isUsernameTaken(body.username, id);
if (usernameTaken) {
throw new common_1.HttpException('用户名已存在!', common_1.HttpStatus.BAD_REQUEST);
}
}
@ -217,6 +236,14 @@ let UserService = class UserService {
}
return '修改用户信息成功!';
}
async isUsernameTaken(username, excludeUserId) {
const where = { username };
if (excludeUserId) {
where.id = (0, typeorm_2.Not)(excludeUserId);
}
const user = await this.userEntity.findOne({ where });
return !!user;
}
async updateUserPassword(userId, password) {
const hashedPassword = bcrypt.hashSync(password, 10);
const r = await this.userEntity.update({ id: userId }, { password: hashedPassword });
@ -253,7 +280,14 @@ let UserService = class UserService {
const [rows, count] = await this.userEntity.findAndCount({
where: { invitedBy },
order: { id: 'DESC' },
select: ['username', 'email', 'createdAt', 'status', 'avatar', 'updatedAt'],
select: [
'username',
'email',
'createdAt',
'status',
'avatar',
'updatedAt',
],
take: size,
skip: (page - 1) * size,
});
@ -286,7 +320,11 @@ let UserService = class UserService {
}
async userRecharge(body) {
const { userId, model3Count = 0, model4Count = 0, drawMjCount = 0 } = body;
await this.userBalanceService.addBalanceToUser(userId, { model3Count, model4Count, drawMjCount });
await this.userBalanceService.addBalanceToUser(userId, {
model3Count,
model4Count,
drawMjCount,
});
const res = await this.userBalanceService.saveRecordRechargeLog({
userId,
rechargeType: balance_constant_1.RechargeType.ADMIN_GIFT,
@ -298,14 +336,18 @@ let UserService = class UserService {
return res;
}
async queryAll(query, req) {
const { page = 1, size = 10, username, email, status, keyword, phone } = query;
const { page = 1, size = 10, username, email, status, keyword, phone, } = query;
let where = {};
username && Object.assign(where, { username: (0, typeorm_2.Like)(`%${username}%`) });
email && Object.assign(where, { email: (0, typeorm_2.Like)(`%${email}%`) });
phone && Object.assign(where, { phone: (0, typeorm_2.Like)(`%${phone}%`) });
status && Object.assign(where, { status });
if (keyword) {
where = [{ username: (0, typeorm_2.Like)(`%${keyword}%`) }, { email: (0, typeorm_2.Like)(`%${keyword}%`) }, { phone: (0, typeorm_2.Like)(`%${keyword}%`) }];
where = [
{ username: (0, typeorm_2.Like)(`%${keyword}%`) },
{ email: (0, typeorm_2.Like)(`%${keyword}%`) },
{ phone: (0, typeorm_2.Like)(`%${keyword}%`) },
];
}
const [rows, count] = await this.userEntity.findAndCount({
skip: (page - 1) * size,
@ -313,18 +355,36 @@ let UserService = class UserService {
take: size,
order: { createdAt: 'DESC' },
cache: true,
select: ['username', 'avatar', 'inviteCode', 'role', 'sign', 'status', 'id', 'email', 'createdAt', 'lastLoginIp', 'phone'],
select: [
'username',
'avatar',
'inviteCode',
'role',
'sign',
'status',
'id',
'email',
'createdAt',
'lastLoginIp',
'phone',
],
});
const ids = rows.map((t) => t.id);
const data = await this.userBalanceService.queryUserBalanceByIds(ids);
rows.forEach((user) => (user.balanceInfo = data.find((t) => t.userId === user.id)));
req.user.role !== 'super' && rows.forEach((t) => (t.email = (0, utils_1.maskEmail)(t.email)));
req.user.role !== 'super' && rows.forEach((t) => (t.lastLoginIp = (0, utils_1.maskIpAddress)(t.lastLoginIp)));
req.user.role !== 'super' && rows.forEach((t) => (t.phone = (0, utils_1.maskIpAddress)(t.phone)));
req.user.role !== 'super' &&
rows.forEach((t) => (t.email = (0, utils_1.maskEmail)(t.email)));
req.user.role !== 'super' &&
rows.forEach((t) => (t.lastLoginIp = (0, utils_1.maskIpAddress)(t.lastLoginIp)));
req.user.role !== 'super' &&
rows.forEach((t) => (t.phone = (0, utils_1.maskIpAddress)(t.phone)));
return { rows, count };
}
async queryOne({ id }) {
return await this.userEntity.findOne({ where: { id }, select: ['username', 'avatar', 'inviteCode', 'role', 'sign', 'status'] });
return await this.userEntity.findOne({
where: { id },
select: ['username', 'avatar', 'inviteCode', 'role', 'sign', 'status'],
});
}
async updateStatus(body) {
const { id, status } = body;
@ -373,7 +433,9 @@ let UserService = class UserService {
return user;
}
async createUserFromOpenId(openId, invitedBy) {
const userDefautlAvatar = await this.globalConfigService.getConfigs(['userDefautlAvatar']);
const userDefautlAvatar = await this.globalConfigService.getConfigs([
'userDefautlAvatar',
]);
const userInfo = {
avatar: userDefautlAvatar,
username: `用户${(0, utils_1.createRandomUid)()}`,
@ -386,6 +448,46 @@ let UserService = class UserService {
const user = await this.userEntity.save(userInfo);
return user;
}
async createUserFromContact(params) {
const { username, email, phone, invitedBy } = params;
const userDefautlAvatar = await this.globalConfigService.getConfigs([
'userDefautlAvatar',
]);
const userInfo = {
avatar: userDefautlAvatar,
username: `用户${(0, utils_1.createRandomUid)()}`,
status: user_constant_1.UserStatusEnum.ACTIVE,
sex: 0,
};
if (username) {
userInfo.username = username;
}
if (email) {
userInfo.email = email;
}
if (phone) {
userInfo.phone = phone;
}
if (invitedBy) {
userInfo.invitedBy = invitedBy;
}
const user = await this.userEntity.save(userInfo);
return user;
}
async getUserByContact(params) {
const { username, email, phone } = params;
const where = [];
if (username) {
where.push({ username });
}
if (email) {
where.push({ email });
}
if (phone) {
where.push({ phone });
}
return await this.userEntity.findOne({ where });
}
async bindWx(openId, userId) {
try {
const user = await this.userEntity.findOne({ where: { id: userId } });
@ -412,23 +514,33 @@ let UserService = class UserService {
if (phone) {
const userByPhone = await this.userEntity.findOne({ where: { phone } });
if (userByPhone) {
throw new common_1.HttpException('当前手机号已注册、请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
return false;
}
}
if (email) {
const userByEmail = await this.userEntity.findOne({ where: { email } });
if (userByEmail) {
throw new common_1.HttpException('当前邮箱已注册、请勿重复注册!', common_1.HttpStatus.BAD_REQUEST);
return false;
}
}
const userByUsername = await this.userEntity.findOne({ where: { username } });
if (userByUsername) {
throw new common_1.HttpException('用户名已存在、请更换用户名!', common_1.HttpStatus.BAD_REQUEST);
if (username) {
const userByUsername = await this.userEntity.findOne({
where: { username },
});
if (userByUsername) {
return false;
}
}
if (!phone && !email && !username) {
return false;
}
return true;
}
async verifyUserRegisterByPhone(params) {
const { username, password, phone, phoneCode } = params;
const user = await this.userEntity.findOne({ where: [{ username }, { phone }] });
const user = await this.userEntity.findOne({
where: [{ username }, { phone }],
});
if (user && user.username === username) {
throw new common_1.HttpException('用户名已存在、请更换用户名!', common_1.HttpStatus.BAD_REQUEST);
}
@ -439,7 +551,9 @@ let UserService = class UserService {
async verifyUserRegisterByEmail(params) {
const { username, email } = params;
console.log(`校验邮箱注册: 开始 - 用户名: ${username}, 邮箱: ${email}`);
const user = await this.userEntity.findOne({ where: [{ username }, { email }] });
const user = await this.userEntity.findOne({
where: [{ username }, { email }],
});
if (user && user.username === username) {
console.error(`校验失败: 用户名 "${username}" 已存在`);
throw new common_1.HttpException('用户名已存在、请更换用户名!', common_1.HttpStatus.BAD_REQUEST);
@ -457,10 +571,8 @@ let UserService = class UserService {
UserService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(user_entity_1.UserEntity)),
__param(1, (0, typeorm_1.InjectRepository)(whiteList_entity_1.WhiteListEntity)),
__param(7, (0, typeorm_1.InjectRepository)(config_entity_1.ConfigEntity)),
__param(6, (0, typeorm_1.InjectRepository)(config_entity_1.ConfigEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Connection,
verification_service_1.VerificationService,
mailer_service_1.MailerService,

View File

@ -13,11 +13,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserBalanceController = void 0;
const common_1 = require("@nestjs/common");
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
const jwtAuth_guard_1 = require("../../common/auth/jwtAuth.guard");
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const userBalance_service_1 = require("./userBalance.service");
const adminAuth_guard_1 = require("../../common/auth/adminAuth.guard");
let UserBalanceController = class UserBalanceController {
constructor(userBalanceService) {
this.userBalanceService = userBalanceService;

View File

@ -8,24 +8,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserBalanceModule = void 0;
const common_1 = require("@nestjs/common");
const userBalance_service_1 = require("./userBalance.service");
const typeorm_1 = require("@nestjs/typeorm");
const balance_entity_1 = require("./balance.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
const config_entity_1 = require("../globalConfig/config.entity");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const user_entity_1 = require("../user/user.entity");
const verification_service_1 = require("../verification/verification.service");
const verifycation_entity_1 = require("../verification/verifycation.entity");
const accountLog_entity_1 = require("./accountLog.entity");
const userBalance_controller_1 = require("./userBalance.controller");
const config_entity_1 = require("../globalConfig/config.entity");
const cramiPackage_entity_1 = require("../crami/cramiPackage.entity");
const userBalance_entity_1 = require("./userBalance.entity");
const user_entity_1 = require("../user/user.entity");
const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const redisCache_service_1 = require("../redisCache/redisCache.service");
const balance_entity_1 = require("./balance.entity");
const fingerprint_entity_1 = require("./fingerprint.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
const userBalance_controller_1 = require("./userBalance.controller");
const userBalance_entity_1 = require("./userBalance.entity");
const userBalance_service_1 = require("./userBalance.service");
let UserBalanceModule = class UserBalanceModule {
};
UserBalanceModule = __decorate([
@ -41,11 +40,10 @@ UserBalanceModule = __decorate([
cramiPackage_entity_1.CramiPackageEntity,
user_entity_1.UserEntity,
salesUsers_entity_1.SalesUsersEntity,
whiteList_entity_1.WhiteListEntity,
fingerprint_entity_1.FingerprintLogEntity,
chatLog_entity_1.ChatLogEntity,
chatGroup_entity_1.ChatGroupEntity,
midjourney_entity_1.MidjourneyEntity
midjourney_entity_1.MidjourneyEntity,
]),
],
controllers: [userBalance_controller_1.UserBalanceController],

View File

@ -25,7 +25,6 @@ const accountLog_entity_1 = require("./accountLog.entity");
const balance_entity_1 = require("./balance.entity");
const userBalance_entity_1 = require("./userBalance.entity");
const date_1 = require("../../common/utils/date");
const whiteList_entity_1 = require("../chat/whiteList.entity");
const chatGroup_entity_1 = require("../chatGroup/chatGroup.entity");
const chatLog_entity_1 = require("../chatLog/chatLog.entity");
const midjourney_entity_1 = require("../midjourney/midjourney.entity");
@ -34,7 +33,7 @@ const salesUsers_entity_1 = require("../sales/salesUsers.entity");
const user_entity_1 = require("../user/user.entity");
const fingerprint_entity_1 = require("./fingerprint.entity");
let UserBalanceService = class UserBalanceService {
constructor(balanceEntity, userBalanceEntity, accountLogEntity, cramiPackageEntity, configEntity, userEntity, salesUsersEntity, whiteListEntity, fingerprintLogEntity, chatGroupEntity, chatLogEntity, midjourneyEntity, salesService, globalConfigService) {
constructor(balanceEntity, userBalanceEntity, accountLogEntity, cramiPackageEntity, configEntity, userEntity, salesUsersEntity, fingerprintLogEntity, chatGroupEntity, chatLogEntity, midjourneyEntity, salesService, globalConfigService) {
this.balanceEntity = balanceEntity;
this.userBalanceEntity = userBalanceEntity;
this.accountLogEntity = accountLogEntity;
@ -42,7 +41,6 @@ let UserBalanceService = class UserBalanceService {
this.configEntity = configEntity;
this.userEntity = userEntity;
this.salesUsersEntity = salesUsersEntity;
this.whiteListEntity = whiteListEntity;
this.fingerprintLogEntity = fingerprintLogEntity;
this.chatGroupEntity = chatGroupEntity;
this.chatLogEntity = chatLogEntity;
@ -88,17 +86,28 @@ let UserBalanceService = class UserBalanceService {
model4Count = model4Count + configMap.registerSendModel4Count;
drawMjCount = drawMjCount + configMap.registerSendDrawMjCount;
}
if (configMap.registerSendStatus === 1 && configMap.firstRegisterSendStatus === 1 && userId <= configMap.firstRegisterSendRank) {
if (configMap.registerSendStatus === 1 &&
configMap.firstRegisterSendStatus === 1 &&
userId <= configMap.firstRegisterSendRank) {
model3Count = model3Count + configMap.firstRregisterSendModel3Count;
model4Count = model4Count + configMap.firstRregisterSendModel4Count;
drawMjCount = drawMjCount + configMap.firstRregisterSendDrawMjCount;
}
await this.saveRecordRechargeLog({ userId, rechargeType: balance_constant_1.RechargeType.REG_GIFT, model3Count, drawMjCount, model4Count });
await this.saveRecordRechargeLog({
userId,
rechargeType: balance_constant_1.RechargeType.REG_GIFT,
model3Count,
drawMjCount,
model4Count,
});
if (invitedId) {
if (Number(configMap.inviteSendStatus) === 1) {
model3Count = model3Count + Number(configMap.invitedGuestSendModel3Count);
model4Count = model4Count + Number(configMap.invitedGuestSendModel4Count);
drawMjCount = drawMjCount + Number(configMap.invitedGuestSendDrawMjCount);
model3Count =
model3Count + Number(configMap.invitedGuestSendModel3Count);
model4Count =
model4Count + Number(configMap.invitedGuestSendModel4Count);
drawMjCount =
drawMjCount + Number(configMap.invitedGuestSendDrawMjCount);
await this.saveRecordRechargeLog({
userId,
rechargeType: balance_constant_1.RechargeType.INVITE_GIFT,
@ -120,7 +129,13 @@ let UserBalanceService = class UserBalanceService {
});
}
}
await this.userBalanceEntity.save({ userId, model3Count, model4Count, drawMjCount, useTokens: 0 });
await this.userBalanceEntity.save({
userId,
model3Count,
model4Count,
drawMjCount,
useTokens: 0,
});
}
catch (error) {
console.log('error: ', error);
@ -136,11 +151,25 @@ let UserBalanceService = class UserBalanceService {
if (role === 'visitor') {
return this.validateVisitorBalance(req, type, amount);
}
const res = await this.configEntity.findOne({ where: { configKey: 'vxNumber' } });
const res = await this.configEntity.findOne({
where: { configKey: 'vxNumber' },
});
const vxNumber = res ? res.configVal : '---';
const memberKey = type === 1 ? 'memberModel3Count' : type === 2 ? 'memberModel4Count' : type === 3 ? 'memberDrawMjCount' : null;
const baseKey = type === 1 ? 'model3Count' : type === 2 ? 'model4Count' : type === 3 ? 'drawMjCount' : null;
if (b.packageId && b[memberKey] < amount) {
const memberKey = type === 1
? 'memberModel3Count'
: type === 2
? 'memberModel4Count'
: type === 3
? 'memberDrawMjCount'
: null;
const baseKey = type === 1
? 'model3Count'
: type === 2
? 'model4Count'
: type === 3
? 'drawMjCount'
: null;
if (b.packageId && b[memberKey] + b[baseKey] < amount) {
if (b[baseKey] < amount) {
throw new common_1.HttpException(`您的账户余额不足,如果想继续体验服务,请联系管理员或购买专属套餐 `, common_1.HttpStatus.PAYMENT_REQUIRED);
}
@ -152,21 +181,33 @@ let UserBalanceService = class UserBalanceService {
}
async validateVisitorBalance(req, type, amount) {
const { id } = req.user;
const baseKey = type === 1 ? 'model3Count' : type === 2 ? 'model4Count' : type === 3 ? 'drawMjCount' : null;
const baseKey = type === 1
? 'model3Count'
: type === 2
? 'model4Count'
: type === 3
? 'drawMjCount'
: null;
const now = new Date();
const log = await this.fingerprintLogEntity.findOne({ where: { fingerprint: id } });
const { visitorModel3Num, visitorModel4Num, visitorMJNum } = await this.globalConfigService.getConfigs(['visitorModel3Num', 'visitorModel4Num', 'visitorMJNum']);
const log = await this.fingerprintLogEntity.findOne({
where: { fingerprint: id },
});
const { visitorModel3Num, visitorModel4Num, visitorMJNum } = await this.globalConfigService.getConfigs([
'visitorModel3Num',
'visitorModel4Num',
'visitorMJNum',
]);
const settings = {
model3Count: visitorModel3Num ? Number(visitorModel3Num) : 0,
model4Count: visitorModel4Num ? Number(visitorModel4Num) : 0,
drawMjCount: visitorMJNum ? Number(visitorMJNum) : 0
drawMjCount: visitorMJNum ? Number(visitorMJNum) : 0,
};
if (!log) {
let data = {
fingerprint: id,
model3Count: 0,
model4Count: 0,
drawMjCount: 0
drawMjCount: 0,
};
data[baseKey] = data[baseKey] + amount;
if (data[baseKey] > settings[baseKey]) {
@ -182,7 +223,7 @@ let UserBalanceService = class UserBalanceService {
let data = {
model3Count,
model4Count,
drawMjCount
drawMjCount,
};
const date = Number(new Date(log.updatedAt));
const isUpdateLastDay = this.isUpdatedToday(date);
@ -193,7 +234,7 @@ let UserBalanceService = class UserBalanceService {
data = {
model3Count: 0,
model4Count: 0,
drawMjCount: 0
drawMjCount: 0,
};
data[baseKey] = data[baseKey] + amount;
}
@ -216,37 +257,40 @@ let UserBalanceService = class UserBalanceService {
if (!b) {
throw new common_1.HttpException('缺失当前用户账户记录!', common_1.HttpStatus.BAD_REQUEST);
}
const memberKey = deductionType === 1
? 'memberModel3Count'
: deductionType === 2
? 'memberModel4Count'
: deductionType === 3
? 'memberDrawMjCount'
: null;
const baseKey = deductionType === 1 ? 'model3Count' : deductionType === 2 ? 'model4Count' : deductionType === 3 ? 'drawMjCount' : null;
const updateKey = b.packageId && b[memberKey] < amount ? baseKey : b.packageId ? memberKey : baseKey;
let useKey = null;
if (updateKey.includes('odel3')) {
useKey = 'useModel3Token';
}
if (updateKey.includes('odel4')) {
useKey = 'useModel4Token';
}
if (updateKey.includes('MjCount')) {
useKey = 'useDrawMjToken';
const keys = {
1: {
member: 'memberModel3Count',
nonMember: 'model3Count',
token: 'useModel3Token',
},
2: {
member: 'memberModel4Count',
nonMember: 'model4Count',
token: 'useModel4Token',
},
3: {
member: 'memberDrawMjCount',
nonMember: 'drawMjCount',
token: 'useDrawMjToken',
},
};
const { member, nonMember, token } = keys[deductionType];
let remainingAmount = amount;
let newMemberBalance = Math.max(b[member] - remainingAmount, 0);
remainingAmount -= b[member] - newMemberBalance;
let newNonMemberBalance = b[nonMember];
if (remainingAmount > 0) {
newNonMemberBalance = Math.max(b[nonMember] - remainingAmount, 0);
remainingAmount -= b[nonMember] - newNonMemberBalance;
}
const updateBalance = {
[updateKey]: b[updateKey] - amount < 0 ? 0 : b[updateKey] - amount,
[useKey]: b[useKey] + UseAmount,
[member]: newMemberBalance,
[nonMember]: newNonMemberBalance,
[token]: (b[token] || 0) + UseAmount,
};
if (useKey === 'useModel3Token') {
updateBalance['useModel3Count'] = b['useModel3Count'] + amount;
}
if (useKey === 'useModel4Token') {
updateBalance['useModel4Count'] = b['useModel4Count'] + amount;
}
if (useKey === 'useDrawMjToken') {
updateBalance['useDrawMjToken'] = b['useDrawMjToken'] + amount;
if (token === 'useModel3Token' || token === 'useModel4Token') {
updateBalance[token.replace('Token', 'Count')] =
(b[token.replace('Token', 'Count')] || 0) + amount;
}
const result = await this.userBalanceEntity.update({ userId }, updateBalance);
if (result.affected === 0) {
@ -282,10 +326,18 @@ let UserBalanceService = class UserBalanceService {
throw new common_1.HttpException('查询当前用户余额失败!', common_1.HttpStatus.BAD_REQUEST);
}
}
res.sumModel3Count = res.packageId ? res.model3Count + res.memberModel3Count : res.model3Count;
res.sumModel4Count = res.packageId ? res.model4Count + res.memberModel4Count : res.model4Count;
res.sumDrawMjCount = res.packageId ? res.drawMjCount + res.memberDrawMjCount : res.drawMjCount;
res.expirationTime = res.expirationTime ? (0, date_1.formatDate)(res.expirationTime, 'YYYY-MM-DD') : null;
res.sumModel3Count = res.packageId
? res.model3Count + res.memberModel3Count
: res.model3Count;
res.sumModel4Count = res.packageId
? res.model4Count + res.memberModel4Count
: res.model4Count;
res.sumDrawMjCount = res.packageId
? res.drawMjCount + res.memberDrawMjCount
: res.drawMjCount;
res.expirationTime = res.expirationTime
? (0, date_1.formatDate)(res.expirationTime, 'YYYY-MM-DD')
: null;
return res;
}
catch (error) {
@ -293,35 +345,53 @@ let UserBalanceService = class UserBalanceService {
}
}
async saveRecordRechargeLog(logInfo) {
const { userId, rechargeType, model3Count, model4Count, drawMjCount, days = -1, pkgName = '', extent = '' } = logInfo;
const { userId, rechargeType, model3Count, model4Count, drawMjCount, days = -1, pkgName = '', extent = '', } = logInfo;
if (!userId) {
throw new common_1.HttpException('当前用户不存在,记录充值日志异常', common_1.HttpStatus.BAD_REQUEST);
}
const uid = (0, utils_1.createRandomUid)();
return await this.accountLogEntity.save({ userId, rechargeType, model3Count, model4Count, drawMjCount, days, extent, uid, pkgName });
return await this.accountLogEntity.save({
userId,
rechargeType,
model3Count,
model4Count,
drawMjCount,
days,
extent,
uid,
pkgName,
});
}
async createBaseUserBalance(userId, userBalanceInfo = {}) {
const { model3Count = 0, model4Count = 0, drawMjCount = 0 } = userBalanceInfo;
const { model3Count = 0, model4Count = 0, drawMjCount = 0, } = userBalanceInfo;
const balance = await this.userBalanceEntity.findOne({ where: { userId } });
if (balance) {
throw new common_1.HttpException('当前用户无需创建账户信息!', common_1.HttpStatus.BAD_REQUEST);
}
return await this.userBalanceEntity.save({ userId, model3Count, model4Count, drawMjCount });
return await this.userBalanceEntity.save({
userId,
model3Count,
model4Count,
drawMjCount,
});
}
async addBalanceToUser(userId, balance, days = -1) {
try {
const userBalanceInfo = (await this.userBalanceEntity.findOne({ where: { userId } })) || (await this.createBaseUserBalance(userId));
const userBalanceInfo = (await this.userBalanceEntity.findOne({ where: { userId } })) ||
(await this.createBaseUserBalance(userId));
if (!userBalanceInfo) {
throw new common_1.HttpException('查询用户账户信息失败!', common_1.HttpStatus.BAD_REQUEST);
}
const { model3Count, model4Count, drawMjCount, memberModel3Count, memberModel4Count, memberDrawMjCount } = userBalanceInfo;
const { model3Count, model4Count, drawMjCount, memberModel3Count, memberModel4Count, memberDrawMjCount, } = userBalanceInfo;
let params = {};
if (days > 0) {
const { packageId } = balance;
if (!packageId) {
throw new common_1.HttpException('缺失当前套餐ID、充值失败', common_1.HttpStatus.BAD_REQUEST);
}
const pkgInfo = await this.cramiPackageEntity.findOne({ where: { id: packageId } });
const pkgInfo = await this.cramiPackageEntity.findOne({
where: { id: packageId },
});
if (!pkgInfo) {
throw new common_1.HttpException('当前套餐不存在!', common_1.HttpStatus.BAD_REQUEST);
}
@ -338,7 +408,9 @@ let UserBalanceService = class UserBalanceService {
};
}
else {
const curPackageInfo = await this.cramiPackageEntity.findOne({ where: { id: userBalanceInfo.packageId } });
const curPackageInfo = await this.cramiPackageEntity.findOne({
where: { id: userBalanceInfo.packageId },
});
if (weight >= curPackageInfo.weight) {
params = {
memberModel3Count: memberModel3Count + balance.model3Count,
@ -380,11 +452,13 @@ let UserBalanceService = class UserBalanceService {
console.log('充值的工单信息:', order);
try {
const { userId, goodsId } = order;
const pkg = await this.cramiPackageEntity.findOne({ where: { id: order.goodsId, status: 1 } });
const pkg = await this.cramiPackageEntity.findOne({
where: { id: order.goodsId, status: 1 },
});
if (!pkg) {
throw new common_1.HttpException('非法操作、当前充值套餐暂不存在!', common_1.HttpStatus.BAD_REQUEST);
}
const { model3Count, model4Count, drawMjCount, days, name: pkgName } = pkg;
const { model3Count, model4Count, drawMjCount, days, name: pkgName, } = pkg;
const money = {
model3Count,
model4Count,
@ -393,12 +467,24 @@ let UserBalanceService = class UserBalanceService {
packageId: order.goodsId,
};
await this.addBalanceToUser(userId, money, days);
await this.saveRecordRechargeLog({ userId, rechargeType: balance_constant_1.RechargeType.SCAN_PAY, model3Count, model4Count, drawMjCount, pkgName, days });
await this.saveRecordRechargeLog({
userId,
rechargeType: balance_constant_1.RechargeType.SCAN_PAY,
model3Count,
model4Count,
drawMjCount,
pkgName,
days,
});
const userInfo = await this.userEntity.findOne({ where: { id: userId } });
const { invitedBy } = userInfo;
if (invitedBy) {
const inviteUserInfo = await this.userEntity.findOne({ where: { inviteCode: invitedBy } });
const inviteUserSalesInfo = await this.salesUsersEntity.findOne({ where: { userId: inviteUserInfo.id } });
const inviteUserInfo = await this.userEntity.findOne({
where: { inviteCode: invitedBy },
});
const inviteUserSalesInfo = await this.salesUsersEntity.findOne({
where: { userId: inviteUserInfo.id },
});
if (!inviteUserInfo)
return;
const { id: inviterUserId } = inviteUserInfo;
@ -449,7 +535,9 @@ let UserBalanceService = class UserBalanceService {
take: size,
});
const userIds = rows.map((item) => item.userId);
const userInfo = await this.userEntity.find({ where: { id: (0, typeorm_2.In)(userIds) } });
const userInfo = await this.userEntity.find({
where: { id: (0, typeorm_2.In)(userIds) },
});
rows.forEach((item) => {
const user = userInfo.find((user) => user.id === item.userId);
item.username = user === null || user === void 0 ? void 0 : user.username;
@ -477,57 +565,6 @@ let UserBalanceService = class UserBalanceService {
async refundMjBalance(userId, amount) {
return await this.deductFromBalance(userId, 'mjDraw', -amount);
}
async upgradeBalance() {
const users = await this.userEntity.find();
if (!users.length)
return;
const upgradeStatus = await this.globalConfigService.getConfigs(['upgradeStatus']);
if (!upgradeStatus) {
await this.globalConfigService.setConfig({ settings: [{ configKey: 'upgradeStatus', configVal: '1' }] });
}
else {
throw new common_1.HttpException('您已经升级过了、请勿重复操作!', common_1.HttpStatus.BAD_REQUEST);
}
users.forEach((user) => {
const { id } = user;
this.balanceEntity.findOne({ where: { userId: id } }).then((res) => {
if (!res)
return;
this.writeOldBalanceToNewTable(id, res);
});
});
}
async writeOldBalanceToNewTable(userId, balanceInfo) {
const { balance = 0, usesLeft = 0, paintCount = 0, useTokens = 0, useChats = 0, usePaints = 0 } = balanceInfo;
const model4Info = await this.whiteListEntity.findOne({ where: { userId } });
const newBalanceInfo = {
userId,
model3Count: Number(usesLeft),
model4Count: (model4Info === null || model4Info === void 0 ? void 0 : model4Info.count) || 0,
drawMjCount: Number(balance),
useModel3Count: Number(useChats),
useModel4Count: (model4Info === null || model4Info === void 0 ? void 0 : model4Info.useCount) || 0,
useDrawMjCount: Number(usePaints),
useModel3Token: Number(useTokens),
useModel4Token: 0,
useDrawMjToken: 0,
};
const userBalanceInfo = await this.userBalanceEntity.findOne({ where: { userId } });
if (userBalanceInfo) {
common_1.Logger.debug(`用户${userId}账户信息已经存在、迁移无效`, 'BalanceService');
}
else {
this.userBalanceEntity
.save(newBalanceInfo)
.then((res) => {
common_1.Logger.debug(`用户${userId}旧账户信息迁移成功`, 'BalanceService');
})
.catch((error) => {
console.log('error: ', error);
common_1.Logger.debug(`用户${userId}旧账户信息迁移失败`, 'BalanceService');
});
}
}
async inheritVisitorData(req) {
const { fingerprint } = req.headers;
const { id: userId } = req.user;
@ -538,9 +575,15 @@ let UserBalanceService = class UserBalanceService {
}
async getVisitorCount(req) {
const { fingerprint } = req.headers;
const countChat = await this.chatLogEntity.count({ where: { userId: fingerprint } });
const countChatGroup = await this.chatGroupEntity.count({ where: { userId: fingerprint } });
const countMj = await this.midjourneyEntity.count({ where: { userId: fingerprint } });
const countChat = await this.chatLogEntity.count({
where: { userId: fingerprint },
});
const countChatGroup = await this.chatGroupEntity.count({
where: { userId: fingerprint },
});
const countMj = await this.midjourneyEntity.count({
where: { userId: fingerprint },
});
return countChat || countChatGroup || countMj || 0;
}
};
@ -553,11 +596,10 @@ UserBalanceService = __decorate([
__param(4, (0, typeorm_1.InjectRepository)(config_entity_1.ConfigEntity)),
__param(5, (0, typeorm_1.InjectRepository)(user_entity_1.UserEntity)),
__param(6, (0, typeorm_1.InjectRepository)(salesUsers_entity_1.SalesUsersEntity)),
__param(7, (0, typeorm_1.InjectRepository)(whiteList_entity_1.WhiteListEntity)),
__param(8, (0, typeorm_1.InjectRepository)(fingerprint_entity_1.FingerprintLogEntity)),
__param(9, (0, typeorm_1.InjectRepository)(chatGroup_entity_1.ChatGroupEntity)),
__param(10, (0, typeorm_1.InjectRepository)(chatLog_entity_1.ChatLogEntity)),
__param(11, (0, typeorm_1.InjectRepository)(midjourney_entity_1.MidjourneyEntity)),
__param(7, (0, typeorm_1.InjectRepository)(fingerprint_entity_1.FingerprintLogEntity)),
__param(8, (0, typeorm_1.InjectRepository)(chatGroup_entity_1.ChatGroupEntity)),
__param(9, (0, typeorm_1.InjectRepository)(chatLog_entity_1.ChatLogEntity)),
__param(10, (0, typeorm_1.InjectRepository)(midjourney_entity_1.MidjourneyEntity)),
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
@ -569,7 +611,6 @@ UserBalanceService = __decorate([
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
sales_service_1.SalesService,
globalConfig_service_1.GlobalConfigService])
], UserBalanceService);

View File

@ -1,10 +1,10 @@
{
"name": "99AI",
"version": "3.3.0",
"name": "99ai",
"version": "3.5.0",
"description": "",
"author": "",
"author": "vastxie",
"private": true,
"license": "UNLICENSED",
"license": "Apache-2.0",
"bin": "./dist/main.js",
"scripts": {
"start": "pm2 start pm2.conf.json",
@ -27,87 +27,89 @@
},
"dependencies": {
"@alicloud/pop-core": "^1.7.13",
"@dqbd/tiktoken": "^1.0.7",
"@keyv/redis": "^2.6.1",
"@dqbd/tiktoken": "^1.0.15",
"@keyv/redis": "^2.8.5",
"@nestjs/bull": "^0.6.3",
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0",
"@nestjs/jwt": "^10.0.3",
"@nestjs/common": "^9.4.3",
"@nestjs/config": "^3.2.2",
"@nestjs/core": "^9.4.3",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^9.0.3",
"@nestjs/platform-express": "^9.4.0",
"@nestjs/schedule": "^2.2.2",
"@nestjs/serve-static": "^4.0.0",
"@nestjs/swagger": "^6.2.1",
"@nestjs/platform-express": "^9.4.3",
"@nestjs/platform-socket.io": "^10.3.9",
"@nestjs/schedule": "^2.2.3",
"@nestjs/serve-static": "^4.0.2",
"@nestjs/swagger": "^6.3.0",
"@nestjs/typeorm": "^9.0.1",
"@types/cache-manager-redis-store": "^2.0.1",
"@nestjs/websockets": "^10.3.9",
"@types/cache-manager-redis-store": "^2.0.4",
"abort-controller": "^3.0.0",
"ali-oss": "^6.17.1",
"ali-oss": "^6.20.0",
"app-root-path": "^3.1.0",
"axios": "^1.4.0",
"axios": "^1.7.2",
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.2",
"bull": "^4.10.4",
"bull": "^4.14.0",
"cache-manager-redis-store": "^3.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"class-validator": "^0.14.1",
"compression": "^1.7.4",
"cos-nodejs-sdk-v5": "^2.11.19",
"css-inline": "^0.11.2",
"dayjs": "^1.11.7",
"cos-nodejs-sdk-v5": "^2.14.2",
"dayjs": "^1.11.11",
"decimal.js": "^10.4.3",
"dotenv": "^16.0.3",
"dotenv": "^16.4.5",
"eventsource": "^2.0.2",
"exceljs": "^4.3.0",
"express": "^4.18.2",
"exceljs": "^4.4.0",
"express": "^4.19.2",
"express-xml-bodyparser": "^0.3.0",
"form-data": "^4.0.0",
"guid-typescript": "^1.0.9",
"handlebars": "^4.7.8",
"hbs": "^4.2.0",
"image-size": "^1.1.1",
"ioredis": "^5.3.2",
"ioredis": "^5.4.1",
"isomorphic-fetch": "^3.0.0",
"javascript-obfuscator": "^4.0.2",
"jimp": "^0.22.7",
"jsonwebtoken": "^9.0.0",
"keyv": "^4.5.2",
"javascript-obfuscator": "^4.1.1",
"jimp": "^0.22.12",
"jsonwebtoken": "^9.0.2",
"keyv": "^4.5.4",
"lodash": "^4.17.21",
"microsoft-cognitiveservices-speech-sdk": "^1.36.0",
"mysql2": "^3.2.0",
"nestjs-config": "^1.4.10",
"microsoft-cognitiveservices-speech-sdk": "^1.38.0",
"mysql2": "^3.10.1",
"nestjs-config": "^1.4.11",
"nestjs-rate-limiter": "^3.1.0",
"nestjs-redis": "^1.3.3",
"node-fetch": "^3.3.1",
"nodemailer": "^6.9.12",
"node-fetch": "^3.3.2",
"nodemailer": "^6.9.14",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"redis": "^4.6.5",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.2.0",
"redis": "^4.6.14",
"reflect-metadata": "^0.1.14",
"rxjs": "^7.8.1",
"stream-to-buffer": "^0.1.0",
"svg-captcha": "^1.4.0",
"swagger-ui-express": "^4.6.2",
"typeorm": "^0.3.12",
"uuid": "^9.0.0",
"wechatpay-node-v3": "^2.1.5"
"swagger-ui-express": "^4.6.3",
"typeorm": "^0.3.20",
"uuid": "^9.0.1",
"wechatpay-node-v3": "^2.2.0"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@nestjs/cli": "^9.5.0",
"@nestjs/schematics": "^9.2.0",
"@nestjs/testing": "^9.4.3",
"@types/express": "^4.17.21",
"@types/jest": "29.2.4",
"@types/node": "18.11.18",
"@types/supertest": "^2.0.11",
"@types/supertest": "^2.0.16",
"jest": "29.3.1",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"prettier": "^2.8.8",
"source-map-support": "^0.5.21",
"supertest": "^6.3.4",
"ts-jest": "29.0.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "4.1.1",
"typescript": "^4.7.4"
"typescript": "^4.9.5"
},
"jest": {
"moduleFileExtensions": [

View File

@ -0,0 +1,8 @@
/**
* Fantastic-admin 提供技术支持
* Powered by Fantastic-admin
* https://fantastic-admin.github.io
*/
import{_ as f}from"./index-B-LUCRde.js";export{f as default};

Binary file not shown.

View File

@ -0,0 +1,8 @@
/**
* Fantastic-admin 提供技术支持
* Powered by Fantastic-admin
* https://fantastic-admin.github.io
*/
import{_ as m}from"./HCheckList.vue_vue_type_script_setup_true_lang-DNeoHT7d.js";import"./index-B-LUCRde.js";export{m as default};

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More