Initial commit: 酒桌派对 / 大话骰 multiplayer drinking-game hub

- server.py: zero-dependency stdlib backend (HTTP + WebSocket /ws), 大话骰 rule engine, server-driven bots
- live.html: real MVP frontend wired to the backend over WebSocket
- index.html/app.js/style.css: older static prototype
- deploy/: systemd unit + Nginx reverse proxy + Let's Encrypt setup.sh
- test_*.py: standalone HTTP / in-process test scripts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gongch
2026-06-17 10:05:10 +08:00
commit 6d1dd5d56c
28 changed files with 2167 additions and 0 deletions

90
deploy/setup.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/usr/bin/env bash
#
# 在服务器上一键部署「酒桌派对 / 大话骰」
# - 把项目复制到 /opt/drinking-games
# - systemd 常驻运行 server.py (127.0.0.1 视角的 8765 端口,外部由 Nginx 反代)
# - Nginx 反向代理 dn.akqp.online -> 8765含 WebSocket
# - certbot 自动签发 Let's Encrypt 证书并配置 HTTPS + 80→443 跳转
#
# 用法(在已 scp 上来的项目根目录里执行):
# sudo bash deploy/setup.sh
#
set -euo pipefail
DOMAIN="dn.akqp.online"
APP_DIR="/opt/drinking-games"
EMAIL="PumpkinPiekur@hairdresser.net" # certbot 续期通知邮箱
SRC_DIR="$(cd "$(dirname "$0")/.." && pwd)"
log() { printf '\n\033[1;36m== %s\033[0m\n' "$*"; }
die() { printf '\n\033[1;31m[ERR] %s\033[0m\n' "$*" >&2; exit 1; }
[ "$(id -u)" = "0" ] || die "请用 root 执行sudo bash deploy/setup.sh"
command -v python3 >/dev/null || die "未找到 python3"
# ---------- 0. Cloudflare 代理检测 ----------
log "检测域名解析Let's Encrypt 需直连源站)"
SERVER_IP="$(curl -fsS --max-time 10 https://api.ipify.org || echo '?')"
RESOLVED="$(getent ahostsv4 "$DOMAIN" | awk '{print $1}' | sort -u | tr '\n' ' ')"
echo " 本机公网 IP : $SERVER_IP"
echo " 域名解析到 : ${RESOLVED:-(无)}"
if [ "$SERVER_IP" != "?" ] && ! echo " $RESOLVED " | grep -q " $SERVER_IP "; then
cat <<EOF
⚠ $DOMAIN 当前未直接解析到本机(可能在 Cloudflare 橙云代理后面)。
Let's Encrypt 的 HTTP-01 验证可能失败。建议二选一:
a) 在 Cloudflare 把该记录临时切到 "DNS only"(灰云)直连本机,签完证书再开回代理;
开回代理后请把 SSL/TLS 模式设为 Full (strict)。
b) 保持代理,但确保 SSL 模式为 Full 且未强制把 80 端口跳转。
脚本将继续,签证书若失败会停在 certbot 步骤,按上面处理后重跑即可。
EOF
fi
# ---------- 1. 安装依赖 ----------
log "安装 Nginx 与 certbot"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y nginx certbot python3-certbot-nginx rsync
# ---------- 2. 部署应用 ----------
log "复制项目到 $APP_DIR"
mkdir -p "$APP_DIR"
rsync -a --delete \
--exclude '.git' --exclude '__pycache__' --exclude 'deploy' \
--exclude 'test_*.py' \
"$SRC_DIR"/ "$APP_DIR"/
log "安装 systemd 服务 drinking-games"
install -m 644 "$SRC_DIR/deploy/drinking-games.service" /etc/systemd/system/drinking-games.service
systemctl daemon-reload
systemctl enable drinking-games
systemctl restart drinking-games
sleep 1
systemctl is-active --quiet drinking-games || { journalctl -u drinking-games --no-pager -n 30; die "服务启动失败"; }
curl -fsS --max-time 5 http://127.0.0.1:8765/api/rooms >/dev/null && echo " 后端本地自检 OK" || echo " ⚠ 后端本地自检失败,稍后检查日志"
# ---------- 3. Nginx 反代 ----------
log "配置 Nginx 反向代理"
install -m 644 "$SRC_DIR/deploy/nginx-dn.akqp.online.conf" /etc/nginx/sites-available/dn.akqp.online.conf
ln -sf /etc/nginx/sites-available/dn.akqp.online.conf /etc/nginx/sites-enabled/dn.akqp.online.conf
[ -e /etc/nginx/sites-enabled/default ] && rm -f /etc/nginx/sites-enabled/default || true
nginx -t
systemctl reload nginx
# ---------- 4. 防火墙(若启用了 ufw ----------
if command -v ufw >/dev/null && ufw status | grep -q "Status: active"; then
log "放行 80/443关闭 8765 外部访问"
ufw allow 'Nginx Full' || true
ufw deny 8765/tcp || true
fi
# ---------- 5. HTTPS 证书 ----------
log "签发 Let's Encrypt 证书并启用 HTTPS"
certbot --nginx -d "$DOMAIN" \
--non-interactive --agree-tos -m "$EMAIL" \
--redirect || die "证书签发失败(多为 Cloudflare 代理导致 HTTP-01 验证不通),按开头提示处理后重跑本脚本"
systemctl reload nginx
log "完成"
echo " 访问: https://$DOMAIN/ (自动跳到 /live.html"
echo " 服务: systemctl status drinking-games | journalctl -u drinking-games -f"
echo " 证书自动续期由 certbot.timer 负责,可用 'certbot renew --dry-run' 验证。"