botbuilder
Version:
Bot Builder is a framework for building rich bots on virtually any platform.
174 lines • 8.96 kB
JavaScript
;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SkillHandlerImpl = void 0;
const botframework_connector_1 = require("botframework-connector");
const uuid_1 = require("uuid");
const botbuilder_core_1 = require("botbuilder-core");
/**
* @internal
*/
class SkillHandlerImpl {
/**
* @internal
*/
constructor(skillConversationReferenceKey, adapter, logic, conversationIdFactory, getOauthScope = () => undefined) {
this.skillConversationReferenceKey = skillConversationReferenceKey;
this.adapter = adapter;
this.logic = logic;
this.conversationIdFactory = conversationIdFactory;
this.getOauthScope = getOauthScope;
}
/**
* @internal
*/
onSendToConversation(claimsIdentity, conversationId, activity) {
return this.processActivity(claimsIdentity, conversationId, null, activity);
}
/**
* @internal
*/
onReplyToActivity(claimsIdentity, conversationId, activityId, activity) {
return this.processActivity(claimsIdentity, conversationId, activityId, activity);
}
/**
* @internal
*/
onUpdateActivity(claimsIdentity, conversationId, activityId, activity) {
return __awaiter(this, void 0, void 0, function* () {
let resourceResponse;
yield this.continueConversation(claimsIdentity, conversationId, (context, ref) => __awaiter(this, void 0, void 0, function* () {
const newActivity = botbuilder_core_1.TurnContext.applyConversationReference(activity, ref.conversationReference);
context.activity.id = activityId;
context.activity.callerId = `${botbuilder_core_1.CallerIdConstants.BotToBotPrefix}${botframework_connector_1.JwtTokenValidation.getAppIdFromClaims(claimsIdentity.claims)}`;
resourceResponse = yield context.updateActivity(newActivity);
}));
return resourceResponse ? resourceResponse : { id: activityId };
});
}
/**
* @internal
*/
onDeleteActivity(claimsIdentity, conversationId, activityId) {
return __awaiter(this, void 0, void 0, function* () {
return this.continueConversation(claimsIdentity, conversationId, (context) => context.deleteActivity(activityId));
});
}
getSkillConversationReference(conversationId) {
return __awaiter(this, void 0, void 0, function* () {
let skillConversationReference;
try {
skillConversationReference = yield this.conversationIdFactory.getSkillConversationReference(conversationId);
}
catch (err) {
// If the factory has overridden getSkillConversationReference, call the deprecated getConversationReference().
// In this scenario, the oAuthScope paired with the ConversationReference can only be used for talking with
// an official channel, not another bot.
if (err.message === 'NotImplemented') {
skillConversationReference = {
conversationReference: yield this.conversationIdFactory.getConversationReference(conversationId),
oAuthScope: this.getOauthScope(),
};
}
else {
throw err;
}
}
if (!skillConversationReference) {
throw new Error('skillConversationReference not found');
}
else if (!skillConversationReference.conversationReference) {
throw new Error('conversationReference not found.');
}
return skillConversationReference;
});
}
processActivity(claimsIdentity, conversationId, replyToActivityId, activity) {
return __awaiter(this, void 0, void 0, function* () {
let resourceResponse;
yield this.continueConversation(claimsIdentity, conversationId, (context, ref) => __awaiter(this, void 0, void 0, function* () {
/**
* This callback does the following:
* - Applies the correct ConversationReference to the Activity for sending to the user-router conversation.
* - For EndOfConversation Activities received from the Skill, removes the ConversationReference from the
* ConversationIdFactory
*/
const newActivity = botbuilder_core_1.TurnContext.applyConversationReference(activity, ref.conversationReference);
context.activity.id = replyToActivityId;
context.activity.callerId = `${botbuilder_core_1.CallerIdConstants.BotToBotPrefix}${botframework_connector_1.JwtTokenValidation.getAppIdFromClaims(claimsIdentity.claims)}`;
switch (newActivity.type) {
case botbuilder_core_1.ActivityTypes.EndOfConversation:
yield this.conversationIdFactory.deleteConversationReference(conversationId);
this.applySkillActivityToTurnContext(context, newActivity);
yield this.logic(context);
break;
case botbuilder_core_1.ActivityTypes.Event:
this.applySkillActivityToTurnContext(context, newActivity);
yield this.logic(context);
break;
default:
resourceResponse = yield context.sendActivity(newActivity);
break;
}
}));
if (!resourceResponse) {
resourceResponse = { id: uuid_1.v4() };
}
return resourceResponse;
});
}
continueConversation(claimsIdentity, conversationId, callback) {
return __awaiter(this, void 0, void 0, function* () {
const ref = yield this.getSkillConversationReference(conversationId);
const continueCallback = (context) => {
context.turnState.set(this.skillConversationReferenceKey, ref);
return callback(context, ref);
};
try {
yield this.adapter.continueConversationAsync(claimsIdentity, ref.conversationReference, ref.oAuthScope, continueCallback);
}
catch (err) {
if (err.message === 'NotImplemented') {
// We're in the legacy scenario where our adapter does not support passing through claims/audience
// explicitly. Stash it in turn context and hope for the best!
yield this.adapter.continueConversation(ref.conversationReference, (context) => __awaiter(this, void 0, void 0, function* () {
context.turnState.set(context.adapter.BotIdentityKey, claimsIdentity);
return continueCallback(context);
}));
}
else {
throw err;
}
}
});
}
// adapter.continueConversation() sends an event activity with continueConversation in the name.
// this warms up the incoming middlewares but once that's done and we hit the custom callback,
// we need to swap the values back to the ones received from the skill so the bot gets the actual activity.
applySkillActivityToTurnContext(context, activity) {
context.activity.channelData = activity.channelData;
context.activity.code = activity.code;
context.activity.entities = activity.entities;
context.activity.locale = activity.locale;
context.activity.localTimestamp = activity.localTimestamp;
context.activity.name = activity.name;
context.activity.relatesTo = activity.relatesTo;
context.activity.replyToId = activity.replyToId;
context.activity.timestamp = activity.timestamp;
context.activity.text = activity.text;
context.activity.type = activity.type;
context.activity.value = activity.value;
}
}
exports.SkillHandlerImpl = SkillHandlerImpl;
//# sourceMappingURL=skillHandlerImpl.js.map