From 42a2614a382258c8692840c036a317cf160f4d4e Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Mon, 7 Oct 2019 14:34:55 -0700 Subject: [PATCH] add search based messaging extension from samples (thanks Steven) (#1267) --- .../teams/searchBasedMessagingExtension/.env | 3 + .../searchBasedMessagingExtension/README.md | 84 +++++++++ .../package.json | 30 +++ .../src/index.ts | 65 +++++++ .../src/teamsSearchExtensionBot.ts | 175 ++++++++++++++++++ .../static/composeExtensionSettings.html | 31 ++++ .../teams-app-manifest/icon-color.png | Bin 0 -> 3196 bytes .../teams-app-manifest/icon-outline.png | Bin 0 -> 526 bytes .../teams-app-manifest/manifest.json | 68 +++++++ .../tsconfig.json | 11 ++ 10 files changed, 467 insertions(+) create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/.env create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/README.md create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/package.json create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/index.ts create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/teamsSearchExtensionBot.ts create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/static/composeExtensionSettings.html create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-color.png create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-outline.png create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/manifest.json create mode 100644 libraries/botbuilder/tests/teams/searchBasedMessagingExtension/tsconfig.json diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/.env b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/.env new file mode 100644 index 0000000000..edaf1908bc --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/.env @@ -0,0 +1,3 @@ +MicrosoftAppId= +MicrosoftAppPassword= +host= \ No newline at end of file diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/README.md b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/README.md new file mode 100644 index 0000000000..450a22c0f6 --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/README.md @@ -0,0 +1,84 @@ +# Teams Search-based Messaging Extensions Bot + +Search-based Messaging Extensions allow users to have bots search for information on the user's behalf in Teams. + +___ + +To create a Teams Bot that contains Search-based Messaging Extensions, users must first create a [Teams Manifest](https://docs.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) which will outline where the extension is available. + +> _Note_ +> +> _The name of the feature was changed from "compose extension" to "messaging extension" in November, 2017, but the manifest name remains the same so that existing extensions continue to function._ + +### Example Teams Manifest for Search-based Messaging Extensions bot + +```json +{ + "$schema": "https://github.com/OfficeDev/microsoft-teams-app-schema/blob/preview/DevPreview/MicrosoftTeams.schema.json", + "manifestVersion": "devPreview", + "version": "1.0", + "id": "<>", + "packageName": "com.microsoft.teams.samples.v4bot", + "developer": { + "name": "Microsoft Corp", + "websiteUrl": "https://example.azurewebsites.net", + "privacyUrl": "https://example.azurewebsites.net/privacy", + "termsOfUseUrl": "https://example.azurewebsites.net/termsofuse" + }, + "name": { + "short": "search-extension-settings", + "full": "Microsoft Teams V4 Search Messaging Extension Bot and settings" + }, + "description": { + "short": "Microsoft Teams V4 Search Messaging Extension Bot and settings", + "full": "Sample Search Messaging Extension Bot using V4 Bot Builder SDK and V4 Microsoft Teams Extension SDK" + }, + "icons": { + "outline": "icon-outline.png", + "color": "icon-color.png" + }, + "accentColor": "#abcdef", + "bots": [ + { + "botId": "<>", + "scopes": ["personal", "team"] + } + ], + "composeExtensions": [ + { + "botId": "<>", + "canUpdateConfiguration": true, + "commands": [ + { + "id": "searchQuery", + "context": ["compose", "commandBox"], + "description": "Test command to run query", + "title": "Search", + "type": "query", + "parameters": [ + { + "name": "searchQuery", + "title": "Search Query", + "description": "Your search query", + "inputType": "text" + } + ] + } + ], + "messageHandlers": [ + { + "type": "link", + "value": { + "domains": [ + "*.ngrok.io" + ] + } + } + ] + } + ], + "validDomains": [ + "*.ngrok.io" + ] +} +``` \ No newline at end of file diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/package.json b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/package.json new file mode 100644 index 0000000000..e2e018620c --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/package.json @@ -0,0 +1,30 @@ +{ + "name": "search-extension-bot", + "version": "1.0.0", + "description": "", + "main": "./lib/index.js", + "scripts": { + "start": "tsc --build && node ./lib/index.js", + "build": "tsc --build", + "watch": "nodemon --watch ./src -e ts --exec \"npm run start\"" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "botbuilder": "file:../../../", + "dotenv": "^8.1.0", + "node-fetch": "^2.6.0", + "restify": "^8.4.0", + "uuid": "^3.3.3" + }, + "devDependencies": { + "@types/node": "^12.7.1", + "@types/node-fetch": "^2.5.0", + "@types/request": "^2.48.1", + "@types/restify": "^7.2.7", + "nodemon": "^1.19.1", + "ts-node": "^7.0.1", + "typescript": "^3.2.4" + } +} diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/index.ts b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/index.ts new file mode 100644 index 0000000000..bae0bcf49a --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/index.ts @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { config } from 'dotenv'; +import * as path from 'path'; +import * as restify from 'restify'; + +// Import required bot services. +// See https://aka.ms/bot-services to learn more about the different parts of a bot. +import { BotFrameworkAdapter, MemoryStorage, UserState } from 'botbuilder'; + +// This bot's main dialog. +import { TeamsSearchExtensionBot } from './teamsSearchExtensionBot'; + +const ENV_FILE = path.join(__dirname, '..', '.env'); +config({ path: ENV_FILE }); + +// Create HTTP server. +const server = restify.createServer(); +server.listen(process.env.port || process.env.PORT || 3978, () => { + console.log(`\n${server.name} listening to ${server.url}`); + console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`); + console.log(`\nTo test your bot, see: https://aka.ms/debug-with-emulator`); +}); + +// Create adapter. +// See https://aka.ms/about-bot-adapter to learn more about adapters. +const adapter = new BotFrameworkAdapter({ + appId: process.env.MicrosoftAppId, + appPassword: process.env.MicrosoftAppPassword +}); + +// Catch-all for errors. +adapter.onTurnError = async (context, error) => { + // This check writes out errors to console log .vs. app insights. + console.error('[onTurnError]:'); + console.error(error); + // Send a message to the user + await context.sendActivity(`Oops. Something went wrong in the bot!\n ${error.message}`); +}; + +// Define a state store for your bot. See https://aka.ms/about-bot-state to learn more about using MemoryStorage. +// A bot requires a state store to persist the dialog and user state between messages. + +// For local development, in-memory storage is used. +// CAUTION: The Memory Storage used here is for local bot debugging only. When the bot +// is restarted, anything stored in memory will be gone. +const memoryStorage = new MemoryStorage(); +const userState = new UserState(memoryStorage); + +// Create the main dialog. +const myBot = new TeamsSearchExtensionBot(userState); + +server.get('/*', restify.plugins.serveStatic({ + directory: path.join(__dirname, '../static'), + appendRequestPath: false +})); + +// Listen for incoming requests. +server.post('/api/messages', (req, res) => { + adapter.processActivity(req, res, async (context) => { + // Route to main dialog. + await myBot.run(context); + }); +}); diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/teamsSearchExtensionBot.ts b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/teamsSearchExtensionBot.ts new file mode 100644 index 0000000000..4796666fd8 --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/src/teamsSearchExtensionBot.ts @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { + ActionTypes, + CardFactory, + BotState, + MessagingExtensionResponse, + MessagingExtensionResult, + MessagingExtensionQuery, + TeamsActivityHandler, + TurnContext, + MessagingExtensionSuggestedAction, + MessagingExtensionActionResponse, + AppBasedLinkQuery +} from 'botbuilder'; + +const RICH_CARD_PROPERTY = 'richCardConfig'; + +export class TeamsSearchExtensionBot extends TeamsActivityHandler { + + // For this example, we're using UserState to store the user's preferences for the type of Rich Card they receive. + // Users can specify the type of card they receive by configuring the Messaging Extension. + // To store their configuration, we will use the userState passed in via the constructor. + + /** + * We need to change the key for the user state because the bot might not be in the conversation, which means they get a 403 error. + * @param userState + */ + constructor(public userState: BotState) { + super(); + + // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. + this.onMessage(async (context, next) => { + await context.sendActivity(`You said '${context.activity.text}'`); + // By calling next() you ensure that the next BotHandler is run. + await next(); + }); + + this.onMembersAdded(async (context, next) => { + const membersAdded = context.activity.membersAdded; + for (const member of membersAdded) { + if (member.id !== context.activity.recipient.id) { + await context.sendActivity('Hello and welcome!'); + } + } + + // By calling next() you ensure that the next BotHandler is run. + await next(); + }); + } + + protected async onTeamsMessagingExtensionQuery(context: TurnContext, query: MessagingExtensionQuery): Promise{ + const accessor = this.userState.createProperty<{ useHeroCard: boolean }>(RICH_CARD_PROPERTY); + const config = await accessor.get(context, { useHeroCard: true }); + + const searchQuery = query.parameters[0].value; + const cardText = `You said "${searchQuery}"`; + let composeExtensionResponse: MessagingExtensionResponse; + + const bfLogo = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU'; + const button = { type: 'openUrl', title: 'Click for more Information', value: "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview" }; + + if (config.useHeroCard) { + const heroCard = CardFactory.heroCard('You searched for:', cardText, [bfLogo], [button]); + const preview = CardFactory.heroCard('You searched for:', cardText, [bfLogo]); + + const secondPreview = CardFactory.heroCard('Learn more about Teams:', "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview", [bfLogo]); + const secondHeroCard = CardFactory.heroCard('Learn more about Teams:', "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview", [bfLogo], [button]); + composeExtensionResponse = { + composeExtension: { + type: 'result', + attachmentLayout: 'list', + attachments: [ + { ...heroCard, preview }, + { ...secondHeroCard, preview: secondPreview } + ] + } + } + } else { + const thumbnailCard = CardFactory.thumbnailCard('You searched for:', cardText, [bfLogo], [button]); + const preview = CardFactory.thumbnailCard('You searched for:', cardText, [bfLogo]); + + const secondPreview = CardFactory.thumbnailCard('Learn more about Teams:', "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview", [bfLogo]); + const secondThumbnailCard = CardFactory.thumbnailCard('Learn more about Teams:', "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview", [bfLogo], [button]); + composeExtensionResponse = { + composeExtension: { + type: 'result', + attachmentLayout: 'list', + attachments: [ + { ...thumbnailCard, preview }, + { ...secondThumbnailCard, preview: secondPreview } + ] + } + } + } + + return composeExtensionResponse; + } + + protected async onTeamsAppBasedLinkQuery(context: TurnContext, query: AppBasedLinkQuery): Promise{ + const accessor = this.userState.createProperty<{ useHeroCard: boolean }>(RICH_CARD_PROPERTY); + const config = await accessor.get(context, { useHeroCard: true }); + + const url = query.url; + const cardText = `You entered "${url}"`; + let composeExtensionResponse: MessagingExtensionResponse; + + const bfLogo = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU'; + const button = { type: 'openUrl', title: 'Click for more Information', value: "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-overview" }; + + if (config.useHeroCard) { + const heroCard = CardFactory.heroCard('HeroCard for Link Unfurling:', cardText, [bfLogo], [button]); + const preview = CardFactory.heroCard('HeroCard for Link Unfurling:', cardText, [bfLogo]); + + composeExtensionResponse = { + composeExtension: { + type: 'result', + attachmentLayout: 'list', + attachments: [ + { ...heroCard, preview } + ] + } + } + } else { + const thumbnailCard = CardFactory.thumbnailCard('ThumbnailCard for Link Unfurling:', cardText, [bfLogo], [button]); + const preview = CardFactory.thumbnailCard('ThumbnailCard for Link Unfurling:', cardText, [bfLogo]); + + composeExtensionResponse = { + composeExtension: { + type: 'result', + attachmentLayout: 'list', + attachments: [ + { ...thumbnailCard, preview } + ] + } + } + } + + return composeExtensionResponse; + } + + protected async onTeamsMessagingExtensionConfigurationQuerySettingUrl(context: TurnContext, query: MessagingExtensionQuery){ + return + { + composeExtension: { + type: 'config', + suggestedActions: { + actions: [ + { + type: ActionTypes.OpenUrl, + title: 'Config', + value: process.env.host + '/composeExtensionSettings.html', + }, + ] + } + } + } + } + + protected async onTeamsMessagingExtensionConfigurationSetting(context: TurnContext, settings: MessagingExtensionQuery){ + // This event is fired when the settings page is submitted + const accessor = this.userState.createProperty<{ useHeroCard: boolean }>(RICH_CARD_PROPERTY); + const config = await accessor.get(context, { useHeroCard: true }); + + if (settings.state === 'hero') { + config.useHeroCard = true; + } else if (settings.state === 'thumbnail') { + config.useHeroCard = false; + } + + // We should save it after we send the message back to Teams. + await this.userState.saveChanges(context); + } +} diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/static/composeExtensionSettings.html b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/static/composeExtensionSettings.html new file mode 100644 index 0000000000..2efc693b98 --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/static/composeExtensionSettings.html @@ -0,0 +1,31 @@ + + + + Bot Info + + + + + + + +

I prefer:

+ + + + + \ No newline at end of file diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-color.png b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-color.png new file mode 100644 index 0000000000000000000000000000000000000000..bd9928dfc81f89346424786cac141e2883e55a9c GIT binary patch literal 3196 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 literal 0 HcmV?d00001 diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-outline.png b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/icon-outline.png new file mode 100644 index 0000000000000000000000000000000000000000..45e7a7c56ee72c8119a855cedc06f94f9c7ec8f9 GIT binary patch literal 526 zcmV+p0`dKcP)Px$$Vo&&R9Fe^SG{h7KnylfC&a+orOjHl&KbH^>c}hb7~MMd5qN|?K=%%b6r^;B z#6YD;EL|djlnjaZOKl?an@gZc%Yr5N&S&Gl^W6yvkakFfM3QNm88aLXVX&Xi-?a&e zWI`L7rv1i7?hjx*9+%@P3Mocemg_!>N;Iy;%?hsTK8!{qiStlV;IojCN;JTiaY(pc zuVFHoh=Zge5D8;QrT?RF#lEUYHK4ilMFULt9$`k~CKQGtSe6CSa=Cm}RrQHK+H5v= zJU)c0)e3MGGEu1sv)Lm9ZUR<0S!Y%hVfO}v%Onb!+So9R50;;u0vk#Z*LFsGyeTaf zi(RpizR}8c$>I@aKA!{asnh^^3{kgnJ*LwsL{XHQmoRLb9mR1h2SISl{2?UIMQYuN zywlmp*{jeSXmD(DwME!{5gWHJr@*H%^WCSAZD$UN5O?Pd!aF|uD~={FNJ)}_<2c}X zUVbr=eRTYY@P>~<{H1BT-GXh~K*+@B(F;yI^W>$GGNp_u^D4DIj;aPu@zsm8s(*GD zRt>i0`vCe1^cCp50uoef9bj|{Q2p82|5qp2g)1PFZU@_ Q3jhEB07*qoM6N<$f`Z=ZMF0Q* literal 0 HcmV?d00001 diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/manifest.json b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/manifest.json new file mode 100644 index 0000000000..5183fd4240 --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/teams-app-manifest/manifest.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://github.com/OfficeDev/microsoft-teams-app-schema/blob/preview/DevPreview/MicrosoftTeams.schema.json", + "manifestVersion": "1.5", + "version": "1.0", + "id": "<>", + "packageName": "com.microsoft.teams.samples.searchExtension", + "developer": { + "name": "Microsoft Corp", + "websiteUrl": "https://example.azurewebsites.net", + "privacyUrl": "https://example.azurewebsites.net/privacy", + "termsOfUseUrl": "https://example.azurewebsites.net/termsofuse" + }, + "name": { + "short": "search-extension-settings", + "full": "Microsoft Teams V4 Search Messaging Extension Bot and settings" + }, + "description": { + "short": "Microsoft Teams V4 Search Messaging Extension Bot and settings", + "full": "Sample Search Messaging Extension Bot using V4 Bot Builder SDK and V4 Microsoft Teams Extension SDK" + }, + "icons": { + "outline": "icon-outline.png", + "color": "icon-color.png" + }, + "accentColor": "#abcdef", + "bots": [ + { + "botId": "<>", + "scopes": ["personal", "team"] + } + ], + "composeExtensions": [ + { + "botId": "<>", + "canUpdateConfiguration": true, + "commands": [ + { + "id": "searchQuery", + "context": ["compose", "commandBox"], + "description": "Test command to run query", + "title": "Search", + "type": "query", + "parameters": [ + { + "name": "searchQuery", + "title": "Search Query", + "description": "Your search query", + "inputType": "text" + } + ] + } + ], + "messageHandlers": [ + { + "type": "link", + "value": { + "domains": [ + "*.ngrok.io" + ] + } + } + ] + } + ], + "validDomains": [ + "*.ngrok.io" + ] +} \ No newline at end of file diff --git a/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/tsconfig.json b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/tsconfig.json new file mode 100644 index 0000000000..a168d60662 --- /dev/null +++ b/libraries/botbuilder/tests/teams/searchBasedMessagingExtension/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "composite": true, + "declaration": true, + "sourceMap": true, + "outDir": "./lib", + "rootDir": "./src", + } +} \ No newline at end of file