node-karin 0.10.5 → 0.10.7

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.
@@ -112,7 +112,7 @@ export class AdapterInput {
112
112
  }
113
113
  const buffer = await common.buffer(file);
114
114
  // 生成文件名 根据type生成不同的文件后缀
115
- const name = `${Date.now()}.${type === 'image' ? 'jpg' : type === 'voice' ? 'mp3' : 'file'}`;
115
+ const name = `${Date.now()}.${type === 'image' ? 'jpg' : type === 'record' ? 'mp3' : 'file'}`;
116
116
  fs.writeFileSync(`./temp/input/${name}`, buffer);
117
117
  return `[${type === 'image' ? '图片' : '语音'}: http://${ip}:${config.Server.http.port}/api/input?name=${name}&token=${this.token} ]`;
118
118
  }
@@ -135,7 +135,7 @@ export class AdapterInput {
135
135
  text.push(v.text);
136
136
  break;
137
137
  case 'image':
138
- case 'voice':
138
+ case 'record':
139
139
  text.push(await this.#MsgToFile(v.type, v.file));
140
140
  break;
141
141
  default:
@@ -1,3 +1,4 @@
1
+ import { AdapterOneBot11 } from './index.js';
1
2
  import { KarinElement, OB11Segment } from '../../../types/index.js';
2
3
  /**
3
4
  * onebot11转karin
@@ -8,4 +9,4 @@ export declare function AdapterConvertKarin(data: Array<OB11Segment>): Array<Kar
8
9
  * karin转onebot11
9
10
  * @param data karin格式消息
10
11
  */
11
- export declare function KarinConvertAdapter(data: Array<KarinElement>): Array<OB11Segment>;
12
+ export declare function KarinConvertAdapter(data: Array<KarinElement>, bot: AdapterOneBot11): Array<OB11Segment>;
@@ -1,3 +1,4 @@
1
+ import fs from 'fs';
1
2
  import { segment } from '../../../utils/index.js';
2
3
  /**
3
4
  * onebot11转karin
@@ -53,11 +54,22 @@ export function AdapterConvertKarin(data) {
53
54
  }
54
55
  return elements;
55
56
  }
57
+ /**
58
+ * 处理非本地ws的文件
59
+ * @param file 文件路径
60
+ */
61
+ function fileToBase64(file, bot) {
62
+ if (!bot || !file.startsWith('file://') || !bot.adapter.connect)
63
+ return file;
64
+ const list = ['127.0.0.1', 'localhost'];
65
+ const url = new URL(bot.adapter.connect);
66
+ return list.includes(url.hostname) ? `base64://${fs.readFileSync(file).toString('base64')}` : file;
67
+ }
56
68
  /**
57
69
  * karin转onebot11
58
70
  * @param data karin格式消息
59
71
  */
60
- export function KarinConvertAdapter(data) {
72
+ export function KarinConvertAdapter(data, bot) {
61
73
  const elements = [];
62
74
  for (const i of data) {
63
75
  const type = i.type;
@@ -77,7 +89,7 @@ export function KarinConvertAdapter(data) {
77
89
  case "image" /* OB11SegmentType.Image */:
78
90
  case "video" /* OB11SegmentType.Video */:
79
91
  case "file" /* OB11SegmentType.File */: {
80
- elements.push({ type, data: { file: i.file } });
92
+ elements.push({ type, data: { file: fileToBase64(i.file, bot) } });
81
93
  break;
82
94
  }
83
95
  case "xml" /* OB11SegmentType.Xml */: {
@@ -93,7 +105,7 @@ export function KarinConvertAdapter(data) {
93
105
  break;
94
106
  }
95
107
  case "record" /* OB11SegmentType.Record */: {
96
- elements.push({ type, data: { file: i.file, magic: i.magic || false } });
108
+ elements.push({ type, data: { file: fileToBase64(i.file, bot), magic: i.magic || false } });
97
109
  break;
98
110
  }
99
111
  case "music" /* OB11SegmentType.Music */: {
@@ -106,21 +118,6 @@ export function KarinConvertAdapter(data) {
106
118
  }
107
119
  break;
108
120
  }
109
- case 'button': {
110
- elements.push({ type: 'button', data: i.data });
111
- break;
112
- }
113
- case 'markdown': {
114
- const { type, ...data } = i;
115
- elements.push({ type, data: { ...data } });
116
- break;
117
- }
118
- case 'rows': {
119
- for (const val of i.rows) {
120
- elements.push({ type: 'button', data: val.data });
121
- }
122
- break;
123
- }
124
121
  case "poke" /* OB11SegmentType.Poke */: {
125
122
  elements.push({ type, data: { type: i.poke_type, id: i.id } });
126
123
  break;
@@ -157,6 +154,9 @@ export function KarinConvertAdapter(data) {
157
154
  elements.push({ type: 'weather', data: { city: i.city, type: i.type } });
158
155
  break;
159
156
  }
157
+ case 'button':
158
+ case 'markdown':
159
+ case 'keyboard':
160
160
  default: {
161
161
  elements.push(i);
162
162
  break;
@@ -137,7 +137,7 @@ export class AdapterOneBot11 {
137
137
  * @param data karin格式消息
138
138
  */
139
139
  KarinConvertAdapter(data) {
140
- return KarinConvertAdapter(data);
140
+ return KarinConvertAdapter(data, this);
141
141
  }
142
142
  /**
143
143
  * 专属当前Bot的日志打印方法
@@ -3,7 +3,7 @@ import { KarinAdapter, Contact, KarinElement } from '../../types/index.js';
3
3
  /**
4
4
  * 监听器管理
5
5
  */
6
- declare class Listeners extends EventEmitter {
6
+ export declare class Listeners extends EventEmitter {
7
7
  #private;
8
8
  /**
9
9
  * Bot索引
@@ -103,4 +103,3 @@ declare class Listeners extends EventEmitter {
103
103
  }
104
104
  export declare const listener: Listeners;
105
105
  export declare const Bot: Listeners;
106
- export {};
@@ -6,7 +6,7 @@ import { MessageHandler, NoticeHandler, RequestHandler } from '../../event/index
6
6
  /**
7
7
  * 监听器管理
8
8
  */
9
- class Listeners extends EventEmitter {
9
+ export class Listeners extends EventEmitter {
10
10
  /**
11
11
  * Bot索引
12
12
  * @type - Bot索引
@@ -108,8 +108,11 @@ export class MessageHandler extends EventBaseHandler {
108
108
  logs.push(`[face:${val.id}]`);
109
109
  break;
110
110
  case 'video':
111
+ logs.push(`[video:${val.file}]`);
112
+ break;
111
113
  case 'record':
112
- logs.push(`[${val.type}:${val.file}]`);
114
+ this.e.record = val.file;
115
+ logs.push(`[record:${val.file}]`);
113
116
  break;
114
117
  case 'image':
115
118
  this.e.image.push(val.file);
@@ -186,11 +189,8 @@ export class MessageHandler extends EventBaseHandler {
186
189
  logs.push(`[markdown_tpl:${JSON.stringify(content)}]`);
187
190
  break;
188
191
  }
189
- case 'rows': {
190
- const rows = [];
191
- for (const v of val.rows)
192
- rows.push(JSON.stringify(v.data));
193
- logs.push(`[rows:${JSON.stringify(rows)}]`);
192
+ case 'keyboard': {
193
+ logs.push(`[rows:${JSON.stringify(val.rows)}]`);
194
194
  break;
195
195
  }
196
196
  case 'button':
@@ -1,4 +1,4 @@
1
- export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | 'voice' | 'video' | 'basketball' | 'dice' | 'rps' | 'poke' | 'music' | 'weather' | 'location' | 'share' | 'gift' | 'market_face' | 'forward' | 'contact' | 'json' | 'xml' | 'file' | 'markdown' | 'markdown_tpl' | 'keyboard' | 'node' | 'rows' | 'record' | 'long_msg';
1
+ export type ElementType = 'text' | 'at' | 'face' | 'bubble_face' | 'reply' | 'image' | 'video' | 'basketball' | 'dice' | 'rps' | 'poke' | 'music' | 'weather' | 'location' | 'share' | 'gift' | 'market_face' | 'forward' | 'contact' | 'json' | 'xml' | 'file' | 'markdown' | 'markdown_tpl' | 'keyboard' | 'node' | 'rows' | 'record' | 'long_msg';
2
2
  export interface Element {
3
3
  /**
4
4
  * - 元素类型
@@ -109,29 +109,6 @@ export interface ImageElement extends Element {
109
109
  */
110
110
  file_type: 'show' | 'flash' | 'original';
111
111
  }
112
- /**
113
- * - 语音元素
114
- * @deprecated 即将废弃 请使用segment.record
115
- */
116
- export interface VoiceElement extends Element {
117
- type: 'voice';
118
- /**
119
- * - 语音文件url、路径或者base64
120
- */
121
- file: string;
122
- /**
123
- * - 是否为魔法语音
124
- */
125
- magic: boolean;
126
- /**
127
- * - 语音md5
128
- */
129
- md5?: string;
130
- /**
131
- * - 语音名称
132
- */
133
- name?: string;
134
- }
135
112
  /**
136
113
  * - 语音元素
137
114
  */
@@ -489,68 +466,81 @@ export interface MarkdownElement extends Element {
489
466
  content: string;
490
467
  }
491
468
  /**
492
- * - 按钮
469
+ * 单个按钮结构 这是karin的按钮结构 与qqbot的不同
470
+ */
471
+ export interface Button {
472
+ /**
473
+ * - 按钮显示文本
474
+ */
475
+ text: string;
476
+ /**
477
+ * - 按钮类型 不建议使用 此为预留字段
478
+ */
479
+ type?: number;
480
+ /**
481
+ * - 是否为回调按钮
482
+ * @default false
483
+ */
484
+ callback?: boolean;
485
+ /**
486
+ * - 跳转按钮
487
+ */
488
+ link?: string;
489
+ /**
490
+ * - 操作相关的数据
491
+ */
492
+ data?: string;
493
+ /**
494
+ * - 按钮点击后显示的文字,不传为text
495
+ */
496
+ show?: string;
497
+ /**
498
+ * 按钮样式
499
+ * - 0-灰色线框
500
+ * - 1-蓝色线框
501
+ * - 2-特殊样式按钮
502
+ * - 3-红色文字
503
+ * - 4-白色填充
504
+ */
505
+ style?: number;
506
+ /**
507
+ * - 点击按钮后直接自动发送 data
508
+ */
509
+ enter?: boolean;
510
+ /**
511
+ * - 指令是否带引用回复本消息
512
+ */
513
+ reply?: boolean;
514
+ /**
515
+ * - 是否仅群管理员可操作
516
+ */
517
+ admin?: boolean;
518
+ /**
519
+ * - 有权限点击的用户UID列表 群聊、私聊
520
+ */
521
+ list?: string[];
522
+ /**
523
+ * - 有权限点击的用户UID列表 频道
524
+ */
525
+ role?: string[];
526
+ /**
527
+ * - 客户端不支持本 action 的时候,弹出的 toast 文案
528
+ */
529
+ tips?: string;
530
+ }
531
+ /**
532
+ * - 按钮 构建单行多个按钮
493
533
  */
494
534
  export interface ButtonElement {
495
535
  type: 'button';
496
- data: {
497
- /**
498
- * - 按钮显示文本
499
- */
500
- text: string;
501
- /**
502
- * - 是否为回调按钮
503
- * @default false
504
- */
505
- callback?: boolean;
506
- /**
507
- * - 跳转按钮
508
- */
509
- link?: string;
510
- /**
511
- * - 操作相关的数据
512
- */
513
- data?: string;
514
- /**
515
- * - 按钮点击后显示的文字,不传为text
516
- */
517
- show?: string;
518
- /**
519
- * - 按钮样式:0 灰色线框,1 蓝色线框
520
- */
521
- style?: number;
522
- /**
523
- * - 点击按钮后直接自动发送 data
524
- */
525
- enter?: boolean;
526
- /**
527
- * - 指令是否带引用回复本消息
528
- */
529
- reply?: boolean;
530
- /**
531
- * - 是否仅群管理员可操作
532
- */
533
- admin?: boolean;
534
- /**
535
- * - 有权限点击的用户UID列表 群聊、私聊
536
- */
537
- list?: string[];
538
- /**
539
- * - 有权限点击的用户UID列表 频道
540
- */
541
- role?: string[];
542
- /**
543
- * - 客户端不支持本 action 的时候,弹出的 toast 文案
544
- */
545
- tips?: string;
546
- };
536
+ data: Array<Button>;
547
537
  }
548
538
  /**
549
- * - 按钮组
539
+ * - 按钮组 构建多行多个按钮
550
540
  */
551
- export interface RowElement extends Element {
552
- type: 'rows';
553
- rows: Array<ButtonElement>;
541
+ export interface KeyBoardElement extends Element {
542
+ type: 'keyboard';
543
+ rows: Array<Array<Button>>;
554
544
  }
555
545
  /**
556
546
  * - 长消息元素
@@ -562,7 +552,7 @@ export interface LongMsgElement extends Element {
562
552
  */
563
553
  id: string;
564
554
  }
565
- export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VoiceElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement | ButtonElement | RowElement | RecordElement | LongMsgElement | TplMarkdownElement | RawMarkdownElement;
555
+ export type KarinElement = TextElement | AtElement | FaceElement | BubbleFaceElement | ReplyElement | ImageElement | VideoElement | BasketballElement | DiceElement | RpsElement | PokeElement | MusicElement | WeatherElement | LocationElement | ShareElement | GiftElement | MarketFaceElement | ForwardElement | ContactElement | JsonElement | XmlElement | FileElement | ButtonElement | KeyBoardElement | RecordElement | LongMsgElement | TplMarkdownElement | RawMarkdownElement;
566
556
  /**
567
557
  * - 构建自定义转发节点 此元素仅可通过专用接口发送 不支持混合发送
568
558
  */
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 原生Markdown消息结构
3
+ */
4
+ export interface RawMarkdownType {
5
+ /** markdown文本 */
6
+ content: string;
7
+ }
8
+ /**
9
+ * 模板Markdown消息结构
10
+ */
11
+ export interface TplMarkdownType {
12
+ /**
13
+ * - 模板ID
14
+ */
15
+ custom_template_id: string;
16
+ /**
17
+ * - 模板参数
18
+ */
19
+ params: Array<{
20
+ /**
21
+ * - 模板参数键名称
22
+ */
23
+ key: string;
24
+ /**
25
+ * - 模板参数值
26
+ */
27
+ values: Array<string>;
28
+ }>;
29
+ }
30
+ /**
31
+ * Markdown消息结构
32
+ * @param T 是否为原生结构
33
+ */
34
+ export type MarkdownType<T extends boolean> = T extends true ? RawMarkdownType : TplMarkdownType;
35
+ /**
36
+ * 原生keyboard消息结构
37
+ */
38
+ export interface RawKeyboardType {
39
+ content: {
40
+ rows: Array<{
41
+ buttons: Array<ButtonType>;
42
+ }>;
43
+ };
44
+ }
45
+ /**
46
+ * 模板keyboard消息结构
47
+ */
48
+ export interface TplKeyboardType {
49
+ /** 模板ID */
50
+ id: string;
51
+ }
52
+ /**
53
+ * 按钮消息结构
54
+ */
55
+ export interface ButtonType {
56
+ /** 按钮ID:在一个keyboard消息内设置唯一 */
57
+ id: string;
58
+ /** 按钮上的文字 */
59
+ render_data: {
60
+ /** 按钮上的文字 */
61
+ label: string;
62
+ /** 点击后按钮的上文字 */
63
+ visited_label: string;
64
+ /**
65
+ * 按钮样式
66
+ * - 0-灰色线框
67
+ * - 1-蓝色线框
68
+ * - 2-特殊样式按钮
69
+ * - 3-红色文字
70
+ * - 4-白色填充
71
+ */
72
+ style: number;
73
+ };
74
+ /** 操作相关的数据 */
75
+ action: {
76
+ /** 设置 0 跳转按钮:http 或 小程序 客户端识别 scheme,设置 1 回调按钮:回调后台接口, data 传给后台,设置 2 指令按钮:自动在输入框插入 @bot data */
77
+ type: number;
78
+ /** 权限设置 */
79
+ permission: {
80
+ /** 0 指定用户可操作,1 仅管理者可操作,2 所有人可操作,3 指定身份组可操作(仅频道可用) */
81
+ type: number;
82
+ /** 有权限的用户 id 的列表 */
83
+ specify_user_ids?: string[];
84
+ /** 有权限的身份组 id 的列表(仅频道可用) */
85
+ specify_role_ids?: string[];
86
+ };
87
+ /** 操作相关的数据 */
88
+ data: string;
89
+ /** 指令按钮可用,指令是否带引用回复本消息,默认 false */
90
+ reply?: boolean;
91
+ /** 指令按钮可用,点击按钮后直接自动发送 data,默认 false */
92
+ enter?: boolean;
93
+ /** 本字段仅在指令按钮下有效,设置后后会忽略 action.enter 配置。
94
+ 设置为 1 时 ,点击按钮自动唤起启手Q选图器,其他值暂无效果。
95
+ (仅支持手机端版本 8983+ 的单聊场景,桌面端不支持) */
96
+ anchor?: number;
97
+ /** 【已弃用】可操作点击的次数,默认不限 */
98
+ click_limit?: number;
99
+ /** 【已弃用】指令按钮可用,弹出子频道选择器,默认 false */
100
+ at_bot_show_channel_list?: boolean;
101
+ /** 客户端不支持本action的时候,弹出的toast文案 */
102
+ unsupport_tips: string;
103
+ };
104
+ }
105
+ /**
106
+ * Keyboard消息结构
107
+ * @param T 是否为原生结构
108
+ */
109
+ export type KeyboardType<T extends boolean> = T extends true ? RawKeyboardType : TplKeyboardType;
110
+ /**
111
+ * Ark消息结构
112
+ */
113
+ export interface ArkType {
114
+ /** 模版 id,管理端可获得或内邀申请获得 */
115
+ template_id: number;
116
+ /** {key: xxx, value: xxx},模版内变量与填充值的kv映射 */
117
+ kv: Array<{
118
+ obj_kv: Array<{
119
+ key: string;
120
+ value: string;
121
+ }>;
122
+ }>;
123
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -34,6 +34,10 @@ export interface KarinMessageType extends KarinEventType {
34
34
  * - 消息图片
35
35
  */
36
36
  image: string[];
37
+ /**
38
+ * - 语音url
39
+ */
40
+ record: string;
37
41
  file: any;
38
42
  /**
39
43
  * 是否atBot
@@ -88,6 +92,7 @@ export declare class KarinMessage implements KarinMessageType {
88
92
  replyCallback: KarinMessageType['replyCallback'];
89
93
  msg: KarinMessageType['msg'];
90
94
  image: KarinMessageType['image'];
95
+ record: KarinMessageType['record'];
91
96
  file: KarinMessageType['file'];
92
97
  atBot: KarinMessageType['atBot'];
93
98
  atAll: KarinMessageType['atAll'];
@@ -30,6 +30,7 @@ export class KarinMessage {
30
30
  replyCallback;
31
31
  msg;
32
32
  image;
33
+ record;
33
34
  file;
34
35
  atBot;
35
36
  atAll;
@@ -63,6 +64,7 @@ export class KarinMessage {
63
64
  this.msg = '';
64
65
  this.image = [];
65
66
  this.file = {};
67
+ this.record = '';
66
68
  this.atBot = false;
67
69
  this.atAll = false;
68
70
  this.at = [];
@@ -1,6 +1,7 @@
1
1
  export * from './adapter/base.js';
2
2
  export * from './config/config.js';
3
3
  export * from './element/element.js';
4
+ export * from './element/qqbot.js';
4
5
  export * from './event/index.js';
5
6
  export * from './logger/logger.js';
6
7
  export * from './render/render.js';
@@ -1,6 +1,7 @@
1
1
  export * from './adapter/base.js'
2
2
  export * from './config/config.js'
3
3
  export * from './element/element.js'
4
+ export * from './element/qqbot.js'
4
5
  export * from './event/index.js'
5
6
  export * from './logger/logger.js'
6
7
  export * from './render/render.js'
@@ -0,0 +1,23 @@
1
+ import { Logger as LoggerType } from 'log4js';
2
+ import { Logger } from '../../types/index.js';
3
+ import { Lang, Mode, Runner } from '../../cli/karin.js';
4
+ declare global {
5
+ namespace NodeJS {
6
+ interface ProcessEnv {
7
+ /** 重启次数 */
8
+ karin_app_start_count: string;
9
+ /** 是否为监听模式 yes=true no=false */
10
+ karin_app_watch: string;
11
+ /** 运行模式 "dev" | "prod" */
12
+ karin_app_mode: `${Mode}`;
13
+ /** 语言环境 "js" | "ts" */
14
+ karin_app_lang: `${Lang}`;
15
+ /** 运行器 "node" | "tsx" | "pm2" */
16
+ karin_app_runner: `${Runner}`;
17
+ }
18
+ }
19
+ }
20
+ declare global {
21
+ var logger: LoggerType & Logger;
22
+ }
23
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import { AxiosRequestConfig } from 'axios';
3
3
  import { Readable } from 'stream';
4
- import { dirName, fileName, KarinElement, NodeElement } from '../../types/index.js';
4
+ import { ButtonElement, ButtonType, dirName, fileName, KarinElement, NodeElement, KeyBoardElement } from '../../types/index.js';
5
5
  /**
6
6
  * 常用方法
7
7
  */
@@ -174,6 +174,13 @@ declare class Common {
174
174
  /** 需要写入的注释 */
175
175
  comment: string;
176
176
  }[]): void;
177
+ /**
178
+ * karin按钮转换为QQBot官方按钮 返回官方按钮结构
179
+ * @param button - 按钮
180
+ */
181
+ buttonToQQBot(button: ButtonElement | KeyBoardElement): Array<{
182
+ buttons: Array<ButtonType>;
183
+ }>;
177
184
  }
178
185
  /**
179
186
  * 常用方法
@@ -324,18 +324,10 @@ class Common {
324
324
  * @param elements - 消息内容
325
325
  */
326
326
  makeMessage(elements) {
327
- /** 将msg格式化为数组 */
328
327
  if (!Array.isArray(elements))
329
328
  elements = [elements];
330
329
  const message = [];
331
- elements.forEach(v => {
332
- if (typeof v === 'string') {
333
- message.push(segment.text(v));
334
- }
335
- else {
336
- message.push(v);
337
- }
338
- });
330
+ elements.forEach(v => { typeof v === 'string' ? message.push(segment.text(v)) : message.push(v); });
339
331
  return message;
340
332
  }
341
333
  /**
@@ -468,7 +460,6 @@ class Common {
468
460
  break;
469
461
  case 'video':
470
462
  case 'image':
471
- case 'voice':
472
463
  case 'record':
473
464
  case 'file': {
474
465
  let file;
@@ -534,11 +525,8 @@ class Common {
534
525
  logs.push(`[markdown_tpl:${JSON.stringify(content)}]`);
535
526
  break;
536
527
  }
537
- case 'rows': {
538
- const rows = [];
539
- for (const v of val.rows)
540
- rows.push(JSON.stringify(v.data));
541
- logs.push(`[rows:${JSON.stringify(rows)}]`);
528
+ case 'keyboard': {
529
+ logs.push(`[rows:${JSON.stringify(val.rows)}]`);
542
530
  break;
543
531
  }
544
532
  case 'button':
@@ -584,6 +572,55 @@ class Common {
584
572
  });
585
573
  yaml.save();
586
574
  }
575
+ /**
576
+ * karin按钮转换为QQBot官方按钮 返回官方按钮结构
577
+ * @param button - 按钮
578
+ */
579
+ buttonToQQBot(button) {
580
+ let id = 0;
581
+ const rows = [];
582
+ /** 格式化为多行 */
583
+ const list = [];
584
+ button.type === 'button' ? list.push(button.data) : list.push(...button.rows);
585
+ for (const row of list) {
586
+ const buttons = [];
587
+ for (const i of row) {
588
+ const type = i.link ? 0 : (i.callback ? 1 : i.type ?? 2);
589
+ const data = {
590
+ id: String(id),
591
+ render_data: {
592
+ label: i.text,
593
+ style: i.style ?? 0,
594
+ visited_label: i.show || i.text,
595
+ },
596
+ action: {
597
+ type,
598
+ data: i.data || i.link || i.text,
599
+ unsupport_tips: i.tips || '.',
600
+ permission: { type: 2 },
601
+ },
602
+ };
603
+ if (i.enter)
604
+ data.action.enter = true;
605
+ if (i.reply)
606
+ data.action.reply = true;
607
+ if (i.admin)
608
+ data.action.permission.type = 1;
609
+ if (i.list) {
610
+ data.action.permission.type = 0;
611
+ data.action.permission.specify_user_ids = i.list;
612
+ }
613
+ else if (i.role) {
614
+ data.action.permission.type = 3;
615
+ data.action.permission.specify_role_ids = i.role;
616
+ }
617
+ buttons.push(data);
618
+ id++;
619
+ }
620
+ rows.push({ buttons });
621
+ }
622
+ return rows;
623
+ }
587
624
  }
588
625
  /**
589
626
  * 常用方法
@@ -1,4 +1,4 @@
1
- import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TplMarkdownElement, RawMarkdownElement, NodeElement, KarinElement, LongMsgElement, RecordElement } from '../../types/index.js';
1
+ import { TextElement, AtElement, ImageElement, FaceElement, BubbleFaceElement, ReplyElement, VideoElement, BasketballElement, DiceElement, RpsElement, PokeElement, MusicElement, WeatherElement, LocationElement, ShareElement, GiftElement, MarketFaceElement, ForwardElement, ContactElement, JsonElement, XmlElement, FileElement, ButtonElement, CustomMusicElemen, TplMarkdownElement, RawMarkdownElement, NodeElement, KarinElement, LongMsgElement, RecordElement, KeyBoardElement, Button } from '../../types/index.js';
2
2
  export declare const segment: {
3
3
  /**
4
4
  * 纯文本
@@ -70,12 +70,10 @@ export declare const segment: {
70
70
  }): ImageElement;
71
71
  /**
72
72
  * 语音
73
- * @description 即将废弃,请使用voice
74
73
  * @param file - 语音URL或路径、Base64
75
74
  * @param magic - 是否魔法语音,默认为 false
76
75
  * @param md5 - 语音md5
77
76
  * @param name - 语音名称
78
- * @returns {VoiceElement} 语音元素
79
77
  */
80
78
  record(file: string, magic?: boolean, md5?: string, name?: string): RecordElement;
81
79
  /**
@@ -84,8 +82,6 @@ export declare const segment: {
84
82
  * @param magic - 是否魔法语音,默认为 false
85
83
  * @param md5 - 语音md5
86
84
  * @param name - 语音名称
87
- * @returns {VoiceElement} 语音元素
88
- * @deprecated 即将废弃 请使用segment.record
89
85
  */
90
86
  voice(file: string, magic?: boolean, md5?: string, name?: string): RecordElement;
91
87
  /**
@@ -260,15 +256,19 @@ export declare const segment: {
260
256
  */
261
257
  markdown_tpl(custom_template_id: TplMarkdownElement["custom_template_id"], params: TplMarkdownElement["params"]): TplMarkdownElement;
262
258
  /**
263
- * 按钮
259
+ * 按钮 构建单行单个(obj)、多个按钮(obj[])
264
260
  * @param data - 按钮数据
265
261
  * @returns {ButtonElement} 按钮元素
266
262
  */
267
- button(data: ButtonElement["data"]): ButtonElement;
268
- rows(data: Array<ButtonElement["data"]>): {
269
- type: "rows";
270
- rows: Array<ButtonElement>;
263
+ button(data: Button | Array<Button>): {
264
+ type: ButtonElement["type"];
265
+ data: Array<Button>;
271
266
  };
267
+ /**
268
+ * 多维按钮
269
+ * @param data - 按钮数据
270
+ */
271
+ keyboard(data: Array<Button> | Array<Array<Button>>): KeyBoardElement;
272
272
  /**
273
273
  * 转发自定义节点
274
274
  * @param user_id - 用户ID
@@ -90,12 +90,10 @@ export const segment = new (class Segment {
90
90
  }
91
91
  /**
92
92
  * 语音
93
- * @description 即将废弃,请使用voice
94
93
  * @param file - 语音URL或路径、Base64
95
94
  * @param magic - 是否魔法语音,默认为 false
96
95
  * @param md5 - 语音md5
97
96
  * @param name - 语音名称
98
- * @returns {VoiceElement} 语音元素
99
97
  */
100
98
  record(file, magic = false, md5 = '', name = '') {
101
99
  return {
@@ -112,8 +110,6 @@ export const segment = new (class Segment {
112
110
  * @param magic - 是否魔法语音,默认为 false
113
111
  * @param md5 - 语音md5
114
112
  * @param name - 语音名称
115
- * @returns {VoiceElement} 语音元素
116
- * @deprecated 即将废弃 请使用segment.record
117
113
  */
118
114
  voice(file, magic = false, md5 = '', name = '') {
119
115
  return {
@@ -404,25 +400,39 @@ export const segment = new (class Segment {
404
400
  };
405
401
  }
406
402
  /**
407
- * 按钮
403
+ * 按钮 构建单行单个(obj)、多个按钮(obj[])
408
404
  * @param data - 按钮数据
409
405
  * @returns {ButtonElement} 按钮元素
410
406
  */
411
407
  button(data) {
412
408
  return {
413
409
  type: 'button',
414
- data,
410
+ data: Array.isArray(data) ? data : [data],
415
411
  };
416
412
  }
417
- rows(data) {
413
+ /**
414
+ * 多维按钮
415
+ * @param data - 按钮数据
416
+ */
417
+ keyboard(data) {
418
+ /** 每一个元素为一行按钮 每一行按钮存在多个 */
418
419
  const rows = [];
419
420
  if (!Array.isArray(data))
420
421
  data = [data];
421
422
  for (const i of data) {
422
- rows.push(this.button(i));
423
- continue;
423
+ /** 如果还是数组 说明是单行多个按钮 */
424
+ if (Array.isArray(i)) {
425
+ const button = [];
426
+ for (const v of i)
427
+ button.push(v);
428
+ rows.push(button);
429
+ }
430
+ else {
431
+ /** 单行 单个按钮 */
432
+ rows.push([i]);
433
+ }
424
434
  }
425
- return { type: 'rows', rows };
435
+ return { type: 'keyboard', rows };
426
436
  }
427
437
  /**
428
438
  * 转发自定义节点
@@ -42,11 +42,9 @@ export const exec = (cmd, log = true, options = { cwd: process.cwd(), encoding:
42
42
  */
43
43
  export const execs = (cmd, options = { cwd: process.cwd(), encoding: 'utf-8' }) => {
44
44
  return new Promise((resolve, reject) => {
45
- execCmd(cmd, options, (error, stdout, stderr) => {
45
+ execCmd(cmd, options, (error, stdout) => {
46
46
  if (error)
47
47
  return reject(error);
48
- if (stderr)
49
- console.error(stderr);
50
48
  resolve(stdout.trim());
51
49
  });
52
50
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-karin",
3
- "version": "0.10.5",
3
+ "version": "0.10.7",
4
4
  "private": false,
5
5
  "description": "基于 Kritor 进行开发的nodejs机器人框架",
6
6
  "homepage": "https://github.com/KarinJS/Karin",