wingbot-mongodb 2.16.3 → 2.19.0
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/.mocharc.js +14 -0
- package/.nyc_output/8e3ceac5-95c5-4bf9-a069-da51cccc2525.json +1 -0
- package/.nyc_output/processinfo/8e3ceac5-95c5-4bf9-a069-da51cccc2525.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -1
- package/README.md +58 -50
- package/package.json +21 -20
- package/src/AuditLogStorage.js +364 -0
- package/src/BaseStorage.js +73 -30
- package/src/BotConfigStorage.js +18 -7
- package/src/BotTokenStorage.js +3 -3
- package/src/ChatLogStorage.js +65 -34
- package/src/NotificationsStorage.js +37 -37
- package/src/StateStorage.js +36 -138
- package/src/main.js +3 -1
- package/.nyc_output/5a4dc5e6-8e98-4d63-a4fc-e2fe688626a9.json +0 -1
- package/.nyc_output/ccf7d45a-e479-43d4-862d-f3f229049ae1.json +0 -1
- package/.nyc_output/processinfo/5a4dc5e6-8e98-4d63-a4fc-e2fe688626a9.json +0 -1
- package/.nyc_output/processinfo/ccf7d45a-e479-43d4-862d-f3f229049ae1.json +0 -1
package/src/StateStorage.js
CHANGED
|
@@ -4,20 +4,21 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
const mongodb = require('mongodb'); // eslint-disable-line no-unused-vars
|
|
7
|
+
const BaseStorage = require('./BaseStorage');
|
|
7
8
|
|
|
8
9
|
const USER_INDEX = 'senderId_1_pageId_1';
|
|
9
10
|
const LAST_INTERACTION_INDEX = 'lastInteraction_1';
|
|
10
11
|
const SEARCH = 'search-text';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* @typedef {
|
|
14
|
+
* @typedef {object} State
|
|
14
15
|
* @prop {string} senderId
|
|
15
16
|
* @prop {string} pageId
|
|
16
|
-
* @prop {
|
|
17
|
+
* @prop {object} state
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
* @typedef {
|
|
21
|
+
* @typedef {object} StateCondition
|
|
21
22
|
* @prop {string} [search]
|
|
22
23
|
*/
|
|
23
24
|
|
|
@@ -26,7 +27,7 @@ const SEARCH = 'search-text';
|
|
|
26
27
|
*
|
|
27
28
|
* @class
|
|
28
29
|
*/
|
|
29
|
-
class StateStorage {
|
|
30
|
+
class StateStorage extends BaseStorage {
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
*
|
|
@@ -35,140 +36,37 @@ class StateStorage {
|
|
|
35
36
|
* @param {{error:Function,log:Function}} [log] - console like logger
|
|
36
37
|
* @param {boolean} isCosmo
|
|
37
38
|
*/
|
|
38
|
-
constructor (mongoDb, collectionName = '
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
constructor (mongoDb, collectionName = 'chatlogs', log = console, isCosmo = false) {
|
|
40
|
+
super(mongoDb, collectionName, log, isCosmo);
|
|
41
|
+
|
|
42
|
+
this.addIndex(
|
|
43
|
+
{ senderId: 1, pageId: 1 },
|
|
44
|
+
{ name: USER_INDEX, unique: true, dropDups: true }
|
|
45
|
+
);
|
|
46
|
+
this.addIndex(
|
|
47
|
+
{ lastInteraction: isCosmo ? 1 : -1 },
|
|
48
|
+
{ name: LAST_INTERACTION_INDEX }
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (!isCosmo) {
|
|
52
|
+
this.addIndex(
|
|
53
|
+
{ '$**': 'text' },
|
|
54
|
+
{ name: SEARCH }
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
/**
|
|
54
61
|
* Add custom indexing rule
|
|
55
62
|
*
|
|
56
|
-
* @param {
|
|
57
|
-
* @param {
|
|
63
|
+
* @param {object} index
|
|
64
|
+
* @param {object} options
|
|
58
65
|
* @param {string} options.name
|
|
66
|
+
* @deprecated
|
|
59
67
|
*/
|
|
60
68
|
addCustomIndex (index, options) {
|
|
61
|
-
this.
|
|
62
|
-
index,
|
|
63
|
-
options
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
_getIndexes () {
|
|
68
|
-
const indexes = [
|
|
69
|
-
{
|
|
70
|
-
index: { senderId: 1, pageId: 1 },
|
|
71
|
-
options: { name: USER_INDEX, unique: true, dropDups: true }
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
index: { lastInteraction: this._isCosmo ? 1 : -1 },
|
|
75
|
-
options: { name: LAST_INTERACTION_INDEX }
|
|
76
|
-
}
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
if (!this._doesNotSupportTextIndex) {
|
|
80
|
-
indexes.push({
|
|
81
|
-
// @ts-ignore
|
|
82
|
-
index: { '$**': 'text' },
|
|
83
|
-
options: { name: SEARCH },
|
|
84
|
-
isTextIndex: true
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return [...indexes, ...this._customIndexes];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async _getOrCreateCollection (name) {
|
|
92
|
-
const db = typeof this._mongoDb === 'function'
|
|
93
|
-
? await this._mongoDb()
|
|
94
|
-
: this._mongoDb;
|
|
95
|
-
|
|
96
|
-
let collection;
|
|
97
|
-
|
|
98
|
-
if (this._isCosmo) {
|
|
99
|
-
const collections = await db.collections();
|
|
100
|
-
|
|
101
|
-
collection = collections
|
|
102
|
-
.find(c => c.collectionName === name);
|
|
103
|
-
|
|
104
|
-
if (!collection) {
|
|
105
|
-
try {
|
|
106
|
-
collection = await db.createCollection(name);
|
|
107
|
-
} catch (e) {
|
|
108
|
-
collection = db.collection(name);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
} else {
|
|
113
|
-
collection = db.collection(name);
|
|
114
|
-
}
|
|
115
|
-
return collection;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @returns {Promise<mongodb.Collection>}
|
|
120
|
-
*/
|
|
121
|
-
async _getCollection () {
|
|
122
|
-
if (this._collection === null) {
|
|
123
|
-
let c;
|
|
124
|
-
try {
|
|
125
|
-
this._collection = this._getOrCreateCollection(this._collectionName);
|
|
126
|
-
c = await this._collection;
|
|
127
|
-
} catch (e) {
|
|
128
|
-
this._collection = null;
|
|
129
|
-
throw e;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const indexes = this._getIndexes();
|
|
133
|
-
|
|
134
|
-
await this._ensureIndexes(indexes, c);
|
|
135
|
-
}
|
|
136
|
-
return this._collection;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async _ensureIndexes (indexes, collection) {
|
|
140
|
-
let existing;
|
|
141
|
-
try {
|
|
142
|
-
existing = await collection.indexes();
|
|
143
|
-
} catch (e) {
|
|
144
|
-
existing = [];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
await Promise.all(existing
|
|
148
|
-
.filter(e => !['_id_', '_id'].includes(e.name) && !indexes.some(i => e.name === i.options.name))
|
|
149
|
-
.map((e) => {
|
|
150
|
-
// eslint-disable-next-line no-console
|
|
151
|
-
this._log.log(`dropping index ${e.name}`);
|
|
152
|
-
return collection.dropIndex(e.name)
|
|
153
|
-
.catch((err) => {
|
|
154
|
-
// eslint-disable-next-line no-console
|
|
155
|
-
this._log.error(`dropping index ${e.name} FAILED`, err);
|
|
156
|
-
});
|
|
157
|
-
}));
|
|
158
|
-
|
|
159
|
-
await Promise.all(indexes
|
|
160
|
-
.filter(i => !existing.some(e => e.name === i.options.name))
|
|
161
|
-
.map(i => collection
|
|
162
|
-
.createIndex(i.index, i.options)
|
|
163
|
-
// @ts-ignore
|
|
164
|
-
.catch((e) => {
|
|
165
|
-
if (i.isTextIndex) {
|
|
166
|
-
this._doesNotSupportTextIndex = true;
|
|
167
|
-
} else {
|
|
168
|
-
this._log.error(`failed to create index ${i.options.name} on ${collection.collectionName}`);
|
|
169
|
-
throw e;
|
|
170
|
-
}
|
|
171
|
-
})));
|
|
69
|
+
this.addIndex(index, options);
|
|
172
70
|
}
|
|
173
71
|
|
|
174
72
|
/**
|
|
@@ -187,9 +85,9 @@ class StateStorage {
|
|
|
187
85
|
*
|
|
188
86
|
* @param {string} senderId - sender identifier
|
|
189
87
|
* @param {string} pageId - page identifier
|
|
190
|
-
* @param {
|
|
88
|
+
* @param {object} [defaultState] - default state of the conversation
|
|
191
89
|
* @param {number} [timeout=300] - given default state
|
|
192
|
-
* @returns {Promise<
|
|
90
|
+
* @returns {Promise<object>} - conversation state
|
|
193
91
|
*/
|
|
194
92
|
async getOrCreateAndLock (senderId, pageId, defaultState = {}, timeout = 300) {
|
|
195
93
|
const now = Date.now();
|
|
@@ -217,7 +115,7 @@ class StateStorage {
|
|
|
217
115
|
$set
|
|
218
116
|
}, {
|
|
219
117
|
upsert: true,
|
|
220
|
-
|
|
118
|
+
returnDocument: 'after',
|
|
221
119
|
projection: {
|
|
222
120
|
_id: 0
|
|
223
121
|
}
|
|
@@ -257,7 +155,7 @@ class StateStorage {
|
|
|
257
155
|
const searchStates = typeof condition.search === 'string';
|
|
258
156
|
|
|
259
157
|
if (searchStates) {
|
|
260
|
-
if (this.
|
|
158
|
+
if (this._isCosmo) {
|
|
261
159
|
Object.assign(useCondition, {
|
|
262
160
|
name: { $regex: condition.search, $options: 'i' }
|
|
263
161
|
});
|
|
@@ -270,7 +168,7 @@ class StateStorage {
|
|
|
270
168
|
.find(useCondition)
|
|
271
169
|
.limit(limit + 1)
|
|
272
170
|
.skip(skip);
|
|
273
|
-
if (!this.
|
|
171
|
+
if (!this._isCosmo) {
|
|
274
172
|
cursor
|
|
275
173
|
.project({ score: { $meta: 'textScore' } })
|
|
276
174
|
.sort({ score: { $meta: 'textScore' } });
|
|
@@ -301,7 +199,7 @@ class StateStorage {
|
|
|
301
199
|
}
|
|
302
200
|
|
|
303
201
|
return {
|
|
304
|
-
data: data.map(camp => this._mapState(camp)),
|
|
202
|
+
data: data.map((camp) => this._mapState(camp)),
|
|
305
203
|
lastKey: nextLastKey
|
|
306
204
|
};
|
|
307
205
|
}
|
|
@@ -323,8 +221,8 @@ class StateStorage {
|
|
|
323
221
|
/**
|
|
324
222
|
* Save the state to database
|
|
325
223
|
*
|
|
326
|
-
* @param {
|
|
327
|
-
* @returns {Promise<
|
|
224
|
+
* @param {object} state - conversation state
|
|
225
|
+
* @returns {Promise<object>}
|
|
328
226
|
*/
|
|
329
227
|
async saveState (state) {
|
|
330
228
|
Object.assign(state, {
|
package/src/main.js
CHANGED
|
@@ -9,6 +9,7 @@ const BotTokenStorage = require('./BotTokenStorage');
|
|
|
9
9
|
const ChatLogStorage = require('./ChatLogStorage');
|
|
10
10
|
const BotConfigStorage = require('./BotConfigStorage');
|
|
11
11
|
const AttachmentCache = require('./AttachmentCache');
|
|
12
|
+
const AuditLogStorage = require('./AuditLogStorage');
|
|
12
13
|
const NotificationsStorage = require('./NotificationsStorage');
|
|
13
14
|
|
|
14
15
|
module.exports = {
|
|
@@ -18,5 +19,6 @@ module.exports = {
|
|
|
18
19
|
ChatLogStorage,
|
|
19
20
|
BotConfigStorage,
|
|
20
21
|
AttachmentCache,
|
|
21
|
-
NotificationsStorage
|
|
22
|
+
NotificationsStorage,
|
|
23
|
+
AuditLogStorage
|
|
22
24
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|