chat-platform 1.3.2 → 2.0.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/.eslintrc +23 -16
- package/__tests__/context-provider-memory.js +148 -189
- package/__tests__/context-provider-sqlite.js +49 -82
- package/__tests__/universal-platform.js +37 -86
- package/chat-platform.js +69 -89
- package/package.json +4 -3
- package/providers/memory.js +69 -29
- package/providers/plain-file.js +32 -3
- package/providers/sqlite.js +109 -39
- package/__tests__/context-provider-plain-file.js +0 -174
|
@@ -82,57 +82,48 @@ describe('Universal Connector', () => {
|
|
|
82
82
|
resolve(message);
|
|
83
83
|
})
|
|
84
84
|
);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
it('send outgoing message', async () => {
|
|
89
|
+
await chatServer.start()
|
|
90
|
+
const message = await chatServer.createMessage('42', '1234', '4567', {
|
|
91
|
+
payload: {
|
|
92
|
+
type: 'a-message-type',
|
|
93
|
+
chatId: '42'
|
|
91
94
|
}
|
|
92
|
-
return null;
|
|
93
95
|
});
|
|
94
|
-
|
|
96
|
+
let sentMessage = await chatServer.send(message);
|
|
97
|
+
|
|
98
|
+
assert.equal(sentMessage.message_id, '444');
|
|
99
|
+
expect(sendFunction).to.have.been.called();
|
|
95
100
|
|
|
96
|
-
it('receive incoming message', () => {
|
|
97
|
-
chatServer.start()
|
|
98
|
-
.then(() => {
|
|
99
|
-
chatServer.on('message', message => {
|
|
100
|
-
assert.equal(message.payload.type, 'message');
|
|
101
|
-
assert.equal(message.custom_value, 42);
|
|
102
|
-
assert.equal(message.payload.chatId, '42');
|
|
103
|
-
assert.equal(message.originalMessage.messageId, 'xyz');
|
|
104
|
-
assert.equal(message.originalMessage.userId, 24);
|
|
105
|
-
assert.isFunction(message.chat);
|
|
106
|
-
const variables = message.chat().all();
|
|
107
|
-
assert.equal(variables.payload, 'Bazinga');
|
|
108
|
-
assert.equal(variables.transport, 'universal');
|
|
109
|
-
assert.equal(variables.authorized, false);
|
|
110
|
-
assert.equal(variables.language, 'it');
|
|
111
|
-
assert.instanceOf(message.payload.ts, moment);
|
|
112
|
-
});
|
|
113
|
-
chatServer.receive({
|
|
114
|
-
text: 'Bazinga',
|
|
115
|
-
lang: 'it',
|
|
116
|
-
chat_id: '42',
|
|
117
|
-
_id: 'xyz',
|
|
118
|
-
user: { id: 24 }
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
101
|
});
|
|
122
102
|
|
|
123
|
-
it('
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
.
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
103
|
+
it('receive incoming message', async (done) => {
|
|
104
|
+
await chatServer.start()
|
|
105
|
+
|
|
106
|
+
chatServer.on('message', message => {
|
|
107
|
+
assert.equal(message.payload.type, 'message');
|
|
108
|
+
assert.equal(message.custom_value, 42);
|
|
109
|
+
assert.equal(message.payload.chatId, '42');
|
|
110
|
+
assert.equal(message.originalMessage.messageId, 'xyz');
|
|
111
|
+
assert.equal(message.originalMessage.userId, 42);
|
|
112
|
+
assert.isFunction(message.chat);
|
|
113
|
+
const variables = message.chat().all();
|
|
114
|
+
assert.equal(variables.payload, 'Bazinga');
|
|
115
|
+
assert.equal(variables.authorized, false);
|
|
116
|
+
assert.equal(variables.language, 'it');
|
|
117
|
+
assert.instanceOf(message.payload.ts, moment);
|
|
118
|
+
done();
|
|
119
|
+
});
|
|
120
|
+
chatServer.receive({
|
|
121
|
+
text: 'Bazinga',
|
|
122
|
+
lang: 'it',
|
|
123
|
+
chat_id: '42',
|
|
124
|
+
_id: 'xyz',
|
|
125
|
+
user: { id: 24 }
|
|
126
|
+
});
|
|
136
127
|
});
|
|
137
128
|
|
|
138
129
|
it('send outgoing message wrong type', () => {
|
|
@@ -147,44 +138,4 @@ describe('Universal Connector', () => {
|
|
|
147
138
|
.then(() => expect(sendFunction).to.not.have.been.called());
|
|
148
139
|
});
|
|
149
140
|
|
|
150
|
-
it('create a message with just a userId and resolves it', () => {
|
|
151
|
-
return chatServer.start()
|
|
152
|
-
.then(() => chatServer.createMessage(null, '1234', '4567', {
|
|
153
|
-
payload: {
|
|
154
|
-
type: 'a-message-type'
|
|
155
|
-
}
|
|
156
|
-
}))
|
|
157
|
-
.then(message => chatServer.send(message))
|
|
158
|
-
.then(() => expect(sendFunction).to.have.been.called());
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('create a message with just a userId and doesn\'t resolve it', () => {
|
|
162
|
-
return chatServer.start()
|
|
163
|
-
.then(() => chatServer.createMessage(null, '5678', '4567', {
|
|
164
|
-
payload: {
|
|
165
|
-
type: 'a-message-type'
|
|
166
|
-
}
|
|
167
|
-
}))
|
|
168
|
-
.then(message => chatServer.send(message))
|
|
169
|
-
.then(
|
|
170
|
-
() => {},
|
|
171
|
-
e => {
|
|
172
|
-
assert.include(e.toString(), 'Error: The userId<->chatId resolver was not able to find a valid chatId for user 5678');
|
|
173
|
-
expect(sendFunction).to.not.have.been.called()
|
|
174
|
-
}
|
|
175
|
-
);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('create a message with a server and just a userId and try to send to the other server', () => {
|
|
179
|
-
return chatServer.start()
|
|
180
|
-
.then(() => chatServer.createMessage(null, '1234', '4567', {
|
|
181
|
-
payload: {
|
|
182
|
-
type: 'a-message-type'
|
|
183
|
-
}
|
|
184
|
-
}))
|
|
185
|
-
.then(message => chatServerAlt.send(message))
|
|
186
|
-
.then(() => expect(sendFunctionAlt).to.have.been.called());
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
|
|
190
141
|
});
|
package/chat-platform.js
CHANGED
|
@@ -2,7 +2,7 @@ const _ = require('underscore');
|
|
|
2
2
|
const _s = require('underscore.string');
|
|
3
3
|
const clc = require('cli-color');
|
|
4
4
|
const prettyjson = require('prettyjson');
|
|
5
|
-
const {
|
|
5
|
+
const { when } = require('./lib/utils');
|
|
6
6
|
const EventEmitter = require('events').EventEmitter;
|
|
7
7
|
const inherits = require('util').inherits;
|
|
8
8
|
const lcd = require('./helpers/lcd');
|
|
@@ -96,8 +96,9 @@ const ChatExpress = function(options) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function parseMessage(payload, options, chatServer) {
|
|
100
|
-
|
|
99
|
+
async function parseMessage(payload, options, chatServer) {
|
|
100
|
+
const instanceOptions = chatServer.getOptions();
|
|
101
|
+
const { contextProvider, transport } = instanceOptions;
|
|
101
102
|
|
|
102
103
|
payload = _.clone(payload);
|
|
103
104
|
// sets inbound
|
|
@@ -111,21 +112,34 @@ const ChatExpress = function(options) {
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
evaluateParam(payload, 'chatId', 'chatIdKey', chatServer);
|
|
114
|
-
evaluateParam(payload, 'userId', 'userIdKey', chatServer);
|
|
115
115
|
evaluateParam(payload, 'messageId', 'messageIdKey', chatServer);
|
|
116
116
|
evaluateParam(payload, 'ts', 'tsKey', chatServer);
|
|
117
117
|
evaluateParam(payload, 'type', 'type', chatServer);
|
|
118
118
|
evaluateParam(payload, 'language', 'language', chatServer);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
payload.userId = !_.isEmpty(payload.userId) ? payload.userId : payload.chatId;
|
|
119
|
+
evaluateParam(payload, 'userId', 'userIdKey', chatServer);
|
|
120
|
+
|
|
122
121
|
// evaluate callbacks
|
|
123
122
|
const callbacks = chatServer.getCallbacks();
|
|
124
|
-
_(['chatId', '
|
|
123
|
+
_(['chatId', 'ts', 'type', 'language', 'messageId']).each(function(callbackName) {
|
|
125
124
|
if (_.isFunction(callbacks[callbackName])) {
|
|
126
125
|
payload[callbackName] = callbacks[callbackName].call(chatServer, payload)
|
|
127
126
|
}
|
|
128
127
|
});
|
|
128
|
+
|
|
129
|
+
// try to evaluate a default userId
|
|
130
|
+
let defaultUserId = payload.userId;
|
|
131
|
+
if (_.isEmpty(defaultUserId) && _.isFunction(callbacks['userId'])) {
|
|
132
|
+
defaultUserId = callbacks['userId'].call(chatServer, payload);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// get the userId from chatId, ask the context provider to create one and to create
|
|
136
|
+
// the bindings between chatId <-> transport <-> userId
|
|
137
|
+
payload.userId = await contextProvider.getOrCreateUserId(
|
|
138
|
+
String(payload.chatId),
|
|
139
|
+
transport,
|
|
140
|
+
defaultUserId
|
|
141
|
+
);
|
|
142
|
+
|
|
129
143
|
// at this point should have at least the values chatId and type
|
|
130
144
|
if (payload.chatId == null && !options.relaxChatId) {
|
|
131
145
|
throw 'Error: inbound message key "chatId" for transport ' + _this.options.transport + ' is empty\n\n'
|
|
@@ -166,11 +180,30 @@ const ChatExpress = function(options) {
|
|
|
166
180
|
const onCreateMessage = _.isFunction(options.onCreateMessage) ? options.onCreateMessage : identity;
|
|
167
181
|
inboudMessage = inboudMessage || {};
|
|
168
182
|
|
|
169
|
-
|
|
170
|
-
chatId
|
|
171
|
-
|
|
183
|
+
if (_.isEmpty(userId) && _.isEmpty(chatId)) {
|
|
184
|
+
throw 'Both userId and chatId empty, cannot start a conversation';
|
|
185
|
+
}
|
|
186
|
+
// get the context finding the userId given chatId, chatbotId and transport
|
|
187
|
+
if (_.isEmpty(userId) && !_.isEmpty(chatId)) {
|
|
188
|
+
userId = await contextProvider.getUserId(chatId, options.transport);
|
|
189
|
+
if (_.isEmpty(userId)) {
|
|
190
|
+
throw `Unable to resolve userId from chatId "${chatId}" (${options.transport})`;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (_.isEmpty(chatId) && !_.isEmpty(userId)) {
|
|
194
|
+
chatId = await contextProvider.getChatId(userId, options.transport);
|
|
195
|
+
if (_.isEmpty(chatId)) {
|
|
196
|
+
throw `Unable to resolve chatId from userId "${userId}" (${options.transport}). That means either the userId "${userId}" doesn't exist or it's not possible to find a valid chatId for the platform ${options.transport}.`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const chatContext = await contextProvider.getOrCreateContext(userId, {
|
|
201
|
+
chatId,
|
|
202
|
+
userId,
|
|
172
203
|
transport: options.transport,
|
|
173
|
-
|
|
204
|
+
chatbotId: options.chatbotId
|
|
205
|
+
});
|
|
206
|
+
|
|
174
207
|
await chatContext.set({
|
|
175
208
|
authorized: false,
|
|
176
209
|
pending: false,
|
|
@@ -180,13 +213,13 @@ const ChatExpress = function(options) {
|
|
|
180
213
|
originalMessage: {
|
|
181
214
|
chatId: chatId,
|
|
182
215
|
userId: userId,
|
|
216
|
+
chatbotId: options.chatbotId,
|
|
183
217
|
messageId: messageId,
|
|
184
218
|
transport: options.transport,
|
|
185
219
|
language: null
|
|
186
220
|
},
|
|
187
221
|
chat() {
|
|
188
|
-
return contextProvider.
|
|
189
|
-
chatId,
|
|
222
|
+
return contextProvider.getContext(
|
|
190
223
|
userId,
|
|
191
224
|
{
|
|
192
225
|
userId: this.originalMessage.userId,
|
|
@@ -214,7 +247,7 @@ const ChatExpress = function(options) {
|
|
|
214
247
|
return onCreateMessage.call(chatServer, message);
|
|
215
248
|
}
|
|
216
249
|
|
|
217
|
-
function inboundMessage(payload, chatServer) {
|
|
250
|
+
async function inboundMessage(payload, chatServer) {
|
|
218
251
|
const options = chatServer.getOptions();
|
|
219
252
|
const contextProvider = options.contextProvider;
|
|
220
253
|
if (chatServer.isDebug()) {
|
|
@@ -233,7 +266,7 @@ const ChatExpress = function(options) {
|
|
|
233
266
|
// parse the message to extract the minimum payload needed for chat-platform to work properly
|
|
234
267
|
// could raise errors, relay to chat server
|
|
235
268
|
try {
|
|
236
|
-
var parsedMessage = parseMessage(payload, _this.options, chatServer);
|
|
269
|
+
var parsedMessage = await parseMessage(payload, _this.options, chatServer);
|
|
237
270
|
} catch(e) {
|
|
238
271
|
chatServer.emit('error', e);
|
|
239
272
|
return;
|
|
@@ -258,10 +291,13 @@ const ChatExpress = function(options) {
|
|
|
258
291
|
inbound: true
|
|
259
292
|
},
|
|
260
293
|
chat: function() {
|
|
261
|
-
return contextProvider.
|
|
262
|
-
parsedMessage.chatId,
|
|
294
|
+
return contextProvider.getContext(
|
|
263
295
|
parsedMessage.userId,
|
|
264
|
-
{
|
|
296
|
+
{
|
|
297
|
+
userId: this.originalMessage.userId,
|
|
298
|
+
transport: this.originalMessage.transport,
|
|
299
|
+
chatId: this.originalMessage.chatId
|
|
300
|
+
}
|
|
265
301
|
);
|
|
266
302
|
},
|
|
267
303
|
api: function() {
|
|
@@ -281,15 +317,20 @@ const ChatExpress = function(options) {
|
|
|
281
317
|
// if any context provider, then create the context
|
|
282
318
|
if (contextProvider != null) {
|
|
283
319
|
stack = stack
|
|
284
|
-
.then(() =>
|
|
285
|
-
parsedMessage.chatId,
|
|
320
|
+
.then(() => contextProvider.getOrCreateContext(
|
|
286
321
|
parsedMessage.userId,
|
|
287
|
-
{
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
322
|
+
{
|
|
323
|
+
userId: parsedMessage.userId,
|
|
324
|
+
transport: parsedMessage.transport,
|
|
325
|
+
chatId: parsedMessage.chatId
|
|
326
|
+
}
|
|
327
|
+
))
|
|
328
|
+
.then(chatContext => when(chatContext.set({
|
|
329
|
+
language: parsedMessage.language,
|
|
330
|
+
authorized: false,
|
|
331
|
+
pending: false
|
|
332
|
+
})))
|
|
333
|
+
.then(() => when(message));
|
|
293
334
|
} else {
|
|
294
335
|
// eslint-disable-next-line no-console
|
|
295
336
|
console.log(yellow('WARNING: context provider was not specified'));
|
|
@@ -406,18 +447,6 @@ const ChatExpress = function(options) {
|
|
|
406
447
|
return;
|
|
407
448
|
}
|
|
408
449
|
|
|
409
|
-
const instanceOptions = chatServer.getOptions();
|
|
410
|
-
// check if the message is from the right platform (in static class or instance)
|
|
411
|
-
/*if (message.originalMessage != null && message.originalMessage.transport !== _this.options.transport &&
|
|
412
|
-
message.originalMessage.transport !== instanceOptions.transport) {
|
|
413
|
-
// exit, it's not from the current platform
|
|
414
|
-
if (chatServer.isDebug()) {
|
|
415
|
-
// eslint-disable-next-line no-console
|
|
416
|
-
console.log(yellow('Skipped incoming message for platform: ' + message.originalMessage.transport));
|
|
417
|
-
}
|
|
418
|
-
return;
|
|
419
|
-
}*/
|
|
420
|
-
|
|
421
450
|
if (chatServer.isDebug()) {
|
|
422
451
|
// eslint-disable-next-line no-console
|
|
423
452
|
console.log(orange('-- OUTBOUND MESSAGE --'));
|
|
@@ -429,56 +458,7 @@ const ChatExpress = function(options) {
|
|
|
429
458
|
|
|
430
459
|
// create empty promise
|
|
431
460
|
let stack = new Promise(resolve => resolve(message));
|
|
432
|
-
|
|
433
|
-
stack = stack.then(message => {
|
|
434
|
-
const { transport } = instanceOptions;
|
|
435
|
-
if (!isEmpty(message.payload.chatId)) {
|
|
436
|
-
// if there's a chatId, everything ok, skip
|
|
437
|
-
return message;
|
|
438
|
-
} else if (_.isFunction(_globalCallbacks.getChatIdFromUserId) && message.originalMessage.userId != null) {
|
|
439
|
-
// try to call the callback
|
|
440
|
-
try {
|
|
441
|
-
return when(_globalCallbacks.getChatIdFromUserId.call(chatServer, message.originalMessage.userId, transport, message))
|
|
442
|
-
.then(
|
|
443
|
-
chatId => {
|
|
444
|
-
if (isEmpty(chatId)) {
|
|
445
|
-
// eslint-disable-next-line no-console
|
|
446
|
-
console.log(lcd.error(`[onGetChatIdFromUserId] The userId<->chatId resolver was not able to find a valid chatId for user ${message.originalMessage.userId}(${transport})`));
|
|
447
|
-
throw new Error(`The userId<->chatId resolver was not able to find a valid chatId for user ${message.originalMessage.userId}(${transport})`);
|
|
448
|
-
} else {
|
|
449
|
-
if (instanceOptions.debug) {
|
|
450
|
-
// eslint-disable-next-line no-console
|
|
451
|
-
console.log(lcd.green('[onGetChatIdFromUserId]') + lcd.grey(` Resolved ${message.originalMessage.userId}(${transport}) in chatId:${chatId}`));
|
|
452
|
-
}
|
|
453
|
-
message.payload.chatId = chatId;
|
|
454
|
-
return message;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
);
|
|
458
|
-
} catch(e) {
|
|
459
|
-
// eslint-disable-next-line no-console
|
|
460
|
-
console.log(lcd.error(`[onGetChatIdFromUserId] runtime error in chatId<->userId resolver for user ${message.originalMessage.userId}(${transport})`));
|
|
461
|
-
lcd.dump(e);
|
|
462
|
-
throw new Error(`[onGetChatIdFromUserId] runtime error in chatId<->userId resolver for user ${message.originalMessage.userId}(${transport})`);
|
|
463
|
-
}
|
|
464
|
-
} else {
|
|
465
|
-
// provide some feedback for not being able to resolve a chatId
|
|
466
|
-
if (instanceOptions.debug) {
|
|
467
|
-
if (_.isFunction(_globalCallbacks.getChatIdFromUserId) && isEmpty(message.originalMessage.userId)) {
|
|
468
|
-
// eslint-disable-next-line no-console
|
|
469
|
-
console.log(lcd.warn(`[onGetChatIdFromUserId] Callback was provided but incoming message has no userId (${transport}), unable to resolve a valid chatId`));
|
|
470
|
-
} else if (!_.isFunction(_globalCallbacks.getChatIdFromUserId)) {
|
|
471
|
-
// eslint-disable-next-line no-console
|
|
472
|
-
console.log(lcd.warn('[onGetChatIdFromUserId] Callback was NOT provided and chatId is empty'));
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
// raise error only if not relaxChatId
|
|
476
|
-
if (!instanceOptions.relaxChatId) {
|
|
477
|
-
throw new Error('Incoming message has empty chatId and no chatId - userId resolved has been provided');
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
return message;
|
|
481
|
-
});
|
|
461
|
+
|
|
482
462
|
// run general middleware
|
|
483
463
|
_(_this.uses.concat(chatServer.getUseMiddleWares())).each(function(filter) {
|
|
484
464
|
stack = stack.then(function(message) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chat-platform",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Universal Chat Platform",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,14 +19,15 @@
|
|
|
19
19
|
"prettyjson": "^1.2.1",
|
|
20
20
|
"request": "^2.88.0",
|
|
21
21
|
"sequelize": "^5.21.6",
|
|
22
|
-
"sqlite3": "^
|
|
22
|
+
"sqlite3": "^5.0.0",
|
|
23
23
|
"underscore": "^1.9.1",
|
|
24
24
|
"underscore.string": "^3.3.5"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"chai": "^4.1.1",
|
|
28
28
|
"chai-spies": "^1.0.0",
|
|
29
|
-
"eslint": "^
|
|
29
|
+
"eslint": "^8.12.0",
|
|
30
|
+
"eslint-plugin-jest": "^26.1.3",
|
|
30
31
|
"jest": "^22.0.6"
|
|
31
32
|
}
|
|
32
33
|
}
|
package/providers/memory.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
const _ = require('underscore');
|
|
2
|
-
const _store = {};
|
|
3
|
-
const _storeUserIds = {};
|
|
4
2
|
|
|
5
3
|
const isEmpty = value => value == null || value === '';
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const _storeChatIds = {};
|
|
6
|
+
const _storeUserIds = {};
|
|
7
|
+
const _store = {};
|
|
8
|
+
|
|
9
|
+
function MemoryStore(userId, statics = {}, warnings = false) {
|
|
10
|
+
//this.chatId = chatId != null ? String(chatId) : null;
|
|
9
11
|
this.userId = userId != null ? String(userId) : null;
|
|
10
12
|
// make sure userId is always a string
|
|
11
13
|
this.statics = Object.assign({}, statics, { userId: statics.userId != null ? String(statics.userId) : undefined });
|
|
@@ -14,19 +16,15 @@ function MemoryStore(chatId, userId, statics = {}, warnings = false) {
|
|
|
14
16
|
}
|
|
15
17
|
return this;
|
|
16
18
|
}
|
|
19
|
+
|
|
17
20
|
_.extend(MemoryStore.prototype, {
|
|
18
21
|
getPayload() {
|
|
19
22
|
// always precedence to userId
|
|
20
23
|
if (this.userId != null && _storeUserIds[this.userId] != null) {
|
|
21
24
|
return _storeUserIds[this.userId];
|
|
22
|
-
} else if (this.chatId != null && _store[this.chatId] != null) {
|
|
23
|
-
return _store[this.chatId];
|
|
24
25
|
} else if (this.userId != null) {
|
|
25
26
|
_storeUserIds[this.userId] = {};
|
|
26
27
|
return _storeUserIds[this.userId];
|
|
27
|
-
} else if (this.chatId != null) {
|
|
28
|
-
_store[this.chatId] = {};
|
|
29
|
-
return _store[this.chatId];
|
|
30
28
|
}
|
|
31
29
|
return {};
|
|
32
30
|
},
|
|
@@ -105,32 +103,74 @@ _.extend(MemoryStore.prototype, {
|
|
|
105
103
|
|
|
106
104
|
function MemoryFactory() {
|
|
107
105
|
|
|
106
|
+
this.getOrCreateUserId = async function(chatId, transport, defaultUserId) {
|
|
107
|
+
// try to find a userId given then chatId / transport for the current chatbot
|
|
108
|
+
if (isEmpty(chatId)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (_storeChatIds[transport] != null && !_.isEmpty(_storeChatIds[transport][chatId])) {
|
|
113
|
+
return _storeUserIds[transport][chatId];
|
|
114
|
+
} else {
|
|
115
|
+
const userId = !_.isEmpty(defaultUserId) ? defaultUserId : chatId;
|
|
116
|
+
_storeUserIds[chatId] = _storeUserIds[chatId] != null ? _storeUserIds[chatId] : {};
|
|
117
|
+
_storeUserIds[chatId][transport] = userId;
|
|
118
|
+
_storeChatIds[userId] = _storeChatIds[userId] != null ? _storeChatIds[userId] : {};
|
|
119
|
+
_storeChatIds[userId][transport] = chatId;
|
|
120
|
+
return userId;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
this.getUserId = async function(chatId, transport) {
|
|
125
|
+
return _storeUserIds[chatId] != null && !_.isEmpty(_storeUserIds[chatId][transport]) ?
|
|
126
|
+
_storeUserIds[chatId][transport] : chatId;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
this.getChatId = async function(userId, transport) {
|
|
130
|
+
return _storeChatIds[userId] != null && !_.isEmpty(_storeChatIds[userId][transport]) ?
|
|
131
|
+
_storeChatIds[userId][transport] : null;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
this.getOrCreateContext = async function(userId, statics) {
|
|
135
|
+
if (isEmpty(userId)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return new MemoryStore(userId, { ...statics });
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
this.mergeUserId = async function(fromUserId, toUserId) {
|
|
142
|
+
const destination = _storeChatIds[toUserId];
|
|
143
|
+
const source = _storeChatIds[fromUserId];
|
|
144
|
+
|
|
145
|
+
Object.keys(source)
|
|
146
|
+
.forEach(transport => {
|
|
147
|
+
const chatId = source[transport];
|
|
148
|
+
// copy chatId/transport to destination if doesn't exist
|
|
149
|
+
if (destination[transport] == null) {
|
|
150
|
+
destination[transport] = chatId;
|
|
151
|
+
}
|
|
152
|
+
// replace chatId reference
|
|
153
|
+
_storeUserIds[chatId][transport] = toUserId;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
delete _storeChatIds[fromUserId];
|
|
157
|
+
};
|
|
158
|
+
this.getContext = function(userId, statics) {
|
|
159
|
+
return new MemoryStore(userId, { ...statics });
|
|
160
|
+
};
|
|
161
|
+
|
|
108
162
|
this.getOrCreate = function(chatId, userId, statics) {
|
|
163
|
+
console.log('getOrCreate() is deprecated, use getOrCreateContext() instead');
|
|
109
164
|
if (isEmpty(chatId) && isEmpty(userId)) {
|
|
110
165
|
return null;
|
|
111
166
|
}
|
|
112
167
|
// just create an class that just wraps chatId and userId, add static value (cline)
|
|
113
|
-
const store = new MemoryStore(
|
|
168
|
+
const store = new MemoryStore(userId, { ...statics });
|
|
114
169
|
return store;
|
|
115
|
-
/*const chatContext = this.get(chatId, userId);
|
|
116
|
-
if (chatContext == null) {
|
|
117
|
-
const memoryStore = new MemoryStore({ ...defaults });
|
|
118
|
-
_store[chatId] = memoryStore;
|
|
119
|
-
if (!isEmpty(userId)) {
|
|
120
|
-
_storeUserIds[userId] = memoryStore;
|
|
121
|
-
}
|
|
122
|
-
return _store[chatId];
|
|
123
|
-
}
|
|
124
|
-
return chatContext;
|
|
125
|
-
*/
|
|
126
170
|
};
|
|
171
|
+
|
|
127
172
|
this.get = function(chatId, userId, statics) {
|
|
128
|
-
|
|
129
|
-
return _store[chatId];
|
|
130
|
-
} else if (!isEmpty(userId) && _storeUserIds[userId] != null) {
|
|
131
|
-
return _storeUserIds[userId];
|
|
132
|
-
}
|
|
133
|
-
return null;*/
|
|
173
|
+
console.log('get() is deprecated');
|
|
134
174
|
return new MemoryStore(chatId, userId, { ...statics });
|
|
135
175
|
};
|
|
136
176
|
|
|
@@ -145,13 +185,13 @@ _.extend(MemoryFactory.prototype, {
|
|
|
145
185
|
getOrCreate: function(/*chatId, userId, statics*/) {
|
|
146
186
|
},
|
|
147
187
|
assignToUser(userId, context) {
|
|
148
|
-
|
|
149
|
-
// TODO perhaps remove other occurence
|
|
188
|
+
console.log('assignToUser() is deprecated')
|
|
150
189
|
_storeUserIds[userId] = context;
|
|
151
190
|
},
|
|
152
191
|
reset() {
|
|
153
192
|
Object.keys(_store).forEach(key => delete _store[key]);
|
|
154
193
|
Object.keys(_storeUserIds).forEach(key => delete _storeUserIds[key]);
|
|
194
|
+
Object.keys(_storeChatIds).forEach(key => delete _storeUserIds[key]);
|
|
155
195
|
return this;
|
|
156
196
|
},
|
|
157
197
|
stop: function() {
|
package/providers/plain-file.js
CHANGED
|
@@ -2,12 +2,11 @@ const _ = require('underscore');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const moment = require('moment');
|
|
4
4
|
const crypto = require('crypto');
|
|
5
|
+
|
|
5
6
|
const lcd = require('../helpers/lcd');
|
|
6
7
|
const FileQueue = require('../helpers/promises-queue');
|
|
7
8
|
const filesQueue = {};
|
|
8
9
|
|
|
9
|
-
// memory cache, each loaded store is here and it's saved to filesystem at every changes,
|
|
10
|
-
// subsequent read hit the cache
|
|
11
10
|
let _store = {};
|
|
12
11
|
// main index
|
|
13
12
|
let _index;
|
|
@@ -28,7 +27,6 @@ const parse = content => {
|
|
|
28
27
|
return obj;
|
|
29
28
|
};
|
|
30
29
|
|
|
31
|
-
|
|
32
30
|
const deleteFile = file => {
|
|
33
31
|
return new Promise((resolve, reject) => {
|
|
34
32
|
fs.unlink(file, err => {
|
|
@@ -131,6 +129,37 @@ function FileFactory(params) {
|
|
|
131
129
|
throw 'Plain file context provider: "path" (' + params.path + ') doesn\'t exist';
|
|
132
130
|
}
|
|
133
131
|
|
|
132
|
+
this.getOrCreateUserId = async function(chatId, transport) {
|
|
133
|
+
return chatId;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
this.getUserId = async function(chatId, transport) {
|
|
137
|
+
// plain file is actually not implemented for multi-transport, alwats use sqlite
|
|
138
|
+
return chatId;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
this.getChatId = async function(userId, transport) {
|
|
142
|
+
return userId;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
this.getOrCreateContext = async function(userId, statics) {
|
|
146
|
+
const { path } = params;
|
|
147
|
+
// chatId is always userId
|
|
148
|
+
return new FileStore(userId, userId, { ...statics }, { path });
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
this.mergeUserId = async function(fromUserId, toUserId) {
|
|
152
|
+
// not implemented
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
this.getContext = function(userId, statics) {
|
|
156
|
+
const { path } = params;
|
|
157
|
+
// chatId is always userId
|
|
158
|
+
return new FileStore(userId, userId, { ...statics }, { path });
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// below here deprecated
|
|
162
|
+
|
|
134
163
|
this.getOrCreate = function(chatId, userId = null, statics = {}) {
|
|
135
164
|
const { path } = params;
|
|
136
165
|
return new FileStore(chatId, userId, { ...statics }, { path });
|