Skip to content

Commit 340ba33

Browse files
committed
Added new BotStorage classes
1 parent d0f20ba commit 340ba33

File tree

2 files changed

+180
-38
lines changed

2 files changed

+180
-38
lines changed

Node/src/storage/BotConnectorStorage.ts

Lines changed: 89 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3232
//
3333

34-
import storage = require('./Storage');
34+
import storage = require('./BotStorage');
3535
import request = require('request');
3636

3737
export interface IBotConnectorStorageOptions {
@@ -40,53 +40,104 @@ export interface IBotConnectorStorageOptions {
4040
appSecret: string;
4141
}
4242

43-
export class BotConnectorStorage implements storage.IStorage {
43+
export interface IBotConnectorStorageData extends storage.IBotStorageData {
44+
userDataHash?: string;
45+
conversationDataHash?: string;
46+
}
47+
48+
export class BotConnectorStorage implements storage.IBotStorage {
4449
constructor(private options: IBotConnectorStorageOptions) {
4550

4651
}
4752

48-
public get(id: string, callback: (err: Error, data: any) => void): void {
53+
public get(address: storage.IBotStorageAddress, callback: (err: Error, data: storage.IBotStorageData) => void): void {
54+
var ops = 2;
4955
var settings = this.options;
50-
var options: request.Options = {
51-
url: settings.endpoint + '/bot/v1.0/bots' + id
52-
};
53-
if (settings.appId && settings.appSecret) {
54-
options.auth = {
55-
username: settings.appId,
56-
password: settings.appSecret
57-
};
58-
options.headers = {
59-
'Ocp-Apim-Subscription-Key': settings.appSecret
60-
};
61-
}
62-
request.get(options, (err, response, body) => {
63-
try {
64-
var data: any;
65-
if (!err && typeof body === 'string') {
66-
data = JSON.parse(body);
56+
var data: storage.IBotStorageData = {};
57+
function read(path: string, field: string) {
58+
if (path) {
59+
var options: request.Options = {
60+
url: settings.endpoint + '/bot/v1.0/bots' + path
61+
};
62+
if (settings.appId && settings.appSecret) {
63+
options.auth = {
64+
username: settings.appId,
65+
password: settings.appSecret
66+
};
67+
options.headers = {
68+
'Ocp-Apim-Subscription-Key': settings.appSecret
69+
};
6770
}
68-
callback(err, data);
69-
} catch (e) {
70-
callback(e instanceof Error ? e : new Error(e.toString()), null);
71+
request.get(options, (err, response, body) => {
72+
if (!err) {
73+
try {
74+
(<any>data)[field + 'Hash'] = body;
75+
(<any>data)[field] = typeof body === 'string' ? JSON.parse(body) : null;
76+
} catch (e) {
77+
err = e instanceof Error ? e : new Error(e.toString());
78+
}
79+
}
80+
if (callback && (err || --ops == 0)) {
81+
callback(err, data);
82+
callback = null;
83+
}
84+
});
85+
} else if (callback && --ops == 0) {
86+
callback(null, data);
7187
}
72-
});
88+
}
89+
var userPath = address.userId ? '/users/' + address.userId : null;
90+
var convoPath = address.conversationId ? '/conversations/' + address.conversationId + userPath : null;
91+
read(userPath, 'userData');
92+
read(convoPath, 'conversationData');
7393
}
7494

75-
public save(id: string, data: any, callback?: (err: Error) => void): void {
95+
public save(address: storage.IBotStorageAddress, data: storage.IBotStorageData, callback?: (err: Error) => void): void {
96+
var ops = 2;
7697
var settings = this.options;
77-
var options: request.Options = {
78-
url: settings.endpoint + '/bot/v1.0/bots' + id,
79-
body: data
80-
};
81-
if (settings.appId && settings.appSecret) {
82-
options.auth = {
83-
username: settings.appId,
84-
password: settings.appSecret
85-
};
86-
options.headers = {
87-
'Ocp-Apim-Subscription-Key': settings.appSecret
88-
};
98+
function write(path: string, field: string) {
99+
if (path) {
100+
var err: Error;
101+
var body: string;
102+
var hashField = field + 'Hash';
103+
try {
104+
body = JSON.stringify((<any>data)[field]);
105+
} catch (e) {
106+
err = e instanceof Error ? e : new Error(e.toString());
107+
}
108+
if (!err && (!(<any>data)[hashField] || body !== (<any>data)[hashField])) {
109+
(<any>data)[hashField] = body;
110+
var options: request.Options = {
111+
url: settings.endpoint + '/bot/v1.0/bots' + path,
112+
body: body
113+
};
114+
if (settings.appId && settings.appSecret) {
115+
options.auth = {
116+
username: settings.appId,
117+
password: settings.appSecret
118+
};
119+
options.headers = {
120+
'Ocp-Apim-Subscription-Key': settings.appSecret
121+
};
122+
}
123+
request.post(options, (err) => {
124+
if (callback && (err || --ops == 0)) {
125+
callback(err);
126+
callback = null;
127+
}
128+
});
129+
} else if (callback && (err || --ops == 0)) {
130+
callback(err);
131+
callback = null;
132+
}
133+
} else if (callback && --ops == 0) {
134+
callback(null);
135+
}
89136
}
90-
request.post(options, callback);
137+
var userPath = address.userId ? '/users/' + address.userId : null;
138+
var convoPath = address.conversationId ? '/conversations/' + address.conversationId + userPath : null;
139+
write(userPath, 'userData');
140+
write(convoPath, 'conversationData');
141+
91142
}
92143
}

Node/src/storage/BotStorage.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license.
4+
//
5+
// Microsoft Bot Framework: http://botframework.com
6+
//
7+
// Bot Builder SDK Github:
8+
// https://github.com/Microsoft/BotBuilder
9+
//
10+
// Copyright (c) Microsoft Corporation
11+
// All rights reserved.
12+
//
13+
// MIT License:
14+
// Permission is hereby granted, free of charge, to any person obtaining
15+
// a copy of this software and associated documentation files (the
16+
// "Software"), to deal in the Software without restriction, including
17+
// without limitation the rights to use, copy, modify, merge, publish,
18+
// distribute, sublicense, and/or sell copies of the Software, and to
19+
// permit persons to whom the Software is furnished to do so, subject to
20+
// the following conditions:
21+
//
22+
// The above copyright notice and this permission notice shall be
23+
// included in all copies or substantial portions of the Software.
24+
//
25+
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32+
//
33+
34+
import utils = require('../utils');
35+
36+
export interface IBotStorageAddress {
37+
userId?: string;
38+
conversationId?: string;
39+
}
40+
41+
export interface IBotStorageData {
42+
userData?: any;
43+
conversationData?: any;
44+
}
45+
46+
export interface IBotStorage {
47+
get(address: IBotStorageAddress, callback: (err: Error, data: IBotStorageData) => void): void;
48+
save(address: IBotStorageAddress, data: IBotStorageData, callback?: (err: Error) => void): void;
49+
}
50+
51+
export class MemoryBotStorage implements IBotStorage {
52+
private userStore: { [id: string]: string; } = {};
53+
private conversationStore: { [id: string]: string; } = {};
54+
55+
public get(address: IBotStorageAddress, callback: (err: Error, data: IBotStorageData) => void): void {
56+
var data: IBotStorageData = {};
57+
if (address.userId) {
58+
if (this.userStore.hasOwnProperty(address.userId)) {
59+
data.userData = JSON.parse(this.userStore[address.userId]);
60+
} else {
61+
data.userData = null;
62+
}
63+
}
64+
if (address.conversationId) {
65+
if (this.conversationStore.hasOwnProperty(address.conversationId)) {
66+
data.conversationData = JSON.parse(this.conversationStore[address.conversationId]);
67+
} else {
68+
data.conversationData = null;
69+
}
70+
}
71+
callback(null, data);
72+
}
73+
74+
public save(address: IBotStorageAddress, data: IBotStorageData, callback?: (err: Error) => void): void {
75+
if (address.userId) {
76+
this.userStore[address.userId] = JSON.stringify(data.userData || {});
77+
}
78+
if (address.conversationId) {
79+
this.conversationStore[address.conversationId] = JSON.stringify(data.conversationData || {});
80+
}
81+
}
82+
83+
public delete(address: IBotStorageAddress) {
84+
if (address.userId && this.userStore.hasOwnProperty(address.userId)) {
85+
delete this.userStore[address.userId];
86+
}
87+
if (address.conversationId && this.conversationStore.hasOwnProperty(address.conversationId)) {
88+
delete this.conversationStore[address.conversationId];
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)