├── bot
├── run.cjs
├── images
│ ├── chatgpt-chat.png
│ └── chatgpt-chat-with-context.png
├── .gitignore
├── config.ts
├── .webappignore
├── tsconfig.json
├── adaptiveCards
│ └── welcome.json
├── package.json
├── teamsBot.ts
├── index.ts
├── web.config
└── README.md
├── .gitattributes
├── templates
├── appPackage
│ ├── resources
│ │ ├── color.png
│ │ └── outline.png
│ └── manifest.template.json
└── azure
│ ├── main.bicep
│ ├── config.bicep
│ ├── provision
│ ├── identity.bicep
│ ├── botService.bicep
│ └── azureWebAppBot.bicep
│ ├── teamsFx
│ └── azureWebAppBotConfig.bicep
│ └── provision.bicep
├── .gitignore
├── .vscode
├── settings.json
├── launch.json
└── tasks.json
├── package.json
├── README.md
└── .fx
└── configs
├── azure.parameters.dev.json
├── config.dev.json
└── projectSettings.json
/bot/run.cjs:
--------------------------------------------------------------------------------
1 | import("./index.js");
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.bicep linguist-vendored
--------------------------------------------------------------------------------
/bot/images/chatgpt-chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/formulahendry/chatgpt-teams-bot/HEAD/bot/images/chatgpt-chat.png
--------------------------------------------------------------------------------
/bot/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | node_modules/
3 |
4 | # misc
5 | .env
6 | .deployment
7 | .DS_Store
8 |
9 | # build
10 | lib/
11 |
--------------------------------------------------------------------------------
/bot/images/chatgpt-chat-with-context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/formulahendry/chatgpt-teams-bot/HEAD/bot/images/chatgpt-chat-with-context.png
--------------------------------------------------------------------------------
/templates/appPackage/resources/color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/formulahendry/chatgpt-teams-bot/HEAD/templates/appPackage/resources/color.png
--------------------------------------------------------------------------------
/templates/appPackage/resources/outline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/formulahendry/chatgpt-teams-bot/HEAD/templates/appPackage/resources/outline.png
--------------------------------------------------------------------------------
/bot/config.ts:
--------------------------------------------------------------------------------
1 | const config = {
2 | botId: process.env.BOT_ID,
3 | botPassword: process.env.BOT_PASSWORD,
4 | openaiApiKey: process.env.OPENAI_API_KEY,
5 | };
6 |
7 | export default config;
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # TeamsFx files
2 | node_modules
3 | .fx/configs/localSettings.json
4 | .fx/states/*.userdata
5 | .DS_Store
6 | .env.teamsfx.local
7 | subscriptionInfo.json
8 | build
9 | .fx/configs/config.local.json
10 | .fx/states/state.local.json
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.onTaskErrors": "abort",
3 | "json.schemas": [
4 | {
5 | "fileMatch": [
6 | "/aad.*.json"
7 | ],
8 | "schema": {}
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/bot/.webappignore:
--------------------------------------------------------------------------------
1 | .fx
2 | .deployment
3 | .vscode
4 | *.js.map
5 | *.ts.map
6 | *.ts
7 | .git*
8 | .tsbuildinfo
9 | CHANGELOG.md
10 | readme.md
11 | local.settings.json
12 | test
13 | tsconfig.json
14 | .DS_Store
15 | node_modules/.bin
16 | node_modules/ts-node
17 | node_modules/typescript
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chatgpt-teams-bot",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "devDependencies": {
10 | "@microsoft/teamsfx-cli": "1.*"
11 | },
12 | "license": "MIT"
13 | }
--------------------------------------------------------------------------------
/bot/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "target": "ES2017",
5 | "module": "NodeNext",
6 | "outDir": "./lib",
7 | "rootDir": "./",
8 | "sourceMap": true,
9 | "incremental": true,
10 | "tsBuildInfoFile": "./lib/.tsbuildinfo",
11 | "resolveJsonModule": true,
12 | "esModuleInterop": true,
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChatGPT Teams Bot app
2 |
3 | This is a ChatGPT Teams Bot app which uses latest `gpt-3.5-turbo` model optimized for chat. `Turbo` is the same model family that powers ChatGPT.
4 |
5 | Follow [this guide](./bot/README.md) to get started.
6 |
7 | You could also try the [ChatGPT WeChat Bot](https://github.com/formulahendry/chatgpt-wechat-bot).
8 |
9 | 
--------------------------------------------------------------------------------
/.fx/configs/azure.parameters.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "provisionParameters": {
6 | "value": {
7 | "botAadAppClientId": "{{state.teams-bot.botId}}",
8 | "botAadAppClientSecret": "{{state.teams-bot.botPassword}}",
9 | "openaiApiKey": "{{$env.OPENAI_API_KEY}}",
10 | "resourceBaseName": "chatgptbot{{state.solution.resourceNameSuffix}}",
11 | "botDisplayName": "chatgpt-bot"
12 | }
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/templates/azure/main.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 |
4 | module provision './provision.bicep' = {
5 | name: 'provisionResources'
6 | params: {
7 | provisionParameters: provisionParameters
8 | }
9 | }
10 | output provisionOutput object = provision
11 | module config './config.bicep' = {
12 | name: 'configureResources'
13 | params: {
14 | provisionParameters: provisionParameters
15 | provisionOutputs: provision
16 | }
17 | }
18 | output configOutput object = contains(reference(resourceId('Microsoft.Resources/deployments', config.name), '2020-06-01'), 'outputs') ? config : {}
19 |
--------------------------------------------------------------------------------
/templates/azure/config.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 | param provisionOutputs object
4 |
5 | // Get existing app settings for merge
6 | var currentAppSettings = list('${ provisionOutputs.azureWebAppBotOutput.value.resourceId }/config/appsettings', '2021-02-01').properties
7 |
8 | // Merge TeamsFx configurations to Bot resources
9 | module teamsFxAzureWebAppBotConfig './teamsFx/azureWebAppBotConfig.bicep' = {
10 | name: 'teamsFxAzureWebAppBotConfig'
11 | params: {
12 | provisionParameters: provisionParameters
13 | provisionOutputs: provisionOutputs
14 | currentAppSettings: currentAppSettings
15 | }
16 | }
--------------------------------------------------------------------------------
/.fx/configs/config.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://aka.ms/teamsfx-env-config-schema",
3 | "description": "You can customize the TeamsFx config for different environments. Visit https://aka.ms/teamsfx-env-config to learn more about this.",
4 | "manifest": {
5 | "appName": {
6 | "short": "chatgpt-teams-bot",
7 | "full": "Full name for chatgpt-teams-bot"
8 | },
9 | "description": {
10 | "short": "Short description of chatgpt-teams-bot",
11 | "full": "Full description of chatgpt-teams-bot"
12 | },
13 | "icons": {
14 | "color": "resources/color.png",
15 | "outline": "resources/outline.png"
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/templates/azure/provision/identity.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 | var resourceBaseName = provisionParameters.resourceBaseName
4 | var identityName = contains(provisionParameters, 'userAssignedIdentityName') ? provisionParameters['userAssignedIdentityName'] : '${resourceBaseName}' // Try to read name for user assigned identity from parameters
5 |
6 | // user assigned identity will be used to access other Azure resources
7 | resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
8 | name: identityName
9 | location: resourceGroup().location
10 | }
11 |
12 | output identityName string = identityName
13 | output identityClientId string = managedIdentity.properties.clientId
14 | output identityResourceId string = managedIdentity.id
15 | output identityPrincipalId string = managedIdentity.properties.principalId
--------------------------------------------------------------------------------
/bot/adaptiveCards/welcome.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "AdaptiveCard",
3 | "body": [
4 | {
5 | "type": "TextBlock",
6 | "size": "Medium",
7 | "weight": "Bolder",
8 | "text": "Your Hello World Bot is Running"
9 | },
10 | {
11 | "type": "TextBlock",
12 | "text": "Congratulations! Your hello world bot is running. Click the documentation below to learn more about Bots and the Teams Toolkit.",
13 | "wrap": true
14 | }
15 | ],
16 | "actions": [
17 | {
18 | "type": "Action.OpenUrl",
19 | "title": "Bot Framework Docs",
20 | "url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
21 | },
22 | {
23 | "type": "Action.OpenUrl",
24 | "title": "Teams Toolkit Docs",
25 | "url": "https://aka.ms/teamsfx-docs"
26 | }
27 | ],
28 | "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
29 | "version": "1.4"
30 | }
31 |
--------------------------------------------------------------------------------
/templates/azure/teamsFx/azureWebAppBotConfig.bicep:
--------------------------------------------------------------------------------
1 | // Auto generated content, please customize files under provision folder
2 |
3 | @secure()
4 | param provisionParameters object
5 | param provisionOutputs object
6 | @secure()
7 | param currentAppSettings object
8 |
9 | var webAppName = split(provisionOutputs.azureWebAppBotOutput.value.resourceId, '/')[8]
10 | var botAadAppClientId = provisionParameters['botAadAppClientId']
11 | var botAadAppClientSecret = provisionParameters['botAadAppClientSecret']
12 |
13 | resource webAppSettings 'Microsoft.Web/sites/config@2021-02-01' = {
14 | name: '${webAppName}/appsettings'
15 | properties: union({
16 | BOT_ID: botAadAppClientId // ID of your bot
17 | BOT_PASSWORD: botAadAppClientSecret // Secret of your bot
18 | IDENTITY_ID: provisionOutputs.identityOutput.value.identityClientId // User assigned identity id, the identity is used to access other Azure resources
19 | }, currentAppSettings)
20 | }
--------------------------------------------------------------------------------
/bot/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "echobot",
3 | "type": "module",
4 | "version": "1.0.0",
5 | "description": "Microsoft Teams Toolkit hello world Bot sample",
6 | "author": "Microsoft",
7 | "license": "MIT",
8 | "main": "./lib/index.js",
9 | "scripts": {
10 | "dev:teamsfx": "env-cmd --silent -f .env.teamsfx.local npm run dev",
11 | "dev": "nodemon --exec node --inspect=9239 --signal SIGINT -r ts-node/register --loader ts-node/esm ./index.ts",
12 | "build": "tsc --build && shx cp -r ./adaptiveCards ./lib/ && shx cp run.cjs ./lib/",
13 | "start": "node ./lib/index.js",
14 | "watch": "nodemon --exec \"npm run start\"",
15 | "test": "echo \"Error: no test specified\" && exit 1"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com"
20 | },
21 | "dependencies": {
22 | "@microsoft/adaptivecards-tools": "^1.0.0",
23 | "botbuilder": "^4.18.0",
24 | "chatgpt": "^5.0.4",
25 | "express": "^4.18.2",
26 | "restify": "^8.5.1"
27 | },
28 | "devDependencies": {
29 | "@types/express": "^4.17.14",
30 | "@types/restify": "8.4.2",
31 | "env-cmd": "^10.1.0",
32 | "nodemon": "^2.0.7",
33 | "shx": "^0.3.3",
34 | "ts-node": "^10.4.0",
35 | "typescript": "^4.4.4"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/templates/azure/provision/botService.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 | param botEndpoint string
4 | var resourceBaseName = provisionParameters.resourceBaseName
5 | var botAadAppClientId = provisionParameters['botAadAppClientId'] // Read AAD app client id for Azure Bot Service from parameters
6 | var botServiceName = contains(provisionParameters, 'botServiceName') ? provisionParameters['botServiceName'] : '${resourceBaseName}' // Try to read name for Azure Bot Service from parameters
7 | var botServiceSku = contains(provisionParameters, 'botServiceSku') ? provisionParameters['botServiceSku'] : 'F0' // Try to read SKU for Azure Bot Service from parameters
8 | var botDisplayName = contains(provisionParameters, 'botDisplayName') ? provisionParameters['botDisplayName'] : '${resourceBaseName}' // Try to read display name for Azure Bot Service from parameters
9 |
10 | // Register your web service as a bot with the Bot Framework
11 | resource azureBot 'Microsoft.BotService/botServices@2021-03-01' = {
12 | kind: 'azurebot'
13 | location: 'global'
14 | name: botServiceName
15 | properties: {
16 | displayName: botDisplayName
17 | endpoint: uri(botEndpoint, '/api/messages')
18 | msaAppId: botAadAppClientId
19 | }
20 | sku: {
21 | name: botServiceSku // You can follow https://aka.ms/teamsfx-bicep-add-param-tutorial to add botServiceSku property to provisionParameters to override the default value "F0".
22 | }
23 | }
24 |
25 | // Connect the bot service to Microsoft Teams
26 | resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
27 | parent: azureBot
28 | location: 'global'
29 | name: 'MsTeamsChannel'
30 | properties: {
31 | channelName: 'MsTeamsChannel'
32 | }
33 | }
--------------------------------------------------------------------------------
/.fx/configs/projectSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "appName": "chatgpt-teams-bot",
3 | "projectId": "5758b4c5-1d35-482a-af71-5a4546396689",
4 | "version": "2.1.0",
5 | "components": [
6 | {
7 | "name": "teams-bot",
8 | "hosting": "azure-web-app",
9 | "provision": false,
10 | "deploy": true,
11 | "capabilities": [
12 | "bot"
13 | ],
14 | "build": true,
15 | "folder": "bot",
16 | "artifactFolder": "bot"
17 | },
18 | {
19 | "name": "bot-service",
20 | "provision": true
21 | },
22 | {
23 | "name": "azure-web-app",
24 | "scenario": "Bot",
25 | "connections": [
26 | "identity",
27 | "teams-bot"
28 | ]
29 | },
30 | {
31 | "name": "identity",
32 | "provision": true
33 | }
34 | ],
35 | "programmingLanguage": "typescript",
36 | "solutionSettings": {
37 | "name": "fx-solution-azure",
38 | "version": "1.0.0",
39 | "hostType": "Azure",
40 | "azureResources": [],
41 | "capabilities": [
42 | "Bot"
43 | ],
44 | "activeResourcePlugins": [
45 | "fx-resource-local-debug",
46 | "fx-resource-appstudio",
47 | "fx-resource-cicd",
48 | "fx-resource-api-connector",
49 | "fx-resource-bot",
50 | "fx-resource-identity"
51 | ]
52 | },
53 | "pluginSettings": {
54 | "fx-resource-bot": {
55 | "host-type": "app-service",
56 | "capabilities": [
57 | "bot"
58 | ]
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/bot/teamsBot.ts:
--------------------------------------------------------------------------------
1 | import {
2 | TeamsActivityHandler,
3 | CardFactory,
4 | TurnContext,
5 | } from "botbuilder";
6 | import rawWelcomeCard from "./adaptiveCards/welcome.json" assert { type: "json" };
7 | import { AdaptiveCards } from "@microsoft/adaptivecards-tools";
8 | import { ChatGPTAPI } from 'chatgpt';
9 | import config from "./config.js";
10 |
11 | export class TeamsBot extends TeamsActivityHandler {
12 |
13 | constructor() {
14 | super();
15 |
16 | const api = new ChatGPTAPI({
17 | apiKey: config.openaiApiKey,
18 | });
19 |
20 | let parentMessageId;
21 |
22 | this.onMessage(async (context, next) => {
23 | console.log("Running with Message Activity.");
24 |
25 | let txt = context.activity.text;
26 | const removedMentionText = TurnContext.removeRecipientMention(context.activity);
27 | if (removedMentionText) {
28 | // Remove the line break
29 | txt = removedMentionText.toLowerCase().replace(/\n|\r/g, "").trim();
30 | }
31 |
32 | const response = await api.sendMessage(txt, {
33 | parentMessageId
34 | });
35 |
36 | parentMessageId = response.id;
37 |
38 | await context.sendActivity(response.text);
39 |
40 | // By calling next() you ensure that the next BotHandler is run.
41 | await next();
42 | });
43 |
44 | this.onMembersAdded(async (context, next) => {
45 | const membersAdded = context.activity.membersAdded;
46 | for (let cnt = 0; cnt < membersAdded.length; cnt++) {
47 | if (membersAdded[cnt].id) {
48 | const card = AdaptiveCards.declareWithoutData(rawWelcomeCard).render();
49 | await context.sendActivity({ attachments: [CardFactory.adaptiveCard(card)] });
50 | break;
51 | }
52 | }
53 | await next();
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/templates/azure/provision.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 |
4 | // Merge TeamsFx configurations to Bot service
5 | module botProvision './provision/botService.bicep' = {
6 | name: 'botProvision'
7 | params: {
8 | provisionParameters: provisionParameters
9 | botEndpoint: azureWebAppBotProvision.outputs.siteEndpoint
10 | }
11 | }
12 |
13 | // Resources web app
14 | module azureWebAppBotProvision './provision/azureWebAppBot.bicep' = {
15 | name: 'azureWebAppBotProvision'
16 | params: {
17 | provisionParameters: provisionParameters
18 | userAssignedIdentityId: userAssignedIdentityProvision.outputs.identityResourceId
19 | }
20 | }
21 |
22 |
23 | output azureWebAppBotOutput object = {
24 | teamsFxPluginId: 'teams-bot'
25 | skuName: azureWebAppBotProvision.outputs.skuName
26 | siteName: azureWebAppBotProvision.outputs.siteName
27 | domain: azureWebAppBotProvision.outputs.domain
28 | appServicePlanName: azureWebAppBotProvision.outputs.appServicePlanName
29 | resourceId: azureWebAppBotProvision.outputs.resourceId
30 | siteEndpoint: azureWebAppBotProvision.outputs.siteEndpoint
31 | }
32 |
33 | output BotOutput object = {
34 | domain: azureWebAppBotProvision.outputs.domain
35 | endpoint: azureWebAppBotProvision.outputs.siteEndpoint
36 | }
37 |
38 | // Resources for identity
39 | module userAssignedIdentityProvision './provision/identity.bicep' = {
40 | name: 'userAssignedIdentityProvision'
41 | params: {
42 | provisionParameters: provisionParameters
43 | }
44 | }
45 |
46 | output identityOutput object = {
47 | teamsFxPluginId: 'identity'
48 | identityName: userAssignedIdentityProvision.outputs.identityName
49 | identityResourceId: userAssignedIdentityProvision.outputs.identityResourceId
50 | identityClientId: userAssignedIdentityProvision.outputs.identityClientId
51 | }
--------------------------------------------------------------------------------
/templates/appPackage/manifest.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.14/MicrosoftTeams.schema.json",
3 | "manifestVersion": "1.14",
4 | "version": "1.0.0",
5 | "id": "{{state.fx-resource-appstudio.teamsAppId}}",
6 | "packageName": "com.microsoft.teams.extension",
7 | "developer": {
8 | "name": "Teams App, Inc.",
9 | "websiteUrl": "https://www.example.com",
10 | "privacyUrl": "https://www.example.com/termofuse",
11 | "termsOfUseUrl": "https://www.example.com/privacy"
12 | },
13 | "icons": {
14 | "color": "{{config.manifest.icons.color}}",
15 | "outline": "{{config.manifest.icons.outline}}"
16 | },
17 | "name": {
18 | "short": "{{config.manifest.appName.short}}",
19 | "full": "{{config.manifest.appName.full}}"
20 | },
21 | "description": {
22 | "short": "{{config.manifest.description.short}}",
23 | "full": "{{config.manifest.description.full}}"
24 | },
25 | "accentColor": "#FFFFFF",
26 | "bots": [
27 | {
28 | "botId": "{{state.fx-resource-bot.botId}}",
29 | "scopes": [
30 | "personal",
31 | "team",
32 | "groupchat"
33 | ],
34 | "supportsFiles": false,
35 | "isNotificationOnly": false,
36 | "commandLists": [
37 | {
38 | "scopes": [
39 | "personal",
40 | "team",
41 | "groupchat"
42 | ],
43 | "commands": []
44 | }
45 | ]
46 | }
47 | ],
48 | "composeExtensions": [],
49 | "configurableTabs": [],
50 | "staticTabs": [],
51 | "permissions": [
52 | "identity",
53 | "messageTeamMembers"
54 | ],
55 | "validDomains": [
56 | "{{state.fx-resource-bot.domain}}"
57 | ]
58 | }
--------------------------------------------------------------------------------
/bot/index.ts:
--------------------------------------------------------------------------------
1 | // Import required packages
2 | import express from "express";
3 |
4 | // Import required bot services.
5 | // See https://aka.ms/bot-services to learn more about the different parts of a bot.
6 | import { BotFrameworkAdapter, TurnContext } from "botbuilder";
7 |
8 | // This bot's main dialog.
9 | import { TeamsBot } from "./teamsBot.js";
10 | import config from "./config.js";
11 |
12 | // Create adapter.
13 | // See https://aka.ms/about-bot-adapter to learn more about adapters.
14 | const adapter = new BotFrameworkAdapter({
15 | appId: config.botId,
16 | appPassword: config.botPassword,
17 | });
18 |
19 | // Catch-all for errors.
20 | const onTurnErrorHandler = async (context: TurnContext, error: Error) => {
21 | // This check writes out errors to console log .vs. app insights.
22 | // NOTE: In production environment, you should consider logging this to Azure
23 | // application insights.
24 | console.error(`\n [onTurnError] unhandled error: ${error}`);
25 |
26 | // Send a trace activity, which will be displayed in Bot Framework Emulator
27 | await context.sendTraceActivity(
28 | "OnTurnError Trace",
29 | `${error}`,
30 | "https://www.botframework.com/schemas/error",
31 | "TurnError"
32 | );
33 |
34 | // Send a message to the user
35 | await context.sendActivity(`The bot encountered unhandled error:\n ${error.message}`);
36 | await context.sendActivity("To continue to run this bot, please fix the bot source code.");
37 | };
38 |
39 | // Set the onTurnError for the singleton BotFrameworkAdapter.
40 | adapter.onTurnError = onTurnErrorHandler;
41 |
42 | // Create the bot that will handle incoming messages.
43 | const bot = new TeamsBot();
44 |
45 | // Create HTTP server.
46 | const server = express();
47 |
48 | server.listen(process.env.port || process.env.PORT || 3978, () => {
49 | console.log(`\nBot Started, express server is runnning.`);
50 | });
51 |
52 | // Listen for incoming requests.
53 | server.post("/api/messages", async (req, res) => {
54 | await adapter.processActivity(req, res, async (context) => {
55 | await bot.run(context);
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/templates/azure/provision/azureWebAppBot.bicep:
--------------------------------------------------------------------------------
1 | @secure()
2 | param provisionParameters object
3 | param userAssignedIdentityId string
4 |
5 | var resourceBaseName = provisionParameters.resourceBaseName
6 | var openaiApiKey = provisionParameters.openaiApiKey
7 | var serverfarmsName = contains(provisionParameters, 'webAppServerfarmsName') ? provisionParameters['webAppServerfarmsName'] : '${resourceBaseName}bot' // Try to read name for App Service Plan from parameters
8 | var webAppSKU = contains(provisionParameters, 'webAppSKU') ? provisionParameters['webAppSKU'] : 'B1' // Try to read SKU for Azure Web App from parameters
9 | var webAppName = contains(provisionParameters, 'webAppSitesName') ? provisionParameters['webAppSitesName'] : '${resourceBaseName}bot' // Try to read name for Azure Web App from parameters
10 |
11 | // Compute resources for your Web App
12 | resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = {
13 | kind: 'app'
14 | location: resourceGroup().location
15 | name: serverfarmsName
16 | sku: {
17 | name: webAppSKU
18 | }
19 | properties: {}
20 | }
21 |
22 | // Web App that hosts your app
23 | resource webApp 'Microsoft.Web/sites@2021-02-01' = {
24 | kind: 'app'
25 | location: resourceGroup().location
26 | name: webAppName
27 | properties: {
28 | serverFarmId: serverfarm.id
29 | keyVaultReferenceIdentity: userAssignedIdentityId // Use given user assigned identity to access Key Vault
30 | httpsOnly: true
31 | siteConfig: {
32 | alwaysOn: true
33 | appSettings: [
34 | {
35 | name: 'WEBSITE_NODE_DEFAULT_VERSION'
36 | value: '~18' // Set NodeJS version to 18.x for your site
37 | }
38 | {
39 | name: 'SCM_SCRIPT_GENERATOR_ARGS'
40 | value: '--node' // Register as node server
41 | }
42 | {
43 | name: 'RUNNING_ON_AZURE'
44 | value: '1'
45 | }
46 | {
47 | name: 'OPENAI_API_KEY'
48 | value: openaiApiKey
49 | }
50 | ]
51 | }
52 | }
53 | identity: {
54 | type: 'UserAssigned'
55 | userAssignedIdentities: {
56 | '${userAssignedIdentityId}': {} // The identity is used to access other Azure resources
57 | }
58 | }
59 | }
60 |
61 | output skuName string = webAppSKU
62 | output siteName string = webAppName
63 | output domain string = webApp.properties.defaultHostName
64 | output appServicePlanName string = serverfarmsName
65 | output resourceId string = webApp.id
66 | output siteEndpoint string = 'https://${webApp.properties.defaultHostName}'
67 |
--------------------------------------------------------------------------------
/bot/web.config:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |