Compare commits

..

79 Commits

Author SHA1 Message Date
shanshanzhong147 b650b1a108 tg
Build docker and publish / build (20.15.1) (push) Successful in 6m13s
2025-09-29 17:45:09 -07:00
shanshanzhong147 efc5be5142 maindev
Build docker and publish / build (20.15.1) (push) Failing after 6m30s
2025-09-29 17:32:10 -07:00
shanshanzhong147 5c43bd7a3d init
Build docker and publish / build (20.15.1) (push) Failing after 9m55s
2025-09-27 10:52:39 -07:00
shanshanzhong147 30bbb33129 init
Build docker and publish / build (20.15.1) (push) Failing after 6m3s
2025-09-26 21:49:16 -07:00
shanshanzhong147 66e753e69b x
Build docker and publish / build (20.15.1) (push) Failing after 6m2s
2025-09-26 21:04:11 -07:00
shanshanzhong147 93fcaace26 x
Build docker and publish / build (20.15.1) (push) Failing after 5m51s
2025-09-26 20:12:09 -07:00
shanshanzhong147 97bb873bb8 x
Build docker and publish / build (20.15.1) (push) Failing after 5m41s
2025-09-26 19:46:56 -07:00
shanshanzhong147 723ceddc3d x
Build docker and publish / build (20.15.1) (push) Failing after 5m24s
2025-09-26 19:34:49 -07:00
shanshanzhong147 be532bec1b x
Build docker and publish / build (20.15.1) (push) Failing after 5m23s
2025-09-26 19:25:47 -07:00
shanshanzhong147 e788693713 x
Build docker and publish / build (20.15.1) (push) Failing after 5m33s
2025-09-26 19:16:32 -07:00
shanshanzhong147 aaa6cb149c x
Build docker and publish / build (20.15.1) (push) Failing after 10m26s
2025-09-26 19:05:02 -07:00
shanshanzhong147 6a146f0898 x
Build docker and publish / build (20.15.1) (push) Failing after 1m1s
2025-09-26 19:00:51 -07:00
shanshanzhong147 b9b0dc3bda x
Build docker and publish / build (20.15.1) (push) Failing after 14s
2025-09-26 18:57:19 -07:00
shanshanzhong147 4d39fd1b84 i1
Build docker and publish / build (20.15.1) (push) Failing after 7s
2025-09-26 18:43:33 -07:00
shanshanzhong147 bcf81ab683 i1
Build docker and publish / build (push) Failing after 19s
2025-09-26 18:42:35 -07:00
shanshanzhong147 7471fd8e3d ci
Build docker and publish / linux (1.24.3) (push) Has been cancelled
2025-09-26 18:37:43 -07:00
shanshanzhong147 ac3bbaf7bf feat(ticket): 添加issue_type字段支持工单分类
在工单系统中新增issue_type字段用于区分工单类型(0-普通工单,1-提现工单)
修改相关API、模型和逻辑以支持该字段的创建、查询和筛选
2025-09-15 01:42:44 -07:00
shanshanzhong147 2d4bfe0330 remark 2025-09-14 23:41:00 -07:00
shanshanzhong147 602ecc31bc feat(proxy): 新增混合模式和中继直连模式支持
添加 RelayModeMixed、RelayModeAllDirect 和 RelayModeRandomDirect 三种中继模式
修复 README.md 中的拼写错误
更新 JWT 密钥和日志模式配置
优化流量日志查询排序
统一邮件验证码主题格式
2025-09-01 02:22:16 -07:00
shanshanzhong147 b16ac2cb9b feat(用户): 添加用户余额日志分页查询功能
修复AnyTLSUri端口使用错误问题
添加订阅列表排序功能
更新.gitignore移除日志文件忽略
完善流量通知模板变量
2025-08-27 08:15:31 -07:00
shanshanzhong147 41423ca666 fix: 修复订阅列表查询逻辑并更新Dockerfile配置
修复订阅列表查询中服务器组为空时的处理逻辑,避免潜在错误
在getSubscribeListLogic.go中添加服务器数量统计功能
更新Dockerfile添加logs目录拷贝
清理ppanel.yaml配置文件中的合并冲突和冗余配置
2025-08-17 04:28:32 -07:00
shanshanzhong147 e898e6afbe init 2025-08-12 07:52:04 -07:00
shanshanzhong147 2e01ba0e3d ci(docker): 更新Docker工作流和配置
清理Go模块缓存并移除go.sum文件
更新Docker网络名称和数据库连接配置
2025-08-10 00:28:32 -07:00
shanshanzhong147 25db7ea428 chore(deploy): 更新GITEA_RUNNER_NAME为ubuntu-latest 2025-08-09 08:32:09 -07:00
shanshanzhong147 e37ad50410 ci: 将linux作业的运行环境从vpn改为ubuntu-latest 2025-08-09 08:17:36 -07:00
shanshanzhong147 c503e06c9c ci(workflow): 将linux作业的运行环境改为vpn
避免使用公共runner以提高构建安全性
2025-08-09 08:00:12 -07:00
shanshanzhong147 0992c2ad7b ci(docker): 更新Docker工作流以包含构建步骤
添加checkout步骤并使用环境变量进行认证
包含构建Linux可执行文件的步骤
2025-08-09 07:18:58 -07:00
shanshanzhong147 e78b93d6fb ci: 移除不必要的检出步骤 2025-08-09 07:13:25 -07:00
shanshanzhong147 79020ccea0 1 2025-08-09 06:55:11 -07:00
shanshanzhong147 8a8ece76b1 ci: 将Linux构建任务运行环境从vpn改为ubuntu-latest 2025-08-09 06:26:21 -07:00
shanshanzhong147 0316345e9f ci: 将linux job的运行环境从vpn-runner改为vpn 2025-08-09 06:25:23 -07:00
shanshanzhong147 b56b1240f3 ci(workflow): 将linux job的运行环境改为vpn-runner并移除build-linux步骤 2025-08-09 06:23:30 -07:00
shanshanzhong147 77b3af8015 init 2025-08-09 05:18:44 -07:00
shanshanzhong147 634f43d644 fix: 更新MySQL和Redis的连接地址为具体IP
将MySQL和Redis的连接地址从服务名称改为具体IP地址,以便在特定网络环境下能够正确连接
2025-08-05 10:37:47 -07:00
shanshanzhong147 e5b4dc75d7 fix(deploy): 更新docker-compose配置和数据库连接地址
- 在docker-compose中添加时区环境变量
- 将MySQL和Redis连接地址从localhost改为服务名
- 更新Makefile中的docker compose命令语法
2025-08-05 10:12:29 -07:00
shanshanzhong147 40b8c07036 chore: 在docker-run命令中添加当前工作目录打印 2025-08-05 10:00:07 -07:00
shanshanzhong147 b261ddeeb1 ci(docker): 更新Docker工作流,添加构建步骤并注释发布步骤
添加应用构建步骤以确保镜像包含最新代码
暂时注释发布步骤以进行本地测试
2025-08-05 09:52:27 -07:00
shanshanzhong147 62f07b7f6b ci(docker): 移除构建应用的步骤并修复docker-compose命令
移除docker.yml中冗余的go mod tidy和build-linux步骤,这些步骤已在其他流程中处理
将docker compose命令改为docker-compose以兼容旧版本
2025-08-05 09:46:27 -07:00
shanshanzhong147 31a2aa0e84 ci(workflow): 优化Docker工作流配置并简化步骤
- 添加DOMAIN环境变量以替代硬编码的域名
- 简化git克隆流程,使用凭证存储提高安全性
- 移除不必要的SSH文件复制步骤
- 添加构建和发布Docker镜像的详细日志输出
2025-08-05 09:24:13 -07:00
shanshanzhong147 7965c33790 ci(docker): 更新Gitea工作流以使用容器化构建环境
将Linux作业改为在golang容器中运行,简化Go环境设置步骤
移除不必要的SSH步骤,优化构建流程
2025-08-05 09:22:37 -07:00
shanshanzhong147 fcae874fd2 ci: 移除不再需要的Node.js安装步骤 2025-08-05 09:20:50 -07:00
shanshanzhong147 dad83339c1 ci(docker): 更新Gitea工作流配置并优化构建步骤
- 使用标准actions/checkout@v4替代自定义checkout
- 添加Go环境设置步骤并启用缓存
- 优化SSH action使用标准appleboy/ssh-action
- 调整工作空间路径变量为github标准
2025-08-05 09:18:32 -07:00
shanshanzhong147 84842ec3dd ci(docker): 添加 Node.js 设置步骤以支持前端构建 2025-08-05 09:16:06 -07:00
shanshanzhong147 59bc008b69 ci(docker): 更新SSH action的版本引用
使用明确的版本号v1替代隐式引用,提高工作流的稳定性
2025-08-05 09:13:06 -07:00
shanshanzhong147 8cb58ad91f ci(docker): 更新Gitea Actions checkout步骤使用v1版本
修复checkout步骤未指定版本的问题,确保构建稳定性
2025-08-05 09:12:16 -07:00
shanshanzhong147 7372302618 ci(docker): 移除actions引用中的main分支后缀 2025-08-05 09:10:44 -07:00
shanshanzhong147 cbf5a2b450 1 2025-08-05 09:09:02 -07:00
shanshanzhong147 33f450cdbc init 2025-08-05 08:47:18 -07:00
shanshanzhong147 bce4c4e56e ci(workflow): 更新Gitea工作流使用内部actions
使用内部认证的actions替换公开actions以增强安全性
2025-08-05 08:22:04 -07:00
shanshanzhong147 b6cbcb3040 ci: 移除不必要的Node.js设置和检出步骤 2025-08-05 08:09:59 -07:00
shanshanzhong147 fdbe3c75ee ci(workflow): 添加Node.js环境并降级checkout action版本
添加Node.js环境设置步骤以满足构建需求
将actions/checkout从v4降级至v3以解决兼容性问题
2025-08-05 08:08:36 -07:00
shanshanzhong147 bf13c56261 ci: 更新Gitea工作流中使用GitHub官方actions
将自定义的actions地址替换为GitHub官方actions,提高工作流的稳定性和可维护性
2025-08-05 08:05:21 -07:00
shanshanzhong147 85343f3f82 fix(deploy): 修正GITEA_RUNNER_NAME变量值为vpn-runner 2025-08-05 08:01:25 -07:00
shanshanzhong147 51b493a10d ci(workflow): 将linux作业的运行环境从ubuntu-latest改为vpn 2025-08-05 07:59:50 -07:00
shanshanzhong147 ae04e0d518 chore: 更新GITEA_RUNNER_NAME为vpn-runner 2025-08-05 07:54:18 -07:00
shanshanzhong147 2b1ce740e1 ci: 更新部署配置和CI认证方式
将域名从ppanel.kxsw.us更改为api.kxsw.us
将CI工作流中的SSH认证方式从私钥改为密码认证
2025-08-05 07:47:50 -07:00
shanshanzhong147 e620abcce6 init 2025-08-05 06:19:25 -07:00
shanshanzhong147 7ea6fc226e refactor(Dockerfile): 优化时区文件拷贝并添加注释
将单个时区文件拷贝改为拷贝整个时区目录,提高可维护性
添加时区设置的环境变量注释
2025-07-28 06:56:07 -07:00
shanshanzhong147 d5f4b04c6c fix(deploy): 将API外部端口从8070改为8080 2025-07-24 09:33:40 -07:00
shanshanzhong147 a0ca976e66 chore: 开启调试模式并添加代码对比脚本
开启调试模式以便更好地排查问题。
添加代码对比脚本 see.sh,用于简洁地对比代码变更,包括文件变更对比和变更统计,方便查看我们和他们的修改情况。
2025-07-23 10:13:42 -07:00
shanshanzhong147 917732eeee fix: 修改 MySQL 配置中的密码和数据库名 2025-07-23 09:43:38 -07:00
shanshanzhong147 f0fbd9d208 fix: 更新MySQL和Redis连接地址以及Docker网络名称
将MySQL地址从localhost改为mysql_db,Redis地址从127.0.0.1改为redis_cache
更新Docker网络名称为ppanel-script_ppanel-network以匹配部署配置
2025-07-23 09:25:32 -07:00
shanshanzhong147 2d07182bd6 fix: 修正 Dockerfile 中的 CMD 命令参数 2025-07-23 09:20:32 -07:00
shanshanzhong147 e0ae15355b style: 将项目名称从Ppanel改为ppanel以保持命名一致性 2025-07-23 08:48:36 -07:00
shanshanzhong147 c0e0d03431 fix: 修正Dockerfile和Makefile中的可执行文件名称
将Dockerfile中的CMD命令和Makefile中的build-linux目标输出文件名称统一为'ppanel',确保容器运行时使用正确的可执行文件名称
2025-07-23 08:22:45 -07:00
shanshanzhong147 bb5d6974fa ci: 从发布流程中移除docker登录步骤
移除Makefile中自动登录docker的步骤,因为登录凭证应通过更安全的方式处理
2025-07-23 07:51:46 -07:00
shanshanzhong147 df7fcddb40 refactor: 更新Dockerfile和Makefile配置
统一服务名称为Ppanel并更新相关变量命名
优化Makefile结构,移除无用swagger相关命令
添加构建时间变量并改进构建命令
2025-07-23 07:36:26 -07:00
shanshanzhong147 6c9d5fb39e fix: 修正Makefile中的服务名称拼写错误 2025-07-22 10:25:41 -07:00
shanshanzhong147 4ecc5177ed ci(docker): 优化Go环境设置并启用缓存
使用setup-go替代gitea-tool-cache来设置Go环境
启用依赖缓存以提高构建效率
移除不必要的清理步骤
2025-07-22 10:11:10 -07:00
shanshanzhong147 c11d46bdbf ci: 更新工作流中使用的工作空间变量从github到gitea 2025-07-22 10:09:55 -07:00
shanshanzhong147 9b7a588997 ci(workflow): 更新docker工作流配置
- 添加GOSUMDB=off设置并清理go缓存
- 修复工作空间路径变量引用错误
- 增加go.sum清理步骤
2025-07-22 10:05:09 -07:00
shanshanzhong147 0f40c63ea0 ci(docker): 修复工作流中容器环境变量处理逻辑
修复容器名称变量引用错误,并添加对RUNNER_CONTAINER_NAME未设置的检查
2025-07-22 09:53:59 -07:00
shanshanzhong147 1d1d8c0e30 ci(workflows): 修改docker工作流中的环境文件路径
将环境文件存储路径从/install/cicd_env_files改为用户主目录下的~/cicd_env_files,避免权限问题
2025-07-22 09:52:25 -07:00
shanshanzhong147 5d890fdfcc ci: 更新Gitea Actions的引用版本为main分支 2025-07-22 09:50:20 -07:00
shanshanzhong147 94e2f33db1 ci: 移除Gitea Actions插件版本号以使用最新版本 2025-07-22 09:45:30 -07:00
shanshanzhong147 a7d9deb9cd ci(workflow): 更新 setup-go action 的引用方式 2025-07-22 09:36:18 -07:00
shanshanzhong147 9f9e832e37 chore(deploy): 更新GITEA_RUNNER_NAME为server-runner 2025-07-22 09:08:59 -07:00
shanshanzhong147 a73a3f2313 feat: 添加docker-compose配置和用户管理逻辑更新
fix(ci): 移除敏感信息并更新SSH认证方式

