上传文件至「/」

This commit is contained in:
2026-05-14 21:05:10 +00:00
commit f8ed063b76
5 changed files with 4333 additions and 0 deletions
+404
View File
@@ -0,0 +1,404 @@
#!/bin/bash
# ══════════════════════════════════════════════════════════
# CiBird 词鸟 安装脚本
# 一键部署你的私人英语单词本
# 项目地址:https://github.com/zhangyang-games/cibird
# ══════════════════════════════════════════════════════════
set -e
# ── 颜色 ──────────────────────────────────────────────────
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'
REPO_RAW="https://raw.githubusercontent.com/zhangyang-games/cibird/main"
INSTALL_DIR="$HOME/cibird"
# ── Banner ────────────────────────────────────────────────
print_banner() {
clear
echo ""
echo -e "${BOLD}${CYAN}"
echo " ██████╗██╗██████╗ ██╗██████╗ ██████╗"
echo " ██╔════╝██║██╔══██╗██║██╔══██╗██╔══██╗"
echo " ██║ ██║██████╔╝██║██████╔╝██║ ██║"
echo " ██║ ██║██╔══██╗██║██╔══██╗██║ ██║"
echo " ╚██████╗██║██████╔╝██║██║ ██║██████╔╝"
echo " ╚═════╝╚═╝╚═════╝ ╚═╝╚═╝ ╚═╝╚═════╝"
echo -e "${NC}"
echo -e "${BOLD} ┌─────────────────────────────────────────────┐${NC}"
echo -e "${BOLD} │ 🦜 CiBird 词鸟 · 你的私人英语单词本 │${NC}"
echo -e "${DIM} │ AI造句 · 发音 · 推特/游戏英语场景 │${NC}"
echo -e "${BOLD} └─────────────────────────────────────────────┘${NC}"
echo ""
}
# ── 步骤提示 ──────────────────────────────────────────────
step() { echo -e "\n${BOLD}${CYAN}[$1]${NC} $2"; }
ok() { echo -e " ${GREEN}${NC} $1"; }
err() { echo -e " ${RED}✗ 错误:${NC}$1"; exit 1; }
info() { echo -e " ${DIM}$1${NC}"; }
ask() { echo -e " ${YELLOW}${NC} $1"; }
# ── 0. 检查基础依赖 ────────────────────────────────────────
check_deps() {
step "0/6" "检查系统环境"
for cmd in curl python3; do
if ! command -v $cmd &>/dev/null; then
info "正在安装 $cmd ..."
if command -v apt-get &>/dev/null; then
apt-get update -qq && apt-get install -y $cmd -qq
elif command -v apk &>/dev/null; then
apk add --no-cache $cmd
elif command -v yum &>/dev/null; then
yum install -y $cmd
else
err "请手动安装 $cmd 后重试"
fi
fi
ok "$cmd 已就绪"
done
}
# ── 1. 安装 Python 依赖 ────────────────────────────────────
install_python_deps() {
step "1/6" "安装 Python 依赖包"
info "需要安装:fastapi uvicorn httpx"
# 判断是否需要 --break-system-packagesUbuntu 22+
BREAK_SYS=""
if python3 -c "import sys; exit(0 if sys.version_info>=(3,11) else 1)" 2>/dev/null; then
BREAK_SYS="--break-system-packages"
fi
# 另一种判断:pip 报 externally-managed
if pip3 install --help 2>&1 | grep -q 'break-system'; then
BREAK_SYS="--break-system-packages"
fi
python3 -m pip install --quiet fastapi uvicorn[standard] httpx $BREAK_SYS 2>/dev/null \
|| pip3 install --quiet fastapi uvicorn[standard] httpx $BREAK_SYS 2>/dev/null \
|| err "pip 安装失败,请手动执行:pip3 install fastapi uvicorn httpx"
ok "Python 依赖安装完成"
}
# ── 2. 下载项目文件 ────────────────────────────────────────
download_files() {
step "2/6" "下载 CiBird 项目文件"
mkdir -p "$INSTALL_DIR"
for f in server.py index.html; do
info "下载 $f ..."
curl -fsSL "$REPO_RAW/$f" -o "$INSTALL_DIR/$f" \
|| err "下载 $f 失败,请检查网络或 GitHub 地址"
ok "$f 已下载"
done
}
# ── 3. 选择 AI 服务商 ──────────────────────────────────────
choose_provider() {
step "3/6" "选择 AI 服务商"
echo ""
echo -e " ${BOLD}请选择你要使用的 AI 服务商:${NC}"
echo ""
echo -e " ${GREEN}1)${NC} Google Gemini ${DIM}← 免费额度大,推荐新手${NC}"
echo -e " ${GREEN}2)${NC} DeepSeek ${DIM}← 国产之光,便宜效果好${NC}"
echo -e " ${GREEN}3)${NC} Groq ${DIM}← 速度极快,免费${NC}"
echo -e " ${GREEN}4)${NC} OpenRouter ${DIM}← 一个Key用几十种模型${NC}"
echo -e " ${GREEN}5)${NC} Claude ${DIM}← Anthropic,你有付费Key${NC}"
echo -e " ${GREEN}6)${NC} OpenAI ${DIM}← ChatGPT 同款${NC}"
echo ""
read -p " 👉 输入编号 [1-6]" PROVIDER_CHOICE
case "$PROVIDER_CHOICE" in
1)
PROVIDER="gemini"
MODEL="gemini-2.0-flash"
info "获取 Keyhttps://aistudio.google.com/apikey"
;;
2)
PROVIDER="deepseek"
MODEL="deepseek-chat"
info "获取 Keyhttps://platform.deepseek.com"
;;
3)
PROVIDER="groq"
MODEL="llama-3.1-8b-instant"
info "获取 Keyhttps://console.groq.com"
;;
4)
PROVIDER="openrouter"
MODEL="google/gemini-flash-1.5"
info "获取 Keyhttps://openrouter.ai"
;;
5)
PROVIDER="claude"
MODEL="claude-haiku-4-5-20251001"
info "获取 Keyhttps://console.anthropic.com"
;;
6)
PROVIDER="openai"
MODEL="gpt-4o-mini"
info "获取 Keyhttps://platform.openai.com"
;;
*)
err "无效选择,请输入 1-6"
;;
esac
ok "已选择:$PROVIDER(模型:$MODEL"
echo ""
read -p " 👉 请粘贴你的 API Key" API_KEY
[ -z "$API_KEY" ] && err "API Key 不能为空"
ok "API Key 已录入"
echo ""
echo -e " ${DIM}💡 如果你想用其他模型,可以直接改默认值,也可以回车使用默认${NC}"
read -p " 👉 模型名称(默认 $MODEL,直接回车跳过):" MODEL_INPUT
[ -n "$MODEL_INPUT" ] && MODEL="$MODEL_INPUT"
ok "模型:$MODEL"
}
# ── 4. 设置访问密码 ────────────────────────────────────────
setup_auth() {
step "4/6" "设置登录账号"
echo ""
read -p " 👉 用户名(默认 admin,回车跳过):" USERNAME
[ -z "$USERNAME" ] && USERNAME="admin"
ok "用户名:$USERNAME"
echo ""
while true; do
read -s -p " 👉 设置登录密码(至少6位):" PASSWORD
echo ""
[ ${#PASSWORD} -ge 6 ] && break
echo -e " ${RED}密码太短,请至少6位!${NC}"
done
read -s -p " 👉 再次确认密码:" PASSWORD2
echo ""
[ "$PASSWORD" != "$PASSWORD2" ] && err "两次密码不一致"
ok "密码已设置"
echo ""
read -p " 👉 访问端口(默认 8848,回车跳过):" PORT
[ -z "$PORT" ] && PORT="8848"
ok "端口:$PORT"
# 生成密码 hash
PASSWORD_HASH=$(python3 -c "import hashlib; print(hashlib.sha256('$PASSWORD'.encode()).hexdigest())")
}
# ── 5. 写入配置 ────────────────────────────────────────────
write_config() {
step "5/6" "写入配置文件"
cat > "$INSTALL_DIR/config.json" <<EOF
{
"username": "$USERNAME",
"password_hash": "$PASSWORD_HASH",
"port": $PORT,
"provider": "$PROVIDER",
"api_key": "$API_KEY",
"model": "$MODEL"
}
EOF
chmod 600 "$INSTALL_DIR/config.json"
ok "config.json 已写入(权限已设为仅自己可读)"
}
# ── 6. 启动服务 ────────────────────────────────────────────
start_service() {
step "6/6" "启动 CiBird 服务"
# 停掉旧进程
if [ -f "$INSTALL_DIR/cibird.pid" ]; then
OLD_PID=$(cat "$INSTALL_DIR/cibird.pid")
kill "$OLD_PID" 2>/dev/null && info "已停止旧进程 (PID $OLD_PID)" || true
rm -f "$INSTALL_DIR/cibird.pid"
fi
# 也搜一下
pkill -f "server.py" 2>/dev/null || true
sleep 1
# 初始化数据库
cd "$INSTALL_DIR"
python3 -c "
import sys; sys.path.insert(0,'.')
from server import init_db
init_db()
print(' DB 初始化完成')
"
# 后台启动
nohup python3 "$INSTALL_DIR/server.py" >> "$INSTALL_DIR/cibird.log" 2>&1 &
echo $! > "$INSTALL_DIR/cibird.pid"
sleep 2
# 验证是否启动成功
if kill -0 $(cat "$INSTALL_DIR/cibird.pid") 2>/dev/null; then
ok "服务启动成功!(PID $(cat $INSTALL_DIR/cibird.pid))"
else
err "服务启动失败,查看日志:cat $INSTALL_DIR/cibird.log"
fi
}
# ── 写入快捷命令 ───────────────────────────────────────────
write_shortcut() {
SHORTCUT="/usr/local/bin/cibird"
cat > "$SHORTCUT" <<'SCRIPT'
#!/bin/bash
INSTALL_DIR="$HOME/cibird"
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
get_pid() { [ -f "$INSTALL_DIR/cibird.pid" ] && cat "$INSTALL_DIR/cibird.pid" || echo ""; }
is_running() { PID=$(get_pid); [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; }
get_port() { python3 -c "import json; print(json.load(open('$INSTALL_DIR/config.json'))['port'])" 2>/dev/null || echo "8848"; }
case "$1" in
start)
if is_running; then
echo -e " ${YELLOW}词鸟已经在运行中${NC}"
else
cd "$INSTALL_DIR"
nohup python3 server.py >> cibird.log 2>&1 &
echo $! > cibird.pid
sleep 1
echo -e " ${GREEN}✓ 词鸟已启动${NC} 访问 http://$(curl -s ifconfig.me 2>/dev/null || echo '你的IP'):$(get_port)"
fi
;;
stop)
PID=$(get_pid)
[ -n "$PID" ] && kill "$PID" 2>/dev/null && echo -e " ${GREEN}✓ 词鸟已停止${NC}" || echo -e " ${DIM}没有运行中的词鸟${NC}"
rm -f "$INSTALL_DIR/cibird.pid"
;;
restart)
$0 stop; sleep 1; $0 start
;;
log)
tail -f "$INSTALL_DIR/cibird.log"
;;
status)
PORT=$(get_port)
if is_running; then
echo -e " ${GREEN}● 词鸟运行中${NC} PID $(get_pid)"
echo -e " ${DIM}访问地址:http://$(curl -s ifconfig.me 2>/dev/null || echo '你的IP'):$PORT${NC}"
else
echo -e " ${RED}○ 词鸟未运行${NC}"
fi
;;
*)
echo ""
echo -e " ${BOLD}🦜 CiBird 词鸟 管理命令${NC}"
echo ""
PORT=$(get_port)
if is_running; then
echo -e " ${GREEN}● 状态:运行中${NC} PID $(get_pid)"
else
echo -e " ${RED}○ 状态:未运行${NC}"
fi
echo -e " ${DIM}访问地址:http://你的IP:$PORT${NC}"
echo ""
echo -e " ${CYAN}cibird start${NC} 启动"
echo -e " ${CYAN}cibird stop${NC} 停止"
echo -e " ${CYAN}cibird restart${NC} 重启"
echo -e " ${CYAN}cibird status${NC} 查看状态"
echo -e " ${CYAN}cibird log${NC} 查看日志"
echo ""
;;
esac
SCRIPT
chmod +x "$SHORTCUT" 2>/dev/null || true
ok "快捷命令 cibird 已安装(可用 cibird start/stop/status"
}
# ── 获取公网 IP ────────────────────────────────────────────
get_public_ip() {
PUBLIC_IP=$(curl -s --connect-timeout 5 ifconfig.me 2>/dev/null \
|| curl -s --connect-timeout 5 api.ipify.org 2>/dev/null \
|| echo "你的VPS公网IP")
}
# ── 导入单词 ───────────────────────────────────────────────
import_words() {
echo ""
echo -e " ${BOLD}📖 导入多邻国单词本${NC}"
echo -e " ${DIM}从 GitHub 拉取 words.txt 导入到词库${NC}"
echo ""
WORDS_URL="https://raw.githubusercontent.com/zhangyang-games/cibird/main/words.txt"
curl -sL "$WORDS_URL" | python3 -c "
import sys,sqlite3,pathlib
DB=pathlib.Path.home()/'cibird/cibird.db'
if not DB.exists(): print(' 找不到数据库'); exit(1)
words=[l.strip().split('|',1) for l in sys.stdin if '|' in l]
conn=sqlite3.connect(DB)
existing=set(r[0].lower() for r in conn.execute('SELECT word FROM words'))
added=skipped=0
for w in words:
if len(w)!=2: continue
word,meaning=w
if word.lower() in existing: skipped+=1; continue
conn.execute('INSERT INTO words(word,meaning,phonetic,pos,examples,note) VALUES(?,?,?,?,?,?)',(word,meaning,'','','[]',''))
existing.add(word.lower()); added+=1
conn.commit(); conn.close()
print(f' ✓ 导入完成!新增 {added} 个,跳过 {skipped} 个')
" || echo -e " ${RED}✗ 导入失败,请检查网络${NC}"
}
# ═══════════════════════════════════════════════════════════
# MAIN
# ═══════════════════════════════════════════════════════════
print_banner
echo -e " 欢迎!这个脚本会帮你在 VPS 上部署 CiBird 词鸟。"
echo -e " ${DIM}整个过程大约需要 2-3 分钟,请跟着提示一步步来。${NC}"
echo ""
read -p " 按回车键开始安装,Ctrl+C 取消..." _
check_deps
install_python_deps
download_files
choose_provider
setup_auth
write_config
start_service
write_shortcut
get_public_ip
# ── 可选:导入单词 ─────────────────────────────────────────
echo ""
read -p " 👉 是否导入你的多邻国单词本?(输入 y 导入,回车跳过):" IMPORT_CHOICE
if [ "$IMPORT_CHOICE" = "y" ] || [ "$IMPORT_CHOICE" = "Y" ]; then
import_words
fi
# ── 完成提示 ──────────────────────────────────────────────
echo ""
echo -e "${BOLD}${GREEN}"
echo " ┌──────────────────────────────────────────────┐"
echo " │ 🎉 CiBird 词鸟安装完成! │"
echo " └──────────────────────────────────────────────┘"
echo -e "${NC}"
echo -e " ${BOLD}🌐 访问地址:${CYAN}http://$PUBLIC_IP:$PORT${NC}"
echo -e " ${BOLD}👤 用户名:${NC}$USERNAME"
echo -e " ${BOLD}🔑 密码:${NC}你刚才设置的密码"
echo ""
echo -e " ${DIM}💡 管理命令:${NC}"
echo -e " ${DIM} cibird 查看状态${NC}"
echo -e " ${DIM} cibird stop 停止服务${NC}"
echo -e " ${DIM} cibird start 启动服务${NC}"
echo -e " ${DIM} cibird log 查看日志(排查问题用)${NC}"
echo ""
echo -e " ${DIM}⚠️ 如果访问不了,请确认防火墙已开放 $PORT 端口${NC}"
echo -e " ${DIM} Oracle Cloud 需要在安全列表里手动添加规则${NC}"
echo ""
echo -e " ${BOLD}展翅高飞!🦜${NC}"
echo ""