Include local config, CPA auth files, account dumps, and temp-mail deploy helpers for the private Gitea repo.
131 lines
3.8 KiB
Bash
131 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
REPO="${REPO:-$HOME/projects/cloudflare_temp_email}"
|
|
WORKER_DIR="$REPO/worker"
|
|
|
|
# shellcheck disable=SC1091
|
|
source "$ROOT/secrets.env"
|
|
|
|
DOMAIN="${DOMAIN:-zhangyunuo.net}"
|
|
WORKER_NAME="${WORKER_NAME:-temp-email-zhangyunuo}"
|
|
D1_NAME="${D1_NAME:-temp-email-zhangyunuo}"
|
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:?ADMIN_PASSWORD missing in secrets.env}"
|
|
JWT_SECRET="${JWT_SECRET:?JWT_SECRET missing in secrets.env}"
|
|
|
|
cd "$WORKER_DIR"
|
|
export PATH="$WORKER_DIR/node_modules/.bin:$PATH"
|
|
|
|
if ! command -v wrangler >/dev/null 2>&1; then
|
|
echo "[!] wrangler 不在 PATH,尝试 pnpm exec"
|
|
WR="pnpm exec wrangler"
|
|
else
|
|
WR="wrangler"
|
|
fi
|
|
|
|
if [ -z "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
|
# no token: require interactive oauth session
|
|
if ! $WR whoami 2>/dev/null | grep -qiE 'Account Name|Account ID|email:'; then
|
|
echo "[!] 未登录 Cloudflare,且未设置 CLOUDFLARE_API_TOKEN"
|
|
echo " 方式 A(交互): cd $WORKER_DIR && pnpm exec wrangler login"
|
|
echo " 方式 B(推荐服务器): export CLOUDFLARE_API_TOKEN=你的token"
|
|
echo " Token 创建: https://dash.cloudflare.com/profile/api-tokens"
|
|
echo " 权限至少: Account.D1 Edit + Account.Workers Scripts Edit + Account.Workers KV Storage Edit(可选)"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "[*] 使用 CLOUDFLARE_API_TOKEN 部署"
|
|
fi
|
|
|
|
echo "[*] 创建/查找 D1: $D1_NAME"
|
|
CREATE_OUT=$($WR d1 create "$D1_NAME" 2>&1 || true)
|
|
echo "$CREATE_OUT"
|
|
|
|
DB_ID=""
|
|
if echo "$CREATE_OUT" | grep -q "database_id"; then
|
|
DB_ID=$(echo "$CREATE_OUT" | sed -n 's/.*database_id *= *"\([^"]*\)".*/\1/p' | head -1)
|
|
if [ -z "$DB_ID" ]; then
|
|
DB_ID=$(echo "$CREATE_OUT" | sed -n 's/.*database_id = \([a-f0-9-]*\).*/\1/p' | head -1)
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$DB_ID" ]; then
|
|
DB_ID=$($WR d1 list --json 2>/dev/null | python3 -c '
|
|
import sys, json
|
|
name = sys.argv[1]
|
|
data = json.load(sys.stdin)
|
|
items = data if isinstance(data, list) else data.get("result", data.get("databases", []))
|
|
print(next((str(x.get("uuid") or x.get("id") or "") for x in items if x.get("name") == name), ""), end="")
|
|
' "$D1_NAME" || true)
|
|
fi
|
|
|
|
if [ -z "$DB_ID" ]; then
|
|
echo "[!] 无法解析 database_id,请检查 wrangler 登录权限后重试"
|
|
exit 1
|
|
fi
|
|
echo "[+] D1 id=$DB_ID"
|
|
|
|
python3 - "$DOMAIN" "$WORKER_NAME" "$D1_NAME" "$DB_ID" "$ADMIN_PASSWORD" "$JWT_SECRET" <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
domain, name, db_name, db_id, admin, jwt = sys.argv[1:7]
|
|
text = f'''name = "{name}"
|
|
main = "src/worker.ts"
|
|
compatibility_date = "2025-04-01"
|
|
compatibility_flags = [ "nodejs_compat" ]
|
|
keep_vars = true
|
|
|
|
[vars]
|
|
PREFIX = ""
|
|
ADMIN_PASSWORDS = ["{admin}"]
|
|
DEFAULT_DOMAINS = ["{domain}"]
|
|
DOMAINS = ["{domain}"]
|
|
JWT_SECRET = "{jwt}"
|
|
BLACK_LIST = ""
|
|
ENABLE_USER_CREATE_EMAIL = true
|
|
ENABLE_USER_DELETE_EMAIL = true
|
|
ENABLE_AUTO_REPLY = false
|
|
DEFAULT_LANG = "zh"
|
|
TITLE = "Temp Mail"
|
|
|
|
[[d1_databases]]
|
|
binding = "DB"
|
|
database_name = "{db_name}"
|
|
database_id = "{db_id}"
|
|
'''
|
|
Path("wrangler.toml").write_text(text, encoding="utf-8")
|
|
print("wrote wrangler.toml")
|
|
PY
|
|
|
|
echo "[*] 初始化 schema"
|
|
$WR d1 execute "$D1_NAME" --remote --file=../db/schema.sql
|
|
|
|
echo "[*] 执行 patches"
|
|
for f in ../db/*.sql; do
|
|
base=$(basename "$f")
|
|
[ "$base" = "schema.sql" ] && continue
|
|
echo " -> $base"
|
|
$WR d1 execute "$D1_NAME" --remote --file="$f" || true
|
|
done
|
|
|
|
echo "[*] 部署 Worker"
|
|
$WR deploy --minify
|
|
|
|
echo
|
|
echo "[+] 完成 Worker: $WORKER_NAME"
|
|
echo "[+] Admin 密码见 $ROOT/secrets.env"
|
|
echo "[+] 下一步: Cloudflare Email Routing catch-all -> $WORKER_NAME"
|
|
echo "[+] 注册机配置示例:"
|
|
cat <<CFG
|
|
{
|
|
"email_provider": "cloudflare",
|
|
"cloudflare_api_base": "https://${WORKER_NAME}.<subdomain>.workers.dev",
|
|
"cloudflare_api_key": "${ADMIN_PASSWORD}",
|
|
"cloudflare_auth_mode": "x-admin-auth",
|
|
"cloudflare_path_accounts": "/admin/new_address",
|
|
"cloudflare_path_messages": "/api/mails",
|
|
"defaultDomains": "${DOMAIN}"
|
|
}
|
|
CFG
|