onebots 0.4.37 → 0.4.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <div align="center">
2
- <h1>使用ts实现的oneBot应用启动器,支持icqqqq官方机器人</h1>
2
+ <h1>使用ts实现的oneBot应用启动器,支持icqqqq官方机器人以及钉钉机器人</h1>
3
3
  <p>
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/onebots)](https://www.npmjs.com/package/onebots) [![Release and Publish](https://github.com/icqqjs/onebots/actions/workflows/release.yml/badge.svg?branch=master&event=push)](https://github.com/icqqjs/onebots/actions/workflows/release.yml) [![dm](https://shields.io/npm/dm/onebots)](https://www.npmjs.com/package/onebots) [![oneBot V11](https://img.shields.io/badge/OneBot-11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://onebot.dev/)
@@ -41,10 +41,13 @@ onebots
41
41
  npm init -y
42
42
  ```
43
43
 
44
- ## 2. 安装onebots和icqq
44
+ ## 2. 安装onebots以及对应适配器的依赖
45
45
 
46
46
  ```shell
47
- npm install onebots icqq
47
+ npm install onebots
48
+ npm install icqq # 如需使用icqq适配器,请务必安装
49
+ npm install qq-group-bot # 如需使用qq官方机器人适配器,请务必安装
50
+ npm install node-dd-bot # 如需使用钉钉机器人适配器,请务必安装
48
51
  npm install sqlite3 # 如果你需要使用 OneBot11 请自行安装该依赖
49
52
  ```
50
53
 
@@ -124,7 +127,15 @@ qq.123456789: # `${适配器名称}:${appId}`
124
127
  - 'INTERACTION' # 互动事件
125
128
  - 'PUBLIC_GUILD_MESSAGES' # 公域机器人频道消息事件,私域机器人请注释
126
129
  # 。。。其他配置项参见上方对应oneBot版本的通用配置
127
-
130
+
131
+ dingtalk.abcedfg: # `${适配器名称}:${clientId}`
132
+ versions:
133
+ - version: V11
134
+ - version: V12
135
+ protocol:
136
+ clientSecret: '' # 钉钉机器人秘钥 必填
137
+ username: '钉钉机器人' #钉钉后台配置的机器人名称 不填则显示'钉钉机器人'
138
+ avatar: '' # 机器人头像 不填则显示钉钉logo
128
139
  ```
129
140
 
130
141
  # 配置解释
@@ -0,0 +1,42 @@
1
+ import { Adapter } from "../../adapter";
2
+ import { App } from "../../server/app";
3
+ import { OneBot } from "../../onebot";
4
+ import { Bot, Sendable } from "node-dd-bot";
5
+ export default class DingtalkAdapter extends Adapter<'dingtalk'> {
6
+ #private;
7
+ constructor(app: App, config: DingtalkAdapter.Config);
8
+ startOneBot(oneBot: OneBot<Bot>): Promise<() => void>;
9
+ getBaseInfo(uin: string): {
10
+ username: string;
11
+ avatar: string;
12
+ };
13
+ setOnline(uin: string): Promise<void>;
14
+ setOffline(uin: string): Promise<void>;
15
+ createOneBot(uin: string, protocol: Bot.Options, versions: OneBot.Config[]): OneBot;
16
+ call(uin: string, version: string, method: string, args?: any[]): Promise<any>;
17
+ sendPrivateMessage<V extends OneBot.Version>(uin: string, version: V, args: [string, OneBot.MessageElement<V>[]]): Promise<OneBot.MessageRet<V>>;
18
+ sendGroupMessage<V extends OneBot.Version>(uin: string, version: V, args: [string, OneBot.MessageElement<V>[]]): Promise<OneBot.MessageRet<V>>;
19
+ fromSegment<V extends OneBot.Version>(version: V, segment: OneBot.Segment<V> | OneBot.Segment<V>[]): OneBot.MessageElement<V>[];
20
+ toSegment<V extends OneBot.Version, M = Sendable>(version: V, message: M): OneBot.Segment<V>[];
21
+ fromCqcode<V extends OneBot.Version>(version: V, message: string): OneBot.MessageElement<V>[];
22
+ toCqcode<V extends OneBot.Version>(version: V, messageArr: OneBot.MessageElement<V>[]): string;
23
+ formatEventPayload<V extends OneBot.Version>(version: V, event: string, data: any): OneBot.Payload<V>;
24
+ start(uin: string): Promise<void>;
25
+ stop(uin?: string): Promise<void>;
26
+ getSelfInfo<V extends OneBot.Version>(uin: string, version: V): OneBot.SelfInfo<V>;
27
+ }
28
+ declare module '../../adapter' {
29
+ namespace Adapter {
30
+ interface Configs {
31
+ dingtalk: DingtalkAdapter.Config;
32
+ }
33
+ }
34
+ }
35
+ export declare namespace DingtalkAdapter {
36
+ interface Config extends Adapter.Config<'dingtalk'> {
37
+ protocol: Omit<Bot.Options, 'clientId'> & {
38
+ username?: string;
39
+ avatar?: string;
40
+ };
41
+ }
42
+ }
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
+ };
30
+ var _DingtalkAdapter_disposes;
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ const adapter_1 = require("../../adapter");
33
+ const onebot_1 = require("../../onebot");
34
+ const node_dd_bot_1 = require("node-dd-bot");
35
+ const path = __importStar(require("path"));
36
+ class DingtalkAdapter extends adapter_1.Adapter {
37
+ constructor(app, config) {
38
+ super(app, 'dingtalk', config);
39
+ _DingtalkAdapter_disposes.set(this, new Map());
40
+ this.icon = `https://img.alicdn.com/imgextra/i4/O1CN01RtfAks1Xa6qJFAekm_!!6000000002939-2-tps-128-128.png`;
41
+ }
42
+ async startOneBot(oneBot) {
43
+ await this.setOnline(oneBot.uin);
44
+ const selfInfo = this.getBaseInfo(oneBot.uin);
45
+ oneBot.avatar = selfInfo.avatar;
46
+ oneBot.nickname = selfInfo.username;
47
+ const pkg = require(path.resolve(path.dirname(require.resolve('node-dd-bot')), '../package.json'));
48
+ oneBot.dependency = `node-dd-bot v${pkg.version}`;
49
+ const disposeArr = [];
50
+ const clean = () => {
51
+ while (disposeArr.length > 0) {
52
+ disposeArr.pop()();
53
+ }
54
+ oneBot.internal.stop();
55
+ };
56
+ const messageHandler = (event) => {
57
+ this.emit('message.receive', oneBot.uin, event);
58
+ };
59
+ oneBot.internal.on('message', messageHandler);
60
+ disposeArr.push(() => {
61
+ oneBot.internal.off('message', messageHandler);
62
+ });
63
+ return clean;
64
+ }
65
+ getBaseInfo(uin) {
66
+ const config = this.app.config[`${this.platform}.${uin}`].protocol;
67
+ return {
68
+ avatar: config.avatar || this.icon,
69
+ username: config.username || '钉钉机器人',
70
+ };
71
+ }
72
+ async setOnline(uin) {
73
+ const oneBot = this.getOneBot(uin);
74
+ await oneBot?.internal.start();
75
+ oneBot.status = onebot_1.OneBotStatus.Good;
76
+ }
77
+ async setOffline(uin) {
78
+ const oneBot = this.getOneBot(uin);
79
+ await oneBot?.internal.stop();
80
+ oneBot.status = onebot_1.OneBotStatus.Bad;
81
+ }
82
+ createOneBot(uin, protocol, versions) {
83
+ const oneBot = super.createOneBot(uin, protocol, versions);
84
+ oneBot.internal = new node_dd_bot_1.Bot({
85
+ clientId: oneBot.uin,
86
+ log_level: this.app.config.log_level,
87
+ ...protocol
88
+ });
89
+ oneBot.status = onebot_1.OneBotStatus.Online;
90
+ return oneBot;
91
+ }
92
+ call(uin, version, method, args) {
93
+ const oneBot = this.oneBots.get(uin);
94
+ if (!oneBot) {
95
+ throw new Error(`未找到账号${uin}`);
96
+ }
97
+ if (typeof this[method] === 'function')
98
+ return this[method](uin, version, args);
99
+ if (typeof oneBot.internal[method] !== 'function')
100
+ throw onebot_1.OneBot.UnsupportedMethodError;
101
+ try {
102
+ return oneBot.internal[method](...(args || []));
103
+ }
104
+ catch (e) {
105
+ throw new Error(`call internal method error:${e.message}`);
106
+ }
107
+ }
108
+ async sendPrivateMessage(uin, version, args) {
109
+ const [user_id, message] = args;
110
+ return this.oneBots.get(uin)?.internal.sendPrivateMsg(user_id, message.map(item => {
111
+ const { type, data } = item;
112
+ return {
113
+ type,
114
+ ...data
115
+ };
116
+ }));
117
+ }
118
+ async sendGroupMessage(uin, version, args) {
119
+ const [group_id, message] = args;
120
+ return this.oneBots.get(uin)?.internal.sendGroupMsg(group_id, message.map(item => {
121
+ const { type, data } = item;
122
+ return {
123
+ type,
124
+ ...data
125
+ };
126
+ }));
127
+ }
128
+ fromSegment(version, segment) {
129
+ return [].concat(segment).map(item => {
130
+ if (typeof item === "string")
131
+ return {
132
+ type: 'text',
133
+ data: {
134
+ text: item
135
+ }
136
+ };
137
+ return item;
138
+ });
139
+ }
140
+ toSegment(version, message) {
141
+ return [].concat(message).map(item => {
142
+ if (!item || typeof item !== "object")
143
+ return {
144
+ type: 'text',
145
+ data: {
146
+ text: item
147
+ }
148
+ };
149
+ const { type, data, ...other } = item;
150
+ return {
151
+ type,
152
+ data: {
153
+ ...data,
154
+ ...other
155
+ }
156
+ };
157
+ });
158
+ }
159
+ fromCqcode(version, message) {
160
+ const regExpMatchArray = message.match(/\[CQ:([a-z]+),(!])+]/g);
161
+ if (!regExpMatchArray)
162
+ return [
163
+ {
164
+ type: 'text',
165
+ data: {
166
+ text: message
167
+ }
168
+ }
169
+ ];
170
+ const result = [];
171
+ for (const match of regExpMatchArray) {
172
+ const [type, ...valueArr] = match.substring(1, match.length - 1).split(',');
173
+ result.push({
174
+ type: type,
175
+ data: Object.fromEntries(valueArr.map(item => {
176
+ const [key, value] = item.split('=');
177
+ return [key, value];
178
+ }))
179
+ });
180
+ }
181
+ return result;
182
+ }
183
+ toCqcode(version, messageArr) {
184
+ return [].concat(messageArr).map(item => {
185
+ const dataStr = Object.entries(item.data).map(([key, value]) => {
186
+ // is Buffer
187
+ if (value instanceof Buffer)
188
+ return `${key}=${value.toString('base64')}`;
189
+ // is Object
190
+ if (value instanceof Object)
191
+ return `${key}=${JSON.stringify(value)}`;
192
+ // is Array
193
+ if (value instanceof Array)
194
+ return `${key}=${value.map(v => JSON.stringify(v)).join(',')}`;
195
+ // is String
196
+ return `${key}=${item[key]}`;
197
+ });
198
+ return `[CQ:${item.type},${dataStr.join(',')}]`;
199
+ }).join('');
200
+ }
201
+ formatEventPayload(version, event, data) {
202
+ const result = {
203
+ id: data.id,
204
+ [version === 'V12' ? 'type' : 'post_type']: event,
205
+ version: version,
206
+ self: {
207
+ platform: 'qq',
208
+ user_id: data.self_id
209
+ },
210
+ detail_type: data.message_type || data.notice_type || data.request_type,
211
+ platform: 'qq',
212
+ time: data.timestamp,
213
+ ...data,
214
+ };
215
+ delete result.bot;
216
+ return result;
217
+ }
218
+ async start(uin) {
219
+ const startOneBots = [...this.oneBots.values()].filter(oneBot => {
220
+ return uin ? oneBot.uin === uin : true;
221
+ });
222
+ for (const oneBot of startOneBots) {
223
+ __classPrivateFieldGet(this, _DingtalkAdapter_disposes, "f").set(oneBot.uin, await this.startOneBot(oneBot));
224
+ }
225
+ const { protocol } = this.config;
226
+ await super.start();
227
+ }
228
+ async stop(uin) {
229
+ const stopOneBots = [...this.oneBots.values()].filter(oneBot => {
230
+ return uin ? oneBot.uin === uin : true;
231
+ });
232
+ for (const oneBot of stopOneBots) {
233
+ const dispose = __classPrivateFieldGet(this, _DingtalkAdapter_disposes, "f").get(oneBot.uin);
234
+ if (dispose) {
235
+ dispose();
236
+ }
237
+ }
238
+ await super.stop();
239
+ }
240
+ getSelfInfo(uin, version) {
241
+ const oneBot = this.oneBots.get(uin);
242
+ return {
243
+ nickname: oneBot?.internal?.nickname,
244
+ status: onebot_1.OneBotStatus.Online,
245
+ };
246
+ }
247
+ }
248
+ _DingtalkAdapter_disposes = new WeakMap();
249
+ exports.default = DingtalkAdapter;
@@ -0,0 +1,10 @@
1
+ export declare function remove<T>(list: T[], item: T): void;
2
+ export declare function deepClone<T extends object>(obj: T): any;
3
+ /**
4
+ * 寻找数组中最后一个符合条件的元素下标
5
+ * @param list 数组
6
+ * @param predicate 条件
7
+ * @returns {number} 元素下标,未找到返回-1
8
+ */
9
+ export declare function findLastIndex<T>(list: T[], predicate: (item: T, index: number) => boolean): number;
10
+ export declare function trimQuote(str: string): string;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trimQuote = exports.findLastIndex = exports.deepClone = exports.remove = void 0;
4
+ function remove(list, item) {
5
+ const index = list.indexOf(item);
6
+ if (index !== -1)
7
+ list.splice(index, 1);
8
+ }
9
+ exports.remove = remove;
10
+ function deepClone(obj) {
11
+ if (typeof obj !== "object")
12
+ return obj;
13
+ if (Array.isArray(obj))
14
+ return obj.map(deepClone);
15
+ const Constructor = obj.constructor;
16
+ let newObj = Constructor();
17
+ for (let key in obj) {
18
+ newObj[key] = deepClone(obj[key]);
19
+ }
20
+ return newObj;
21
+ }
22
+ exports.deepClone = deepClone;
23
+ /**
24
+ * 寻找数组中最后一个符合条件的元素下标
25
+ * @param list 数组
26
+ * @param predicate 条件
27
+ * @returns {number} 元素下标,未找到返回-1
28
+ */
29
+ function findLastIndex(list, predicate) {
30
+ for (let i = list.length - 1; i >= 0; i--) {
31
+ if (predicate(list[i], i))
32
+ return i;
33
+ }
34
+ return -1;
35
+ }
36
+ exports.findLastIndex = findLastIndex;
37
+ function trimQuote(str) {
38
+ const quotes = [
39
+ [
40
+ '"',
41
+ '"',
42
+ ],
43
+ [
44
+ "'",
45
+ "'",
46
+ ],
47
+ [
48
+ '`',
49
+ '`',
50
+ ],
51
+ [
52
+ '“',
53
+ '”',
54
+ ],
55
+ [
56
+ '‘',
57
+ '’',
58
+ ]
59
+ ];
60
+ for (let i = 0; i < quotes.length; i++) {
61
+ const [start, end] = quotes[i];
62
+ if (str.startsWith(start) && str.endsWith(end)) {
63
+ return str.slice(1, -1);
64
+ }
65
+ }
66
+ return str;
67
+ }
68
+ exports.trimQuote = trimQuote;
@@ -52,3 +52,11 @@ qq.a: # `${适配器名称}:${账号}`
52
52
  - 'INTERACTION' # 互动事件
