yz-yuki-plugin 2.0.3-3 → 2.0.3-5
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 +2 -0
- package/README.md +73 -63
- package/lib/models/bilibili/bilibili.query.d.ts +15 -5
- package/lib/models/bilibili/bilibili.query.js +112 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -8,20 +8,34 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://github.com/snowtafir/yuki-plugin)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# 🌰一、安装插件
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
## 选择安装方式
|
|
14
|
+
按照网络情况以及使用的bot框架是`Yunzai-Next`还是`Yunzai-V3`,选择对应的安装方式。
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
### ***(一)Yunzai-Next***
|
|
17
|
+
> 选择其中一种方式安装插件:
|
|
17
18
|
|
|
18
|
-
1.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
1. npm包安装到`yunzai-next/node_modules`的方式,仅Yunzai-Next支持:
|
|
20
|
+
```
|
|
21
|
+
yarn add yz-yuki-plugin -W
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
选择启用插件方式:
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
* 方式1(推荐):
|
|
27
|
+
|
|
28
|
+
手动新建 `yunzai-next/yunzai.config.json` 文件,输入如下内容,`applications`字段添加的 `"yz-yuki-plugin"`即为启用本插件:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"applications": ["yz-system", "yz-yuki-plugin"],
|
|
33
|
+
"middlewares": ["yunzai-mys/runtime", "yunzai-mys/mw"]
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
* 方式2:
|
|
37
|
+
|
|
38
|
+
修改 `yunzai-next/yunzai.config.js`:
|
|
25
39
|
```js
|
|
26
40
|
import { defineConfig } from 'yunzai'
|
|
27
41
|
export default defineConfig({
|
|
@@ -30,69 +44,64 @@ export default defineConfig({
|
|
|
30
44
|
})
|
|
31
45
|
```
|
|
32
46
|
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
import yuki from 'yz-yuki-plugin' //新增该行
|
|
36
|
-
export default defineConfig({
|
|
37
|
-
applications: [system(), yuki()], //该行添加 yuki()
|
|
38
|
-
middlewares: [runtime(), starRail()]
|
|
39
|
-
})
|
|
40
|
-
```
|
|
47
|
+
2. 安装到 `yunzai-next/plugins` 的方式:
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
>gitee仓库:
|
|
44
|
-
>```
|
|
45
|
-
>git clone --branch main https://gitee.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
46
|
-
>```
|
|
49
|
+
> 仅支持Yunzai-Next的分支,选择仓库:
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
gitee仓库:
|
|
52
|
+
```shell
|
|
53
|
+
git clone --branch main https://gitee.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
github仓库:
|
|
57
|
+
```shell
|
|
58
|
+
git clone --branch main https://github.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
59
|
+
```
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
>```
|
|
61
|
+
* 依赖安装:
|
|
62
|
+
```shell
|
|
63
|
+
yarn install
|
|
64
|
+
```
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
>```
|
|
61
|
-
>git clone --branch main3 https://github.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
62
|
-
>```
|
|
66
|
+
### ***(二)Yunzai-V3***
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
* Yunzai-Next:
|
|
68
|
+
> 仅支持Yunzai-V3(TRSS/Miao)的分支,选择仓库,安装到 `yunzai/plugins`:
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
gitee仓库:
|
|
68
71
|
```
|
|
69
|
-
|
|
72
|
+
git clone --branch main3 https://gitee.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
70
73
|
```
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
github仓库:
|
|
73
76
|
```
|
|
77
|
+
git clone --branch main3 https://github.com/snowtafir/yuki-plugin.git ./plugins/yuki-plugin
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
* 安装依赖
|
|
81
|
+
|
|
82
|
+
```shell
|
|
74
83
|
pnpm install --filter=yuki-plugin
|
|
75
84
|
```
|
|
76
85
|
|
|
77
|
-
|
|
86
|
+
# 📦二、插件配置
|
|
78
87
|
|
|
79
88
|
> [!IMPORTANT]
|
|
80
89
|
> 统一的配置文件路径:
|
|
81
90
|
|
|
82
91
|
`Yunzai/data/yuki-plugin/config/`,启动一次后,即可查看配置文件。
|
|
83
92
|
|
|
84
|
-
###
|
|
85
|
-
|
|
93
|
+
### (一)B站动态功能:
|
|
94
|
+
使用前建议先绑定B站账号或配置cookie,绑定后即可使用相关功能。
|
|
86
95
|
|
|
87
|
-
> **CK优先级:** **#添加B站CK** > ***#扫码B站登录*** > 自动ck
|
|
96
|
+
> **CK优先级:** **#添加B站CK** > ***#扫码B站登录*** > 自动ck。`只有删除前一个,后一个才生效,删除方法见功能指令。`
|
|
88
97
|
|
|
89
|
-
|
|
98
|
+
#### 1)绑定账号(推荐):
|
|
99
|
+
`#扫码B站登录`,获取B站登录CK。取消使用登录则发送:`#删除B站登录`
|
|
90
100
|
|
|
91
|
-
####
|
|
92
|
-
#### (2) 手动配置本地Cookie(可选):
|
|
101
|
+
#### 2)手动配置本地Cookie(可选):
|
|
93
102
|
私聊/私信 Bot下发送`#添加B站CK: xxx` 添加本地浏览器 无痕模式下 登录b站 获取的B站cookie。
|
|
94
103
|
|
|
95
|
-
|
|
104
|
+
<details> <summary>本地CK获取方法:</summary>
|
|
96
105
|
|
|
97
106
|
***注意事项:***
|
|
98
107
|
> 你平常使用浏览器访问 b 站为普通模式,cookie会定期自动刷新而导致复制的旧ck一段时间就失效,你应该使用`隐私窗口/无痕式窗口`重新登录b站,并获取新的 cookie。
|
|
@@ -111,27 +120,29 @@ pnpm install --filter=yuki-plugin
|
|
|
111
120
|
> [!TIP]
|
|
112
121
|
> 保存目录:`Yunzai/data/yuki-plugin/biliCookie.yaml`,如需更换/更新cookie 使用新的cookie发送`#添加B站CK: xxx`覆盖绑定即可。停用手动本地ck则发送命令:`#删除B站ck`
|
|
113
122
|
|
|
114
|
-
###
|
|
115
|
-
|
|
116
|
-
|
|
123
|
+
### (二)微博动态功能:
|
|
124
|
+
* 获取微博博主uid:
|
|
125
|
+
|
|
126
|
+
博主主页如:
|
|
117
127
|
```
|
|
118
128
|
https://m.weibo.cn/u/6593199887 # 6593199887 为原神博主uid
|
|
119
129
|
https://m.weibo.cn/u/7643376782 # 7643376782 为崩坏星穹铁道博主uid
|
|
120
130
|
```
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
或打开微博app,进入博主主页,右上角点击分享,复制分享链接,在链接里找到相应uid。
|
|
132
|
+
|
|
133
|
+
微博限制,可能连续获取动态会出现获取连接中断报错,待定时任务自动重试即可。
|
|
123
134
|
|
|
124
|
-
|
|
135
|
+
# 🌈 三、功能列表
|
|
125
136
|
|
|
126
|
-
请使用
|
|
137
|
+
请使用 `#优纪帮助`或 `/yuki帮助` 获取完整帮助
|
|
127
138
|
|
|
128
139
|
- [x] B站动态
|
|
129
140
|
- [x] 微博动态
|
|
130
141
|
|
|
131
142
|
|
|
132
|
-
|
|
143
|
+
# 🚀 四、指令列表
|
|
133
144
|
|
|
134
|
-
<details><summary
|
|
145
|
+
<details><summary>指令列表,点击展开</summary>
|
|
135
146
|
|
|
136
147
|
> [!TIP]
|
|
137
148
|
> 指令前缀:`#优纪`、`#yuki`、`/优纪`、`/yuki`,
|
|
@@ -173,20 +184,19 @@ https://m.weibo.cn/u/7643376782 # 7643376782 为崩坏星穹铁道博主uid
|
|
|
173
184
|
|
|
174
185
|
</details>
|
|
175
186
|
|
|
176
|
-
|
|
177
|
-
<details><summary>点击展开</summary>
|
|
187
|
+
<details><summary>样式预览,点击展开</summary>
|
|
178
188
|
|
|
179
189
|

|
|
180
190
|
|
|
181
191
|
</details>
|
|
182
192
|
|
|
183
|
-
|
|
193
|
+
# 🧩 五、支持与贡献
|
|
184
194
|
|
|
185
195
|
如果你喜欢这个项目,请不妨点个 Star🌟,这是对开发者最大的动力,呜咪~❤️
|
|
186
196
|
|
|
187
197
|
有意见或者建议也欢迎提交 [Issues](https://github.com/snowtafir/yuki-plugin/issues) 和 [Pull requests](https://github.com/snowtafir/yuki-plugin/pulls)。
|
|
188
198
|
|
|
189
|
-
|
|
199
|
+
# 🌟 六、license/声明
|
|
190
200
|
- this project is inspired by [trss-xianxin-plugin](https://github.com/snowtafir/xianxin-plugin)
|
|
191
201
|
- 基于 `MIT` 协议开源,但有如下额外限制:
|
|
192
202
|
1. 其中`resources/img/icon/`目录下的素材来源于网络,不保证商业使用,请遵守相关版权法律,如有侵权请联系本人删除。
|
|
@@ -194,7 +204,7 @@ https://m.weibo.cn/u/7643376782 # 7643376782 为崩坏星穹铁道博主uid
|
|
|
194
204
|
3. ```严禁用于非法行为```
|
|
195
205
|
|
|
196
206
|
|
|
197
|
-
|
|
207
|
+
# 🔗 七、链接/致谢
|
|
198
208
|
|
|
199
209
|
| Nickname | Contribution |
|
|
200
210
|
| :-----------------------------------------------------------------: | ----------------------- |
|
|
@@ -17,12 +17,22 @@ export declare class BiliQuery {
|
|
|
17
17
|
*/
|
|
18
18
|
static parseRichTextNodes: (nodes: any[] | string | any) => any;
|
|
19
19
|
/**获取完整B站文章内容
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
* @param postUrl - 文章链接: https://www.bilibili.com/read/cvxxxx 或者 https://www.bilibili.com/opus/xxxx
|
|
21
|
+
* @returns {Json} 完整的B站文章内容json数据
|
|
22
22
|
*/
|
|
23
|
-
static getFullArticleContent(postUrl: string): Promise<
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
static getFullArticleContent(postUrl: string): Promise<{
|
|
24
|
+
readInfo: any;
|
|
25
|
+
articleType: string;
|
|
26
|
+
}>;
|
|
27
|
+
/**解析旧版完整文章内容 */
|
|
28
|
+
static praseFullOldTypeArticleContent(content: string): string;
|
|
29
|
+
/**解析新版完整文章内容
|
|
30
|
+
* @param paragraphs - MODULE_TYPE_CONTENT 类型文章的段落数组
|
|
31
|
+
*/
|
|
32
|
+
static praseFullNewTypeArticleContent: (paragraphs: any[] | any) => {
|
|
33
|
+
content: string;
|
|
34
|
+
img: any[];
|
|
35
|
+
};
|
|
26
36
|
static formatUrl(url: string): string;
|
|
27
37
|
/**
|
|
28
38
|
* 生成动态消息文字内容
|
|
@@ -86,16 +86,31 @@ class BiliQuery {
|
|
|
86
86
|
pics = desc?.pics;
|
|
87
87
|
pics = pics.map((item) => { return { url: item?.url, width: item?.width, height: item?.height }; }) || [];
|
|
88
88
|
formatData.data.title = desc?.title;
|
|
89
|
+
// 文章内容过长,则尝试获取全文
|
|
89
90
|
if ((desc?.summary?.text)?.length >= 480) {
|
|
90
|
-
const readInfo = await this.getFullArticleContent(this.formatUrl(desc?.jump_url));
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
formatData.data.content
|
|
95
|
-
|
|
91
|
+
const { readInfo, articleType } = await this.getFullArticleContent(this.formatUrl(desc?.jump_url));
|
|
92
|
+
// 文章链接类型为 cv(旧类型) 或者 opus(新类型)
|
|
93
|
+
if (articleType === "cv") {
|
|
94
|
+
formatData.data.content = this.praseFullOldTypeArticleContent(readInfo?.content);
|
|
95
|
+
if (String(formatData.data.content).length < 100) {
|
|
96
|
+
formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || "";
|
|
97
|
+
formatData.data.pics = pics;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
formatData.data.pics = [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (articleType === "opus") {
|
|
104
|
+
const { content, img } = this.praseFullNewTypeArticleContent(readInfo?.paragraphs);
|
|
105
|
+
formatData.data.content = content;
|
|
106
|
+
formatData.data.pics = (img && img.length > 0) ? img : pics;
|
|
107
|
+
if (content && content.length < 100) {
|
|
108
|
+
formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text);
|
|
109
|
+
}
|
|
96
110
|
}
|
|
97
111
|
else {
|
|
98
|
-
formatData.data.
|
|
112
|
+
formatData.data.content = this.parseRichTextNodes(desc?.summary?.rich_text_nodes || desc?.summary?.text) || "";
|
|
113
|
+
formatData.data.pics = pics;
|
|
99
114
|
}
|
|
100
115
|
}
|
|
101
116
|
else {
|
|
@@ -106,7 +121,7 @@ class BiliQuery {
|
|
|
106
121
|
else if (majorType === "MAJOR_TYPE_ARTICLE") {
|
|
107
122
|
desc = data?.modules?.module_dynamic?.major?.article || {};
|
|
108
123
|
pics = desc?.covers;
|
|
109
|
-
pics = pics.map((item) => {
|
|
124
|
+
pics = pics.map((item) => ({ url: item }));
|
|
110
125
|
formatData.data.title = desc?.title;
|
|
111
126
|
formatData.data.content = this.parseRichTextNodes(desc?.desc);
|
|
112
127
|
}
|
|
@@ -210,8 +225,8 @@ class BiliQuery {
|
|
|
210
225
|
}
|
|
211
226
|
};
|
|
212
227
|
/**获取完整B站文章内容
|
|
213
|
-
|
|
214
|
-
|
|
228
|
+
* @param postUrl - 文章链接: https://www.bilibili.com/read/cvxxxx 或者 https://www.bilibili.com/opus/xxxx
|
|
229
|
+
* @returns {Json} 完整的B站文章内容json数据
|
|
215
230
|
*/
|
|
216
231
|
static async getFullArticleContent(postUrl) {
|
|
217
232
|
const Cookie = await readSyncCookie();
|
|
@@ -221,11 +236,24 @@ class BiliQuery {
|
|
|
221
236
|
responseType: 'text'
|
|
222
237
|
});
|
|
223
238
|
const text = response.data;
|
|
224
|
-
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
239
|
+
let match, readInfo, articleType;
|
|
240
|
+
if (/^https:\/\/www.bilibili.com\/read\/cv/.test(postUrl)) {
|
|
241
|
+
match = String(text).match(/"readInfo":([\s\S]+?),"readViewInfo":/);
|
|
242
|
+
if (match) {
|
|
243
|
+
const full_json_text = match[1];
|
|
244
|
+
readInfo = JSON.parse(full_json_text);
|
|
245
|
+
articleType = 'cv';
|
|
246
|
+
return { readInfo, articleType };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else if (/^https:\/\/www.bilibili.com\/opus\//.test(postUrl)) {
|
|
250
|
+
match = String(text).match(/"module_content":([\s\S]+?),\s*"module_type":"MODULE_TYPE_CONTENT"/);
|
|
251
|
+
if (match) {
|
|
252
|
+
const full_json_text = match[1];
|
|
253
|
+
readInfo = JSON.parse(full_json_text);
|
|
254
|
+
articleType = 'opus';
|
|
255
|
+
return { readInfo, articleType };
|
|
256
|
+
}
|
|
229
257
|
}
|
|
230
258
|
}
|
|
231
259
|
catch (err) {
|
|
@@ -233,8 +261,8 @@ class BiliQuery {
|
|
|
233
261
|
return null;
|
|
234
262
|
}
|
|
235
263
|
}
|
|
236
|
-
|
|
237
|
-
static
|
|
264
|
+
/**解析旧版完整文章内容 */
|
|
265
|
+
static praseFullOldTypeArticleContent(content) {
|
|
238
266
|
content = String(content).replace(/\n/g, '<br>');
|
|
239
267
|
// 使用正则表达式匹配 <img> 标签的 data-src 属性
|
|
240
268
|
const imgTagRegex = /<img[^>]*data-src="([^"]*)"[^>]*>/g;
|
|
@@ -245,6 +273,73 @@ class BiliQuery {
|
|
|
245
273
|
});
|
|
246
274
|
return content;
|
|
247
275
|
}
|
|
276
|
+
/**解析新版完整文章内容
|
|
277
|
+
* @param paragraphs - MODULE_TYPE_CONTENT 类型文章的段落数组
|
|
278
|
+
*/
|
|
279
|
+
static praseFullNewTypeArticleContent = (paragraphs) => {
|
|
280
|
+
if (Array.isArray(paragraphs)) {
|
|
281
|
+
// 筛选出正文和图片
|
|
282
|
+
paragraphs = paragraphs.filter(paragraph => paragraph.para_type === 1 || paragraph.para_type === 2);
|
|
283
|
+
let content = "";
|
|
284
|
+
let img = [];
|
|
285
|
+
paragraphs.forEach((item) => {
|
|
286
|
+
switch (item.para_type) {
|
|
287
|
+
case 1:
|
|
288
|
+
// 处理正文
|
|
289
|
+
content += item.text.nodes.map((node) => {
|
|
290
|
+
let nodeType = node.type;
|
|
291
|
+
if (nodeType === 'TEXT_NODE_TYPE_RICH') {
|
|
292
|
+
let richType = node?.rich?.type;
|
|
293
|
+
switch (richType) {
|
|
294
|
+
case 'RICH_TEXT_NODE_TYPE_TOPIC':
|
|
295
|
+
// 确保链接以 https:// 开头
|
|
296
|
+
let jumpUrl = node?.rich?.jump_url;
|
|
297
|
+
if (jumpUrl && !jumpUrl.startsWith('http://') && !jumpUrl.startsWith('https://')) {
|
|
298
|
+
jumpUrl = `https://${jumpUrl}`;
|
|
299
|
+
}
|
|
300
|
+
return `<span class="bili-rich-text-module topic" href="${jumpUrl}">${node?.rich?.text}</span>`;
|
|
301
|
+
case 'RICH_TEXT_NODE_TYPE_TEXT':
|
|
302
|
+
// 正文将 \n 替换为 <br> 以实现换行
|
|
303
|
+
return node?.rich?.text.replace(/\n/g, '<br>');
|
|
304
|
+
case 'RICH_TEXT_NODE_TYPE_AT':
|
|
305
|
+
// 处理 @ 类型,使用官方的HTML标签写法
|
|
306
|
+
return `<span data-module="desc" data-type="at" data-oid="${node?.rich?.rid}" class="bili-rich-text-module at">${node?.rich?.text}</span>`;
|
|
307
|
+
case 'RICH_TEXT_NODE_TYPE_LOTTERY':
|
|
308
|
+
// 处理互动抽奖类型,使用官方的HTML标签写法
|
|
309
|
+
return `<span data-module="desc" data-type="lottery" data-oid="${node?.rich?.rid}" class="bili-rich-text-module lottery">${node?.rich?.text}</span>`;
|
|
310
|
+
case 'RICH_TEXT_NODE_TYPE_WEB':
|
|
311
|
+
// 处理 RICH_TEXT_NODE_TYPE_WEB 类型,直接拼接 text 属性
|
|
312
|
+
return node?.rich?.text;
|
|
313
|
+
case 'RICH_TEXT_NODE_TYPE_EMOJI':
|
|
314
|
+
// 处理表情类型,使用 img 标签显示表情
|
|
315
|
+
const emoji = node?.rich?.emoji;
|
|
316
|
+
return `<img src="${emoji?.icon_url}" alt="${emoji?.text}" title="${emoji?.text}" style="vertical-align: middle; width: ${emoji?.size}em; height: ${emoji?.size}em;">`;
|
|
317
|
+
case 'RICH_TEXT_NODE_TYPE_GOODS':
|
|
318
|
+
// 处理商品推广类型,使用官方的HTML标签写法
|
|
319
|
+
const goods_url = node?.rich?.jump_url;
|
|
320
|
+
return `<span data-module="desc" data-type="goods" data-url="${goods_url}" data-oid="${node?.rich?.rid}" class="bili-rich-text-module goods ${node?.rich?.icon_name}">​${node?.rich?.text}</span>`;
|
|
321
|
+
default:
|
|
322
|
+
return node;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (nodeType === "TEXT_NODE_TYPE_WORD") {
|
|
326
|
+
return `${node?.word?.words}<br>`;
|
|
327
|
+
}
|
|
328
|
+
}).join('');
|
|
329
|
+
break;
|
|
330
|
+
case 2:
|
|
331
|
+
// 处理图片
|
|
332
|
+
img = img.concat(item?.pic?.pics.map((item) => { return { url: item?.url, width: item?.width, height: item?.height }; }) || []);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return { content, img };
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
// 未知类型,返回null
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
248
343
|
// 处理斜杠开头的链接
|
|
249
344
|
static formatUrl(url) {
|
|
250
345
|
return 0 == url.indexOf('//') ? `https:${url}` : url;
|