新增webhook url参数

This commit is contained in:
2025-10-29 12:06:18 +08:00
parent 003ff9a94e
commit 38e81dbfe6
8 changed files with 715 additions and 18 deletions

View File

@@ -89,24 +89,58 @@ pip install -r requirements.txt
# 注意成语接龙游戏需要pypinyin库进行拼音处理
```
3. **配置环境变量**
3. **配置Webhook**
有三种方式配置Webhook URL
#### 方式1命令行参数推荐
```bash
# Linux/Mac
python app.py --webhook-url "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
# Windows
python app.py --webhook-url "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
```
#### 方式2使用启动脚本
```bash
# Linux/Mac
./start.sh -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
# Windows
start.bat -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
```
#### 方式3环境变量
```bash
# 复制配置文件模板
cp env.example .env
cp config.env.example config.env
# 编辑配置文件填入你的Webhook URL
nano .env
nano config.env
```
4. **运行应用**
```bash
# 开发模式
# 基本启动
python app.py
# 自定义参数启动
python app.py --webhook-url "your_webhook_url" --port 8080 --log-level debug
# 使用启动脚本
./start.sh -w "your_webhook_url" -p 8080 -l debug
# 生产模式使用uvicorn
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 1
```
### 命令行参数说明
- `--webhook-url, -w`: WPS Webhook URL
- `--host, -H`: 服务器主机地址 (默认: 0.0.0.0)
- `--port, -p`: 服务器端口 (默认: 11000)
- `--workers`: 工作进程数 (默认: 1)
- `--log-level`: 日志级别 (默认: info)
## 📝 配置说明
### 环境变量

243
STARTUP_GUIDE.md Normal file
View File

@@ -0,0 +1,243 @@
# WPS Bot Game 启动方式说明
## 🚀 多种启动方式
### 1. 命令行参数启动(推荐)
#### 基本启动
```bash
python app.py --webhook-url "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
```
#### 自定义参数启动
```bash
python app.py \
--webhook-url "https://xz.wps.cn/api/v1/webhook/send?key=your_key" \
--host 0.0.0.0 \
--port 8080 \
--workers 1 \
--log-level debug
```
#### 短参数形式
```bash
python app.py -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key" -p 8080 -l debug
```
### 2. 使用启动脚本
#### Linux/Mac
```bash
# 基本启动
./start.sh -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
# 自定义参数
./start.sh -w "your_webhook_url" -p 8080 -l debug
# 查看帮助
./start.sh --help
```
#### Windows
```cmd
REM 基本启动
start.bat -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
REM 自定义参数
start.bat -w "your_webhook_url" -p 8080 -l debug
REM 查看帮助
start.bat --help
```
### 3. 环境变量启动
#### 设置环境变量
```bash
# Linux/Mac
export WEBHOOK_URL="https://xz.wps.cn/api/v1/webhook/send?key=your_key"
export HOST="0.0.0.0"
export PORT="8080"
export LOG_LEVEL="debug"
# Windows
set WEBHOOK_URL=https://xz.wps.cn/api/v1/webhook/send?key=your_key
set HOST=0.0.0.0
set PORT=8080
set LOG_LEVEL=debug
```
#### 启动应用
```bash
python app.py
```
### 4. 配置文件启动
#### 创建配置文件
```bash
# 复制配置模板
cp config.env.example config.env
# 编辑配置文件
nano config.env
```
#### 配置文件内容
```env
WEBHOOK_URL=https://xz.wps.cn/api/v1/webhook/send?key=your_key
HOST=0.0.0.0
PORT=8080
WORKERS=1
LOG_LEVEL=debug
```
#### 启动应用
```bash
python app.py
```
## 📋 参数说明
| 参数 | 短参数 | 默认值 | 说明 |
|------|--------|--------|------|
| `--webhook-url` | `-w` | 无 | WPS Webhook URL |
| `--host` | `-H` | `0.0.0.0` | 服务器主机地址 |
| `--port` | `-p` | `11000` | 服务器端口 |
| `--workers` | 无 | `1` | 工作进程数 |
| `--log-level` | `-l` | `info` | 日志级别 |
## 🔧 生产环境部署
### 使用systemd服务
```bash
# 编辑服务文件
sudo nano /etc/systemd/system/wps-bot.service
# 服务文件内容
[Unit]
Description=WPS Bot Game
After=network.target
[Service]
Type=simple
User=your_user
WorkingDirectory=/path/to/WPSBotGame
ExecStart=/usr/bin/python3 app.py --webhook-url "your_webhook_url" --port 11000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
### 使用Docker
```dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py", "--webhook-url", "your_webhook_url"]
```
### 使用Nginx反向代理
```nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://127.0.0.1:11000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## 🐛 故障排除
### 1. 端口被占用
```bash
# 查看端口占用
netstat -tlnp | grep :11000
# 杀死占用进程
sudo kill -9 PID
# 或使用其他端口
python app.py --port 8080
```
### 2. 权限问题
```bash
# 给启动脚本执行权限
chmod +x start.sh
# 检查文件权限
ls -la start.sh
```
### 3. 依赖问题
```bash
# 检查Python版本
python --version
# 安装依赖
pip install -r requirements.txt
# 检查依赖
python -c "import fastapi, uvicorn"
```
### 4. 网络问题
```bash
# 测试Webhook URL
curl -X POST "your_webhook_url" \
-H "Content-Type: application/json" \
-d '{"msg_type": "text", "content": {"text": "test"}}'
# 检查防火墙
sudo ufw status
sudo ufw allow 11000
```
## 📊 监控和日志
### 查看日志
```bash
# 实时查看日志
tail -f /var/log/wps-bot.log
# 查看系统日志
journalctl -u wps-bot -f
# 查看错误日志
grep ERROR /var/log/wps-bot.log
```
### 健康检查
```bash
# 检查服务状态
curl http://localhost:11000/health
# 检查统计信息
curl http://localhost:11000/stats
```
### 性能监控
```bash
# 查看进程状态
ps aux | grep python
# 查看内存使用
free -h
# 查看磁盘使用
df -h
```

41
app.py
View File

@@ -1,5 +1,7 @@
"""WPS Bot Game - FastAPI主应用"""
import logging
import argparse
import os
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
@@ -94,14 +96,45 @@ async def global_exception_handler(request, exc):
)
def parse_args():
"""解析命令行参数"""
parser = argparse.ArgumentParser(description='WPS Bot Game')
parser.add_argument('--webhook-url', '-w',
help='WPS Webhook URL')
parser.add_argument('--host', '-H',
default='0.0.0.0',
help='服务器主机地址 (默认: 0.0.0.0)')
parser.add_argument('--port', '-p',
type=int, default=11000,
help='服务器端口 (默认: 11000)')
parser.add_argument('--workers',
type=int, default=1,
help='工作进程数 (默认: 1)')
parser.add_argument('--log-level',
default='info',
choices=['debug', 'info', 'warning', 'error'],
help='日志级别 (默认: info)')
return parser.parse_args()
if __name__ == "__main__":
import uvicorn
# 解析命令行参数
args = parse_args()
# 如果提供了webhook URL设置环境变量
if args.webhook_url:
os.environ['WEBHOOK_URL'] = args.webhook_url
logger.info(f"设置Webhook URL: {args.webhook_url}")
# 启动服务器
uvicorn.run(
"app:app",
host="0.0.0.0",
port=11000,
workers=1,
host=args.host,
port=args.port,
workers=args.workers,
limit_concurrency=5,
log_level="info"
log_level=args.log_level
)

21
config.env.example Normal file
View File

@@ -0,0 +1,21 @@
# WPS Bot Game 配置文件示例
# 复制此文件为 config.env 并修改相应配置
# WPS Webhook URL (必需)
# 格式: https://xz.wps.cn/api/v1/webhook/send?key=your_key
WEBHOOK_URL=https://xz.wps.cn/api/v1/webhook/send?key=your_key_here
# 服务器配置
HOST=0.0.0.0
PORT=11000
WORKERS=1
# 日志配置
LOG_LEVEL=info
# 数据库配置
DATABASE_URL=sqlite:///data/bot.db
# 其他配置
SESSION_TIMEOUT=300
CONCURRENCY_LIMIT=5

View File

@@ -33,12 +33,25 @@ class Database:
def conn(self) -> sqlite3.Connection:
"""获取数据库连接(懒加载)"""
if self._conn is None:
try:
self._conn = sqlite3.connect(
self.db_path,
check_same_thread=False, # 允许多线程访问
isolation_level=None # 自动提交
isolation_level=None, # 自动提交
timeout=30.0 # 增加超时时间
)
self._conn.row_factory = sqlite3.Row # 支持字典式访问
# 启用WAL模式以提高并发性能
self._conn.execute("PRAGMA journal_mode=WAL")
self._conn.execute("PRAGMA synchronous=NORMAL")
self._conn.execute("PRAGMA cache_size=1000")
self._conn.execute("PRAGMA temp_store=MEMORY")
logger.info(f"数据库连接成功: {self.db_path}")
except Exception as e:
logger.error(f"数据库连接失败: {e}", exc_info=True)
raise
return self._conn
def init_tables(self):
@@ -416,12 +429,16 @@ class Database:
是否成功
"""
if points <= 0:
logger.warning(f"积分数量无效: {points}")
return False
cursor = self.conn.cursor()
current_time = int(time.time())
try:
# 确保用户存在
self.get_or_create_user(user_id)
# 更新用户积分
cursor.execute("""
INSERT INTO user_points (user_id, total_points, available_points, created_at, updated_at)
@@ -433,17 +450,24 @@ class Database:
updated_at = ?
""", (user_id, points, points, current_time, current_time, points, points, current_time))
# 验证积分是否真的更新了
cursor.execute("SELECT available_points FROM user_points WHERE user_id = ?", (user_id,))
updated_points = cursor.fetchone()
if not updated_points:
logger.error(f"积分更新后查询失败: user_id={user_id}")
return False
# 记录积分变动
cursor.execute(
"INSERT INTO points_records (user_id, points, source, description, created_at) VALUES (?, ?, ?, ?, ?)",
(user_id, points, source, description, current_time)
)
logger.debug(f"用户 {user_id} 获得 {points} 积分,来源:{source}")
logger.info(f"用户 {user_id} 成功获得 {points} 积分,来源:{source},当前积分:{updated_points[0]}")
return True
except Exception as e:
logger.error(f"添加积分失败: {e}")
logger.error(f"添加积分失败: user_id={user_id}, points={points}, error={e}", exc_info=True)
return False
def consume_points(self, user_id: int, points: int, source: str, description: str = None) -> bool:
@@ -554,6 +578,10 @@ class Database:
# 确保用户存在
self.get_or_create_user(user_id)
# 获取签到前积分
points_before = self.get_user_points(user_id)
logger.info(f"用户 {user_id} 签到前积分: {points_before['available_points']}")
# 记录签到
cursor.execute(
"INSERT INTO daily_checkins (user_id, checkin_date, points_earned, created_at) VALUES (?, ?, ?, ?)",
@@ -562,8 +590,17 @@ class Database:
# 添加积分
result = self.add_points(user_id, points, "daily_checkin", f"每日签到奖励")
logger.info(f"用户 {user_id} 签到结果: {result}, 积分: {points}")
return result
# 验证积分是否真的增加了
points_after = self.get_user_points(user_id)
logger.info(f"用户 {user_id} 签到后积分: {points_after['available_points']}")
if points_after['available_points'] > points_before['available_points']:
logger.info(f"用户 {user_id} 签到成功,积分增加: {points_after['available_points'] - points_before['available_points']}")
return True
else:
logger.error(f"用户 {user_id} 签到失败,积分未增加")
return False
except Exception as e:
logger.error(f"每日签到失败: {e}", exc_info=True)

75
diagnose_checkin.py Normal file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""签到问题诊断脚本"""
import os
import sys
import sqlite3
from pathlib import Path
from datetime import datetime
import time
def diagnose_checkin_issue():
"""诊断签到问题"""
print("=== 签到问题诊断 ===")
# 1. 检查数据库文件
db_path = "data/bot.db"
print(f"1. 数据库文件路径: {db_path}")
print(f" 文件存在: {os.path.exists(db_path)}")
if os.path.exists(db_path):
stat = os.stat(db_path)
print(f" 文件大小: {stat.st_size} bytes")
print(f" 文件权限: {oct(stat.st_mode)}")
print(f" 最后修改: {datetime.fromtimestamp(stat.st_mtime)}")
# 2. 检查数据库目录
db_dir = Path(db_path).parent
print(f"2. 数据库目录: {db_dir}")
print(f" 目录存在: {db_dir.exists()}")
print(f" 目录可写: {os.access(db_dir, os.W_OK)}")
# 3. 测试数据库连接
print("3. 测试数据库连接...")
try:
conn = sqlite3.connect(db_path, timeout=10.0)
cursor = conn.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = cursor.fetchall()
print(f" 数据库表: {[table[0] for table in tables]}")
# 检查用户积分表
if ('user_points',) in tables:
cursor.execute("SELECT COUNT(*) FROM user_points")
count = cursor.fetchone()[0]
print(f" 用户积分记录数: {count}")
if count > 0:
cursor.execute("SELECT user_id, available_points FROM user_points LIMIT 3")
users = cursor.fetchall()
print(f" 示例用户积分: {users}")
conn.close()
print(" 数据库连接: 成功")
except Exception as e:
print(f" 数据库连接: 失败 - {e}")
# 4. 检查磁盘空间
print("4. 检查磁盘空间...")
try:
statvfs = os.statvfs(db_dir)
free_space = statvfs.f_frsize * statvfs.f_bavail
total_space = statvfs.f_frsize * statvfs.f_blocks
print(f" 可用空间: {free_space / (1024*1024):.1f} MB")
print(f" 总空间: {total_space / (1024*1024):.1f} MB")
except Exception as e:
print(f" 磁盘空间检查失败: {e}")
# 5. 检查进程权限
print("5. 检查进程权限...")
print(f" 当前用户: {os.getuid() if hasattr(os, 'getuid') else 'N/A'}")
print(f" 当前组: {os.getgid() if hasattr(os, 'getgid') else 'N/A'}")
print("=== 诊断完成 ===")
if __name__ == "__main__":
diagnose_checkin_issue()

150
start.bat Normal file
View File

@@ -0,0 +1,150 @@
@echo off
REM WPS Bot Game Windows启动脚本
setlocal enabledelayedexpansion
REM 默认配置
set DEFAULT_WEBHOOK_URL=
set DEFAULT_HOST=0.0.0.0
set DEFAULT_PORT=11000
set DEFAULT_WORKERS=1
set DEFAULT_LOG_LEVEL=info
REM 显示帮助信息
:show_help
echo WPS Bot Game Windows启动脚本
echo.
echo 用法: %0 [选项]
echo.
echo 选项:
echo -w, --webhook-url URL 设置WPS Webhook URL
echo -H, --host HOST 服务器主机地址 (默认: %DEFAULT_HOST%)
echo -p, --port PORT 服务器端口 (默认: %DEFAULT_PORT%)
echo -W, --workers NUM 工作进程数 (默认: %DEFAULT_WORKERS%)
echo -l, --log-level LEVEL 日志级别 (默认: %DEFAULT_LOG_LEVEL%)
echo -h, --help 显示此帮助信息
echo.
echo 示例:
echo %0 -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key"
echo %0 -w "https://xz.wps.cn/api/v1/webhook/send?key=your_key" -p 8080
echo %0 --webhook-url "https://xz.wps.cn/api/v1/webhook/send?key=your_key" --port 8080 --log-level debug
goto :eof
REM 初始化变量
set WEBHOOK_URL=%DEFAULT_WEBHOOK_URL%
set HOST=%DEFAULT_HOST%
set PORT=%DEFAULT_PORT%
set WORKERS=%DEFAULT_WORKERS%
set LOG_LEVEL=%DEFAULT_LOG_LEVEL%
REM 解析命令行参数
:parse_args
if "%~1"=="" goto :start_app
if "%~1"=="-w" (
set WEBHOOK_URL=%~2
shift
shift
goto :parse_args
)
if "%~1"=="--webhook-url" (
set WEBHOOK_URL=%~2
shift
shift
goto :parse_args
)
if "%~1"=="-H" (
set HOST=%~2
shift
shift
goto :parse_args
)
if "%~1"=="--host" (
set HOST=%~2
shift
shift
goto :parse_args
)
if "%~1"=="-p" (
set PORT=%~2
shift
shift
goto :parse_args
)
if "%~1"=="--port" (
set PORT=%~2
shift
shift
goto :parse_args
)
if "%~1"=="-W" (
set WORKERS=%~2
shift
shift
goto :parse_args
)
if "%~1"=="--workers" (
set WORKERS=%~2
shift
shift
goto :parse_args
)
if "%~1"=="-l" (
set LOG_LEVEL=%~2
shift
shift
goto :parse_args
)
if "%~1"=="--log-level" (
set LOG_LEVEL=%~2
shift
shift
goto :parse_args
)
if "%~1"=="-h" (
call :show_help
exit /b 0
)
if "%~1"=="--help" (
call :show_help
exit /b 0
)
echo 未知参数: %~1
call :show_help
exit /b 1
:start_app
REM 检查Python环境
python --version >nul 2>&1
if errorlevel 1 (
echo 错误: 未找到Python
exit /b 1
)
REM 检查依赖
python -c "import fastapi, uvicorn" >nul 2>&1
if errorlevel 1 (
echo 错误: 缺少必要的Python依赖
echo 请运行: pip install -r requirements.txt
exit /b 1
)
REM 构建启动命令
set CMD=python app.py --host %HOST% --port %PORT% --workers %WORKERS% --log-level %LOG_LEVEL%
if not "%WEBHOOK_URL%"=="" (
set CMD=%CMD% --webhook-url "%WEBHOOK_URL%"
)
REM 显示启动信息
echo 启动WPS Bot Game...
echo 主机: %HOST%
echo 端口: %PORT%
echo 工作进程: %WORKERS%
echo 日志级别: %LOG_LEVEL%
if not "%WEBHOOK_URL%"=="" (
echo Webhook URL: %WEBHOOK_URL%
)
echo.
REM 启动应用
%CMD%

104
start.sh Normal file
View File

@@ -0,0 +1,104 @@
#!/bin/bash
# WPS Bot Game 启动脚本
# 默认配置
DEFAULT_WEBHOOK_URL=""
DEFAULT_HOST="0.0.0.0"
DEFAULT_PORT="11000"
DEFAULT_WORKERS="1"
DEFAULT_LOG_LEVEL="info"
# 显示帮助信息
show_help() {
echo "WPS Bot Game 启动脚本"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " -w, --webhook-url URL 设置WPS Webhook URL"
echo " -H, --host HOST 服务器主机地址 (默认: $DEFAULT_HOST)"
echo " -p, --port PORT 服务器端口 (默认: $DEFAULT_PORT)"
echo " -W, --workers NUM 工作进程数 (默认: $DEFAULT_WORKERS)"
echo " -l, --log-level LEVEL 日志级别 (默认: $DEFAULT_LOG_LEVEL)"
echo " -h, --help 显示此帮助信息"
echo ""
echo "示例:"
echo " $0 -w 'https://xz.wps.cn/api/v1/webhook/send?key=your_key'"
echo " $0 -w 'https://xz.wps.cn/api/v1/webhook/send?key=your_key' -p 8080"
echo " $0 --webhook-url 'https://xz.wps.cn/api/v1/webhook/send?key=your_key' --port 8080 --log-level debug"
}
# 解析命令行参数
WEBHOOK_URL="$DEFAULT_WEBHOOK_URL"
HOST="$DEFAULT_HOST"
PORT="$DEFAULT_PORT"
WORKERS="$DEFAULT_WORKERS"
LOG_LEVEL="$DEFAULT_LOG_LEVEL"
while [[ $# -gt 0 ]]; do
case $1 in
-w|--webhook-url)
WEBHOOK_URL="$2"
shift 2
;;
-H|--host)
HOST="$2"
shift 2
;;
-p|--port)
PORT="$2"
shift 2
;;
-W|--workers)
WORKERS="$2"
shift 2
;;
-l|--log-level)
LOG_LEVEL="$2"
shift 2
;;
-h|--help)
show_help
exit 0
;;
*)
echo "未知参数: $1"
show_help
exit 1
;;
esac
done
# 检查Python环境
if ! command -v python3 &> /dev/null; then
echo "错误: 未找到python3"
exit 1
fi
# 检查依赖
if ! python3 -c "import fastapi, uvicorn" &> /dev/null; then
echo "错误: 缺少必要的Python依赖"
echo "请运行: pip install -r requirements.txt"
exit 1
fi
# 构建启动命令
CMD="python3 app.py --host $HOST --port $PORT --workers $WORKERS --log-level $LOG_LEVEL"
if [ -n "$WEBHOOK_URL" ]; then
CMD="$CMD --webhook-url '$WEBHOOK_URL'"
fi
# 显示启动信息
echo "启动WPS Bot Game..."
echo "主机: $HOST"
echo "端口: $PORT"
echo "工作进程: $WORKERS"
echo "日志级别: $LOG_LEVEL"
if [ -n "$WEBHOOK_URL" ]; then
echo "Webhook URL: $WEBHOOK_URL"
fi
echo ""
# 启动应用
eval $CMD