Files

217 lines
8.0 KiB
Bash
Raw Permalink Normal View History

2026-08-04 14:02:45 +08:00
#!/usr/bin/env bash
# get-cookie.sh — Holy Crab AI 认证流程
#
# 流程:
# 1. 从后端获取钉钉授权 URL
# 2. 让用户在浏览器打开,授权后 URL 里会带 authCode
# 3. AI 把 authCode 贴过来 → 调用 /api/v1/auth/direct-token 换出 session token
# 4. 存 token 到 ~/.holy_crab_env后续所有请求自动带 Cookie
#
# 用法:
# bash get-cookie.sh # 交互式
# bash get-cookie.sh --check # 仅检查 token 是否有效
# bash get-cookie.sh <authCode> # 直接用 authCode 换 token
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
COOKIE_FILE="$HOME/.holy_crab_cookie"
ENV_FILE="$HOME/.holy_crab_env"
BACKEND="${HC_BACKEND_URL:-http://localhost:8000}"
# ---------------------------------------------------------------------------
# 工具函数
# ---------------------------------------------------------------------------
save_token() {
local token="$1"
echo "HC_SESSION=${token}" > "$ENV_FILE"
chmod 600 "$ENV_FILE"
echo "✅ Token 已写入: $ENV_FILE"
echo ""
echo "📋 后续 AI 将自动从此文件读取 Cookie无需任何额外操作。"
}
save_token_raw() {
local token="$1"
echo "$token" > "$COOKIE_FILE"
chmod 600 "$COOKIE_FILE"
}
check_token() {
local token="$1"
local http_code
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
--max-time 10 \
-H "Cookie: hc_session=${token}" \
"$BACKEND/api/v1/auth/me")
if [ "$http_code" = "200" ]; then
echo "✅ Token 有效"
return 0
else
echo "❌ Token 无效或已过期 (HTTP $http_code)"
return 1
fi
}
# 从现有文件读 token
load_existing_token() {
# 优先 ~/.holy_crab_env
if [ -f "$ENV_FILE" ]; then
local val
val=$(grep -E "^HC_SESSION=" "$ENV_FILE" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'" | xargs)
[ -n "$val" ] && echo "$val" && return 0
fi
# 兜底 ~/.holy_crab_cookie
if [ -f "$COOKIE_FILE" ]; then
local val
val=$(cat "$COOKIE_FILE" | xargs)
[ -n "$val" ] && echo "$val" && return 0
fi
return 1
}
# ---------------------------------------------------------------------------
# Step 1检查现有 token
# ---------------------------------------------------------------------------
if [ "$1" = "--check" ]; then
echo ""
echo "🔍 检查现有 Token..."
if EXISTING=$(load_existing_token 2>/dev/null); then
if check_token "$EXISTING"; then
echo ""
echo " Token 来自: ${ENV_FILE:-$COOKIE_FILE}"
exit 0
fi
fi
echo " 未找到有效 Token需要重新授权。"
exit 1
fi
# ---------------------------------------------------------------------------
# Step 2直接用 authCode 换 token
# ---------------------------------------------------------------------------
if [ -n "$1" ] && [ "$1" != "--check" ]; then
AUTH_CODE="$1"
echo ""
echo "🔄 正在用 authCode 换取 session token..."
RESPONSE=$(curl -s --max-time 20 \
"$BACKEND/api/v1/auth/direct-token?authCode=${AUTH_CODE}")
ERROR=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('code',''))" 2>/dev/null)
if [ -n "$ERROR" ]; then
MSG=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('msg',''))" 2>/dev/null)
echo "❌ 换取失败: [$ERROR] $MSG"
echo " 原始响应: $RESPONSE"
exit 1
fi
TOKEN=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['token'])" 2>/dev/null)
USER=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['user'].get('name','?'))" 2>/dev/null)
EXPIRES=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['expires_at'])" 2>/dev/null)
if [ -z "$TOKEN" ]; then
echo "❌ 响应解析失败,原始响应:"
echo "$RESPONSE"
exit 1
fi
echo "✅ 换取成功!"
echo " 用户:$USER"
echo " 有效期至:$EXPIRES"
save_token "$TOKEN"
echo ""
echo "🎉 认证完成AI 现在可以访问 Holy Crab 后端了!"
exit 0
fi
# ---------------------------------------------------------------------------
# Step 3交互式引导 — 获取 authCode
# ---------------------------------------------------------------------------
echo ""
echo "═══════════════════════════════════════════════════════"
echo " 🔐 Holy Crab · AI 授权流程"
echo "═══════════════════════════════════════════════════════"
echo ""
echo " 本流程分两步:① 获取授权码 ② 换取 Token"
echo ""
# 检查后端是否可达
if ! curl -s --max-time 5 "$BACKEND/health" > /dev/null 2>&1; then
echo " ❌ 后端不可达: $BACKEND"
echo ""
echo " 请确认:"
echo " 1. 后端是否已启动python3 app.py"
echo " 2. HC_BACKEND_URL 是否正确?"
echo ""
echo " 当前 BACKEND=$BACKEND"
echo " 修改方式export HC_BACKEND_URL=http://服务器IP:8000"
exit 1
fi
echo " ✅ 后端在线: $BACKEND"
# 检查现有 token
if EXISTING=$(load_existing_token 2>/dev/null); then
if check_token "$EXISTING"; then
echo ""
echo " ✅ 已有有效 Token无需重新授权。"
echo " Token 来源: ${ENV_FILE:-$COOKIE_FILE}"
exit 0
else
echo " ⚠️ 已有 Token 但已过期,需要重新授权..."
fi
fi
echo ""
echo "───────────────────────────────────────────────────────"
echo " Step 1在浏览器中完成钉钉授权"
echo "───────────────────────────────────────────────────────"
echo ""
# 获取钉钉授权 URL
AUTH_URL_RESP=$(curl -s --max-time 10 "$BACKEND/api/v1/auth/dingtalk/login?redirect=/")
AUTH_URL=$(echo "$AUTH_URL_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['url'])" 2>/dev/null)
if [ -z "$AUTH_URL" ]; then
echo " ❌ 无法获取钉钉授权 URL后端可能未配置 DINGTALK_CLIENT_ID"
echo " 原始响应: $AUTH_URL_RESP"
exit 1
fi
echo " 请在浏览器中打开以下链接:"
echo ""
echo " $AUTH_URL"
echo ""
echo " 操作步骤:"
echo " 1. 浏览器会自动打开钉钉授权页面"
echo " 2. 点击「授权登录」"
echo " 3. 授权成功后,浏览器会跳转到后端页面"
echo " 4. 此时地址栏 URL 中会有 ?authCode=xxxxx"
echo " 把 authCode= 后面的那串字符复制下来"
echo ""
# 自动打开浏览器
if command -v open >/dev/null 2>&1; then
echo " 正在打开授权页面..."
open "$AUTH_URL" 2>/dev/null || true
fi
echo ""
echo "───────────────────────────────────────────────────────"
echo " Step 2把 authCode 贴过来"
echo "───────────────────────────────────────────────────────"
echo ""
echo " 复制 authCode 后,运行以下命令(把 YOUR_AUTH_CODE 换成你的值):"
echo ""
echo " bash $0 YOUR_AUTH_CODE"
echo ""
echo " 或者直接告诉 AI"
echo " 【authCode】YOUR_AUTH_CODE"
echo " AI 会自动帮你完成后续操作。"
echo ""
echo "═══════════════════════════════════════════════════════"