karin-plugin-kkk 2.44.1 → 2.45.0-beta.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/CHANGELOG.md +41 -0
- package/config/default_config/app.yaml +4 -0
- package/config/default_config/config.json +42 -7
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/main.js +681 -45
- package/lib/style.css +49 -0
- package/lib/web/assets/{CronEditor-7jONBXc7.js → CronEditor-B8UDHt0_.js} +1 -1
- package/lib/web/assets/{DesktopLayout-DBoDs9Vs.js → DesktopLayout-drMRNCzE.js} +1 -1
- package/lib/web/assets/{MobileLayout-DRRbkB4n.js → MobileLayout-DVcUuYNA.js} +1 -1
- package/lib/web/assets/{ThemeSwitch-CwRb5j8E.js → ThemeSwitch-CtOTxsWS.js} +1 -1
- package/lib/web/assets/{index-C6OKJLTC.js → index-CKFMwQze.js} +2 -2
- package/lib/web/assets/{separator-DpAAkxFR.js → separator-CRsEEbKb.js} +1 -1
- package/lib/web/index.html +1 -1
- package/package.json +54 -10
package/lib/core_chunk/main.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createRequire } from "node:module";
|
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import path, { resolve } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import karin, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, common, config, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, hooks, isDocker, karin as karin$1, karinPathHtml, logger, logs, mkdirSync, parseChangelog, range, render, restart, segment, updatePkg, watch } from "node-karin";
|
|
9
|
+
import karin, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, common, config, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, exec, ffmpeg, ffprobe, getPkgVersion, getRemotePkgVersion, hooks, isDocker, karin as karin$1, karinPathHtml, logger, logs, mkdirSync, parseChangelog, range, render, restart, segment, updatePkg, watch } from "node-karin";
|
|
10
10
|
import crypto from "node:crypto";
|
|
11
11
|
import { deflateSync, inflateSync } from "node:zlib";
|
|
12
12
|
import express from "node-karin/express";
|
|
@@ -7433,6 +7433,26 @@ var resolveEmojiSrc = (filename) => {
|
|
|
7433
7433
|
};
|
|
7434
7434
|
setUnicodeEmojiSrcResolver(resolveEmojiSrc);
|
|
7435
7435
|
//#endregion
|
|
7436
|
+
//#region src/module/utils/releaseChannel.ts
|
|
7437
|
+
var parseReleaseChannel = (version) => {
|
|
7438
|
+
const v = version.trim().replace(/^[vV]/, "").split("+", 1)[0];
|
|
7439
|
+
const match = /^\d+\.\d+\.\d+(?:-(.+))?$/.exec(v);
|
|
7440
|
+
if (!match) return "Canary";
|
|
7441
|
+
if (!match[1]) return "Stable";
|
|
7442
|
+
const pre = match[1].split(".");
|
|
7443
|
+
if (pre[0] === "rc") return "Rc";
|
|
7444
|
+
if (pre[0] === "canary") return "Canary";
|
|
7445
|
+
if (pre[0] === "beta" && pre.length <= 2) return "Beta";
|
|
7446
|
+
return "Canary";
|
|
7447
|
+
};
|
|
7448
|
+
/** 渠道显示名(中文) */
|
|
7449
|
+
var RELEASE_CHANNEL_LABEL = {
|
|
7450
|
+
Stable: "正式版",
|
|
7451
|
+
Beta: "测试版",
|
|
7452
|
+
Rc: "预览版",
|
|
7453
|
+
Canary: "金丝雀"
|
|
7454
|
+
};
|
|
7455
|
+
//#endregion
|
|
7436
7456
|
//#region src/module/utils/semver.ts
|
|
7437
7457
|
/**
|
|
7438
7458
|
* 语义化版本比较
|
|
@@ -7832,7 +7852,7 @@ var Render = async (event, path, data) => {
|
|
|
7832
7852
|
plugin: "karin-plugin",
|
|
7833
7853
|
pluginName: "kkk",
|
|
7834
7854
|
pluginVersion: Root.pluginVersion,
|
|
7835
|
-
releaseType:
|
|
7855
|
+
releaseType: parseReleaseChannel(Root.pluginVersion),
|
|
7836
7856
|
poweredBy: "Karin",
|
|
7837
7857
|
frameworkVersion: Root.karinVersion,
|
|
7838
7858
|
hasUpdate
|
|
@@ -11413,6 +11433,15 @@ var ViteLogo = ({ className = "w-auto h-12" }) => /* @__PURE__ */ (0, import_jsx
|
|
|
11413
11433
|
* @param props 组件属性
|
|
11414
11434
|
* @returns JSX元素
|
|
11415
11435
|
*/
|
|
11436
|
+
/**
|
|
11437
|
+
* 渠道徽章文案:ctx.version.releaseType → 中文渠道名(未知值回显原值兜底)
|
|
11438
|
+
*/
|
|
11439
|
+
var RELEASE_TYPE_LABEL = {
|
|
11440
|
+
Stable: "正式版",
|
|
11441
|
+
Beta: "测试版",
|
|
11442
|
+
Rc: "预览版",
|
|
11443
|
+
Canary: "金丝雀"
|
|
11444
|
+
};
|
|
11416
11445
|
var DefaultLayout = ({ children, ctx, className = "", style = {} }) => {
|
|
11417
11446
|
const useDarkTheme = isDark(ctx);
|
|
11418
11447
|
const { version } = ctx;
|
|
@@ -11480,21 +11509,21 @@ var DefaultLayout = ({ children, ctx, className = "", style = {} }) => {
|
|
|
11480
11509
|
strokeWidth: 3,
|
|
11481
11510
|
className: "w-4 h-4"
|
|
11482
11511
|
}),
|
|
11483
|
-
!version.hasUpdate && version.releaseType === "
|
|
11512
|
+
!version.hasUpdate && (version.releaseType === "Beta" || version.releaseType === "Rc") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
|
|
11484
11513
|
strokeWidth: 3,
|
|
11485
11514
|
className: "w-4 h-4 text-warning"
|
|
11486
11515
|
}),
|
|
11487
|
-
!version.hasUpdate && version.releaseType
|
|
11516
|
+
!version.hasUpdate && version.releaseType === "Canary" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Info, {
|
|
11488
11517
|
strokeWidth: 3,
|
|
11489
11518
|
className: "w-4 h-4"
|
|
11490
11519
|
}),
|
|
11491
11520
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
11492
|
-
className: cn(version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "
|
|
11493
|
-
children: version.hasUpdate ? "有可用更新" : version.releaseType
|
|
11521
|
+
className: cn(version.hasUpdate && "text-success", !version.hasUpdate && (version.releaseType === "Beta" || version.releaseType === "Rc") && "text-warning"),
|
|
11522
|
+
children: version.hasUpdate ? "有可用更新" : RELEASE_TYPE_LABEL[version.releaseType] ?? version.releaseType
|
|
11494
11523
|
})
|
|
11495
11524
|
]
|
|
11496
11525
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
11497
|
-
className: cn("text-5xl font-bold tracking-wide", version.hasUpdate && "text-success", !version.hasUpdate && version.releaseType === "
|
|
11526
|
+
className: cn("text-5xl font-bold tracking-wide", version.hasUpdate && "text-success", !version.hasUpdate && (version.releaseType === "Beta" || version.releaseType === "Rc") && "text-warning"),
|
|
11498
11527
|
children: ["v", version.pluginVersion]
|
|
11499
11528
|
})]
|
|
11500
11529
|
}),
|
|
@@ -23944,7 +23973,7 @@ var qrlogin_default = defineTemplate({
|
|
|
23944
23973
|
var RuntimeReport = import_react.memo((props) => {
|
|
23945
23974
|
const { data } = props;
|
|
23946
23975
|
const dark = isDark(props.ctx);
|
|
23947
|
-
const releaseLabel = data.identity.releaseType
|
|
23976
|
+
const releaseLabel = RELEASE_TYPE_LABEL[data.identity.releaseType] ?? data.identity.releaseType;
|
|
23948
23977
|
const buildStatus = data.build.state === "matched" ? {
|
|
23949
23978
|
label: "构建信息一致",
|
|
23950
23979
|
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleCheck, { className: "h-8 w-8" }),
|
|
@@ -24412,6 +24441,459 @@ var runtime_default = defineTemplate({
|
|
|
24412
24441
|
component: RuntimeReport
|
|
24413
24442
|
});
|
|
24414
24443
|
//#endregion
|
|
24444
|
+
//#region ktr/template/other/updateHelp/components/updateHelp.tsx
|
|
24445
|
+
/**
|
|
24446
|
+
* `#kkk更新` 用法面板(kkk-design 系统 B × Apple 排版原则)。
|
|
24447
|
+
*
|
|
24448
|
+
* 主情绪色为深青(teal)——紫罗兰系在 runtime/更新日志等模板已被占用,避开色彩同质化。
|
|
24449
|
+
* 构图:横向 Hero 带(左主标题、右当前安装版本,版本号按长度分级缩放防溢出)→
|
|
24450
|
+
* 表格式渠道清单(固定列宽 grid,命令列纵向对齐)→ 命令→说明单行对。
|
|
24451
|
+
* 状态为完整 semver 比较:有更新 / 已是最新 / 低于当前版本三分,而非笼统布尔。
|
|
24452
|
+
* 噪点沿用 runtime 的高对比离散颗粒(深色 0.16 / 浅色 0.12)。
|
|
24453
|
+
*/
|
|
24454
|
+
/** 完整 semver 比较(core 数字 + prerelease 段,规则与 core 的 semver.ts 一致) */
|
|
24455
|
+
var semverCompare = (a, b) => {
|
|
24456
|
+
const parse = (v) => {
|
|
24457
|
+
const [core, pre] = v.trim().replace(/^[vV]/, "").split("+")[0].split("-");
|
|
24458
|
+
const [maj, min, pat] = core.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
24459
|
+
return {
|
|
24460
|
+
maj,
|
|
24461
|
+
min,
|
|
24462
|
+
pat,
|
|
24463
|
+
pre: pre ? pre.split(".") : []
|
|
24464
|
+
};
|
|
24465
|
+
};
|
|
24466
|
+
const p = parse(a);
|
|
24467
|
+
const q = parse(b);
|
|
24468
|
+
if (p.maj !== q.maj) return p.maj - q.maj;
|
|
24469
|
+
if (p.min !== q.min) return p.min - q.min;
|
|
24470
|
+
if (p.pat !== q.pat) return p.pat - q.pat;
|
|
24471
|
+
if (p.pre.length === 0 && q.pre.length === 0) return 0;
|
|
24472
|
+
if (p.pre.length === 0) return 1;
|
|
24473
|
+
if (q.pre.length === 0) return -1;
|
|
24474
|
+
const len = Math.min(p.pre.length, q.pre.length);
|
|
24475
|
+
for (let i = 0; i < len; i++) {
|
|
24476
|
+
const an = /^\d+$/.test(p.pre[i]);
|
|
24477
|
+
const bn = /^\d+$/.test(q.pre[i]);
|
|
24478
|
+
if (an !== bn) return an ? -1 : 1;
|
|
24479
|
+
if (p.pre[i] !== q.pre[i]) {
|
|
24480
|
+
if (an && bn) return Number(p.pre[i]) - Number(q.pre[i]);
|
|
24481
|
+
return p.pre[i] > q.pre[i] ? 1 : -1;
|
|
24482
|
+
}
|
|
24483
|
+
}
|
|
24484
|
+
return p.pre.length === q.pre.length ? 0 : p.pre.length > q.pre.length ? 1 : -1;
|
|
24485
|
+
};
|
|
24486
|
+
/**
|
|
24487
|
+
* Hero 版本号布局:
|
|
24488
|
+
* - 短版本(纯 semver,≤6 字符)与主标题同行横排,150px;
|
|
24489
|
+
* - 长版本(canary 等 prerelease)独占整行堆叠在标题下方,字号按「可用宽 1180px ÷
|
|
24490
|
+
* 等宽字符宽 0.6em」自适应,上限仍 150px——标题与版本号不再挤同一行。
|
|
24491
|
+
*/
|
|
24492
|
+
var heroStacked = (version) => version.trim().replace(/^[vV]/, "").length > 6;
|
|
24493
|
+
var heroVersionSize = (version) => {
|
|
24494
|
+
const len = version.trim().replace(/^[vV]/, "").length;
|
|
24495
|
+
if (len <= 6) return 150;
|
|
24496
|
+
return Math.max(72, Math.min(150, Math.floor(1180 / (len * .6))));
|
|
24497
|
+
};
|
|
24498
|
+
//#endregion
|
|
24499
|
+
//#region ktr/template/other/updateHelp/index.tsx
|
|
24500
|
+
var updateHelp_default = defineTemplate({
|
|
24501
|
+
name: "更新渠道面板",
|
|
24502
|
+
description: "#kkk更新 用法与各渠道可用版本一览",
|
|
24503
|
+
component: import_react.memo((props) => {
|
|
24504
|
+
const { data } = props;
|
|
24505
|
+
const palette = isDark(props.ctx) ? {
|
|
24506
|
+
background: "#081416",
|
|
24507
|
+
glowPrimary: "rgba(45, 212, 191, 0.28)",
|
|
24508
|
+
glowSecondary: "rgba(56, 130, 246, 0.14)",
|
|
24509
|
+
glowWarm: "rgba(250, 204, 21, 0.12)",
|
|
24510
|
+
bgWord: "#99f6e4",
|
|
24511
|
+
ink: "#effefd",
|
|
24512
|
+
muted: "rgba(239, 254, 253, 0.62)",
|
|
24513
|
+
faint: "rgba(239, 254, 253, 0.36)",
|
|
24514
|
+
pillBg: "rgba(45, 212, 191, 0.12)",
|
|
24515
|
+
pillBorder: "rgba(94, 234, 212, 0.32)",
|
|
24516
|
+
pillText: "#5eead4",
|
|
24517
|
+
accentText: "#5eead4",
|
|
24518
|
+
success: "#4ade80",
|
|
24519
|
+
warning: "#fbbf24",
|
|
24520
|
+
noiseOpacity: .16
|
|
24521
|
+
} : {
|
|
24522
|
+
background: "#effaf8",
|
|
24523
|
+
glowPrimary: "rgba(20, 184, 166, 0.26)",
|
|
24524
|
+
glowSecondary: "rgba(125, 211, 252, 0.40)",
|
|
24525
|
+
glowWarm: "rgba(250, 204, 21, 0.26)",
|
|
24526
|
+
bgWord: "#0c3b38",
|
|
24527
|
+
ink: "#0c3b38",
|
|
24528
|
+
muted: "rgba(12, 59, 56, 0.68)",
|
|
24529
|
+
faint: "rgba(12, 59, 56, 0.42)",
|
|
24530
|
+
pillBg: "rgba(20, 184, 166, 0.10)",
|
|
24531
|
+
pillBorder: "rgba(20, 184, 166, 0.30)",
|
|
24532
|
+
pillText: "#0f766e",
|
|
24533
|
+
accentText: "#0d9488",
|
|
24534
|
+
success: "#15803d",
|
|
24535
|
+
warning: "#8a5a06",
|
|
24536
|
+
noiseOpacity: .12
|
|
24537
|
+
};
|
|
24538
|
+
/**
|
|
24539
|
+
* 渠道状态:文案按具体状态区分(有更新 / 已是最新 / 低于当前版本 / 暂未发布 / 获取失败),
|
|
24540
|
+
* 颜色只分两档 —— 可升级(success)与置灰(faint):非可升级状态一律不引导行动。
|
|
24541
|
+
* active 供行内所有元素同步置灰。
|
|
24542
|
+
*/
|
|
24543
|
+
const statusView = (channel) => {
|
|
24544
|
+
if (channel.status === "missing") return {
|
|
24545
|
+
dot: palette.faint,
|
|
24546
|
+
text: "该渠道暂未发布",
|
|
24547
|
+
active: false
|
|
24548
|
+
};
|
|
24549
|
+
if (channel.status === "error") return {
|
|
24550
|
+
dot: palette.faint,
|
|
24551
|
+
text: "获取失败",
|
|
24552
|
+
active: false
|
|
24553
|
+
};
|
|
24554
|
+
if (channel.status === "canary") return {
|
|
24555
|
+
dot: palette.accentText,
|
|
24556
|
+
text: "main 分支构建",
|
|
24557
|
+
active: true
|
|
24558
|
+
};
|
|
24559
|
+
const order = semverCompare(channel.version ?? "0.0.0", data.currentVersion);
|
|
24560
|
+
if (order > 0) return {
|
|
24561
|
+
dot: palette.success,
|
|
24562
|
+
text: "有更新可升级",
|
|
24563
|
+
active: true
|
|
24564
|
+
};
|
|
24565
|
+
if (order === 0) return {
|
|
24566
|
+
dot: palette.faint,
|
|
24567
|
+
text: "已是最新",
|
|
24568
|
+
active: false
|
|
24569
|
+
};
|
|
24570
|
+
return {
|
|
24571
|
+
dot: palette.faint,
|
|
24572
|
+
text: "低于当前版本",
|
|
24573
|
+
active: false
|
|
24574
|
+
};
|
|
24575
|
+
};
|
|
24576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DefaultLayout, {
|
|
24577
|
+
...props,
|
|
24578
|
+
className: "relative min-h-440 overflow-hidden",
|
|
24579
|
+
style: { backgroundColor: palette.background },
|
|
24580
|
+
children: [
|
|
24581
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24582
|
+
className: "pointer-events-none absolute inset-0 z-0 overflow-hidden",
|
|
24583
|
+
children: [
|
|
24584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24585
|
+
className: "absolute -left-130 -top-120 h-337.5 w-375 rounded-full blur-[230px]",
|
|
24586
|
+
style: { background: `radial-gradient(ellipse at center, ${palette.glowPrimary} 0%, transparent 70%)` }
|
|
24587
|
+
}),
|
|
24588
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24589
|
+
className: "absolute -right-130 top-[36%] h-312.5 w-300 rounded-full blur-[240px]",
|
|
24590
|
+
style: { background: `radial-gradient(ellipse at center, ${palette.glowSecondary} 0%, transparent 72%)` }
|
|
24591
|
+
}),
|
|
24592
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24593
|
+
className: "absolute -bottom-120 -left-80 h-287.5 w-337.5 rounded-full blur-[260px]",
|
|
24594
|
+
style: { background: `radial-gradient(ellipse at center, ${palette.glowWarm} 0%, transparent 72%)` }
|
|
24595
|
+
}),
|
|
24596
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24597
|
+
className: "pointer-events-none absolute right-14 top-8 select-none font-bold leading-none tracking-[-0.02em]",
|
|
24598
|
+
style: {
|
|
24599
|
+
fontSize: "220px",
|
|
24600
|
+
opacity: .04,
|
|
24601
|
+
color: palette.bgWord
|
|
24602
|
+
},
|
|
24603
|
+
children: "UPDATE"
|
|
24604
|
+
})
|
|
24605
|
+
]
|
|
24606
|
+
}),
|
|
24607
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24608
|
+
className: "pointer-events-none absolute inset-0 z-0",
|
|
24609
|
+
style: { opacity: palette.noiseOpacity },
|
|
24610
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
24611
|
+
className: "h-full w-full",
|
|
24612
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
24613
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("filter", {
|
|
24614
|
+
id: "updateHelpNoise",
|
|
24615
|
+
x: "0%",
|
|
24616
|
+
y: "0%",
|
|
24617
|
+
width: "100%",
|
|
24618
|
+
height: "100%",
|
|
24619
|
+
children: [
|
|
24620
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feTurbulence", {
|
|
24621
|
+
type: "fractalNoise",
|
|
24622
|
+
baseFrequency: "0.8",
|
|
24623
|
+
numOctaves: "1",
|
|
24624
|
+
stitchTiles: "stitch",
|
|
24625
|
+
result: "noise"
|
|
24626
|
+
}),
|
|
24627
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", {
|
|
24628
|
+
type: "saturate",
|
|
24629
|
+
values: "0",
|
|
24630
|
+
result: "gray"
|
|
24631
|
+
}),
|
|
24632
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("feComponentTransfer", { children: [
|
|
24633
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncR", {
|
|
24634
|
+
type: "discrete",
|
|
24635
|
+
tableValues: "0 1"
|
|
24636
|
+
}),
|
|
24637
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncG", {
|
|
24638
|
+
type: "discrete",
|
|
24639
|
+
tableValues: "0 1"
|
|
24640
|
+
}),
|
|
24641
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feFuncB", {
|
|
24642
|
+
type: "discrete",
|
|
24643
|
+
tableValues: "0 1"
|
|
24644
|
+
})
|
|
24645
|
+
] })
|
|
24646
|
+
]
|
|
24647
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
|
|
24648
|
+
width: "100%",
|
|
24649
|
+
height: "100%",
|
|
24650
|
+
filter: "url(#updateHelpNoise)"
|
|
24651
|
+
})]
|
|
24652
|
+
})
|
|
24653
|
+
}),
|
|
24654
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
|
|
24655
|
+
className: "relative z-10 px-22 pb-16 pt-20",
|
|
24656
|
+
children: [
|
|
24657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
|
|
24658
|
+
className: "relative flex items-center justify-between gap-12",
|
|
24659
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24660
|
+
className: "flex items-center gap-4",
|
|
24661
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24662
|
+
className: "h-3 w-3 rounded-full",
|
|
24663
|
+
style: { background: palette.accentText }
|
|
24664
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24665
|
+
className: "whitespace-nowrap text-[24px] font-bold tracking-[0.28em] text-foreground/44",
|
|
24666
|
+
children: "更新面板 · UPDATE PANEL"
|
|
24667
|
+
})]
|
|
24668
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24669
|
+
className: "whitespace-nowrap rounded-full border px-6 py-2 text-[22px] font-bold tracking-[0.14em]",
|
|
24670
|
+
style: {
|
|
24671
|
+
borderColor: palette.pillBorder,
|
|
24672
|
+
background: palette.pillBg,
|
|
24673
|
+
color: palette.pillText
|
|
24674
|
+
},
|
|
24675
|
+
children: data.currentChannel
|
|
24676
|
+
})]
|
|
24677
|
+
}),
|
|
24678
|
+
heroStacked(data.currentVersion) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
|
|
24679
|
+
className: "whitespace-nowrap text-[96px] font-bold leading-[1.04] tracking-[-0.02em] text-foreground",
|
|
24680
|
+
children: "更新渠道"
|
|
24681
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
24682
|
+
className: "mt-6 whitespace-nowrap text-[30px] font-semibold text-foreground/48",
|
|
24683
|
+
children: data.currentChannel === "金丝雀" ? "金丝雀构建跟随 main 分支实时发布,可随时切换回正式渠道" : "各渠道可用版本与 #kkk更新 用法一览"
|
|
24684
|
+
})] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24685
|
+
className: "relative mt-14",
|
|
24686
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24687
|
+
className: "text-[22px] font-bold uppercase tracking-[0.22em] text-foreground/36",
|
|
24688
|
+
children: "当前安装 · INSTALLED"
|
|
24689
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24690
|
+
className: "mt-4 whitespace-nowrap font-mono font-bold leading-none tracking-[-0.05em] tabular-nums text-foreground",
|
|
24691
|
+
style: { fontSize: `${heroVersionSize(data.currentVersion)}px` },
|
|
24692
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24693
|
+
className: "mr-3 align-top text-[0.42em] font-bold text-foreground/40",
|
|
24694
|
+
children: "v"
|
|
24695
|
+
}), data.currentVersion]
|
|
24696
|
+
})]
|
|
24697
|
+
})] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24698
|
+
className: "relative mt-14 flex items-end justify-between gap-12",
|
|
24699
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
|
|
24700
|
+
className: "whitespace-nowrap text-[96px] font-bold leading-[1.04] tracking-[-0.02em] text-foreground",
|
|
24701
|
+
children: "更新渠道"
|
|
24702
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
24703
|
+
className: "mt-6 whitespace-nowrap text-[30px] font-semibold text-foreground/48",
|
|
24704
|
+
children: data.currentChannel === "金丝雀" ? "金丝雀构建跟随 main 分支实时发布,可随时切换回正式渠道" : "各渠道可用版本与 #kkk更新 用法一览"
|
|
24705
|
+
})] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24706
|
+
className: "flex shrink-0 flex-col items-end",
|
|
24707
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24708
|
+
className: "text-[22px] font-bold uppercase tracking-[0.22em] text-foreground/36",
|
|
24709
|
+
children: "当前安装 · INSTALLED"
|
|
24710
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24711
|
+
className: "mt-4 whitespace-nowrap font-mono font-bold leading-none tracking-[-0.05em] tabular-nums text-foreground",
|
|
24712
|
+
style: { fontSize: `${heroVersionSize(data.currentVersion)}px` },
|
|
24713
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24714
|
+
className: "mr-3 align-top text-[0.42em] font-bold text-foreground/40",
|
|
24715
|
+
children: "v"
|
|
24716
|
+
}), data.currentVersion]
|
|
24717
|
+
})]
|
|
24718
|
+
})]
|
|
24719
|
+
}),
|
|
24720
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
24721
|
+
className: "relative mt-24",
|
|
24722
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24723
|
+
className: "flex items-center gap-4",
|
|
24724
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24725
|
+
className: "h-3 w-3 rounded-full",
|
|
24726
|
+
style: { background: palette.accentText }
|
|
24727
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24728
|
+
className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
|
|
24729
|
+
children: "可用版本 · AVAILABLE"
|
|
24730
|
+
})]
|
|
24731
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24732
|
+
className: "mt-12 flex flex-col gap-14",
|
|
24733
|
+
children: data.channels.map((channel) => {
|
|
24734
|
+
const status = statusView(channel);
|
|
24735
|
+
const publishedDate = channel.publishedAt ? new Date(channel.publishedAt) : void 0;
|
|
24736
|
+
if (channel.status === "canary") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24737
|
+
className: "flex flex-col gap-4",
|
|
24738
|
+
children: [
|
|
24739
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24740
|
+
className: "flex items-center justify-between gap-10",
|
|
24741
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24742
|
+
className: "flex items-center gap-4",
|
|
24743
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24744
|
+
className: "whitespace-nowrap text-[30px] font-semibold",
|
|
24745
|
+
style: { color: status.active ? palette.muted : palette.faint },
|
|
24746
|
+
children: channel.label
|
|
24747
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24748
|
+
className: "whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
|
|
24749
|
+
style: {
|
|
24750
|
+
borderColor: palette.pillBorder,
|
|
24751
|
+
background: palette.pillBg,
|
|
24752
|
+
color: status.active ? palette.pillText : palette.faint
|
|
24753
|
+
},
|
|
24754
|
+
children: channel.tag
|
|
24755
|
+
})]
|
|
24756
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24757
|
+
className: "flex items-center gap-6",
|
|
24758
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24759
|
+
className: "whitespace-nowrap font-mono text-[46px] font-bold leading-none",
|
|
24760
|
+
style: { color: status.active ? palette.ink : palette.faint },
|
|
24761
|
+
children: channel.version
|
|
24762
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
24763
|
+
className: "flex items-center gap-3 whitespace-nowrap text-[24px] font-semibold",
|
|
24764
|
+
style: { color: status.dot },
|
|
24765
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24766
|
+
className: "h-2.5 w-2.5 rounded-full",
|
|
24767
|
+
style: { background: status.dot }
|
|
24768
|
+
}), status.text]
|
|
24769
|
+
})]
|
|
24770
|
+
})]
|
|
24771
|
+
}),
|
|
24772
|
+
channel.installCommand && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24773
|
+
className: "whitespace-nowrap rounded-3xl px-7 py-4 font-mono text-[27px] font-semibold",
|
|
24774
|
+
style: {
|
|
24775
|
+
background: status.active ? palette.pillBg : "transparent",
|
|
24776
|
+
color: status.active ? palette.pillText : palette.faint
|
|
24777
|
+
},
|
|
24778
|
+
children: channel.installCommand
|
|
24779
|
+
}),
|
|
24780
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24781
|
+
className: "flex items-center justify-between gap-10 whitespace-nowrap",
|
|
24782
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
24783
|
+
className: "text-[24px] text-foreground/42",
|
|
24784
|
+
children: ["发布于 ", publishedDate && format(publishedDate, "yyyy/MM/dd HH:mm")]
|
|
24785
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24786
|
+
className: "font-mono text-[24px] font-semibold",
|
|
24787
|
+
style: { color: palette.faint },
|
|
24788
|
+
title: channel.publishedAt,
|
|
24789
|
+
children: publishedDate && formatDistanceToNow(publishedDate, {
|
|
24790
|
+
addSuffix: true,
|
|
24791
|
+
locale: zhCN
|
|
24792
|
+
})
|
|
24793
|
+
})]
|
|
24794
|
+
})
|
|
24795
|
+
]
|
|
24796
|
+
}, channel.tag);
|
|
24797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24798
|
+
className: "grid grid-cols-[11rem_1fr_auto] items-center gap-8",
|
|
24799
|
+
children: [
|
|
24800
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24801
|
+
className: "flex flex-col gap-2",
|
|
24802
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24803
|
+
className: "whitespace-nowrap text-[30px] font-semibold",
|
|
24804
|
+
style: { color: status.active ? palette.muted : palette.faint },
|
|
24805
|
+
children: channel.label
|
|
24806
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24807
|
+
className: "w-fit whitespace-nowrap rounded-full border px-4 py-0.5 font-mono text-[20px] font-semibold",
|
|
24808
|
+
style: {
|
|
24809
|
+
borderColor: palette.pillBorder,
|
|
24810
|
+
background: palette.pillBg,
|
|
24811
|
+
color: status.active ? palette.pillText : palette.faint
|
|
24812
|
+
},
|
|
24813
|
+
children: channel.tag
|
|
24814
|
+
})]
|
|
24815
|
+
}),
|
|
24816
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24817
|
+
className: "whitespace-nowrap font-mono text-[24px] font-semibold",
|
|
24818
|
+
style: { color: status.active ? palette.muted : palette.faint },
|
|
24819
|
+
children: channel.command
|
|
24820
|
+
}),
|
|
24821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24822
|
+
className: "flex flex-col items-end gap-2.5 whitespace-nowrap",
|
|
24823
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24824
|
+
className: "font-mono text-[56px] font-bold leading-none tracking-[-0.02em] tabular-nums",
|
|
24825
|
+
style: { color: status.active ? palette.ink : palette.faint },
|
|
24826
|
+
children: channel.status === "ok" ? `v${channel.version}` : "—"
|
|
24827
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
24828
|
+
className: "flex items-center gap-3 text-[24px] font-semibold",
|
|
24829
|
+
style: { color: status.dot },
|
|
24830
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24831
|
+
className: "h-2.5 w-2.5 rounded-full",
|
|
24832
|
+
style: { background: status.dot }
|
|
24833
|
+
}), status.text]
|
|
24834
|
+
})]
|
|
24835
|
+
})
|
|
24836
|
+
]
|
|
24837
|
+
}, channel.tag);
|
|
24838
|
+
})
|
|
24839
|
+
})]
|
|
24840
|
+
}),
|
|
24841
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
24842
|
+
className: "relative mt-28",
|
|
24843
|
+
children: [
|
|
24844
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24845
|
+
className: "flex items-center gap-4",
|
|
24846
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24847
|
+
className: "h-3 w-3 rounded-full",
|
|
24848
|
+
style: { background: palette.accentText }
|
|
24849
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24850
|
+
className: "text-[24px] font-bold tracking-[0.28em] text-foreground/44",
|
|
24851
|
+
children: "用法 · COMMANDS"
|
|
24852
|
+
})]
|
|
24853
|
+
}),
|
|
24854
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
24855
|
+
className: "mt-12 flex flex-col gap-10",
|
|
24856
|
+
children: [
|
|
24857
|
+
{
|
|
24858
|
+
command: "#kkk更新",
|
|
24859
|
+
desc: "更新到最新正式版"
|
|
24860
|
+
},
|
|
24861
|
+
{
|
|
24862
|
+
command: "#kkk更新rc",
|
|
24863
|
+
desc: "更新到预览渠道最新版"
|
|
24864
|
+
},
|
|
24865
|
+
{
|
|
24866
|
+
command: "#kkk更新beta",
|
|
24867
|
+
desc: "更新到测试渠道最新版"
|
|
24868
|
+
},
|
|
24869
|
+
{
|
|
24870
|
+
command: "#kkk更新<版本号>",
|
|
24871
|
+
desc: "更新到指定 stable 版本,例如 #kkk更新2.45.0"
|
|
24872
|
+
}
|
|
24873
|
+
].map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24874
|
+
className: "grid grid-cols-[24rem_1fr] items-baseline gap-8",
|
|
24875
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24876
|
+
className: "whitespace-nowrap font-mono text-[34px] font-bold text-foreground",
|
|
24877
|
+
children: item.command
|
|
24878
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
24879
|
+
className: "whitespace-nowrap text-[26px] font-semibold text-foreground/48",
|
|
24880
|
+
children: item.desc
|
|
24881
|
+
})]
|
|
24882
|
+
}, item.command))
|
|
24883
|
+
}),
|
|
24884
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
24885
|
+
className: "mt-16 flex flex-col gap-2 whitespace-nowrap font-mono text-[22px] font-semibold text-foreground/28",
|
|
24886
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "金丝雀版本经 pkg.pr.new 分发,不提供渠道订阅与更新推送" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "指定低于当前安装版本的版本号属于降级,需回复「确认」才会执行" })]
|
|
24887
|
+
})
|
|
24888
|
+
]
|
|
24889
|
+
})
|
|
24890
|
+
]
|
|
24891
|
+
})
|
|
24892
|
+
]
|
|
24893
|
+
});
|
|
24894
|
+
})
|
|
24895
|
+
});
|
|
24896
|
+
//#endregion
|
|
24415
24897
|
//#region ktr/template/other/version_warning/components/VersionWarning.tsx
|
|
24416
24898
|
var VersionWarning = (props) => {
|
|
24417
24899
|
const dark = isDark(props.ctx);
|
|
@@ -28329,6 +28811,7 @@ var templates = {
|
|
|
28329
28811
|
"other/live-photo-tip": live_photo_tip_default,
|
|
28330
28812
|
"other/qrlogin": qrlogin_default,
|
|
28331
28813
|
"other/runtime": runtime_default,
|
|
28814
|
+
"other/updateHelp": updateHelp_default,
|
|
28332
28815
|
"other/version_warning": version_warning_default,
|
|
28333
28816
|
"statistics/global": global_default,
|
|
28334
28817
|
"statistics/group": group_default,
|
|
@@ -38114,7 +38597,7 @@ var collectRuntimeReport = (event) => {
|
|
|
38114
38597
|
pluginName: Root.pluginName,
|
|
38115
38598
|
pluginVersion: Root.pluginVersion,
|
|
38116
38599
|
karinVersion: Root.karinVersion || "未知",
|
|
38117
|
-
releaseType:
|
|
38600
|
+
releaseType: parseReleaseChannel(Root.pluginVersion),
|
|
38118
38601
|
requiredNodeVersion: packageMetadata.engines?.node ?? "未声明",
|
|
38119
38602
|
requiredKarinVersion: packageMetadata.karin?.engines ?? packageMetadata.engines?.karin ?? "未声明"
|
|
38120
38603
|
},
|
|
@@ -39928,6 +40411,7 @@ var getChangelogImage = async (ctx, props) => {
|
|
|
39928
40411
|
const localMeta = getBuildMetadata();
|
|
39929
40412
|
if (localMeta?.buildTime) buildTime = formatBuildTime(localMeta.buildTime);
|
|
39930
40413
|
}
|
|
40414
|
+
changelog = changelog.replace(/^(## \[\d+\.\d+\.\d+-[^\]]+\][^\r\n]*)/gm, "$1 「测试版」");
|
|
39931
40415
|
return await Render(event, "other/changelog", {
|
|
39932
40416
|
markdown: changelog,
|
|
39933
40417
|
Tip: props.Tip,
|
|
@@ -39941,32 +40425,34 @@ var getChangelogImage = async (ctx, props) => {
|
|
|
39941
40425
|
//#endregion
|
|
39942
40426
|
//#region src/apps/update.ts
|
|
39943
40427
|
var UPDATE_LOCK_KEY = "kkk:update:lock";
|
|
39944
|
-
var UPDATE_MSGID_KEY = "kkk:update:
|
|
40428
|
+
var UPDATE_MSGID_KEY = "kkk:update:msgid";
|
|
39945
40429
|
/**
|
|
39946
40430
|
* 定时更新检测处理器
|
|
39947
|
-
*
|
|
39948
|
-
*
|
|
40431
|
+
* 按订阅渠道检查远程版本(latest 恒参与 —— 装 prerelease 的用户也要收到转正提醒),
|
|
40432
|
+
* 候选取 semver 最大且大于本地者,渲染变更日志并私聊通知所有主人。
|
|
39949
40433
|
*
|
|
39950
40434
|
* @returns 是否继续后续任务
|
|
39951
40435
|
*/
|
|
39952
40436
|
var Handler = async () => {
|
|
39953
|
-
|
|
39954
|
-
|
|
39955
|
-
|
|
39956
|
-
|
|
39957
|
-
|
|
39958
|
-
|
|
39959
|
-
|
|
39960
|
-
|
|
40437
|
+
const tags = ["latest", ...(Config.app.UpdateNotifyChannels?.length ? Config.app.UpdateNotifyChannels : ["stable"]).filter((c) => c !== "stable")];
|
|
40438
|
+
const remotes = await Promise.all(tags.map(async (tag) => {
|
|
40439
|
+
try {
|
|
40440
|
+
return await getRemotePkgVersion(Root.pluginName, tag) || null;
|
|
40441
|
+
} catch {
|
|
40442
|
+
return null;
|
|
40443
|
+
}
|
|
40444
|
+
}));
|
|
40445
|
+
const remote = [...new Set(remotes.filter((v) => !!v))].filter((v) => isSemverGreater(v, Root.pluginVersion)).sort((a, b) => isSemverGreater(b, a) ? 1 : -1)[0];
|
|
40446
|
+
if (!remote) return true;
|
|
39961
40447
|
try {
|
|
39962
40448
|
const lockedVersion = await db.get(UPDATE_LOCK_KEY);
|
|
39963
40449
|
if (typeof lockedVersion === "string" && lockedVersion.length > 0) {
|
|
39964
40450
|
if (!isSemverGreater(lockedVersion, Root.pluginVersion)) await db.del(UPDATE_LOCK_KEY);
|
|
39965
|
-
else if (!isSemverGreater(
|
|
40451
|
+
else if (!isSemverGreater(remote, lockedVersion)) return true;
|
|
39966
40452
|
}
|
|
39967
40453
|
} catch {}
|
|
39968
40454
|
try {
|
|
39969
|
-
await db.set(UPDATE_LOCK_KEY,
|
|
40455
|
+
await db.set(UPDATE_LOCK_KEY, remote);
|
|
39970
40456
|
} catch {}
|
|
39971
40457
|
const masters = config.master().filter((id) => id !== "console");
|
|
39972
40458
|
if (masters.length === 0) return true;
|
|
@@ -39977,9 +40463,7 @@ var Handler = async () => {
|
|
|
39977
40463
|
try {
|
|
39978
40464
|
const list = await item.bot.getFriendList();
|
|
39979
40465
|
friendsMap.set(item.bot.account.selfId, list || []);
|
|
39980
|
-
} catch {
|
|
39981
|
-
friendsMap.set(item.bot.account.selfId, []);
|
|
39982
|
-
}
|
|
40466
|
+
} catch {}
|
|
39983
40467
|
}));
|
|
39984
40468
|
const masterToBot = /* @__PURE__ */ new Map();
|
|
39985
40469
|
for (const owner of masters) {
|
|
@@ -39991,7 +40475,7 @@ var Handler = async () => {
|
|
|
39991
40475
|
if (!Array.from(masterToBot.entries()).some(([, b]) => b.account.selfId === item.bot.account.selfId)) continue;
|
|
39992
40476
|
const img = await getChangelogImage({ bot: item.bot }, {
|
|
39993
40477
|
localVersion: Root.pluginVersion,
|
|
39994
|
-
remoteVersion:
|
|
40478
|
+
remoteVersion: remote,
|
|
39995
40479
|
Tip: true
|
|
39996
40480
|
});
|
|
39997
40481
|
if (img && img.length > 0) botToImage.set(item.bot.account.selfId, [segment.text("karin-plugin-kkk 有新的更新!"), ...img]);
|
|
@@ -40033,39 +40517,191 @@ var kkkUpdate = hooks.message.friend(async (e, next) => {
|
|
|
40033
40517
|
}
|
|
40034
40518
|
next();
|
|
40035
40519
|
}, { priority: 100 });
|
|
40520
|
+
/** 解析 #kkk更新 的可选参数:缺省/stable=正式版,beta/rc=渠道 tag,其余识别为版本号 */
|
|
40521
|
+
var parseUpdateArg = (arg) => {
|
|
40522
|
+
if (!arg) return { type: "latest" };
|
|
40523
|
+
if (arg === "stable" || arg === "latest") return { type: "latest" };
|
|
40524
|
+
if (arg === "beta" || arg === "rc") return {
|
|
40525
|
+
type: "tag",
|
|
40526
|
+
tag: arg
|
|
40527
|
+
};
|
|
40528
|
+
if (/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(arg)) return {
|
|
40529
|
+
type: "version",
|
|
40530
|
+
version: arg
|
|
40531
|
+
};
|
|
40532
|
+
return { type: "unknown" };
|
|
40533
|
+
};
|
|
40534
|
+
/** 解析目标版本号:latest / 渠道 tag 取对应 dist-tag,指定版本号校验存在性 */
|
|
40535
|
+
var resolveUpdateTarget = async (parsed) => {
|
|
40536
|
+
if (parsed.type === "latest") {
|
|
40537
|
+
const version = await getRemotePkgVersion(Root.pluginName).catch(() => "");
|
|
40538
|
+
return version ? {
|
|
40539
|
+
version,
|
|
40540
|
+
tag: "latest"
|
|
40541
|
+
} : { error: "获取远程版本失败" };
|
|
40542
|
+
}
|
|
40543
|
+
if (parsed.type === "tag") {
|
|
40544
|
+
const version = await getRemotePkgVersion(Root.pluginName, parsed.tag).catch(() => "");
|
|
40545
|
+
return version ? {
|
|
40546
|
+
version,
|
|
40547
|
+
tag: parsed.tag
|
|
40548
|
+
} : { error: `渠道 ${parsed.tag} 暂无可用版本` };
|
|
40549
|
+
}
|
|
40550
|
+
if (parsed.type === "version") {
|
|
40551
|
+
const { status, stdout } = await exec(`npm view ${Root.pluginName}@${parsed.version} version`);
|
|
40552
|
+
const found = status ? stdout.toString().trim() : "";
|
|
40553
|
+
return found ? {
|
|
40554
|
+
version: found,
|
|
40555
|
+
tag: ""
|
|
40556
|
+
} : { error: `版本 ${parsed.version} 不存在` };
|
|
40557
|
+
}
|
|
40558
|
+
return { error: "未识别的渠道或版本" };
|
|
40559
|
+
};
|
|
40560
|
+
/** 安装指定版本并重启(含降级;调用前必须已完成二次确认) */
|
|
40561
|
+
var installAndRestart = async (e, version) => {
|
|
40562
|
+
await e.reply(`开始更新 karin-plugin-kkk → ${version} ......`, { reply: true });
|
|
40563
|
+
const { error } = await exec(`pnpm up ${Root.pluginName}@${version}`);
|
|
40564
|
+
if (error) {
|
|
40565
|
+
e.reply(`${Root.pluginName} 更新失败: ${error}`, { reply: true });
|
|
40566
|
+
return;
|
|
40567
|
+
}
|
|
40568
|
+
const installed = await getPkgVersion(Root.pluginName);
|
|
40569
|
+
if (installed !== version) {
|
|
40570
|
+
e.reply(`更新失败:安装后版本为 ${installed},预期 ${version}。可尝试手动执行 pnpm up ${Root.pluginName}@${version}`, { reply: true });
|
|
40571
|
+
return;
|
|
40572
|
+
}
|
|
40573
|
+
const msgResult = await e.reply(`${Root.pluginName} 更新成功!→ ${version}\n开始执行重启......`);
|
|
40574
|
+
if (msgResult.messageId) try {
|
|
40575
|
+
await db.del(UPDATE_MSGID_KEY);
|
|
40576
|
+
await db.del(UPDATE_LOCK_KEY);
|
|
40577
|
+
} catch {}
|
|
40578
|
+
await restart(e.selfId, e.contact, msgResult.messageId);
|
|
40579
|
+
};
|
|
40580
|
+
/** pkg.pr.new 仓库(金丝雀数据源,只跟踪 main 分支构建) */
|
|
40581
|
+
var PKG_PR_NEW_REPO = "ikenxuan/karin-plugin-kkk";
|
|
40582
|
+
/** 拉取 pkg.pr.new 上 main 分支的最新金丝雀构建(失败返回 null,由调用方降级展示) */
|
|
40583
|
+
var fetchLatestCanary = async () => {
|
|
40584
|
+
try {
|
|
40585
|
+
const [owner, repo] = PKG_PR_NEW_REPO.split("/");
|
|
40586
|
+
const nodes = (await axios.get(`https://pkg.pr.new/api/repo/commits?owner=${owner}&repo=${repo}`, { timeout: 1e4 })).data?.target?.history?.nodes;
|
|
40587
|
+
if (!Array.isArray(nodes)) return null;
|
|
40588
|
+
const node = nodes.find((n) => n.branch === "main" && n.statusCheckRollup?.contexts?.nodes?.some((c) => c.packages?.some((pkg) => pkg.installUrl)));
|
|
40589
|
+
const pkg = node?.statusCheckRollup?.contexts?.nodes?.flatMap((c) => c.packages ?? []).find((p) => p.installUrl);
|
|
40590
|
+
if (!node?.abbreviatedOid || !pkg?.installUrl) return null;
|
|
40591
|
+
return {
|
|
40592
|
+
label: "金丝雀",
|
|
40593
|
+
tag: "pkg.pr.new · main",
|
|
40594
|
+
status: "canary",
|
|
40595
|
+
version: node.abbreviatedOid.slice(0, 7),
|
|
40596
|
+
installCommand: `pnpm add ${pkg.installUrl} -w`,
|
|
40597
|
+
publishedAt: node.authoredDate,
|
|
40598
|
+
commitMessage: node.message?.slice(0, 40)
|
|
40599
|
+
};
|
|
40600
|
+
} catch {
|
|
40601
|
+
return null;
|
|
40602
|
+
}
|
|
40603
|
+
};
|
|
40604
|
+
/** 渲染 #kkk更新 用法面板(含各渠道可用版本) */
|
|
40605
|
+
var getUpdateHelpImage = async (e) => {
|
|
40606
|
+
const { status, stdout } = await exec(`npm view ${Root.pluginName} dist-tags --json`);
|
|
40607
|
+
let distTags = {};
|
|
40608
|
+
if (status) try {
|
|
40609
|
+
distTags = JSON.parse(stdout.toString());
|
|
40610
|
+
} catch {}
|
|
40611
|
+
const channels = [
|
|
40612
|
+
{
|
|
40613
|
+
label: "正式版",
|
|
40614
|
+
tag: "latest",
|
|
40615
|
+
command: "#kkk更新"
|
|
40616
|
+
},
|
|
40617
|
+
{
|
|
40618
|
+
label: "预览版",
|
|
40619
|
+
tag: "rc",
|
|
40620
|
+
command: "#kkk更新rc"
|
|
40621
|
+
},
|
|
40622
|
+
{
|
|
40623
|
+
label: "测试版",
|
|
40624
|
+
tag: "beta",
|
|
40625
|
+
command: "#kkk更新beta"
|
|
40626
|
+
}
|
|
40627
|
+
].map((def) => {
|
|
40628
|
+
if (!status) return {
|
|
40629
|
+
...def,
|
|
40630
|
+
status: "error"
|
|
40631
|
+
};
|
|
40632
|
+
const version = distTags[def.tag];
|
|
40633
|
+
if (!version) return {
|
|
40634
|
+
...def,
|
|
40635
|
+
status: "missing"
|
|
40636
|
+
};
|
|
40637
|
+
return {
|
|
40638
|
+
...def,
|
|
40639
|
+
status: "ok",
|
|
40640
|
+
version,
|
|
40641
|
+
hasUpdate: isSemverGreater(version, Root.pluginVersion)
|
|
40642
|
+
};
|
|
40643
|
+
});
|
|
40644
|
+
channels.push(await fetchLatestCanary() ?? {
|
|
40645
|
+
label: "金丝雀",
|
|
40646
|
+
tag: "pkg.pr.new · main",
|
|
40647
|
+
status: "error"
|
|
40648
|
+
});
|
|
40649
|
+
return await Render(e, "other/updateHelp", {
|
|
40650
|
+
currentVersion: Root.pluginVersion,
|
|
40651
|
+
currentChannel: RELEASE_CHANNEL_LABEL[parseReleaseChannel(Root.pluginVersion)],
|
|
40652
|
+
channels
|
|
40653
|
+
});
|
|
40654
|
+
};
|
|
40036
40655
|
var handleKkkUpdate = wrapWithErrorHandler(async (e) => {
|
|
40037
|
-
const
|
|
40038
|
-
|
|
40039
|
-
|
|
40656
|
+
const arg = /^#?kkk更新(?:\s*(\S+))?$/.exec(e.msg)?.[1];
|
|
40657
|
+
const parsed = parseUpdateArg(arg);
|
|
40658
|
+
if (parsed.type === "unknown") {
|
|
40659
|
+
const img = await getUpdateHelpImage(e).catch(() => null);
|
|
40660
|
+
if (img && img.length > 0) e.reply(img, { reply: true });
|
|
40661
|
+
else e.reply("渲染更新面板失败。用法:#kkk更新 | #kkk更新beta | #kkk更新rc | #kkk更新<版本号>", { reply: true });
|
|
40040
40662
|
return;
|
|
40041
40663
|
}
|
|
40042
|
-
|
|
40043
|
-
|
|
40664
|
+
const resolved = await resolveUpdateTarget(parsed);
|
|
40665
|
+
if ("error" in resolved) {
|
|
40666
|
+
e.reply(resolved.error, { reply: true });
|
|
40044
40667
|
return;
|
|
40045
40668
|
}
|
|
40046
|
-
|
|
40047
|
-
|
|
40669
|
+
const { version: remote } = resolved;
|
|
40670
|
+
const local = Root.pluginVersion;
|
|
40671
|
+
if (remote === local) {
|
|
40672
|
+
e.reply(`当前已是该版本:${local}`, { reply: true });
|
|
40673
|
+
return;
|
|
40674
|
+
}
|
|
40675
|
+
if (!isSemverGreater(remote, local)) {
|
|
40676
|
+
e.reply([
|
|
40677
|
+
`⚠️ 检测到降级更新:当前 ${local} → 目标 ${remote}`,
|
|
40678
|
+
"降级可能带来配置或数据兼容问题,请确认你知道自己在做什么。",
|
|
40679
|
+
"回复「确认」继续更新,回复其他内容放弃(2 分钟内有效)。"
|
|
40680
|
+
].join("\n"), { reply: true });
|
|
40681
|
+
const confirmCtx = await karin.ctx(e, {
|
|
40682
|
+
time: 120,
|
|
40683
|
+
reply: true,
|
|
40684
|
+
throwOnTimeout: false
|
|
40685
|
+
});
|
|
40686
|
+
if (!confirmCtx) return;
|
|
40687
|
+
if (confirmCtx.msg.trim() !== "确认") {
|
|
40688
|
+
e.reply("已放弃降级更新。", { reply: true });
|
|
40689
|
+
return;
|
|
40690
|
+
}
|
|
40691
|
+
await installAndRestart(e, remote);
|
|
40048
40692
|
return;
|
|
40049
40693
|
}
|
|
40050
40694
|
const ChangeLogImg = await getChangelogImage(e, {
|
|
40051
|
-
localVersion:
|
|
40052
|
-
remoteVersion:
|
|
40695
|
+
localVersion: local,
|
|
40696
|
+
remoteVersion: remote,
|
|
40053
40697
|
Tip: false,
|
|
40054
40698
|
isRemote: true
|
|
40055
40699
|
});
|
|
40056
40700
|
if (ChangeLogImg) e.reply([segment.text(`${Root.pluginName} 的更新日志:`), ...ChangeLogImg], { reply: true });
|
|
40057
40701
|
else e.reply("获取更新日志失败,更新进程继续......", { reply: true });
|
|
40058
|
-
|
|
40059
|
-
if (result.status === "ok") {
|
|
40060
|
-
const msgResult = await e.reply(`${Root.pluginName} 更新成功!\n${result.local} -> ${result.remote}\n开始执行重启......`);
|
|
40061
|
-
if (msgResult.messageId) try {
|
|
40062
|
-
await db.del(UPDATE_MSGID_KEY);
|
|
40063
|
-
await db.del(UPDATE_LOCK_KEY);
|
|
40064
|
-
} catch {}
|
|
40065
|
-
await restart(e.selfId, e.contact, msgResult.messageId);
|
|
40066
|
-
} else e.reply(`${Root.pluginName} 更新失败: ${result.data ?? "更新执行失败"}`);
|
|
40702
|
+
await installAndRestart(e, remote);
|
|
40067
40703
|
}, { businessName: "KKK更新" });
|
|
40068
|
-
var kkkUpdateCommand = karin.command(/^#?kkk
|
|
40704
|
+
var kkkUpdateCommand = karin.command(/^#?kkk更新(?:\s*(\S+))?$/, handleKkkUpdate, {
|
|
40069
40705
|
name: "kkk-更新",
|
|
40070
40706
|
perm: "master"
|
|
40071
40707
|
});
|