refactor: 整理脚本目录结构,兼容原仓库插件清理

- 脚本统一移入 scripts/ 目录(pull-latest.sh, upgrade-and-run.sh, set-markdown.sh)
- 删除不可用的 npm 版 scripts/pull-latest.sh,保留 git 版
- upgrade.sh / qqbot-cli.js 清理逻辑兼容原仓库 @sliverp/qqbot 和本仓库多种插件 ID
- 扩展目录查找兼容 extensions/qqbot 和 extensions/openclaw-qq
- 新增 moltbot 支持
- LICENSE 添加原作者 sliverp 版权声明
- 更新 README/docs 中脚本路径引用
- package.json files 字段增加 scripts 目录
This commit is contained in:
rianli
2026-03-09 20:12:24 +08:00
parent efed32cf34
commit 11b230a989
11 changed files with 358 additions and 659 deletions

View File

@@ -1,5 +1,6 @@
MIT License
Copyright (c) 2026 sliverp
Copyright (c) 2026 Tencent Connect
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -358,14 +358,14 @@ STT supports two-level configuration with priority fallback:
### Via upgrade-and-run.sh (One-Click)
```bash
bash ./upgrade-and-run.sh
bash ./scripts/upgrade-and-run.sh
```
When no `--appid` / `--secret` is provided, the script reads existing config from `~/.openclaw/openclaw.json` automatically.
```bash
# First-time or override credentials
bash ./upgrade-and-run.sh --appid YOUR_APPID --secret YOUR_SECRET
bash ./scripts/upgrade-and-run.sh --appid YOUR_APPID --secret YOUR_SECRET
```
<details>
@@ -385,16 +385,16 @@ Environment variables `QQBOT_APPID`, `QQBOT_SECRET`, `QQBOT_TOKEN` (AppID:Secret
### Via pull-latest.sh (Git Source)
```bash
bash ./pull-latest.sh
bash ./scripts/pull-latest.sh
```
<details>
<summary>Options</summary>
```bash
bash ./pull-latest.sh --branch main # specify branch (default: main)
bash ./pull-latest.sh --force # skip prompts, force update
bash ./pull-latest.sh --repo <git-url> # use a different repo
bash ./scripts/pull-latest.sh --branch main # specify branch (default: main)
bash ./scripts/pull-latest.sh --force # skip prompts, force update
bash ./scripts/pull-latest.sh --repo <git-url> # use a different repo
```
</details>

View File

@@ -354,14 +354,14 @@ STT 支持两级配置,按优先级查找:
### 通过 upgrade-and-run.sh 一键升级
```bash
bash ./upgrade-and-run.sh
bash ./scripts/upgrade-and-run.sh
```
不传 `--appid` / `--secret` 参数时,脚本会自动读取 `~/.openclaw/openclaw.json` 中已有的配置。
```bash
# 首次配置或需要覆盖时
bash ./upgrade-and-run.sh --appid YOUR_APPID --secret YOUR_SECRET
bash ./scripts/upgrade-and-run.sh --appid YOUR_APPID --secret YOUR_SECRET
```
<details>
@@ -381,16 +381,16 @@ bash ./upgrade-and-run.sh --appid YOUR_APPID --secret YOUR_SECRET
### 通过 pull-latest.shGit 源码更新)
```bash
bash ./pull-latest.sh
bash ./scripts/pull-latest.sh
```
<details>
<summary>选项</summary>
```bash
bash ./pull-latest.sh --branch main # 指定分支(默认 main
bash ./pull-latest.sh --force # 跳过交互,强制更新
bash ./pull-latest.sh --repo <git-url> # 使用其他仓库地址
bash ./scripts/pull-latest.sh --branch main # 指定分支(默认 main
bash ./scripts/pull-latest.sh --force # 跳过交互,强制更新
bash ./scripts/pull-latest.sh --repo <git-url> # 使用其他仓库地址
```
</details>

View File

@@ -35,18 +35,22 @@ function detectInstallation() {
return null;
}
// 需要清理的所有可能的插件 ID / 包名(原仓库 + 本仓库 + 框架推断名)
const PLUGIN_IDS = ['qqbot', 'openclaw-qq', '@sliverp/qqbot', '@tencent-connect/openclaw-qq'];
// 可能的扩展目录名
const EXTENSION_DIR_NAMES = ['qqbot', 'openclaw-qq'];
// 清理旧版本插件,返回旧的 qqbot 配置
function cleanupInstallation(appName) {
const home = homedir();
const appDir = join(home, `.${appName}`);
const configFile = join(appDir, `${appName}.json`);
const extensionDir = join(appDir, 'extensions', 'qqbot');
let oldQqbotConfig = null;
console.log(`\n>>> 处理 ${appName} 安装...`);
// 1. 先读取旧的 qqbot 配置
// 1. 先读取旧的 qqbot 配置(尝试所有可能的 channel key
if (existsSync(configFile)) {
try {
const config = JSON.parse(readFileSync(configFile, 'utf8'));
@@ -59,36 +63,39 @@ function cleanupInstallation(appName) {
}
}
// 2. 删除旧扩展目录
if (existsSync(extensionDir)) {
console.log(`删除旧版本插件: ${extensionDir}`);
rmSync(extensionDir, { recursive: true, force: true });
} else {
console.log('未找到旧版本插件目录,跳过删除');
// 2. 删除所有可能的旧扩展目录
for (const dirName of EXTENSION_DIR_NAMES) {
const extensionDir = join(appDir, 'extensions', dirName);
if (existsSync(extensionDir)) {
console.log(`删除旧版本插件: ${extensionDir}`);
rmSync(extensionDir, { recursive: true, force: true });
}
}
// 3. 清理配置文件中的 qqbot 相关字段
// 3. 清理配置文件中所有可能的插件 ID 相关字段
if (existsSync(configFile)) {
console.log('清理配置文件中的 qqbot 字段...');
console.log('清理配置文件中的插件字段...');
try {
const config = JSON.parse(readFileSync(configFile, 'utf8'));
// 删除 channels.qqbot
if (config.channels?.qqbot) {
delete config.channels.qqbot;
console.log(' - 已删除 channels.qqbot');
}
for (const id of PLUGIN_IDS) {
// 删除 channels.<id>
if (config.channels?.[id]) {
delete config.channels[id];
console.log(` - 已删除 channels.${id}`);
}
// 删除 plugins.entries.qqbot
if (config.plugins?.entries?.qqbot) {
delete config.plugins.entries.qqbot;
console.log(' - 已删除 plugins.entries.qqbot');
}
// 删除 plugins.entries.<id>
if (config.plugins?.entries?.[id]) {
delete config.plugins.entries[id];
console.log(` - 已删除 plugins.entries.${id}`);
}
// 删除 plugins.installs.qqbot
if (config.plugins?.installs?.qqbot) {
delete config.plugins.installs.qqbot;
console.log(' - 已删除 plugins.installs.qqbot');
// 删除 plugins.installs.<id>
if (config.plugins?.installs?.[id]) {
delete config.plugins.installs[id];
console.log(` - 已删除 plugins.installs.${id}`);
}
}
writeFileSync(configFile, JSON.stringify(config, null, 2));

View File

@@ -138,16 +138,16 @@ openclaw config
### 一键升级并启动
```bash
# 基本用法
./upgrade-and-run.sh
./scripts/upgrade-and-run.sh
# 指定 AppID 和 Secret
./upgrade-and-run.sh --appid 123456789 --secret your_secret
./scripts/upgrade-and-run.sh --appid 123456789 --secret your_secret
# 同时启用 Markdown
./upgrade-and-run.sh --appid 123456789 --secret your_secret --markdown yes
./scripts/upgrade-and-run.sh --appid 123456789 --secret your_secret --markdown yes
# 查看帮助
./upgrade-and-run.sh --help
./scripts/upgrade-and-run.sh --help
```
**环境变量方式:**
@@ -155,22 +155,22 @@ openclaw config
export QQBOT_APPID="123456789"
export QQBOT_SECRET="your_secret"
export QQBOT_MARKDOWN="no"
./upgrade-and-run.sh
./scripts/upgrade-and-run.sh
```
### Markdown 设置脚本
```bash
# 启用 Markdown
./set-markdown.sh enable
./scripts/set-markdown.sh enable
# 禁用 Markdown
./set-markdown.sh disable
./scripts/set-markdown.sh disable
# 查看当前状态
./set-markdown.sh status
./scripts/set-markdown.sh status
# 交互式选择
./set-markdown.sh
./scripts/set-markdown.sh
```
### 升级脚本(清理旧版本)

View File

@@ -12,6 +12,7 @@
"bin",
"src",
"skills",
"scripts",
"index.ts",
"tsconfig.json",
"openclaw.plugin.json",

View File

@@ -1,310 +0,0 @@
#!/bin/bash
# QQBot 拉取最新源码并更新
# 从 GitHub 拉取最新代码,安装依赖并重启网关
# 兼容 clawdbot / openclaw / moltbotmacOS 开箱即用
#
# 用法:
# pull-latest.sh # 拉取最新代码并更新
# pull-latest.sh --branch main # 指定分支(默认 main
# pull-latest.sh --force # 跳过交互,强制更新
# pull-latest.sh --repo <git-url> # 指定仓库地址
set -euo pipefail
##############################################################################
# 常量 & 参数
##############################################################################
readonly DEFAULT_REPO="https://github.com/tencent-connect/openclaw-qq.git"
readonly GATEWAY_PORT=18789
readonly SUPPORTED_CLIS=(openclaw clawdbot moltbot)
FORCE=false
BRANCH="main"
REPO_URL=""
while [[ $# -gt 0 ]]; do
case "$1" in
-f|--force) FORCE=true; shift ;;
-b|--branch) BRANCH="$2"; shift 2 ;;
--repo) REPO_URL="$2"; shift 2 ;;
-h|--help)
echo "QQBot 拉取最新源码并更新"
echo ""
echo "用法:"
echo " pull-latest.sh # 拉取最新代码并更新"
echo " pull-latest.sh --branch main # 指定分支(默认 main"
echo " pull-latest.sh --force # 跳过交互,强制更新"
echo " pull-latest.sh --repo <git-url> # 指定仓库地址"
exit 0
;;
*)
echo "未知选项: $1 (使用 --help 查看帮助)"
exit 1
;;
esac
done
REPO_URL="${REPO_URL:-$DEFAULT_REPO}"
##############################################################################
# 工具函数
##############################################################################
json_get() {
local file="$1" expr="$2"
node -e "process.stdout.write(String((function(){$expr})(JSON.parse(require('fs').readFileSync('$file','utf8')))||''))" 2>/dev/null || true
}
##############################################################################
# 环境检查
##############################################################################
printf "%b\n" "\033[32m=========================================\033[0m"
printf "%b\n" "\033[32m QQBot 拉取最新源码并更新\033[0m"
printf "%b\n" "\033[32m=========================================\033[0m"
echo ""
# 检查必要命令
for dep in node npm git; do
if ! command -v "$dep" &>/dev/null; then
printf "%b\n" "\033[31m❌ 未检测到 $dep,请先安装\033[0m"
exit 1
fi
done
printf "%b\n" "\033[34m系统信息:\033[0m"
echo " macOS $(sw_vers -productVersion 2>/dev/null || echo '未知')"
echo " Node $(node -v)"
echo " npm $(npm -v)"
echo " Git $(git --version 2>/dev/null | awk '{print $3}')"
echo " 仓库 $REPO_URL"
echo " 分支 $BRANCH"
# 检测 CLI
CMD=""
for name in "${SUPPORTED_CLIS[@]}"; do
if command -v "$name" &>/dev/null; then
CMD="$name"
break
fi
done
if [ -z "$CMD" ]; then
printf "%b\n" "\033[31m❌ 未找到 openclaw / clawdbot / moltbot 命令,请先安装其中之一\033[0m"
exit 1
fi
echo " CLI $CMD ($($CMD --version 2>/dev/null || echo '未知版本'))"
APP_HOME="$HOME/.$CMD"
APP_CONFIG="$APP_HOME/$CMD.json"
##############################################################################
# 定位插件目录
##############################################################################
PROJ_DIR=""
FRESH_INSTALL=false
for app in "${SUPPORTED_CLIS[@]}"; do
ext_dir="$HOME/.$app/extensions/qqbot"
if [ -d "$ext_dir" ] && [ -f "$ext_dir/package.json" ]; then
PROJ_DIR="$ext_dir"
break
fi
done
if [ -z "$PROJ_DIR" ]; then
PROJ_DIR="$APP_HOME/extensions/qqbot"
FRESH_INSTALL=true
echo " 插件 未安装(首次安装)"
else
echo " 插件 $PROJ_DIR"
fi
##############################################################################
# 第一步:获取当前版本
##############################################################################
echo ""
printf "%b\n" "\033[34m1. 获取当前版本...\033[0m"
LOCAL_VER=""
LOCAL_COMMIT=""
if [ "$FRESH_INSTALL" = true ]; then
echo " 首次安装,无本地版本"
else
[ -f "$PROJ_DIR/package.json" ] && LOCAL_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
[ -d "$PROJ_DIR/.git" ] && LOCAL_COMMIT=$(cd "$PROJ_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "")
echo " 当前版本: ${LOCAL_VER:-未知}${LOCAL_COMMIT:+ (${LOCAL_COMMIT})}"
fi
##############################################################################
# 第二步:备份通道配置
##############################################################################
echo ""
printf "%b\n" "\033[34m2. 备份通道配置...\033[0m"
SAVED_CHANNELS_JSON=""
for app in "${SUPPORTED_CLIS[@]}"; do
cfg="$HOME/.$app/$app.json"
[ -f "$cfg" ] || continue
SAVED_CHANNELS_JSON=$(node -e "
const cfg = JSON.parse(require('fs').readFileSync('$cfg', 'utf8'));
const ch = cfg.channels && cfg.channels.qqbot;
if (ch) process.stdout.write(JSON.stringify(ch));
" 2>/dev/null || true)
[ -n "$SAVED_CHANNELS_JSON" ] && break
done
if [ -n "$SAVED_CHANNELS_JSON" ]; then
echo " ✅ 已备份 qqbot 通道配置"
else
echo " 未找到已有通道配置"
fi
##############################################################################
# 第三步:拉取最新代码
##############################################################################
echo ""
printf "%b\n" "\033[34m3. 拉取最新代码...\033[0m"
TMP_DIR="${TMPDIR:-/tmp}/qqbot-update-$$"
cleanup() { rm -rf "$TMP_DIR" 2>/dev/null; }
trap cleanup EXIT INT TERM
if [ -d "$PROJ_DIR/.git" ] && [ "$FRESH_INSTALL" = false ]; then
cd "$PROJ_DIR"
# 有本地修改直接重置,插件目录不需要保留用户改动
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
echo " 检测到本地修改,自动重置..."
git checkout -- . 2>/dev/null
git clean -fd 2>/dev/null
fi
echo " 切换到分支 $BRANCH..."
git fetch --all --prune 2>&1 | tail -3
git checkout "$BRANCH" 2>/dev/null || git checkout -b "$BRANCH" "origin/$BRANCH" 2>/dev/null || true
git reset --hard "origin/$BRANCH" 2>/dev/null
REMOTE_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "")
NEW_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
if [ -n "$LOCAL_COMMIT" ] && [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ]; then
echo " ✅ 已是最新 ($LOCAL_VER, commit: $LOCAL_COMMIT),继续检查依赖..."
else
echo " 更新: ${LOCAL_COMMIT:-???}${REMOTE_COMMIT}"
git --no-pager log --oneline "${LOCAL_COMMIT}..HEAD" 2>/dev/null | head -10 || true
fi
else
rm -rf "$TMP_DIR"
echo " 克隆仓库..."
if ! git clone --branch "$BRANCH" --depth 1 "$REPO_URL" "$TMP_DIR" 2>&1 | tail -3; then
printf "%b\n" "\033[31m❌ Git clone 失败\033[0m"
echo ""
echo "请排查:"
echo " 1. 检查网络: curl -I https://github.com"
echo " 2. 检查仓库地址: $REPO_URL"
echo " 3. 如果是私有仓库,确认已配置 SSH key 或 token"
exit 1
fi
mkdir -p "$PROJ_DIR"
rsync -a --delete --exclude 'node_modules' "$TMP_DIR/" "$PROJ_DIR/"
cd "$PROJ_DIR"
REMOTE_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "")
NEW_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
echo " 已克隆到版本: ${NEW_VER:-未知} (${REMOTE_COMMIT})"
cleanup
fi
NEW_VER="${NEW_VER:-未知}"
printf "%b\n" "\033[32m ✅ 代码已更新到 $NEW_VER\033[0m"
##############################################################################
# 第四步:安装依赖
##############################################################################
echo ""
printf "%b\n" "\033[34m4. 安装依赖...\033[0m"
cd "$PROJ_DIR"
if ! npm install --omit=dev 2>&1 | tail -5; then
printf "%b\n" "\033[31m❌ npm 依赖安装失败\033[0m"
echo ""
echo "请排查:"
echo " 1. 手动重试: cd $PROJ_DIR && npm install --omit=dev"
echo " 2. 清理后重试: rm -rf $PROJ_DIR/node_modules && npm install --omit=dev"
echo " 3. 切换镜像: npm config set registry https://registry.npmmirror.com/"
exit 1
fi
echo " ✅ 依赖安装完成"
##############################################################################
# 第五步:恢复配置 → 重启网关
##############################################################################
echo ""
printf "%b\n" "\033[34m5. 恢复配置并重启网关...\033[0m"
# 恢复通道配置
if [ -n "$SAVED_CHANNELS_JSON" ]; then
if node -e "
const fs = require('fs');
const cfg = JSON.parse(fs.readFileSync('$APP_CONFIG', 'utf8'));
cfg.channels = cfg.channels || {};
cfg.channels.qqbot = $SAVED_CHANNELS_JSON;
fs.writeFileSync('$APP_CONFIG', JSON.stringify(cfg, null, 4) + '\n');
" 2>/dev/null; then
echo " ✅ 通道配置已恢复"
else
printf "%b\n" "\033[33m ⚠️ 通道配置写入失败,请手动检查: $APP_CONFIG\033[0m"
fi
elif [ "$FRESH_INSTALL" = true ]; then
echo ""
printf "%b\n" "\033[33m ⚠️ 首次安装,请配置 QQ Bot 凭据:\033[0m"
echo " $CMD channels add --channel qqbot --token 'YOUR_APPID:YOUR_SECRET'"
echo ""
fi
# 停止旧 gateway
echo " 停止旧网关..."
$CMD gateway stop 2>/dev/null || true
sleep 1
# 强制杀占用端口的进程
PORT_PID=$(lsof -ti:"$GATEWAY_PORT" 2>/dev/null || true)
if [ -n "$PORT_PID" ]; then
printf "%b\n" "\033[33m ⚠️ 端口 $GATEWAY_PORT 仍被占用 (PID: $PORT_PID),强制终止...\033[0m"
kill -9 $PORT_PID 2>/dev/null || true
sleep 1
fi
# 卸载 launchd 服务(防止自动拉起旧进程)
for svc in ai.openclaw.gateway ai.clawdbot.gateway ai.moltbot.gateway; do
launchctl bootout "gui/$(id -u)/$svc" 2>/dev/null || true
done
# 启动网关
echo " 启动网关..."
if $CMD gateway 2>&1; then
printf "%b\n" "\033[32m ✅ 网关已启动\033[0m"
else
echo ""
printf "%b\n" "\033[33m ⚠️ 网关启动失败(不影响已安装的插件)\033[0m"
echo ""
echo " 请手动启动:"
echo " 1. 安装服务: $CMD gateway install"
echo " 2. 启动网关: $CMD gateway"
echo " 3. 查看日志: $CMD logs --follow"
fi
##############################################################################
# 完成
##############################################################################
echo ""
printf "%b\n" "\033[32m=========================================\033[0m"
printf "%b\n" "\033[32m ✅ QQBot 已更新到 ${NEW_VER}${REMOTE_COMMIT:+ (${REMOTE_COMMIT})}\033[0m"
[ -n "$LOCAL_VER" ] && printf "%b\n" "\033[32m (从 ${LOCAL_VER}${LOCAL_COMMIT:+ (${LOCAL_COMMIT})} 升级)\033[0m"
printf "%b\n" "\033[32m=========================================\033[0m"
echo ""
echo "常用命令:"
echo " $CMD logs --follow # 跟踪日志"
echo " $CMD gateway restart # 重启服务"
echo " $CMD plugins list # 查看插件列表"
echo " cd $PROJ_DIR && git log # 查看更新历史"
echo "========================================="

View File

@@ -1,336 +1,316 @@
#!/bin/bash
# QQBot 拉取最新 npm 包并更新脚本
# 从 npm 下载 @tencent-connect/openclaw-qq@latest解压覆盖本地源码重新安装插件并重启
# QQBot 拉取最新源码并更新
# 从 GitHub 拉取最新代码,安装依赖并重启网关
# 兼容 clawdbot / openclaw / moltbotmacOS 开箱即用
#
# 用法:
# ./scripts/pull-latest.sh # 更新到最新版
# ./scripts/pull-latest.sh @tencent-connect/openclaw-qq@1.5.2 # 更新到指定版本
# ./scripts/pull-latest.sh --force # 跳过交互,强制重新安装
# ./scripts/pull-latest.sh --force @tencent-connect/openclaw-qq@1.5.3
# pull-latest.sh # 拉取最新代码并更新
# pull-latest.sh --branch main # 指定分支(默认 main
# pull-latest.sh --force # 跳过交互,强制更新
# pull-latest.sh --repo <git-url> # 指定仓库地址
set -e
set -euo pipefail
##############################################################################
# 常量 & 参数
##############################################################################
readonly DEFAULT_REPO="https://github.com/tencent-connect/openclaw-qq.git"
readonly GATEWAY_PORT=18789
readonly SUPPORTED_CLIS=(openclaw clawdbot moltbot)
# ============================================================
# 参数解析
# ============================================================
FORCE=false
PKG_NAME="@tencent-connect/openclaw-qq"
PKG_SPEC=""
BRANCH="main"
REPO_URL=""
for arg in "$@"; do
case "$arg" in
-f|--force) FORCE=true ;;
*) PKG_SPEC="$arg" ;;
while [[ $# -gt 0 ]]; do
case "$1" in
-f|--force) FORCE=true; shift ;;
-b|--branch) BRANCH="$2"; shift 2 ;;
--repo) REPO_URL="$2"; shift 2 ;;
-h|--help)
echo "QQBot 拉取最新源码并更新"
echo ""
echo "用法:"
echo " pull-latest.sh # 拉取最新代码并更新"
echo " pull-latest.sh --branch main # 指定分支(默认 main"
echo " pull-latest.sh --force # 跳过交互,强制更新"
echo " pull-latest.sh --repo <git-url> # 指定仓库地址"
exit 0
;;
*)
echo "未知选项: $1 (使用 --help 查看帮助)"
exit 1
;;
esac
done
PKG_SPEC="${PKG_SPEC:-${PKG_NAME}@latest}"
REPO_URL="${REPO_URL:-$DEFAULT_REPO}"
# ============================================================
# 定位项目目录(兼容从任意位置执行)
# ============================================================
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# 如果脚本在 scripts/ 子目录里,往上一级就是项目根目录
if [ "$(basename "$SCRIPT_DIR")" = "scripts" ]; then
PROJ_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJ_DIR="$SCRIPT_DIR"
fi
cd "$PROJ_DIR"
# ============================================================
# 前置依赖检查
# ============================================================
check_cmd() {
if ! command -v "$1" &>/dev/null; then
echo "❌ 缺少必要命令: $1"
echo " $2"
exit 1
fi
##############################################################################
# 工具函数
##############################################################################
json_get() {
local file="$1" expr="$2"
node -e "process.stdout.write(String((function(){$expr})(JSON.parse(require('fs').readFileSync('$file','utf8')))||''))" 2>/dev/null || true
}
check_cmd node "请先安装 Node.js: https://nodejs.org/ 或 brew install node"
check_cmd npm "npm 通常随 Node.js 一起安装"
check_cmd tar "macOS 自带 tar如果缺失请检查系统完整性"
echo "========================================="
echo " QQBot 拉取最新版本并更新"
echo "========================================="
##############################################################################
# 环境检查
##############################################################################
printf "%b\n" "\033[32m=========================================\033[0m"
printf "%b\n" "\033[32m QQBot 拉取最新源码并更新\033[0m"
printf "%b\n" "\033[32m=========================================\033[0m"
echo ""
echo "系统信息:"
echo " macOS $(sw_vers -productVersion 2>/dev/null || echo '未知')"
echo " Node $(node -v 2>/dev/null)"
echo " npm $(npm -v 2>/dev/null)"
# ============================================================
# 0. 检测 openclaw / clawdbot / moltbot
# ============================================================
# 检查必要命令
for dep in node npm git; do
if ! command -v "$dep" &>/dev/null; then
printf "%b\n" "\033[31m❌ 未检测到 $dep,请先安装\033[0m"
exit 1
fi
done
printf "%b\n" "\033[34m系统信息:\033[0m"
echo " macOS $(sw_vers -productVersion 2>/dev/null || echo '未知')"
echo " Node $(node -v)"
echo " npm $(npm -v)"
echo " Git $(git --version 2>/dev/null | awk '{print $3}')"
echo " 仓库 $REPO_URL"
echo " 分支 $BRANCH"
# 检测 CLI
CMD=""
for name in openclaw clawdbot moltbot; do
for name in "${SUPPORTED_CLIS[@]}"; do
if command -v "$name" &>/dev/null; then
CMD="$name"
break
fi
done
if [ -z "$CMD" ]; then
echo ""
echo "❌ 未找到 openclaw / clawdbot / moltbot 命令"
echo " 请先安装其中之一,参考: https://docs.openclaw.ai"
printf "%b\n" "\033[31m❌ 未找到 openclaw / clawdbot / moltbot 命令,请先安装其中之一\033[0m"
exit 1
fi
echo " CLI $CMD ($($CMD --version 2>/dev/null || echo '未知版本'))"
echo " CLI $CMD ($($CMD --version 2>/dev/null || echo '未知版本'))"
# ============================================================
# 1. 获取当前本地版本
# ============================================================
LOCAL_VER=""
if [ -f "$PROJ_DIR/package.json" ]; then
LOCAL_VER=$(node -e "process.stdout.write(JSON.parse(require('fs').readFileSync('$PROJ_DIR/package.json','utf8')).version||'')" 2>/dev/null || true)
fi
echo ""
echo "[1/5] 当前本地版本: ${LOCAL_VER:-未知}"
APP_HOME="$HOME/.$CMD"
APP_CONFIG="$APP_HOME/$CMD.json"
# ============================================================
# 2. 查询 npm 远程版本
# ============================================================
echo ""
echo "[2/5] 查询 npm 版本..."
##############################################################################
# 定位插件目录
##############################################################################
PROJ_DIR=""
FRESH_INSTALL=false
# 如果指定了具体版本号,直接从 PKG_SPEC 提取;否则查询 latest
if echo "$PKG_SPEC" | grep -qE '@[0-9]+\.[0-9]+'; then
REMOTE_VER=$(echo "$PKG_SPEC" | sed 's/.*@//')
else
REMOTE_VER=$(npm view "$PKG_NAME" version 2>/dev/null || echo "")
fi
if [ -z "$REMOTE_VER" ]; then
echo "❌ 无法查询 $PKG_NAME 的版本,请检查网络"
echo " 当前 npm 源: $(npm config get registry 2>/dev/null)"
echo ""
echo " 可尝试切换镜像源:"
echo " npm config set registry https://registry.npmmirror.com/"
exit 1
fi
echo "目标版本: ${REMOTE_VER}"
if [ "$LOCAL_VER" = "$REMOTE_VER" ]; then
echo ""
echo "✅ 本地版本已是最新 ($LOCAL_VER)"
if [ "$FORCE" = true ]; then
echo "已指定 --force继续重新安装..."
else
printf "是否强制重新安装? (y/N): "
read -r force_choice </dev/tty 2>/dev/null || force_choice="N"
case "$force_choice" in
[Yy]* ) echo "强制重新安装..." ;;
* ) echo "跳过更新。"; exit 0 ;;
esac
fi
fi
# ============================================================
# 3. 备份通道配置
# ============================================================
echo ""
echo "[3/5] 备份已有通道配置..."
SAVED_QQBOT_TOKEN=""
SAVED_MARKDOWN=""
for APP_NAME in openclaw clawdbot moltbot; do
CONFIG_FILE="$HOME/.$APP_NAME/$APP_NAME.json"
[ -f "$CONFIG_FILE" ] || continue
if [ -z "$SAVED_QQBOT_TOKEN" ]; then
SAVED_QQBOT_TOKEN=$(node -e "
const cfg = JSON.parse(require('fs').readFileSync('$CONFIG_FILE', 'utf8'));
const ch = cfg.channels && cfg.channels.qqbot;
if (!ch) process.exit(0);
if (ch.token) { process.stdout.write(ch.token); process.exit(0); }
if (ch.appId && ch.clientSecret) { process.stdout.write(ch.appId + ':' + ch.clientSecret); process.exit(0); }
" 2>/dev/null || true)
fi
if [ -z "$SAVED_MARKDOWN" ]; then
SAVED_MARKDOWN=$(node -e "
const cfg = JSON.parse(require('fs').readFileSync('$CONFIG_FILE', 'utf8'));
const v = (cfg.channels && cfg.channels.qqbot && cfg.channels.qqbot.markdownSupport);
if (v !== undefined && v !== null) process.stdout.write(String(v));
" 2>/dev/null || true)
fi
[ -n "$SAVED_QQBOT_TOKEN" ] && [ -n "$SAVED_MARKDOWN" ] && break
for app in "${SUPPORTED_CLIS[@]}"; do
for plugin_dir in qqbot openclaw-qq; do
ext_dir="$HOME/.$app/extensions/$plugin_dir"
if [ -d "$ext_dir" ] && [ -f "$ext_dir/package.json" ]; then
PROJ_DIR="$ext_dir"
break 2
fi
done
done
if [ -n "$SAVED_QQBOT_TOKEN" ]; then
echo "已备份 qqbot 通道 token: ${SAVED_QQBOT_TOKEN:0:10}..."
if [ -z "$PROJ_DIR" ]; then
PROJ_DIR="$APP_HOME/extensions/qqbot"
FRESH_INSTALL=true
echo " 插件 未安装(首次安装)"
else
echo "未找到已有通道配置(首次安装或已清理)"
echo " 插件 $PROJ_DIR"
fi
# ============================================================
# 4. 下载并解压最新包
# ============================================================
##############################################################################
# 第一步:获取当前版本
##############################################################################
echo ""
echo "[4/5] 下载 $PKG_SPEC 并更新本地文件..."
printf "%b\n" "\033[34m1. 获取当前版本...\033[0m"
TMP_DIR="$PROJ_DIR/.qqbot-update-tmp"
LOCAL_VER=""
LOCAL_COMMIT=""
if [ "$FRESH_INSTALL" = true ]; then
echo " 首次安装,无本地版本"
else
[ -f "$PROJ_DIR/package.json" ] && LOCAL_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
[ -d "$PROJ_DIR/.git" ] && LOCAL_COMMIT=$(cd "$PROJ_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "")
echo " 当前版本: ${LOCAL_VER:-未知}${LOCAL_COMMIT:+ (${LOCAL_COMMIT})}"
fi
# 清理函数:删除临时文件夹
cleanup() {
if [ -d "$TMP_DIR" ]; then
echo "清理临时文件夹: $TMP_DIR"
rm -rf "$TMP_DIR"
fi
}
# 正常退出、中断、终止时都清理
##############################################################################
# 第二步:备份通道配置
##############################################################################
echo ""
printf "%b\n" "\033[34m2. 备份通道配置...\033[0m"
SAVED_CHANNELS_JSON=""
for app in "${SUPPORTED_CLIS[@]}"; do
cfg="$HOME/.$app/$app.json"
[ -f "$cfg" ] || continue
SAVED_CHANNELS_JSON=$(node -e "
const cfg = JSON.parse(require('fs').readFileSync('$cfg', 'utf8'));
// 尝试所有可能的 channel key原仓库 + 本仓库)
const keys = ['qqbot', 'openclaw-qq'];
for (const key of keys) {
const ch = cfg.channels && cfg.channels[key];
if (ch) { process.stdout.write(JSON.stringify(ch)); process.exit(0); }
}
" 2>/dev/null || true)
[ -n "$SAVED_CHANNELS_JSON" ] && break
done
if [ -n "$SAVED_CHANNELS_JSON" ]; then
echo " ✅ 已备份 qqbot 通道配置"
else
echo " 未找到已有通道配置"
fi
##############################################################################
# 第三步:拉取最新代码
##############################################################################
echo ""
printf "%b\n" "\033[34m3. 拉取最新代码...\033[0m"
TMP_DIR="${TMPDIR:-/tmp}/qqbot-update-$$"
cleanup() { rm -rf "$TMP_DIR" 2>/dev/null; }
trap cleanup EXIT INT TERM
# 如果上次意外残留,先清理
[ -d "$TMP_DIR" ] && rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"
if [ -d "$PROJ_DIR/.git" ] && [ "$FRESH_INSTALL" = false ]; then
cd "$PROJ_DIR"
echo "下载中..."
TARBALL=$(cd "$TMP_DIR" && npm pack "$PKG_SPEC" 2>/dev/null)
if [ -z "$TARBALL" ] || [ ! -f "$TMP_DIR/$TARBALL" ]; then
echo "❌ 下载失败"
echo " 请检查网络连接,或尝试:"
echo " npm pack $PKG_SPEC"
exit 1
fi
echo "已下载: $TARBALL"
echo "解压中..."
tar xzf "$TMP_DIR/$TARBALL" -C "$TMP_DIR"
PACK_DIR="$TMP_DIR/package"
if [ ! -d "$PACK_DIR" ]; then
echo "❌ 解压后未找到 package 目录"
exit 1
fi
NEW_VER=$(node -e "process.stdout.write(JSON.parse(require('fs').readFileSync('$PACK_DIR/package.json','utf8')).version||'')" 2>/dev/null || echo "$REMOTE_VER")
echo "将更新到版本: $NEW_VER"
# 同步文件(不用 rsync用 tar + cp 保证 macOS 原生兼容)
echo "同步文件到本地..."
# 把包中所有文件复制过来,跳过不该覆盖的目录
(
cd "$PACK_DIR"
find . -type f | while IFS= read -r f; do
case "$f" in
./.DS_Store|./.git/*|./node_modules/*) continue ;;
esac
dir=$(dirname "$f")
mkdir -p "$PROJ_DIR/$dir"
cp -f "$f" "$PROJ_DIR/$f"
done
)
echo "✅ 文件已更新到 $NEW_VER"
# 删除临时文件夹(不等到 EXIT立即清理
echo "删除临时文件夹..."
rm -rf "$TMP_DIR"
echo "安装依赖..."
cd "$PROJ_DIR"
npm install --omit=dev 2>&1 | tail -5
# ============================================================
# 5. 卸载旧插件、安装新插件、恢复配置、重启
# ============================================================
echo ""
echo "[5/5] 重新安装插件并重启..."
# 清理旧版本(配置 + 扩展目录)
if [ -f "$PROJ_DIR/scripts/upgrade.sh" ]; then
echo "清理旧版本插件..."
bash "$PROJ_DIR/scripts/upgrade.sh"
fi
# 强制删除已有扩展目录,防止 "plugin already exists" 错误
for APP_NAME in openclaw clawdbot moltbot; do
EXT_DIR="$HOME/.$APP_NAME/extensions/qqbot"
if [ -d "$EXT_DIR" ]; then
echo "删除已有扩展目录: $EXT_DIR"
rm -rf "$EXT_DIR"
# 有本地修改直接重置,插件目录不需要保留用户改动
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
echo " 检测到本地修改,自动重置..."
git checkout -- . 2>/dev/null
git clean -fd 2>/dev/null
fi
done
# 安装插件
echo " 切换到分支 $BRANCH..."
git fetch --all --prune 2>&1 | tail -3
git checkout "$BRANCH" 2>/dev/null || git checkout -b "$BRANCH" "origin/$BRANCH" 2>/dev/null || true
git reset --hard "origin/$BRANCH" 2>/dev/null
REMOTE_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "")
NEW_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
if [ -n "$LOCAL_COMMIT" ] && [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ]; then
echo " ✅ 已是最新 ($LOCAL_VER, commit: $LOCAL_COMMIT),继续检查依赖..."
else
echo " 更新: ${LOCAL_COMMIT:-???}${REMOTE_COMMIT}"
git --no-pager log --oneline "${LOCAL_COMMIT}..HEAD" 2>/dev/null | head -10 || true
fi
else
rm -rf "$TMP_DIR"
echo " 克隆仓库..."
if ! git clone --branch "$BRANCH" --depth 1 "$REPO_URL" "$TMP_DIR" 2>&1 | tail -3; then
printf "%b\n" "\033[31m❌ Git clone 失败\033[0m"
echo ""
echo "请排查:"
echo " 1. 检查网络: curl -I https://github.com"
echo " 2. 检查仓库地址: $REPO_URL"
echo " 3. 如果是私有仓库,确认已配置 SSH key 或 token"
exit 1
fi
mkdir -p "$PROJ_DIR"
rsync -a --delete --exclude 'node_modules' "$TMP_DIR/" "$PROJ_DIR/"
cd "$PROJ_DIR"
REMOTE_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "")
NEW_VER=$(json_get "$PROJ_DIR/package.json" "c => c.version")
echo " 已克隆到版本: ${NEW_VER:-未知} (${REMOTE_COMMIT})"
cleanup
fi
NEW_VER="${NEW_VER:-未知}"
printf "%b\n" "\033[32m ✅ 代码已更新到 $NEW_VER\033[0m"
##############################################################################
# 第四步:安装依赖
##############################################################################
echo ""
echo "安装新版本插件..."
if ! $CMD plugins install . 2>&1; then
echo "❌ 插件安装失败,请检查上方错误信息"
printf "%b\n" "\033[34m4. 安装依赖...\033[0m"
cd "$PROJ_DIR"
if ! npm install --omit=dev 2>&1 | tail -5; then
printf "%b\n" "\033[31m❌ npm 依赖安装失败\033[0m"
echo ""
echo "请排查:"
echo " 1. 手动重试: cd $PROJ_DIR && npm install --omit=dev"
echo " 2. 清理后重试: rm -rf $PROJ_DIR/node_modules && npm install --omit=dev"
echo " 3. 切换镜像: npm config set registry https://registry.npmmirror.com/"
exit 1
fi
echo "✅ 插件安装成功"
echo " ✅ 依赖安装完成"
##############################################################################
# 第五步:恢复配置 → 重启网关
##############################################################################
echo ""
printf "%b\n" "\033[34m5. 恢复配置并重启网关...\033[0m"
# 恢复通道配置
if [ -n "$SAVED_QQBOT_TOKEN" ]; then
echo ""
echo "恢复 qqbot 通道配置..."
$CMD channels add --channel qqbot --token "$SAVED_QQBOT_TOKEN" 2>&1 || true
fi
# 恢复 markdown 配置
if [ "$SAVED_MARKDOWN" = "true" ]; then
echo "恢复 Markdown 配置 (已启用)..."
APP_CONFIG="$HOME/.$CMD/$CMD.json"
if [ -f "$APP_CONFIG" ]; then
node -e "
var fs = require('fs');
var cfg = JSON.parse(fs.readFileSync('$APP_CONFIG', 'utf-8'));
if (!cfg.channels) cfg.channels = {};
if (!cfg.channels.qqbot) cfg.channels.qqbot = {};
cfg.channels.qqbot.markdownSupport = true;
fs.writeFileSync('$APP_CONFIG', JSON.stringify(cfg, null, 4) + '\n');
" 2>/dev/null && echo "✅ Markdown 配置已恢复" || echo "⚠️ Markdown 配置恢复失败"
if [ -n "$SAVED_CHANNELS_JSON" ]; then
if node -e "
const fs = require('fs');
const cfg = JSON.parse(fs.readFileSync('$APP_CONFIG', 'utf8'));
cfg.channels = cfg.channels || {};
cfg.channels.qqbot = $SAVED_CHANNELS_JSON;
fs.writeFileSync('$APP_CONFIG', JSON.stringify(cfg, null, 4) + '\n');
" 2>/dev/null; then
echo " ✅ 通道配置已恢复"
else
printf "%b\n" "\033[33m ⚠️ 通道配置写入失败,请手动检查: $APP_CONFIG\033[0m"
fi
elif [ "$FRESH_INSTALL" = true ]; then
echo ""
printf "%b\n" "\033[33m ⚠️ 首次安装,请配置 QQ Bot 凭据:\033[0m"
echo " $CMD channels add --channel qqbot --token 'YOUR_APPID:YOUR_SECRET'"
echo ""
fi
# 重启网关(先确保旧进程停掉,避免无限重启循环)
echo ""
echo "重启网关服务..."
# 先尝试正常停止
# 停止旧 gateway
echo " 停止旧网关..."
$CMD gateway stop 2>/dev/null || true
sleep 1
# 如果端口还被占用,强制杀进程
PORT_PID=$(lsof -ti:18789 2>/dev/null || true)
# 强制杀占用端口的进程
PORT_PID=$(lsof -ti:"$GATEWAY_PORT" 2>/dev/null || true)
if [ -n "$PORT_PID" ]; then
echo "端口 18789 仍被占用 (pid: $PORT_PID),强制终止..."
printf "%b\n" "\033[33m ⚠️ 端口 $GATEWAY_PORT 仍被占用 (PID: $PORT_PID),强制终止...\033[0m"
kill -9 $PORT_PID 2>/dev/null || true
sleep 1
fi
# 卸载 launchd 服务(防止自动拉起旧进程)
for SVC_NAME in ai.openclaw.gateway ai.clawdbot.gateway ai.moltbot.gateway; do
launchctl bootout "gui/$(id -u)/$SVC_NAME" 2>/dev/null || true
for svc in ai.openclaw.gateway ai.clawdbot.gateway ai.moltbot.gateway; do
launchctl bootout "gui/$(id -u)/$svc" 2>/dev/null || true
done
# 启动新的 gateway
# 启动网关
echo " 启动网关..."
if $CMD gateway 2>&1; then
echo ""
echo "✅ 网关已启动"
echo "查看日志: $CMD gateway log"
printf "%b\n" "\033[32m ✅ 网关已启动\033[0m"
else
echo ""
echo "⚠️ 网关启动失败,尝试手动启动:"
echo " $CMD gateway install && $CMD gateway"
printf "%b\n" "\033[33m ⚠️ 网关启动失败(不影响已安装的插件)\033[0m"
echo ""
echo " 请手动启动:"
echo " 1. 安装服务: $CMD gateway install"
echo " 2. 启动网关: $CMD gateway"
echo " 3. 查看日志: $CMD logs --follow"
fi
##############################################################################
# 完成
##############################################################################
echo ""
echo "========================================="
echo " ✅ QQBot 已 ${LOCAL_VER:-未知} 更新到 ${NEW_VER}"
echo "========================================="
printf "%b\n" "\033[32m=========================================\033[0m"
printf "%b\n" "\033[32m ✅ QQBot 已更新到 ${NEW_VER}${REMOTE_COMMIT:+ (${REMOTE_COMMIT})}\033[0m"
[ -n "$LOCAL_VER" ] && printf "%b\n" "\033[32m (从 ${LOCAL_VER}${LOCAL_COMMIT:+ (${LOCAL_COMMIT})} 升级)\033[0m"
printf "%b\n" "\033[32m=========================================\033[0m"
echo ""
echo "常用命令:"
echo " $CMD gateway log # 查看日志"
echo " $CMD logs --follow # 跟踪日志"
echo " $CMD gateway restart # 重启服务"
echo " $CMD plugins list # 查看插件列表"
echo " cd $PROJ_DIR && git log # 查看更新历史"
echo "========================================="

View File

@@ -13,7 +13,13 @@
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
# 如果脚本在 scripts/ 子目录里,往上一级就是项目根目录
if [ "$(basename "$SCRIPT_DIR")" = "scripts" ]; then
PROJ_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJ_DIR="$SCRIPT_DIR"
fi
cd "$PROJ_DIR"
# 解析命令行参数
APPID=""
@@ -75,17 +81,19 @@ echo "========================================="
echo ""
echo "[1/6] 备份已有配置..."
SAVED_QQBOT_TOKEN=""
for APP_NAME in openclaw clawdbot; do
for APP_NAME in openclaw clawdbot moltbot; do
CONFIG_FILE="$HOME/.$APP_NAME/$APP_NAME.json"
if [ -f "$CONFIG_FILE" ]; then
SAVED_QQBOT_TOKEN=$(node -e "
const cfg = JSON.parse(require('fs').readFileSync('$CONFIG_FILE', 'utf8'));
const ch = cfg.channels && cfg.channels.qqbot;
if (!ch) process.exit(0);
// token 字段openclaw channels add 写入)
if (ch.token) { process.stdout.write(ch.token); process.exit(0); }
// appId + clientSecret 字段openclaw 实际存储格式)
if (ch.appId && ch.clientSecret) { process.stdout.write(ch.appId + ':' + ch.clientSecret); process.exit(0); }
// 尝试所有可能的 channel key原仓库 + 本仓库)
const keys = ['qqbot', 'openclaw-qq'];
for (const key of keys) {
const ch = cfg.channels && cfg.channels[key];
if (!ch) continue;
if (ch.token) { process.stdout.write(ch.token); process.exit(0); }
if (ch.appId && ch.clientSecret) { process.stdout.write(ch.appId + ':' + ch.clientSecret); process.exit(0); }
}
" 2>/dev/null || true)
if [ -n "$SAVED_QQBOT_TOKEN" ]; then
echo "已备份 qqbot 通道 token: ${SAVED_QQBOT_TOKEN:0:10}..."
@@ -97,8 +105,8 @@ done
# 2. 移除老版本
echo ""
echo "[2/6] 移除老版本..."
if [ -f "./scripts/upgrade.sh" ]; then
bash ./scripts/upgrade.sh
if [ -f "$PROJ_DIR/scripts/upgrade.sh" ]; then
bash "$PROJ_DIR/scripts/upgrade.sh"
else
echo "警告: upgrade.sh 不存在,跳过移除步骤"
fi

View File

@@ -18,49 +18,55 @@ detect_installation() {
fi
}
# 可能的扩展目录名(原仓库 qqbot + 本仓库框架推断名 openclaw-qq
EXTENSION_DIRS=("qqbot" "openclaw-qq")
# 清理指定目录的函数
cleanup_installation() {
local APP_NAME="$1"
local APP_DIR="$HOME/.$APP_NAME"
local CONFIG_FILE="$APP_DIR/$APP_NAME.json"
local EXTENSION_DIR="$APP_DIR/extensions/qqbot"
echo ""
echo ">>> 处理 $APP_NAME 安装..."
# 1. 删除旧扩展目录
if [ -d "$EXTENSION_DIR" ]; then
echo "删除旧版本插件: $EXTENSION_DIR"
rm -rf "$EXTENSION_DIR"
else
echo "未找到旧版本插件目录,跳过删除"
fi
# 1. 删除所有可能的旧扩展目录
for dir_name in "${EXTENSION_DIRS[@]}"; do
local ext_dir="$APP_DIR/extensions/$dir_name"
if [ -d "$ext_dir" ]; then
echo "删除旧版本插件: $ext_dir"
rm -rf "$ext_dir"
fi
done
# 2. 清理配置文件中的 qqbot 相关字段
# 2. 清理配置文件中所有可能的插件 ID 相关字段
if [ -f "$CONFIG_FILE" ]; then
echo "清理配置文件中的 qqbot 字段..."
echo "清理配置文件中的插件字段..."
# 使用 node 处理 JSON比 jq 更可靠处理复杂结构)
node -e "
const fs = require('fs');
const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
const ids = ['qqbot', 'openclaw-qq', '@sliverp/qqbot', '@tencent-connect/openclaw-qq'];
// 删除 channels.qqbot
if (config.channels && config.channels.qqbot) {
delete config.channels.qqbot;
console.log(' - 已删除 channels.qqbot');
}
// 删除 plugins.entries.qqbot
if (config.plugins && config.plugins.entries && config.plugins.entries.qqbot) {
delete config.plugins.entries.qqbot;
console.log(' - 已删除 plugins.entries.qqbot');
}
// 删除 plugins.installs.qqbot
if (config.plugins && config.plugins.installs && config.plugins.installs.qqbot) {
delete config.plugins.installs.qqbot;
console.log(' - 已删除 plugins.installs.qqbot');
for (const id of ids) {
// 删除 channels.<id>
if (config.channels && config.channels[id]) {
delete config.channels[id];
console.log(' - 已删除 channels.' + id);
}
// 删除 plugins.entries.<id>
if (config.plugins && config.plugins.entries && config.plugins.entries[id]) {
delete config.plugins.entries[id];
console.log(' - 已删除 plugins.entries.' + id);
}
// 删除 plugins.installs.<id>
if (config.plugins && config.plugins.installs && config.plugins.installs[id]) {
delete config.plugins.installs[id];
console.log(' - 已删除 plugins.installs.' + id);
}
}
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(config, null, 2));
@@ -86,10 +92,16 @@ if [ -d "$HOME/.openclaw" ]; then
FOUND_INSTALLATION="openclaw"
fi
# 检查 moltbot
if [ -d "$HOME/.moltbot" ]; then
cleanup_installation "moltbot"
FOUND_INSTALLATION="moltbot"
fi
# 如果都没找到
if [ -z "$FOUND_INSTALLATION" ]; then
echo "未找到 clawdbot openclaw 安装目录"
echo "请确认已安装 clawdbot 或 openclaw"
echo "未找到 clawdbot / openclaw / moltbot 安装目录"
echo "请确认已安装其中之一"
exit 1
fi
@@ -100,7 +112,7 @@ echo ""
echo "=== 清理完成 ==="
echo ""
echo "接下来请执行以下命令重新安装插件:"
echo " cd /path/to/qqbot"
echo " cd /path/to/openclaw-qq"
echo " $CMD plugins install ."
echo " $CMD channels add --channel qqbot --token \"AppID:AppSecret\""
echo " $CMD gateway restart"