#!/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 换 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 "═══════════════════════════════════════════════════════"