botbuilder-teams-messagingextensions
Version:
Microsoft Bot Builder Framework v4 middleware for Microsoft Teams Messaging Extensions
330 lines • 16.6 kB
JavaScript
"use strict";
// Copyright (c) Wictor Wilén. All rights reserved.
// 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.MessagingExtensionMiddleware = void 0;
const debug_1 = require("debug");
// Initialize debug logging module
const log = (0, debug_1.debug)("msteams");
const INVOKERESPONSE = "invokeResponse";
/**
* A Messaging Extension Middleware for Microsoft Teams
*/
class MessagingExtensionMiddleware {
/**
* Default constructor
* @param commandId The commandId of the Messaging Extension to process,
* or `undefined` to process all incoming requests
* @param processor The processor
*/
// eslint-disable-next-line no-useless-constructor
constructor(commandId, processor) {
this.commandId = commandId;
this.processor = processor;
// nop
}
/**
* Bot Framework `onTurn` method
* @param context the turn context
* @param next the next function
*/
onTurn(context, next) {
return __awaiter(this, void 0, void 0, function* () {
if (context.activity !== undefined && context.activity.name !== undefined) {
log(`Activity received - activity.name: ${context.activity.name}`);
if (this.commandId !== undefined && context.activity.value !== undefined) {
log(` commandId: ${context.activity.value.commandId}`);
log(` parameters: ${JSON.stringify(context.activity.value.parameters)}`);
}
else {
log(` activity.value: ${JSON.stringify(context.activity.value)}`);
}
switch (context.activity.name) {
case "composeExtension/query":
if ((this.commandId === context.activity.value.commandId || this.commandId === undefined) &&
this.processor.onQuery) {
try {
const result = yield this.processor.onQuery(context, context.activity.value);
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: {
composeExtension: result
},
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
}
break;
case "composeExtension/querySettingUrl":
if ((this.commandId === context.activity.value.commandId || this.commandId === undefined) &&
this.processor.onQuerySettingsUrl) {
try {
const result = yield this.processor.onQuerySettingsUrl(context);
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: {
composeExtension: {
suggestedActions: {
actions: [Object.assign({ type: "openApp" }, result)]
},
type: "config"
}
},
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
}
break;
case "composeExtension/setting":
if ((this.commandId === context.activity.value.commandId || this.commandId === undefined) &&
this.processor.onSettings) {
try {
yield this.processor.onSettings(context);
context.sendActivity({
type: INVOKERESPONSE,
value: {
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
}
break;
case "composeExtension/queryLink":
if (this.processor.onQueryLink) {
try {
const result = yield this.processor.onQueryLink(context, context.activity.value);
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: {
composeExtension: result
},
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
// we're doing a return here and not next() so we're not colliding with
// any botbuilder-teams invoke things. This however will also invalidate the use
// of multiple message extensions using queryLink - only the first one will be triggered
}
break;
case "composeExtension/submitAction":
if (this.commandId === context.activity.value.commandId || this.commandId === undefined) {
try {
let result;
let body;
switch (context.activity.value.botMessagePreviewAction) {
case "send":
if (this.processor.onBotMessagePreviewSend) {
result = yield this.processor.onBotMessagePreviewSend(context, context.activity.value);
body = result;
}
break;
case "edit":
if (this.processor.onBotMessagePreviewEdit) {
result = yield this.processor.onBotMessagePreviewEdit(context, context.activity.value);
body = {
task: result
};
}
break;
default:
if (this.processor.onSubmitAction) {
result = yield this.processor.onSubmitAction(context, context.activity.value);
body = {
composeExtension: result
};
}
break;
}
if (result) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body,
status: 200
}
});
return;
}
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
return;
}
}
break;
case "composeExtension/fetchTask":
case "task/fetch": // for some reason Teams sends this instead of the composeExtension/fetchTask after a config/auth flow
if ((this.commandId === context.activity.value.commandId || this.commandId === undefined) &&
this.processor.onFetchTask) {
try {
const result = yield this.processor.onFetchTask(context, context.activity.value);
const body = result.type === "continue" || result.type === "message"
? { task: result }
: { composeExtension: result };
context.sendActivity({
type: INVOKERESPONSE,
value: {
body,
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
}
break;
case "composeExtension/onCardButtonClicked":
if (this.processor.onCardButtonClicked) {
try {
yield this.processor.onCardButtonClicked(context, context.activity.value);
context.sendActivity({
type: INVOKERESPONSE,
value: {
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
}
break;
case "composeExtension/selectItem":
if (this.processor.onSelectItem) {
try {
const result = yield this.processor.onSelectItem(context, context.activity.value);
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: {
composeExtension: result
},
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
// we're doing a return here and not next() so we're not colliding with
// any botbuilder-teams invoke things. This however will also invalidate the use
// of multiple message extensions using selectItem - only the first one will be triggered
}
break;
case "adaptiveCard/action":
if (this.processor.onActionExecute) {
try {
const result = yield this.processor.onActionExecute(context, context.activity.value);
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: result,
status: 200
}
});
}
catch (err) {
context.sendActivity({
type: INVOKERESPONSE,
value: {
body: err,
status: 500
}
});
}
return;
}
break;
default:
// nop
break;
}
}
return next();
});
}
}
exports.MessagingExtensionMiddleware = MessagingExtensionMiddleware;
//# sourceMappingURL=index.js.map