Compare commits
79 Commits
old
..
b650b1a108
| Author | SHA1 | Date | |
|---|---|---|---|
| b650b1a108 | |||
| efc5be5142 | |||
| 5c43bd7a3d | |||
| 30bbb33129 | |||
| 66e753e69b | |||
| 93fcaace26 | |||
| 97bb873bb8 | |||
| 723ceddc3d | |||
| be532bec1b | |||
| e788693713 | |||
| aaa6cb149c | |||
| 6a146f0898 | |||
| b9b0dc3bda | |||
| 4d39fd1b84 | |||
| bcf81ab683 | |||
| 7471fd8e3d | |||
| ac3bbaf7bf | |||
| 2d4bfe0330 | |||
| 602ecc31bc | |||
| b16ac2cb9b | |||
| 41423ca666 | |||
| e898e6afbe | |||
| 2e01ba0e3d | |||
| 25db7ea428 | |||
| e37ad50410 | |||
| c503e06c9c | |||
| 0992c2ad7b | |||
| e78b93d6fb | |||
| 79020ccea0 | |||
| 8a8ece76b1 | |||
| 0316345e9f | |||
| b56b1240f3 | |||
| 77b3af8015 | |||
| 634f43d644 | |||
| e5b4dc75d7 | |||
| 40b8c07036 | |||
| b261ddeeb1 | |||
| 62f07b7f6b | |||
| 31a2aa0e84 | |||
| 7965c33790 | |||
| fcae874fd2 | |||
| dad83339c1 | |||
| 84842ec3dd | |||
| 59bc008b69 | |||
| 8cb58ad91f | |||
| 7372302618 | |||
| cbf5a2b450 | |||
| 33f450cdbc | |||
| bce4c4e56e | |||
| b6cbcb3040 | |||
| fdbe3c75ee | |||
| bf13c56261 | |||
| 85343f3f82 | |||
| 51b493a10d | |||
| ae04e0d518 | |||
| 2b1ce740e1 | |||
| e620abcce6 | |||
| 7ea6fc226e | |||
| d5f4b04c6c | |||
| a0ca976e66 | |||
| 917732eeee | |||
| f0fbd9d208 | |||
| 2d07182bd6 | |||
| e0ae15355b | |||
| c0e0d03431 | |||
| bb5d6974fa | |||
| df7fcddb40 | |||
| 6c9d5fb39e | |||
| 4ecc5177ed | |||
| c11d46bdbf | |||
| 9b7a588997 | |||
| 0f40c63ea0 | |||
| 1d1d8c0e30 | |||
| 5d890fdfcc | |||
| 94e2f33db1 | |||
| a7d9deb9cd | |||
| 9f9e832e37 | |||
| a73a3f2313 | |||
| cc6ebc18e5 |
@@ -0,0 +1,231 @@
|
||||
name: Build docker and publish
|
||||
run-name: 简化的Docker构建和部署流程
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
env:
|
||||
# Docker镜像仓库
|
||||
REPO: ${{ vars.REPO || 'registry.kxsw.us/ppanel-server' }}
|
||||
# SSH连接信息
|
||||
SSH_HOST: ${{ vars.SSH_HOST }}
|
||||
SSH_PORT: ${{ vars.SSH_PORT }}
|
||||
SSH_USER: ${{ vars.SSH_USER }}
|
||||
SSH_PASSWORD: ${{ vars.SSH_PASSWORD }}
|
||||
# TG通知
|
||||
TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0
|
||||
TG_CHAT_ID: "-4940243803"
|
||||
# Go构建变量
|
||||
SERVICE: ppanel
|
||||
SERVICE_STYLE: ppanel
|
||||
VERSION: ${{ github.sha }}
|
||||
BUILDTIME: ${{ github.event.head_commit.timestamp }}
|
||||
GOARCH: amd64
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ppanel-server
|
||||
container:
|
||||
image: node:20
|
||||
strategy:
|
||||
matrix:
|
||||
# 只有node支持版本号别名
|
||||
node: ['20.15.1']
|
||||
steps:
|
||||
# 步骤1: 下载代码
|
||||
- name: 📥 下载代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# 步骤2: 设置动态环境变量
|
||||
- name: ⚙️ 设置动态环境变量
|
||||
run: |
|
||||
if [ "${{ github.ref_name }}" = "main" ]; then
|
||||
echo "DOCKER_TAG_SUFFIX=latest" >> $GITHUB_ENV
|
||||
echo "CONTAINER_NAME=ppanel-server" >> $GITHUB_ENV
|
||||
echo "DEPLOY_PATH=/root/vpn_server" >> $GITHUB_ENV
|
||||
echo "为 main 分支设置生产环境变量"
|
||||
elif [ "${{ github.ref_name }}" = "dev" ]; then
|
||||
echo "DOCKER_TAG_SUFFIX=dev" >> $GITHUB_ENV
|
||||
echo "CONTAINER_NAME=ppanel-server-dev" >> $GITHUB_ENV
|
||||
echo "DEPLOY_PATH=/root/vpn_server_dev" >> $GITHUB_ENV
|
||||
echo "为 dev 分支设置开发环境变量"
|
||||
else
|
||||
echo "DOCKER_TAG_SUFFIX=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "CONTAINER_NAME=ppanel-server-${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "DEPLOY_PATH=/root/vpn_server_other" >> $GITHUB_ENV
|
||||
echo "为其他分支 (${{ github.ref_name }}) 设置环境变量"
|
||||
fi
|
||||
|
||||
# 步骤3: 安装系统工具 (Docker, curl, jq)
|
||||
- name: 🔧 安装系统工具 (Docker, curl, jq)
|
||||
run: |
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
echo "等待 apt/dpkg 锁释放 (unattended-upgrades)..."
|
||||
# 等待最多 300 秒让 unattended-upgrades/apt/dpkg 锁释放
|
||||
end=$((SECONDS+300))
|
||||
while true; do
|
||||
LOCKS_BUSY=0
|
||||
# 如果 unattended-upgrades 正在运行,标记为忙碌
|
||||
if pgrep -x unattended-upgrades >/dev/null 2>&1; then LOCKS_BUSY=1; fi
|
||||
# 如果 fuser 存在,检查常见的锁文件
|
||||
if command -v fuser >/dev/null 2>&1; then
|
||||
if fuser /var/lib/dpkg/lock >/dev/null 2>&1 \
|
||||
|| fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \
|
||||
|| fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then
|
||||
LOCKS_BUSY=1
|
||||
fi
|
||||
fi
|
||||
# 如果不忙碌则跳出循环
|
||||
if [ "$LOCKS_BUSY" -eq 0 ]; then break; fi
|
||||
# 超时后约 5 分钟
|
||||
if [ $SECONDS -ge $end ]; then
|
||||
echo "等待 apt/dpkg 锁超时,使用 Dpkg::Lock::Timeout 继续..."
|
||||
break
|
||||
fi
|
||||
echo "仍在等待锁释放..."; sleep 5
|
||||
done
|
||||
apt-get update -y -o Dpkg::Lock::Timeout=600
|
||||
apt-get install -y -o Dpkg::Lock::Timeout=600 jq curl ca-certificates docker.io
|
||||
docker --version
|
||||
jq --version
|
||||
curl --version
|
||||
|
||||
# 步骤4: 构建并发布到镜像仓库
|
||||
- name: 📤 构建并发布到镜像仓库
|
||||
run: |
|
||||
echo "开始构建并推送镜像..."
|
||||
echo "仓库: ${{ env.REPO }}"
|
||||
echo "版本标签: ${{ env.VERSION }}"
|
||||
echo "分支标签: ${{ env.DOCKER_TAG_SUFFIX }}"
|
||||
|
||||
# 构建镜像,同时打上版本和分支两个标签
|
||||
docker build -f Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
--build-arg TARGETARCH=amd64 \
|
||||
--build-arg VERSION=${{ env.VERSION }} \
|
||||
--build-arg BUILDTIME=${{ env.BUILDTIME }} \
|
||||
-t ${{ env.REPO }}:${{ env.VERSION }} \
|
||||
-t ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} \
|
||||
.
|
||||
|
||||
echo "推送版本标签镜像: ${{ env.REPO }}:${{ env.VERSION }}"
|
||||
docker push ${{ env.REPO }}:${{ env.VERSION }}
|
||||
|
||||
echo "推送分支标签镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}"
|
||||
docker push ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
|
||||
|
||||
echo "镜像推送完成"
|
||||
|
||||
# 步骤5: 连接服务器拉镜像启动
|
||||
- name: 🚀 连接服务器拉镜像启动
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ env.SSH_HOST }}
|
||||
username: ${{ env.SSH_USER }}
|
||||
password: ${{ env.SSH_PASSWORD }}
|
||||
port: ${{ env.SSH_PORT }}
|
||||
timeout: 300s
|
||||
command_timeout: 600s
|
||||
script: |
|
||||
echo "连接服务器成功,开始部署..."
|
||||
echo "部署容器名: ${{ env.CONTAINER_NAME }}"
|
||||
echo "部署路径: ${{ env.DEPLOY_PATH }}"
|
||||
echo "部署镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}"
|
||||
|
||||
# 确保部署目录存在
|
||||
mkdir -p ${{ env.DEPLOY_PATH }}/config
|
||||
mkdir -p ${{ env.DEPLOY_PATH }}/logs
|
||||
|
||||
# 停止并删除旧容器(忽略所有错误)
|
||||
if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then
|
||||
echo "停止旧容器..."
|
||||
docker stop ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
|
||||
echo "等待容器完全停止..."
|
||||
sleep 5
|
||||
|
||||
echo "删除旧容器..."
|
||||
# 静默删除,完全忽略错误输出
|
||||
docker rm ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
|
||||
sleep 2
|
||||
|
||||
# 如果仍然存在,尝试强制删除(静默)
|
||||
if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then
|
||||
echo "尝试强制删除..."
|
||||
docker rm -f ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
echo "容器清理完成,继续部署..."
|
||||
fi
|
||||
|
||||
# 拉取最新分支镜像
|
||||
echo "拉取镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}..."
|
||||
docker pull ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
|
||||
|
||||
# 启动新容器
|
||||
echo "启动新容器..."
|
||||
cd ${{ env.DEPLOY_PATH }}
|
||||
docker run -d \
|
||||
--name ${{ env.CONTAINER_NAME }} \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
-v ./config/ppanel.yaml:/app/etc/ppanel.yaml \
|
||||
-v ./logs:/app/logs \
|
||||
${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}
|
||||
|
||||
# 检查容器状态
|
||||
sleep 5
|
||||
if docker ps | grep -q ${{ env.CONTAINER_NAME }}; then
|
||||
echo "✅ 容器启动成功"
|
||||
else
|
||||
echo "❌ 容器启动失败"
|
||||
docker logs ${{ env.CONTAINER_NAME }}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 步骤6: TG通知 (成功)
|
||||
- name: 📱 发送成功通知到Telegram
|
||||
if: success()
|
||||
uses: appleboy/telegram-action@master
|
||||
with:
|
||||
token: ${{ env.TG_BOT_TOKEN }}
|
||||
to: ${{ env.TG_CHAT_ID }}
|
||||
message: |
|
||||
✅ 部署成功!
|
||||
|
||||
📦 项目: ${{ github.repository }}
|
||||
🌿 分支: ${{ github.ref_name }}
|
||||
📝 提交: ${{ github.sha }}
|
||||
👤 提交者: ${{ github.actor }}
|
||||
🕐 时间: ${{ github.event.head_commit.timestamp }}
|
||||
|
||||
🚀 服务已成功部署到生产环境
|
||||
parse_mode: Markdown
|
||||
|
||||
# 步骤5: TG通知 (失败)
|
||||
- name: 📱 发送失败通知到Telegram
|
||||
if: failure()
|
||||
uses: appleboy/telegram-action@master
|
||||
with:
|
||||
token: ${{ env.TG_BOT_TOKEN }}
|
||||
to: ${{ env.TG_CHAT_ID }}
|
||||
message: |
|
||||
❌ 部署失败!
|
||||
|
||||
📦 项目: ${{ github.repository }}
|
||||
🌿 分支: ${{ github.ref_name }}
|
||||
📝 提交: ${{ github.sha }}
|
||||
👤 提交者: ${{ github.actor }}
|
||||
🕐 时间: ${{ github.event.head_commit.timestamp }}
|
||||
|
||||
⚠️ 请检查构建日志获取详细信息
|
||||
parse_mode: Markdown
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop"]
|
||||
pull_request:
|
||||
branches: ["develop"]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Get short Git commit ID
|
||||
id: vars
|
||||
run: echo "COMMIT_ID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
|
||||
|
||||
- name: Build Docker image
|
||||
run: docker build --build-arg VERSION=${{ env.COMMIT_ID }} -t ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }} .
|
||||
|
||||
- name: Push Docker image
|
||||
run: docker push ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
|
||||
|
||||
# - name: Deploy to server
|
||||
# uses: appleboy/ssh-action@v0.1.6
|
||||
# with:
|
||||
# host: ${{ secrets.SSH_HOST }}
|
||||
# username: ${{ secrets.SSH_USER }}
|
||||
# key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
# script: |
|
||||
# if [ $(docker ps -a -q -f name=ppanel-server-dev) ]; then
|
||||
# echo "Stopping and removing existing ppanel-server container..."
|
||||
# docker stop ppanel-server-dev
|
||||
# docker rm ppanel-server-dev
|
||||
# else
|
||||
# echo "No existing ppanel-server-dev container running."
|
||||
# fi
|
||||
#
|
||||
# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
# docker run -d --restart=always --log-driver=journald --name ppanel-server-dev -p 8080:8080 -v /www/wwwroot/api/etc:/app/etc -v /www/wwwroot/api/logs:/app/logs --restart=always -d ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
|
||||
#
|
||||
@@ -1,131 +0,0 @@
|
||||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
IMAGE_NAME: ppanel-server
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract version from git tag
|
||||
id: version
|
||||
run: echo "VERSION=$(git describe --tags --abbrev=0 | sed 's/^v//')" >> $GITHUB_ENV
|
||||
|
||||
- name: Get short SHA
|
||||
id: sha
|
||||
run: echo "GIT_SHA=${GITHUB_SHA::8}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set BUILD_TIME env
|
||||
run: echo BUILD_TIME=$(date --iso-8601=seconds) >> ${GITHUB_ENV}
|
||||
|
||||
|
||||
- name: Build and push Docker image for main release
|
||||
if: "!contains(github.ref_name, 'beta')"
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
build-args: |
|
||||
VERSION=${{ env.VERSION }}
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.GIT_SHA }}
|
||||
|
||||
- name: Build and push Docker image for beta release
|
||||
if: contains(github.ref_name, 'beta')
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
build-args: |
|
||||
VERSION=${{ env.VERSION }}
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:beta
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.GIT_SHA }}
|
||||
|
||||
release-notes:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Install GoReleaser
|
||||
run: |
|
||||
go install github.com/goreleaser/goreleaser/v2@latest
|
||||
|
||||
- name: Run GoReleaser
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
goreleaser check
|
||||
goreleaser release --clean
|
||||
|
||||
releases-matrix:
|
||||
name: Release ppanel-server binary
|
||||
runs-on: ubuntu-latest
|
||||
needs: release-notes # wait for release-notes job to finish
|
||||
strategy:
|
||||
matrix:
|
||||
# build and publish in parallel: linux/386, linux/amd64, linux/arm64,
|
||||
# windows/386, windows/amd64, windows/arm64, darwin/amd64, darwin/arm64
|
||||
goos: [ linux, windows, darwin ]
|
||||
goarch: [ '386', amd64, arm64 ]
|
||||
exclude:
|
||||
- goarch: '386'
|
||||
goos: darwin
|
||||
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Extract version from git tag
|
||||
id: version
|
||||
run: echo "VERSION=$(git describe --tags --abbrev=0 | sed 's/^v//')" >> $GITHUB_ENV
|
||||
|
||||
- name: Set BUILD_TIME env
|
||||
run: echo BUILD_TIME=$(date --iso-8601=seconds) >> ${GITHUB_ENV}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: wangyoucao577/go-release-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
goos: ${{ matrix.goos }}
|
||||
goarch: ${{ matrix.goarch }}
|
||||
asset_name: "ppanel-server-${{ matrix.goos }}-${{ matrix.goarch }}"
|
||||
goversion: "https://dl.google.com/go/go1.23.3.linux-amd64.tar.gz"
|
||||
project_path: "."
|
||||
binary_name: "ppanel-server"
|
||||
extra_files: LICENSE etc
|
||||
ldflags: -X "github.com/perfect-panel/server/pkg/constant.Version=${{env.VERSION}}" -X "github.com/perfect-panel/server/pkg/constant.BuildTime=${{env.BUILD_TIME}}"
|
||||
@@ -1,81 +0,0 @@
|
||||
name: Go CI/CD with goctl and Swagger
|
||||
|
||||
on:
|
||||
# release:
|
||||
# types: [published]
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install goctl
|
||||
run: |
|
||||
curl -L https://github.com/zeromicro/go-zero/releases/download/tools%2Fgoctl%2Fv1.7.2/goctl-v1.7.2-linux-amd64.tar.gz -o goctl-v1.7.2-linux-amd64.tar.gz
|
||||
tar -xvzf goctl-v1.7.2-linux-amd64.tar.gz
|
||||
chmod +x goctl
|
||||
sudo mv goctl /usr/local/bin/goctl
|
||||
goctl --version
|
||||
|
||||
- name: Install goctl-swagger
|
||||
run: |
|
||||
curl -L https://github.com/tensionc/goctl-swagger/releases/download/v1.0.1/goctl-swagger-v1.0.1-linux-amd64.tar.gz -o goctl-swagger.tar.gz
|
||||
tar -xvzf goctl-swagger.tar.gz
|
||||
chmod +x goctl-swagger
|
||||
sudo mv goctl-swagger /usr/local/bin/
|
||||
|
||||
- name: Generate Swagger file
|
||||
run: |
|
||||
mkdir -p swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename common.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_common.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename user.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_user.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename admin.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_admin.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename ppanel.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ppanel.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename node.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_node.api -dir ./swagger
|
||||
|
||||
|
||||
- name: Verify Swagger file
|
||||
run: |
|
||||
test -f ./swagger/common.json
|
||||
test -f ./swagger/user.json
|
||||
test -f ./swagger/admin.json
|
||||
|
||||
- name: Checkout target repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: perfect-panel/ppanel-docs
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: ppanel-docs
|
||||
persist-credentials: true
|
||||
|
||||
- name: Verify or create public/swagger directory
|
||||
run: |
|
||||
mkdir -p ./ppanel-docs/public/swagger
|
||||
|
||||
- name: Copy Swagger files
|
||||
run: |
|
||||
cp -rf swagger/* ppanel-docs/public/swagger
|
||||
cd ppanel-docs
|
||||
|
||||
- name: Check for file changes
|
||||
run: |
|
||||
cd ppanel-docs
|
||||
git add .
|
||||
git status
|
||||
if [ "$(git status --porcelain)" ]; then
|
||||
echo "Changes detected in the doc repository."
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "actions@ppanel.dev"
|
||||
git commit -m "Update Swagger files"
|
||||
git push
|
||||
else
|
||||
echo "No changes detected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
*-dev.yaml
|
||||
*.local.yaml
|
||||
/test/
|
||||
*.log
|
||||
.DS_Store
|
||||
*_test_config.go
|
||||
*.log*
|
||||
/build/
|
||||
*.p8
|
||||
*.crt
|
||||
|
||||
+5
-3
@@ -20,16 +20,17 @@ RUN go mod download
|
||||
COPY . .
|
||||
|
||||
# Build the binary with version and build time
|
||||
RUN BUILD_TIME=$(date -u +"%Y-%m-%d %H:%M:%S") && \
|
||||
RUN BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") && \
|
||||
go build -ldflags="-s -w -X 'github.com/perfect-panel/server/pkg/constant.Version=${VERSION}' -X 'github.com/perfect-panel/server/pkg/constant.BuildTime=${BUILD_TIME}'" -o /app/ppanel ppanel.go
|
||||
|
||||
# Final minimal image
|
||||
FROM scratch
|
||||
FROM alpine:latest
|
||||
|
||||
# Copy CA certificates and timezone data
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
|
||||
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
# Set Shanghai timezone
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
# Set working directory and copy binary
|
||||
@@ -37,6 +38,7 @@ WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/ppanel /app/ppanel
|
||||
COPY --from=builder /build/etc /app/etc
|
||||
COPY --from=builder /build/logs /app/logs
|
||||
|
||||
# Expose the port (optional)
|
||||
EXPOSE 8080
|
||||
|
||||
@@ -1,84 +1,73 @@
|
||||
NAME="ppanel-server"
|
||||
BINDIR=bin
|
||||
VERSION=$(shell git describe --tags || echo "unknown version")
|
||||
BUILDTIME=$(shell date -u)
|
||||
# Custom configuration | 独立配置
|
||||
# Service name | 项目名称
|
||||
SERVICE=ppanel
|
||||
# Service name in specific style | 项目经过style格式化的名称
|
||||
SERVICE_STYLE=ppanel
|
||||
|
||||
# Service name in lowercase | 项目名称全小写格式
|
||||
SERVICE_LOWER=ppanel
|
||||
# Service name in snake format | 项目名称下划线格式
|
||||
SERVICE_SNAKE=ppanel
|
||||
# Service name in snake format | 项目名称短杠格式
|
||||
SERVICE_DASH=ppanel
|
||||
|
||||
# The project version, if you don't use git, you should set it manually | 项目版本,如果不使用git请手动设置
|
||||
VERSION=$(shell git describe --tags --always)
|
||||
# Build time | 构建时间
|
||||
BUILDTIME=$(shell date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# The project file name style | 项目文件命名风格
|
||||
PROJECT_STYLE=go_zero
|
||||
|
||||
# Whether to use i18n | 是否启用 i18n
|
||||
PROJECT_I18N=true
|
||||
|
||||
# The suffix after build or compile | 构建后缀
|
||||
PROJECT_BUILD_SUFFIX=api
|
||||
|
||||
|
||||
# The arch of the build | 构建的架构
|
||||
GOARCH=amd64
|
||||
|
||||
# The repository of docker | Docker 仓库地址
|
||||
DOCKER_REPO=docker.i.on ticcheck
|
||||
|
||||
# ---- You may not need to modify the codes below | 下面的代码大概率不需要更改 ----
|
||||
|
||||
GO ?= go
|
||||
GOFMT ?= gofmt "-s"
|
||||
GOFILES := $(shell find . -name "*.go")
|
||||
LDFLAGS := -s -w
|
||||
|
||||
# Build command with version injection | 带版本信息注入的构建命令
|
||||
GOBUILD=CGO_ENABLED=0 go build -trimpath -ldflags '-X "github.com/perfect-panel/server/pkg/constant.Version=$(VERSION)" \
|
||||
-X "github.com/perfect-panel/server/pkg/constant.BuildTime=$(BUILDTIME)" \
|
||||
-w -s -buildid='
|
||||
|
||||
PLATFORM_LIST = \
|
||||
darwin-amd64 \
|
||||
darwin-amd64-v3 \
|
||||
darwin-arm64 \
|
||||
linux-386 \
|
||||
linux-amd64 \
|
||||
linux-amd64-v3 \
|
||||
linux-armv5 \
|
||||
linux-armv6 \
|
||||
linux-armv7 \
|
||||
linux-arm64 \
|
||||
.PHONY: docker
|
||||
docker: # Build the docker image | 构建 docker 镜像
|
||||
docker build -f Dockerfile -t ${API_IMAGE_NAME}:${VERSION} .
|
||||
@echo "Build docker successfully"
|
||||
|
||||
WINDOWS_ARCH_LIST = \
|
||||
windows-386 \
|
||||
windows-amd64 \
|
||||
windows-amd64-v3 \
|
||||
windows-arm64 \
|
||||
windows-armv7
|
||||
.PHONY: publish-docker
|
||||
publish-docker: # Publish docker image | 发布 docker 镜像
|
||||
docker tag ${API_IMAGE_NAME}:${VERSION} ${API_IMAGE_NAME}:latest
|
||||
docker push ${API_IMAGE_NAME}:latest
|
||||
@echo "Publish docker successfully"
|
||||
|
||||
all: linux-amd64 darwin-amd64 windows-amd64 # Most used
|
||||
|
||||
darwin-amd64:
|
||||
GOARCH=amd64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
darwin-amd64-v3:
|
||||
GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
darwin-arm64:
|
||||
GOARCH=arm64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-386:
|
||||
GOARCH=386 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-amd64:
|
||||
GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-amd64-v3:
|
||||
GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-armv5:
|
||||
GOARCH=arm GOOS=linux GOARM=5 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-armv6:
|
||||
GOARCH=arm GOOS=linux GOARM=6 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-armv7:
|
||||
GOARCH=arm GOOS=linux GOARM=7 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
linux-arm64:
|
||||
GOARCH=arm64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
|
||||
|
||||
windows-386:
|
||||
GOARCH=386 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
|
||||
|
||||
windows-amd64:
|
||||
GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
|
||||
|
||||
windows-amd64-v3:
|
||||
GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
|
||||
|
||||
windows-arm64:
|
||||
GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
|
||||
|
||||
windows-armv7:
|
||||
GOARCH=arm GOOS=windows GOARM=7 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
|
||||
.PHONY: docker-run
|
||||
docker-run: # Publish docker image | 发布 docker 镜像
|
||||
docker rm -f ${API_CONTAINER_NAME}
|
||||
@echo "pwd: $(pwd)"
|
||||
docker compose -p ${DOCKER_PROJECT_NAME} -f ${DOCKER_COMPOSE_FILE} up -d
|
||||
@echo "docker run successfully"
|
||||
|
||||
|
||||
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
|
||||
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))
|
||||
.PHONY: build-linux
|
||||
build-linux: # Build project for Linux | 构建Linux下的可执行文件
|
||||
GOOS=linux GOARCH=$(GOARCH) $(GOBUILD) -o /app/ppanel $(SERVICE_STYLE).go
|
||||
@echo "Build project for Linux successfully"
|
||||
|
||||
$(gz_releases): %.gz : %
|
||||
chmod +x $(BINDIR)/$(NAME)-$(basename $@)
|
||||
gzip -f -S -$(VERSION).gz $(BINDIR)/$(NAME)-$(basename $@)
|
||||
|
||||
$(zip_releases): %.zip : %
|
||||
zip -m -j $(BINDIR)/$(NAME)-$(basename $@)-$(VERSION).zip $(BINDIR)/$(NAME)-$(basename $@).exe
|
||||
.PHONY: help
|
||||
help: # Show help | 显示帮助
|
||||
@grep kfile | sort | while read-r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done
|
||||
|
||||
@@ -14,19 +14,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
> **Article 1.**
|
||||
> All human beings are born free and equal in dignity and rights.
|
||||
> They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.
|
||||
>
|
||||
> **Article 12.**
|
||||
> No one shall be subjected to arbitrary interference with his privacy, family, home or correspondence, nor to attacks upon his honour and reputation.
|
||||
> Everyone has the right to the protection of the law against such interference or attacks.
|
||||
>
|
||||
> **Article 19.**
|
||||
> Everyone has the right to freedom of opinion and expression; this right includes freedom to hold opinions without interference and to seek, receive and impart information and ideas through any media and regardless of frontiers.
|
||||
>
|
||||
> *Source: [United Nations – Universal Declaration of Human Rights (UN.org)](https://www.un.org/sites/un2.un.org/files/2021/03/udhr.pdf)*
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
PPanel Server is the backend component of the PPanel project, providing robust APIs and core functionality for managing
|
||||
@@ -113,9 +100,9 @@ proxy services. Built with Go, it emphasizes performance, security, and scalabil
|
||||
```
|
||||
|
||||
4. **Pull from Docker Hub** (after CI/CD publishes):
|
||||
```bash
|
||||
docker pull ppanel/ppanel-server:latest
|
||||
docker run --rm -p 8080:8080 ppanel/ppanel-server:latest
|
||||
```bashw
|
||||
docker pull yourusername/ppanel-server:latest
|
||||
docker run --rm -p 8080:8080 yourusername/ppanel-server:latest
|
||||
```
|
||||
|
||||
## 📖 API Documentation
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type Adapter struct {
|
||||
SiteName string // 站点名称
|
||||
Servers []*node.Node // 服务器列表
|
||||
UserInfo User // 用户信息
|
||||
ClientTemplate string // 客户端配置模板
|
||||
OutputFormat string // 输出格式,默认是 base64
|
||||
SubscribeName string // 订阅名称
|
||||
}
|
||||
|
||||
type Option func(*Adapter)
|
||||
|
||||
// WithServers 设置服务器列表
|
||||
func WithServers(servers []*node.Node) Option {
|
||||
return func(opts *Adapter) {
|
||||
opts.Servers = servers
|
||||
}
|
||||
}
|
||||
|
||||
// WithUserInfo 设置用户信息
|
||||
func WithUserInfo(user User) Option {
|
||||
return func(opts *Adapter) {
|
||||
opts.UserInfo = user
|
||||
}
|
||||
}
|
||||
|
||||
// WithOutputFormat 设置输出格式
|
||||
func WithOutputFormat(format string) Option {
|
||||
return func(opts *Adapter) {
|
||||
opts.OutputFormat = format
|
||||
}
|
||||
}
|
||||
|
||||
// WithSiteName 设置站点名称
|
||||
func WithSiteName(name string) Option {
|
||||
return func(opts *Adapter) {
|
||||
opts.SiteName = name
|
||||
}
|
||||
}
|
||||
|
||||
// WithSubscribeName 设置订阅名称
|
||||
func WithSubscribeName(name string) Option {
|
||||
return func(opts *Adapter) {
|
||||
opts.SubscribeName = name
|
||||
}
|
||||
}
|
||||
|
||||
func NewAdapter(tpl string, opts ...Option) *Adapter {
|
||||
adapter := &Adapter{
|
||||
Servers: []*node.Node{},
|
||||
UserInfo: User{},
|
||||
ClientTemplate: tpl,
|
||||
OutputFormat: "base64", // 默认输出格式
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(adapter)
|
||||
}
|
||||
|
||||
return adapter
|
||||
}
|
||||
|
||||
func (adapter *Adapter) Client() (*Client, error) {
|
||||
client := &Client{
|
||||
SiteName: adapter.SiteName,
|
||||
SubscribeName: adapter.SubscribeName,
|
||||
ClientTemplate: adapter.ClientTemplate,
|
||||
OutputFormat: adapter.OutputFormat,
|
||||
Proxies: []Proxy{},
|
||||
UserInfo: adapter.UserInfo,
|
||||
}
|
||||
|
||||
proxies, err := adapter.Proxies(adapter.Servers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.Proxies = proxies
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (adapter *Adapter) Proxies(servers []*node.Node) ([]Proxy, error) {
|
||||
var proxies []Proxy
|
||||
|
||||
for _, item := range servers {
|
||||
if item.Server == nil {
|
||||
logger.Errorf("[Adapter] Server is nil for node ID: %d", item.Id)
|
||||
continue
|
||||
}
|
||||
protocols, err := item.Server.UnmarshalProtocols()
|
||||
if err != nil {
|
||||
logger.Errorf("[Adapter] Unmarshal Protocols error: %s; server id : %d", err.Error(), item.ServerId)
|
||||
continue
|
||||
}
|
||||
for _, protocol := range protocols {
|
||||
if protocol.Type == item.Protocol {
|
||||
proxies = append(proxies, Proxy{
|
||||
Sort: item.Sort,
|
||||
Name: item.Name,
|
||||
Server: item.Address,
|
||||
Port: item.Port,
|
||||
Type: item.Protocol,
|
||||
Tags: strings.Split(item.Tags, ","),
|
||||
Security: protocol.Security,
|
||||
SNI: protocol.SNI,
|
||||
AllowInsecure: protocol.AllowInsecure,
|
||||
Fingerprint: protocol.Fingerprint,
|
||||
RealityServerAddr: protocol.RealityServerAddr,
|
||||
RealityServerPort: protocol.RealityServerPort,
|
||||
RealityPrivateKey: protocol.RealityPrivateKey,
|
||||
RealityPublicKey: protocol.RealityPublicKey,
|
||||
RealityShortId: protocol.RealityShortId,
|
||||
Transport: protocol.Transport,
|
||||
Host: protocol.Host,
|
||||
Path: protocol.Path,
|
||||
ServiceName: protocol.ServiceName,
|
||||
Method: protocol.Cipher,
|
||||
ServerKey: protocol.ServerKey,
|
||||
Flow: protocol.Flow,
|
||||
HopPorts: protocol.HopPorts,
|
||||
HopInterval: protocol.HopInterval,
|
||||
ObfsPassword: protocol.ObfsPassword,
|
||||
UpMbps: protocol.UpMbps,
|
||||
DownMbps: protocol.DownMbps,
|
||||
DisableSNI: protocol.DisableSNI,
|
||||
ReduceRtt: protocol.ReduceRtt,
|
||||
UDPRelayMode: protocol.UDPRelayMode,
|
||||
CongestionController: protocol.CongestionController,
|
||||
PaddingScheme: protocol.PaddingScheme,
|
||||
Multiplex: protocol.Multiplex,
|
||||
XhttpMode: protocol.XhttpMode,
|
||||
XhttpExtra: protocol.XhttpExtra,
|
||||
Encryption: protocol.Encryption,
|
||||
EncryptionMode: protocol.EncryptionMode,
|
||||
EncryptionRtt: protocol.EncryptionRtt,
|
||||
EncryptionTicket: protocol.EncryptionTicket,
|
||||
EncryptionServerPadding: protocol.EncryptionServerPadding,
|
||||
EncryptionPrivateKey: protocol.EncryptionPrivateKey,
|
||||
EncryptionClientPadding: protocol.EncryptionClientPadding,
|
||||
EncryptionPassword: protocol.EncryptionPassword,
|
||||
Ratio: protocol.Ratio,
|
||||
CertMode: protocol.CertMode,
|
||||
CertDNSProvider: protocol.CertDNSProvider,
|
||||
CertDNSEnv: protocol.CertDNSEnv,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAdapter_Client(t *testing.T) {
|
||||
servers := getServers()
|
||||
if len(servers) == 0 {
|
||||
t.Errorf("[Test] No servers found")
|
||||
return
|
||||
}
|
||||
a := NewAdapter(tpl, WithServers(servers), WithUserInfo(User{
|
||||
Password: "test-password",
|
||||
ExpiredAt: time.Now().AddDate(1, 0, 0),
|
||||
Download: 0,
|
||||
Upload: 0,
|
||||
Traffic: 1000,
|
||||
SubscribeURL: "https://example.com/subscribe",
|
||||
}))
|
||||
client, err := a.Client()
|
||||
if err != nil {
|
||||
t.Errorf("[Test] Failed to get client: %v", err.Error())
|
||||
return
|
||||
}
|
||||
bytes, err := client.Build()
|
||||
if err != nil {
|
||||
t.Errorf("[Test] Failed to build client config: %v", err.Error())
|
||||
return
|
||||
}
|
||||
t.Logf("[Test] Client config built successfully: %s", string(bytes))
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
)
|
||||
|
||||
type Proxy struct {
|
||||
Sort int
|
||||
Name string
|
||||
Server string
|
||||
Port uint16
|
||||
Type string
|
||||
Tags []string
|
||||
|
||||
// Security Options
|
||||
Security string
|
||||
SNI string // Server Name Indication for TLS
|
||||
AllowInsecure bool // Allow insecure connections (skip certificate verification)
|
||||
Fingerprint string // Client fingerprint for TLS connections
|
||||
RealityServerAddr string // Reality server address
|
||||
RealityServerPort int // Reality server port
|
||||
RealityPrivateKey string // Reality private key for authentication
|
||||
RealityPublicKey string // Reality public key for authentication
|
||||
RealityShortId string // Reality short ID for authentication
|
||||
// Transport Options
|
||||
Transport string // Transport protocol (e.g., ws, http, grpc)
|
||||
Host string // For WebSocket/HTTP/HTTPS
|
||||
Path string // For HTTP/HTTPS
|
||||
ServiceName string // For gRPC
|
||||
// Shadowsocks Options
|
||||
Method string
|
||||
ServerKey string // For Shadowsocks 2022
|
||||
|
||||
// Vmess/Vless/Trojan Options
|
||||
Flow string // Flow for Vmess/Vless/Trojan
|
||||
// Hysteria2 Options
|
||||
HopPorts string // Comma-separated list of hop ports
|
||||
HopInterval int // Interval for hop ports in seconds
|
||||
ObfsPassword string // Obfuscation password for Hysteria2
|
||||
UpMbps int // Upload speed in Mbps
|
||||
DownMbps int // Download speed in Mbps
|
||||
|
||||
// Tuic Options
|
||||
DisableSNI bool // Disable SNI
|
||||
ReduceRtt bool // Reduce RTT
|
||||
UDPRelayMode string // UDP relay mode (e.g., "full", "partial")
|
||||
CongestionController string // Congestion controller (e.g., "cubic", "bbr")
|
||||
|
||||
// AnyTLS
|
||||
PaddingScheme string
|
||||
|
||||
// Mieru
|
||||
Multiplex string
|
||||
|
||||
// Obfs
|
||||
//Obfs string // obfs, 'none', 'http', 'tls'
|
||||
//ObfsHost string // obfs host
|
||||
//ObfsPath string // obfs path
|
||||
|
||||
// Vless
|
||||
XhttpMode string // xhttp mode
|
||||
XhttpExtra string // xhttp path
|
||||
|
||||
// encryption
|
||||
Encryption string // encryption,'none', 'mlkem768x25519plus'
|
||||
EncryptionMode string // encryption mode,'native', 'xorpub', 'random'
|
||||
EncryptionRtt string // encryption rtt,'0rtt', '1rtt'
|
||||
EncryptionTicket string // encryption ticket
|
||||
EncryptionServerPadding string // encryption server padding
|
||||
EncryptionPrivateKey string // encryption private key
|
||||
EncryptionClientPadding string // encryption client padding
|
||||
EncryptionPassword string // encryption password
|
||||
|
||||
Ratio float64 // Traffic ratio, default is 1
|
||||
CertMode string // Certificate mode, `none`|`http`|`dns`|`self`
|
||||
CertDNSProvider string // DNS provider for certificate
|
||||
CertDNSEnv string // Environment for DNS provider
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Password string
|
||||
ExpiredAt time.Time
|
||||
Download int64
|
||||
Upload int64
|
||||
Traffic int64
|
||||
SubscribeURL string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
SiteName string // Name of the site
|
||||
SubscribeName string // Name of the subscription
|
||||
ClientTemplate string // Template for the entire client configuration
|
||||
OutputFormat string // json, yaml, etc.
|
||||
Proxies []Proxy // List of proxy configurations
|
||||
UserInfo User // User information
|
||||
}
|
||||
|
||||
func (c *Client) Build() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
tmpl, err := template.New("client").Funcs(sprig.TxtFuncMap()).Parse(c.ClientTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxies := make([]map[string]interface{}, len(c.Proxies))
|
||||
for i, p := range c.Proxies {
|
||||
proxies[i] = StructToMap(p)
|
||||
}
|
||||
|
||||
err = tmpl.Execute(&buf, map[string]interface{}{
|
||||
"SiteName": c.SiteName,
|
||||
"SubscribeName": c.SubscribeName,
|
||||
"OutputFormat": c.OutputFormat,
|
||||
"Proxies": proxies,
|
||||
"UserInfo": c.UserInfo,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := buf.String()
|
||||
if c.OutputFormat == "base64" {
|
||||
encoded := base64.StdEncoding.EncodeToString([]byte(result))
|
||||
return []byte(encoded), nil
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
v := reflect.ValueOf(obj)
|
||||
t := reflect.TypeOf(obj)
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
m[field.Name] = v.Field(i).Interface()
|
||||
}
|
||||
return m
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var tpl = `
|
||||
{{- range $n := .Proxies }}
|
||||
{{- $dn := urlquery (default "node" $n.Name) -}}
|
||||
{{- $sni := default $n.Host $n.SNI -}}
|
||||
|
||||
{{- if eq $n.Type "shadowsocks" -}}
|
||||
{{- $userinfo := b64enc (print $n.Method ":" $.UserInfo.Password) -}}
|
||||
{{- printf "ss://%s@%s:%v#%s" $userinfo $n.Host $n.Port $dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $n.Type "trojan" -}}
|
||||
{{- $qs := "security=tls" -}}
|
||||
{{- if $sni }}{{ $qs = printf "%s&sni=%s" $qs (urlquery $sni) }}{{ end -}}
|
||||
{{- if $n.AllowInsecure }}{{ $qs = printf "%s&allowInsecure=%v" $qs $n.AllowInsecure }}{{ end -}}
|
||||
{{- if $n.Fingerprint }}{{ $qs = printf "%s&fp=%s" $qs (urlquery $n.Fingerprint) }}{{ end -}}
|
||||
{{- printf "trojan://%s@%s:%v?%s#%s" $.UserInfo.Password $n.Host $n.Port $qs $dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $n.Type "vless" -}}
|
||||
{{- $qs := "encryption=none" -}}
|
||||
{{- if $n.RealityPublicKey -}}
|
||||
{{- $qs = printf "%s&security=reality" $qs -}}
|
||||
{{- $qs = printf "%s&pbk=%s" $qs (urlquery $n.RealityPublicKey) -}}
|
||||
{{- if $n.RealityShortId }}{{ $qs = printf "%s&sid=%s" $qs (urlquery $n.RealityShortId) }}{{ end -}}
|
||||
{{- else -}}
|
||||
{{- if or $n.SNI $n.Fingerprint $n.AllowInsecure }}
|
||||
{{- $qs = printf "%s&security=tls" $qs -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if $n.SNI }}{{ $qs = printf "%s&sni=%s" $qs (urlquery $n.SNI) }}{{ end -}}
|
||||
{{- if $n.AllowInsecure }}{{ $qs = printf "%s&allowInsecure=%v" $qs $n.AllowInsecure }}{{ end -}}
|
||||
{{- if $n.Fingerprint }}{{ $qs = printf "%s&fp=%s" $qs (urlquery $n.Fingerprint) }}{{ end -}}
|
||||
{{- if $n.Network }}{{ $qs = printf "%s&type=%s" $qs $n.Network }}{{ end -}}
|
||||
{{- if $n.Path }}{{ $qs = printf "%s&path=%s" $qs (urlquery $n.Path) }}{{ end -}}
|
||||
{{- if $n.ServiceName }}{{ $qs = printf "%s&serviceName=%s" $qs (urlquery $n.ServiceName) }}{{ end -}}
|
||||
{{- if $n.Flow }}{{ $qs = printf "%s&flow=%s" $qs (urlquery $n.Flow) }}{{ end -}}
|
||||
{{- printf "vless://%s@%s:%v?%s#%s" $n.ServerKey $n.Host $n.Port $qs $dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $n.Type "vmess" -}}
|
||||
{{- $obj := dict
|
||||
"v" "2"
|
||||
"ps" $n.Name
|
||||
"add" $n.Host
|
||||
"port" $n.Port
|
||||
"id" $n.ServerKey
|
||||
"aid" 0
|
||||
"net" (or $n.Network "tcp")
|
||||
"type" "none"
|
||||
"path" (or $n.Path "")
|
||||
"host" $n.Host
|
||||
-}}
|
||||
{{- if or $n.SNI $n.Fingerprint $n.AllowInsecure }}{{ set $obj "tls" "tls" }}{{ end -}}
|
||||
{{- if $n.SNI }}{{ set $obj "sni" $n.SNI }}{{ end -}}
|
||||
{{- if $n.Fingerprint }}{{ set $obj "fp" $n.Fingerprint }}{{ end -}}
|
||||
{{- printf "vmess://%s" (b64enc (toJson $obj)) -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if or (eq $n.Type "hysteria2") (eq $n.Type "hy2") -}}
|
||||
{{- $qs := "" -}}
|
||||
{{- if $n.SNI }}{{ $qs = printf "sni=%s" (urlquery $n.SNI) }}{{ end -}}
|
||||
{{- if $n.AllowInsecure }}{{ $qs = printf "%s&insecure=%v" $qs $n.AllowInsecure }}{{ end -}}
|
||||
{{- if $n.ObfsPassword }}{{ $qs = printf "%s&obfs-password=%s" $qs (urlquery $n.ObfsPassword) }}{{ end -}}
|
||||
{{- printf "hy2://%s@%s:%v%s#%s"
|
||||
$.UserInfo.Password
|
||||
$n.Host
|
||||
$n.Port
|
||||
(ternary (gt (len $qs) 0) (print "?" $qs) "")
|
||||
$dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $n.Type "tuic" -}}
|
||||
{{- $qs := "" -}}
|
||||
{{- if $n.SNI }}{{ $qs = printf "sni=%s" (urlquery $n.SNI) }}{{ end -}}
|
||||
{{- if $n.AllowInsecure }}{{ $qs = printf "%s&insecure=%v" $qs $n.AllowInsecure }}{{ end -}}
|
||||
{{- printf "tuic://%s:%s@%s:%v%s#%s"
|
||||
$n.ServerKey
|
||||
$.UserInfo.Password
|
||||
$n.Host
|
||||
$n.Port
|
||||
(ternary (gt (len $qs) 0) (print "?" $qs) "")
|
||||
$dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $n.Type "anytls" -}}
|
||||
{{- $qs := "" -}}
|
||||
{{- if $n.SNI }}{{ $qs = printf "sni=%s" (urlquery $n.SNI) }}{{ end -}}
|
||||
{{- printf "anytls://%s@%s:%v%s#%s"
|
||||
$.UserInfo.Password
|
||||
$n.Host
|
||||
$n.Port
|
||||
(ternary (gt (len $qs) 0) (print "?" $qs) "")
|
||||
$dn -}}
|
||||
{{- "\n" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end }}
|
||||
`
|
||||
|
||||
func TestClient_Build(t *testing.T) {
|
||||
client := &Client{
|
||||
SiteName: "TestSite",
|
||||
SubscribeName: "TestSubscribe",
|
||||
ClientTemplate: tpl,
|
||||
Proxies: []Proxy{
|
||||
{
|
||||
Name: "TestShadowSocks",
|
||||
Type: "shadowsocks",
|
||||
Host: "127.0.0.1",
|
||||
Port: 1234,
|
||||
Method: "aes-256-gcm",
|
||||
},
|
||||
{
|
||||
Name: "TestTrojan",
|
||||
Type: "trojan",
|
||||
Host: "example.com",
|
||||
Port: 443,
|
||||
AllowInsecure: true,
|
||||
Security: "tls",
|
||||
Transport: "tcp",
|
||||
SNI: "v1-dy.ixigua.com",
|
||||
},
|
||||
},
|
||||
UserInfo: User{
|
||||
Password: "testpassword",
|
||||
ExpiredAt: time.Now().Add(24 * time.Hour),
|
||||
Download: 1000000,
|
||||
Upload: 500000,
|
||||
Traffic: 1500000,
|
||||
SubscribeURL: "https://example.com/subscribe",
|
||||
},
|
||||
}
|
||||
buf, err := client.Build()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to build client: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("[测试] 输出: %s", buf)
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package adapter
|
||||
@@ -1,46 +0,0 @@
|
||||
package adapter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/server"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestAdapterProxy(t *testing.T) {
|
||||
|
||||
servers := getServers()
|
||||
if len(servers) == 0 {
|
||||
t.Fatal("no servers found")
|
||||
}
|
||||
for _, srv := range servers {
|
||||
proxy, err := adapterProxy(*srv, "example.com", 0)
|
||||
if err != nil {
|
||||
t.Errorf("failed to adapt server %s: %v", srv.Name, err)
|
||||
}
|
||||
t.Logf("[测试] 适配服务器 %s 成功: %+v", srv.Name, proxy)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getServers() []*server.Server {
|
||||
db, err := connectMySQL("root:mylove520@tcp(localhost:3306)/perfectlink?charset=utf8mb4&parseTime=True&loc=Local")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var servers []*server.Server
|
||||
if err = db.Model(&server.Server{}).Find(&servers).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
return servers
|
||||
}
|
||||
func connectMySQL(dsn string) (*gorm.DB, error) {
|
||||
db, err := gorm.Open(mysql.New(mysql.Config{
|
||||
DSN: dsn,
|
||||
}), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Application API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
SubscribeApplication {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
SubscribeTemplate string `json:"template"`
|
||||
OutputFormat string `json:"output_format"`
|
||||
DownloadLink DownloadLink `json:"download_link,omitempty"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
GetSubscribeApplicationListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []SubscribeApplication `json:"list"`
|
||||
}
|
||||
CreateSubscribeApplicationRequest {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
SubscribeTemplate string `json:"template"`
|
||||
OutputFormat string `json:"output_format"`
|
||||
DownloadLink DownloadLink `json:"download_link"`
|
||||
}
|
||||
UpdateSubscribeApplicationRequest {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
SubscribeTemplate string `json:"template"`
|
||||
OutputFormat string `json:"output_format"`
|
||||
DownloadLink DownloadLink `json:"download_link,omitempty"`
|
||||
}
|
||||
DeleteSubscribeApplicationRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
GetSubscribeApplicationListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
PreviewSubscribeTemplateRequest {
|
||||
Id int64 `form:"id"`
|
||||
}
|
||||
PreviewSubscribeTemplateResponse {
|
||||
Template string `json:"template"` // 预览的模板内容
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/application
|
||||
group: admin/application
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create subscribe application"
|
||||
@handler CreateSubscribeApplication
|
||||
post / (CreateSubscribeApplicationRequest) returns (SubscribeApplication)
|
||||
|
||||
@doc "Update subscribe application"
|
||||
@handler UpdateSubscribeApplication
|
||||
put /subscribe_application (UpdateSubscribeApplicationRequest) returns (SubscribeApplication)
|
||||
|
||||
@doc "Get subscribe application list"
|
||||
@handler GetSubscribeApplicationList
|
||||
get /subscribe_application_list (GetSubscribeApplicationListRequest) returns (GetSubscribeApplicationListResponse)
|
||||
|
||||
@doc "Delete subscribe application"
|
||||
@handler DeleteSubscribeApplication
|
||||
delete /subscribe_application (DeleteSubscribeApplicationRequest)
|
||||
|
||||
@doc "Preview Template"
|
||||
@handler PreviewSubscribeTemplate
|
||||
get /preview (PreviewSubscribeTemplateRequest) returns (PreviewSubscribeTemplateResponse)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ type (
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
ServerTotalDataResponse {
|
||||
OnlineUsers int64 `json:"online_users"`
|
||||
OnlineUserIPs int64 `json:"online_user_ips"`
|
||||
OnlineServers int64 `json:"online_servers"`
|
||||
OfflineServers int64 `json:"offline_servers"`
|
||||
TodayUpload int64 `json:"today_upload"`
|
||||
|
||||
+6
-227
@@ -14,182 +14,17 @@ type (
|
||||
GetMessageLogListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Type uint8 `form:"type"`
|
||||
Search string `form:"search,optional"`
|
||||
Type string `form:"type"`
|
||||
Platform string `form:"platform,omitempty"`
|
||||
To string `form:"to,omitempty"`
|
||||
Subject string `form:"subject,omitempty"`
|
||||
Content string `form:"content,omitempty"`
|
||||
Status int `form:"status,omitempty"`
|
||||
}
|
||||
GetMessageLogListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []MessageLog `json:"list"`
|
||||
}
|
||||
FilterLogParams {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Date string `form:"date,optional"`
|
||||
Search string `form:"search,optional"`
|
||||
}
|
||||
FilterEmailLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []MessageLog `json:"list"`
|
||||
}
|
||||
FilterMobileLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []MessageLog `json:"list"`
|
||||
}
|
||||
SubscribeLog {
|
||||
UserId int64 `json:"user_id"`
|
||||
Token string `json:"token"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
ClientIP string `json:"client_ip"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterSubscribeLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
UserSubscribeId int64 `form:"user_subscribe_id,optional"`
|
||||
}
|
||||
FilterSubscribeLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []SubscribeLog `json:"list"`
|
||||
}
|
||||
LoginLog {
|
||||
UserId int64 `json:"user_id"`
|
||||
Method string `json:"method"`
|
||||
LoginIP string `json:"login_ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Success bool `json:"success"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterLoginLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterLoginLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []LoginLog `json:"list"`
|
||||
}
|
||||
RegisterLog {
|
||||
UserId int64 `json:"user_id"`
|
||||
AuthMethod string `json:"auth_method"`
|
||||
Identifier string `json:"identifier"`
|
||||
RegisterIP string `json:"register_ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterRegisterLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterRegisterLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []RegisterLog `json:"list"`
|
||||
}
|
||||
ResetSubscribeLog {
|
||||
Type uint16 `json:"type"`
|
||||
UserId int64 `json:"user_id"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
OrderNo string `json:"order_no,omitempty"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterResetSubscribeLogRequest {
|
||||
FilterLogParams
|
||||
UserSubscribeId int64 `form:"user_subscribe_id,optional"`
|
||||
}
|
||||
FilterResetSubscribeLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ResetSubscribeLog `json:"list"`
|
||||
}
|
||||
UserSubscribeTrafficLog {
|
||||
SubscribeId int64 `json:"subscribe_id"` // Subscribe ID
|
||||
UserId int64 `json:"user_id"` // User ID
|
||||
Upload int64 `json:"upload"` // Upload traffic in bytes
|
||||
Download int64 `json:"download"` // Download traffic in bytes
|
||||
Total int64 `json:"total"` // Total traffic in bytes (Upload + Download)
|
||||
Date string `json:"date"` // Date in YYYY-MM-DD format
|
||||
Details bool `json:"details"` // Whether to show detailed traffic
|
||||
}
|
||||
FilterSubscribeTrafficRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
UserSubscribeId int64 `form:"user_subscribe_id,optional"`
|
||||
}
|
||||
FilterSubscribeTrafficResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []UserSubscribeTrafficLog `json:"list"`
|
||||
}
|
||||
ServerTrafficLog {
|
||||
ServerId int64 `json:"server_id"` // Server ID
|
||||
Upload int64 `json:"upload"` // Upload traffic in bytes
|
||||
Download int64 `json:"download"` // Download traffic in bytes
|
||||
Total int64 `json:"total"` // Total traffic in bytes (Upload + Download)
|
||||
Date string `json:"date"` // Date in YYYY-MM-DD format
|
||||
Details bool `json:"details"` // Whether to show detailed traffic
|
||||
}
|
||||
FilterServerTrafficLogRequest {
|
||||
FilterLogParams
|
||||
ServerId int64 `form:"server_id,optional"`
|
||||
}
|
||||
FilterServerTrafficLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerTrafficLog `json:"list"`
|
||||
}
|
||||
FilterBalanceLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterBalanceLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []BalanceLog `json:"list"`
|
||||
}
|
||||
FilterCommissionLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterCommissionLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []CommissionLog `json:"list"`
|
||||
}
|
||||
GiftLog {
|
||||
Type uint16 `json:"type"`
|
||||
userId int64 `json:"user_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
Balance int64 `json:"balance"`
|
||||
Remark string `json:"remark,omitempty"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterGiftLogRequest {
|
||||
FilterLogParams
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterGiftLogResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []GiftLog `json:"list"`
|
||||
}
|
||||
TrafficLogDetails {
|
||||
Id int64 `json:"id"`
|
||||
ServerId int64 `json:"server_id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Download int64 `json:"download"`
|
||||
Upload int64 `json:"upload"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
FilterTrafficLogDetailsRequest {
|
||||
FilterLogParams
|
||||
ServerId int64 `form:"server_id,optional"`
|
||||
SubscribeId int64 `form:"subscribe_id,optional"`
|
||||
UserId int64 `form:"user_id,optional"`
|
||||
}
|
||||
FilterTrafficLogDetailsResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []TrafficLogDetails `json:"list"`
|
||||
}
|
||||
LogSetting {
|
||||
AutoClear *bool `json:"auto_clear"`
|
||||
ClearDays int64 `json:"clear_days"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
@@ -201,61 +36,5 @@ service ppanel {
|
||||
@doc "Get message log list"
|
||||
@handler GetMessageLogList
|
||||
get /message/list (GetMessageLogListRequest) returns (GetMessageLogListResponse)
|
||||
|
||||
@doc "Filter email log"
|
||||
@handler FilterEmailLog
|
||||
get /email/list (FilterLogParams) returns (FilterEmailLogResponse)
|
||||
|
||||
@doc "Filter mobile log"
|
||||
@handler FilterMobileLog
|
||||
get /mobile/list (FilterLogParams) returns (FilterMobileLogResponse)
|
||||
|
||||
@doc "Filter subscribe log"
|
||||
@handler FilterSubscribeLog
|
||||
get /subscribe/list (FilterSubscribeLogRequest) returns (FilterSubscribeLogResponse)
|
||||
|
||||
@doc "Filter login log"
|
||||
@handler FilterLoginLog
|
||||
get /login/list (FilterLoginLogRequest) returns (FilterLoginLogResponse)
|
||||
|
||||
@doc "Filter register log"
|
||||
@handler FilterRegisterLog
|
||||
get /register/list (FilterRegisterLogRequest) returns (FilterRegisterLogResponse)
|
||||
|
||||
@doc "Filter reset subscribe log"
|
||||
@handler FilterResetSubscribeLog
|
||||
get /subscribe/reset/list (FilterResetSubscribeLogRequest) returns (FilterResetSubscribeLogResponse)
|
||||
|
||||
@doc "Filter user subscribe traffic log"
|
||||
@handler FilterUserSubscribeTrafficLog
|
||||
get /subscribe/traffic/list (FilterSubscribeTrafficRequest) returns (FilterSubscribeTrafficResponse)
|
||||
|
||||
@doc "Filter server traffic log"
|
||||
@handler FilterServerTrafficLog
|
||||
get /server/traffic/list (FilterServerTrafficLogRequest) returns (FilterServerTrafficLogResponse)
|
||||
|
||||
@doc "Filter balance log"
|
||||
@handler FilterBalanceLog
|
||||
get /balance/list (FilterBalanceLogRequest) returns (FilterBalanceLogResponse)
|
||||
|
||||
@doc "Filter commission log"
|
||||
@handler FilterCommissionLog
|
||||
get /commission/list (FilterCommissionLogRequest) returns (FilterCommissionLogResponse)
|
||||
|
||||
@doc "Filter gift log"
|
||||
@handler FilterGiftLog
|
||||
get /gift/list (FilterGiftLogRequest) returns (FilterGiftLogResponse)
|
||||
|
||||
@doc "Filter traffic log details"
|
||||
@handler FilterTrafficLogDetails
|
||||
get /traffic/details (FilterTrafficLogDetailsRequest) returns (FilterTrafficLogDetailsResponse)
|
||||
|
||||
@doc "Get log setting"
|
||||
@handler GetLogSetting
|
||||
get /setting returns (LogSetting)
|
||||
|
||||
@doc "Update log setting"
|
||||
@handler UpdateLogSetting
|
||||
post /setting (LogSetting)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Marketing API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
CreateBatchSendEmailTaskRequest {
|
||||
Subject string `json:"subject"`
|
||||
Content string `json:"content"`
|
||||
Scope int8 `json:"scope"`
|
||||
RegisterStartTime int64 `json:"register_start_time,omitempty"`
|
||||
RegisterEndTime int64 `json:"register_end_time,omitempty"`
|
||||
Additional string `json:"additional,omitempty"`
|
||||
Scheduled int64 `json:"scheduled,omitempty"`
|
||||
Interval uint8 `json:"interval,omitempty"`
|
||||
Limit uint64 `json:"limit,omitempty"`
|
||||
}
|
||||
BatchSendEmailTask {
|
||||
Id int64 `json:"id"`
|
||||
Subject string `json:"subject"`
|
||||
Content string `json:"content"`
|
||||
Recipients string `json:"recipients"`
|
||||
Scope int8 `json:"scope"`
|
||||
RegisterStartTime int64 `json:"register_start_time"`
|
||||
RegisterEndTime int64 `json:"register_end_time"`
|
||||
Additional string `json:"additional"`
|
||||
Scheduled int64 `json:"scheduled"`
|
||||
Interval uint8 `json:"interval"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Status uint8 `json:"status"`
|
||||
Errors string `json:"errors"`
|
||||
Total uint64 `json:"total"`
|
||||
Current uint64 `json:"current"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
GetBatchSendEmailTaskListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Scope *int8 `form:"scope,omitempty"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
}
|
||||
GetBatchSendEmailTaskListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []BatchSendEmailTask `json:"list"`
|
||||
}
|
||||
StopBatchSendEmailTaskRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
GetPreSendEmailCountRequest {
|
||||
Scope int8 `json:"scope"`
|
||||
RegisterStartTime int64 `json:"register_start_time,omitempty"`
|
||||
RegisterEndTime int64 `json:"register_end_time,omitempty"`
|
||||
}
|
||||
GetPreSendEmailCountResponse {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
GetBatchSendEmailTaskStatusRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
GetBatchSendEmailTaskStatusResponse {
|
||||
Status uint8 `json:"status"`
|
||||
Current int64 `json:"current"`
|
||||
Total int64 `json:"total"`
|
||||
Errors string `json:"errors"`
|
||||
}
|
||||
CreateQuotaTaskRequest {
|
||||
Subscribers []int64 `json:"subscribers"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
ResetTraffic bool `json:"reset_traffic"`
|
||||
Days uint64 `json:"days"`
|
||||
GiftType uint8 `json:"gift_type"`
|
||||
GiftValue uint64 `json:"gift_value"`
|
||||
}
|
||||
QuotaTask {
|
||||
Id int64 `json:"id"`
|
||||
Subscribers []int64 `json:"subscribers"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
ResetTraffic bool `json:"reset_traffic"`
|
||||
Days uint64 `json:"days"`
|
||||
GiftType uint8 `json:"gift_type"`
|
||||
GiftValue uint64 `json:"gift_value"`
|
||||
Objects []int64 `json:"objects"` // UserSubscribe IDs
|
||||
Status uint8 `json:"status"`
|
||||
Total int64 `json:"total"`
|
||||
Current int64 `json:"current"`
|
||||
Errors string `json:"errors"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
QueryQuotaTaskPreCountRequest {
|
||||
Subscribers []int64 `json:"subscribers"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
}
|
||||
QueryQuotaTaskPreCountResponse {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
QueryQuotaTaskListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
}
|
||||
QueryQuotaTaskListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []QuotaTask `json:"list"`
|
||||
}
|
||||
QueryQuotaTaskStatusRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
QueryQuotaTaskStatusResponse {
|
||||
Status uint8 `json:"status"`
|
||||
Current int64 `json:"current"`
|
||||
Total int64 `json:"total"`
|
||||
Errors string `json:"errors"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/marketing
|
||||
group: admin/marketing
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create a batch send email task"
|
||||
@handler CreateBatchSendEmailTask
|
||||
post /email/batch/send (CreateBatchSendEmailTaskRequest)
|
||||
|
||||
@doc "Get batch send email task list"
|
||||
@handler GetBatchSendEmailTaskList
|
||||
get /email/batch/list (GetBatchSendEmailTaskListRequest) returns (GetBatchSendEmailTaskListResponse)
|
||||
|
||||
@doc "Stop a batch send email task"
|
||||
@handler StopBatchSendEmailTask
|
||||
post /email/batch/stop (StopBatchSendEmailTaskRequest)
|
||||
|
||||
@doc "Get pre-send email count"
|
||||
@handler GetPreSendEmailCount
|
||||
post /email/batch/pre-send-count (GetPreSendEmailCountRequest) returns (GetPreSendEmailCountResponse)
|
||||
|
||||
@doc "Get batch send email task status"
|
||||
@handler GetBatchSendEmailTaskStatus
|
||||
post /email/batch/status (GetBatchSendEmailTaskStatusRequest) returns (GetBatchSendEmailTaskStatusResponse)
|
||||
|
||||
@doc "Create a quota task"
|
||||
@handler CreateQuotaTask
|
||||
post /quota/create (CreateQuotaTaskRequest)
|
||||
|
||||
@doc "Query quota task pre-count"
|
||||
@handler QueryQuotaTaskPreCount
|
||||
post /quota/pre-count (QueryQuotaTaskPreCountRequest) returns (QueryQuotaTaskPreCountResponse)
|
||||
|
||||
@doc "Query quota task list"
|
||||
@handler QueryQuotaTaskList
|
||||
get /quota/list (QueryQuotaTaskListRequest) returns (QueryQuotaTaskListResponse)
|
||||
}
|
||||
|
||||
+138
-156
@@ -11,134 +11,108 @@ info (
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
ServerOnlineIP {
|
||||
IP string `json:"ip"`
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
ServerOnlineUser {
|
||||
IP []ServerOnlineIP `json:"ip"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Subscribe string `json:"subscribe"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
ExpiredAt int64 `json:"expired_at"`
|
||||
}
|
||||
ServerStatus {
|
||||
Cpu float64 `json:"cpu"`
|
||||
Mem float64 `json:"mem"`
|
||||
Disk float64 `json:"disk"`
|
||||
Protocol string `json:"protocol"`
|
||||
Online []ServerOnlineUser `json:"online"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
Server {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Address string `json:"address"`
|
||||
Sort int `json:"sort"`
|
||||
Protocols []Protocol `json:"protocols"`
|
||||
LastReportedAt int64 `json:"last_reported_at"`
|
||||
Status ServerStatus `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
CreateServerRequest {
|
||||
Name string `json:"name"`
|
||||
Country string `json:"country,omitempty"`
|
||||
City string `json:"city,omitempty"`
|
||||
Address string `json:"address"`
|
||||
Sort int `json:"sort,omitempty"`
|
||||
Protocols []Protocol `json:"protocols"`
|
||||
}
|
||||
UpdateServerRequest {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Country string `json:"country,omitempty"`
|
||||
City string `json:"city,omitempty"`
|
||||
Address string `json:"address"`
|
||||
Sort int `json:"sort,omitempty"`
|
||||
Protocols []Protocol `json:"protocols"`
|
||||
}
|
||||
DeleteServerRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
FilterServerListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
GetNodeServerListRequest {
|
||||
Page int `form:"page" validate:"required"`
|
||||
Size int `form:"size" validate:"required"`
|
||||
Tags string `form:"tags,omitempty"`
|
||||
GroupId int64 `form:"group_id,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
FilterServerListResponse {
|
||||
GetNodeServerListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Server `json:"list"`
|
||||
}
|
||||
GetServerProtocolsRequest {
|
||||
Id int64 `form:"id"`
|
||||
}
|
||||
GetServerProtocolsResponse {
|
||||
Protocols []Protocol `json:"protocols"`
|
||||
}
|
||||
Node {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
UpdateNodeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Port uint16 `json:"port"`
|
||||
Address string `json:"address"`
|
||||
ServerId int64 `json:"server_id"`
|
||||
Protocol string `json:"protocol"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Sort int `json:"sort,omitempty"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
ServerAddr string `json:"server_addr" validate:"required"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol" validate:"required"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
Enable *bool `json:"enable"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
CreateNodeRequest {
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Port uint16 `json:"port"`
|
||||
Address string `json:"address"`
|
||||
ServerId int64 `json:"server_id"`
|
||||
Protocol string `json:"protocol"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
UpdateNodeRequest {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Port uint16 `json:"port"`
|
||||
Address string `json:"address"`
|
||||
ServerId int64 `json:"server_id"`
|
||||
Protocol string `json:"protocol"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
ToggleNodeStatusRequest {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
ServerAddr string `json:"server_addr" validate:"required"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol" validate:"required"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
Enable *bool `json:"enable"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
DeleteNodeRequest {
|
||||
Id int64 `json:"id"`
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
FilterNodeListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
FilterNodeListResponse {
|
||||
GetNodeGroupListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Node `json:"list"`
|
||||
List []ServerGroup `json:"list"`
|
||||
}
|
||||
HasMigrateSeverNodeResponse {
|
||||
HasMigrate bool `json:"has_migrate"`
|
||||
CreateNodeGroupRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
MigrateServerNodeResponse {
|
||||
Succee uint64 `json:"succee"`
|
||||
Fail uint64 `json:"fail"`
|
||||
Message string `json:"message,omitempty"`
|
||||
UpdateNodeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
ResetSortRequest {
|
||||
DeleteNodeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteNodeRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
BatchDeleteNodeGroupRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
GetNodeDetailRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
NodeSortRequest {
|
||||
Sort []SortItem `json:"sort"`
|
||||
}
|
||||
QueryNodeTagResponse {
|
||||
CreateRuleGroupRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
Rules string `json:"rules"`
|
||||
Default bool `json:"default"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
UpdateRuleGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Rules string `json:"rules"`
|
||||
Default bool `json:"default"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
DeleteRuleGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetRuleGroupResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerRuleGroup `json:"list"`
|
||||
}
|
||||
GetNodeTagListResponse {
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
)
|
||||
@@ -149,64 +123,72 @@ type (
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create Server"
|
||||
@handler CreateServer
|
||||
post /create (CreateServerRequest)
|
||||
@doc "Get node tag list"
|
||||
@handler GetNodeTagList
|
||||
get /tag/list returns (GetNodeTagListResponse)
|
||||
|
||||
@doc "Update Server"
|
||||
@handler UpdateServer
|
||||
post /update (UpdateServerRequest)
|
||||
@doc "Get node list"
|
||||
@handler GetNodeList
|
||||
get /list (GetNodeServerListRequest) returns (GetNodeServerListResponse)
|
||||
|
||||
@doc "Delete Server"
|
||||
@handler DeleteServer
|
||||
post /delete (DeleteServerRequest)
|
||||
@doc "Get node detail"
|
||||
@handler GetNodeDetail
|
||||
get /detail (GetNodeDetailRequest) returns (Server)
|
||||
|
||||
@doc "Filter Server List"
|
||||
@handler FilterServerList
|
||||
get /list (FilterServerListRequest) returns (FilterServerListResponse)
|
||||
|
||||
@doc "Get Server Protocols"
|
||||
@handler GetServerProtocols
|
||||
get /protocols (GetServerProtocolsRequest) returns (GetServerProtocolsResponse)
|
||||
|
||||
@doc "Create Node"
|
||||
@handler CreateNode
|
||||
post /node/create (CreateNodeRequest)
|
||||
|
||||
@doc "Update Node"
|
||||
@doc "Update node"
|
||||
@handler UpdateNode
|
||||
post /node/update (UpdateNodeRequest)
|
||||
put / (UpdateNodeRequest)
|
||||
|
||||
@doc "Delete Node"
|
||||
@doc "Create node"
|
||||
@handler CreateNode
|
||||
post / (CreateNodeRequest)
|
||||
|
||||
@doc "Delete node"
|
||||
@handler DeleteNode
|
||||
post /node/delete (DeleteNodeRequest)
|
||||
delete / (DeleteNodeRequest)
|
||||
|
||||
@doc "Filter Node List"
|
||||
@handler FilterNodeList
|
||||
get /node/list (FilterNodeListRequest) returns (FilterNodeListResponse)
|
||||
@doc "Batch delete node"
|
||||
@handler BatchDeleteNode
|
||||
delete /batch (BatchDeleteNodeRequest)
|
||||
|
||||
@doc "Toggle Node Status"
|
||||
@handler ToggleNodeStatus
|
||||
post /node/status/toggle (ToggleNodeStatusRequest)
|
||||
@doc "Get node group list"
|
||||
@handler GetNodeGroupList
|
||||
get /group/list returns (GetNodeGroupListResponse)
|
||||
|
||||
@doc "Check if there is any server or node to migrate"
|
||||
@handler HasMigrateSeverNode
|
||||
get /migrate/has returns (HasMigrateSeverNodeResponse)
|
||||
@doc "Create node group"
|
||||
@handler CreateNodeGroup
|
||||
post /group (CreateNodeGroupRequest)
|
||||
|
||||
@doc "Migrate server and node data to new database"
|
||||
@handler MigrateServerNode
|
||||
post /migrate/run returns (MigrateServerNodeResponse)
|
||||
@doc "Update node group"
|
||||
@handler UpdateNodeGroup
|
||||
put /group (UpdateNodeGroupRequest)
|
||||
|
||||
@doc "Reset server sort"
|
||||
@handler ResetSortWithServer
|
||||
post /server/sort (ResetSortRequest)
|
||||
@doc "Delete node group"
|
||||
@handler DeleteNodeGroup
|
||||
delete /group (DeleteNodeGroupRequest)
|
||||
|
||||
@doc "Reset node sort"
|
||||
@handler ResetSortWithNode
|
||||
post /node/sort (ResetSortRequest)
|
||||
@doc "Batch delete node group"
|
||||
@handler BatchDeleteNodeGroup
|
||||
delete /group/batch (BatchDeleteNodeGroupRequest)
|
||||
|
||||
@doc "Query all node tags"
|
||||
@handler QueryNodeTag
|
||||
get /node/tags returns (QueryNodeTagResponse)
|
||||
@doc "Node sort "
|
||||
@handler NodeSort
|
||||
post /sort (NodeSortRequest)
|
||||
|
||||
@doc "Create rule group"
|
||||
@handler CreateRuleGroup
|
||||
post /rule_group (CreateRuleGroupRequest)
|
||||
|
||||
@doc "Update rule group"
|
||||
@handler UpdateRuleGroup
|
||||
put /rule_group (UpdateRuleGroupRequest)
|
||||
|
||||
@doc "Delete rule group"
|
||||
@handler DeleteRuleGroup
|
||||
delete /rule_group (DeleteRuleGroupRequest)
|
||||
|
||||
@doc "Get rule group list"
|
||||
@handler GetRuleGroupList
|
||||
get /rule_group_list returns (GetRuleGroupResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ type (
|
||||
}
|
||||
CreateSubscribeRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Language string `json:"language"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
@@ -46,8 +45,9 @@ type (
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
Nodes []int64 `json:"nodes"`
|
||||
NodeTags []string `json:"node_tags"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show *bool `json:"show"`
|
||||
Sell *bool `json:"sell"`
|
||||
DeductionRatio int64 `json:"deduction_ratio"`
|
||||
@@ -58,7 +58,6 @@ type (
|
||||
UpdateSubscribeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Language string `json:"language"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
@@ -69,8 +68,9 @@ type (
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
Nodes []int64 `json:"nodes"`
|
||||
NodeTags []string `json:"node_tags"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show *bool `json:"show"`
|
||||
Sell *bool `json:"sell"`
|
||||
Sort int64 `json:"sort"`
|
||||
@@ -85,7 +85,7 @@ type (
|
||||
GetSubscribeListRequest {
|
||||
Page int64 `form:"page" validate:"required"`
|
||||
Size int64 `form:"size" validate:"required"`
|
||||
Language string `form:"language,omitempty"`
|
||||
GroupId int64 `form:"group_id,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
SubscribeItem {
|
||||
@@ -102,9 +102,6 @@ type (
|
||||
BatchDeleteSubscribeRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
ResetAllSubscribeTokenResponse {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
@@ -160,9 +157,5 @@ service ppanel {
|
||||
@doc "Subscribe sort"
|
||||
@handler SubscribeSort
|
||||
post /sort (SubscribeSortRequest)
|
||||
|
||||
@doc "Reset all subscribe tokens"
|
||||
@handler ResetAllSubscribeToken
|
||||
post /reset_all_token returns (ResetAllSubscribeTokenResponse)
|
||||
}
|
||||
|
||||
|
||||
+84
-17
@@ -11,6 +11,50 @@ info (
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
// Update application request
|
||||
UpdateApplicationRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
Platform ApplicationPlatform `json:"platform"`
|
||||
}
|
||||
// Create application request
|
||||
CreateApplicationRequest {
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
Platform ApplicationPlatform `json:"platform"`
|
||||
}
|
||||
// Update application request
|
||||
UpdateApplicationVersionRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
ApplicationId int64 `json:"application_id" validate:"required"`
|
||||
}
|
||||
// Create application request
|
||||
CreateApplicationVersionRequest {
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
ApplicationId int64 `json:"application_id" validate:"required"`
|
||||
}
|
||||
// Delete application request
|
||||
DeleteApplicationRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
// Delete application request
|
||||
DeleteApplicationVersionRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetNodeMultiplierResponse {
|
||||
Periods []TimePeriod `json:"periods"`
|
||||
}
|
||||
@@ -18,15 +62,6 @@ type (
|
||||
SetNodeMultiplierRequest {
|
||||
Periods []TimePeriod `json:"periods"`
|
||||
}
|
||||
PreViewNodeMultiplierResponse {
|
||||
CurrentTime string `json:"current_time"`
|
||||
Ratio float32 `json:"ratio"`
|
||||
}
|
||||
ModuleConfig {
|
||||
Secret string `json:"secret"` // 通讯密钥
|
||||
ServiceName string `json:"service_name"` // 服务名称
|
||||
ServiceVersion string `json:"service_version"` // 服务版本
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
@@ -51,6 +86,46 @@ service ppanel {
|
||||
@handler UpdateSubscribeConfig
|
||||
put /subscribe_config (SubscribeConfig)
|
||||
|
||||
@doc "Get subscribe type"
|
||||
@handler GetSubscribeType
|
||||
get /subscribe_type returns (SubscribeType)
|
||||
|
||||
@doc "update application config"
|
||||
@handler UpdateApplicationConfig
|
||||
put /application_config (ApplicationConfig)
|
||||
|
||||
@doc "get application config"
|
||||
@handler GetApplicationConfig
|
||||
get /application_config returns (ApplicationConfig)
|
||||
|
||||
@doc "Get application"
|
||||
@handler GetApplication
|
||||
get /application returns (ApplicationResponse)
|
||||
|
||||
@doc "Update application"
|
||||
@handler UpdateApplication
|
||||
put /application (UpdateApplicationRequest)
|
||||
|
||||
@doc "Create application"
|
||||
@handler CreateApplication
|
||||
post /application (CreateApplicationRequest)
|
||||
|
||||
@doc "Delete application"
|
||||
@handler DeleteApplication
|
||||
delete /application (DeleteApplicationRequest)
|
||||
|
||||
@doc "Update application version"
|
||||
@handler UpdateApplicationVersion
|
||||
put /application_version (UpdateApplicationVersionRequest)
|
||||
|
||||
@doc "Create application version"
|
||||
@handler CreateApplicationVersion
|
||||
post /application_version (CreateApplicationVersionRequest)
|
||||
|
||||
@doc "Delete application"
|
||||
@handler DeleteApplicationVersion
|
||||
delete /application_version (DeleteApplicationVersionRequest)
|
||||
|
||||
@doc "Get register config"
|
||||
@handler GetRegisterConfig
|
||||
get /register_config returns (RegisterConfig)
|
||||
@@ -126,13 +201,5 @@ service ppanel {
|
||||
@doc "Update Verify Code Config"
|
||||
@handler UpdateVerifyCodeConfig
|
||||
put /verify_code_config (VerifyCodeConfig)
|
||||
|
||||
@doc "PreView Node Multiplier"
|
||||
@handler PreViewNodeMultiplier
|
||||
get /node_multiplier/preview returns (PreViewNodeMultiplierResponse)
|
||||
|
||||
@doc "Get Module Config"
|
||||
@handler GetModuleConfig
|
||||
get /module returns (ModuleConfig)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ type (
|
||||
Size int64 `form:"size"`
|
||||
UserId int64 `form:"user_id,omitempty"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
IssueType *uint8 `form:"issue_type,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetTicketListResponse {
|
||||
|
||||
@@ -14,17 +14,6 @@ type (
|
||||
LogResponse {
|
||||
List interface{} `json:"list"`
|
||||
}
|
||||
VersionResponse {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
QueryIPLocationRequest {
|
||||
IP string `form:"ip" validate:"required"`
|
||||
}
|
||||
QueryIPLocationResponse {
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region,omitempty"`
|
||||
City string `json:"city"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
@@ -40,13 +29,5 @@ service ppanel {
|
||||
@doc "Restart System"
|
||||
@handler RestartSystem
|
||||
get /restart
|
||||
|
||||
@doc "Get Version"
|
||||
@handler GetVersion
|
||||
get /version returns (VersionResponse)
|
||||
|
||||
@doc "Query IP Location"
|
||||
@handler QueryIPLocation
|
||||
get /ip/location (QueryIPLocationRequest) returns (QueryIPLocationResponse)
|
||||
}
|
||||
|
||||
|
||||
+1
-17
@@ -37,12 +37,11 @@ type (
|
||||
Avatar string `json:"avatar"`
|
||||
Balance int64 `json:"balance"`
|
||||
Commission int64 `json:"commission"`
|
||||
ReferralPercentage uint8 `json:"referral_percentage"`
|
||||
OnlyFirstPurchase bool `json:"only_first_purchase"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Telegram int64 `json:"telegram"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
RefererId int64 `json:"referer_id"`
|
||||
Remark string `json:"remark"`
|
||||
Enable bool `json:"enable"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
}
|
||||
@@ -60,8 +59,6 @@ type (
|
||||
Password string `json:"password"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
Duration int64 `json:"duration"`
|
||||
ReferralPercentage uint8 `json:"referral_percentage"`
|
||||
OnlyFirstPurchase bool `json:"only_first_purchase"`
|
||||
RefererUser string `json:"referer_user"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
Balance int64 `json:"balance"`
|
||||
@@ -168,15 +165,6 @@ type (
|
||||
List []UserLoginLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
GetUserSubscribeResetTrafficLogsRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserSubscribeId int64 `form:"user_subscribe_id"`
|
||||
}
|
||||
GetUserSubscribeResetTrafficLogsResponse {
|
||||
List []ResetSubscribeTrafficLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
DeleteUserSubscribeRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
@@ -264,10 +252,6 @@ service ppanel {
|
||||
@handler GetUserSubscribeLogs
|
||||
get /subscribe/logs (GetUserSubscribeLogsRequest) returns (GetUserSubscribeLogsResponse)
|
||||
|
||||
@doc "Get user subcribe reset traffic logs"
|
||||
@handler GetUserSubscribeResetTrafficLogs
|
||||
get /subscribe/reset/logs (GetUserSubscribeResetTrafficLogsRequest) returns (GetUserSubscribeResetTrafficLogsResponse)
|
||||
|
||||
@doc "Get user subcribe traffic logs"
|
||||
@handler GetUserSubscribeTrafficLogs
|
||||
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Announcement API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/app/announcement
|
||||
group: app/announcement
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query announcement"
|
||||
@handler QueryAnnouncement
|
||||
get /list (QueryAnnouncementRequest) returns (QueryAnnouncementResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App Auth Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
AppAuthCheckRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
|
||||
Account string `json:"account"`
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
AreaCode string `json:"area_code"`
|
||||
}
|
||||
AppAuthCheckResponse {
|
||||
Status bool
|
||||
}
|
||||
AppAuthRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
|
||||
Account string `json:"account"`
|
||||
Password string `json:"password"`
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
Code string `json:"code"`
|
||||
Invite string `json:"invite"`
|
||||
AreaCode string `json:"area_code"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppAuthRespone {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
AppSendCodeRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=email mobile"`
|
||||
Account string `json:"account"`
|
||||
AreaCode string `json:"area_code"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppSendCodeRespone {
|
||||
Status bool `json:"status"`
|
||||
Code string `json:"code,omitempty"`
|
||||
}
|
||||
AppConfigRequest {
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
}
|
||||
AppConfigResponse {
|
||||
EncryptionKey string `json:"encryption_key"`
|
||||
EncryptionMethod string `json:"encryption_method"`
|
||||
Domains []string `json:"domains"`
|
||||
StartupPicture string `json:"startup_picture"`
|
||||
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
|
||||
Application AppInfo `json:"applications"`
|
||||
OfficialEmail string `json:"official_email"`
|
||||
OfficialWebsite string `json:"official_website"`
|
||||
OfficialTelegram string `json:"official_telegram"`
|
||||
OfficialTelephone string `json:"official_telephone"`
|
||||
InvitationLink string `json:"invitation_link"`
|
||||
KrWebsiteId string `json:"kr_website_id"`
|
||||
}
|
||||
AppInfo {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version"`
|
||||
VersionDescription string `json:"version_description"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/auth
|
||||
group: app/auth
|
||||
middleware: AppMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Check Account"
|
||||
@handler Check
|
||||
post /check (AppAuthCheckRequest) returns (AppAuthCheckResponse)
|
||||
|
||||
@doc "Login"
|
||||
@handler Login
|
||||
post /login (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "Register"
|
||||
@handler Register
|
||||
post /register (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "Reset Password"
|
||||
@handler ResetPassword
|
||||
post /reset_password (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "GetAppConfig"
|
||||
@handler GetAppConfig
|
||||
post /config (AppConfigRequest) returns (AppConfigResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Document API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/app/document
|
||||
group: app/document
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get document list"
|
||||
@handler QueryDocumentList
|
||||
get /list returns (QueryDocumentListResponse)
|
||||
|
||||
@doc "Get document detail"
|
||||
@handler QueryDocumentDetail
|
||||
get /detail (QueryDocumentDetailRequest) returns (Document)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App Node Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
AppRuleGroupListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerRuleGroup `json:"list"`
|
||||
}
|
||||
AppUserSubscbribeNodeRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
AppUserSubscbribeNodeResponse {
|
||||
List []AppUserSubscbribeNode `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/node
|
||||
group: app/node
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get Node list"
|
||||
@handler GetNodeList
|
||||
get /list (AppUserSubscbribeNodeRequest) returns (AppUserSubscbribeNodeResponse)
|
||||
|
||||
@doc "Get rule group list"
|
||||
@handler GetRuleGroupList
|
||||
get /rule_group_list returns (AppRuleGroupListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Order API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/order
|
||||
group: app/order
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Pre create order"
|
||||
@handler PreCreateOrder
|
||||
post /pre (PurchaseOrderRequest) returns (PreOrderResponse)
|
||||
|
||||
@doc "purchase Subscription"
|
||||
@handler Purchase
|
||||
post /purchase (PurchaseOrderRequest) returns (PurchaseOrderResponse)
|
||||
|
||||
@doc "Renewal Subscription"
|
||||
@handler Renewal
|
||||
post /renewal (RenewalOrderRequest) returns (RenewalOrderResponse)
|
||||
|
||||
@doc "Reset traffic"
|
||||
@handler ResetTraffic
|
||||
post /reset (ResetTrafficOrderRequest) returns (ResetTrafficOrderResponse)
|
||||
|
||||
@doc "Recharge"
|
||||
@handler Recharge
|
||||
post /recharge (RechargeOrderRequest) returns (RechargeOrderResponse)
|
||||
|
||||
@doc "Checkout order"
|
||||
@handler CheckoutOrder
|
||||
post /checkout (CheckoutOrderRequest) returns (CheckoutOrderResponse)
|
||||
|
||||
@doc "Close order"
|
||||
@handler CloseOrder
|
||||
post /close (CloseOrderRequest)
|
||||
|
||||
@doc "Get order"
|
||||
@handler QueryOrderDetail
|
||||
get /detail (QueryOrderDetailRequest) returns (OrderDetail)
|
||||
|
||||
@doc "Get order list"
|
||||
@handler QueryOrderList
|
||||
get /list (QueryOrderListRequest) returns (QueryOrderListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "payment API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/app/payment
|
||||
group: app/payment
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
@handler GetAvailablePaymentMethods
|
||||
get /methods returns (GetAvailablePaymentMethodsResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Subscribe API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
QueryUserSubscribeResp {
|
||||
Data []UserSubscribeData `json:"data"`
|
||||
}
|
||||
UserSubscribeData {
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
UserSubscribeResetPeriodRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
UserSubscribeResetPeriodResponse {
|
||||
Status bool `json:"status"`
|
||||
}
|
||||
AppUserSubscribeRequest {
|
||||
ContainsNodes *bool `form:"contains_nodes"`
|
||||
}
|
||||
AppUserSubscbribeResponse {
|
||||
List []AppUserSubcbribe `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/subscribe
|
||||
group: app/subscribe
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get subscribe list"
|
||||
@handler QuerySubscribeList
|
||||
get /list returns (QuerySubscribeListResponse)
|
||||
|
||||
@doc "Get subscribe group list"
|
||||
@handler QuerySubscribeGroupList
|
||||
get /group/list returns (QuerySubscribeGroupListResponse)
|
||||
|
||||
@doc "Get application config"
|
||||
@handler QueryApplicationConfig
|
||||
get /application/config returns (ApplicationResponse)
|
||||
|
||||
@doc "Get Already subscribed to package"
|
||||
@handler QueryUserAlreadySubscribe
|
||||
get /user/already_subscribe returns (QueryUserSubscribeResp)
|
||||
|
||||
@doc "Get Available subscriptions for users"
|
||||
@handler QueryUserAvailableUserSubscribe
|
||||
get /user/available_subscribe (AppUserSubscribeRequest) returns (AppUserSubscbribeResponse)
|
||||
|
||||
@doc "Reset user subscription period"
|
||||
@handler ResetUserSubscribePeriod
|
||||
post /reset/period (UserSubscribeResetPeriodRequest) returns (UserSubscribeResetPeriodResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App User Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
UserInfoResponse {
|
||||
Id int64 `json:"id"`
|
||||
Balance int64 `json:"balance"`
|
||||
Email string `json:"email"`
|
||||
RefererId int64 `json:"referer_id"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
Avatar string `json:"avatar"`
|
||||
AreaCode string `json:"area_code"`
|
||||
Telephone string `json:"telephone"`
|
||||
Devices []UserDevice `json:"devices"`
|
||||
AuthMethods []UserAuthMethod `json:"auth_methods"`
|
||||
}
|
||||
UpdatePasswordRequeset {
|
||||
Password string `json:"password"`
|
||||
NewPassword string `json:"new_password"`
|
||||
}
|
||||
DeleteAccountRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=email telephone device"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
GetUserOnlineTimeStatisticsResponse {
|
||||
WeeklyStats []WeeklyStat `json:"weekly_stats"`
|
||||
ConnectionRecords ConnectionRecords `json:"connection_records"`
|
||||
}
|
||||
WeeklyStat {
|
||||
Day int `json:"day"`
|
||||
DayName string `json:"day_name"`
|
||||
Hours float64 `json:"hours"`
|
||||
}
|
||||
ConnectionRecords {
|
||||
CurrentContinuousDays int64 `json:"current_continuous_days"`
|
||||
HistoryContinuousDays int64 `json:"history_continuous_days"`
|
||||
LongestSingleConnection int64 `json:"longest_single_connection"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/user
|
||||
group: app/user
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "query user info"
|
||||
@handler QueryUserInfo
|
||||
get /info returns (UserInfoResponse)
|
||||
|
||||
@doc "Update Password "
|
||||
@handler UpdatePassword
|
||||
put /password (UpdatePasswordRequeset)
|
||||
|
||||
@doc "Delete Account"
|
||||
@handler DeleteAccount
|
||||
delete /account (DeleteAccountRequest)
|
||||
|
||||
@doc "Get user subcribe traffic logs"
|
||||
@handler GetUserSubscribeTrafficLogs
|
||||
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
|
||||
|
||||
@doc "Get user online time total"
|
||||
@handler GetUserOnlineTimeStatistics
|
||||
get /online_time/statistics returns (GetUserOnlineTimeStatisticsResponse)
|
||||
|
||||
@doc "Query User Affiliate List"
|
||||
@handler QueryUserAffiliateList
|
||||
get /affiliate/list (QueryUserAffiliateListRequest) returns (QueryUserAffiliateListResponse)
|
||||
|
||||
@doc "Query User Affiliate Count"
|
||||
@handler QueryUserAffiliate
|
||||
get /affiliate/count returns (QueryUserAffiliateCountResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App Heartbeat Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/ws
|
||||
group: app/ws
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "App heartbeat"
|
||||
@handler AppWs
|
||||
get /:userid/:identifier
|
||||
}
|
||||
|
||||
@@ -11,12 +11,10 @@ info (
|
||||
type (
|
||||
// User login request
|
||||
UserLoginRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// Check user is exist request
|
||||
@@ -29,25 +27,21 @@ type (
|
||||
}
|
||||
// User login response
|
||||
UserRegisterRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Invite string `json:"invite,optional"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// User login response
|
||||
ResetPasswordRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
LoginResponse {
|
||||
@@ -66,14 +60,11 @@ type (
|
||||
}
|
||||
// login request
|
||||
TelephoneLoginRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneCode string `json:"telephone_code"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// Check user is exist request
|
||||
@@ -87,27 +78,21 @@ type (
|
||||
}
|
||||
// User login response
|
||||
TelephoneRegisterRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Invite string `json:"invite,optional"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type,optional"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// User login response
|
||||
TelephoneResetPasswordRequest {
|
||||
Identifier string `json:"identifier"`
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
LoginType string `header:"Login-Type,optional"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppleLoginCallbackRequest {
|
||||
@@ -119,18 +104,11 @@ type (
|
||||
Code string `form:"code"`
|
||||
State string `form:"state"`
|
||||
}
|
||||
DeviceLoginRequest {
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `json:"user_agent" validate:"required"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/auth
|
||||
group: auth
|
||||
middleware: DeviceMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "User login"
|
||||
@@ -164,10 +142,6 @@ service ppanel {
|
||||
@doc "Reset password"
|
||||
@handler TelephoneResetPassword
|
||||
post /reset/telephone (TelephoneResetPasswordRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Device Login"
|
||||
@handler DeviceLogin
|
||||
post /login/device (DeviceLoginRequest) returns (LoginResponse)
|
||||
}
|
||||
|
||||
@server (
|
||||
|
||||
+8
-27
@@ -35,6 +35,10 @@ type (
|
||||
GetTosResponse {
|
||||
TosContent string `json:"tos_content"`
|
||||
}
|
||||
GetAppcationResponse {
|
||||
Config ApplicationConfig `json:"config"`
|
||||
Applications []ApplicationResponseInfo `json:"applications"`
|
||||
}
|
||||
// GetCodeRequest Get code request
|
||||
SendCodeRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
@@ -74,36 +78,21 @@ type (
|
||||
CheckVerificationCodeRespone {
|
||||
Status bool `json:"status"`
|
||||
}
|
||||
SubscribeClient {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
DownloadLink DownloadLink `json:"download_link,omitempty"`
|
||||
}
|
||||
GetSubscribeClientResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []SubscribeClient `json:"list"`
|
||||
}
|
||||
HeartbeatResponse {
|
||||
Status bool `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/common
|
||||
group: common
|
||||
middleware: DeviceMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get global config"
|
||||
@handler GetGlobalConfig
|
||||
get /site/config returns (GetGlobalConfigResponse)
|
||||
|
||||
@doc "Get Tos Content"
|
||||
@handler GetApplication
|
||||
get /application returns (GetAppcationResponse)
|
||||
|
||||
@doc "Get Tos Content"
|
||||
@handler GetTos
|
||||
get /site/tos returns (GetTosResponse)
|
||||
@@ -131,13 +120,5 @@ service ppanel {
|
||||
@doc "Check verification code"
|
||||
@handler CheckVerificationCode
|
||||
post /check_verification_code (CheckVerificationCodeRequest) returns (CheckVerificationCodeRespone)
|
||||
|
||||
@doc "Get Client"
|
||||
@handler GetClient
|
||||
get /client returns (GetSubscribeClientResponse)
|
||||
|
||||
@doc "Heartbeat"
|
||||
@handler Heartbeat
|
||||
get /heartbeat returns (HeartbeatResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,6 @@ info (
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
OnlineUser {
|
||||
SID int64 `json:"uid"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
ShadowsocksProtocol {
|
||||
Port int `json:"port"`
|
||||
Method string `json:"method"`
|
||||
@@ -93,20 +89,6 @@ type (
|
||||
ServerCommon
|
||||
Users []OnlineUser `json:"users"`
|
||||
}
|
||||
QueryServerConfigRequest {
|
||||
ServerID int64 `path:"server_id"`
|
||||
SecretKey string `form:"secret_key"`
|
||||
Protocols []string `form:"protocols,omitempty"`
|
||||
}
|
||||
QueryServerConfigResponse {
|
||||
TrafficReportThreshold int64 `json:"traffic_report_threshold"`
|
||||
IPStrategy string `json:"ip_strategy"`
|
||||
DNS []NodeDNS `json:"dns"`
|
||||
Block []string `json:"block"`
|
||||
Outbound []NodeOutbound `json:"outbound"`
|
||||
Protocols []Protocol `json:"protocols"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
@@ -136,13 +118,3 @@ service ppanel {
|
||||
post /online (OnlineUsersRequest)
|
||||
}
|
||||
|
||||
@server (
|
||||
prefix: v2/server
|
||||
group: server
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get Server Protocol Config"
|
||||
@handler QueryServerProtocolConfig
|
||||
get /:server_id (QueryServerConfigRequest) returns (QueryServerConfigResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import "../types.api"
|
||||
@server (
|
||||
prefix: v1/public/announcement
|
||||
group: public/announcement
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query announcement"
|
||||
|
||||
@@ -13,7 +13,7 @@ import "../types.api"
|
||||
@server (
|
||||
prefix: v1/public/document
|
||||
group: public/document
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get document list"
|
||||
|
||||
@@ -13,7 +13,7 @@ import "../types.api"
|
||||
@server (
|
||||
prefix: v1/public/order
|
||||
group: public/order
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Pre create order"
|
||||
|
||||
@@ -13,7 +13,7 @@ import "../types.api"
|
||||
@server (
|
||||
prefix: v1/public/payment
|
||||
group: public/payment
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
|
||||
@@ -25,9 +25,6 @@ type (
|
||||
PortalPurchaseResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
GetSubscriptionRequest {
|
||||
Language string `form:"language"`
|
||||
}
|
||||
GetSubscriptionResponse {
|
||||
List []Subscribe `json:"list"`
|
||||
}
|
||||
@@ -70,7 +67,6 @@ type (
|
||||
@server (
|
||||
prefix: v1/public/portal
|
||||
group: public/portal
|
||||
middleware: DeviceMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
@@ -79,7 +75,7 @@ service ppanel {
|
||||
|
||||
@doc "Get Subscription"
|
||||
@handler GetSubscription
|
||||
get /subscribe (GetSubscriptionRequest) returns (GetSubscriptionResponse)
|
||||
get /subscribe returns (GetSubscriptionResponse)
|
||||
|
||||
@doc "Pre Purchase Order"
|
||||
@handler PrePurchaseOrder
|
||||
|
||||
@@ -10,58 +10,22 @@ info (
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
QuerySubscribeListRequest {
|
||||
Language string `form:"language"`
|
||||
}
|
||||
QueryUserSubscribeNodeListResponse {
|
||||
List []UserSubscribeInfo `json:"list"`
|
||||
}
|
||||
UserSubscribeInfo {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderId int64 `json:"order_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
ExpireTime int64 `json:"expire_time"`
|
||||
FinishedAt int64 `json:"finished_at"`
|
||||
ResetTime int64 `json:"reset_time"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
Download int64 `json:"download"`
|
||||
Upload int64 `json:"upload"`
|
||||
Token string `json:"token"`
|
||||
Status uint8 `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
IsTryOut bool `json:"is_try_out"`
|
||||
Nodes []*UserSubscribeNodeInfo `json:"nodes"`
|
||||
}
|
||||
UserSubscribeNodeInfo {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Uuid string `json:"uuid"`
|
||||
Protocol string `json:"protocol"`
|
||||
Port uint16 `json:"port"`
|
||||
Address string `json:"address"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/public/subscribe
|
||||
group: public/subscribe
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get subscribe list"
|
||||
@handler QuerySubscribeList
|
||||
get /list (QuerySubscribeListRequest) returns (QuerySubscribeListResponse)
|
||||
get /list returns (QuerySubscribeListResponse)
|
||||
|
||||
@doc "Get user subscribe node info"
|
||||
@handler QueryUserSubscribeNodeList
|
||||
get /node/list returns (QueryUserSubscribeNodeListResponse)
|
||||
@doc "Get subscribe group list"
|
||||
@handler QuerySubscribeGroupList
|
||||
get /group/list returns (QuerySubscribeGroupListResponse)
|
||||
|
||||
@doc "Get application config"
|
||||
@handler QueryApplicationConfig
|
||||
get /application/config returns (ApplicationResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@ type (
|
||||
CreateUserTicketRequest {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
IssueType uint8 `json:"issue_type"`
|
||||
}
|
||||
GetUserTicketListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
IssueType *uint8 `form:"issue_type,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetUserTicketDetailRequest {
|
||||
@@ -43,7 +45,7 @@ type (
|
||||
@server (
|
||||
prefix: v1/public/ticket
|
||||
group: public/ticket
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get ticket list"
|
||||
|
||||
+9
-62
@@ -25,9 +25,16 @@ type (
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
QueryUserBalanceLogListResponse {
|
||||
List []BalanceLog `json:"list"`
|
||||
List []UserBalanceLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
CommissionLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Amount int64 `json:"amount"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
QueryUserCommissionLogListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
@@ -97,48 +104,12 @@ type (
|
||||
Email string `json:"email" validate:"required"`
|
||||
Code string `json:"code" validate:"required"`
|
||||
}
|
||||
GetDeviceListResponse {
|
||||
List []UserDevice `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
UnbindDeviceRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
UpdateUserSubscribeNoteRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"`
|
||||
Note string `json:"note" validate:"max=500"`
|
||||
}
|
||||
UpdateUserRulesRequest {
|
||||
Rules []string `json:"rules" validate:"required"`
|
||||
}
|
||||
CommissionWithdrawRequest {
|
||||
Amount int64 `json:"amount"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
WithdrawalLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
Content string `json:"content"`
|
||||
Status uint8 `json:"status"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
QueryWithdrawalLogListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
QueryWithdrawalLogListResponse {
|
||||
List []WithdrawalLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/public/user
|
||||
group: public/user
|
||||
middleware: AuthMiddleware,DeviceMiddleware
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query User Info"
|
||||
@@ -228,29 +199,5 @@ service ppanel {
|
||||
@doc "Update Bind Email"
|
||||
@handler UpdateBindEmail
|
||||
put /bind_email (UpdateBindEmailRequest)
|
||||
|
||||
@doc "Get Device List"
|
||||
@handler GetDeviceList
|
||||
get /devices returns (GetDeviceListResponse)
|
||||
|
||||
@doc "Unbind Device"
|
||||
@handler UnbindDevice
|
||||
put /unbind_device (UnbindDeviceRequest)
|
||||
|
||||
@doc "Update User Subscribe Note"
|
||||
@handler UpdateUserSubscribeNote
|
||||
put /subscribe_note (UpdateUserSubscribeNoteRequest)
|
||||
|
||||
@doc "Update User Rules"
|
||||
@handler UpdateUserRules
|
||||
put /rules (UpdateUserRulesRequest)
|
||||
|
||||
@doc "Commission Withdraw"
|
||||
@handler CommissionWithdraw
|
||||
post /commission_withdraw (CommissionWithdrawRequest) returns (WithdrawalLog)
|
||||
|
||||
@doc "Query Withdrawal Log"
|
||||
@handler QueryWithdrawalLog
|
||||
get /withdrawal_log (QueryWithdrawalLogListRequest) returns (QueryWithdrawalLogListResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,5 @@ import (
|
||||
"./admin/auth.api"
|
||||
"./admin/log.api"
|
||||
"./admin/ads.api"
|
||||
"./admin/marketing.api"
|
||||
"./admin/application.api"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"./app/auth.api"
|
||||
"./app/user.api"
|
||||
"./app/node.api"
|
||||
"./app/ws.api"
|
||||
"./app/order.api"
|
||||
"./app/announcement.api"
|
||||
"./app/payment.api"
|
||||
"./app/document.api"
|
||||
"./app/subscribe.api"
|
||||
)
|
||||
|
||||
+57
-149
@@ -14,8 +14,6 @@ type (
|
||||
Avatar string `json:"avatar"`
|
||||
Balance int64 `json:"balance"`
|
||||
Commission int64 `json:"commission"`
|
||||
ReferralPercentage uint8 `json:"referral_percentage"`
|
||||
OnlyFirstPurchase bool `json:"only_first_purchase"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Telegram int64 `json:"telegram"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
@@ -28,7 +26,6 @@ type (
|
||||
EnableTradeNotify bool `json:"enable_trade_notify"`
|
||||
AuthMethods []UserAuthMethod `json:"auth_methods"`
|
||||
UserDevices []UserDevice `json:"user_devices"`
|
||||
Rules []string `json:"rules"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
DeletedAt int64 `json:"deleted_at,omitempty"`
|
||||
@@ -66,8 +63,6 @@ type (
|
||||
SubscribePath string `json:"subscribe_path"`
|
||||
SubscribeDomain string `json:"subscribe_domain"`
|
||||
PanDomain bool `json:"pan_domain"`
|
||||
UserAgentLimit bool `json:"user_agent_limit"`
|
||||
UserAgentList string `json:"user_agent_list"`
|
||||
}
|
||||
VerifyCodeConfig {
|
||||
VerifyCodeExpireTime int64 `json:"verify_code_expire_time"`
|
||||
@@ -116,7 +111,6 @@ type (
|
||||
AuthConfig {
|
||||
Mobile MobileAuthenticateConfig `json:"mobile"`
|
||||
Email EmailAuthticateConfig `json:"email"`
|
||||
Device DeviceAuthticateConfig `json:"device"`
|
||||
Register PubilcRegisterConfig `json:"register"`
|
||||
}
|
||||
PubilcRegisterConfig {
|
||||
@@ -136,12 +130,6 @@ type (
|
||||
EnableDomainSuffix bool `json:"enable_domain_suffix"`
|
||||
DomainSuffixList string `json:"domain_suffix_list"`
|
||||
}
|
||||
DeviceAuthticateConfig {
|
||||
Enable bool `json:"enable"`
|
||||
ShowAds bool `json:"show_ads"`
|
||||
EnableSecurity bool `json:"enable_security"`
|
||||
OnlyRealDevice bool `json:"only_real_device"`
|
||||
}
|
||||
RegisterConfig {
|
||||
StopRegister bool `json:"stop_register"`
|
||||
EnableTrial bool `json:"enable_trial"`
|
||||
@@ -163,24 +151,6 @@ type (
|
||||
NodeSecret string `json:"node_secret"`
|
||||
NodePullInterval int64 `json:"node_pull_interval"`
|
||||
NodePushInterval int64 `json:"node_push_interval"`
|
||||
TrafficReportThreshold int64 `json:"traffic_report_threshold"`
|
||||
IPStrategy string `json:"ip_strategy"`
|
||||
DNS []NodeDNS `json:"dns"`
|
||||
Block []string `json:"block"`
|
||||
Outbound []NodeOutbound `json:"outbound"`
|
||||
}
|
||||
NodeDNS {
|
||||
Proto string `json:"proto"`
|
||||
Address string `json:"address"`
|
||||
Domains []string `json:"domains"`
|
||||
}
|
||||
NodeOutbound {
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
Address string `json:"address"`
|
||||
Port int64 `json:"port"`
|
||||
Password string `json:"password"`
|
||||
Rules []string `json:"rules"`
|
||||
}
|
||||
InviteConfig {
|
||||
ForcedInvite bool `json:"forced_invite"`
|
||||
@@ -212,7 +182,6 @@ type (
|
||||
Subscribe {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Language string `json:"language"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
@@ -223,8 +192,9 @@ type (
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
Nodes []int64 `json:"nodes"`
|
||||
NodeTags []string `json:"node_tags"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show bool `json:"show"`
|
||||
Sell bool `json:"sell"`
|
||||
Sort int64 `json:"sort"`
|
||||
@@ -303,37 +273,37 @@ type (
|
||||
Host string `json:"host"`
|
||||
ServiceName string `json:"service_name"`
|
||||
}
|
||||
// Server {
|
||||
// Id int64 `json:"id"`
|
||||
// Tags []string `json:"tags"`
|
||||
// Country string `json:"country"`
|
||||
// City string `json:"city"`
|
||||
// Name string `json:"name"`
|
||||
// ServerAddr string `json:"server_addr"`
|
||||
// RelayMode string `json:"relay_mode"`
|
||||
// RelayNode []NodeRelay `json:"relay_node"`
|
||||
// SpeedLimit int `json:"speed_limit"`
|
||||
// TrafficRatio float32 `json:"traffic_ratio"`
|
||||
// GroupId int64 `json:"group_id"`
|
||||
// Protocol string `json:"protocol"`
|
||||
// Config interface{} `json:"config"`
|
||||
// Enable *bool `json:"enable"`
|
||||
// CreatedAt int64 `json:"created_at"`
|
||||
// UpdatedAt int64 `json:"updated_at"`
|
||||
// Status *NodeStatus `json:"status"`
|
||||
// Sort int64 `json:"sort"`
|
||||
// }
|
||||
// OnlineUser {
|
||||
// SID int64 `json:"uid"`
|
||||
// IP string `json:"ip"`
|
||||
// }
|
||||
// NodeStatus {
|
||||
// Online interface{} `json:"online"`
|
||||
// Cpu float64 `json:"cpu"`
|
||||
// Mem float64 `json:"mem"`
|
||||
// Disk float64 `json:"disk"`
|
||||
// UpdatedAt int64 `json:"updated_at"`
|
||||
// }
|
||||
Server {
|
||||
Id int64 `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Name string `json:"name"`
|
||||
ServerAddr string `json:"server_addr"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol"`
|
||||
Config interface{} `json:"config"`
|
||||
Enable *bool `json:"enable"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
Status *NodeStatus `json:"status"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
OnlineUser {
|
||||
SID int64 `json:"uid"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
NodeStatus {
|
||||
Online interface{} `json:"online"`
|
||||
Cpu float64 `json:"cpu"`
|
||||
Mem float64 `json:"mem"`
|
||||
Disk float64 `json:"disk"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
ServerGroup {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -472,10 +442,18 @@ type (
|
||||
Upload int64 `json:"upload"`
|
||||
Token string `json:"token"`
|
||||
Status uint8 `json:"status"`
|
||||
Short string `json:"short"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
UserBalanceLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
Type uint8 `json:"type"`
|
||||
OrderId int64 `json:"order_id"`
|
||||
Balance int64 `json:"balance"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
UserAffiliate {
|
||||
Avatar string `json:"avatar"`
|
||||
Identifier string `json:"identifier"`
|
||||
@@ -496,6 +474,14 @@ type (
|
||||
Port int `json:"port"`
|
||||
Prefix string `json:"prefix"`
|
||||
}
|
||||
ApplicationConfig {
|
||||
AppId int64 `json:"app_id"`
|
||||
EncryptionKey string `json:"encryption_key"`
|
||||
EncryptionMethod string `json:"encryption_method"`
|
||||
Domains []string `json:"domains" validate:"required"`
|
||||
StartupPicture string `json:"startup_picture"`
|
||||
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
|
||||
}
|
||||
UserDevice {
|
||||
Id int64 `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
@@ -545,7 +531,7 @@ type (
|
||||
Token string `json:"token"`
|
||||
IP string `json:"ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
UserLoginLog {
|
||||
Id int64 `json:"id"`
|
||||
@@ -553,17 +539,18 @@ type (
|
||||
LoginIP string `json:"login_ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Success bool `json:"success"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
MessageLog {
|
||||
Id int64 `json:"id"`
|
||||
Type uint8 `json:"type"`
|
||||
Type string `json:"type"`
|
||||
Platform string `json:"platform"`
|
||||
To string `json:"to"`
|
||||
Subject string `json:"subject"`
|
||||
Content interface{} `json:"content"`
|
||||
Status uint8 `json:"status"`
|
||||
Content string `json:"content"`
|
||||
Status int `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Ads {
|
||||
Id int `json:"id"`
|
||||
@@ -767,84 +754,5 @@ type (
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
DownloadLink {
|
||||
IOS string `json:"ios,omitempty"`
|
||||
Android string `json:"android,omitempty"`
|
||||
Windows string `json:"windows,omitempty"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Linux string `json:"linux,omitempty"`
|
||||
Harmony string `json:"harmony,omitempty"`
|
||||
}
|
||||
ResetSubscribeTrafficLog {
|
||||
Id int64 `json:"id"`
|
||||
Type uint16 `json:"type"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
OrderNo string `json:"order_no,omitempty"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
BalanceLog {
|
||||
Type uint16 `json:"type"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
OrderNo string `json:"order_no,omitempty"`
|
||||
Balance int64 `json:"balance"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
CommissionLog {
|
||||
Type uint16 `json:"type"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
Protocol {
|
||||
Type string `json:"type"`
|
||||
Port uint16 `json:"port"`
|
||||
Enable bool `json:"enable"`
|
||||
Security string `json:"security,omitempty"`
|
||||
SNI string `json:"sni,omitempty"`
|
||||
AllowInsecure bool `json:"allow_insecure,omitempty"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
RealityServerAddr string `json:"reality_server_addr,omitempty"`
|
||||
RealityServerPort int `json:"reality_server_port,omitempty"`
|
||||
RealityPrivateKey string `json:"reality_private_key,omitempty"`
|
||||
RealityPublicKey string `json:"reality_public_key,omitempty"`
|
||||
RealityShortId string `json:"reality_short_id,omitempty"`
|
||||
Transport string `json:"transport,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
ServiceName string `json:"service_name,omitempty"`
|
||||
Cipher string `json:"cipher,omitempty"`
|
||||
ServerKey string `json:"server_key,omitempty"`
|
||||
Flow string `json:"flow,omitempty"`
|
||||
HopPorts string `json:"hop_ports,omitempty"`
|
||||
HopInterval int `json:"hop_interval,omitempty"`
|
||||
ObfsPassword string `json:"obfs_password,omitempty"`
|
||||
DisableSNI bool `json:"disable_sni,omitempty"`
|
||||
ReduceRtt bool `json:"reduce_rtt,omitempty"`
|
||||
UDPRelayMode string `json:"udp_relay_mode,omitempty"`
|
||||
CongestionController string `json:"congestion_controller,omitempty"`
|
||||
Multiplex string `json:"multiplex,omitempty"` // mux, eg: off/low/medium/high
|
||||
PaddingScheme string `json:"padding_scheme,omitempty"` // padding scheme
|
||||
UpMbps int `json:"up_mbps,omitempty"` // upload speed limit
|
||||
DownMbps int `json:"down_mbps,omitempty"` // download speed limit
|
||||
Obfs string `json:"obfs,omitempty"` // obfs, 'none', 'http', 'tls'
|
||||
ObfsHost string `json:"obfs_host,omitempty"` // obfs host
|
||||
ObfsPath string `json:"obfs_path,omitempty"` // obfs path
|
||||
XhttpMode string `json:"xhttp_mode,omitempty"` // xhttp mode
|
||||
XhttpExtra string `json:"xhttp_extra,omitempty"` // xhttp extra path
|
||||
Encryption string `json:"encryption,omitempty"` // encryption,'none', 'mlkem768x25519plus'
|
||||
EncryptionMode string `json:"encryption_mode,omitempty"` // encryption mode,'native', 'xorpub', 'random'
|
||||
EncryptionRtt string `json:"encryption_rtt,omitempty"` // encryption rtt,'0rtt', '1rtt'
|
||||
EncryptionTicket string `json:"encryption_ticket,omitempty"` // encryption ticket
|
||||
EncryptionServerPadding string `json:"encryption_server_padding,omitempty"` // encryption server padding
|
||||
EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key
|
||||
EncryptionClientPadding string `json:"encryption_client_padding,omitempty"` // encryption client padding
|
||||
EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password
|
||||
Ratio float64 `json:"ratio,omitempty"` // Traffic ratio, default is 1
|
||||
CertMode string `json:"cert_mode,omitempty"` // Certificate mode, `none`|`http`|`dns`|`self`
|
||||
CertDNSProvider string `json:"cert_dns_provider,omitempty"` // DNS provider for certificate
|
||||
CertDNSEnv string `json:"cert_dns_env,omitempty"` // Environment for DNS provider
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/perfect-panel/server/initialize"
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/conf"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
migrateCmd.Flags().StringVar(&migrateConfigPath, "config", "etc/ppanel.yaml", "ppanel.yaml directory to read from")
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
}
|
||||
|
||||
var (
|
||||
migrateConfigPath string
|
||||
)
|
||||
|
||||
var migrateCmd = &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Run database migrations",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
runMigrate()
|
||||
},
|
||||
}
|
||||
|
||||
func runMigrate() {
|
||||
var c config.Config
|
||||
conf.MustLoad(migrateConfigPath, &c)
|
||||
if err := logger.SetUp(c.Logger); err != nil {
|
||||
fmt.Println("Logger setup failed:", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := svc.NewServiceContext(c)
|
||||
initialize.Migrate(ctx)
|
||||
logger.Info("[Migrate] database migration completed")
|
||||
}
|
||||
+15
-3
@@ -2,11 +2,11 @@ Host: 0.0.0.0
|
||||
Port: 8080
|
||||
Debug: false
|
||||
JwtAuth:
|
||||
AccessSecret: 1234567890
|
||||
AccessSecret: e4bbdb8ca57179374c0e8a7a85038da21341aee4bdff98c0e612751d7c362cac
|
||||
AccessExpire: 604800
|
||||
Logger:
|
||||
ServiceName: PPanel
|
||||
Mode: console
|
||||
Mode: file
|
||||
Encoding: plain
|
||||
TimeFormat: '2025-01-01 00:00:00.000'
|
||||
Path: logs
|
||||
@@ -21,7 +21,7 @@ Logger:
|
||||
Rotation: daily
|
||||
FileTimeFormat: 2025-01-01T00:00:00.000Z00:00
|
||||
MySQL:
|
||||
Addr: 172.245.180.199:3306
|
||||
Addr: ppanel-db:3306
|
||||
Dbname: ppanel
|
||||
Username: ppanel
|
||||
Password: ppanelpassword
|
||||
@@ -36,3 +36,15 @@ Redis:
|
||||
Administrator:
|
||||
Password: password
|
||||
Email: admin@ppanel.dev
|
||||
Email:
|
||||
Enable: true
|
||||
Platform: smtp
|
||||
PlatformConfig: '{"host":"smtp.gmail.com","port":465,"user":"devneeds52@gmail.com","pass":"bqxn hurw ckxt ookj","from":"devneeds52@gmail.com","ssl":true}'
|
||||
EnableVerify: true
|
||||
EnableNotify: true
|
||||
EnableDomainSuffix: false
|
||||
DomainSuffixList: ""
|
||||
VerifyEmailTemplate: ""
|
||||
ExpirationEmailTemplate: ""
|
||||
MaintenanceEmailTemplate: ""
|
||||
TrafficExceedEmailTemplate: ""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -20,7 +20,7 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/hibiken/asynq v0.24.1
|
||||
@@ -28,7 +28,7 @@ require (
|
||||
github.com/klauspost/compress v1.17.7
|
||||
github.com/nyaruka/phonenumbers v1.5.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/redis/go-redis/v9 v9.7.2
|
||||
github.com/redis/go-redis/v9 v9.6.1
|
||||
github.com/smartwalle/alipay/v3 v3.2.23
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1
|
||||
@@ -44,7 +44,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.29.0
|
||||
go.opentelemetry.io/otel/trace v1.29.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.35.0
|
||||
golang.org/x/crypto v0.32.0
|
||||
golang.org/x/oauth2 v0.25.0
|
||||
golang.org/x/time v0.6.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
@@ -60,7 +60,6 @@ require (
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/goccy/go-json v0.10.4
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2
|
||||
github.com/oschwald/geoip2-golang v1.13.0
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
google.golang.org/grpc v1.64.1
|
||||
google.golang.org/protobuf v1.36.3
|
||||
@@ -118,7 +117,6 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.2 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.13.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
@@ -140,8 +138,8 @@ require (
|
||||
golang.org/x/arch v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
|
||||
@@ -155,8 +155,8 @@ github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -285,10 +285,6 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
|
||||
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
|
||||
github.com/oschwald/geoip2-golang v1.13.0 h1:Q44/Ldc703pasJeP5V9+aFSZFmBN7DKHbNsSFzQATJI=
|
||||
github.com/oschwald/geoip2-golang v1.13.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
|
||||
github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
|
||||
github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -298,8 +294,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||
github.com/redis/go-redis/v9 v9.7.2 h1:PSGhv13dJyrTCw1+55H0pIKM3WFov7HuUrKUmInGL0o=
|
||||
github.com/redis/go-redis/v9 v9.7.2/go.mod h1:yp5+a5FnEEP0/zTYuw6u6/2nn3zivwhv274qYgWQhDM=
|
||||
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
@@ -406,8 +402,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d h1:N0hmiNbwsSNwHBAvR3QB5w25pUwH4tK0Y/RltD1j1h4=
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
@@ -467,8 +463,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -482,8 +478,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
|
||||
+1
-22
@@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/perfect-panel/server/internal/report"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"gorm.io/driver/mysql"
|
||||
|
||||
@@ -36,30 +35,10 @@ func Config(path string) (chan bool, *http.Server) {
|
||||
configPath = path
|
||||
// Create a new Gin instance
|
||||
r := gin.Default()
|
||||
// get server port
|
||||
port := 8080
|
||||
host := "127.0.0.1"
|
||||
|
||||
// check gateway mode
|
||||
if report.IsGatewayMode() {
|
||||
// get free port
|
||||
freePort, err := report.ModulePort()
|
||||
if err != nil {
|
||||
logger.Errorf("get module port error: %s", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
port = freePort
|
||||
// register module
|
||||
err = report.RegisterModule(port)
|
||||
if err != nil {
|
||||
logger.Errorf("register module error: %s", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
logger.Infof("module registered on port %d", port)
|
||||
}
|
||||
// Create a new HTTP server
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", host, port),
|
||||
Addr: ":8080",
|
||||
Handler: r,
|
||||
}
|
||||
// Load templates
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/model/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
)
|
||||
|
||||
func Device(ctx *svc.ServiceContext) {
|
||||
logger.Debug("device config initialization")
|
||||
method, err := ctx.AuthModel.FindOneByMethod(context.Background(), "device")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var cfg config.DeviceConfig
|
||||
var deviceConfig auth.DeviceConfig
|
||||
deviceConfig.Unmarshal(method.Config)
|
||||
tool.DeepCopy(&cfg, deviceConfig)
|
||||
cfg.Enable = *method.Enabled
|
||||
ctx.Config.Device = cfg
|
||||
}
|
||||
+1
-1
@@ -9,12 +9,12 @@ func StartInitSystemConfig(svc *svc.ServiceContext) {
|
||||
Site(svc)
|
||||
Node(svc)
|
||||
Email(svc)
|
||||
Device(svc)
|
||||
Invite(svc)
|
||||
Verify(svc)
|
||||
Subscribe(svc)
|
||||
Register(svc)
|
||||
Mobile(svc)
|
||||
TrafficDataToRedis(svc)
|
||||
if !svc.Config.Debug {
|
||||
Telegram(svc)
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ CREATE TABLE IF NOT EXISTS `auth_method`
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_auth_method` (`method`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 9
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
@@ -304,6 +305,7 @@ CREATE TABLE IF NOT EXISTS `subscribe_type`
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 15
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
@@ -321,6 +323,7 @@ CREATE TABLE IF NOT EXISTS `system`
|
||||
UNIQUE KEY `uni_system_key` (`key`),
|
||||
KEY `index_key` (`key`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 42
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
@@ -379,6 +382,7 @@ CREATE TABLE IF NOT EXISTS `user`
|
||||
`referer_id` bigint DEFAULT NULL COMMENT 'Referrer ID',
|
||||
`commission` bigint DEFAULT '0' COMMENT 'Commission',
|
||||
`gift_amount` bigint DEFAULT '0' COMMENT 'User Gift Amount',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'User Remark',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Is Account Enabled',
|
||||
`is_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Admin',
|
||||
`valid_email` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Email Verified',
|
||||
@@ -395,6 +399,7 @@ CREATE TABLE IF NOT EXISTS `user`
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_referer` (`referer_id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 2
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
@@ -411,6 +416,7 @@ CREATE TABLE IF NOT EXISTS `user_auth_methods`
|
||||
UNIQUE KEY `idx_auth_identifier` (`auth_identifier`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 2
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE IF EXISTS `email_task`;
|
||||
@@ -1,23 +0,0 @@
|
||||
DROP TABLE IF EXISTS `email_task`;
|
||||
CREATE TABLE `email_task` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`subject` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Email Subject',
|
||||
`content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Email Content',
|
||||
`recipient` text COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Email Recipient',
|
||||
`scope` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Email Scope',
|
||||
`register_start_time` datetime(3) DEFAULT NULL COMMENT 'Register Start Time',
|
||||
`register_end_time` datetime(3) DEFAULT NULL COMMENT 'Register End Time',
|
||||
`additional` text COLLATE utf8mb4_general_ci COMMENT 'Additional Information',
|
||||
`scheduled` datetime(3) NOT NULL COMMENT 'Scheduled Time',
|
||||
`interval` tinyint unsigned NOT NULL COMMENT 'Interval in Seconds',
|
||||
`limit` bigint unsigned NOT NULL COMMENT 'Daily send limit',
|
||||
`status` tinyint unsigned NOT NULL COMMENT 'Daily Status',
|
||||
`errors` text COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Errors',
|
||||
`total` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Total Number',
|
||||
`current` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Current Number',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE IF EXISTS `subscribe_application`;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +0,0 @@
|
||||
INSERT IGNORE INTO `system` (`id`, `category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
VALUES
|
||||
(42, 'subscribe', 'UserAgentLimit', 'false', 'bool', 'User Agent Limit', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
(43, 'subscribe', 'UserAgentList', '', 'string', 'User Agent List', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637');
|
||||
@@ -1,3 +0,0 @@
|
||||
DROP TABLE IF EXISTS `application`;
|
||||
DROP TABLE IF EXISTS `application_version`;
|
||||
DROP TABLE IF EXISTS `application_config`;
|
||||
@@ -1,106 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS `user_balance_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Recharge 2: Withdraw 3: Payment 4: Refund 5: Reward',
|
||||
`order_id` bigint DEFAULT NULL COMMENT 'Order ID',
|
||||
`balance` bigint NOT NULL COMMENT 'Balance',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_commission_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_gift_amount_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`user_subscribe_id` bigint DEFAULT NULL COMMENT 'Deduction User Subscribe ID',
|
||||
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
|
||||
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Increase 2: Reduce',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`balance` bigint NOT NULL COMMENT 'Balance',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Remark',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_login_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Login IP',
|
||||
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
|
||||
`success` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Login Success',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_reset_subscribe_log`
|
||||
(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`user_id` BIGINT NOT NULL COMMENT 'User ID',
|
||||
`type` TINYINT(1) NOT NULL COMMENT 'Type: 1: Auto 2: Advance 3: Paid',
|
||||
`order_no` VARCHAR(255) DEFAULT NULL COMMENT 'Order No.',
|
||||
`user_subscribe_id` BIGINT NOT NULL COMMENT 'User Subscribe ID',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
|
||||
INDEX `idx_user_id` (`user_id`),
|
||||
INDEX `idx_user_subscribe_id` (`user_subscribe_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_subscribe_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`user_subscribe_id` bigint NOT NULL COMMENT 'User Subscribe ID',
|
||||
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Token',
|
||||
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP',
|
||||
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_user_subscribe_id` (`user_subscribe_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `message_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'email' COMMENT 'Message Type',
|
||||
`platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'smtp' COMMENT 'Platform',
|
||||
`to` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'To',
|
||||
`subject` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Subject',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Content',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Status',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
DROP TABLE IF EXISTS `system_logs`;
|
||||
@@ -1,19 +0,0 @@
|
||||
DROP TABLE IF EXISTS `user_balance_log`;
|
||||
DROP TABLE IF EXISTS `user_commission_log`;
|
||||
DROP TABLE IF EXISTS `user_gift_amount_log`;
|
||||
DROP TABLE IF EXISTS `user_login_log`;
|
||||
DROP TABLE IF EXISTS `user_reset_subscribe_log`;
|
||||
DROP TABLE IF EXISTS `user_subscribe_log`;
|
||||
DROP TABLE IF EXISTS `message_log`;
|
||||
DROP TABLE IF EXISTS `system_logs`;
|
||||
CREATE TABLE `system_logs` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`type` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Log Type: 1: Email Message 2: Mobile Message 3: Subscribe 4: Subscribe Traffic 5: Server Traffic 6: Login 7: Register 8: Balance 9: Commission 10: Reset Subscribe 11: Gift',
|
||||
`date` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Log Date',
|
||||
`object_id` bigint NOT NULL DEFAULT '0' COMMENT 'Object ID',
|
||||
`content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Log Content',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_type` (`type`),
|
||||
KEY `idx_object_id` (`object_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@@ -1,2 +0,0 @@
|
||||
DROP TABLE IF EXISTS `nodes`;
|
||||
DROP TABLE IF EXISTS `servers`;
|
||||
@@ -1,28 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS `servers` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Server Name',
|
||||
`country` varchar(128) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Country',
|
||||
`city` varchar(128) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'City',
|
||||
`ratio` decimal(4,2) NOT NULL DEFAULT '0.00' COMMENT 'Traffic Ratio',
|
||||
`address` varchar(100) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Server Address',
|
||||
`sort` bigint NOT NULL DEFAULT '0' COMMENT 'Sort',
|
||||
`protocols` text COLLATE utf8mb4_general_ci COMMENT 'Protocol',
|
||||
`last_reported_at` datetime(3) DEFAULT NULL COMMENT 'Last Reported Time',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nodes` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Node Name',
|
||||
`tags` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Tags',
|
||||
`port` smallint unsigned NOT NULL DEFAULT '0' COMMENT 'Connect Port',
|
||||
`address` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Connect Address',
|
||||
`server_id` bigint NOT NULL DEFAULT '0' COMMENT 'Server ID',
|
||||
`protocol` varchar(100) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Protocol',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Enabled',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@@ -1,5 +0,0 @@
|
||||
ALTER TABLE `subscribe`
|
||||
DROP COLUMN `nodes`,
|
||||
DROP COLUMN `node_tags`,
|
||||
ADD COLUMN `server` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Server',
|
||||
ADD COLUMN `server_group` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Server Group';
|
||||
@@ -1,7 +0,0 @@
|
||||
ALTER TABLE `subscribe`
|
||||
ADD COLUMN `nodes` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node IDs',
|
||||
ADD COLUMN `node_tags` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node Tags',
|
||||
DROP COLUMN `server`,
|
||||
DROP COLUMN `server_group`;
|
||||
|
||||
DROP TABLE IF EXISTS `server_rule_group`;
|
||||
@@ -1,4 +0,0 @@
|
||||
INSERT IGNORE INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
VALUES
|
||||
('log', 'AutoClear', 'true', 'bool', 'Auto Clear Log', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
('log', 'ClearDays', '7', 'int', 'Clear Days', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637');
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE `user`
|
||||
DROP COLUMN `referral_percentage`,
|
||||
DROP COLUMN `only_first_purchase`;
|
||||
@@ -1,7 +0,0 @@
|
||||
ALTER TABLE `user`
|
||||
ADD COLUMN `referral_percentage` TINYINT UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Referral Percentage'
|
||||
AFTER `commission`,
|
||||
ADD COLUMN `only_first_purchase` TINYINT(1) NOT NULL DEFAULT 1
|
||||
COMMENT 'Only First Purchase'
|
||||
AFTER `referral_percentage`;
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `nodes`
|
||||
DROP COLUMN `sort`;
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE `nodes`
|
||||
ADD COLUMN `sort` INT UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Sort' AFTER `enabled`;
|
||||
@@ -1 +0,0 @@
|
||||
DROP INDEX idx_traffic_log_time_user_sub ON traffic_log;
|
||||
@@ -1 +0,0 @@
|
||||
CREATE INDEX idx_traffic_log_time_user_sub ON traffic_log (timestamp, user_id, subscribe_id);
|
||||
@@ -1,2 +0,0 @@
|
||||
DROP TABLE IF EXISTS `subscribe_type`;
|
||||
DROP TABLE IF EXISTS `sms`;
|
||||
@@ -1,2 +0,0 @@
|
||||
DROP TABLE IF EXISTS `subscribe_type`;
|
||||
DROP TABLE IF EXISTS `sms`;
|
||||
@@ -1,7 +0,0 @@
|
||||
ALTER TABLE `subscribe`
|
||||
DROP COLUMN `group_id`,
|
||||
ADD COLUMN `language` VARCHAR(255) NOT NULL DEFAULT ''
|
||||
COMMENT 'Language'
|
||||
AFTER `name`;
|
||||
|
||||
DROP TABLE IF EXISTS `subscribe_group`;
|
||||
@@ -1,14 +0,0 @@
|
||||
DROP TABLE IF EXISTS `email_task`;
|
||||
CREATE TABLE `task` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`type` tinyint NOT NULL COMMENT 'Task Type',
|
||||
`scope` text COLLATE utf8mb4_general_ci COMMENT 'Task Scope',
|
||||
`content` text COLLATE utf8mb4_general_ci COMMENT 'Task Content',
|
||||
`status` tinyint NOT NULL DEFAULT '0' COMMENT 'Task Status: 0: Pending, 1: In Progress, 2: Completed, 3: Failed',
|
||||
`errors` text COLLATE utf8mb4_general_ci COMMENT 'Task Errors',
|
||||
`total` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Total Number',
|
||||
`current` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Current Number',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@@ -1,8 +0,0 @@
|
||||
INSERT
|
||||
IGNORE INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
VALUE
|
||||
('server', 'TrafficReportThreshold', '0', 'int', 'Traffic report threshold', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'),
|
||||
('server', 'IPStrategy', '', 'string', 'IP Strategy', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'),
|
||||
('server', 'DNS', '', 'string', 'DNS', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'),
|
||||
('server', 'Block', '', 'string', 'Block', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'),
|
||||
('server', 'Outbound', '', 'string', 'Proxy Outbound', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637');
|
||||
@@ -1,20 +0,0 @@
|
||||
-- 只有当 ads 表中不存在 description 字段时才添加
|
||||
SET
|
||||
@col_exists := (
|
||||
SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'ads'
|
||||
AND COLUMN_NAME = 'description'
|
||||
);
|
||||
|
||||
SET
|
||||
@query := IF(
|
||||
@col_exists = 0,
|
||||
'ALTER TABLE `ads` ADD COLUMN `description` VARCHAR(255) DEFAULT '''' COMMENT ''Description'';',
|
||||
'SELECT "Column `description` already exists"'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @query;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE `user`
|
||||
DROP COLUMN `algo`,
|
||||
DROP COLUMN `salt`;
|
||||
@@ -1,35 +0,0 @@
|
||||
-- 添加 algo 列(如果不存在)
|
||||
SET @dbname = DATABASE();
|
||||
SET @tablename = 'user';
|
||||
SET @colname = 'algo';
|
||||
SET @sql = (
|
||||
SELECT IF(
|
||||
COUNT(*) = 0,
|
||||
'ALTER TABLE `user` ADD COLUMN `algo` VARCHAR(20) NOT NULL DEFAULT ''default'' COMMENT ''Encryption Algorithm'' AFTER `password`;',
|
||||
'SELECT "Column `algo` already exists";'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @dbname
|
||||
AND TABLE_NAME = @tablename
|
||||
AND COLUMN_NAME = @colname
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 添加 salt 列(如果不存在)
|
||||
SET @colname = 'salt';
|
||||
SET @sql = (
|
||||
SELECT IF(
|
||||
COUNT(*) = 0,
|
||||
'ALTER TABLE `user` ADD COLUMN `salt` VARCHAR(20) NOT NULL DEFAULT ''default'' COMMENT ''Password Salt'' AFTER `algo`;',
|
||||
'SELECT "Column `salt` already exists";'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @dbname
|
||||
AND TABLE_NAME = @tablename
|
||||
AND COLUMN_NAME = @colname
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -1,7 +0,0 @@
|
||||
INSERT INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
SELECT 'site', 'CustomData', '{
|
||||
"kr_website_id": ""
|
||||
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `system` WHERE `category` = 'site' AND `key` = 'CustomData'
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
INSERT INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
SELECT 'site', 'CustomData', '{
|
||||
"kr_website_id": ""
|
||||
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `system` WHERE `category` = 'site' AND `key` = 'CustomData'
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE traffic_log DROP INDEX idx_timestamp;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE traffic_log ADD INDEX idx_timestamp (timestamp);
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `user_subscribe`
|
||||
DROP COLUMN `note`;
|
||||
@@ -1,4 +0,0 @@
|
||||
ALTER TABLE `user_subscribe`
|
||||
ADD COLUMN `note` VARCHAR(500) NOT NULL DEFAULT ''
|
||||
COMMENT 'User note for subscription'
|
||||
AFTER `status`;
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `user`
|
||||
DROP COLUMN IF EXISTS `rules`;
|
||||
@@ -1,4 +0,0 @@
|
||||
ALTER TABLE `user`
|
||||
ADD COLUMN `rules` TEXT NULL
|
||||
COMMENT 'User rules for subscription'
|
||||
AFTER `created_at`;
|
||||
@@ -1,5 +0,0 @@
|
||||
DROP TABLE IF EXISTS `withdrawals`;
|
||||
|
||||
DELETE FROM `system`
|
||||
WHERE `category` = 'invite'
|
||||
AND `key` = 'WithdrawalMethod';
|
||||
@@ -1,16 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS `withdrawals` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
|
||||
`user_id` BIGINT NOT NULL COMMENT 'User ID',
|
||||
`amount` BIGINT NOT NULL COMMENT 'Withdrawal Amount',
|
||||
`content` TEXT COMMENT 'Withdrawal Content',
|
||||
`status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Withdrawal Status',
|
||||
`reason` VARCHAR(500) NOT NULL DEFAULT '' COMMENT 'Rejection Reason',
|
||||
`created_at` DATETIME NOT NULL COMMENT 'Creation Time',
|
||||
`updated_at` DATETIME NOT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT IGNORE INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
VALUES
|
||||
('invite', 'WithdrawalMethod', '', 'string', 'withdrawal method', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637');
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user