karin-plugin-kkk 2.45.1 → 2.45.2-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 +30 -0
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/default.js +164 -3
- package/lib/core_chunk/main.js +611 -53
- package/lib/style.css +109 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [2.45.2-beta.1](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.2-beta.0...v2.45.2-beta.1) (2026-10-26)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ✨ 新功能
|
|
9
|
+
|
|
10
|
+
* 初步支持抖音合集、短剧解析 ([0fc91a2](https://github.com/ikenxuan/karin-plugin-kkk/commit/0fc91a2258fd2d1c6fe59defa28883845f51fbba))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### 🐛 错误修复
|
|
14
|
+
|
|
15
|
+
* **douyin:** 设置推送时改用游客接口转换sec_uid ([6ee68fa](https://github.com/ikenxuan/karin-plugin-kkk/commit/6ee68faae634447114721cc4ada5524f074d1663))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### 🧰 其他更新
|
|
19
|
+
|
|
20
|
+
* 优化发版脚本 ([6175b0c](https://github.com/ikenxuan/karin-plugin-kkk/commit/6175b0c4f0815058db0559c22651a943921a846f))
|
|
21
|
+
|
|
22
|
+
## [2.45.2-beta.0](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.1...v2.45.2-beta.0) (2026-10-24)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### ✨ 新功能
|
|
26
|
+
|
|
27
|
+
* **douyin:** 推送二维码改用 amagi 签发的短链 ([e2975a3](https://github.com/ikenxuan/karin-plugin-kkk/commit/e2975a32b26384a6dcf2f1ad982b1b52abcbdbb6))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### 🐛 错误修复
|
|
31
|
+
|
|
32
|
+
* **bilibili:** 下载时避开被代理屏蔽的 PCDN 直链 (#370) ([1c64ace](https://github.com/ikenxuan/karin-plugin-kkk/commit/1c64ace13e9384a45a7e88853251a644229692cb))
|
|
33
|
+
* **xiaohongshu:** 优化合并转发消息上传逻辑 ([e093d05](https://github.com/ikenxuan/karin-plugin-kkk/commit/e093d056455b9d914e7b7728d8d2ad2513c30dbf))
|
|
34
|
+
|
|
5
35
|
## [2.45.1](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.0...v2.45.1) (2026-10-17)
|
|
6
36
|
|
|
7
37
|
|
package/lib/build-metadata.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.45.1",
|
|
3
|
-
"buildTime": "2026-10-
|
|
4
|
-
"buildTimestamp":
|
|
2
|
+
"version": "2.45.2-beta.1",
|
|
3
|
+
"buildTime": "2026-10-26T06:10:25.889Z",
|
|
4
|
+
"buildTimestamp": 1792995025889,
|
|
5
5
|
"name": "karin-plugin-kkk",
|
|
6
6
|
"description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
|
|
7
7
|
"homepage": "https://github.com/ikenxuan/karin-plugin-kkk",
|
|
8
|
-
"commitHash": "
|
|
9
|
-
"shortCommitHash": "
|
|
8
|
+
"commitHash": "db1a3fc234b0dae7da5f86d8f16964c76447fd93",
|
|
9
|
+
"shortCommitHash": "db1a3fc2"
|
|
10
10
|
}
|
|
@@ -7335,7 +7335,7 @@ var liveXs = () => ({
|
|
|
7335
7335
|
}
|
|
7336
7336
|
});
|
|
7337
7337
|
//#endregion
|
|
7338
|
-
//#region ../amagi/packages/core/dist/src-
|
|
7338
|
+
//#region ../amagi/packages/core/dist/src-DLPJF1Oy.mjs
|
|
7339
7339
|
var import_protobufjs = /* @__PURE__ */ __toESM(require_protobufjs(), 1);
|
|
7340
7340
|
/**
|
|
7341
7341
|
* B站评论区类型代码(`comments` / `commentReplies` 的 `type` 参数)。
|
|
@@ -13392,6 +13392,7 @@ var METHOD_NAMES = {
|
|
|
13392
13392
|
"douyin.userRecommendList": "fetchUserRecommendList",
|
|
13393
13393
|
/** ⚠️ 不规则:`search` → `searchContent` */
|
|
13394
13394
|
"douyin.search": "searchContent",
|
|
13395
|
+
"douyin.shortUrl": "fetchShortUrl",
|
|
13395
13396
|
"douyin.suggestWords": "fetchSuggestWords",
|
|
13396
13397
|
"douyin.musicInfo": "fetchMusicInfo",
|
|
13397
13398
|
"douyin.musicAwemeList": "fetchMusicAwemeList",
|
|
@@ -13922,6 +13923,21 @@ need_all: "true" }))}`;
|
|
|
13922
13923
|
count: data.number ?? 20
|
|
13923
13924
|
}))}`;
|
|
13924
13925
|
}
|
|
13926
|
+
/**
|
|
13927
|
+
* 分享链接转短链接。
|
|
13928
|
+
*
|
|
13929
|
+
* `target` 只编码一次(`buildQueryString` 的 `encodeURIComponent`),与抓包一致 ——
|
|
13930
|
+
* 预先编码会变成 `%25`,接口会把它当另一个链接。
|
|
13931
|
+
* `belong=aweme` 是能缩短的前提,缺了或换成别的值会回 `reason: "not allowed to shorten"`;
|
|
13932
|
+
* `persist=1` 照浏览器抓包固定发送(实测省略也能成功,保留只为与浏览器同形)。
|
|
13933
|
+
*/
|
|
13934
|
+
getWebShorten(data) {
|
|
13935
|
+
return `https://www.douyin.com/aweme/v1/web/web_shorten/?${buildQueryString$3(webQuery(this.browser, {
|
|
13936
|
+
target: data.target,
|
|
13937
|
+
belong: data.belong ?? "aweme",
|
|
13938
|
+
persist: "1"
|
|
13939
|
+
}))}`;
|
|
13940
|
+
}
|
|
13925
13941
|
/** 获取用户主页视频数据 */
|
|
13926
13942
|
getUserVideoList(data) {
|
|
13927
13943
|
return `https://www.douyin.com/aweme/v1/web/aweme/post/?${buildQueryString$3(webQuery(this.browser, {
|
|
@@ -14992,6 +15008,116 @@ var search = defineDouyinEndpoint({
|
|
|
14992
15008
|
response: type()
|
|
14993
15009
|
});
|
|
14994
15010
|
/**
|
|
15011
|
+
* `web_shorten` 的响应判定。
|
|
15012
|
+
*
|
|
15013
|
+
* 成功与失败**都是 HTTP 200 + `code: 0`**,差别只在 `message` / `reason`:
|
|
15014
|
+
*
|
|
15015
|
+
* ```jsonc
|
|
15016
|
+
* // 成功
|
|
15017
|
+
* { "code": 0, "message": "success", "now": 1792253001, "data": "https://v.douyin.com/V6jASdpUrtY/" }
|
|
15018
|
+
* // 签名没带 / 不对
|
|
15019
|
+
* { "code": 0, "message": "error", "reason": "Bad request: check failed", "now": 1792252373 }
|
|
15020
|
+
* // belong 缺失或不是 aweme
|
|
15021
|
+
* { "code": 0, "message": "error", "reason": "not allowed to shorten", "now": 1792252323,
|
|
15022
|
+
* "data": "https://www.iesdouyin.com/share/video/…" }
|
|
15023
|
+
* ```
|
|
15024
|
+
*
|
|
15025
|
+
* 平台默认的 {@link douyinJudge} 只看 `status_code`,而这个接口用 `code` 且两种失败都回 0,
|
|
15026
|
+
* 默认判定会把失败当成功 —— 调用方会拿到一个装着原链接、甚至没有 `data` 的「成功」信封。
|
|
15027
|
+
* 所以这里补一层:
|
|
15028
|
+
*
|
|
15029
|
+
* - `code` 非 0 → `PLATFORM_ERROR`;
|
|
15030
|
+
* - `reason` 点名签名校验失败 → `SIGNATURE_REFUSED`(是签名器的问题,换 cookie 无用);
|
|
15031
|
+
* - 其余带 `reason` 的拒绝 → `forbidden` / `PLATFORM_ERROR`(请求本身合法,平台不放行)。
|
|
15032
|
+
*
|
|
15033
|
+
* `message` 的原文是 `error`,`reason` 才是原因;runtime 的 error 文案只认
|
|
15034
|
+
* `message` / `status_msg` / `msg`,所以失败信封里看不到 reason 原文 —— 要排查看
|
|
15035
|
+
* `debug: true` 下的 `error.raw`。
|
|
15036
|
+
* @param raw - 解码后的响应体
|
|
15037
|
+
* @param http - HTTP 状态与响应头
|
|
15038
|
+
* @returns 平台判定结论
|
|
15039
|
+
*/
|
|
15040
|
+
var shortUrlJudge = (raw, http) => {
|
|
15041
|
+
const verdict = douyinJudge(raw, http);
|
|
15042
|
+
if (!verdict.ok) return verdict;
|
|
15043
|
+
if (typeof raw !== "object" || raw === null) return verdict;
|
|
15044
|
+
const body = raw;
|
|
15045
|
+
if (body.code !== void 0 && (typeof body.code === "number" || typeof body.code === "string") && Number(body.code) !== 0) return {
|
|
15046
|
+
ok: false,
|
|
15047
|
+
kind: "unknown",
|
|
15048
|
+
code: "PLATFORM_ERROR",
|
|
15049
|
+
retryable: false
|
|
15050
|
+
};
|
|
15051
|
+
if (typeof body.reason !== "string" || body.reason.length === 0) return verdict;
|
|
15052
|
+
if (/check failed/i.test(body.reason)) return {
|
|
15053
|
+
ok: false,
|
|
15054
|
+
kind: "risk",
|
|
15055
|
+
code: "SIGNATURE_REFUSED",
|
|
15056
|
+
retryable: false
|
|
15057
|
+
};
|
|
15058
|
+
return {
|
|
15059
|
+
ok: false,
|
|
15060
|
+
kind: "forbidden",
|
|
15061
|
+
code: "PLATFORM_ERROR",
|
|
15062
|
+
retryable: false
|
|
15063
|
+
};
|
|
15064
|
+
};
|
|
15065
|
+
/**
|
|
15066
|
+
* 分享链接转短链接(`/aweme/v1/web/web_shorten/`)。
|
|
15067
|
+
*
|
|
15068
|
+
* ## 这是唯一一条「免登录但仍要签名」的工具端点
|
|
15069
|
+
*
|
|
15070
|
+
* 2026-10-18 实测(零 cookie、随机 msToken、本项目 a_bogus):
|
|
15071
|
+
*
|
|
15072
|
+
* ```text
|
|
15073
|
+
* 只带 target + belong + a_bogus → 200 success,返回 v.douyin.com 短链
|
|
15074
|
+
* 同一组参数不带 a_bogus → 200,reason: "Bad request: check failed"
|
|
15075
|
+
* target + belong=aweme → 200 success
|
|
15076
|
+
* target 不带 belong / belong=other → 200,reason: "not allowed to shorten"
|
|
15077
|
+
* ```
|
|
15078
|
+
*
|
|
15079
|
+
* 也就是说 **cookie 完全不需要**(空串、伪造的 `ttwid/UIFID`、刚铸的游客 cookie 三种都成功),
|
|
15080
|
+
* 但 **`a_bogus` 必须带**,且 `belong=aweme` 是能缩短的前提 —— 客户端算不出短链、也没有
|
|
15081
|
+
* 别的接口能补,这条没有「免签」的退路。
|
|
15082
|
+
*
|
|
15083
|
+
* ## 为什么保留完整的 web 版式
|
|
15084
|
+
*
|
|
15085
|
+
* 浏览器抓包里这条的 query 很长(`target,belong,persist` + 25 个环境参数 + tail)。
|
|
15086
|
+
* 实测最小化到 `target+belong+a_bogus` 也能成功,但这里仍走 `webQuery` 的完整版式:
|
|
15087
|
+
* 这是 `/aweme/v1/web/*` 的统一形状,抖音按查询串重算签名,形状一致不增加成本。
|
|
15088
|
+
* `persist=1` 照抓包固定发送(实测省略也能成功,保留是为了与浏览器一致)。
|
|
15089
|
+
*
|
|
15090
|
+
* ## 短链是稳定映射
|
|
15091
|
+
*
|
|
15092
|
+
* 同一个 `target` 多次调用返回同一个短码(跨进程、跨 cookie 实测一致),
|
|
15093
|
+
* 不是一次性令牌;`https://www.douyin.com/video/<id>` 与它的分享链接会得到**不同**的短码,
|
|
15094
|
+
* 取决于传入的字符串本身。
|
|
15095
|
+
*/
|
|
15096
|
+
var shortUrl = defineDouyinEndpoint({
|
|
15097
|
+
name: "douyin.shortUrl",
|
|
15098
|
+
route: "/fetch_short_url",
|
|
15099
|
+
doc: {
|
|
15100
|
+
summary: "分享链接转短链接",
|
|
15101
|
+
description: "把抖音作品分享链接转换成 `v.douyin.com` 短链;`belong=aweme` 是能缩短的前提。"
|
|
15102
|
+
},
|
|
15103
|
+
params: object$1({
|
|
15104
|
+
target: string().min(1, { error: "目标链接不能为空" }).describe("需要缩短的分享链接"),
|
|
15105
|
+
belong: string().min(1).default("aweme").optional().describe("短链归属类型,抖音作品固定为 aweme,默认 aweme")
|
|
15106
|
+
}),
|
|
15107
|
+
build: (p, ctx) => ({
|
|
15108
|
+
method: "GET",
|
|
15109
|
+
url: createDouyinApiUrls(ctx.userAgent).getWebShorten({
|
|
15110
|
+
target: p.target,
|
|
15111
|
+
belong: p.belong ?? "aweme"
|
|
15112
|
+
})
|
|
15113
|
+
}),
|
|
15114
|
+
sign: douyinBogus(184),
|
|
15115
|
+
judge: shortUrlJudge,
|
|
15116
|
+
retryOn: DOUYIN_RISK_RETRY,
|
|
15117
|
+
retryFresh: true,
|
|
15118
|
+
response: type()
|
|
15119
|
+
});
|
|
15120
|
+
/**
|
|
14995
15121
|
* 图文/幻灯片作品详情(新路径 `/fetch_slides_work`,避免与其他作品类型共用路由)。
|
|
14996
15122
|
*
|
|
14997
15123
|
* 行为与旧版一致:`getWorkDetail` GET + a_bogus 签名。
|
|
@@ -15237,11 +15363,14 @@ var userVideoList = defineDouyinEndpoint({
|
|
|
15237
15363
|
/**
|
|
15238
15364
|
* 抖音端点注册表。
|
|
15239
15365
|
*
|
|
15240
|
-
* 共
|
|
15366
|
+
* 共 26 条路由,路由唯一:5 个作品端点拆成 5 条独立路由
|
|
15241
15367
|
* (`parseWork` 保留 `/fetch_one_work`)。
|
|
15242
15368
|
*
|
|
15243
15369
|
* 末尾 4 条是**免鉴权**端点(`sign: false` + `dropHeaders` 去掉 cookie)。
|
|
15244
|
-
* 它们与前面
|
|
15370
|
+
* 它们与前面 22 条走同一条管线,所以事件、trace、信封形状一致。
|
|
15371
|
+
*
|
|
15372
|
+
* `shortUrl` 是例外:免登录**但仍要签名**(`sign: douyinBogus(184)`),
|
|
15373
|
+
* 所以按签名端点计数;它不在免鉴权那 4 条里。
|
|
15245
15374
|
*/
|
|
15246
15375
|
var douyinRegistry = {
|
|
15247
15376
|
parseWork,
|
|
@@ -15278,6 +15407,7 @@ var douyinRegistry = {
|
|
|
15278
15407
|
userRecommendList,
|
|
15279
15408
|
search,
|
|
15280
15409
|
suggestWords,
|
|
15410
|
+
shortUrl,
|
|
15281
15411
|
musicInfo,
|
|
15282
15412
|
musicAwemeList,
|
|
15283
15413
|
mixAweme,
|
|
@@ -22906,6 +23036,37 @@ var RESPONSE_SCHEMAS = {
|
|
|
22906
23036
|
]
|
|
22907
23037
|
}
|
|
22908
23038
|
] },
|
|
23039
|
+
"douyin_shortUrl": { "anyOf": [{
|
|
23040
|
+
"type": "object",
|
|
23041
|
+
"properties": {
|
|
23042
|
+
"code": { "type": "number" },
|
|
23043
|
+
"data": { "type": "string" },
|
|
23044
|
+
"message": { "type": "string" },
|
|
23045
|
+
"now": { "type": "number" }
|
|
23046
|
+
},
|
|
23047
|
+
"required": [
|
|
23048
|
+
"code",
|
|
23049
|
+
"data",
|
|
23050
|
+
"message",
|
|
23051
|
+
"now"
|
|
23052
|
+
]
|
|
23053
|
+
}, {
|
|
23054
|
+
"type": "object",
|
|
23055
|
+
"properties": {
|
|
23056
|
+
"code": { "type": "number" },
|
|
23057
|
+
"data": { "type": "string" },
|
|
23058
|
+
"message": { "type": "string" },
|
|
23059
|
+
"now": { "type": "number" },
|
|
23060
|
+
"reason": { "type": "string" }
|
|
23061
|
+
},
|
|
23062
|
+
"required": [
|
|
23063
|
+
"code",
|
|
23064
|
+
"data",
|
|
23065
|
+
"message",
|
|
23066
|
+
"now",
|
|
23067
|
+
"reason"
|
|
23068
|
+
]
|
|
23069
|
+
}] },
|
|
22909
23070
|
"douyin_slidesWork": { "anyOf": [
|
|
22910
23071
|
{
|
|
22911
23072
|
"type": "object",
|