├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── HttpBot ├── README.md ├── dotnet_core │ ├── AdapterWithErrorHandler.cs │ ├── Bots │ │ ├── ConversationFlow.cs │ │ ├── HTTPBot.cs │ │ └── UserProfile.cs │ ├── Config.cs │ ├── Controllers │ │ └── BotController.cs │ ├── DeploymentTemplates │ │ ├── new-rg-parameters.json │ │ ├── preexisting-rg-parameters.json │ │ ├── template-with-new-rg.json │ │ └── template-with-preexisting-rg.json │ ├── HTTPBotSample.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ │ └── default.html └── node │ ├── .env │ ├── bot.js │ ├── index.js │ ├── package-lock.json │ └── package.json ├── LICENSE ├── LUISBot ├── ContentModel.json ├── README.md ├── dotnet_core │ ├── AdapterWithErrorHandler.cs │ ├── Bots │ │ ├── ConversationFlow.cs │ │ └── LUISBot.cs │ ├── ContentDialog.cs │ ├── ContentModel.cs │ ├── ContentRecognizer.cs │ ├── Controllers │ │ └── BotController.cs │ ├── DeploymentTemplates │ │ ├── new-rg-parameters.json │ │ ├── preexisting-rg-parameters.json │ │ ├── template-with-new-rg.json │ │ └── template-with-preexisting-rg.json │ ├── LUISBotSample.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ │ └── default.html └── node │ ├── .gitignore │ ├── bot.js │ ├── contentDialog.js │ ├── contentRecognizer.js │ ├── index.js │ ├── package-lock.json │ ├── package.json │ └── template.json ├── README.md ├── img └── logicapp.png └── template.json /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/dotnet/bin/Debug/netcoreapp3.1/HTTPBot.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/dotnet", 16 | "stopAtEntry": false, 17 | // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser 18 | "serverReadyAction": { 19 | "action": "openExternally", 20 | "pattern": "\\bNow listening on:\\s+(https?://\\S+)" 21 | }, 22 | "env": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "sourceFileMap": { 26 | "/Views": "${workspaceFolder}/Views" 27 | } 28 | }, 29 | { 30 | "name": ".NET Core Attach", 31 | "type": "coreclr", 32 | "request": "attach", 33 | "processId": "${command:pickProcess}" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/dotnet/HTTPBot.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/dotnet/HTTPBot.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/dotnet/HTTPBot.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /HttpBot/README.md: -------------------------------------------------------------------------------- 1 | # HTTPS Chatbot Sample 2 | 3 | Bot using the [Microsoft Bot Framework](https://dev.botframework.com?WT.mc_id=ca-github-jasmineg) to send a user's responses to an HTTP endpoint. 4 | 5 | ## How it Works 6 | 7 | The bot greets the user and prompts for their name and a message. These responses are sent via POST request to a HTTP triggered Logic App that can be built upon to respond to the request. 8 | 9 | ### 💡 Ideas for your Logic App 10 | 11 | - Send a Response with a personalized message to user 12 | - Use a Twilio connector to format and send responses as a text message 13 | - Send an email 14 | - Update a table or collection in a database 15 | - Send a desktop or browser notification 16 | 17 | ## Prerequisites 18 | 19 | - Clone/Download this repo to your local machine. 20 | - [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) 21 | - [Node.js](https://nodejs.org) version 10.14.1 or higher 22 | OR 23 | - [.NET Core SDK](https://dotnet.microsoft.com/download?WT.mc_id=ca-github-jasmineg) 24 | 25 | - [Azure Account](https://azure.microsoft.com/en-us/free/?WT.mc_id=ca-github-jasmineg) 26 | - [Student? 🎓 Sign up for an Azure Student account!](https://azure.microsoft.com/en-us/free/students/?WT.mc_id=ca-github-jasmineg) 27 | 28 | ## Setup 29 | 30 | ### Create Logic App 31 | 32 | - Click this button to create an HTTP Triggered Logic App with your Azure account: [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fpaladique%2FAzureSample-HTTPBot%2Fmaster%2Ftemplate.json) 33 | - **OR** Create a [HTTP triggered Logic App in the Azure Portal](https://docs.microsoft.com/en-us/azure/connectors/connectors-native-reqres#prerequisites?WT.mc_id=ca-github-jasmineg) 34 | - After deployment is complete, open Logic App and click "Edit" 35 | - Copy the URL labeled **HTTP POST URL** 36 | ![POST URL](img/logicapp.png) 37 | 38 | ### Edit Code 39 | 40 | #### Edit Code: Node 41 | 42 | - Paste Logic app URL from previous step as the value for `MessageEndpoint` in the provided `.env` file 43 | 44 | ```node 45 | MessageEndpoint=https://copied-url 46 | ``` 47 | 48 | - Confirm that the beginning/base of the url matches the line 105 of `bot.js`, update this line if it does not. 49 | 50 | #### Edit Code: .NET Core 51 | 52 | - In your favorite command line tool, navigate to the project directory and enter the following 53 | 54 | ```bash 55 | dotnet user-secrets init 56 | dotnet user-secrets set "MessageEndpoint" "https://copied-url" 57 | ``` 58 | 59 | - Confirm that the .csproj file contains a UserSecretsId entry: `unique-guid` 60 | - You can remove the secrets with 61 | 62 | ```bash 63 | dotnet user-secrets clear 64 | ``` 65 | 66 | ### Run the bot 67 | 68 | #### Run the bot: Node 69 | 70 | - Install modules and start bot 71 | 72 | ```bash 73 | npm install 74 | npm start 75 | ``` 76 | 77 | #### Run the bot: .NET Core 78 | 79 | - Start from command line (in project directory) 80 | 81 | ```bash 82 | dotnet run 83 | ``` 84 | 85 | ### Testing the bot locally using Bot Framework Emulator 86 | 87 | The [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. 88 | 89 | - Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) 90 | - Launch Bot Framework Emulator 91 | - File -> Open Bot 92 | - Enter a Bot URL of `http://localhost:3978/api/messages` 93 | 94 | ## Optional: Deploy the bot to Azure 95 | 96 | To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. 97 | 98 | ## Learn More 99 | 100 | ### Concepts Used in This Demo 101 | 102 | - [Gathering Input Using Prompts](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-prompts?WT.mc_id=ca-github-jasmineg) 103 | - [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?WT.mc_id=ca-github-jasmineg) 104 | - [Receive and respond to inbound HTTPS requests in Azure Logic Apps](https://docs.microsoft.com/en-us/azure/connectors/connectors-native-reqres#prerequisites?WT.mc_id=ca-github-jasmineg) 105 | 106 | ### General Resources 107 | 108 | - [Bot Framework Documentation](https://docs.botframework.com?WT.mc_id=ca-github-jasmineg) 109 | - [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?WT.mc_id=ca-github-jasmineg) 110 | - [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?WT.mc_id=ca-github-jasmineg) 111 | - [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/?WT.mc_id=ca-github-jasmineg) 112 | - [Overview - What is Azure Logic Apps?](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-overview?WT.mc_id=ca-github-jasmineg) 113 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/AdapterWithErrorHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 2 | using Microsoft.Bot.Builder.TraceExtensions; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace HTTPBotSample 7 | { 8 | public class AdapterWithErrorHandler : BotFrameworkHttpAdapter 9 | { 10 | public AdapterWithErrorHandler(IConfiguration configuration, ILogger logger) 11 | : base(configuration, logger) 12 | { 13 | OnTurnError = async (turnContext, exception) => 14 | { 15 | // Log any leaked exception from the application. 16 | logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); 17 | 18 | // Send a message to the user 19 | await turnContext.SendActivityAsync("The bot encountered an error or bug."); 20 | await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); 21 | 22 | // Send a trace activity, which will be displayed in the Bot Framework Emulator 23 | await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Bots/ConversationFlow.cs: -------------------------------------------------------------------------------- 1 | namespace HTTPBotSample 2 | { 3 | public class ConversationFlow 4 | { 5 | // Identifies the last question asked. 6 | public enum Question 7 | { 8 | Name, 9 | Message, 10 | None, // Our last action did not involve a question. 11 | } 12 | 13 | // The last question asked. 14 | public Question LastQuestionAsked { get; set; } = Question.None; 15 | } 16 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Bots/HTTPBot.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Microsoft.Bot.Builder; 6 | using Microsoft.Bot.Schema; 7 | using System.Net.Http; 8 | using System.Net; 9 | using Newtonsoft.Json; 10 | using Microsoft.Extensions.Options; 11 | 12 | namespace HTTPBotSample 13 | { 14 | public class HTTPBot : ActivityHandler 15 | { 16 | private readonly BotState _userState; 17 | private readonly BotState _conversationState; 18 | private readonly IOptionsMonitor _optionsMonitor; 19 | 20 | public HTTPBot(ConversationState conversationState, UserState userState, IOptionsMonitor optionsMonitor) 21 | { 22 | _userState = userState; 23 | _conversationState = conversationState; 24 | _optionsMonitor = optionsMonitor; 25 | 26 | } 27 | 28 | protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) 29 | { 30 | var conversationStateAccessors = _conversationState.CreateProperty(nameof(ConversationFlow)); 31 | var flow = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationFlow(), cancellationToken); 32 | var userStateAccessors = _userState.CreateProperty(nameof(UserProfile)); 33 | var profile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile(), cancellationToken); 34 | await FillOutUserProfileAsync(flow, profile, turnContext, cancellationToken); 35 | 36 | // Save changes. 37 | await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); 38 | await _userState.SaveChangesAsync(turnContext, false, cancellationToken); 39 | } 40 | 41 | protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) 42 | { 43 | var welcomeText = "Hello and welcome to this bot!"; 44 | foreach (var member in membersAdded) 45 | { 46 | if (member.Id != turnContext.Activity.Recipient.Id) 47 | { 48 | await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken); 49 | } 50 | } 51 | } 52 | 53 | private async Task FillOutUserProfileAsync(ConversationFlow flow, UserProfile profile, ITurnContext turnContext, CancellationToken cancellationToken) 54 | { 55 | var input = turnContext.Activity.Text?.Trim(); 56 | 57 | switch (flow.LastQuestionAsked) 58 | { 59 | case ConversationFlow.Question.None: 60 | await turnContext.SendActivityAsync("Let's get started. What is your name?", null, null, cancellationToken); 61 | flow.LastQuestionAsked = ConversationFlow.Question.Name; 62 | break; 63 | case ConversationFlow.Question.Name: 64 | 65 | profile.Name = input; 66 | await turnContext.SendActivityAsync($"Hi {profile.Name}.", null, null, cancellationToken); 67 | await turnContext.SendActivityAsync("What's your message?", null, null, cancellationToken); 68 | flow.LastQuestionAsked = ConversationFlow.Question.Message; 69 | break; 70 | 71 | case ConversationFlow.Question.Message: 72 | profile.Message = input; 73 | 74 | var messageRecieved = sendResponses(profile); 75 | if (messageRecieved) 76 | { 77 | await turnContext.SendActivityAsync($"Thank you for your message!", null, null, cancellationToken); 78 | } 79 | else 80 | { 81 | await turnContext.SendActivityAsync($"There was a problem sending your message. Try again!", null, null, cancellationToken); 82 | } 83 | flow.LastQuestionAsked = ConversationFlow.Question.None; 84 | break; 85 | } 86 | } 87 | 88 | public bool sendResponses(UserProfile profile) 89 | { 90 | var endpoint = _optionsMonitor.CurrentValue.MessageEndpoint; 91 | 92 | var json = JsonConvert.SerializeObject(profile); 93 | var data = new StringContent(json, Encoding.UTF8, "application/json"); 94 | 95 | var hc = new HttpClient(); 96 | var response = hc.PostAsync(endpoint, data); 97 | var success = response.Result.StatusCode == HttpStatusCode.Accepted ? true : false; 98 | return success; 99 | } 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Bots/UserProfile.cs: -------------------------------------------------------------------------------- 1 | namespace HTTPBotSample 2 | { 3 | public class UserProfile 4 | { 5 | public string Name { get; set; } 6 | 7 | public string Message { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace HTTPBotSample 4 | { 5 | public class Config 6 | { 7 | public Uri MessageEndpoint { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Controllers/BotController.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Bot.Builder; 4 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 5 | 6 | namespace HTTPBotSample 7 | { 8 | // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot 9 | // implementation at runtime. Multiple different IBot implementations running at different endpoints can be 10 | // achieved by specifying a more specific type for the bot constructor argument. 11 | [Route("api/messages")] 12 | [ApiController] 13 | public class BotController : ControllerBase 14 | { 15 | private readonly IBotFrameworkHttpAdapter Adapter; 16 | private readonly IBot Bot; 17 | 18 | public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) 19 | { 20 | Adapter = adapter; 21 | Bot = bot; 22 | } 23 | 24 | [HttpPost] 25 | public async Task PostAsync() 26 | { 27 | // Delegate the processing of the HTTP POST to the adapter. 28 | // The adapter will invoke the bot. 29 | await Adapter.ProcessAsync(Request, Response, Bot); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/DeploymentTemplates/new-rg-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "groupLocation": { 6 | "value": "" 7 | }, 8 | "groupName": { 9 | "value": "" 10 | }, 11 | "appId": { 12 | "value": "" 13 | }, 14 | "appSecret": { 15 | "value": "" 16 | }, 17 | "botId": { 18 | "value": "" 19 | }, 20 | "botSku": { 21 | "value": "" 22 | }, 23 | "newAppServicePlanName": { 24 | "value": "" 25 | }, 26 | "newAppServicePlanSku": { 27 | "value": { 28 | "name": "S1", 29 | "tier": "Standard", 30 | "size": "S1", 31 | "family": "S", 32 | "capacity": 1 33 | } 34 | }, 35 | "newAppServicePlanLocation": { 36 | "value": "" 37 | }, 38 | "newWebAppName": { 39 | "value": "" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/DeploymentTemplates/preexisting-rg-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appId": { 6 | "value": "" 7 | }, 8 | "appSecret": { 9 | "value": "" 10 | }, 11 | "botId": { 12 | "value": "" 13 | }, 14 | "botSku": { 15 | "value": "" 16 | }, 17 | "newAppServicePlanName": { 18 | "value": "" 19 | }, 20 | "newAppServicePlanSku": { 21 | "value": { 22 | "name": "S1", 23 | "tier": "Standard", 24 | "size": "S1", 25 | "family": "S", 26 | "capacity": 1 27 | } 28 | }, 29 | "appServicePlanLocation": { 30 | "value": "" 31 | }, 32 | "existingAppServicePlan": { 33 | "value": "" 34 | }, 35 | "newWebAppName": { 36 | "value": "" 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/DeploymentTemplates/template-with-new-rg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "groupLocation": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "Specifies the location of the Resource Group." 9 | } 10 | }, 11 | "groupName": { 12 | "type": "string", 13 | "metadata": { 14 | "description": "Specifies the name of the Resource Group." 15 | } 16 | }, 17 | "appId": { 18 | "type": "string", 19 | "metadata": { 20 | "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." 21 | } 22 | }, 23 | "appSecret": { 24 | "type": "string", 25 | "metadata": { 26 | "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings." 27 | } 28 | }, 29 | "botId": { 30 | "type": "string", 31 | "metadata": { 32 | "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." 33 | } 34 | }, 35 | "botSku": { 36 | "type": "string", 37 | "metadata": { 38 | "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." 39 | } 40 | }, 41 | "newAppServicePlanName": { 42 | "type": "string", 43 | "metadata": { 44 | "description": "The name of the App Service Plan." 45 | } 46 | }, 47 | "newAppServicePlanSku": { 48 | "type": "object", 49 | "defaultValue": { 50 | "name": "S1", 51 | "tier": "Standard", 52 | "size": "S1", 53 | "family": "S", 54 | "capacity": 1 55 | }, 56 | "metadata": { 57 | "description": "The SKU of the App Service Plan. Defaults to Standard values." 58 | } 59 | }, 60 | "newAppServicePlanLocation": { 61 | "type": "string", 62 | "metadata": { 63 | "description": "The location of the App Service Plan. Defaults to \"westus\"." 64 | } 65 | }, 66 | "newWebAppName": { 67 | "type": "string", 68 | "defaultValue": "", 69 | "metadata": { 70 | "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." 71 | } 72 | } 73 | }, 74 | "variables": { 75 | "appServicePlanName": "[parameters('newAppServicePlanName')]", 76 | "resourcesLocation": "[parameters('newAppServicePlanLocation')]", 77 | "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", 78 | "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", 79 | "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" 80 | }, 81 | "resources": [ 82 | { 83 | "name": "[parameters('groupName')]", 84 | "type": "Microsoft.Resources/resourceGroups", 85 | "apiVersion": "2018-05-01", 86 | "location": "[parameters('groupLocation')]", 87 | "properties": { 88 | } 89 | }, 90 | { 91 | "type": "Microsoft.Resources/deployments", 92 | "apiVersion": "2018-05-01", 93 | "name": "storageDeployment", 94 | "resourceGroup": "[parameters('groupName')]", 95 | "dependsOn": [ 96 | "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" 97 | ], 98 | "properties": { 99 | "mode": "Incremental", 100 | "template": { 101 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 102 | "contentVersion": "1.0.0.0", 103 | "parameters": {}, 104 | "variables": {}, 105 | "resources": [ 106 | { 107 | "comments": "Create a new App Service Plan", 108 | "type": "Microsoft.Web/serverfarms", 109 | "name": "[variables('appServicePlanName')]", 110 | "apiVersion": "2018-02-01", 111 | "location": "[variables('resourcesLocation')]", 112 | "sku": "[parameters('newAppServicePlanSku')]", 113 | "properties": { 114 | "name": "[variables('appServicePlanName')]" 115 | } 116 | }, 117 | { 118 | "comments": "Create a Web App using the new App Service Plan", 119 | "type": "Microsoft.Web/sites", 120 | "apiVersion": "2015-08-01", 121 | "location": "[variables('resourcesLocation')]", 122 | "kind": "app", 123 | "dependsOn": [ 124 | "[resourceId('Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" 125 | ], 126 | "name": "[variables('webAppName')]", 127 | "properties": { 128 | "name": "[variables('webAppName')]", 129 | "serverFarmId": "[variables('appServicePlanName')]", 130 | "siteConfig": { 131 | "appSettings": [ 132 | { 133 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 134 | "value": "10.14.1" 135 | }, 136 | { 137 | "name": "MicrosoftAppId", 138 | "value": "[parameters('appId')]" 139 | }, 140 | { 141 | "name": "MicrosoftAppPassword", 142 | "value": "[parameters('appSecret')]" 143 | } 144 | ], 145 | "cors": { 146 | "allowedOrigins": [ 147 | "https://botservice.hosting.portal.azure.net", 148 | "https://hosting.onecloud.azure-test.net/" 149 | ] 150 | }, 151 | "webSocketsEnabled": true 152 | } 153 | } 154 | }, 155 | { 156 | "apiVersion": "2017-12-01", 157 | "type": "Microsoft.BotService/botServices", 158 | "name": "[parameters('botId')]", 159 | "location": "global", 160 | "kind": "bot", 161 | "sku": { 162 | "name": "[parameters('botSku')]" 163 | }, 164 | "properties": { 165 | "name": "[parameters('botId')]", 166 | "displayName": "[parameters('botId')]", 167 | "endpoint": "[variables('botEndpoint')]", 168 | "msaAppId": "[parameters('appId')]", 169 | "developerAppInsightsApplicationId": null, 170 | "developerAppInsightKey": null, 171 | "publishingCredentials": null, 172 | "storageResourceId": null 173 | }, 174 | "dependsOn": [ 175 | "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" 176 | ] 177 | } 178 | ], 179 | "outputs": {} 180 | } 181 | } 182 | } 183 | ] 184 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/DeploymentTemplates/template-with-preexisting-rg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appId": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." 9 | } 10 | }, 11 | "appSecret": { 12 | "type": "string", 13 | "metadata": { 14 | "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"." 15 | } 16 | }, 17 | "botId": { 18 | "type": "string", 19 | "metadata": { 20 | "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." 21 | } 22 | }, 23 | "botSku": { 24 | "defaultValue": "F0", 25 | "type": "string", 26 | "metadata": { 27 | "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." 28 | } 29 | }, 30 | "newAppServicePlanName": { 31 | "type": "string", 32 | "defaultValue": "", 33 | "metadata": { 34 | "description": "The name of the new App Service Plan." 35 | } 36 | }, 37 | "newAppServicePlanSku": { 38 | "type": "object", 39 | "defaultValue": { 40 | "name": "S1", 41 | "tier": "Standard", 42 | "size": "S1", 43 | "family": "S", 44 | "capacity": 1 45 | }, 46 | "metadata": { 47 | "description": "The SKU of the App Service Plan. Defaults to Standard values." 48 | } 49 | }, 50 | "appServicePlanLocation": { 51 | "type": "string", 52 | "metadata": { 53 | "description": "The location of the App Service Plan." 54 | } 55 | }, 56 | "existingAppServicePlan": { 57 | "type": "string", 58 | "defaultValue": "", 59 | "metadata": { 60 | "description": "Name of the existing App Service Plan used to create the Web App for the bot." 61 | } 62 | }, 63 | "newWebAppName": { 64 | "type": "string", 65 | "defaultValue": "", 66 | "metadata": { 67 | "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." 68 | } 69 | } 70 | }, 71 | "variables": { 72 | "defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]", 73 | "useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]", 74 | "servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]", 75 | "resourcesLocation": "[parameters('appServicePlanLocation')]", 76 | "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", 77 | "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", 78 | "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" 79 | }, 80 | "resources": [ 81 | { 82 | "comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.", 83 | "type": "Microsoft.Web/serverfarms", 84 | "condition": "[not(variables('useExistingAppServicePlan'))]", 85 | "name": "[variables('servicePlanName')]", 86 | "apiVersion": "2018-02-01", 87 | "location": "[variables('resourcesLocation')]", 88 | "sku": "[parameters('newAppServicePlanSku')]", 89 | "properties": { 90 | "name": "[variables('servicePlanName')]" 91 | } 92 | }, 93 | { 94 | "comments": "Create a Web App using an App Service Plan", 95 | "type": "Microsoft.Web/sites", 96 | "apiVersion": "2015-08-01", 97 | "location": "[variables('resourcesLocation')]", 98 | "kind": "app", 99 | "dependsOn": [ 100 | "[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]" 101 | ], 102 | "name": "[variables('webAppName')]", 103 | "properties": { 104 | "name": "[variables('webAppName')]", 105 | "serverFarmId": "[variables('servicePlanName')]", 106 | "siteConfig": { 107 | "appSettings": [ 108 | { 109 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 110 | "value": "10.14.1" 111 | }, 112 | { 113 | "name": "MicrosoftAppId", 114 | "value": "[parameters('appId')]" 115 | }, 116 | { 117 | "name": "MicrosoftAppPassword", 118 | "value": "[parameters('appSecret')]" 119 | } 120 | ], 121 | "cors": { 122 | "allowedOrigins": [ 123 | "https://botservice.hosting.portal.azure.net", 124 | "https://hosting.onecloud.azure-test.net/" 125 | ] 126 | }, 127 | "webSocketsEnabled": true 128 | } 129 | } 130 | }, 131 | { 132 | "apiVersion": "2017-12-01", 133 | "type": "Microsoft.BotService/botServices", 134 | "name": "[parameters('botId')]", 135 | "location": "global", 136 | "kind": "bot", 137 | "sku": { 138 | "name": "[parameters('botSku')]" 139 | }, 140 | "properties": { 141 | "name": "[parameters('botId')]", 142 | "displayName": "[parameters('botId')]", 143 | "endpoint": "[variables('botEndpoint')]", 144 | "msaAppId": "[parameters('appId')]", 145 | "developerAppInsightsApplicationId": null, 146 | "developerAppInsightKey": null, 147 | "publishingCredentials": null, 148 | "storageResourceId": null 149 | }, 150 | "dependsOn": [ 151 | "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" 152 | ] 153 | } 154 | ] 155 | } -------------------------------------------------------------------------------- /HttpBot/dotnet_core/HTTPBotSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | latest 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace HTTPBotSample 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | CreateHostBuilder(args).Build().Run(); 12 | } 13 | 14 | public static IHostBuilder CreateHostBuilder(string[] args) => 15 | Host.CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(webBuilder => 17 | { 18 | webBuilder.ConfigureLogging((logging) => 19 | { 20 | logging.AddDebug(); 21 | logging.AddConsole(); 22 | }); 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:3978", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "HTTPBot": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "applicationUrl": "http://localhost:3978", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Bot.Builder; 4 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | 9 | namespace HTTPBotSample 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddControllers().AddNewtonsoftJson(); 24 | 25 | // Create the Bot Framework Adapter with error handling enabled. 26 | services.AddSingleton(); 27 | services.AddSingleton(); 28 | services.AddSingleton(); 29 | services.AddSingleton(); 30 | 31 | //Get Message Endpoint Secret 32 | services.Configure(Configuration); 33 | services.AddTransient(); 34 | } 35 | 36 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 37 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 38 | { 39 | if (env.IsDevelopment()) 40 | { 41 | app.UseDeveloperExceptionPage(); 42 | } 43 | 44 | app.UseDefaultFiles() 45 | .UseStaticFiles() 46 | .UseWebSockets() 47 | .UseRouting() 48 | .UseAuthorization() 49 | .UseEndpoints(endpoints => 50 | { 51 | endpoints.MapControllers(); 52 | }); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "MicrosoftAppId": "", 3 | "MicrosoftAppPassword": "" 4 | } 5 | -------------------------------------------------------------------------------- /HttpBot/dotnet_core/wwwroot/default.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | HTTPBot 8 | 367 | 389 | 390 | 391 | 392 |
393 |
394 |
395 |
HTTPBot
396 |
397 |
398 |
399 |
400 |
Your bot is ready!
401 |
You can test your bot in the Bot Framework Emulator
402 | by connecting to http://localhost:3978/api/messages.
403 | 405 |
Visit Azure 406 | Bot Service to register your bot and add it to
407 | various channels. The bot's endpoint URL typically looks 408 | like this:
409 |
https://your_bots_hostname/api/messages
410 |
411 |
412 |
413 |
414 | 415 |
416 | 417 | 418 | 419 | -------------------------------------------------------------------------------- /HttpBot/node/.env: -------------------------------------------------------------------------------- 1 | MessageEndpoint= -------------------------------------------------------------------------------- /HttpBot/node/bot.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | const fetch = require('node-fetch'); 4 | const dotenv = require('dotenv'); 5 | const path = require('path'); 6 | const { ActivityHandler, MessageFactory } = require('botbuilder'); 7 | 8 | const ENV_FILE = path.join(__dirname, '.env'); 9 | dotenv.config({ path: ENV_FILE }); 10 | const CONVERSATION_FLOW_PROPERTY = 'CONVERSATION_FLOW_PROPERTY'; 11 | const USER_PROFILE_PROPERTY = 'USER_PROFILE_PROPERTY'; 12 | const HTTP_MESSAGE_ENDPOINT = process.env.MessageEndpoint; 13 | 14 | const question = { 15 | name: 'name', 16 | message: 'message', 17 | none: 'none' 18 | }; 19 | 20 | class HTTPBot extends ActivityHandler { 21 | constructor(conversationState, userState) { 22 | super(); 23 | // The state property accessors for conversation flow and user profile. 24 | this.conversationFlow = conversationState.createProperty(CONVERSATION_FLOW_PROPERTY); 25 | this.userProfile = userState.createProperty(USER_PROFILE_PROPERTY); 26 | 27 | // The state management objects for the conversation and user. 28 | this.conversationState = conversationState; 29 | this.userState = userState; 30 | 31 | // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. 32 | this.onMessage(async (context, next) => { 33 | const flow = await this.conversationFlow.get(context, { lastQuestionAsked: question.none }); 34 | const profile = await this.userProfile.get(context, {}); 35 | await HTTPBot.fillOutUserProfile(flow, profile, context); 36 | 37 | // By calling next() you ensure that the next BotHandler is run. 38 | await next(); 39 | }); 40 | 41 | // Welcome user when they start the chat 42 | this.onMembersAdded(async (context, next) => { 43 | const membersAdded = context.activity.membersAdded; 44 | const welcomeText = 'Hello and welcome to this bot!'; 45 | for (let cnt = 0; cnt < membersAdded.length; ++cnt) { 46 | if (membersAdded[cnt].id !== context.activity.recipient.id) { 47 | await context.sendActivity(MessageFactory.text(welcomeText, welcomeText)); 48 | } 49 | } 50 | const flow = await this.conversationFlow.get(context, { lastQuestionAsked: question.none }); 51 | const profile = await this.userProfile.get(context, {}); 52 | await HTTPBot.fillOutUserProfile(flow, profile, context); 53 | await next(); 54 | }); 55 | } 56 | 57 | async run(context) { 58 | await super.run(context); 59 | // Save any state changes. The load happened during the execution of the Dialog. 60 | await this.conversationState.saveChanges(context, false); 61 | await this.userState.saveChanges(context, false); 62 | } 63 | 64 | static async fillOutUserProfile(flow, profile, turnContext) { 65 | const input = turnContext.activity.text; 66 | let result; 67 | switch (flow.lastQuestionAsked) { 68 | case question.none: 69 | await turnContext.sendActivity("Let's get started. What is your name?"); 70 | flow.lastQuestionAsked = question.name; 71 | break; 72 | 73 | // If we last asked for their name, record their response, confirm that we got it. 74 | // Ask them for their message and update the conversation flag. 75 | case question.name: 76 | result = input !== ''; 77 | if (result) { 78 | profile.name = input; 79 | await turnContext.sendActivity(`Hi ${ profile.name }! What is your message?`); 80 | flow.lastQuestionAsked = question.message; 81 | break; 82 | } else { 83 | // If we couldn't interpret their input, ask them for it again. 84 | // Don't update the conversation flag, so that we repeat this step. 85 | await turnContext.sendActivity(result.message || "I'm sorry, I didn't understand that."); 86 | break; 87 | } 88 | 89 | case question.message: 90 | result = input !== ''; 91 | if (result) { 92 | profile.message = input; 93 | await sendResponses(profile); 94 | await turnContext.sendActivity(`Thank you for this message!!: ${ profile.message }.`); 95 | break; 96 | } else { 97 | await turnContext.sendActivity(result.message || 'Sorry! There was a problem sending your message.'); 98 | break; 99 | } 100 | } 101 | } 102 | } 103 | 104 | async function sendResponses(userInput) { 105 | const url = new URL(HTTP_MESSAGE_ENDPOINT, 'https://prod-05.centralus.logic.azure.com:443'); 106 | 107 | // Send responses to endpoint 108 | await fetch(url, { 109 | method: 'POST', 110 | headers: { 111 | 'Content-Type': 'application/json' 112 | }, 113 | body: JSON.stringify(userInput) 114 | }).then(() => console.log('success!')); 115 | } 116 | 117 | module.exports.HTTPBot = HTTPBot; 118 | -------------------------------------------------------------------------------- /HttpBot/node/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | // Import required bot services. 5 | const dotenv = require('dotenv'); 6 | const path = require('path'); 7 | const restify = require('restify'); 8 | const fetch = require('node-fetch'); 9 | 10 | const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = require('botbuilder'); 11 | 12 | // Import bot's main dialog. 13 | const { HTTPBot } = require('./bot'); 14 | const memoryStorage = new MemoryStorage(); 15 | const conversationState = new ConversationState(memoryStorage); 16 | const userState = new UserState(memoryStorage); 17 | 18 | // Create HTTP server 19 | const server = restify.createServer(); 20 | server.listen(process.env.port || process.env.PORT || 3978, () => { 21 | console.log(`\n${ server.name } listening to ${ server.url }`); 22 | console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator'); 23 | console.log('\nTo talk to your bot, open the emulator select "Open Bot"'); 24 | }); 25 | 26 | // Create adapter. 27 | // See https://aka.ms/about-bot-adapter to learn more about how bots work. 28 | const adapter = new BotFrameworkAdapter({ 29 | appId: process.env.MicrosoftAppId, 30 | appPassword: process.env.MicrosoftAppPassword 31 | }); 32 | 33 | // Catch-all for errors. 34 | const onTurnErrorHandler = async (context, error) => { 35 | // This check writes out errors to console log .vs. app insights. 36 | // NOTE: In production environment, you should consider logging this to Azure 37 | // application insights. 38 | console.error(`\n [onTurnError] unhandled error: ${ error }`); 39 | 40 | // Send a trace activity, which will be displayed in Bot Framework Emulator 41 | await context.sendTraceActivity( 42 | 'OnTurnError Trace', 43 | `${ error }`, 44 | 'https://www.botframework.com/schemas/error', 45 | 'TurnError' 46 | ); 47 | 48 | // Send a message to the user 49 | await context.sendActivity('The bot encountered an error or bug.'); 50 | await context.sendActivity('To continue to run this bot, please fix the bot source code.'); 51 | }; 52 | 53 | // Set the onTurnError for the singleton BotFrameworkAdapter. 54 | adapter.onTurnError = onTurnErrorHandler; 55 | 56 | // Create the main dialog. 57 | const myBot = new HTTPBot(conversationState, userState); 58 | 59 | // Listen for incoming requests. 60 | server.post('/api/messages', (req, res) => { 61 | adapter.processActivity(req, res, async (context) => { 62 | // Route to main dialog. 63 | await myBot.run(context); 64 | }); 65 | }); 66 | 67 | // Listen for Upgrade requests for Streaming. 68 | server.on('upgrade', (req, socket, head) => { 69 | // Create an adapter scoped to this WebSocket connection to allow storing session data. 70 | const streamingAdapter = new BotFrameworkAdapter({ 71 | appId: process.env.MicrosoftAppId, 72 | appPassword: process.env.MicrosoftAppPassword 73 | }); 74 | // Set onTurnError for the BotFrameworkAdapter created for each connection. 75 | streamingAdapter.onTurnError = onTurnErrorHandler; 76 | 77 | streamingAdapter.useWebSocket(req, socket, head, async (context) => { 78 | // After connecting via WebSocket, run this logic for every request sent over 79 | // the WebSocket connection. 80 | await myBot.run(context); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /HttpBot/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "http-bot", 3 | "version": "1.0.0", 4 | "description": "Demonstrate the core capabilities of the Microsoft Bot Framework and HTTP POST request", 5 | "author": "Generated using Microsoft Bot Builder Yeoman generator v4.7.0", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "start": "node ./index.js", 10 | "watch": "nodemon ./index.js", 11 | "lint": "eslint .", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com" 17 | }, 18 | "dependencies": { 19 | "@microsoft/recognizers-text-suite": "^1.3.0", 20 | "botbuilder": "^4.19.2", 21 | "dotenv": "^8.2.0", 22 | "node-fetch": "^2.6.7", 23 | "restify": "~8.4.0" 24 | }, 25 | "devDependencies": { 26 | "eslint": "^6.6.0", 27 | "eslint-config-standard": "^14.1.0", 28 | "eslint-plugin-import": "^2.18.2", 29 | "eslint-plugin-node": "^10.0.0", 30 | "eslint-plugin-promise": "^4.2.1", 31 | "eslint-plugin-standard": "^4.0.1", 32 | "nodemon": "~2.0.19" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jasmine Greenaway 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LUISBot/ContentModel.json: -------------------------------------------------------------------------------- 1 | { 2 | "luis_schema_version": "7.0.0", 3 | "intents": [ 4 | { 5 | "name": "Greet", 6 | "features": [] 7 | }, 8 | { 9 | "name": "Learning", 10 | "features": [] 11 | }, 12 | { 13 | "name": "None", 14 | "features": [] 15 | } 16 | ], 17 | "entities": [ 18 | { 19 | "name": "documentation", 20 | "children": [], 21 | "roles": [], 22 | "features": [] 23 | }, 24 | { 25 | "name": "samples", 26 | "children": [], 27 | "roles": [], 28 | "features": [] 29 | }, 30 | { 31 | "name": "TechInterests", 32 | "children": [], 33 | "roles": [], 34 | "features": [] 35 | } 36 | ], 37 | "hierarchicals": [], 38 | "composites": [], 39 | "closedLists": [], 40 | "prebuiltEntities": [ 41 | { 42 | "name": "personName", 43 | "roles": [] 44 | } 45 | ], 46 | "utterances": [ 47 | { 48 | "text": "asp.net", 49 | "intent": "Learning", 50 | "entities": [ 51 | { 52 | "entity": "TechInterests", 53 | "startPos": 0, 54 | "endPos": 6, 55 | "children": [] 56 | } 57 | ] 58 | }, 59 | { 60 | "text": "c", 61 | "intent": "Learning", 62 | "entities": [] 63 | }, 64 | { 65 | "text": "c sharp", 66 | "intent": "Learning", 67 | "entities": [ 68 | { 69 | "entity": "TechInterests", 70 | "startPos": 0, 71 | "endPos": 6, 72 | "children": [] 73 | } 74 | ] 75 | }, 76 | { 77 | "text": "c#", 78 | "intent": "Learning", 79 | "entities": [ 80 | { 81 | "entity": "TechInterests", 82 | "startPos": 0, 83 | "endPos": 1, 84 | "children": [] 85 | } 86 | ] 87 | }, 88 | { 89 | "text": "docs", 90 | "intent": "Learning", 91 | "entities": [ 92 | { 93 | "entity": "documentation", 94 | "startPos": 0, 95 | "endPos": 3, 96 | "children": [] 97 | } 98 | ] 99 | }, 100 | { 101 | "text": "documentation", 102 | "intent": "Learning", 103 | "entities": [ 104 | { 105 | "entity": "documentation", 106 | "startPos": 0, 107 | "endPos": 12, 108 | "children": [] 109 | } 110 | ] 111 | }, 112 | { 113 | "text": "e", 114 | "intent": "None", 115 | "entities": [] 116 | }, 117 | { 118 | "text": "f#", 119 | "intent": "Learning", 120 | "entities": [ 121 | { 122 | "entity": "TechInterests", 123 | "startPos": 0, 124 | "endPos": 1, 125 | "children": [] 126 | } 127 | ] 128 | }, 129 | { 130 | "text": "go", 131 | "intent": "Learning", 132 | "entities": [ 133 | { 134 | "entity": "TechInterests", 135 | "startPos": 0, 136 | "endPos": 1, 137 | "children": [] 138 | } 139 | ] 140 | }, 141 | { 142 | "text": "hello", 143 | "intent": "Greet", 144 | "entities": [] 145 | }, 146 | { 147 | "text": "hi", 148 | "intent": "Greet", 149 | "entities": [] 150 | }, 151 | { 152 | "text": "i want code samples", 153 | "intent": "Learning", 154 | "entities": [ 155 | { 156 | "entity": "samples", 157 | "startPos": 7, 158 | "endPos": 18, 159 | "children": [] 160 | } 161 | ] 162 | }, 163 | { 164 | "text": "i want docs", 165 | "intent": "Learning", 166 | "entities": [ 167 | { 168 | "entity": "documentation", 169 | "startPos": 7, 170 | "endPos": 10, 171 | "children": [] 172 | } 173 | ] 174 | }, 175 | { 176 | "text": "i want documentation", 177 | "intent": "Learning", 178 | "entities": [ 179 | { 180 | "entity": "documentation", 181 | "startPos": 7, 182 | "endPos": 19, 183 | "children": [] 184 | } 185 | ] 186 | }, 187 | { 188 | "text": "i want documentation on powershell", 189 | "intent": "Learning", 190 | "entities": [ 191 | { 192 | "entity": "documentation", 193 | "startPos": 7, 194 | "endPos": 19, 195 | "children": [] 196 | } 197 | ] 198 | }, 199 | { 200 | "text": "i want samples in", 201 | "intent": "Learning", 202 | "entities": [] 203 | }, 204 | { 205 | "text": "i want samples in c#", 206 | "intent": "Learning", 207 | "entities": [ 208 | { 209 | "entity": "TechInterests", 210 | "startPos": 18, 211 | "endPos": 19, 212 | "children": [] 213 | } 214 | ] 215 | }, 216 | { 217 | "text": "i want samples on powershell", 218 | "intent": "Learning", 219 | "entities": [ 220 | { 221 | "entity": "samples", 222 | "startPos": 7, 223 | "endPos": 13, 224 | "children": [] 225 | }, 226 | { 227 | "entity": "TechInterests", 228 | "startPos": 18, 229 | "endPos": 27, 230 | "children": [] 231 | } 232 | ] 233 | }, 234 | { 235 | "text": "i want to learn", 236 | "intent": "Learning", 237 | "entities": [ 238 | { 239 | "entity": "samples", 240 | "startPos": 10, 241 | "endPos": 14, 242 | "children": [] 243 | }, 244 | { 245 | "entity": "documentation", 246 | "startPos": 10, 247 | "endPos": 14, 248 | "children": [] 249 | } 250 | ] 251 | }, 252 | { 253 | "text": "i want to learn about", 254 | "intent": "Learning", 255 | "entities": [ 256 | { 257 | "entity": "samples", 258 | "startPos": 10, 259 | "endPos": 14, 260 | "children": [] 261 | }, 262 | { 263 | "entity": "documentation", 264 | "startPos": 10, 265 | "endPos": 14, 266 | "children": [] 267 | } 268 | ] 269 | }, 270 | { 271 | "text": "java", 272 | "intent": "Learning", 273 | "entities": [ 274 | { 275 | "entity": "TechInterests", 276 | "startPos": 0, 277 | "endPos": 3, 278 | "children": [] 279 | } 280 | ] 281 | }, 282 | { 283 | "text": "javascript", 284 | "intent": "Learning", 285 | "entities": [] 286 | }, 287 | { 288 | "text": "node", 289 | "intent": "Learning", 290 | "entities": [] 291 | }, 292 | { 293 | "text": "node.js", 294 | "intent": "Learning", 295 | "entities": [ 296 | { 297 | "entity": "TechInterests", 298 | "startPos": 0, 299 | "endPos": 6, 300 | "children": [] 301 | } 302 | ] 303 | }, 304 | { 305 | "text": "notes", 306 | "intent": "None", 307 | "entities": [] 308 | }, 309 | { 310 | "text": "python", 311 | "intent": "Learning", 312 | "entities": [ 313 | { 314 | "entity": "TechInterests", 315 | "startPos": 0, 316 | "endPos": 5, 317 | "children": [] 318 | } 319 | ] 320 | }, 321 | { 322 | "text": "samples", 323 | "intent": "Learning", 324 | "entities": [ 325 | { 326 | "entity": "samples", 327 | "startPos": 0, 328 | "endPos": 6, 329 | "children": [] 330 | } 331 | ] 332 | }, 333 | { 334 | "text": "scala", 335 | "intent": "Learning", 336 | "entities": [ 337 | { 338 | "entity": "TechInterests", 339 | "startPos": 0, 340 | "endPos": 4, 341 | "children": [] 342 | } 343 | ] 344 | }, 345 | { 346 | "text": "sql", 347 | "intent": "Learning", 348 | "entities": [ 349 | { 350 | "entity": "TechInterests", 351 | "startPos": 0, 352 | "endPos": 2, 353 | "children": [] 354 | } 355 | ] 356 | }, 357 | { 358 | "text": "test", 359 | "intent": "None", 360 | "entities": [] 361 | }, 362 | { 363 | "text": "visual studio", 364 | "intent": "Learning", 365 | "entities": [ 366 | { 367 | "entity": "TechInterests", 368 | "startPos": 0, 369 | "endPos": 12, 370 | "children": [] 371 | } 372 | ] 373 | } 374 | ], 375 | "versionId": "0.1", 376 | "name": "ContentModel", 377 | "desc": "", 378 | "culture": "en-us", 379 | "tokenizerVersion": "1.0.0", 380 | "patternAnyEntities": [], 381 | "regex_entities": [], 382 | "phraselists": [], 383 | "regex_features": [], 384 | "patterns": [], 385 | "settings": [] 386 | } -------------------------------------------------------------------------------- /LUISBot/README.md: -------------------------------------------------------------------------------- 1 | # LUIS Chatbot Sample 2 | 3 | Bot using the [Microsoft Bot Framework](https://dev.botframework.com?WT.mc_id=ca-github-jasmineg) and Language Understanding (LUIS) that returns search queries on Microsoft Docs and Samples. 4 | 5 | ## How it Works 6 | 7 | The bot greets the user and prompts for their choices of docs or samples and returns a search query based on their choices. The LUIS model is trained to understand technology interests, including the user's. 8 | 9 | ## Prerequisites 10 | 11 | - Clone/Download this repo to your local machine. 12 | - [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) 13 | - [Node.js](https://nodejs.org) version 10.14.1 or higher 14 | OR 15 | - [.NET Core SDK](https://dotnet.microsoft.com/download?WT.mc_id=ca-github-jasmineg) 16 | 17 | - [Azure Account](https://azure.microsoft.com/en-us/free/?WT.mc_id=ca-github-jasmineg) 18 | - [Student? 🎓 Sign up for an Azure Student account!](https://azure.microsoft.com/en-us/free/students/?WT.mc_id=ca-github-jasmineg) 19 | 20 | ## Setup 21 | 22 | ### Language Understanding (LUIS) 23 | 24 | - Sign in to [LUIS](https://www.luis.ai/) 25 | - Import `ContentModel.json` as new app. **+ New App for conversation** > **Import as JSON** 26 | - Click `Train` and try some input with `Test` 27 | - Click `Publish` to create api keys for the model. 28 | - Copy the primary or secondary key, endpoint url, app id from `Manage` > `Azure Resources` and `Settings` 29 | 30 | ### Edit Code 31 | 32 | #### Edit Code: Node 33 | 34 | - Paste copied values from last step in the provided `.env` file 35 | 36 | ```node 37 | LuisAppId= 38 | LuisAPIKey= 39 | LuisAPIHostName=https://copied-url 40 | ``` 41 | 42 | #### Edit Code: .NET Core 43 | 44 | - In your favorite command line tool, navigate to the project directory and enter the following values from last step in the commands 45 | 46 | ```bash 47 | dotnet user-secrets init 48 | dotnet user-secrets set "LuisAppId" "copied-app-id" 49 | dotnet user-secrets set "LuisAPIKey" "api-key" 50 | dotnet user-secrets set "LuisAPIHostName" "copied-url" 51 | ``` 52 | 53 | - Confirm that the .csproj file contains a UserSecretsId entry: `unique-guid` 54 | - You can remove the secrets with 55 | 56 | ```bash 57 | dotnet user-secrets clear 58 | ``` 59 | 60 | ### Run the bot 61 | 62 | #### Run the bot: Node 63 | 64 | - Install modules and start bot 65 | 66 | ```bash 67 | npm install 68 | npm start 69 | ``` 70 | 71 | #### Run the bot: .NET Core 72 | 73 | - Start from command line (in project directory) 74 | 75 | ```bash 76 | dotnet run 77 | ``` 78 | 79 | ### Testing the bot locally using Bot Framework Emulator 80 | 81 | The [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. 82 | 83 | - Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) 84 | - Launch Bot Framework Emulator 85 | - File -> Open Bot 86 | - Enter a Bot URL of `http://localhost:3978/api/messages` 87 | 88 | ## Optional: Deploy the bot to Azure 89 | 90 | To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. 91 | 92 | ## Learn More 93 | 94 | ### Concepts Used in This Demo 95 | 96 | - [Gathering Input Using Prompts](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-prompts?WT.mc_id=ca-github-jasmineg) 97 | - [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?WT.mc_id=ca-github-jasmineg) 98 | - [Receive and respond to inbound HTTPS requests in Azure Logic Apps](https://docs.microsoft.com/en-us/azure/connectors/connectors-native-reqres#prerequisites?WT.mc_id=ca-github-jasmineg) 99 | 100 | ### General Resources 101 | 102 | - [Bot Framework Documentation](https://docs.botframework.com?WT.mc_id=ca-github-jasmineg) 103 | - [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?WT.mc_id=ca-github-jasmineg) 104 | - [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?WT.mc_id=ca-github-jasmineg) 105 | - [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/?WT.mc_id=ca-github-jasmineg) 106 | - [Overview - What is Azure Logic Apps?](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-overview?WT.mc_id=ca-github-jasmineg) 107 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/AdapterWithErrorHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 2 | using Microsoft.Bot.Builder.TraceExtensions; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace LUISBotSample 7 | { 8 | public class AdapterWithErrorHandler : BotFrameworkHttpAdapter 9 | { 10 | public AdapterWithErrorHandler(IConfiguration configuration, ILogger logger) 11 | : base(configuration, logger) 12 | { 13 | OnTurnError = async (turnContext, exception) => 14 | { 15 | // Log any leaked exception from the application. 16 | logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); 17 | 18 | // Send a message to the user 19 | await turnContext.SendActivityAsync("The bot encountered an error or bug."); 20 | await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); 21 | 22 | // Send a trace activity, which will be displayed in the Bot Framework Emulator 23 | await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Bots/ConversationFlow.cs: -------------------------------------------------------------------------------- 1 | namespace LUISBotSample 2 | { 3 | public class ConversationFlow 4 | { 5 | // Identifies the last question asked. 6 | public enum Question 7 | { 8 | Name, 9 | Message, 10 | None, // Our last action did not involve a question. 11 | } 12 | 13 | // The last question asked. 14 | public Question LastQuestionAsked { get; set; } = Question.None; 15 | } 16 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Bots/LUISBot.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Microsoft.Bot.Builder; 6 | using Microsoft.Bot.Schema; 7 | using System.Net.Http; 8 | using System.Net; 9 | using Newtonsoft.Json; 10 | using Microsoft.Extensions.Options; 11 | using LUISBotSample; 12 | using Microsoft.Bot.Builder.Dialogs; 13 | 14 | namespace LUISBotSample 15 | { 16 | public class LUISBot : ActivityHandler 17 | { 18 | private readonly BotState _userState; 19 | private readonly BotState _conversationState; 20 | private readonly ContentDialog _contentDialog; 21 | 22 | public LUISBot(ConversationState conversationState, UserState userState, ContentDialog contentDialog) 23 | { 24 | _userState = userState; 25 | _conversationState = conversationState; 26 | _contentDialog = contentDialog; 27 | } 28 | 29 | protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) 30 | { 31 | var conversationStateAccessors = _conversationState.CreateProperty(nameof(ConversationFlow)); 32 | var flow = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationFlow(), cancellationToken); 33 | 34 | await _contentDialog.RunAsync(turnContext, _conversationState.CreateProperty(nameof(DialogState)), cancellationToken); 35 | 36 | } 37 | 38 | protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) 39 | { 40 | var welcomeText = "Hello and welcome to this bot!"; 41 | foreach (var member in membersAdded) 42 | { 43 | if (member.Id != turnContext.Activity.Recipient.Id) 44 | { 45 | await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken); 46 | } 47 | } 48 | } 49 | 50 | public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) 51 | { 52 | await base.OnTurnAsync(turnContext, cancellationToken); 53 | 54 | // Save changes. 55 | await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); 56 | await _userState.SaveChangesAsync(turnContext, false, cancellationToken); 57 | } 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/ContentDialog.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Microsoft.Bot.Builder; 5 | using Microsoft.Bot.Builder.Dialogs; 6 | using Microsoft.Bot.Builder.Dialogs.Choices; 7 | using Microsoft.Bot.Schema; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace LUISBotSample 11 | { 12 | public class ContentDialog : ComponentDialog 13 | { 14 | private readonly ContentRecognizer _luisRecognizer; 15 | protected readonly ILogger Logger; 16 | 17 | private readonly string MS_Root = "https://docs.microsoft.com/"; 18 | private readonly string MS_SamplesSearchURL = "samples/browse/?terms="; 19 | private readonly string MS_DocsSearchURL = "search/?terms="; 20 | 21 | public string DocsUrl => MS_Root + MS_DocsSearchURL; 22 | public string SamplesUrl => MS_Root + MS_SamplesSearchURL; 23 | 24 | public ContentDialog(ContentRecognizer luisRecognizer, ILogger logger) 25 | : base(nameof(ContentDialog)) 26 | { 27 | _luisRecognizer = luisRecognizer; 28 | Logger = logger; 29 | 30 | 31 | AddDialog(new TextPrompt(nameof(TextPrompt))); 32 | AddDialog(new ChoicePrompt(nameof(ChoicePrompt))); 33 | AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt))); 34 | 35 | AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[] 36 | { 37 | SelectResourceStepAsync, 38 | SelectTechStepAsync, 39 | ConfirmChoicesStepAsync, 40 | SendResults, 41 | })); 42 | 43 | // The initial child Dialog to run. 44 | InitialDialogId = nameof(WaterfallDialog); 45 | } 46 | private async Task SelectResourceStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) 47 | { 48 | if (!_luisRecognizer.IsConfigured) 49 | { 50 | await stepContext.Context.SendActivityAsync( 51 | MessageFactory.Text("LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file."), cancellationToken); 52 | 53 | return await stepContext.NextAsync(null, cancellationToken); 54 | } 55 | 56 | return await stepContext.PromptAsync(nameof(ChoicePrompt), 57 | new PromptOptions 58 | { 59 | Prompt = MessageFactory.Text("Welcome to the Docs Bot! Which learning resources did you want?"), 60 | Choices = ChoiceFactory.ToChoices(new List { "Docs", "Samples", "Both" }), 61 | }, cancellationToken); 62 | } 63 | 64 | private async Task SelectTechStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) 65 | { 66 | stepContext.Values["resource"] = ((FoundChoice)stepContext.Result).Value; 67 | return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("What language did you want?") }, cancellationToken); 68 | } 69 | 70 | private async Task ConfirmChoicesStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) 71 | { 72 | stepContext.Values["lang"] = (string)stepContext.Result; 73 | var resource = (string)stepContext.Values["resource"]; 74 | var lang = (string)stepContext.Values["lang"]; 75 | 76 | var luisResult = await _luisRecognizer.RecognizeAsync(stepContext.Context, cancellationToken); 77 | if (luisResult.TopIntent().intent != ContentModel.Intent.Learning) 78 | { 79 | MessageFactory.Text($"Your query for {lang} was not recognized by this bot, but will still be added to the search results"); 80 | } 81 | return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text($"You want to see {resource} in {lang} Is this correct?") }, cancellationToken); 82 | } 83 | 84 | private async Task SendResults(WaterfallStepContext stepContext, CancellationToken cancellationToken) 85 | { 86 | var attachments = new List(); 87 | var reply = MessageFactory.Attachment(attachments); 88 | 89 | var resource = (string)stepContext.Values["resource"]; 90 | var lang = (string)stepContext.Values["lang"]; 91 | 92 | var cardActions = new List(); 93 | 94 | if (resource == "Docs" || resource == "Both") 95 | cardActions.Add(new CardAction(ActionTypes.OpenUrl, $"MS Docs on {lang}", value: DocsUrl + lang)); 96 | if (resource == "Samples" || resource == "Both") 97 | cardActions.Add(new CardAction(ActionTypes.OpenUrl, $"MS Samples on {lang}", value: SamplesUrl + lang)); 98 | 99 | var adaptiveCardAttachment = new HeroCard() 100 | { 101 | Text = "Here's your links!", 102 | Buttons = cardActions 103 | }; 104 | 105 | reply.Attachments.Add(adaptiveCardAttachment.ToAttachment()); 106 | await stepContext.Context.SendActivityAsync(reply, cancellationToken); 107 | 108 | return await stepContext.EndDialogAsync(); 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/ContentModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by LUISGen ContentModel.json -cs Luis.ContentModel -o 3 | // Tool github: https://github.com/microsoft/botbuilder-tools 4 | // Changes may cause incorrect behavior and will be lost if the code is 5 | // regenerated. 6 | // 7 | using Newtonsoft.Json; 8 | using System.Collections.Generic; 9 | using Microsoft.Bot.Builder; 10 | using Microsoft.Bot.Builder.AI.Luis; 11 | namespace LUISBotSample 12 | { 13 | public partial class ContentModel: IRecognizerConvert 14 | { 15 | [JsonProperty("text")] 16 | public string Text; 17 | 18 | [JsonProperty("alteredText")] 19 | public string AlteredText; 20 | 21 | public enum Intent { 22 | Greet, 23 | Learning, 24 | None 25 | }; 26 | [JsonProperty("intents")] 27 | public Dictionary Intents; 28 | 29 | public class _Entities 30 | { 31 | // Simple entities 32 | public string[] TechInterests; 33 | 34 | public string[] documentation; 35 | 36 | public string[] samples; 37 | 38 | // Built-in entities 39 | public string[] personName; 40 | 41 | // Instance 42 | public class _Instance 43 | { 44 | public InstanceData[] TechInterests; 45 | public InstanceData[] documentation; 46 | public InstanceData[] personName; 47 | public InstanceData[] samples; 48 | } 49 | [JsonProperty("$instance")] 50 | public _Instance _instance; 51 | } 52 | [JsonProperty("entities")] 53 | public _Entities Entities; 54 | 55 | [JsonExtensionData(ReadData = true, WriteData = true)] 56 | public IDictionary Properties {get; set; } 57 | 58 | public void Convert(dynamic result) 59 | { 60 | var app = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 61 | Text = app.Text; 62 | AlteredText = app.AlteredText; 63 | Intents = app.Intents; 64 | Entities = app.Entities; 65 | Properties = app.Properties; 66 | } 67 | 68 | public (Intent intent, double score) TopIntent() 69 | { 70 | Intent maxIntent = Intent.None; 71 | var max = 0.0; 72 | foreach (var entry in Intents) 73 | { 74 | if (entry.Value.Score > max) 75 | { 76 | maxIntent = entry.Key; 77 | max = entry.Value.Score.Value; 78 | } 79 | } 80 | return (maxIntent, max); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/ContentRecognizer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Microsoft.Bot.Builder; 4 | using Microsoft.Bot.Builder.AI.Luis; 5 | using Microsoft.Extensions.Configuration; 6 | 7 | 8 | namespace LUISBotSample 9 | { 10 | public class ContentRecognizer : IRecognizer 11 | { 12 | private readonly LuisRecognizer _recognizer; 13 | 14 | public ContentRecognizer(IConfiguration configuration) 15 | { 16 | var luisIsConfigured = !string.IsNullOrEmpty(configuration["LuisAppId"]) && !string.IsNullOrEmpty(configuration["LuisAPIKey"]) && !string.IsNullOrEmpty(configuration["LuisAPIHostName"]); 17 | if (luisIsConfigured) 18 | { 19 | var luisApplication = new LuisApplication( 20 | configuration["LuisAppId"], 21 | configuration["LuisAPIKey"], 22 | "https://" + configuration["LuisAPIHostName"]); 23 | // Set the recognizer options depending on which endpoint version you want to use. 24 | // More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3 25 | var recognizerOptions = new LuisRecognizerOptionsV3(luisApplication) 26 | { 27 | PredictionOptions = new Microsoft.Bot.Builder.AI.LuisV3.LuisPredictionOptions 28 | { 29 | IncludeInstanceData = true, 30 | } 31 | }; 32 | 33 | _recognizer = new LuisRecognizer(recognizerOptions); 34 | } 35 | } 36 | 37 | // Returns true if luis is configured in the appsettings.json and initialized. 38 | public virtual bool IsConfigured => _recognizer != null; 39 | 40 | public virtual async Task RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken) 41 | => await _recognizer.RecognizeAsync(turnContext, cancellationToken); 42 | 43 | public virtual async Task RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken) 44 | where T : IRecognizerConvert, new() 45 | => await _recognizer.RecognizeAsync(turnContext, cancellationToken); 46 | } 47 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Controllers/BotController.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Bot.Builder; 4 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 5 | 6 | namespace LUISBotSample 7 | { 8 | // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot 9 | // implementation at runtime. Multiple different IBot implementations running at different endpoints can be 10 | // achieved by specifying a more specific type for the bot constructor argument. 11 | [Route("api/messages")] 12 | [ApiController] 13 | public class BotController : ControllerBase 14 | { 15 | private readonly IBotFrameworkHttpAdapter Adapter; 16 | private readonly IBot Bot; 17 | 18 | public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) 19 | { 20 | Adapter = adapter; 21 | Bot = bot; 22 | } 23 | 24 | [HttpPost] 25 | public async Task PostAsync() 26 | { 27 | // Delegate the processing of the HTTP POST to the adapter. 28 | // The adapter will invoke the bot. 29 | await Adapter.ProcessAsync(Request, Response, Bot); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/DeploymentTemplates/new-rg-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "groupLocation": { 6 | "value": "" 7 | }, 8 | "groupName": { 9 | "value": "" 10 | }, 11 | "appId": { 12 | "value": "" 13 | }, 14 | "appSecret": { 15 | "value": "" 16 | }, 17 | "botId": { 18 | "value": "" 19 | }, 20 | "botSku": { 21 | "value": "" 22 | }, 23 | "newAppServicePlanName": { 24 | "value": "" 25 | }, 26 | "newAppServicePlanSku": { 27 | "value": { 28 | "name": "S1", 29 | "tier": "Standard", 30 | "size": "S1", 31 | "family": "S", 32 | "capacity": 1 33 | } 34 | }, 35 | "newAppServicePlanLocation": { 36 | "value": "" 37 | }, 38 | "newWebAppName": { 39 | "value": "" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/DeploymentTemplates/preexisting-rg-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appId": { 6 | "value": "" 7 | }, 8 | "appSecret": { 9 | "value": "" 10 | }, 11 | "botId": { 12 | "value": "" 13 | }, 14 | "botSku": { 15 | "value": "" 16 | }, 17 | "newAppServicePlanName": { 18 | "value": "" 19 | }, 20 | "newAppServicePlanSku": { 21 | "value": { 22 | "name": "S1", 23 | "tier": "Standard", 24 | "size": "S1", 25 | "family": "S", 26 | "capacity": 1 27 | } 28 | }, 29 | "appServicePlanLocation": { 30 | "value": "" 31 | }, 32 | "existingAppServicePlan": { 33 | "value": "" 34 | }, 35 | "newWebAppName": { 36 | "value": "" 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/DeploymentTemplates/template-with-new-rg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "groupLocation": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "Specifies the location of the Resource Group." 9 | } 10 | }, 11 | "groupName": { 12 | "type": "string", 13 | "metadata": { 14 | "description": "Specifies the name of the Resource Group." 15 | } 16 | }, 17 | "appId": { 18 | "type": "string", 19 | "metadata": { 20 | "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." 21 | } 22 | }, 23 | "appSecret": { 24 | "type": "string", 25 | "metadata": { 26 | "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings." 27 | } 28 | }, 29 | "botId": { 30 | "type": "string", 31 | "metadata": { 32 | "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." 33 | } 34 | }, 35 | "botSku": { 36 | "type": "string", 37 | "metadata": { 38 | "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." 39 | } 40 | }, 41 | "newAppServicePlanName": { 42 | "type": "string", 43 | "metadata": { 44 | "description": "The name of the App Service Plan." 45 | } 46 | }, 47 | "newAppServicePlanSku": { 48 | "type": "object", 49 | "defaultValue": { 50 | "name": "S1", 51 | "tier": "Standard", 52 | "size": "S1", 53 | "family": "S", 54 | "capacity": 1 55 | }, 56 | "metadata": { 57 | "description": "The SKU of the App Service Plan. Defaults to Standard values." 58 | } 59 | }, 60 | "newAppServicePlanLocation": { 61 | "type": "string", 62 | "metadata": { 63 | "description": "The location of the App Service Plan. Defaults to \"westus\"." 64 | } 65 | }, 66 | "newWebAppName": { 67 | "type": "string", 68 | "defaultValue": "", 69 | "metadata": { 70 | "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." 71 | } 72 | } 73 | }, 74 | "variables": { 75 | "appServicePlanName": "[parameters('newAppServicePlanName')]", 76 | "resourcesLocation": "[parameters('newAppServicePlanLocation')]", 77 | "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", 78 | "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", 79 | "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" 80 | }, 81 | "resources": [ 82 | { 83 | "name": "[parameters('groupName')]", 84 | "type": "Microsoft.Resources/resourceGroups", 85 | "apiVersion": "2018-05-01", 86 | "location": "[parameters('groupLocation')]", 87 | "properties": { 88 | } 89 | }, 90 | { 91 | "type": "Microsoft.Resources/deployments", 92 | "apiVersion": "2018-05-01", 93 | "name": "storageDeployment", 94 | "resourceGroup": "[parameters('groupName')]", 95 | "dependsOn": [ 96 | "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" 97 | ], 98 | "properties": { 99 | "mode": "Incremental", 100 | "template": { 101 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 102 | "contentVersion": "1.0.0.0", 103 | "parameters": {}, 104 | "variables": {}, 105 | "resources": [ 106 | { 107 | "comments": "Create a new App Service Plan", 108 | "type": "Microsoft.Web/serverfarms", 109 | "name": "[variables('appServicePlanName')]", 110 | "apiVersion": "2018-02-01", 111 | "location": "[variables('resourcesLocation')]", 112 | "sku": "[parameters('newAppServicePlanSku')]", 113 | "properties": { 114 | "name": "[variables('appServicePlanName')]" 115 | } 116 | }, 117 | { 118 | "comments": "Create a Web App using the new App Service Plan", 119 | "type": "Microsoft.Web/sites", 120 | "apiVersion": "2015-08-01", 121 | "location": "[variables('resourcesLocation')]", 122 | "kind": "app", 123 | "dependsOn": [ 124 | "[resourceId('Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" 125 | ], 126 | "name": "[variables('webAppName')]", 127 | "properties": { 128 | "name": "[variables('webAppName')]", 129 | "serverFarmId": "[variables('appServicePlanName')]", 130 | "siteConfig": { 131 | "appSettings": [ 132 | { 133 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 134 | "value": "10.14.1" 135 | }, 136 | { 137 | "name": "MicrosoftAppId", 138 | "value": "[parameters('appId')]" 139 | }, 140 | { 141 | "name": "MicrosoftAppPassword", 142 | "value": "[parameters('appSecret')]" 143 | } 144 | ], 145 | "cors": { 146 | "allowedOrigins": [ 147 | "https://botservice.hosting.portal.azure.net", 148 | "https://hosting.onecloud.azure-test.net/" 149 | ] 150 | }, 151 | "webSocketsEnabled": true 152 | } 153 | } 154 | }, 155 | { 156 | "apiVersion": "2017-12-01", 157 | "type": "Microsoft.BotService/botServices", 158 | "name": "[parameters('botId')]", 159 | "location": "global", 160 | "kind": "bot", 161 | "sku": { 162 | "name": "[parameters('botSku')]" 163 | }, 164 | "properties": { 165 | "name": "[parameters('botId')]", 166 | "displayName": "[parameters('botId')]", 167 | "endpoint": "[variables('botEndpoint')]", 168 | "msaAppId": "[parameters('appId')]", 169 | "developerAppInsightsApplicationId": null, 170 | "developerAppInsightKey": null, 171 | "publishingCredentials": null, 172 | "storageResourceId": null 173 | }, 174 | "dependsOn": [ 175 | "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" 176 | ] 177 | } 178 | ], 179 | "outputs": {} 180 | } 181 | } 182 | } 183 | ] 184 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/DeploymentTemplates/template-with-preexisting-rg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appId": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." 9 | } 10 | }, 11 | "appSecret": { 12 | "type": "string", 13 | "metadata": { 14 | "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"." 15 | } 16 | }, 17 | "botId": { 18 | "type": "string", 19 | "metadata": { 20 | "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." 21 | } 22 | }, 23 | "botSku": { 24 | "defaultValue": "F0", 25 | "type": "string", 26 | "metadata": { 27 | "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." 28 | } 29 | }, 30 | "newAppServicePlanName": { 31 | "type": "string", 32 | "defaultValue": "", 33 | "metadata": { 34 | "description": "The name of the new App Service Plan." 35 | } 36 | }, 37 | "newAppServicePlanSku": { 38 | "type": "object", 39 | "defaultValue": { 40 | "name": "S1", 41 | "tier": "Standard", 42 | "size": "S1", 43 | "family": "S", 44 | "capacity": 1 45 | }, 46 | "metadata": { 47 | "description": "The SKU of the App Service Plan. Defaults to Standard values." 48 | } 49 | }, 50 | "appServicePlanLocation": { 51 | "type": "string", 52 | "metadata": { 53 | "description": "The location of the App Service Plan." 54 | } 55 | }, 56 | "existingAppServicePlan": { 57 | "type": "string", 58 | "defaultValue": "", 59 | "metadata": { 60 | "description": "Name of the existing App Service Plan used to create the Web App for the bot." 61 | } 62 | }, 63 | "newWebAppName": { 64 | "type": "string", 65 | "defaultValue": "", 66 | "metadata": { 67 | "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." 68 | } 69 | } 70 | }, 71 | "variables": { 72 | "defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]", 73 | "useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]", 74 | "servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]", 75 | "resourcesLocation": "[parameters('appServicePlanLocation')]", 76 | "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", 77 | "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", 78 | "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" 79 | }, 80 | "resources": [ 81 | { 82 | "comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.", 83 | "type": "Microsoft.Web/serverfarms", 84 | "condition": "[not(variables('useExistingAppServicePlan'))]", 85 | "name": "[variables('servicePlanName')]", 86 | "apiVersion": "2018-02-01", 87 | "location": "[variables('resourcesLocation')]", 88 | "sku": "[parameters('newAppServicePlanSku')]", 89 | "properties": { 90 | "name": "[variables('servicePlanName')]" 91 | } 92 | }, 93 | { 94 | "comments": "Create a Web App using an App Service Plan", 95 | "type": "Microsoft.Web/sites", 96 | "apiVersion": "2015-08-01", 97 | "location": "[variables('resourcesLocation')]", 98 | "kind": "app", 99 | "dependsOn": [ 100 | "[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]" 101 | ], 102 | "name": "[variables('webAppName')]", 103 | "properties": { 104 | "name": "[variables('webAppName')]", 105 | "serverFarmId": "[variables('servicePlanName')]", 106 | "siteConfig": { 107 | "appSettings": [ 108 | { 109 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 110 | "value": "10.14.1" 111 | }, 112 | { 113 | "name": "MicrosoftAppId", 114 | "value": "[parameters('appId')]" 115 | }, 116 | { 117 | "name": "MicrosoftAppPassword", 118 | "value": "[parameters('appSecret')]" 119 | } 120 | ], 121 | "cors": { 122 | "allowedOrigins": [ 123 | "https://botservice.hosting.portal.azure.net", 124 | "https://hosting.onecloud.azure-test.net/" 125 | ] 126 | }, 127 | "webSocketsEnabled": true 128 | } 129 | } 130 | }, 131 | { 132 | "apiVersion": "2017-12-01", 133 | "type": "Microsoft.BotService/botServices", 134 | "name": "[parameters('botId')]", 135 | "location": "global", 136 | "kind": "bot", 137 | "sku": { 138 | "name": "[parameters('botSku')]" 139 | }, 140 | "properties": { 141 | "name": "[parameters('botId')]", 142 | "displayName": "[parameters('botId')]", 143 | "endpoint": "[variables('botEndpoint')]", 144 | "msaAppId": "[parameters('appId')]", 145 | "developerAppInsightsApplicationId": null, 146 | "developerAppInsightKey": null, 147 | "publishingCredentials": null, 148 | "storageResourceId": null 149 | }, 150 | "dependsOn": [ 151 | "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" 152 | ] 153 | } 154 | ] 155 | } -------------------------------------------------------------------------------- /LUISBot/dotnet_core/LUISBotSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | latest 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Always 17 | 18 | 19 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace LUISBotSample 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | CreateHostBuilder(args).Build().Run(); 12 | } 13 | 14 | public static IHostBuilder CreateHostBuilder(string[] args) => 15 | Host.CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(webBuilder => 17 | { 18 | webBuilder.ConfigureLogging((logging) => 19 | { 20 | logging.AddDebug(); 21 | logging.AddConsole(); 22 | }); 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:3978", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "HTTPBot": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "applicationUrl": "http://localhost:3978", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Bot.Builder; 4 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | 9 | namespace LUISBotSample 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddControllers().AddNewtonsoftJson(); 24 | 25 | // Create the Bot Framework Adapter with error handling enabled. 26 | services.AddSingleton(); 27 | services.AddSingleton(); 28 | services.AddSingleton(); 29 | services.AddSingleton(); 30 | services.AddSingleton(); 31 | 32 | services.AddSingleton(); 33 | services.AddTransient(); 34 | } 35 | 36 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 37 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 38 | { 39 | if (env.IsDevelopment()) 40 | { 41 | app.UseDeveloperExceptionPage(); 42 | } 43 | 44 | app.UseDefaultFiles() 45 | .UseStaticFiles() 46 | .UseWebSockets() 47 | .UseRouting() 48 | .UseAuthorization() 49 | .UseEndpoints(endpoints => 50 | { 51 | endpoints.MapControllers(); 52 | }); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "MicrosoftAppId": "", 3 | "MicrosoftAppPassword": "" 4 | } 5 | -------------------------------------------------------------------------------- /LUISBot/dotnet_core/wwwroot/default.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | HTTPBot 8 | 367 | 389 | 390 | 391 | 392 |
393 |
394 |
395 |
HTTPBot
396 |
397 |
398 |
399 |
400 |
Your bot is ready!
401 |
You can test your bot in the Bot Framework Emulator
402 | by connecting to http://localhost:3978/api/messages.
403 | 405 |
Visit Azure 406 | Bot Service to register your bot and add it to
407 | various channels. The bot's endpoint URL typically looks 408 | like this:
409 |
https://your_bots_hostname/api/messages
410 |
411 |
412 |
413 |
414 | 415 |
416 | 417 | 418 | 419 | -------------------------------------------------------------------------------- /LUISBot/node/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | .env -------------------------------------------------------------------------------- /LUISBot/node/bot.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | const fetch = require('node-fetch'); 4 | const dotenv = require('dotenv'); 5 | const path = require('path'); 6 | const { ActivityHandler, MessageFactory } = require('botbuilder'); 7 | 8 | const ENV_FILE = path.join(__dirname, '.env'); 9 | dotenv.config({ path: ENV_FILE }); 10 | const CONVERSATION_FLOW_PROPERTY = 'CONVERSATION_FLOW_PROPERTY'; 11 | const USER_PROFILE_PROPERTY = 'USER_PROFILE_PROPERTY'; 12 | const HTTP_MESSAGE_ENDPOINT = process.env.MessageEndpoint; 13 | 14 | const question = { 15 | name: 'name', 16 | message: 'message', 17 | none: 'none' 18 | }; 19 | 20 | class HTTPBot extends ActivityHandler { 21 | constructor(conversationState, userState, dialog) { 22 | super(); 23 | 24 | this.conversationState = conversationState; 25 | this.userState = userState; 26 | this.dialog = dialog; 27 | this.dialogState = this.conversationState.createProperty('DialogState'); 28 | 29 | // The state property accessors for conversation flow and user profile. 30 | this.conversationFlow = conversationState.createProperty(CONVERSATION_FLOW_PROPERTY); 31 | this.userProfile = userState.createProperty(USER_PROFILE_PROPERTY); 32 | 33 | // The state management objects for the conversation and user. 34 | this.conversationState = conversationState; 35 | this.userState = userState; 36 | 37 | // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. 38 | this.onMessage(async (context, next) => { 39 | await this.dialog.run(context, this.dialogState); 40 | await next(); 41 | }); 42 | 43 | // Welcome user when they start the chat 44 | this.onMembersAdded(async (context, next) => { 45 | const membersAdded = context.activity.membersAdded; 46 | const welcomeText = 'Hello and welcome to this bot!'; 47 | for (let cnt = 0; cnt < membersAdded.length; ++cnt) { 48 | if (membersAdded[cnt].id !== context.activity.recipient.id) { 49 | await context.sendActivity(MessageFactory.text(welcomeText, welcomeText)); 50 | } 51 | } 52 | await this.dialog.run(context, this.dialogState); 53 | await next(); 54 | }); 55 | } 56 | 57 | async run(context) { 58 | await super.run(context); 59 | // Save any state changes. The load happened during the execution of the Dialog. 60 | await this.conversationState.saveChanges(context, false); 61 | await this.userState.saveChanges(context, false); 62 | } 63 | } 64 | 65 | module.exports.HTTPBot = HTTPBot; 66 | -------------------------------------------------------------------------------- /LUISBot/node/contentDialog.js: -------------------------------------------------------------------------------- 1 | const { LuisRecognizer } = require("botbuilder-ai"); 2 | const { CardFactory, MessageFactory } = require("botbuilder"); 3 | 4 | const { 5 | ChoiceFactory, 6 | ChoicePrompt, 7 | ComponentDialog, 8 | ConfirmPrompt, 9 | DialogSet, 10 | DialogTurnStatus, 11 | TextPrompt, 12 | WaterfallDialog, 13 | } = require("botbuilder-dialogs"); 14 | 15 | const CHOICE_PROMPT = "CHOICE_PROMPT"; 16 | const CONFIRM_PROMPT = "CONFIRM_PROMPT"; 17 | const LANG_PROMPT = "LANG_PROMPT"; 18 | const WATERFALL_DIALOG = "WATERFALL_DIALOG"; 19 | 20 | const MS_Root = "https://docs.microsoft.com/"; 21 | const MS_SamplesSearchURL = "samples/browse/?terms="; 22 | const MS_DocsSearchURL = "search/?terms="; 23 | 24 | class ContentDialog extends ComponentDialog { 25 | constructor(luis) { 26 | super("contentDialog"); 27 | this.luis = luis; 28 | 29 | this.addDialog(new ChoicePrompt(CHOICE_PROMPT)); 30 | this.addDialog(new TextPrompt(LANG_PROMPT)); 31 | this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT)); 32 | 33 | this.addDialog( 34 | new WaterfallDialog(WATERFALL_DIALOG, [ 35 | this.selectResourceStep.bind(this), 36 | this.selectTechStep.bind(this), 37 | this.confirmChoices.bind(this), 38 | this.sendResults.bind(this), 39 | ]) 40 | ); 41 | 42 | this.initialDialogId = WATERFALL_DIALOG; 43 | } 44 | 45 | async selectResourceStep(step) { 46 | if (!this.luis.isConfigured) { 47 | const messageText = 48 | "NOTE: LUIS is not configured. To enable all capabilities, add `LuisAppId`, `LuisAPIKey` and `LuisAPIHostName` to the .env file."; 49 | step.context.sendActivity(messageText); 50 | return await step.endDialog(); 51 | } else { 52 | return await step.prompt(CHOICE_PROMPT, { 53 | prompt: "Which learning resources did you want?", 54 | choices: ChoiceFactory.toChoices(["Docs", "Samples", "Both"]), 55 | }); 56 | } 57 | } 58 | 59 | async selectTechStep(step) { 60 | step.values.resources = step.result.value; 61 | return await step.prompt(LANG_PROMPT, "What language did you want?"); 62 | } 63 | 64 | async confirmChoices(step) { 65 | step.values.lang = step.result; 66 | const luisResult = await this.luis.executeLuisQuery(step.context); 67 | const message = `You want to see ${step.values.resources} in ${step.values.lang} Is this correct?`; 68 | 69 | if (LuisRecognizer.topIntent(luisResult) != "Learning") { 70 | step.context.sendActivity( 71 | `Your query for ${step.values.lang} was not recognized by this bot, but will still be added to the search results` 72 | ); 73 | } 74 | 75 | return await step.prompt(CONFIRM_PROMPT, message); 76 | } 77 | 78 | async sendResults(step) { 79 | let url = MS_Root; 80 | let resource = step.values.resources; 81 | let language = step.values.lang; 82 | 83 | let sample = { 84 | type: "Action.OpenUrl", 85 | title: "MS Samples on " + language, 86 | url: `${url + MS_SamplesSearchURL + language}`, 87 | }; 88 | 89 | let docs = { 90 | type: "Action.OpenUrl", 91 | title: "MS Docs on " + language, 92 | url: `${url + MS_DocsSearchURL + language}`, 93 | }; 94 | 95 | let cardSchema = { 96 | $schema: "http://adaptivecards.io/schemas/adaptive-card.json", 97 | type: "AdaptiveCard", 98 | version: "1.0", 99 | body: [ 100 | { 101 | type: "TextBlock", 102 | text: "Here's your links!", 103 | }, 104 | ], 105 | actions: [], 106 | }; 107 | 108 | if (resource == "Docs") cardSchema.actions.push(docs); 109 | else if (resource == "Samples") cardSchema.actions.push(sample); 110 | else { 111 | cardSchema.actions.push(docs); 112 | cardSchema.actions.push(sample); 113 | } 114 | 115 | const card = CardFactory.adaptiveCard(cardSchema); 116 | const message = MessageFactory.attachment(card); 117 | await step.context.sendActivity(message); 118 | 119 | return await step.endDialog(); 120 | } 121 | 122 | async run(turnContext, accessor) { 123 | const dialogSet = new DialogSet(accessor); 124 | dialogSet.add(this); 125 | const dialogContext = await dialogSet.createContext(turnContext); 126 | const results = await dialogContext.continueDialog(); 127 | if (results.status === DialogTurnStatus.empty) { 128 | await dialogContext.beginDialog(this.id); 129 | } 130 | } 131 | } 132 | 133 | module.exports.ContentDialog = ContentDialog; 134 | -------------------------------------------------------------------------------- /LUISBot/node/contentRecognizer.js: -------------------------------------------------------------------------------- 1 | const { LuisRecognizer } = require('botbuilder-ai'); 2 | 3 | class ContentRecognizer { 4 | constructor(config) { 5 | const luisIsConfigured = config && config.applicationId && config.endpointKey && config.endpoint; 6 | if (luisIsConfigured) { 7 | // Set the recognizer options depending on which endpoint version you want to use e.g v2 or v3. 8 | // More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3 9 | const recognizerOptions = { 10 | apiVersion: 'v3' 11 | }; 12 | 13 | this.recognizer = new LuisRecognizer(config, recognizerOptions); 14 | } 15 | } 16 | 17 | get isConfigured() { 18 | return (this.recognizer !== undefined); 19 | } 20 | 21 | /** 22 | * Returns an object with preformatted LUIS results for the bot's dialogs to consume. 23 | * @param {TurnContext} context 24 | */ 25 | async executeLuisQuery(context) { 26 | return await this.recognizer.recognize(context); 27 | } 28 | 29 | getResourceEntities(result) { 30 | let fromValue; 31 | if (result.entities.$instance.TechInterests) { 32 | fromValue = result.entities.$instance.From[0].text; 33 | } 34 | 35 | console.log(result.entities.$instance); 36 | } 37 | 38 | } 39 | 40 | module.exports.ContentRecognizer = ContentRecognizer; -------------------------------------------------------------------------------- /LUISBot/node/index.js: -------------------------------------------------------------------------------- 1 | // Import required bot services. 2 | const dotenv = require('dotenv'); 3 | const path = require('path'); 4 | const restify = require('restify'); 5 | const ENV_FILE = path.join(__dirname, '.env'); 6 | dotenv.config({ path: ENV_FILE }); 7 | 8 | const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = require('botbuilder'); 9 | 10 | // Import bot's main dialog. 11 | const { HTTPBot } = require('./bot'); 12 | const { ContentDialog } = require('./contentDialog'); 13 | const { ContentRecognizer } = require('./contentRecognizer'); 14 | 15 | 16 | const memoryStorage = new MemoryStorage(); 17 | const conversationState = new ConversationState(memoryStorage); 18 | const userState = new UserState(memoryStorage); 19 | 20 | // Create HTTP server 21 | const server = restify.createServer(); 22 | server.listen(process.env.port || process.env.PORT || 3978, () => { 23 | console.log(`\n${ server.name } listening to ${ server.url }`); 24 | console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator'); 25 | console.log('\nTo talk to your bot, open the emulator select "Open Bot"'); 26 | }); 27 | 28 | // Create adapter. 29 | // See https://aka.ms/about-bot-adapter to learn more about how bots work. 30 | const adapter = new BotFrameworkAdapter({ 31 | appId: process.env.MicrosoftAppId, 32 | appPassword: process.env.MicrosoftAppPassword 33 | }); 34 | 35 | // Catch-all for errors. 36 | const onTurnErrorHandler = async (context, error) => { 37 | // This check writes out errors to console log .vs. app insights. 38 | // NOTE: In production environment, you should consider logging this to Azure 39 | // application insights. 40 | console.error(`\n [onTurnError] unhandled error: ${ error }`); 41 | 42 | // Send a trace activity, which will be displayed in Bot Framework Emulator 43 | await context.sendTraceActivity( 44 | 'OnTurnError Trace', 45 | `${ error }`, 46 | 'https://www.botframework.com/schemas/error', 47 | 'TurnError' 48 | ); 49 | 50 | // Send a message to the user 51 | await context.sendActivity('The bot encountered an error or bug.'); 52 | await context.sendActivity('To continue to run this bot, please fix the bot source code.'); 53 | }; 54 | 55 | // Set the onTurnError for the singleton BotFrameworkAdapter. 56 | adapter.onTurnError = onTurnErrorHandler; 57 | 58 | // Create the main dialog. Add LUIS to dialog 59 | 60 | const { LuisAppId, LuisAPIKey, LuisAPIHostName } = process.env; 61 | const luisConfig = { applicationId: LuisAppId, endpointKey: LuisAPIKey, endpoint: `https://${ LuisAPIHostName }` }; 62 | const luisRecognizer = new ContentRecognizer(luisConfig); 63 | const contentDialog = new ContentDialog(luisRecognizer); 64 | const myBot = new HTTPBot(conversationState, userState, contentDialog); 65 | 66 | // Listen for incoming requests. 67 | server.post('/api/messages', (req, res) => { 68 | adapter.processActivity(req, res, async (context) => { 69 | // Route to main dialog. 70 | await myBot.run(context); 71 | }); 72 | }); 73 | 74 | // Listen for Upgrade requests for Streaming. 75 | server.on('upgrade', (req, socket, head) => { 76 | // Create an adapter scoped to this WebSocket connection to allow storing session data. 77 | const streamingAdapter = new BotFrameworkAdapter({ 78 | appId: process.env.MicrosoftAppId, 79 | appPassword: process.env.MicrosoftAppPassword 80 | }); 81 | // Set onTurnError for the BotFrameworkAdapter created for each connection. 82 | streamingAdapter.onTurnError = onTurnErrorHandler; 83 | 84 | streamingAdapter.useWebSocket(req, socket, head, async (context) => { 85 | // After connecting via WebSocket, run this logic for every request sent over 86 | // the WebSocket connection. 87 | await myBot.run(context); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /LUISBot/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-chat-bot", 3 | "version": "1.0.0", 4 | "description": "Demonstrate the core capabilities of the Microsoft Bot Framework", 5 | "author": "Generated using Microsoft Bot Builder Yeoman generator v4.7.0", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "start": "node ./index.js", 10 | "watch": "nodemon ./index.js", 11 | "lint": "eslint .", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com" 17 | }, 18 | "dependencies": { 19 | "@microsoft/recognizers-text-suite": "^1.3.0", 20 | "botbuilder": "^4.19.2", 21 | "botbuilder-ai": "^4.20.0", 22 | "dotenv": "^8.2.0", 23 | "node-fetch": "^3.2.10", 24 | "path": "^0.12.7", 25 | "restify": "^8.4.1" 26 | }, 27 | "devDependencies": { 28 | "eslint": "^6.6.0", 29 | "eslint-config-standard": "^14.1.0", 30 | "eslint-plugin-import": "^2.18.2", 31 | "eslint-plugin-node": "^10.0.0", 32 | "eslint-plugin-promise": "^4.2.1", 33 | "eslint-plugin-standard": "^4.0.1", 34 | "nodemon": "~2.0.19" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LUISBot/node/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "metadata": { 5 | "comments": "This template was developed for demonstration purposes.", 6 | "description": "HTTP Triggered Logic App" 7 | }, 8 | "parameters": { 9 | "BotLogicAppName": { 10 | "defaultValue": "BotLogicApp", 11 | "type": "string", 12 | "metadata": { 13 | "description": "Name of the HTTP Triggered Logic App" 14 | } 15 | } 16 | }, 17 | "variables": {}, 18 | "resources": [ 19 | { 20 | "type": "Microsoft.Logic/workflows", 21 | "apiVersion": "2017-07-01", 22 | "name": "[parameters('BotLogicAppName')]", 23 | "location": "centralus", 24 | "properties": { 25 | "state": "Enabled", 26 | "definition": { 27 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", 28 | "contentVersion": "1.0.0.0", 29 | "parameters": {}, 30 | "triggers": { 31 | "manual": { 32 | "type": "Request", 33 | "kind": "Http", 34 | "inputs": { 35 | "method": "POST", 36 | "schema": { 37 | "properties": { 38 | "message": { 39 | "type": "string" 40 | }, 41 | "name": { 42 | "type": "string" 43 | } 44 | }, 45 | "type": "object" 46 | } 47 | } 48 | } 49 | }, 50 | "actions": {}, 51 | "outputs": {} 52 | }, 53 | "parameters": {} 54 | } 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bot Framework Chatbot Samples 2 | 3 | Collection of samples using the [Microsoft Bot Framework](https://dev.botframework.com?WT.mc_id=ca-github-jasmineg). 4 | 5 | ## Samples 6 | 7 | ### Http Bot 8 | 9 | Bot that send a user's responses to an HTTP endpoint. 10 | 11 | [Node](HttpBot/node) 12 | 13 | [.NET Core](HttpBot/dotnet_core) 14 | 15 | ### LUIS Bot 16 | 17 | Bot that returns search queries on Microsoft Docs and Samples. 18 | 19 | [Node](LUISBot/node) 20 | 21 | [.NET Core](LUISBot/dotnet_core) 22 | 23 | ## Prerequisites 24 | 25 | - Clone/Download this repo to your local machine. 26 | - [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) 27 | - [Node.js](https://nodejs.org) version 10.14.1 or higher 28 | OR 29 | - [.NET Core SDK](https://dotnet.microsoft.com/download?WT.mc_id=academic-0000-jasmineg) 30 | 31 | - [Azure Account](https://azure.microsoft.com/free/?WT.mc_id=academic-0000-jasmineg) 32 | - [Student? 🎓 Sign up for an Azure Student account!](https://azure.microsoft.com/free/students/?WT.mc_id=academic-0000-jasmineg) 33 | 34 | ### Testing the bot locally using Bot Framework Emulator 35 | 36 | The [Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. 37 | 38 | - Install the Bot Framework Emulator version 4.3.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) 39 | - Launch Bot Framework Emulator 40 | - File -> Open Bot 41 | - Enter Bot URL of `http://localhost:3978/api/messages` 42 | 43 | ## Optional: Deploy the bot to Azure 44 | 45 | To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. 46 | 47 | ## Learn More 48 | 49 | ### Concepts Used in This Demo 50 | 51 | - [Gathering Input Using Prompts](https://docs.microsoft.com/azure/bot-service/bot-builder-prompts?WT.mc_id=academic-0000-jasmineg) 52 | - [Activity processing](https://docs.microsoft.com/azure/bot-service/bot-builder-concept-activity-processing?WT.mc_id=academic-0000-jasmineg) 53 | - [Receive and respond to inbound HTTPS requests in Azure Logic Apps](https://docs.microsoft.com/azure/connectors/connectors-native-reqres?WT.mc_id=academic-0000-jasmineg#prerequisites?WT.mc_id=ca-github-jasmineg) 54 | 55 | ### General Resources 56 | 57 | - [Bot Framework Documentation](https://docs.botframework.com?WT.mc_id=ca-github-jasmineg) 58 | - [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?WT.mc_id=academic-0000-jasmineg) 59 | - [Channels and Bot Connector Service](https://docs.microsoft.com/azure/bot-service/bot-concepts?WT.mc_id=academic-0000-jasmineg) 60 | - [Language Understanding using LUIS](https://docs.microsoft.com/azure/cognitive-services/luis/?WT.mc_id=academic-0000-jasmineg) 61 | - [Overview - What is Azure Logic Apps?](https://docs.microsoft.com/azure/logic-apps/logic-apps-overview?WT.mc_id=academic-0000-jasmineg) 62 | -------------------------------------------------------------------------------- /img/logicapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paladique/AzureSample-HTTPBot/564360fc42ca807bee5249c03a43ef7e06f0efa6/img/logicapp.png -------------------------------------------------------------------------------- /template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "metadata": { 5 | "comments": "This template was developed for demo and sample purposes.", 6 | "description": "HTTP Triggered Logic App" 7 | }, 8 | "parameters": { 9 | "LogicAppName": { 10 | "defaultValue": "BotLogicApp", 11 | "type": "string", 12 | "metadata": { 13 | "description": "Name of the HTTP Triggered Logic App" 14 | } 15 | } 16 | }, 17 | "variables": {}, 18 | "resources": [ 19 | { 20 | "type": "Microsoft.Logic/workflows", 21 | "apiVersion": "2017-07-01", 22 | "name": "[parameters('LogicAppName')]", 23 | "location": "centralus", 24 | "properties": { 25 | "state": "Enabled", 26 | "definition": { 27 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", 28 | "contentVersion": "1.0.0.0", 29 | "parameters": {}, 30 | "triggers": { 31 | "manual": { 32 | "type": "Request", 33 | "kind": "Http", 34 | "inputs": { 35 | "method": "POST", 36 | "schema": { 37 | "properties": { 38 | "message": { 39 | "type": "string" 40 | }, 41 | "name": { 42 | "type": "string" 43 | } 44 | }, 45 | "type": "object" 46 | } 47 | } 48 | } 49 | }, 50 | "actions": {}, 51 | "outputs": {} 52 | }, 53 | "parameters": {} 54 | } 55 | } 56 | ] 57 | } --------------------------------------------------------------------------------