1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | return new (P || (P = Promise))(function (resolve, reject) {
|
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8 | });
|
9 | };
|
10 | Object.defineProperty(exports, "__esModule", { value: true });
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | const botframework_connector_1 = require("botframework-connector");
|
19 | const botbuilder_core_1 = require("botbuilder-core");
|
20 | const teamsActivityHelpers_1 = require("./teamsActivityHelpers");
|
21 |
|
22 | class TraceActivity {
|
23 | static makeCommandActivity(command) {
|
24 | return {
|
25 | type: botbuilder_core_1.ActivityTypes.Trace,
|
26 | timestamp: new Date(),
|
27 | name: 'Command',
|
28 | label: 'Command',
|
29 | value: command,
|
30 | valueType: 'https://www.botframework.com/schemas/command'
|
31 | };
|
32 | }
|
33 | static fromActivity(activity, name, label) {
|
34 | return {
|
35 | type: botbuilder_core_1.ActivityTypes.Trace,
|
36 | timestamp: new Date(),
|
37 | name: name,
|
38 | label: label,
|
39 | value: activity,
|
40 | valueType: 'https://www.botframework.com/schemas/activity'
|
41 | };
|
42 | }
|
43 | static fromState(botState) {
|
44 | return {
|
45 | type: botbuilder_core_1.ActivityTypes.Trace,
|
46 | timestamp: new Date(),
|
47 | name: 'BotState',
|
48 | label: 'Bot State',
|
49 | value: botState,
|
50 | valueType: 'https://www.botframework.com/schemas/botState'
|
51 | };
|
52 | }
|
53 | static fromConversationReference(conversationReference) {
|
54 | return {
|
55 | type: botbuilder_core_1.ActivityTypes.Trace,
|
56 | timestamp: new Date(),
|
57 | name: 'Deleted Message',
|
58 | label: 'MessageDelete',
|
59 | value: conversationReference,
|
60 | valueType: 'https://www.botframework.com/schemas/conversationReference'
|
61 | };
|
62 | }
|
63 | static fromError(errorMessage) {
|
64 | return {
|
65 | type: botbuilder_core_1.ActivityTypes.Trace,
|
66 | timestamp: new Date(),
|
67 | name: 'Turn Error',
|
68 | label: 'TurnError',
|
69 | value: errorMessage,
|
70 | valueType: 'https://www.botframework.com/schemas/error'
|
71 | };
|
72 | }
|
73 | }
|
74 |
|
75 | class InterceptionMiddleware {
|
76 | |
77 |
|
78 |
|
79 |
|
80 | onTurn(turnContext, next) {
|
81 | return __awaiter(this, void 0, void 0, function* () {
|
82 | var { shouldForwardToApplication, shouldIntercept } = yield this.invokeInbound(turnContext, TraceActivity.fromActivity(turnContext.activity, 'ReceivedActivity', 'Received Activity'));
|
83 | if (shouldIntercept) {
|
84 | turnContext.onSendActivities((ctx, activities, nextSend) => __awaiter(this, void 0, void 0, function* () {
|
85 | var traceActivities = [];
|
86 | activities.forEach(activity => {
|
87 | traceActivities.push(TraceActivity.fromActivity(activity, 'SentActivity', 'Sent Activity'));
|
88 | });
|
89 | yield this.invokeOutbound(ctx, traceActivities);
|
90 | return yield nextSend();
|
91 | }));
|
92 | turnContext.onUpdateActivity((ctx, activity, nextUpdate) => __awaiter(this, void 0, void 0, function* () {
|
93 | var traceActivity = TraceActivity.fromActivity(activity, 'MessageUpdate', 'Updated Message');
|
94 | yield this.invokeOutbound(ctx, [traceActivity]);
|
95 | return yield nextUpdate();
|
96 | }));
|
97 | turnContext.onDeleteActivity((ctx, reference, nextDelete) => __awaiter(this, void 0, void 0, function* () {
|
98 | var traceActivity = TraceActivity.fromConversationReference(reference);
|
99 | yield this.invokeOutbound(ctx, [traceActivity]);
|
100 | return yield nextDelete();
|
101 | }));
|
102 | }
|
103 | if (shouldForwardToApplication) {
|
104 | try {
|
105 | yield next();
|
106 | }
|
107 | catch (err) {
|
108 | var traceActivity = TraceActivity.fromError(err.toString());
|
109 | yield this.invokeOutbound(turnContext, [traceActivity]);
|
110 | throw err;
|
111 | }
|
112 | }
|
113 | if (shouldIntercept) {
|
114 | yield this.invokeTraceState(turnContext);
|
115 | }
|
116 | });
|
117 | }
|
118 | invokeInbound(turnContext, traceActivity) {
|
119 | return __awaiter(this, void 0, void 0, function* () {
|
120 | try {
|
121 | return yield this.inbound(turnContext, traceActivity);
|
122 | }
|
123 | catch (err) {
|
124 | console.warn(`Exception in inbound interception ${err}`);
|
125 | return { shouldForwardToApplication: true, shouldIntercept: false };
|
126 | }
|
127 | });
|
128 | }
|
129 | invokeOutbound(turnContext, traceActivities) {
|
130 | return __awaiter(this, void 0, void 0, function* () {
|
131 | try {
|
132 | yield this.outbound(turnContext, traceActivities);
|
133 | }
|
134 | catch (err) {
|
135 | console.warn(`Exception in outbound interception ${err}`);
|
136 | }
|
137 | });
|
138 | }
|
139 | invokeTraceState(turnContext) {
|
140 | return __awaiter(this, void 0, void 0, function* () {
|
141 | try {
|
142 | yield this.traceState(turnContext);
|
143 | }
|
144 | catch (err) {
|
145 | console.warn(`Exception in state interception ${err}`);
|
146 | }
|
147 | });
|
148 | }
|
149 | }
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 | class InspectionMiddleware extends InterceptionMiddleware {
|
158 | |
159 |
|
160 |
|
161 | constructor(inspectionState, userState, conversationState, credentials) {
|
162 | super();
|
163 | this.inspectionState = inspectionState;
|
164 | this.inspectionStateAccessor = inspectionState.createProperty('InspectionSessionByStatus');
|
165 | this.userState = userState;
|
166 | this.conversationState = conversationState;
|
167 | credentials = Object.assign({ appId: '', appPassword: '' }, credentials);
|
168 | this.credentials = new botframework_connector_1.MicrosoftAppCredentials(credentials.appId, credentials.appPassword);
|
169 | }
|
170 | processCommand(turnContext) {
|
171 | return __awaiter(this, void 0, void 0, function* () {
|
172 | if (turnContext.activity.type == botbuilder_core_1.ActivityTypes.Message && turnContext.activity.text !== undefined) {
|
173 | var originalText = turnContext.activity.text;
|
174 | botbuilder_core_1.TurnContext.removeRecipientMention(turnContext.activity);
|
175 | var command = turnContext.activity.text.trim().split(' ');
|
176 | if (command.length > 1 && command[0] === InspectionMiddleware.command) {
|
177 | if (command.length === 2 && command[1] === 'open') {
|
178 | yield this.processOpenCommand(turnContext);
|
179 | return true;
|
180 | }
|
181 | if (command.length === 3 && command[1] === 'attach') {
|
182 | yield this.processAttachCommand(turnContext, command[2]);
|
183 | return true;
|
184 | }
|
185 | }
|
186 | turnContext.activity.text = originalText;
|
187 | }
|
188 | return false;
|
189 | });
|
190 | }
|
191 | inbound(turnContext, traceActivity) {
|
192 | return __awaiter(this, void 0, void 0, function* () {
|
193 | if (yield this.processCommand(turnContext)) {
|
194 | return { shouldForwardToApplication: false, shouldIntercept: false };
|
195 | }
|
196 | var session = yield this.findSession(turnContext);
|
197 | if (session !== undefined) {
|
198 | if (yield this.invokeSend(turnContext, session, traceActivity)) {
|
199 | return { shouldForwardToApplication: true, shouldIntercept: true };
|
200 | }
|
201 | else {
|
202 | return { shouldForwardToApplication: true, shouldIntercept: false };
|
203 | }
|
204 | }
|
205 | else {
|
206 | return { shouldForwardToApplication: true, shouldIntercept: false };
|
207 | }
|
208 | });
|
209 | }
|
210 | outbound(turnContext, traceActivities) {
|
211 | return __awaiter(this, void 0, void 0, function* () {
|
212 | var session = yield this.findSession(turnContext);
|
213 | if (session !== undefined) {
|
214 | for (var i = 0; i < traceActivities.length; i++) {
|
215 | var traceActivity = traceActivities[i];
|
216 | if (!(yield this.invokeSend(turnContext, session, traceActivity))) {
|
217 | break;
|
218 | }
|
219 | }
|
220 | }
|
221 | });
|
222 | }
|
223 | traceState(turnContext) {
|
224 | return __awaiter(this, void 0, void 0, function* () {
|
225 | var session = yield this.findSession(turnContext);
|
226 | if (session !== undefined) {
|
227 | if (this.userState !== undefined) {
|
228 | yield this.userState.load(turnContext, false);
|
229 | }
|
230 | if (this.conversationState != undefined) {
|
231 | yield this.conversationState.load(turnContext, false);
|
232 | }
|
233 | var botState = {};
|
234 | if (this.userState !== undefined) {
|
235 | botState.userState = this.userState.get(turnContext);
|
236 | }
|
237 | if (this.conversationState !== undefined) {
|
238 | botState.conversationState = this.conversationState.get(turnContext);
|
239 | }
|
240 | yield this.invokeSend(turnContext, session, TraceActivity.fromState(botState));
|
241 | }
|
242 | });
|
243 | }
|
244 | processOpenCommand(turnContext) {
|
245 | return __awaiter(this, void 0, void 0, function* () {
|
246 | var sessions = yield this.inspectionStateAccessor.get(turnContext, InspectionSessionsByStatus.DefaultValue);
|
247 | var sessionId = this.openCommand(sessions, botbuilder_core_1.TurnContext.getConversationReference(turnContext.activity));
|
248 | yield turnContext.sendActivity(TraceActivity.makeCommandActivity(`${InspectionMiddleware.command} attach ${sessionId}`));
|
249 | yield this.inspectionState.saveChanges(turnContext, false);
|
250 | });
|
251 | }
|
252 | processAttachCommand(turnContext, sessionId) {
|
253 | return __awaiter(this, void 0, void 0, function* () {
|
254 | var sessions = yield this.inspectionStateAccessor.get(turnContext, InspectionSessionsByStatus.DefaultValue);
|
255 | if (this.attachCommand(this.getAttachId(turnContext.activity), sessions, sessionId)) {
|
256 | yield turnContext.sendActivity('Attached to session, all traffic is being replicated for inspection.');
|
257 | }
|
258 | else {
|
259 | yield turnContext.sendActivity(`Open session with id ${sessionId} does not exist.`);
|
260 | }
|
261 | yield this.inspectionState.saveChanges(turnContext, false);
|
262 | });
|
263 | }
|
264 | openCommand(sessions, conversationReference) {
|
265 | function generate_guid() {
|
266 | function s4() {
|
267 | return Math.floor((1 + Math.random()) * 0x10000)
|
268 | .toString(16)
|
269 | .substring(1);
|
270 | }
|
271 | return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
272 | s4() + '-' + s4() + s4() + s4();
|
273 | }
|
274 | var sessionId = generate_guid();
|
275 | sessions.openedSessions[sessionId] = conversationReference;
|
276 | return sessionId;
|
277 | }
|
278 | attachCommand(attachId, sessions, sessionId) {
|
279 | var inspectionSessionState = sessions.openedSessions[sessionId];
|
280 | if (inspectionSessionState !== undefined) {
|
281 | sessions.attachedSessions[attachId] = inspectionSessionState;
|
282 | delete sessions.openedSessions[sessionId];
|
283 | return true;
|
284 | }
|
285 | return false;
|
286 | }
|
287 | findSession(turnContext) {
|
288 | return __awaiter(this, void 0, void 0, function* () {
|
289 | var sessions = yield this.inspectionStateAccessor.get(turnContext, InspectionSessionsByStatus.DefaultValue);
|
290 | var conversationReference = sessions.attachedSessions[this.getAttachId(turnContext.activity)];
|
291 | if (conversationReference !== undefined) {
|
292 | return new InspectionSession(conversationReference, this.credentials);
|
293 | }
|
294 | return undefined;
|
295 | });
|
296 | }
|
297 | invokeSend(turnContext, session, activity) {
|
298 | return __awaiter(this, void 0, void 0, function* () {
|
299 | if (yield session.send(activity)) {
|
300 | return true;
|
301 | }
|
302 | else {
|
303 | yield this.cleanUpSession(turnContext);
|
304 | return false;
|
305 | }
|
306 | });
|
307 | }
|
308 | cleanUpSession(turnContext) {
|
309 | return __awaiter(this, void 0, void 0, function* () {
|
310 | var sessions = yield this.inspectionStateAccessor.get(turnContext, InspectionSessionsByStatus.DefaultValue);
|
311 | delete sessions.attachedSessions[this.getAttachId(turnContext.activity)];
|
312 | yield this.inspectionState.saveChanges(turnContext, false);
|
313 | });
|
314 | }
|
315 | getAttachId(activity) {
|
316 |
|
317 |
|
318 | const teamId = teamsActivityHelpers_1.teamsGetTeamId(activity);
|
319 | return teamId ? teamId : activity.conversation.id;
|
320 | }
|
321 | }
|
322 | InspectionMiddleware.command = "/INSPECT";
|
323 | exports.InspectionMiddleware = InspectionMiddleware;
|
324 |
|
325 | class InspectionSession {
|
326 | constructor(conversationReference, credentials) {
|
327 | this.conversationReference = conversationReference;
|
328 | this.connectorClient = new botframework_connector_1.ConnectorClient(credentials, { baseUri: conversationReference.serviceUrl });
|
329 | }
|
330 | send(activity) {
|
331 | return __awaiter(this, void 0, void 0, function* () {
|
332 | botbuilder_core_1.TurnContext.applyConversationReference(activity, this.conversationReference);
|
333 | try {
|
334 | yield this.connectorClient.conversations.sendToConversation(activity.conversation.id, activity);
|
335 | }
|
336 | catch (err) {
|
337 | return false;
|
338 | }
|
339 | return true;
|
340 | });
|
341 | }
|
342 | }
|
343 |
|
344 | class InspectionSessionsByStatus {
|
345 | constructor() {
|
346 | this.openedSessions = {};
|
347 | this.attachedSessions = {};
|
348 | }
|
349 | }
|
350 | InspectionSessionsByStatus.DefaultValue = new InspectionSessionsByStatus();
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 | class InspectionState extends botbuilder_core_1.BotState {
|
359 | constructor(storage) {
|
360 | super(storage, (context) => {
|
361 | return Promise.resolve(this.getStorageKey(context));
|
362 | });
|
363 | }
|
364 | getStorageKey(turnContext) {
|
365 | return 'InspectionState';
|
366 | }
|
367 | }
|
368 | exports.InspectionState = InspectionState;
|
369 |
|
\ | No newline at end of file |