53
53
  - 'PUBLIC_GUILD_MESSAGES' # 公域机器人频道消息事件,私域机器人请注释
54
54
  # 。。。其他配置项参见上方对应oneBot版本的通用配置
55
+ dingtalk.abcedfg: # `${适配器名称}:${clientId}`
56
+ versions:
57
+ - version: V11
58
+ - version: V12
59
+ protocol:
60
+ clientSecret: '' # 钉钉机器人秘钥 必填
61
+ username: '钉钉机器人' #钉钉后台配置的机器人名称 不填则显示'钉钉机器人'
62
+ avatar: '' # 机器人头像 不填则显示钉钉logo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onebots",
3
- "version": "0.4.37",
3
+ "version": "0.4.38",
4
4
  "description": "基于icqq的多例oneBot实现",
5
5
  "engines": {
6
6
  "node": ">=16"
@@ -12,7 +12,7 @@
12
12
  "scripts": {
13
13
  "start": "node .",
14
14
  "build": "vite build && tsc --project tsconfig.json && tsc-alias -p tsconfig.json && cp -r src/config.sample.yaml lib/config.sample.yaml",
15
- "dev": "ts-node-dev -r tsconfig-paths/register ./src/bin.ts -c config.yaml -r qq -r icqq",
15
+ "dev": "ts-node-dev -r tsconfig-paths/register ./src/bin.ts -c config.yaml -r qq -r icqq -r dingtalk",
16
16
  "pub": "npm publish --access public",
17
17
  "lint": "prettier --check ./**/*.{ts,js}",
18
18
  "lint:fix": "prettier --write ./**/*.{ts,js,md}",
@@ -69,7 +69,8 @@
69
69
  ],
70
70
  "peerDependencies": {
71
71
  "icqq": "latest",
72
- "qq-group-bot": "^1.0.7"
72
+ "node-dd-bot": "latest",
73
+ "qq-group-bot": "latest"
73
74
  },
74
75
  "dependencies": {
75
76
  "@koa/router": "^10.1.1",