onebots 0.4.30 → 0.4.32
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/lib/adapters/icqq/index.js +7 -4
- package/lib/adapters/qq/index.js +8 -5
- package/lib/config.sample.yaml +0 -2
- package/lib/db.d.ts +19 -14
- package/lib/db.js +141 -50
- package/lib/service/V11/action/common.js +6 -2
- package/lib/service/V11/action/friend.d.ts +1 -1
- package/lib/service/V11/action/friend.js +2 -2
- package/lib/service/V11/db_entities.d.ts +5 -5
- package/lib/service/V11/db_entities.js +0 -61
- package/lib/service/V11/index.d.ts +2 -2
- package/lib/service/V11/index.js +45 -34
- package/lib/service/V12/index.d.ts +2 -0
- package/lib/service/V12/index.js +27 -14
- package/lib/utils.d.ts +10 -3
- package/lib/utils.js +100 -18
- package/package.json +2 -5
- package/lib/service/V11/db_sqlite.d.ts +0 -52
- package/lib/service/V11/db_sqlite.js +0 -115
|
@@ -96,7 +96,10 @@ class IcqqAdapter extends adapter_1.Adapter {
|
|
|
96
96
|
createOneBot(uin, protocol, versions) {
|
|
97
97
|
const oneBot = super.createOneBot(uin, protocol, versions);
|
|
98
98
|
__classPrivateFieldSet(this, _IcqqAdapter_password, this.app.config[`icqq.${uin}`].password, "f");
|
|
99
|
-
oneBot.internal = new icqq_1.Client((0, utils_1.deepMerge)(protocol, (0, utils_1.deepClone)(
|
|
99
|
+
oneBot.internal = new icqq_1.Client((0, utils_1.deepMerge)(protocol, (0, utils_1.deepClone)({
|
|
100
|
+
...exports.defaultIcqqConfig,
|
|
101
|
+
log_level: this.app.config.log_level
|
|
102
|
+
})));
|
|
100
103
|
return oneBot;
|
|
101
104
|
}
|
|
102
105
|
formatEventPayload(version, event, data) {
|
|
@@ -207,8 +210,8 @@ class IcqqAdapter extends adapter_1.Adapter {
|
|
|
207
210
|
toCqcode(version, messageArr) {
|
|
208
211
|
return [].concat(messageArr).map(item => {
|
|
209
212
|
if (item.type === 'text')
|
|
210
|
-
return item.data.text;
|
|
211
|
-
const dataStr = Object.entries(item.data).map(([key, value]) => {
|
|
213
|
+
return item.data?.text || item.text;
|
|
214
|
+
const dataStr = Object.entries(item.data || item).map(([key, value]) => {
|
|
212
215
|
// is Buffer
|
|
213
216
|
if (value instanceof Buffer)
|
|
214
217
|
return `${key}=${value.toString('base64')}`;
|
|
@@ -219,7 +222,7 @@ class IcqqAdapter extends adapter_1.Adapter {
|
|
|
219
222
|
if (value instanceof Array)
|
|
220
223
|
return `${key}=${value.map(v => JSON.stringify(v)).join(',')}`;
|
|
221
224
|
// is String
|
|
222
|
-
return `${key}=${item.data[key]}`;
|
|
225
|
+
return `${key}=${item.data?.[key] || item[key]}`;
|
|
223
226
|
});
|
|
224
227
|
return `[CQ:${item.type},${dataStr.join(',')}]`;
|
|
225
228
|
}).join('');
|
package/lib/adapters/qq/index.js
CHANGED
|
@@ -26,7 +26,6 @@ class QQAdapter extends adapter_1.Adapter {
|
|
|
26
26
|
}
|
|
27
27
|
qqBot.stop();
|
|
28
28
|
};
|
|
29
|
-
const _this = this;
|
|
30
29
|
const messageHandler = (event) => {
|
|
31
30
|
this.emit('message.receive', oneBot.uin, event);
|
|
32
31
|
};
|
|
@@ -73,10 +72,13 @@ class QQAdapter extends adapter_1.Adapter {
|
|
|
73
72
|
text: item
|
|
74
73
|
}
|
|
75
74
|
};
|
|
76
|
-
const { type,
|
|
75
|
+
const { type, data, ...other } = item;
|
|
77
76
|
return {
|
|
78
77
|
type,
|
|
79
|
-
data
|
|
78
|
+
data: {
|
|
79
|
+
...data,
|
|
80
|
+
...other
|
|
81
|
+
}
|
|
80
82
|
};
|
|
81
83
|
});
|
|
82
84
|
}
|
|
@@ -125,7 +127,7 @@ class QQAdapter extends adapter_1.Adapter {
|
|
|
125
127
|
formatEventPayload(version, event, data) {
|
|
126
128
|
const result = {
|
|
127
129
|
id: data.id,
|
|
128
|
-
type: event,
|
|
130
|
+
[version === 'V12' ? 'type' : 'post_type']: event,
|
|
129
131
|
version: version,
|
|
130
132
|
self: {
|
|
131
133
|
platform: 'qq',
|
|
@@ -133,9 +135,10 @@ class QQAdapter extends adapter_1.Adapter {
|
|
|
133
135
|
},
|
|
134
136
|
detail_type: data.message_type || data.notice_type || data.request_type,
|
|
135
137
|
platform: 'qq',
|
|
138
|
+
time: data.timestamp,
|
|
136
139
|
...data,
|
|
137
140
|
};
|
|
138
|
-
delete
|
|
141
|
+
delete result.bot;
|
|
139
142
|
return result;
|
|
140
143
|
}
|
|
141
144
|
async start(uin) {
|
package/lib/config.sample.yaml
CHANGED
package/lib/db.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
private readonly path;
|
|
1
|
+
export declare class JsonDB {
|
|
2
|
+
private readonly filePath;
|
|
4
3
|
private data;
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
constructor(filePath: string);
|
|
5
|
+
private init;
|
|
6
|
+
private write;
|
|
7
|
+
private read;
|
|
8
|
+
findIndex<T>(route: string, predicate: (value: T, index: number, obj: T[]) => unknown): number;
|
|
9
|
+
indexOf<T>(route: string, item: T): number;
|
|
10
|
+
get<T>(route: string, initialValue?: T): T | undefined;
|
|
11
|
+
set<T>(route: string, data: T): T;
|
|
12
|
+
delete(route: string): boolean;
|
|
13
|
+
private getArray;
|
|
14
|
+
unshift<T>(route: string, ...data: T[]): number;
|
|
15
|
+
shift<T>(route: string): T;
|
|
16
|
+
push<T>(route: string, ...data: T[]): number;
|
|
17
|
+
pop<T>(route: string): T;
|
|
18
|
+
splice<T>(route: string, index?: number, deleteCount?: number, ...data: T[]): T[];
|
|
19
|
+
find<T>(route: string, callback: (item: T) => boolean): T | undefined;
|
|
20
|
+
filter<T>(route: string, callback: (item: T) => boolean): T[];
|
|
16
21
|
}
|
package/lib/db.js
CHANGED
|
@@ -1,58 +1,149 @@
|
|
|
1
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
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
26
|
+
exports.JsonDB = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const utils_1 = require("./utils");
|
|
30
|
+
class JsonDB {
|
|
31
|
+
constructor(filePath) {
|
|
32
|
+
this.filePath = filePath;
|
|
9
33
|
this.data = {};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
34
|
+
const dir = path.dirname(this.filePath);
|
|
35
|
+
if (fs.existsSync(dir))
|
|
36
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
37
|
+
if (!this.filePath.endsWith('.jsondb'))
|
|
38
|
+
this.filePath = this.filePath + '.jsondb';
|
|
39
|
+
if (!fs.existsSync(this.filePath))
|
|
40
|
+
this.write();
|
|
41
|
+
this.init();
|
|
15
42
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
43
|
+
init() {
|
|
44
|
+
this.read();
|
|
45
|
+
}
|
|
46
|
+
write() {
|
|
47
|
+
fs.writeFileSync(this.filePath, (0, utils_1.stringifyObj)(this.data), 'utf8');
|
|
48
|
+
}
|
|
49
|
+
read() {
|
|
50
|
+
this.data = (0, utils_1.parseObjFromStr)(fs.readFileSync(this.filePath, 'utf8'));
|
|
51
|
+
}
|
|
52
|
+
findIndex(route, predicate) {
|
|
53
|
+
const arr = this.getArray(route);
|
|
54
|
+
return arr.findIndex(predicate);
|
|
55
|
+
}
|
|
56
|
+
indexOf(route, item) {
|
|
57
|
+
return this.findIndex(route, (value) => value === item);
|
|
58
|
+
}
|
|
59
|
+
get(route, initialValue) {
|
|
60
|
+
this.read();
|
|
61
|
+
const parentPath = route.split('.');
|
|
62
|
+
const key = parentPath.pop();
|
|
63
|
+
if (!key)
|
|
64
|
+
return this.data;
|
|
65
|
+
let temp = this.data;
|
|
66
|
+
while (parentPath.length) {
|
|
67
|
+
const currentKey = parentPath.shift();
|
|
68
|
+
if (!Reflect.has(temp, currentKey))
|
|
69
|
+
Reflect.set(temp, key, {});
|
|
70
|
+
temp = Reflect.get(temp, currentKey);
|
|
23
71
|
}
|
|
72
|
+
if (temp[key] !== undefined)
|
|
73
|
+
return temp[key];
|
|
74
|
+
temp[key] = initialValue;
|
|
75
|
+
this.write();
|
|
76
|
+
return initialValue;
|
|
77
|
+
}
|
|
78
|
+
set(route, data) {
|
|
79
|
+
const parentPath = route.split('.');
|
|
80
|
+
const key = parentPath.pop();
|
|
81
|
+
if (!key)
|
|
82
|
+
throw new SyntaxError(`route can't empty`);
|
|
83
|
+
const parentObj = this.get(parentPath.join('.'), {});
|
|
84
|
+
if (!parentObj)
|
|
85
|
+
throw new SyntaxError(`can't set property ${key} of undefined`);
|
|
86
|
+
parentObj[key] = data;
|
|
87
|
+
this.write();
|
|
88
|
+
return data;
|
|
89
|
+
}
|
|
90
|
+
delete(route) {
|
|
91
|
+
const parentPath = route.split('.');
|
|
92
|
+
const key = parentPath.pop();
|
|
93
|
+
if (!key)
|
|
94
|
+
throw new SyntaxError(`route can't empty`);
|
|
95
|
+
const parentObj = this.get(parentPath.join('.'), {});
|
|
96
|
+
if (!parentObj)
|
|
97
|
+
throw new SyntaxError(`property ${key} is not exist of undefined`);
|
|
98
|
+
const result = delete parentObj[key];
|
|
99
|
+
this.write();
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
getArray(route) {
|
|
103
|
+
if (!route)
|
|
104
|
+
throw new Error(`route can't empty`);
|
|
105
|
+
const arr = this.get(route, []);
|
|
106
|
+
if (!arr)
|
|
107
|
+
throw new SyntaxError(`route ${route} is not define`);
|
|
108
|
+
if (!Array.isArray(arr))
|
|
109
|
+
throw new TypeError(`data ${route} is not an Array`);
|
|
110
|
+
return arr;
|
|
111
|
+
}
|
|
112
|
+
unshift(route, ...data) {
|
|
113
|
+
const arr = this.getArray(route);
|
|
114
|
+
const result = arr.unshift(...data);
|
|
115
|
+
this.write();
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
shift(route) {
|
|
119
|
+
const arr = this.getArray(route);
|
|
120
|
+
const result = arr.shift();
|
|
121
|
+
this.write();
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
push(route, ...data) {
|
|
125
|
+
const arr = this.getArray(route);
|
|
126
|
+
const result = arr.push(...data);
|
|
127
|
+
this.write();
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
pop(route) {
|
|
131
|
+
const arr = this.getArray(route);
|
|
132
|
+
const result = arr.pop();
|
|
133
|
+
this.write();
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
splice(route, index = 0, deleteCount = 0, ...data) {
|
|
137
|
+
const arr = this.getArray(route);
|
|
138
|
+
const result = arr.splice(index, deleteCount, ...data);
|
|
139
|
+
this.write();
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
find(route, callback) {
|
|
143
|
+
return this.getArray(route).find(callback);
|
|
24
144
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (typeof value !== "object")
|
|
28
|
-
return value;
|
|
29
|
-
const saveValue = () => {
|
|
30
|
-
this.set(key, value);
|
|
31
|
-
};
|
|
32
|
-
return new Proxy(value, {
|
|
33
|
-
set(target, k, v) {
|
|
34
|
-
const res = Reflect.set(target, k, v);
|
|
35
|
-
saveValue();
|
|
36
|
-
return res;
|
|
37
|
-
},
|
|
38
|
-
deleteProperty(target, p) {
|
|
39
|
-
const res = Reflect.deleteProperty(target, p);
|
|
40
|
-
saveValue();
|
|
41
|
-
return res;
|
|
42
|
-
},
|
|
43
|
-
defineProperty(target, p, r) {
|
|
44
|
-
const res = Reflect.defineProperty(target, p, r);
|
|
45
|
-
saveValue();
|
|
46
|
-
return res;
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
delete(key) {
|
|
51
|
-
return (0, shared_1.deleteValue)(this.data, key);
|
|
52
|
-
}
|
|
53
|
-
set(key, value) {
|
|
54
|
-
(0, shared_1.setValue)(this.data, key, value);
|
|
55
|
-
return (0, fs_1.writeFileSync)(this.path, JSON.stringify(this.data, null, 2), "utf-8");
|
|
145
|
+
filter(route, callback) {
|
|
146
|
+
return this.getArray(route).filter(callback);
|
|
56
147
|
}
|
|
57
148
|
}
|
|
58
|
-
exports.
|
|
149
|
+
exports.JsonDB = JsonDB;
|
|
@@ -19,7 +19,9 @@ class CommonAction {
|
|
|
19
19
|
async deleteMsg(message_id) {
|
|
20
20
|
if (message_id == 0)
|
|
21
21
|
throw new Error('getMsg: message_id[0] is invalid');
|
|
22
|
-
let msg_entry =
|
|
22
|
+
let msg_entry = this.db.find('messages', (message) => {
|
|
23
|
+
return message.id === message_id;
|
|
24
|
+
});
|
|
23
25
|
if (!msg_entry)
|
|
24
26
|
throw new Error(`getMsg: can not find msg[${message_id}] in db`);
|
|
25
27
|
return this.adapter.call(this.oneBot.uin, 'V11', 'deleteMsg', [msg_entry.base64_id]);
|
|
@@ -32,7 +34,9 @@ class CommonAction {
|
|
|
32
34
|
async getMsg(message_id) {
|
|
33
35
|
if (message_id == 0)
|
|
34
36
|
throw new Error('getMsg: message_id[0] is invalid');
|
|
35
|
-
let msg_entry =
|
|
37
|
+
let msg_entry = this.db.find('messages', (message) => {
|
|
38
|
+
return message.id === message_id;
|
|
39
|
+
});
|
|
36
40
|
if (!msg_entry)
|
|
37
41
|
throw new Error(`getMsg: can not find msg[${message_id}] in db`);
|
|
38
42
|
let msg = await this.adapter.call(this.oneBot.uin, 'V11', 'getMsg', [msg_entry.base64_id]);
|
|
@@ -38,8 +38,8 @@ class FriendAction {
|
|
|
38
38
|
* @param user_id {number} 用户id
|
|
39
39
|
* @param times 点赞次数
|
|
40
40
|
*/
|
|
41
|
-
async
|
|
42
|
-
return this.adapter.call(this.oneBot.uin, 'V11', '
|
|
41
|
+
async sendLike(user_id, times) {
|
|
42
|
+
return this.adapter.call(this.oneBot.uin, 'V11', 'sendLike', [user_id, times]);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
exports.FriendAction = FriendAction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
id
|
|
1
|
+
export interface MsgEntry {
|
|
2
|
+
id: number;
|
|
3
3
|
base64_id: string;
|
|
4
4
|
seq: number;
|
|
5
5
|
user_id: string;
|
|
@@ -7,7 +7,7 @@ export declare class MsgEntry {
|
|
|
7
7
|
group_id: number;
|
|
8
8
|
group_name: string;
|
|
9
9
|
content: string;
|
|
10
|
-
recalled
|
|
11
|
-
create_time
|
|
12
|
-
recall_time?:
|
|
10
|
+
recalled?: boolean;
|
|
11
|
+
create_time?: number;
|
|
12
|
+
recall_time?: number;
|
|
13
13
|
}
|
|
@@ -1,63 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.MsgEntry = void 0;
|
|
13
|
-
const typeorm_1 = require("typeorm");
|
|
14
|
-
let MsgEntry = class MsgEntry {
|
|
15
|
-
};
|
|
16
|
-
exports.MsgEntry = MsgEntry;
|
|
17
|
-
__decorate([
|
|
18
|
-
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
|
19
|
-
__metadata("design:type", Number)
|
|
20
|
-
], MsgEntry.prototype, "id", void 0);
|
|
21
|
-
__decorate([
|
|
22
|
-
(0, typeorm_1.Column)(),
|
|
23
|
-
__metadata("design:type", String)
|
|
24
|
-
], MsgEntry.prototype, "base64_id", void 0);
|
|
25
|
-
__decorate([
|
|
26
|
-
(0, typeorm_1.Column)(),
|
|
27
|
-
__metadata("design:type", Number)
|
|
28
|
-
], MsgEntry.prototype, "seq", void 0);
|
|
29
|
-
__decorate([
|
|
30
|
-
(0, typeorm_1.Column)(),
|
|
31
|
-
__metadata("design:type", String)
|
|
32
|
-
], MsgEntry.prototype, "user_id", void 0);
|
|
33
|
-
__decorate([
|
|
34
|
-
(0, typeorm_1.Column)(),
|
|
35
|
-
__metadata("design:type", String)
|
|
36
|
-
], MsgEntry.prototype, "nickname", void 0);
|
|
37
|
-
__decorate([
|
|
38
|
-
(0, typeorm_1.Column)(),
|
|
39
|
-
__metadata("design:type", Number)
|
|
40
|
-
], MsgEntry.prototype, "group_id", void 0);
|
|
41
|
-
__decorate([
|
|
42
|
-
(0, typeorm_1.Column)(),
|
|
43
|
-
__metadata("design:type", String)
|
|
44
|
-
], MsgEntry.prototype, "group_name", void 0);
|
|
45
|
-
__decorate([
|
|
46
|
-
(0, typeorm_1.Column)({ length: 1024 }),
|
|
47
|
-
__metadata("design:type", String)
|
|
48
|
-
], MsgEntry.prototype, "content", void 0);
|
|
49
|
-
__decorate([
|
|
50
|
-
(0, typeorm_1.Column)({ default: false }),
|
|
51
|
-
__metadata("design:type", Boolean)
|
|
52
|
-
], MsgEntry.prototype, "recalled", void 0);
|
|
53
|
-
__decorate([
|
|
54
|
-
(0, typeorm_1.CreateDateColumn)(),
|
|
55
|
-
__metadata("design:type", Date)
|
|
56
|
-
], MsgEntry.prototype, "create_time", void 0);
|
|
57
|
-
__decorate([
|
|
58
|
-
(0, typeorm_1.Column)({ nullable: true }),
|
|
59
|
-
__metadata("design:type", Date)
|
|
60
|
-
], MsgEntry.prototype, "recall_time", void 0);
|
|
61
|
-
exports.MsgEntry = MsgEntry = __decorate([
|
|
62
|
-
(0, typeorm_1.Entity)()
|
|
63
|
-
], MsgEntry);
|
|
@@ -5,9 +5,9 @@ import { OneBot, OneBotStatus } from "../../onebot";
|
|
|
5
5
|
import { Logger } from "log4js";
|
|
6
6
|
import { WebSocket, WebSocketServer } from "ws";
|
|
7
7
|
import { Dispose } from "../../types";
|
|
8
|
-
import { Database } from "./db_sqlite";
|
|
9
8
|
import { Service } from "../../service";
|
|
10
9
|
import { Dict } from "@zhinjs/shared";
|
|
10
|
+
import { JsonDB } from "../../db";
|
|
11
11
|
export declare class V11 extends Service<"V11"> implements OneBot.Base {
|
|
12
12
|
oneBot: OneBot<"V11">;
|
|
13
13
|
config: OneBot.Config<"V11">;
|
|
@@ -15,7 +15,7 @@ export declare class V11 extends Service<"V11"> implements OneBot.Base {
|
|
|
15
15
|
version: OneBot.Version;
|
|
16
16
|
protected timestamp: number;
|
|
17
17
|
protected heartbeat?: NodeJS.Timeout;
|
|
18
|
-
db:
|
|
18
|
+
db: JsonDB;
|
|
19
19
|
disposes: Dispose[];
|
|
20
20
|
protected _queue: Array<{
|
|
21
21
|
method: keyof Action;
|
package/lib/service/V11/index.js
CHANGED
|
@@ -13,11 +13,10 @@ const utils_1 = require("../../utils");
|
|
|
13
13
|
const onebot_2 = require("../../onebot");
|
|
14
14
|
const http_1 = __importDefault(require("http"));
|
|
15
15
|
const https_1 = __importDefault(require("https"));
|
|
16
|
-
const db_sqlite_1 = require("./db_sqlite");
|
|
17
16
|
const path_1 = require("path");
|
|
18
17
|
const app_1 = require("../../server/app");
|
|
19
|
-
const db_entities_1 = require("./db_entities");
|
|
20
18
|
const service_1 = require("../../service");
|
|
19
|
+
const db_1 = require("../../db");
|
|
21
20
|
const sendMsgTypes = ["private", "group", "discuss"];
|
|
22
21
|
const sendMsgMethodRegex = new RegExp(`send_(${sendMsgTypes.join("|")})_msg`);
|
|
23
22
|
class V11 extends service_1.Service {
|
|
@@ -32,7 +31,7 @@ class V11 extends service_1.Service {
|
|
|
32
31
|
this.wsr = new Set();
|
|
33
32
|
this.action = new action_1.Action();
|
|
34
33
|
this.logger = this.oneBot.adapter.getLogger(this.oneBot.uin, this.version);
|
|
35
|
-
this.db = new
|
|
34
|
+
this.db = new db_1.JsonDB((0, path_1.join)(app_1.App.configDir, 'data', `${this.oneBot.uin}_v11.jsondb`));
|
|
36
35
|
this.oneBot.on("online", async () => {
|
|
37
36
|
this.logger.info("【好友列表】");
|
|
38
37
|
const friendList = await this.oneBot.getFriendList("V11");
|
|
@@ -228,7 +227,13 @@ class V11 extends service_1.Service {
|
|
|
228
227
|
data.message_id = await this.addMsgToDB(data);
|
|
229
228
|
}
|
|
230
229
|
if (data.post_type == "notice" && String(data.notice_type).endsWith("_recall")) {
|
|
231
|
-
this.db.
|
|
230
|
+
const msgIdx = this.db.findIndex('messages', (message) => {
|
|
231
|
+
return message.base64_id === data.base64_id;
|
|
232
|
+
});
|
|
233
|
+
if (msgIdx >= 0) {
|
|
234
|
+
this.db.set(`messages.${msgIdx}.recalled`, true);
|
|
235
|
+
this.db.set(`messages.${msgIdx}.recall_time`, parseInt((Date.now() / 1000) + ''));
|
|
236
|
+
}
|
|
232
237
|
}
|
|
233
238
|
if (data.font) {
|
|
234
239
|
const fontNo = Buffer.from(data.font).readUInt32BE();
|
|
@@ -304,21 +309,21 @@ class V11 extends service_1.Service {
|
|
|
304
309
|
// eg. notice
|
|
305
310
|
return;
|
|
306
311
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return
|
|
312
|
+
const id = (0, utils_1.randomInt)(1, Number.MAX_SAFE_INTEGER);
|
|
313
|
+
this.db.push('messages', {
|
|
314
|
+
id,
|
|
315
|
+
base64_id: data.base64_id,
|
|
316
|
+
seq: data.seq,
|
|
317
|
+
user_id: data.sender.user_id,
|
|
318
|
+
nickname: data.sender.nickname,
|
|
319
|
+
group_id: data.group_id || 0,
|
|
320
|
+
group_name: data.group_name || '',
|
|
321
|
+
content: data.cqCode || data.message,
|
|
322
|
+
create_time: data.time,
|
|
323
|
+
});
|
|
324
|
+
if (this.db.get('messages').length > 1000)
|
|
325
|
+
this.db.shift('messages');
|
|
326
|
+
return id;
|
|
322
327
|
}
|
|
323
328
|
/**
|
|
324
329
|
* 从 send_msg_xxx() 调用的返回值中提取消息存入数据库(可以让前端在没有收到同步的message数据前就有能力拿到消息对应的base64_id)
|
|
@@ -329,20 +334,27 @@ class V11 extends service_1.Service {
|
|
|
329
334
|
* @param base64_id icqq返回的base64格式的消息id
|
|
330
335
|
*/
|
|
331
336
|
async addMsgToDBFromSendMsgResult(user_id, group_id, seq, base64_id) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
337
|
+
const id = (0, utils_1.randomInt)(1, Number.MAX_SAFE_INTEGER);
|
|
338
|
+
this.db.push('messages', {
|
|
339
|
+
id,
|
|
340
|
+
base64_id,
|
|
341
|
+
seq,
|
|
342
|
+
user_id,
|
|
343
|
+
nickname: '',
|
|
344
|
+
group_id,
|
|
345
|
+
group_name: '',
|
|
346
|
+
content: '',
|
|
347
|
+
});
|
|
348
|
+
if (this.db.get('messages').length > 1000)
|
|
349
|
+
this.db.shift('messages');
|
|
350
|
+
return id;
|
|
341
351
|
}
|
|
342
352
|
async getReplyMsgIdFromDB(data) {
|
|
343
353
|
let group_id = data.message_type === "group" ? data.group_id : 0;
|
|
344
|
-
let msg = await this.db.
|
|
345
|
-
|
|
354
|
+
let msg = await this.db.find('messages', (message) => {
|
|
355
|
+
return message.user_id === data.user_id && message.group_id === group_id && message.seq === data.source.seq;
|
|
356
|
+
});
|
|
357
|
+
return msg?.id || 0;
|
|
346
358
|
}
|
|
347
359
|
async _httpRequestHandler(ctx) {
|
|
348
360
|
if (ctx.method === "OPTIONS") {
|
|
@@ -517,7 +529,9 @@ class V11 extends service_1.Service {
|
|
|
517
529
|
async apply(req) {
|
|
518
530
|
let { action, params, echo } = req;
|
|
519
531
|
if (typeof params.message_id == "number" || /^\d+$/.test(params.message_id)) {
|
|
520
|
-
params.message_id = (await this.db.
|
|
532
|
+
params.message_id = (await this.db.find('messages', (message) => {
|
|
533
|
+
return params.message_id === message.id;
|
|
534
|
+
}))?.base64_id; // 调用api时把本地的数字id转为base64发给icqq
|
|
521
535
|
}
|
|
522
536
|
action = (0, utils_1.toLine)(action);
|
|
523
537
|
let is_async = action.includes("_async");
|
|
@@ -540,9 +554,6 @@ class V11 extends service_1.Service {
|
|
|
540
554
|
else
|
|
541
555
|
throw new Error("required message_type or input (user_id/group_id)");
|
|
542
556
|
}
|
|
543
|
-
else if (action === "send_like") {
|
|
544
|
-
action = "send_user_like";
|
|
545
|
-
}
|
|
546
557
|
const method = (0, utils_1.toHump)(action);
|
|
547
558
|
if (Reflect.has(this.action, method)) {
|
|
548
559
|
const ARGS = String(Reflect.get(this.action, method)).match(/\(.*\)/)?.[0]
|
|
@@ -19,6 +19,8 @@ export declare class V12 extends Service<'V12'> implements OneBot.Base {
|
|
|
19
19
|
wsr: Set<WebSocket>;
|
|
20
20
|
private db;
|
|
21
21
|
constructor(oneBot: OneBot<'V12'>, config: OneBot.Config<'V12'>);
|
|
22
|
+
addHistory(payload: V12.Payload<keyof Action>): number;
|
|
23
|
+
shiftHistory(): unknown;
|
|
22
24
|
get history(): V12.Payload<keyof Action>[];
|
|
23
25
|
getFile(file_id: string): V12.FileInfo;
|
|
24
26
|
delFile(file_id: string): boolean;
|
package/lib/service/V12/index.js
CHANGED
|
@@ -25,20 +25,24 @@ class V12 extends service_1.Service {
|
|
|
25
25
|
this.version = 'V12';
|
|
26
26
|
this.timestamp = Date.now();
|
|
27
27
|
this.wsr = new Set();
|
|
28
|
-
this.db = new db_1.
|
|
29
|
-
this.db.sync({ eventBuffer: [], msgIdMap: {}, files: {} });
|
|
28
|
+
this.db = new db_1.JsonDB((0, path_1.join)(app_1.App.configDir, 'data', `${this.oneBot.uin}_v12.jsondb`));
|
|
30
29
|
this.action = new action_1.Action();
|
|
31
30
|
this.logger = this.oneBot.adapter.getLogger(this.oneBot.uin, this.version);
|
|
32
31
|
}
|
|
32
|
+
addHistory(payload) {
|
|
33
|
+
return this.db.push('eventBuffer', payload);
|
|
34
|
+
}
|
|
35
|
+
shiftHistory() {
|
|
36
|
+
return this.db.shift('eventBuffer');
|
|
37
|
+
}
|
|
33
38
|
get history() {
|
|
34
|
-
return this.db.get('eventBuffer');
|
|
39
|
+
return this.db.get('eventBuffer', []);
|
|
35
40
|
}
|
|
36
41
|
getFile(file_id) {
|
|
37
42
|
return this.db.get(`files.${file_id}`);
|
|
38
43
|
}
|
|
39
44
|
delFile(file_id) {
|
|
40
|
-
|
|
41
|
-
return delete files[file_id];
|
|
45
|
+
return this.db.delete(`files.${file_id}`);
|
|
42
46
|
}
|
|
43
47
|
saveFile(fileInfo) {
|
|
44
48
|
const file_id = (0, utils_2.uuid)();
|
|
@@ -46,7 +50,7 @@ class V12 extends service_1.Service {
|
|
|
46
50
|
return file_id;
|
|
47
51
|
}
|
|
48
52
|
get files() {
|
|
49
|
-
const files = this.db.get('files');
|
|
53
|
+
const files = this.db.get('files', {});
|
|
50
54
|
return Object.keys(files).map((file_id) => {
|
|
51
55
|
return {
|
|
52
56
|
file_id,
|
|
@@ -153,9 +157,9 @@ class V12 extends service_1.Service {
|
|
|
153
157
|
if (!['message', 'notice', 'request', 'meta'].includes(payload.type))
|
|
154
158
|
return;
|
|
155
159
|
if (config.event_enabled) {
|
|
156
|
-
this.
|
|
160
|
+
this.addHistory(payload);
|
|
157
161
|
if (config.event_buffer_size !== 0 && this.history.length > config.event_buffer_size)
|
|
158
|
-
this.
|
|
162
|
+
this.shiftHistory();
|
|
159
163
|
}
|
|
160
164
|
});
|
|
161
165
|
}
|
|
@@ -360,12 +364,18 @@ class V12 extends service_1.Service {
|
|
|
360
364
|
platform: 'qq',
|
|
361
365
|
user_id: `${this.oneBot.uin}`
|
|
362
366
|
},
|
|
363
|
-
...(0, utils_2.transformObj)(data, (key, value) => {
|
|
364
|
-
if (!['user_id', 'group_id', 'discuss_id', 'member_id', 'channel_id', 'guild_id'].includes(key))
|
|
365
|
-
return value;
|
|
366
|
-
return value + '';
|
|
367
|
-
}),
|
|
368
367
|
};
|
|
368
|
+
Object.assign(payload, (0, utils_2.transformObj)(data, (key, value) => {
|
|
369
|
+
if (!['user_id', 'group_id', 'discuss_id', 'member_id', 'channel_id', 'guild_id'].includes(key))
|
|
370
|
+
return value;
|
|
371
|
+
return value + '';
|
|
372
|
+
}), {
|
|
373
|
+
self_id: `${this.oneBot.uin}`,
|
|
374
|
+
self: {
|
|
375
|
+
platform: 'qq',
|
|
376
|
+
user_id: `${this.oneBot.uin}`
|
|
377
|
+
},
|
|
378
|
+
});
|
|
369
379
|
if (!this.filterFn(payload))
|
|
370
380
|
return;
|
|
371
381
|
this.emit('dispatch', payload);
|
|
@@ -563,6 +573,9 @@ class V12 extends service_1.Service {
|
|
|
563
573
|
*/
|
|
564
574
|
_createWsr(url, config) {
|
|
565
575
|
const timestmap = Date.now();
|
|
576
|
+
let remoteUrl = url;
|
|
577
|
+
if (config.access_token)
|
|
578
|
+
remoteUrl += `?access_token=${config.access_token}`;
|
|
566
579
|
const headers = {
|
|
567
580
|
"X-Self-ID": String(this.oneBot.uin),
|
|
568
581
|
"X-Client-Role": "Universal",
|
|
@@ -571,7 +584,7 @@ class V12 extends service_1.Service {
|
|
|
571
584
|
};
|
|
572
585
|
if (config.access_token)
|
|
573
586
|
headers.Authorization = "Bearer " + config.access_token;
|
|
574
|
-
const ws = new ws_1.WebSocket(
|
|
587
|
+
const ws = new ws_1.WebSocket(remoteUrl, { headers });
|
|
575
588
|
ws.on("error", (err) => {
|
|
576
589
|
this.logger.error(err.message);
|
|
577
590
|
});
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
import { Dict } from "@zhinjs/shared";
|
|
1
2
|
export declare const version: any;
|
|
2
3
|
export declare function deepMerge(base: any, ...from: any[]): any;
|
|
3
4
|
export declare function transformObj(obj: any, callback: any): any;
|
|
4
5
|
export declare function deepClone<T extends any>(obj: T): T;
|
|
5
6
|
export declare function pick<T extends object, K extends keyof T>(source: T, keys?: Iterable<K>, forced?: boolean): Pick<T, K>;
|
|
6
7
|
export declare function omit<T, K extends keyof T>(source: T, keys?: Iterable<K>): Omit<T, K>;
|
|
7
|
-
export declare function randomId(seed: string): number;
|
|
8
|
-
export declare function randomId(seed: string, length: number): number;
|
|
9
|
-
export declare function randomId(seed: string, min: number, max: number): number;
|
|
10
8
|
/**
|
|
11
9
|
* 将驼峰命名替换为下划线分割命名
|
|
12
10
|
* @param name
|
|
@@ -22,5 +20,14 @@ export declare function toHump(action: string): string;
|
|
|
22
20
|
export declare function remove<T>(list: T[], item: T): void;
|
|
23
21
|
export declare function toBool(v: any): boolean;
|
|
24
22
|
export declare function uuid(): string;
|
|
23
|
+
export declare function randomInt(max: number): number;
|
|
24
|
+
export declare function randomInt(min: number, max: number): number;
|
|
25
25
|
export declare function protectedFields<T>(source: T, ...keys: ((keyof T) | string)[]): T;
|
|
26
26
|
export declare function getProperties(obj: any): any;
|
|
27
|
+
export declare function setValueToObj(obj: Dict, keys: string[], value: any): boolean;
|
|
28
|
+
export declare function setValueToObj(obj: Dict, key: string, value: any): boolean;
|
|
29
|
+
export declare function getValueOfObj<T = any>(obj: Dict, key: string[]): T;
|
|
30
|
+
export declare function getValueOfObj<T = any>(obj: Dict, key: string): T;
|
|
31
|
+
export declare function getDataKeyOfObj(data: any, obj: Dict): string;
|
|
32
|
+
export declare function parseObjFromStr(str: string): any;
|
|
33
|
+
export declare function stringifyObj(value: any): string;
|
package/lib/utils.js
CHANGED
|
@@ -22,13 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.getProperties = exports.protectedFields = exports.uuid = exports.toBool = exports.remove = exports.toHump = exports.Mixin = exports.toLine = exports.
|
|
26
|
+
exports.stringifyObj = exports.parseObjFromStr = exports.getDataKeyOfObj = exports.getValueOfObj = exports.setValueToObj = exports.getProperties = exports.protectedFields = exports.randomInt = exports.uuid = exports.toBool = exports.remove = exports.toHump = exports.Mixin = exports.toLine = exports.omit = exports.pick = exports.deepClone = exports.transformObj = exports.deepMerge = exports.version = void 0;
|
|
30
27
|
const crypto = __importStar(require("crypto"));
|
|
31
|
-
const seed_random_1 = __importDefault(require("seed-random"));
|
|
32
28
|
const packageJson = require('../package.json');
|
|
33
29
|
exports.version = packageJson.version;
|
|
34
30
|
// 合并对象/数组
|
|
@@ -118,19 +114,6 @@ function omit(source, keys) {
|
|
|
118
114
|
return result;
|
|
119
115
|
}
|
|
120
116
|
exports.omit = omit;
|
|
121
|
-
function randomId(seed, ...args) {
|
|
122
|
-
let [min = 0, max = 1] = args;
|
|
123
|
-
let formatter = (n) => n;
|
|
124
|
-
if (args.length === 1) {
|
|
125
|
-
const len = Math.min(Number.MAX_SAFE_INTEGER.toString().length, args[0]);
|
|
126
|
-
min = 10 ** (len - 1);
|
|
127
|
-
max = Math.min(Number.MAX_SAFE_INTEGER, 10 ** len - 1);
|
|
128
|
-
formatter = (n) => Math.floor(n);
|
|
129
|
-
}
|
|
130
|
-
const rand = (0, seed_random_1.default)(seed);
|
|
131
|
-
return formatter(rand() * (max - min) + min);
|
|
132
|
-
}
|
|
133
|
-
exports.randomId = randomId;
|
|
134
117
|
/**
|
|
135
118
|
* 将驼峰命名替换为下划线分割命名
|
|
136
119
|
* @param name
|
|
@@ -175,6 +158,13 @@ function uuid() {
|
|
|
175
158
|
return hex.substr(0, 8) + "-" + hex.substr(8, 4) + "-" + hex.substr(12, 4) + "-" + hex.substr(16, 4) + "-" + hex.substr(20);
|
|
176
159
|
}
|
|
177
160
|
exports.uuid = uuid;
|
|
161
|
+
function randomInt(...args) {
|
|
162
|
+
let min = args[0] || 0, max = args[1];
|
|
163
|
+
if (args.length === 1)
|
|
164
|
+
max = min, min = 0;
|
|
165
|
+
return Math.floor(Math.random() * (max - min) + min);
|
|
166
|
+
}
|
|
167
|
+
exports.randomInt = randomInt;
|
|
178
168
|
function protectedFields(source, ...keys) {
|
|
179
169
|
const protocolValue = (value) => {
|
|
180
170
|
if (value && typeof value === 'object')
|
|
@@ -197,3 +187,95 @@ function getProperties(obj) {
|
|
|
197
187
|
return Object.getOwnPropertyNames(obj).concat(getProperties(obj.__proto__));
|
|
198
188
|
}
|
|
199
189
|
exports.getProperties = getProperties;
|
|
190
|
+
function setValueToObj(obj, key, value) {
|
|
191
|
+
const keys = Array.isArray(key) ? key : key.split('.').filter(Boolean);
|
|
192
|
+
const lastKey = keys.pop();
|
|
193
|
+
if (!lastKey)
|
|
194
|
+
throw new SyntaxError(`key is empty`);
|
|
195
|
+
while (keys.length) {
|
|
196
|
+
const k = keys.shift();
|
|
197
|
+
obj = Reflect.get(obj, k);
|
|
198
|
+
if (!obj)
|
|
199
|
+
throw new SyntaxError(`can't set ${lastKey} to undefined`);
|
|
200
|
+
}
|
|
201
|
+
return Reflect.set(obj, lastKey, value);
|
|
202
|
+
}
|
|
203
|
+
exports.setValueToObj = setValueToObj;
|
|
204
|
+
function getValueOfObj(obj, key) {
|
|
205
|
+
const keys = Array.isArray(key) ? key : key.split('.').filter(Boolean);
|
|
206
|
+
const lastKey = keys.pop();
|
|
207
|
+
if (!lastKey)
|
|
208
|
+
throw new SyntaxError(`key is empty`);
|
|
209
|
+
while (keys.length) {
|
|
210
|
+
const k = keys.shift();
|
|
211
|
+
obj = Reflect.get(obj, k);
|
|
212
|
+
if (!obj)
|
|
213
|
+
throw new SyntaxError(`can't set ${lastKey} to undefined`);
|
|
214
|
+
}
|
|
215
|
+
return Reflect.get(obj, lastKey);
|
|
216
|
+
}
|
|
217
|
+
exports.getValueOfObj = getValueOfObj;
|
|
218
|
+
function getDataKeyOfObj(data, obj) {
|
|
219
|
+
const _get = (data, obj, prefix) => {
|
|
220
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
221
|
+
if (value === data)
|
|
222
|
+
return [...prefix, key].join('.');
|
|
223
|
+
if (!value || typeof value !== 'object')
|
|
224
|
+
continue;
|
|
225
|
+
const result = _get(data, value, prefix);
|
|
226
|
+
if (result)
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
return _get(data, obj, []);
|
|
231
|
+
}
|
|
232
|
+
exports.getDataKeyOfObj = getDataKeyOfObj;
|
|
233
|
+
function parseObjFromStr(str) {
|
|
234
|
+
const result = JSON.parse(str);
|
|
235
|
+
const format = (data, keys) => {
|
|
236
|
+
if (!data)
|
|
237
|
+
return;
|
|
238
|
+
if (typeof data !== 'object' && typeof data !== 'string')
|
|
239
|
+
return;
|
|
240
|
+
if (typeof data === 'object')
|
|
241
|
+
return Object.entries(data).map(([k, v]) => format(v, [...keys, k]));
|
|
242
|
+
if (/\[Function:.+]/.test(data))
|
|
243
|
+
return setValueToObj(result, [...keys], new Function(`return (${data.slice(10, -1)})`)());
|
|
244
|
+
if (/\[Circular:.+]/.test(data))
|
|
245
|
+
setValueToObj(result, [...keys], getValueOfObj(result, data.slice(10, -1)));
|
|
246
|
+
};
|
|
247
|
+
format(result, []);
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
exports.parseObjFromStr = parseObjFromStr;
|
|
251
|
+
function stringifyObj(value) {
|
|
252
|
+
if (!value || typeof value !== 'object')
|
|
253
|
+
return value;
|
|
254
|
+
if (Array.isArray(value))
|
|
255
|
+
return `[${value.map(stringifyObj).join()}]`;
|
|
256
|
+
let result = { ...value }, cache = new WeakMap();
|
|
257
|
+
const _stringify = (obj, prefix) => {
|
|
258
|
+
for (const key of Reflect.ownKeys(obj)) {
|
|
259
|
+
if (typeof key === 'symbol')
|
|
260
|
+
continue;
|
|
261
|
+
const val = Reflect.get(obj, key);
|
|
262
|
+
if (!val || typeof val !== 'object') {
|
|
263
|
+
if (typeof val === 'function') {
|
|
264
|
+
setValueToObj(result, [...prefix, String(key)], `[Function:${(val + '').replace(/\n/g, '')}]`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
setValueToObj(result, [...prefix, String(key)], val);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (cache.has(val)) {
|
|
271
|
+
setValueToObj(result, [...prefix, String(key)], `[Circular:${getDataKeyOfObj(val, value)}]`);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
cache.set(val, getValueOfObj(value, [...prefix, String(key)]));
|
|
275
|
+
_stringify(val, [...prefix, String(key)]);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
_stringify(value, []);
|
|
279
|
+
return JSON.stringify(result, null, 2);
|
|
280
|
+
}
|
|
281
|
+
exports.stringifyObj = stringifyObj;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onebots",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.32",
|
|
4
4
|
"description": "基于icqq的多例oneBot实现",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=16"
|
|
@@ -56,8 +56,7 @@
|
|
|
56
56
|
"/**/LICENSE"
|
|
57
57
|
],
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"icqq": "latest"
|
|
60
|
-
"sqlite3": "^5.1.6"
|
|
59
|
+
"icqq": "latest"
|
|
61
60
|
},
|
|
62
61
|
"dependencies": {
|
|
63
62
|
"@koa/router": "^10.1.1",
|
|
@@ -69,8 +68,6 @@
|
|
|
69
68
|
"log4js": "^6.5.2",
|
|
70
69
|
"mime-types": "^2.1.35",
|
|
71
70
|
"reflect-metadata": "^0.1.13",
|
|
72
|
-
"seed-random": "^2.2.0",
|
|
73
|
-
"typeorm": "^0.3.17",
|
|
74
71
|
"ws": "^8.8.0"
|
|
75
72
|
}
|
|
76
73
|
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { MsgEntry } from "./db_entities";
|
|
2
|
-
import { DataSource, Repository } from "typeorm";
|
|
3
|
-
import { Logger } from "log4js";
|
|
4
|
-
import { AsyncLock } from "../../types";
|
|
5
|
-
export declare class Database {
|
|
6
|
-
logger: Logger;
|
|
7
|
-
dbPath: string;
|
|
8
|
-
dataSource: DataSource;
|
|
9
|
-
/**
|
|
10
|
-
* 消息在数据库中的保留时间
|
|
11
|
-
*/
|
|
12
|
-
msgHistoryPreserveDays: number;
|
|
13
|
-
msgHistoryCheckInterval: number;
|
|
14
|
-
msgRepo: Repository<MsgEntry>;
|
|
15
|
-
dbLock: AsyncLock;
|
|
16
|
-
constructor(dbPath: string, logger: Logger);
|
|
17
|
-
initDB(): Promise<void>;
|
|
18
|
-
/**
|
|
19
|
-
* 增加或更新一条消息到数据库
|
|
20
|
-
* @param msgData
|
|
21
|
-
*/
|
|
22
|
-
addOrUpdateMsg(msgData: MsgEntry): Promise<number>;
|
|
23
|
-
/**
|
|
24
|
-
* 通过 icqq 的 base64 格式的 message_id 获取一个 MsgData 对象
|
|
25
|
-
* @param base64_id
|
|
26
|
-
* @returns
|
|
27
|
-
*/
|
|
28
|
-
getMsgByBase64Id(base64_id: string): Promise<MsgEntry | null>;
|
|
29
|
-
/**
|
|
30
|
-
* 通过 number 类型的 id 自增主键获取一个 MsgData 对象
|
|
31
|
-
* @param id
|
|
32
|
-
* @returns
|
|
33
|
-
*/
|
|
34
|
-
getMsgById(id: number): Promise<MsgEntry | null>;
|
|
35
|
-
/**
|
|
36
|
-
* 通过参数从数据库中查找消息
|
|
37
|
-
* @param user_id
|
|
38
|
-
* @param group_id
|
|
39
|
-
* @param seq
|
|
40
|
-
*/
|
|
41
|
-
getMsgByParams(user_id: string, group_id: number, seq: number): Promise<MsgEntry | null>;
|
|
42
|
-
/**
|
|
43
|
-
* 将一条消息标记为 recalled
|
|
44
|
-
* @param base64_id
|
|
45
|
-
* @param id
|
|
46
|
-
*/
|
|
47
|
-
markMsgAsRecalled(base64_id?: string, id?: number): Promise<void>;
|
|
48
|
-
/**
|
|
49
|
-
* 根据 `msgPreserveDays` 变量定义的保留期限收缩数据库
|
|
50
|
-
*/
|
|
51
|
-
shrinkDB(): Promise<void>;
|
|
52
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Database = void 0;
|
|
4
|
-
const db_entities_1 = require("./db_entities");
|
|
5
|
-
const typeorm_1 = require("typeorm");
|
|
6
|
-
const types_1 = require("../../types");
|
|
7
|
-
class Database {
|
|
8
|
-
constructor(dbPath, logger) {
|
|
9
|
-
/**
|
|
10
|
-
* 消息在数据库中的保留时间
|
|
11
|
-
*/
|
|
12
|
-
this.msgHistoryPreserveDays = 14; // 历史消息默认存储2周
|
|
13
|
-
this.msgHistoryCheckInterval = 1 * 24 * 3600 * 1000; // 历史记录检查间隔
|
|
14
|
-
this.dbPath = dbPath;
|
|
15
|
-
this.logger = logger;
|
|
16
|
-
this.dbLock = new types_1.AsyncLock();
|
|
17
|
-
this.dataSource = new typeorm_1.DataSource({
|
|
18
|
-
type: "sqlite",
|
|
19
|
-
database: dbPath,
|
|
20
|
-
entities: [db_entities_1.MsgEntry],
|
|
21
|
-
});
|
|
22
|
-
this.initDB();
|
|
23
|
-
}
|
|
24
|
-
async initDB() {
|
|
25
|
-
try {
|
|
26
|
-
await this.dataSource.initialize();
|
|
27
|
-
await this.dataSource.synchronize(false);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
this.logger.error(`sqlite [${this.dbPath}] open fail!`, err);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
this.msgRepo = this.dataSource.getRepository(db_entities_1.MsgEntry);
|
|
34
|
-
this.logger.debug(`sqlite [${this.dbPath}] open success`);
|
|
35
|
-
setInterval(() => {
|
|
36
|
-
this.shrinkDB();
|
|
37
|
-
}, this.msgHistoryCheckInterval);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* 增加或更新一条消息到数据库
|
|
41
|
-
* @param msgData
|
|
42
|
-
*/
|
|
43
|
-
async addOrUpdateMsg(msgData) {
|
|
44
|
-
await this.dbLock.lock();
|
|
45
|
-
try {
|
|
46
|
-
let msgDataExists = await this.getMsgByParams(msgData.user_id, msgData.group_id, msgData.seq);
|
|
47
|
-
if (msgDataExists) {
|
|
48
|
-
// send_msg() 返回值和同步的 message 消息哪个先来不确定,send_msg 返回值后来时不允许更新数据库
|
|
49
|
-
if (msgData.content.length == 0) {
|
|
50
|
-
return msgDataExists.id;
|
|
51
|
-
}
|
|
52
|
-
msgData.id = msgDataExists.id;
|
|
53
|
-
await this.msgRepo.update({ id: msgData.id }, msgData);
|
|
54
|
-
return msgDataExists.id;
|
|
55
|
-
}
|
|
56
|
-
msgData = await this.msgRepo.save(msgData);
|
|
57
|
-
this.logger.debug(`addMsg with id:${msgData.id}`);
|
|
58
|
-
return msgData.id;
|
|
59
|
-
}
|
|
60
|
-
finally {
|
|
61
|
-
this.dbLock.unlock();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 通过 icqq 的 base64 格式的 message_id 获取一个 MsgData 对象
|
|
66
|
-
* @param base64_id
|
|
67
|
-
* @returns
|
|
68
|
-
*/
|
|
69
|
-
async getMsgByBase64Id(base64_id) {
|
|
70
|
-
let ret = await this.msgRepo.findOneBy({ base64_id: base64_id });
|
|
71
|
-
return ret;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* 通过 number 类型的 id 自增主键获取一个 MsgData 对象
|
|
75
|
-
* @param id
|
|
76
|
-
* @returns
|
|
77
|
-
*/
|
|
78
|
-
async getMsgById(id) {
|
|
79
|
-
let ret = await this.msgRepo.findOneBy({ id: id });
|
|
80
|
-
return ret;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* 通过参数从数据库中查找消息
|
|
84
|
-
* @param user_id
|
|
85
|
-
* @param group_id
|
|
86
|
-
* @param seq
|
|
87
|
-
*/
|
|
88
|
-
async getMsgByParams(user_id, group_id, seq) {
|
|
89
|
-
let ret = await this.msgRepo.findOneBy({ user_id: user_id, group_id: group_id, seq: seq });
|
|
90
|
-
return ret;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* 将一条消息标记为 recalled
|
|
94
|
-
* @param base64_id
|
|
95
|
-
* @param id
|
|
96
|
-
*/
|
|
97
|
-
async markMsgAsRecalled(base64_id, id) {
|
|
98
|
-
if (base64_id || id)
|
|
99
|
-
await this.msgRepo.update(base64_id ? { base64_id: base64_id } : { id: id }, {
|
|
100
|
-
recalled: true,
|
|
101
|
-
recall_time: new Date(),
|
|
102
|
-
});
|
|
103
|
-
else
|
|
104
|
-
throw new Error("base64_id 或 id 参数至少一个应该被赋值");
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* 根据 `msgPreserveDays` 变量定义的保留期限收缩数据库
|
|
108
|
-
*/
|
|
109
|
-
async shrinkDB() {
|
|
110
|
-
let dt = new Date();
|
|
111
|
-
dt.setDate(dt.getDate() - this.msgHistoryPreserveDays);
|
|
112
|
-
await this.msgRepo.createQueryBuilder().delete().from(db_entities_1.MsgEntry).where("create_time < :dt", { dt: dt }).execute();
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
exports.Database = Database;
|