@jerryliang122/openclaw-qqbot 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -13
- package/README.zh.md +2 -13
- package/dist/index.cjs +6 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -5
- package/index.ts +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/commands/bot-help.ts +1 -1
- package/src/commands/bot-version.ts +1 -12
- package/src/commands/index.ts +0 -2
- package/src/gateway/lifecycle.ts +2 -6
- package/src/types.ts +0 -5
- package/skills/qqbot-upgrade/SKILL.md +0 -56
- package/src/commands/bot-upgrade.ts +0 -56
- package/src/features/update-checker.ts +0 -166
package/README.md
CHANGED
|
@@ -46,7 +46,6 @@ Scan to join the QQ group chat
|
|
|
46
46
|
| 🌐 **Dual Transport** | WebSocket (default) or Webhook (HTTP callback) — switch via config |
|
|
47
47
|
| 🖼️ **Rich Media** | Send & receive images, voice, video, and files |
|
|
48
48
|
| 🎙️ **Voice (STT/TTS)** | Speech-to-text transcription & text-to-speech replies |
|
|
49
|
-
| 🔄 **Update Check** | `/bot-upgrade` checks the npm registry for new versions and links the upgrade guide |
|
|
50
49
|
| ⏰ **Scheduled Push** | Proactive message delivery via scheduled tasks |
|
|
51
50
|
| 🔗 **URL Support** | Direct URL sending in private chat (no restrictions) |
|
|
52
51
|
| ⌨️ **Typing Indicator** | "Bot is typing..." status shown in real-time |
|
|
@@ -194,16 +193,6 @@ Shows framework version, plugin version, and a direct link to the official repos
|
|
|
194
193
|
|
|
195
194
|
<img width="360" src="docs/images/slash-help.jpg" alt="Help Demo" />
|
|
196
195
|
|
|
197
|
-
#### `/bot-upgrade` — Version Check & Upgrade Guide
|
|
198
|
-
|
|
199
|
-
> **You**: `/bot-upgrade`
|
|
200
|
-
>
|
|
201
|
-
> **QQBot**: 📌 Current: v1.0.0 / 🆕 New version available / 📖 Upgrade guide link
|
|
202
|
-
|
|
203
|
-
Checks the installed version against the npm registry (`@jerryliang122/openclaw-qqbot`) and returns a link to the upgrade guide (repo CHANGELOG by default; override with `channels.qqbot.upgradeUrl`). Actual upgrading is done on the host via `openclaw plugins install` — see [Getting Started](#-getting-started).
|
|
204
|
-
|
|
205
|
-
<img width="360" src="docs/images/hot-update.jpg" alt="Upgrade Demo" />
|
|
206
|
-
|
|
207
196
|
#### `/bot-logs` — Log Export
|
|
208
197
|
|
|
209
198
|
> **You**: `/bot-logs`
|
|
@@ -218,9 +207,9 @@ Exports the last ~2000 lines of gateway logs as a file for quick troubleshooting
|
|
|
218
207
|
|
|
219
208
|
All commands support a `?` suffix to show usage:
|
|
220
209
|
|
|
221
|
-
> **You**: `/bot-
|
|
210
|
+
> **You**: `/bot-ping ?`
|
|
222
211
|
>
|
|
223
|
-
> **QQBot**: 📖 /bot-
|
|
212
|
+
> **QQBot**: 📖 /bot-ping usage: …
|
|
224
213
|
|
|
225
214
|
#### `/bot-approve` — Approval Configuration
|
|
226
215
|
|
package/README.zh.md
CHANGED
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
| 🌐 **双传输模式** | WebSocket(默认)或 Webhook(HTTP 回调)— 配置切换 |
|
|
45
45
|
| 🖼️ **富媒体消息** | 支持图片、语音、视频、文件的收发 |
|
|
46
46
|
| 🎙️ **语音能力 (STT/TTS)** | 语音转文字自动转录 & 文字转语音回复 |
|
|
47
|
-
| 🔄 **版本检查** | 私聊发送 `/bot-upgrade` 检查 npm 新版本并附升级指引 |
|
|
48
47
|
| ⏰ **定时推送** | 支持定时任务触发后主动推送消息 |
|
|
49
48
|
| 🔗 **URL 无限制** | 私聊可直接发送 URL |
|
|
50
49
|
| ⌨️ **输入状态** | 实时显示"Bot 正在输入中…"状态 |
|
|
@@ -192,16 +191,6 @@ AI 可直接发送视频,支持本地文件和公网 URL。
|
|
|
192
191
|
|
|
193
192
|
<img width="360" src="docs/images/slash-help.jpg" alt="Help 演示" />
|
|
194
193
|
|
|
195
|
-
#### `/bot-upgrade` — 版本检查与升级指引
|
|
196
|
-
|
|
197
|
-
> **你**:`/bot-upgrade`
|
|
198
|
-
>
|
|
199
|
-
> **QQBot**:📌当前版本 v1.0.0 / 🆕发现新版本 / 📖升级指引链接
|
|
200
|
-
|
|
201
|
-
对比 npm registry(`@jerryliang122/openclaw-qqbot`)上的最新版本,并返回升级指引链接(默认指向仓库 CHANGELOG,可用 `channels.qqbot.upgradeUrl` 覆盖)。实际升级在主机上通过 `openclaw plugins install` 完成,见[快速开始](#-快速开始)。
|
|
202
|
-
|
|
203
|
-
<img width="360" src="docs/images/hot-update.jpg" alt="升级检查演示" />
|
|
204
|
-
|
|
205
194
|
#### `/bot-logs` — 日志导出
|
|
206
195
|
|
|
207
196
|
> **你**:`/bot-logs`
|
|
@@ -216,9 +205,9 @@ AI 可直接发送视频,支持本地文件和公网 URL。
|
|
|
216
205
|
|
|
217
206
|
所有指令都支持 `?` 后缀查看用法说明:
|
|
218
207
|
|
|
219
|
-
> **你**:`/bot-
|
|
208
|
+
> **你**:`/bot-ping ?`
|
|
220
209
|
>
|
|
221
|
-
> **QQBot**:📖 /bot-
|
|
210
|
+
> **QQBot**:📖 /bot-ping 用法:…
|
|
222
211
|
|
|
223
212
|
#### `/bot-approve` — 审批配置管理
|
|
224
213
|
|
package/dist/index.cjs
CHANGED
|
@@ -5457,7 +5457,7 @@ var require_websocket = __commonJS({
|
|
|
5457
5457
|
"node_modules/ws/lib/websocket.js"(exports2, module2) {
|
|
5458
5458
|
"use strict";
|
|
5459
5459
|
var EventEmitter = require("events");
|
|
5460
|
-
var
|
|
5460
|
+
var https2 = require("https");
|
|
5461
5461
|
var http2 = require("http");
|
|
5462
5462
|
var net2 = require("net");
|
|
5463
5463
|
var tls = require("tls");
|
|
@@ -6000,7 +6000,7 @@ var require_websocket = __commonJS({
|
|
|
6000
6000
|
}
|
|
6001
6001
|
const defaultPort = isSecure ? 443 : 80;
|
|
6002
6002
|
const key2 = randomBytes(16).toString("base64");
|
|
6003
|
-
const request2 = isSecure ?
|
|
6003
|
+
const request2 = isSecure ? https2.request : http2.request;
|
|
6004
6004
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
6005
6005
|
let perMessageDeflate;
|
|
6006
6006
|
opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
|
|
@@ -9962,7 +9962,7 @@ var init_outbound_service = __esm({
|
|
|
9962
9962
|
|
|
9963
9963
|
// src/utils/pkg-version.ts
|
|
9964
9964
|
function getPackageVersion() {
|
|
9965
|
-
return true ? "1.0.
|
|
9965
|
+
return true ? "1.0.1" : "unknown";
|
|
9966
9966
|
}
|
|
9967
9967
|
function getOpenclawVersion(runtimeVersion) {
|
|
9968
9968
|
return runtimeVersion && runtimeVersion !== "unknown" ? runtimeVersion : "unknown";
|
|
@@ -11510,7 +11510,6 @@ init_dist();
|
|
|
11510
11510
|
init_pkg_version();
|
|
11511
11511
|
var PLUGIN_VERSION2 = getPackageVersion();
|
|
11512
11512
|
var GROUP_EXCLUDED = /* @__PURE__ */ new Set([
|
|
11513
|
-
"bot-upgrade",
|
|
11514
11513
|
"bot-clear-storage",
|
|
11515
11514
|
"bot-logs",
|
|
11516
11515
|
"bot-approve",
|
|
@@ -11579,121 +11578,6 @@ function botPing() {
|
|
|
11579
11578
|
|
|
11580
11579
|
// src/commands/bot-version.ts
|
|
11581
11580
|
init_pkg_version();
|
|
11582
|
-
|
|
11583
|
-
// src/features/update-checker.ts
|
|
11584
|
-
var import_node_https2 = __toESM(require("https"), 1);
|
|
11585
|
-
init_pkg_version();
|
|
11586
|
-
var PKG_NAME = "@jerryliang122/openclaw-qqbot";
|
|
11587
|
-
var ENCODED_PKG = encodeURIComponent(PKG_NAME);
|
|
11588
|
-
var REGISTRIES = [
|
|
11589
|
-
`https://registry.npmjs.org/${ENCODED_PKG}`,
|
|
11590
|
-
`https://registry.npmmirror.com/${ENCODED_PKG}`
|
|
11591
|
-
];
|
|
11592
|
-
var CURRENT_VERSION = getPackageVersion();
|
|
11593
|
-
function fetchJson(url, timeoutMs) {
|
|
11594
|
-
return new Promise((resolve2, reject) => {
|
|
11595
|
-
const req2 = import_node_https2.default.get(url, { timeout: timeoutMs, headers: { Accept: "application/json" } }, (res) => {
|
|
11596
|
-
if (res.statusCode !== 200) {
|
|
11597
|
-
res.resume();
|
|
11598
|
-
reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
11599
|
-
return;
|
|
11600
|
-
}
|
|
11601
|
-
let data = "";
|
|
11602
|
-
res.on("data", (chunk) => {
|
|
11603
|
-
data += chunk;
|
|
11604
|
-
});
|
|
11605
|
-
res.on("end", () => {
|
|
11606
|
-
try {
|
|
11607
|
-
resolve2(JSON.parse(data));
|
|
11608
|
-
} catch (e) {
|
|
11609
|
-
reject(e);
|
|
11610
|
-
}
|
|
11611
|
-
});
|
|
11612
|
-
});
|
|
11613
|
-
req2.on("error", reject);
|
|
11614
|
-
req2.on("timeout", () => {
|
|
11615
|
-
req2.destroy();
|
|
11616
|
-
reject(new Error(`timeout fetching ${url}`));
|
|
11617
|
-
});
|
|
11618
|
-
});
|
|
11619
|
-
}
|
|
11620
|
-
async function fetchDistTags(log5) {
|
|
11621
|
-
for (const url of REGISTRIES) {
|
|
11622
|
-
try {
|
|
11623
|
-
const json4 = await fetchJson(url, 1e4);
|
|
11624
|
-
const tags = json4["dist-tags"];
|
|
11625
|
-
if (tags && typeof tags === "object") return tags;
|
|
11626
|
-
} catch (e) {
|
|
11627
|
-
log5?.debug(`[update-checker] ${url} failed: ${e.message}`);
|
|
11628
|
-
}
|
|
11629
|
-
}
|
|
11630
|
-
throw new Error("all registries failed");
|
|
11631
|
-
}
|
|
11632
|
-
function buildUpdateInfo(tags) {
|
|
11633
|
-
const currentIsPrerelease = CURRENT_VERSION.includes("-");
|
|
11634
|
-
const stableTag = tags.latest || null;
|
|
11635
|
-
const alphaTag = tags.alpha || null;
|
|
11636
|
-
const compareTarget = currentIsPrerelease ? alphaTag : stableTag;
|
|
11637
|
-
const hasUpdate = typeof compareTarget === "string" && compareTarget !== CURRENT_VERSION && compareVersions(compareTarget, CURRENT_VERSION) > 0;
|
|
11638
|
-
return {
|
|
11639
|
-
current: CURRENT_VERSION,
|
|
11640
|
-
latest: compareTarget,
|
|
11641
|
-
stable: stableTag,
|
|
11642
|
-
alpha: alphaTag,
|
|
11643
|
-
hasUpdate,
|
|
11644
|
-
checkedAt: Date.now()
|
|
11645
|
-
};
|
|
11646
|
-
}
|
|
11647
|
-
function triggerUpdateCheck(log5) {
|
|
11648
|
-
getUpdateInfo(log5).then((info) => {
|
|
11649
|
-
if (info.hasUpdate) {
|
|
11650
|
-
log5.info(`[update-checker] new version available: ${info.latest} (current: ${CURRENT_VERSION})`);
|
|
11651
|
-
}
|
|
11652
|
-
}).catch(() => {
|
|
11653
|
-
});
|
|
11654
|
-
}
|
|
11655
|
-
async function getUpdateInfo(log5) {
|
|
11656
|
-
try {
|
|
11657
|
-
const tags = await fetchDistTags(log5);
|
|
11658
|
-
return buildUpdateInfo(tags);
|
|
11659
|
-
} catch (err) {
|
|
11660
|
-
log5?.debug(`[update-checker] check failed: ${err.message}`);
|
|
11661
|
-
return { current: CURRENT_VERSION, latest: null, stable: null, alpha: null, hasUpdate: false, checkedAt: Date.now(), error: err.message };
|
|
11662
|
-
}
|
|
11663
|
-
}
|
|
11664
|
-
function compareVersions(a, b2) {
|
|
11665
|
-
const parse = (v) => {
|
|
11666
|
-
const clean = v.replace(/^v/, "");
|
|
11667
|
-
const [main, pre] = clean.split("-", 2);
|
|
11668
|
-
return { parts: main.split(".").map(Number), pre: pre || null };
|
|
11669
|
-
};
|
|
11670
|
-
const pa = parse(a);
|
|
11671
|
-
const pb = parse(b2);
|
|
11672
|
-
for (let i = 0; i < 3; i++) {
|
|
11673
|
-
const diff = (pa.parts[i] || 0) - (pb.parts[i] || 0);
|
|
11674
|
-
if (diff !== 0) return diff;
|
|
11675
|
-
}
|
|
11676
|
-
if (!pa.pre && pb.pre) return 1;
|
|
11677
|
-
if (pa.pre && !pb.pre) return -1;
|
|
11678
|
-
if (!pa.pre && !pb.pre) return 0;
|
|
11679
|
-
const aParts = pa.pre.split(".");
|
|
11680
|
-
const bParts = pb.pre.split(".");
|
|
11681
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
11682
|
-
const aP = aParts[i] ?? "";
|
|
11683
|
-
const bP = bParts[i] ?? "";
|
|
11684
|
-
const aNum = Number(aP);
|
|
11685
|
-
const bNum = Number(bP);
|
|
11686
|
-
if (!isNaN(aNum) && !isNaN(bNum)) {
|
|
11687
|
-
if (aNum !== bNum) return aNum - bNum;
|
|
11688
|
-
} else {
|
|
11689
|
-
if (aP < bP) return -1;
|
|
11690
|
-
if (aP > bP) return 1;
|
|
11691
|
-
}
|
|
11692
|
-
}
|
|
11693
|
-
return 0;
|
|
11694
|
-
}
|
|
11695
|
-
|
|
11696
|
-
// src/commands/bot-version.ts
|
|
11697
11581
|
init_bot_instance();
|
|
11698
11582
|
var PLUGIN_VERSION3 = getPackageVersion();
|
|
11699
11583
|
var GITHUB_URL = "https://github.com/nicepkg/openclaw";
|
|
@@ -11704,24 +11588,15 @@ function botVersion(_account) {
|
|
|
11704
11588
|
usage: [
|
|
11705
11589
|
"/bot-version",
|
|
11706
11590
|
"",
|
|
11707
|
-
"\u67E5\u770B\u5F53\u524D QQBot \u63D2\u4EF6\u7248\u672C\u548C OpenClaw \u6846\u67B6\u7248\u672C\u3002"
|
|
11708
|
-
"\u540C\u65F6\u68C0\u67E5\u662F\u5426\u6709\u65B0\u7248\u672C\u53EF\u7528\u3002"
|
|
11591
|
+
"\u67E5\u770B\u5F53\u524D QQBot \u63D2\u4EF6\u7248\u672C\u548C OpenClaw \u6846\u67B6\u7248\u672C\u3002"
|
|
11709
11592
|
].join("\n"),
|
|
11710
11593
|
handler: async () => {
|
|
11711
11594
|
const frameworkVersion = getOpenClawVersion();
|
|
11712
11595
|
const lines = [
|
|
11713
11596
|
`\u{1F99E}\u6846\u67B6\u7248\u672C\uFF1A${frameworkVersion}`,
|
|
11714
|
-
`\u{1F916}QQBot \u63D2\u4EF6\u7248\u672C\uFF1Av${PLUGIN_VERSION3}
|
|
11597
|
+
`\u{1F916}QQBot \u63D2\u4EF6\u7248\u672C\uFF1Av${PLUGIN_VERSION3}`,
|
|
11598
|
+
`\u{1F31F}\u5B98\u65B9 GitHub \u4ED3\u5E93\uFF1A[\u70B9\u51FB\u524D\u5F80](${GITHUB_URL})`
|
|
11715
11599
|
];
|
|
11716
|
-
const info = await getUpdateInfo();
|
|
11717
|
-
if (info.checkedAt === 0) {
|
|
11718
|
-
lines.push("\u23F3 \u7248\u672C\u68C0\u67E5\u4E2D...");
|
|
11719
|
-
} else if (info.error) {
|
|
11720
|
-
lines.push("\u26A0\uFE0F \u7248\u672C\u68C0\u67E5\u5931\u8D25");
|
|
11721
|
-
} else if (info.hasUpdate && info.latest) {
|
|
11722
|
-
lines.push(`\u{1F195}\u6700\u65B0\u53EF\u7528\u7248\u672C\uFF1Av${info.latest}\uFF0C\u70B9\u51FB <qqbot-cmd-input text="/bot-upgrade" show="/bot-upgrade"/> \u67E5\u770B\u5347\u7EA7\u6307\u5F15`);
|
|
11723
|
-
}
|
|
11724
|
-
lines.push(`\u{1F31F}\u5B98\u65B9 GitHub \u4ED3\u5E93\uFF1A[\u70B9\u51FB\u524D\u5F80](${GITHUB_URL})`);
|
|
11725
11600
|
return lines.join("\n");
|
|
11726
11601
|
}
|
|
11727
11602
|
};
|
|
@@ -11744,9 +11619,6 @@ function botMe() {
|
|
|
11744
11619
|
};
|
|
11745
11620
|
}
|
|
11746
11621
|
|
|
11747
|
-
// src/commands/bot-upgrade.ts
|
|
11748
|
-
init_pkg_version();
|
|
11749
|
-
|
|
11750
11622
|
// src/commands/config-util.ts
|
|
11751
11623
|
init_resolve();
|
|
11752
11624
|
function checkCommandAuth(ctx) {
|
|
@@ -11801,52 +11673,6 @@ async function updateGlobalConfig(getRuntime, updater) {
|
|
|
11801
11673
|
}
|
|
11802
11674
|
}
|
|
11803
11675
|
|
|
11804
|
-
// src/commands/bot-upgrade.ts
|
|
11805
|
-
var PLUGIN_VERSION4 = getPackageVersion();
|
|
11806
|
-
var DEFAULT_UPGRADE_URL = "https://github.com/jerryliang122/qqbot-openclaw/blob/main/CHANGELOG.md";
|
|
11807
|
-
var GITHUB_URL2 = "https://github.com/jerryliang122/qqbot-openclaw";
|
|
11808
|
-
function botUpgrade(account) {
|
|
11809
|
-
return {
|
|
11810
|
-
name: "bot-upgrade",
|
|
11811
|
-
description: "\u68C0\u67E5\u66F4\u65B0\u5E76\u67E5\u770B\u5347\u7EA7\u6307\u5F15",
|
|
11812
|
-
scope: "c2c",
|
|
11813
|
-
authorized: checkCommandAuth,
|
|
11814
|
-
usage: [
|
|
11815
|
-
"/bot-upgrade \u68C0\u67E5\u662F\u5426\u6709\u65B0\u7248\u672C"
|
|
11816
|
-
].join("\n"),
|
|
11817
|
-
handler: async () => {
|
|
11818
|
-
const url = account.config.upgradeUrl ?? DEFAULT_UPGRADE_URL;
|
|
11819
|
-
const info = await getUpdateInfo();
|
|
11820
|
-
if (info.checkedAt === 0) {
|
|
11821
|
-
return "\u23F3 \u7248\u672C\u68C0\u67E5\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5";
|
|
11822
|
-
}
|
|
11823
|
-
if (info.error) {
|
|
11824
|
-
return [
|
|
11825
|
-
"\u274C \u4E3B\u673A\u7F51\u7EDC\u8BBF\u95EE\u5F02\u5E38\uFF0C\u65E0\u6CD5\u68C0\u67E5\u66F4\u65B0",
|
|
11826
|
-
"",
|
|
11827
|
-
`\u67E5\u770B\u5347\u7EA7\u6307\u5F15\uFF1A[\u70B9\u51FB\u67E5\u770B](${url})`
|
|
11828
|
-
].join("\n");
|
|
11829
|
-
}
|
|
11830
|
-
if (!info.hasUpdate) {
|
|
11831
|
-
return [
|
|
11832
|
-
`\u2705 \u5F53\u524D\u5DF2\u662F\u6700\u65B0\u7248\u672C v${PLUGIN_VERSION4}`,
|
|
11833
|
-
"",
|
|
11834
|
-
`\u9879\u76EE\u5730\u5740\uFF1A[GitHub](${GITHUB_URL2})`
|
|
11835
|
-
].join("\n");
|
|
11836
|
-
}
|
|
11837
|
-
return [
|
|
11838
|
-
"\u{1F195} \u53D1\u73B0\u65B0\u7248\u672C",
|
|
11839
|
-
"",
|
|
11840
|
-
`\u5F53\u524D\u7248\u672C\uFF1A**v${PLUGIN_VERSION4}**`,
|
|
11841
|
-
`\u6700\u65B0\u7248\u672C\uFF1A**v${info.latest}**`,
|
|
11842
|
-
"",
|
|
11843
|
-
`\u{1F4D6} \u5347\u7EA7\u6307\u5F15\uFF1A[\u70B9\u51FB\u67E5\u770B](${url})`,
|
|
11844
|
-
`\u{1F31F} GitHub \u4ED3\u5E93\uFF1A[\u70B9\u51FB\u524D\u5F80](${GITHUB_URL2})`
|
|
11845
|
-
].join("\n");
|
|
11846
|
-
}
|
|
11847
|
-
};
|
|
11848
|
-
}
|
|
11849
|
-
|
|
11850
11676
|
// src/commands/bot-streaming.ts
|
|
11851
11677
|
function botStreaming(account, getRuntime) {
|
|
11852
11678
|
return {
|
|
@@ -12746,7 +12572,6 @@ function buildCommandList(account, opts) {
|
|
|
12746
12572
|
botPing(),
|
|
12747
12573
|
botVersion(account),
|
|
12748
12574
|
botMe(),
|
|
12749
|
-
botUpgrade(account),
|
|
12750
12575
|
botLogs(opts.getRuntime()),
|
|
12751
12576
|
botStreaming(account, opts.getRuntime),
|
|
12752
12577
|
botClearStorage(account),
|
|
@@ -17121,7 +16946,6 @@ async function startAccountWithCredentialRecovery(ctx) {
|
|
|
17121
16946
|
);
|
|
17122
16947
|
}
|
|
17123
16948
|
async function initFeatures(account, ctx, log5) {
|
|
17124
|
-
triggerUpdateCheck(log5);
|
|
17125
16949
|
registerApprovalNativeContext(account.accountId, ctx);
|
|
17126
16950
|
syncCommandPanels(account, ctx.cfg, log5).catch((e) => {
|
|
17127
16951
|
log5?.error(`[qqbot:${account.accountId}] command panel sync error: ${e}`);
|