refactor: 清理无用文件和更新Makefile配置

docs: 添加项目配置文件和更新环境变量说明
2025-07-22 08:53:30 -07:00
shanshanzhong147 cc6ebc18e5 ci(docker): 添加docker构建工作流并更新Makefile配置
添加Gitea的docker构建工作流,包含环境变量配置、Go环境安装、镜像构建和发布步骤
重构Makefile以支持多平台构建、docker操作和swagger文档生成
2025-07-21 07:25:47 -07:00
565 changed files with 16941 additions and 16989 deletions
+231
View File
@@ -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
-51
View File
@@ -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 }}
#
-131
View File
@@ -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}}"
-81
View File
@@ -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
-2
View File
@@ -3,10 +3,8 @@
*-dev.yaml *-dev.yaml
*.local.yaml *.local.yaml
/test/ /test/
*.log
.DS_Store .DS_Store
*_test_config.go *_test_config.go
*.log*
/build/ /build/
*.p8 *.p8
*.crt *.crt
+5 -3
View File
@@ -20,16 +20,17 @@ RUN go mod download
COPY . . COPY . .
# Build the binary with version and build time # 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 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 # Final minimal image
FROM scratch FROM alpine:latest
# Copy CA certificates and timezone data # Copy CA certificates and timezone data
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 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 ENV TZ=Asia/Shanghai
# Set working directory and copy binary # Set working directory and copy binary
@@ -37,6 +38,7 @@ WORKDIR /app
COPY --from=builder /app/ppanel /app/ppanel COPY --from=builder /app/ppanel /app/ppanel
COPY --from=builder /build/etc /app/etc COPY --from=builder /build/etc /app/etc
COPY --from=builder /build/logs /app/logs
# Expose the port (optional) # Expose the port (optional)
EXPOSE 8080 EXPOSE 8080
+66 -77
View File
@@ -1,84 +1,73 @@
NAME="ppanel-server" # Custom configuration | 独立配置
BINDIR=bin # Service name | 项目名称
VERSION=$(shell git describe --tags || echo "unknown version") SERVICE=ppanel
BUILDTIME=$(shell date -u) # 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)" \ 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)" \ -X "github.com/perfect-panel/server/pkg/constant.BuildTime=$(BUILDTIME)" \
-w -s -buildid=' -w -s -buildid='
PLATFORM_LIST = \ .PHONY: docker
darwin-amd64 \ docker: # Build the docker image | 构建 docker 镜像
darwin-amd64-v3 \ docker build -f Dockerfile -t ${API_IMAGE_NAME}:${VERSION} .
darwin-arm64 \ @echo "Build docker successfully"
linux-386 \
linux-amd64 \
linux-amd64-v3 \
linux-armv5 \
linux-armv6 \
linux-armv7 \
linux-arm64 \
WINDOWS_ARCH_LIST = \ .PHONY: publish-docker
windows-386 \ publish-docker: # Publish docker image | 发布 docker 镜像
windows-amd64 \ docker tag ${API_IMAGE_NAME}:${VERSION} ${API_IMAGE_NAME}:latest
windows-amd64-v3 \ docker push ${API_IMAGE_NAME}:latest
windows-arm64 \ @echo "Publish docker successfully"
windows-armv7
all: linux-amd64 darwin-amd64 windows-amd64 # Most used .PHONY: docker-run
docker-run: # Publish docker image | 发布 docker 镜像
darwin-amd64: docker rm -f ${API_CONTAINER_NAME}
GOARCH=amd64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ @echo "pwd: $(pwd)"
docker compose -p ${DOCKER_PROJECT_NAME} -f ${DOCKER_COMPOSE_FILE} up -d
darwin-amd64-v3: @echo "docker run successfully"
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
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST)) .PHONY: build-linux
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST)) 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 : % .PHONY: help
chmod +x $(BINDIR)/$(NAME)-$(basename $@) help: # Show help | 显示帮助
gzip -f -S -$(VERSION).gz $(BINDIR)/$(NAME)-$(basename $@) @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
$(zip_releases): %.zip : %
zip -m -j $(BINDIR)/$(NAME)-$(basename $@)-$(VERSION).zip $(BINDIR)/$(NAME)-$(basename $@).exe
+3 -16
View File
@@ -14,19 +14,6 @@
</div> </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 ## 📋 Overview
PPanel Server is the backend component of the PPanel project, providing robust APIs and core functionality for managing 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): 4. **Pull from Docker Hub** (after CI/CD publishes):
```bash ```bashw
docker pull ppanel/ppanel-server:latest docker pull yourusername/ppanel-server:latest
docker run --rm -p 8080:8080 ppanel/ppanel-server:latest docker run --rm -p 8080:8080 yourusername/ppanel-server:latest
``` ```
## 📖 API Documentation ## 📖 API Documentation
-158
View File
@@ -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
}
-34
View File
@@ -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))
}
-146
View File
@@ -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
}
-153
View File
@@ -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
View File
@@ -1 +0,0 @@
package adapter
-46
View File
@@ -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
}
-96
View File
@@ -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)
}
+1 -1
View File
@@ -21,7 +21,7 @@ type (
Download int64 `json:"download"` Download int64 `json:"download"`
} }
ServerTotalDataResponse { ServerTotalDataResponse {
OnlineUsers int64 `json:"online_users"` OnlineUserIPs int64 `json:"online_user_ips"`
OnlineServers int64 `json:"online_servers"` OnlineServers int64 `json:"online_servers"`
OfflineServers int64 `json:"offline_servers"` OfflineServers int64 `json:"offline_servers"`
TodayUpload int64 `json:"today_upload"` TodayUpload int64 `json:"today_upload"`
+8 -229
View File
@@ -12,184 +12,19 @@ import "../types.api"
type ( type (
GetMessageLogListRequest { GetMessageLogListRequest {
Page int `form:"page"` Page int `form:"page"`
Size int `form:"size"` Size int `form:"size"`
Type uint8 `form:"type"` Type string `form:"type"`
Search string `form:"search,optional"` 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 { GetMessageLogListResponse {
Total int64 `json:"total"` Total int64 `json:"total"`
List []MessageLog `json:"list"` 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 ( @server (
@@ -201,61 +36,5 @@ service ppanel {
@doc "Get message log list" @doc "Get message log list"
@handler GetMessageLogList @handler GetMessageLogList
get /message/list (GetMessageLogListRequest) returns (GetMessageLogListResponse) 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)
} }
-167
View File
@@ -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)
}
+141 -159
View File
@@ -11,134 +11,108 @@ info (
import "../types.api" import "../types.api"
type ( type (
ServerOnlineIP { GetNodeServerListRequest {
IP string `json:"ip"` Page int `form:"page" validate:"required"`
Protocol string `json:"protocol"` Size int `form:"size" validate:"required"`
Tags string `form:"tags,omitempty"`
GroupId int64 `form:"group_id,omitempty"`
Search string `form:"search,omitempty"`
} }
ServerOnlineUser { GetNodeServerListResponse {
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"`
Search string `form:"search,omitempty"`
}
FilterServerListResponse {
Total int64 `json:"total"` Total int64 `json:"total"`
List []Server `json:"list"` List []Server `json:"list"`
} }
GetServerProtocolsRequest { UpdateNodeRequest {
Id int64 `form:"id"` Id int64 `json:"id" validate:"required"`
} Tags []string `json:"tags"`
GetServerProtocolsResponse { Country string `json:"country"`
Protocols []Protocol `json:"protocols"` City string `json:"city"`
} Name string `json:"name" validate:"required"`
Node { ServerAddr string `json:"server_addr" validate:"required"`
Id int64 `json:"id"` RelayMode string `json:"relay_mode"`
Name string `json:"name"` RelayNode []NodeRelay `json:"relay_node"`
Tags []string `json:"tags"` SpeedLimit int `json:"speed_limit"`
Port uint16 `json:"port"` TrafficRatio float32 `json:"traffic_ratio"`
Address string `json:"address"` GroupId int64 `json:"group_id"`
ServerId int64 `json:"server_id"` Protocol string `json:"protocol" validate:"required"`
Protocol string `json:"protocol"` Config interface{} `json:"config" validate:"required"`
Enabled *bool `json:"enabled"` Enable *bool `json:"enable"`
Sort int `json:"sort,omitempty"` Sort int64 `json:"sort"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
} }
CreateNodeRequest { CreateNodeRequest {
Name string `json:"name"` Name string `json:"name" validate:"required"`
Tags []string `json:"tags,omitempty"` Tags []string `json:"tags"`
Port uint16 `json:"port"` Country string `json:"country"`
Address string `json:"address"` City string `json:"city"`
ServerId int64 `json:"server_id"` ServerAddr string `json:"server_addr" validate:"required"`
Protocol string `json:"protocol"` RelayMode string `json:"relay_mode"`
Enabled *bool `json:"enabled"` RelayNode []NodeRelay `json:"relay_node"`
} SpeedLimit int `json:"speed_limit"`
UpdateNodeRequest { TrafficRatio float32 `json:"traffic_ratio"`
Id int64 `json:"id"` GroupId int64 `json:"group_id"`
Name string `json:"name"` Protocol string `json:"protocol" validate:"required"`
Tags []string `json:"tags,omitempty"` Config interface{} `json:"config" validate:"required"`
Port uint16 `json:"port"` Enable *bool `json:"enable"`
Address string `json:"address"` Sort int64 `json:"sort"`
ServerId int64 `json:"server_id"`
Protocol string `json:"protocol"`
Enabled *bool `json:"enabled"`
}
ToggleNodeStatusRequest {
Id int64 `json:"id"`
Enable *bool `json:"enable"`
} }
DeleteNodeRequest { DeleteNodeRequest {
Id int64 `json:"id"` Id int64 `json:"id" validate:"required"`
} }
FilterNodeListRequest { GetNodeGroupListResponse {
Page int `form:"page"` Total int64 `json:"total"`
Size int `form:"size"` List []ServerGroup `json:"list"`
Search string `form:"search,omitempty"`
} }
FilterNodeListResponse { CreateNodeGroupRequest {
Total int64 `json:"total"` Name string `json:"name" validate:"required"`
List []Node `json:"list"` Description string `json:"description"`
} }
HasMigrateSeverNodeResponse { UpdateNodeGroupRequest {
HasMigrate bool `json:"has_migrate"` Id int64 `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
Description string `json:"description"`
} }
MigrateServerNodeResponse { DeleteNodeGroupRequest {
Succee uint64 `json:"succee"` Id int64 `json:"id" validate:"required"`
Fail uint64 `json:"fail"`
Message string `json:"message,omitempty"`
} }
ResetSortRequest { 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"` 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"` Tags []string `json:"tags"`
} }
) )
@@ -149,64 +123,72 @@ type (
middleware: AuthMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Create Server" @doc "Get node tag list"
@handler CreateServer @handler GetNodeTagList
post /create (CreateServerRequest) get /tag/list returns (GetNodeTagListResponse)
@doc "Update Server" @doc "Get node list"
@handler UpdateServer @handler GetNodeList
post /update (UpdateServerRequest) get /list (GetNodeServerListRequest) returns (GetNodeServerListResponse)
@doc "Delete Server" @doc "Get node detail"
@handler DeleteServer @handler GetNodeDetail
post /delete (DeleteServerRequest) get /detail (GetNodeDetailRequest) returns (Server)
@doc "Filter Server List" @doc "Update node"
@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"
@handler UpdateNode @handler UpdateNode
post /node/update (UpdateNodeRequest) put / (UpdateNodeRequest)
@doc "Delete Node" @doc "Create node"
@handler CreateNode
post / (CreateNodeRequest)
@doc "Delete node"
@handler DeleteNode @handler DeleteNode
post /node/delete (DeleteNodeRequest) delete / (DeleteNodeRequest)
@doc "Filter Node List" @doc "Batch delete node"
@handler FilterNodeList @handler BatchDeleteNode
get /node/list (FilterNodeListRequest) returns (FilterNodeListResponse) delete /batch (BatchDeleteNodeRequest)
@doc "Toggle Node Status" @doc "Get node group list"
@handler ToggleNodeStatus @handler GetNodeGroupList
post /node/status/toggle (ToggleNodeStatusRequest) get /group/list returns (GetNodeGroupListResponse)
@doc "Check if there is any server or node to migrate" @doc "Create node group"
@handler HasMigrateSeverNode @handler CreateNodeGroup
get /migrate/has returns (HasMigrateSeverNodeResponse) post /group (CreateNodeGroupRequest)
@doc "Migrate server and node data to new database" @doc "Update node group"
@handler MigrateServerNode @handler UpdateNodeGroup
post /migrate/run returns (MigrateServerNodeResponse) put /group (UpdateNodeGroupRequest)
@doc "Reset server sort" @doc "Delete node group"
@handler ResetSortWithServer @handler DeleteNodeGroup
post /server/sort (ResetSortRequest) delete /group (DeleteNodeGroupRequest)
@doc "Reset node sort" @doc "Batch delete node group"
@handler ResetSortWithNode @handler BatchDeleteNodeGroup
post /node/sort (ResetSortRequest) delete /group/batch (BatchDeleteNodeGroupRequest)
@doc "Query all node tags" @doc "Node sort "
@handler QueryNodeTag @handler NodeSort
get /node/tags returns (QueryNodeTagResponse) 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)
} }
+10 -17
View File
@@ -35,7 +35,6 @@ type (
} }
CreateSubscribeRequest { CreateSubscribeRequest {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Language string `json:"language"`
Description string `json:"description"` Description string `json:"description"`
UnitPrice int64 `json:"unit_price"` UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"` UnitTime string `json:"unit_time"`
@@ -46,8 +45,9 @@ type (
SpeedLimit int64 `json:"speed_limit"` SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"` DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"` Quota int64 `json:"quota"`
Nodes []int64 `json:"nodes"` GroupId int64 `json:"group_id"`
NodeTags []string `json:"node_tags"` ServerGroup []int64 `json:"server_group"`
Server []int64 `json:"server"`
Show *bool `json:"show"` Show *bool `json:"show"`
Sell *bool `json:"sell"` Sell *bool `json:"sell"`
DeductionRatio int64 `json:"deduction_ratio"` DeductionRatio int64 `json:"deduction_ratio"`
@@ -58,7 +58,6 @@ type (
UpdateSubscribeRequest { UpdateSubscribeRequest {
Id int64 `json:"id" validate:"required"` Id int64 `json:"id" validate:"required"`
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Language string `json:"language"`
Description string `json:"description"` Description string `json:"description"`
UnitPrice int64 `json:"unit_price"` UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"` UnitTime string `json:"unit_time"`
@@ -69,8 +68,9 @@ type (
SpeedLimit int64 `json:"speed_limit"` SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"` DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"` Quota int64 `json:"quota"`
Nodes []int64 `json:"nodes"` GroupId int64 `json:"group_id"`
NodeTags []string `json:"node_tags"` ServerGroup []int64 `json:"server_group"`
Server []int64 `json:"server"`
Show *bool `json:"show"` Show *bool `json:"show"`
Sell *bool `json:"sell"` Sell *bool `json:"sell"`
Sort int64 `json:"sort"` Sort int64 `json:"sort"`
@@ -83,10 +83,10 @@ type (
Sort []SortItem `json:"sort"` Sort []SortItem `json:"sort"`
} }
GetSubscribeListRequest { GetSubscribeListRequest {
Page int64 `form:"page" validate:"required"` Page int64 `form:"page" validate:"required"`
Size int64 `form:"size" validate:"required"` Size int64 `form:"size" validate:"required"`
Language string `form:"language,omitempty"` GroupId int64 `form:"group_id,omitempty"`
Search string `form:"search,omitempty"` Search string `form:"search,omitempty"`
} }
SubscribeItem { SubscribeItem {
Subscribe Subscribe
@@ -102,9 +102,6 @@ type (
BatchDeleteSubscribeRequest { BatchDeleteSubscribeRequest {
Ids []int64 `json:"ids" validate:"required"` Ids []int64 `json:"ids" validate:"required"`
} }
ResetAllSubscribeTokenResponse {
Success bool `json:"success"`
}
) )
@server ( @server (
@@ -160,9 +157,5 @@ service ppanel {
@doc "Subscribe sort" @doc "Subscribe sort"
@handler SubscribeSort @handler SubscribeSort
post /sort (SubscribeSortRequest) post /sort (SubscribeSortRequest)
@doc "Reset all subscribe tokens"
@handler ResetAllSubscribeToken
post /reset_all_token returns (ResetAllSubscribeTokenResponse)
} }
+84 -17
View File
@@ -11,6 +11,50 @@ info (
import "../types.api" import "../types.api"
type ( 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 { GetNodeMultiplierResponse {
Periods []TimePeriod `json:"periods"` Periods []TimePeriod `json:"periods"`
} }
@@ -18,15 +62,6 @@ type (
SetNodeMultiplierRequest { SetNodeMultiplierRequest {
Periods []TimePeriod `json:"periods"` 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 ( @server (
@@ -51,6 +86,46 @@ service ppanel {
@handler UpdateSubscribeConfig @handler UpdateSubscribeConfig
put /subscribe_config (SubscribeConfig) 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" @doc "Get register config"
@handler GetRegisterConfig @handler GetRegisterConfig
get /register_config returns (RegisterConfig) get /register_config returns (RegisterConfig)
@@ -126,13 +201,5 @@ service ppanel {
@doc "Update Verify Code Config" @doc "Update Verify Code Config"
@handler UpdateVerifyCodeConfig @handler UpdateVerifyCodeConfig
put /verify_code_config (VerifyCodeConfig) 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)
} }
+6 -5
View File
@@ -16,11 +16,12 @@ type (
Status *uint8 `json:"status" validate:"required"` Status *uint8 `json:"status" validate:"required"`
} }
GetTicketListRequest { GetTicketListRequest {
Page int64 `form:"page"` Page int64 `form:"page"`
Size int64 `form:"size"` Size int64 `form:"size"`
UserId int64 `form:"user_id,omitempty"` UserId int64 `form:"user_id,omitempty"`
Status *uint8 `form:"status,omitempty"` Status *uint8 `form:"status,omitempty"`
Search string `form:"search,omitempty"` IssueType *uint8 `form:"issue_type,omitempty"`
Search string `form:"search,omitempty"`
} }
GetTicketListResponse { GetTicketListResponse {
Total int64 `json:"total"` Total int64 `json:"total"`
-19
View File
@@ -14,17 +14,6 @@ type (
LogResponse { LogResponse {
List interface{} `json:"list"` 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 ( @server (
@@ -40,13 +29,5 @@ service ppanel {
@doc "Restart System" @doc "Restart System"
@handler RestartSystem @handler RestartSystem
get /restart get /restart
@doc "Get Version"
@handler GetVersion
get /version returns (VersionResponse)
@doc "Query IP Location"
@handler QueryIPLocation
get /ip/location (QueryIPLocationRequest) returns (QueryIPLocationResponse)
} }
+24 -40
View File
@@ -32,19 +32,18 @@ type (
Id int64 `form:"id" validate:"required"` Id int64 `form:"id" validate:"required"`
} }
UpdateUserBasiceInfoRequest { UpdateUserBasiceInfoRequest {
UserId int64 `json:"user_id" validate:"required"` UserId int64 `json:"user_id" validate:"required"`
Password string `json:"password"` Password string `json:"password"`
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
Commission int64 `json:"commission"` Commission int64 `json:"commission"`
ReferralPercentage uint8 `json:"referral_percentage"` GiftAmount int64 `json:"gift_amount"`
OnlyFirstPurchase bool `json:"only_first_purchase"` Telegram int64 `json:"telegram"`
GiftAmount int64 `json:"gift_amount"` ReferCode string `json:"refer_code"`
Telegram int64 `json:"telegram"` RefererId int64 `json:"referer_id"`
ReferCode string `json:"refer_code"` Remark string `json:"remark"`
RefererId int64 `json:"referer_id"` Enable bool `json:"enable"`
Enable bool `json:"enable"` IsAdmin bool `json:"is_admin"`
IsAdmin bool `json:"is_admin"`
} }
UpdateUserNotifySettingRequest { UpdateUserNotifySettingRequest {
UserId int64 `json:"user_id" validate:"required"` UserId int64 `json:"user_id" validate:"required"`
@@ -54,20 +53,18 @@ type (
EnableTradeNotify bool `json:"enable_trade_notify"` EnableTradeNotify bool `json:"enable_trade_notify"`
} }
CreateUserRequest { CreateUserRequest {
Email string `json:"email"` Email string `json:"email"`
Telephone string `json:"telephone"` Telephone string `json:"telephone"`
TelephoneAreaCode string `json:"telephone_area_code"` TelephoneAreaCode string `json:"telephone_area_code"`
Password string `json:"password"` Password string `json:"password"`
ProductId int64 `json:"product_id"` ProductId int64 `json:"product_id"`
Duration int64 `json:"duration"` Duration int64 `json:"duration"`
ReferralPercentage uint8 `json:"referral_percentage"` RefererUser string `json:"referer_user"`
OnlyFirstPurchase bool `json:"only_first_purchase"` ReferCode string `json:"refer_code"`
RefererUser string `json:"referer_user"` Balance int64 `json:"balance"`
ReferCode string `json:"refer_code"` Commission int64 `json:"commission"`
Balance int64 `json:"balance"` GiftAmount int64 `json:"gift_amount"`
Commission int64 `json:"commission"` IsAdmin bool `json:"is_admin"`
GiftAmount int64 `json:"gift_amount"`
IsAdmin bool `json:"is_admin"`
} }
UserSubscribeDetail { UserSubscribeDetail {
Id int64 `json:"id"` Id int64 `json:"id"`
@@ -168,15 +165,6 @@ type (
List []UserLoginLog `json:"list"` List []UserLoginLog `json:"list"`
Total int64 `json:"total"` 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 { DeleteUserSubscribeRequest {
UserSubscribeId int64 `json:"user_subscribe_id"` UserSubscribeId int64 `json:"user_subscribe_id"`
} }
@@ -264,10 +252,6 @@ service ppanel {
@handler GetUserSubscribeLogs @handler GetUserSubscribeLogs
get /subscribe/logs (GetUserSubscribeLogsRequest) returns (GetUserSubscribeLogsResponse) 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" @doc "Get user subcribe traffic logs"
@handler GetUserSubscribeTrafficLogs @handler GetUserSubscribeTrafficLogs
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse) get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
+23
View File
@@ -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)
}
+104
View File
@@ -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)
}
+27
View File
@@ -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)
}
+40
View File
@@ -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)
}
+57
View File
@@ -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)
}
+23
View File
@@ -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)
}
+65
View File
@@ -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)
}
+86
View File
@@ -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)
}
+21
View File
@@ -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
}
+20 -46
View File
@@ -11,13 +11,11 @@ info (
type ( type (
// User login request // User login request
UserLoginRequest { UserLoginRequest {
Identifier string `json:"identifier"` Email string `json:"email" validate:"required"`
Email string `json:"email" validate:"required"` Password string `json:"password" validate:"required"`
Password string `json:"password" validate:"required"` IP string `header:"X-Original-Forwarded-For"`
IP string `header:"X-Original-Forwarded-For"` UserAgent string `header:"User-Agent"`
UserAgent string `header:"User-Agent"` CfToken string `json:"cf_token,optional"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
} }
// Check user is exist request // Check user is exist request
CheckUserRequest { CheckUserRequest {
@@ -29,26 +27,22 @@ type (
} }
// User login response // User login response
UserRegisterRequest { UserRegisterRequest {
Identifier string `json:"identifier"` Email string `json:"email" validate:"required"`
Email string `json:"email" validate:"required"` Password string `json:"password" validate:"required"`
Password string `json:"password" validate:"required"` Invite string `json:"invite,optional"`
Invite string `json:"invite,optional"` Code string `json:"code,optional"`
Code string `json:"code,optional"` IP string `header:"X-Original-Forwarded-For"`
IP string `header:"X-Original-Forwarded-For"` UserAgent string `header:"User-Agent"`
UserAgent string `header:"User-Agent"` CfToken string `json:"cf_token,optional"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
} }
// User login response // User login response
ResetPasswordRequest { ResetPasswordRequest {
Identifier string `json:"identifier"` Email string `json:"email" validate:"required"`
Email string `json:"email" validate:"required"` Password string `json:"password" validate:"required"`
Password string `json:"password" validate:"required"` Code string `json:"code,optional"`
Code string `json:"code,optional"` IP string `header:"X-Original-Forwarded-For"`
IP string `header:"X-Original-Forwarded-For"` UserAgent string `header:"User-Agent"`
UserAgent string `header:"User-Agent"` CfToken string `json:"cf_token,optional"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"`
} }
LoginResponse { LoginResponse {
Token string `json:"token"` Token string `json:"token"`
@@ -66,14 +60,11 @@ type (
} }
// login request // login request
TelephoneLoginRequest { TelephoneLoginRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"` Telephone string `json:"telephone" validate:"required"`
TelephoneCode string `json:"telephone_code"` TelephoneCode string `json:"telephone_code"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"` TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password"` Password string `json:"password"`
IP string `header:"X-Original-Forwarded-For"` IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type"`
CfToken string `json:"cf_token,optional"` CfToken string `json:"cf_token,optional"`
} }
// Check user is exist request // Check user is exist request
@@ -87,27 +78,21 @@ type (
} }
// User login response // User login response
TelephoneRegisterRequest { TelephoneRegisterRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"` Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"` TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
Invite string `json:"invite,optional"` Invite string `json:"invite,optional"`
Code string `json:"code,optional"` Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"` IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"` CfToken string `json:"cf_token,optional"`
} }
// User login response // User login response
TelephoneResetPasswordRequest { TelephoneResetPasswordRequest {
Identifier string `json:"identifier"`
Telephone string `json:"telephone" validate:"required"` Telephone string `json:"telephone" validate:"required"`
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"` TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
Code string `json:"code,optional"` Code string `json:"code,optional"`
IP string `header:"X-Original-Forwarded-For"` IP string `header:"X-Original-Forwarded-For"`
UserAgent string `header:"User-Agent"`
LoginType string `header:"Login-Type,optional"`
CfToken string `json:"cf_token,optional"` CfToken string `json:"cf_token,optional"`
} }
AppleLoginCallbackRequest { AppleLoginCallbackRequest {
@@ -119,18 +104,11 @@ type (
Code string `form:"code"` Code string `form:"code"`
State string `form:"state"` 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 ( @server (
prefix: v1/auth prefix: v1/auth
group: auth group: auth
middleware: DeviceMiddleware
) )
service ppanel { service ppanel {
@doc "User login" @doc "User login"
@@ -164,10 +142,6 @@ service ppanel {
@doc "Reset password" @doc "Reset password"
@handler TelephoneResetPassword @handler TelephoneResetPassword
post /reset/telephone (TelephoneResetPasswordRequest) returns (LoginResponse) post /reset/telephone (TelephoneResetPasswordRequest) returns (LoginResponse)
@doc "Device Login"
@handler DeviceLogin
post /login/device (DeviceLoginRequest) returns (LoginResponse)
} }
@server ( @server (
+10 -29
View File
@@ -35,6 +35,10 @@ type (
GetTosResponse { GetTosResponse {
TosContent string `json:"tos_content"` TosContent string `json:"tos_content"`
} }
GetAppcationResponse {
Config ApplicationConfig `json:"config"`
Applications []ApplicationResponseInfo `json:"applications"`
}
// GetCodeRequest Get code request // GetCodeRequest Get code request
SendCodeRequest { SendCodeRequest {
Email string `json:"email" validate:"required"` Email string `json:"email" validate:"required"`
@@ -74,36 +78,21 @@ type (
CheckVerificationCodeRespone { CheckVerificationCodeRespone {
Status bool `json:"status"` 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 ( @server (
prefix: v1/common prefix: v1/common
group: common group: common
middleware: DeviceMiddleware
) )
service ppanel { service ppanel {
@doc "Get global config" @doc "Get global config"
@handler GetGlobalConfig @handler GetGlobalConfig
get /site/config returns (GetGlobalConfigResponse) get /site/config returns (GetGlobalConfigResponse)
@doc "Get Tos Content"
@handler GetApplication
get /application returns (GetAppcationResponse)
@doc "Get Tos Content" @doc "Get Tos Content"
@handler GetTos @handler GetTos
get /site/tos returns (GetTosResponse) get /site/tos returns (GetTosResponse)
@@ -131,13 +120,5 @@ service ppanel {
@doc "Check verification code" @doc "Check verification code"
@handler CheckVerificationCode @handler CheckVerificationCode
post /check_verification_code (CheckVerificationCodeRequest) returns (CheckVerificationCodeRespone) post /check_verification_code (CheckVerificationCodeRequest) returns (CheckVerificationCodeRespone)
@doc "Get Client"
@handler GetClient
get /client returns (GetSubscribeClientResponse)
@doc "Heartbeat"
@handler Heartbeat
get /heartbeat returns (HeartbeatResponse)
} }
-28
View File
@@ -11,10 +11,6 @@ info (
import "../types.api" import "../types.api"
type ( type (
OnlineUser {
SID int64 `json:"uid"`
IP string `json:"ip"`
}
ShadowsocksProtocol { ShadowsocksProtocol {
Port int `json:"port"` Port int `json:"port"`
Method string `json:"method"` Method string `json:"method"`
@@ -93,20 +89,6 @@ type (
ServerCommon ServerCommon
Users []OnlineUser `json:"users"` 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 ( @server (
@@ -136,13 +118,3 @@ service ppanel {
post /online (OnlineUsersRequest) post /online (OnlineUsersRequest)
} }
@server (
prefix: v2/server
group: server
)
service ppanel {
@doc "Get Server Protocol Config"
@handler QueryServerProtocolConfig
get /:server_id (QueryServerConfigRequest) returns (QueryServerConfigResponse)
}
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server ( @server (
prefix: v1/public/announcement prefix: v1/public/announcement
group: public/announcement group: public/announcement
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Query announcement" @doc "Query announcement"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server ( @server (
prefix: v1/public/document prefix: v1/public/document
group: public/document group: public/document
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Get document list" @doc "Get document list"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server ( @server (
prefix: v1/public/order prefix: v1/public/order
group: public/order group: public/order
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Pre create order" @doc "Pre create order"
+1 -1
View File
@@ -13,7 +13,7 @@ import "../types.api"
@server ( @server (
prefix: v1/public/payment prefix: v1/public/payment
group: public/payment group: public/payment
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Get available payment methods" @doc "Get available payment methods"
+3 -7
View File
@@ -25,9 +25,6 @@ type (
PortalPurchaseResponse { PortalPurchaseResponse {
OrderNo string `json:"order_no"` OrderNo string `json:"order_no"`
} }
GetSubscriptionRequest {
Language string `form:"language"`
}
GetSubscriptionResponse { GetSubscriptionResponse {
List []Subscribe `json:"list"` List []Subscribe `json:"list"`
} }
@@ -68,9 +65,8 @@ type (
) )
@server ( @server (
prefix: v1/public/portal prefix: v1/public/portal
group: public/portal group: public/portal
middleware: DeviceMiddleware
) )
service ppanel { service ppanel {
@doc "Get available payment methods" @doc "Get available payment methods"
@@ -79,7 +75,7 @@ service ppanel {
@doc "Get Subscription" @doc "Get Subscription"
@handler GetSubscription @handler GetSubscription
get /subscribe (GetSubscriptionRequest) returns (GetSubscriptionResponse) get /subscribe returns (GetSubscriptionResponse)
@doc "Pre Purchase Order" @doc "Pre Purchase Order"
@handler PrePurchaseOrder @handler PrePurchaseOrder
+9 -45
View File
@@ -10,58 +10,22 @@ info (
import "../types.api" 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 ( @server (
prefix: v1/public/subscribe prefix: v1/public/subscribe
group: public/subscribe group: public/subscribe
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Get subscribe list" @doc "Get subscribe list"
@handler QuerySubscribeList @handler QuerySubscribeList
get /list (QuerySubscribeListRequest) returns (QuerySubscribeListResponse) get /list returns (QuerySubscribeListResponse)
@doc "Get user subscribe node info" @doc "Get subscribe group list"
@handler QueryUserSubscribeNodeList @handler QuerySubscribeGroupList
get /node/list returns (QueryUserSubscribeNodeListResponse) get /group/list returns (QuerySubscribeGroupListResponse)
@doc "Get application config"
@handler QueryApplicationConfig
get /application/config returns (ApplicationResponse)
} }
+7 -5
View File
@@ -18,12 +18,14 @@ type (
CreateUserTicketRequest { CreateUserTicketRequest {
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
IssueType uint8 `json:"issue_type"`
} }
GetUserTicketListRequest { GetUserTicketListRequest {
Page int `form:"page"` Page int `form:"page"`
Size int `form:"size"` Size int `form:"size"`
Status *uint8 `form:"status,omitempty"` Status *uint8 `form:"status,omitempty"`
Search string `form:"search,omitempty"` IssueType *uint8 `form:"issue_type,omitempty"`
Search string `form:"search,omitempty"`
} }
GetUserTicketDetailRequest { GetUserTicketDetailRequest {
Id int64 `form:"id" validate:"required"` Id int64 `form:"id" validate:"required"`
@@ -43,7 +45,7 @@ type (
@server ( @server (
prefix: v1/public/ticket prefix: v1/public/ticket
group: public/ticket group: public/ticket
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Get ticket list" @doc "Get ticket list"
+10 -63
View File
@@ -25,8 +25,15 @@ type (
Total int64 `json:"total"` Total int64 `json:"total"`
} }
QueryUserBalanceLogListResponse { QueryUserBalanceLogListResponse {
List []BalanceLog `json:"list"` List []UserBalanceLog `json:"list"`
Total int64 `json:"total"` 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 { QueryUserCommissionLogListRequest {
Page int `form:"page"` Page int `form:"page"`
@@ -97,48 +104,12 @@ type (
Email string `json:"email" validate:"required"` Email string `json:"email" validate:"required"`
Code string `json:"code" 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 ( @server (
prefix: v1/public/user prefix: v1/public/user
group: public/user group: public/user
middleware: AuthMiddleware,DeviceMiddleware middleware: AuthMiddleware
) )
service ppanel { service ppanel {
@doc "Query User Info" @doc "Query User Info"
@@ -228,29 +199,5 @@ service ppanel {
@doc "Update Bind Email" @doc "Update Bind Email"
@handler UpdateBindEmail @handler UpdateBindEmail
put /bind_email (UpdateBindEmailRequest) 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)
} }
-2
View File
@@ -24,7 +24,5 @@ import (
"./admin/auth.api" "./admin/auth.api"
"./admin/log.api" "./admin/log.api"
"./admin/ads.api" "./admin/ads.api"
"./admin/marketing.api"
"./admin/application.api"
) )
+22
View File
@@ -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"
)
+66 -158
View File
@@ -14,8 +14,6 @@ type (
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
Commission int64 `json:"commission"` Commission int64 `json:"commission"`
ReferralPercentage uint8 `json:"referral_percentage"`
OnlyFirstPurchase bool `json:"only_first_purchase"`
GiftAmount int64 `json:"gift_amount"` GiftAmount int64 `json:"gift_amount"`
Telegram int64 `json:"telegram"` Telegram int64 `json:"telegram"`
ReferCode string `json:"refer_code"` ReferCode string `json:"refer_code"`
@@ -28,7 +26,6 @@ type (
EnableTradeNotify bool `json:"enable_trade_notify"` EnableTradeNotify bool `json:"enable_trade_notify"`
AuthMethods []UserAuthMethod `json:"auth_methods"` AuthMethods []UserAuthMethod `json:"auth_methods"`
UserDevices []UserDevice `json:"user_devices"` UserDevices []UserDevice `json:"user_devices"`
Rules []string `json:"rules"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
DeletedAt int64 `json:"deleted_at,omitempty"` DeletedAt int64 `json:"deleted_at,omitempty"`
@@ -66,8 +63,6 @@ type (
SubscribePath string `json:"subscribe_path"` SubscribePath string `json:"subscribe_path"`
SubscribeDomain string `json:"subscribe_domain"` SubscribeDomain string `json:"subscribe_domain"`
PanDomain bool `json:"pan_domain"` PanDomain bool `json:"pan_domain"`
UserAgentLimit bool `json:"user_agent_limit"`
UserAgentList string `json:"user_agent_list"`
} }
VerifyCodeConfig { VerifyCodeConfig {
VerifyCodeExpireTime int64 `json:"verify_code_expire_time"` VerifyCodeExpireTime int64 `json:"verify_code_expire_time"`
@@ -116,7 +111,6 @@ type (
AuthConfig { AuthConfig {
Mobile MobileAuthenticateConfig `json:"mobile"` Mobile MobileAuthenticateConfig `json:"mobile"`
Email EmailAuthticateConfig `json:"email"` Email EmailAuthticateConfig `json:"email"`
Device DeviceAuthticateConfig `json:"device"`
Register PubilcRegisterConfig `json:"register"` Register PubilcRegisterConfig `json:"register"`
} }
PubilcRegisterConfig { PubilcRegisterConfig {
@@ -136,12 +130,6 @@ type (
EnableDomainSuffix bool `json:"enable_domain_suffix"` EnableDomainSuffix bool `json:"enable_domain_suffix"`
DomainSuffixList string `json:"domain_suffix_list"` 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 { RegisterConfig {
StopRegister bool `json:"stop_register"` StopRegister bool `json:"stop_register"`
EnableTrial bool `json:"enable_trial"` EnableTrial bool `json:"enable_trial"`
@@ -160,27 +148,9 @@ type (
EnableResetPasswordVerify bool `json:"enable_reset_password_verify"` EnableResetPasswordVerify bool `json:"enable_reset_password_verify"`
} }
NodeConfig { NodeConfig {
NodeSecret string `json:"node_secret"` NodeSecret string `json:"node_secret"`
NodePullInterval int64 `json:"node_pull_interval"` NodePullInterval int64 `json:"node_pull_interval"`
NodePushInterval int64 `json:"node_push_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 { InviteConfig {
ForcedInvite bool `json:"forced_invite"` ForcedInvite bool `json:"forced_invite"`
@@ -212,7 +182,6 @@ type (
Subscribe { Subscribe {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Language string `json:"language"`
Description string `json:"description"` Description string `json:"description"`
UnitPrice int64 `json:"unit_price"` UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"` UnitTime string `json:"unit_time"`
@@ -223,8 +192,9 @@ type (
SpeedLimit int64 `json:"speed_limit"` SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"` DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"` Quota int64 `json:"quota"`
Nodes []int64 `json:"nodes"` GroupId int64 `json:"group_id"`
NodeTags []string `json:"node_tags"` ServerGroup []int64 `json:"server_group"`
Server []int64 `json:"server"`
Show bool `json:"show"` Show bool `json:"show"`
Sell bool `json:"sell"` Sell bool `json:"sell"`
Sort int64 `json:"sort"` Sort int64 `json:"sort"`
@@ -303,37 +273,37 @@ type (
Host string `json:"host"` Host string `json:"host"`
ServiceName string `json:"service_name"` ServiceName string `json:"service_name"`
} }
// Server { Server {
// Id int64 `json:"id"` Id int64 `json:"id"`
// Tags []string `json:"tags"` Tags []string `json:"tags"`
// Country string `json:"country"` Country string `json:"country"`
// City string `json:"city"` City string `json:"city"`
// Name string `json:"name"` Name string `json:"name"`
// ServerAddr string `json:"server_addr"` ServerAddr string `json:"server_addr"`
// RelayMode string `json:"relay_mode"` RelayMode string `json:"relay_mode"`
// RelayNode []NodeRelay `json:"relay_node"` RelayNode []NodeRelay `json:"relay_node"`
// SpeedLimit int `json:"speed_limit"` SpeedLimit int `json:"speed_limit"`
// TrafficRatio float32 `json:"traffic_ratio"` TrafficRatio float32 `json:"traffic_ratio"`
// GroupId int64 `json:"group_id"` GroupId int64 `json:"group_id"`
// Protocol string `json:"protocol"` Protocol string `json:"protocol"`
// Config interface{} `json:"config"` Config interface{} `json:"config"`
// Enable *bool `json:"enable"` Enable *bool `json:"enable"`
// CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
// UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
// Status *NodeStatus `json:"status"` Status *NodeStatus `json:"status"`
// Sort int64 `json:"sort"` Sort int64 `json:"sort"`
// } }
// OnlineUser { OnlineUser {
// SID int64 `json:"uid"` SID int64 `json:"uid"`
// IP string `json:"ip"` IP string `json:"ip"`
// } }
// NodeStatus { NodeStatus {
// Online interface{} `json:"online"` Online interface{} `json:"online"`
// Cpu float64 `json:"cpu"` Cpu float64 `json:"cpu"`
// Mem float64 `json:"mem"` Mem float64 `json:"mem"`
// Disk float64 `json:"disk"` Disk float64 `json:"disk"`
// UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
// } }
ServerGroup { ServerGroup {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
@@ -472,10 +442,18 @@ type (
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Token string `json:"token"` Token string `json:"token"`
Status uint8 `json:"status"` Status uint8 `json:"status"`
Short string `json:"short"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_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 { UserAffiliate {
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
Identifier string `json:"identifier"` Identifier string `json:"identifier"`
@@ -496,6 +474,14 @@ type (
Port int `json:"port"` Port int `json:"port"`
Prefix string `json:"prefix"` 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 { UserDevice {
Id int64 `json:"id"` Id int64 `json:"id"`
Ip string `json:"ip"` Ip string `json:"ip"`
@@ -530,7 +516,7 @@ type (
Id int64 `json:"id"` Id int64 `json:"id"`
Icon string `json:"icon"` Icon string `json:"icon"`
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Type string `json:"type"` Type string `json:"type"`
Tags []string `json:"tags"` Tags []string `json:"tags"`
Rules string `json:"rules"` Rules string `json:"rules"`
Enable bool `json:"enable"` Enable bool `json:"enable"`
@@ -545,7 +531,7 @@ type (
Token string `json:"token"` Token string `json:"token"`
IP string `json:"ip"` IP string `json:"ip"`
UserAgent string `json:"user_agent"` UserAgent string `json:"user_agent"`
Timestamp int64 `json:"timestamp"` CreatedAt int64 `json:"created_at"`
} }
UserLoginLog { UserLoginLog {
Id int64 `json:"id"` Id int64 `json:"id"`
@@ -553,17 +539,18 @@ type (
LoginIP string `json:"login_ip"` LoginIP string `json:"login_ip"`
UserAgent string `json:"user_agent"` UserAgent string `json:"user_agent"`
Success bool `json:"success"` Success bool `json:"success"`
Timestamp int64 `json:"timestamp"` CreatedAt int64 `json:"created_at"`
} }
MessageLog { MessageLog {
Id int64 `json:"id"` Id int64 `json:"id"`
Type uint8 `json:"type"` Type string `json:"type"`
Platform string `json:"platform"` Platform string `json:"platform"`
To string `json:"to"` To string `json:"to"`
Subject string `json:"subject"` Subject string `json:"subject"`
Content interface{} `json:"content"` Content string `json:"content"`
Status uint8 `json:"status"` Status int `json:"status"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
} }
Ads { Ads {
Id int `json:"id"` Id int `json:"id"`
@@ -767,84 +754,5 @@ type (
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
Download int64 `json:"download"` 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
}
) )
-42
View File
@@ -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
View File
@@ -2,11 +2,11 @@ Host: 0.0.0.0
Port: 8080 Port: 8080
Debug: false Debug: false
JwtAuth: JwtAuth:
AccessSecret: 1234567890 AccessSecret: e4bbdb8ca57179374c0e8a7a85038da21341aee4bdff98c0e612751d7c362cac
AccessExpire: 604800 AccessExpire: 604800
Logger: Logger:
ServiceName: PPanel ServiceName: PPanel
Mode: console Mode: file
Encoding: plain Encoding: plain
TimeFormat: '2025-01-01 00:00:00.000' TimeFormat: '2025-01-01 00:00:00.000'
Path: logs Path: logs
@@ -21,7 +21,7 @@ Logger:
Rotation: daily Rotation: daily
FileTimeFormat: 2025-01-01T00:00:00.000Z00:00 FileTimeFormat: 2025-01-01T00:00:00.000Z00:00
MySQL: MySQL:
Addr: 172.245.180.199:3306 Addr: ppanel-db:3306
Dbname: ppanel Dbname: ppanel
Username: ppanel Username: ppanel
Password: ppanelpassword Password: ppanelpassword
@@ -36,3 +36,15 @@ Redis:
Administrator: Administrator:
Password: password Password: password
Email: admin@ppanel.dev 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.
+5 -7
View File
@@ -20,7 +20,7 @@ require (
github.com/go-sql-driver/mysql v1.8.1 github.com/go-sql-driver/mysql v1.8.1
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
github.com/gofrs/uuid/v5 v5.3.0 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/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/hibiken/asynq v0.24.1 github.com/hibiken/asynq v0.24.1
@@ -28,7 +28,7 @@ require (
github.com/klauspost/compress v1.17.7 github.com/klauspost/compress v1.17.7
github.com/nyaruka/phonenumbers v1.5.0 github.com/nyaruka/phonenumbers v1.5.0
github.com/pkg/errors v0.9.1 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/smartwalle/alipay/v3 v3.2.23
github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
@@ -44,7 +44,7 @@ require (
go.opentelemetry.io/otel/sdk v1.29.0 go.opentelemetry.io/otel/sdk v1.29.0
go.opentelemetry.io/otel/trace v1.29.0 go.opentelemetry.io/otel/trace v1.29.0
go.uber.org/zap v1.27.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/oauth2 v0.25.0
golang.org/x/time v0.6.0 golang.org/x/time v0.6.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
@@ -60,7 +60,6 @@ require (
github.com/fatih/color v1.18.0 github.com/fatih/color v1.18.0
github.com/goccy/go-json v0.10.4 github.com/goccy/go-json v0.10.4
github.com/golang-migrate/migrate/v4 v4.18.2 github.com/golang-migrate/migrate/v4 v4.18.2
github.com/oschwald/geoip2-golang v1.13.0
github.com/spaolacci/murmur3 v1.1.0 github.com/spaolacci/murmur3 v1.1.0
google.golang.org/grpc v1.64.1 google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.36.3 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/openzipkin/zipkin-go v0.4.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/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/robfig/cron/v3 v3.0.1 // 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/arch v0.13.0 // indirect
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d // indirect golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d // indirect
golang.org/x/net v0.34.0 // indirect golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.22.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/api v0.0.0-20240513163218-0867130af1f8 // indirect
google.golang.org/genproto/googleapis/rpc 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 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+10 -14
View File
@@ -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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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 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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= 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 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8=
github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk= 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= 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/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 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= 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 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 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/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/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.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.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
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/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 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= 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= 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-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.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.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= 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-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 h1:N0hmiNbwsSNwHBAvR3QB5w25pUwH4tK0Y/RltD1j1h4=
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= 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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.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.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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-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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 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.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.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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 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.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 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+1 -22
View File
@@ -9,7 +9,6 @@ import (
"net/http" "net/http"
"os" "os"
"github.com/perfect-panel/server/internal/report"
"github.com/perfect-panel/server/pkg/logger" "github.com/perfect-panel/server/pkg/logger"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
@@ -36,30 +35,10 @@ func Config(path string) (chan bool, *http.Server) {
configPath = path configPath = path
// Create a new Gin instance // Create a new Gin instance
r := gin.Default() 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 // Create a new HTTP server
server := &http.Server{ server := &http.Server{
Addr: fmt.Sprintf("%s:%d", host, port), Addr: ":8080",
Handler: r, Handler: r,
} }
// Load templates // Load templates
-26
View File
@@ -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
View File
@@ -9,12 +9,12 @@ func StartInitSystemConfig(svc *svc.ServiceContext) {
Site(svc) Site(svc)
Node(svc) Node(svc)
Email(svc) Email(svc)
Device(svc)
Invite(svc) Invite(svc)
Verify(svc) Verify(svc)
Subscribe(svc) Subscribe(svc)
Register(svc) Register(svc)
Mobile(svc) Mobile(svc)
TrafficDataToRedis(svc)
if !svc.Config.Debug { if !svc.Config.Debug {
Telegram(svc) Telegram(svc)
} }
@@ -91,6 +91,7 @@ CREATE TABLE IF NOT EXISTS `auth_method`
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uni_auth_method` (`method`) UNIQUE KEY `uni_auth_method` (`method`)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 9
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci; COLLATE = utf8mb4_general_ci;
@@ -304,6 +305,7 @@ CREATE TABLE IF NOT EXISTS `subscribe_type`
`updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间', `updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 15
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci; COLLATE = utf8mb4_general_ci;
@@ -321,6 +323,7 @@ CREATE TABLE IF NOT EXISTS `system`
UNIQUE KEY `uni_system_key` (`key`), UNIQUE KEY `uni_system_key` (`key`),
KEY `index_key` (`key`) KEY `index_key` (`key`)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 42
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci; COLLATE = utf8mb4_general_ci;
@@ -379,6 +382,7 @@ CREATE TABLE IF NOT EXISTS `user`
`referer_id` bigint DEFAULT NULL COMMENT 'Referrer ID', `referer_id` bigint DEFAULT NULL COMMENT 'Referrer ID',
`commission` bigint DEFAULT '0' COMMENT 'Commission', `commission` bigint DEFAULT '0' COMMENT 'Commission',
`gift_amount` bigint DEFAULT '0' COMMENT 'User Gift Amount', `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', `enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Is Account Enabled',
`is_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Admin', `is_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Admin',
`valid_email` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Email Verified', `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`), PRIMARY KEY (`id`),
KEY `idx_referer` (`referer_id`) KEY `idx_referer` (`referer_id`)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci; COLLATE = utf8mb4_general_ci;
@@ -411,6 +416,7 @@ CREATE TABLE IF NOT EXISTS `user_auth_methods`
UNIQUE KEY `idx_auth_identifier` (`auth_identifier`), UNIQUE KEY `idx_auth_identifier` (`auth_identifier`),
KEY `idx_user_id` (`user_id`) KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci; 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