This commit is contained in:
Tom Laird-McConnell 2018-03-14 14:09:07 -07:00
Родитель 9aa251458f 716b0d575f
Коммит b053bc3949
194 изменённых файлов: 3485 добавлений и 3303 удалений

Просмотреть файл

@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Ai",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Ai.Tests", "tests\Microsoft.Bot.Builder.Ai.Tests\Microsoft.Bot.Builder.Ai.Tests.csproj", "{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Tests", "tests\Microsoft.Bot.Builder.Tests\Microsoft.Bot.Builder.Tests.csproj", "{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Azure.Tests", "tests\Microsoft.Bot.Builder.Azure.Tests\Microsoft.Bot.Builder.Azure.Tests.csproj", "{E325A0E2-716A-49E0-9767-5087CF05727C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AlarmBot", "Samples\AlarmBot\AlarmBot.csproj", "{AF1A1EAB-9427-4798-A356-65EB4B4BDFCA}"
@ -30,10 +28,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Core"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder", "libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj", "{ADA8AB8B-2066-4193-B8F7-985669B23E00}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.Connector.EchoBot", "samples\Microsoft.Bot.Samples.Connector.EchoBot\Microsoft.Bot.Samples.Connector.EchoBot.csproj", "{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Samples.EchoBot-AspNet461", "samples\Microsoft.Bot.Samples.EchoBot-AspNet461\Microsoft.Bot.Samples.EchoBot-AspNet461.csproj", "{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.EchoBot-Console", "samples\Microsoft.Bot.Samples.EchoBot-Console\Microsoft.Bot.Samples.EchoBot-Console.csproj", "{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Connector.Tests", "tests\Microsoft.Bot.Connector.Tests\Microsoft.Bot.Connector.Tests.csproj", "{BF414C86-DB3B-4022-9B29-DCE8AA954C12}"
@ -50,12 +44,28 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Promp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Prompts.Tests", "tests\Microsoft.Bot.Builder.Prompts.Tests\Microsoft.Bot.Builder.Prompts.Tests.csproj", "{5D145BFC-1C30-4FC5-989A-82260F8225BE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EchoBot", "samples\EchoBot\EchoBot.csproj", "{30B77905-0BAB-44C1-A011-0245F220C30C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.WebApi", "libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.WebApi\Microsoft.Bot.Builder.Integration.AspNet.WebApi.csproj", "{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Integration.AspNet.Core", "libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj", "{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.EchoBot", "samples\Microsoft.Bot.Samples.EchoBot\Microsoft.Bot.Samples.EchoBot.csproj", "{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.EchoBot-AspNetCore", "samples\Microsoft.Bot.Samples.EchoBot-AspNetCore\Microsoft.Bot.Samples.EchoBot-AspNetCore.csproj", "{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Samples.EchoBot-AspNetWebApi", "samples\Microsoft.Bot.Samples.EchoBot-AspNetWebApi\Microsoft.Bot.Samples.EchoBot-AspNetWebApi.csproj", "{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.Connector.EchoBot", "samples\Microsoft.Bot.Samples.Connector.EchoBot\Microsoft.Bot.Samples.Connector.EchoBot.csproj", "{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Core.Extensions", "libraries\Microsoft.Bot.Builder.Core.Extensions\Microsoft.Bot.Builder.Core.Extensions.csproj", "{183B3324-4CFF-477A-8EAE-73953D3E383D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Core.Tests", "tests\Microsoft.Bot.Builder.Core.Tests\Microsoft.Bot.Builder.Core.Tests.csproj", "{99100609-26D5-4BBD-ACD7-4CC810977A06}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Core.Extensions.Tests", "tests\Microsoft.Bot.Builder.Core.Extensions.Tests\Microsoft.Bot.Builder.Core.Extensions.Tests.csproj", "{6034B365-C87B-4A90-A8C7-F24374BFE2E7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TemplateManager", "libraries\Microsoft.Bot.Builder.TemplateManager\Microsoft.Bot.Builder.TemplateManager.csproj", "{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.TemplateManager.Tests", "tests\Microsoft.Bot.Builder.TemplateManager\Microsoft.Bot.Builder.TemplateManager.Tests.csproj", "{C93F6192-0123-4121-AD92-374A71E4B0F3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Classic", "Classic", "{2A46FEEF-4FD9-4DD5-8650-39C36CFDF2BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.Classic.Tests", "tests\Microsoft.Bot.Builder.Classic.Tests\Microsoft.Bot.Builder.Classic.Tests.csproj", "{508661A7-F47A-4D60-8ED6-69E378ED0E74}"
@ -82,10 +92,6 @@ Global
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C}.Release|Any CPU.Build.0 = Release|Any CPU
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E325A0E2-716A-49E0-9767-5087CF05727C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E325A0E2-716A-49E0-9767-5087CF05727C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -114,14 +120,6 @@ Global
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADA8AB8B-2066-4193-B8F7-985669B23E00}.Release|Any CPU.Build.0 = Release|Any CPU
{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B}.Release|Any CPU.Build.0 = Release|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Release|Any CPU.Build.0 = Release|Any CPU
{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -150,10 +148,6 @@ Global
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Release|Any CPU.Build.0 = Release|Any CPU
{30B77905-0BAB-44C1-A011-0245F220C30C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30B77905-0BAB-44C1-A011-0245F220C30C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30B77905-0BAB-44C1-A011-0245F220C30C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30B77905-0BAB-44C1-A011-0245F220C30C}.Release|Any CPU.Build.0 = Release|Any CPU
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -162,6 +156,42 @@ Global
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2}.Release|Any CPU.Build.0 = Release|Any CPU
{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E}.Release|Any CPU.Build.0 = Release|Any CPU
{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768}.Release|Any CPU.Build.0 = Release|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9}.Release|Any CPU.Build.0 = Release|Any CPU
{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B}.Release|Any CPU.Build.0 = Release|Any CPU
{183B3324-4CFF-477A-8EAE-73953D3E383D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{183B3324-4CFF-477A-8EAE-73953D3E383D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{183B3324-4CFF-477A-8EAE-73953D3E383D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{183B3324-4CFF-477A-8EAE-73953D3E383D}.Release|Any CPU.Build.0 = Release|Any CPU
{99100609-26D5-4BBD-ACD7-4CC810977A06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99100609-26D5-4BBD-ACD7-4CC810977A06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99100609-26D5-4BBD-ACD7-4CC810977A06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99100609-26D5-4BBD-ACD7-4CC810977A06}.Release|Any CPU.Build.0 = Release|Any CPU
{6034B365-C87B-4A90-A8C7-F24374BFE2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6034B365-C87B-4A90-A8C7-F24374BFE2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6034B365-C87B-4A90-A8C7-F24374BFE2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6034B365-C87B-4A90-A8C7-F24374BFE2E7}.Release|Any CPU.Build.0 = Release|Any CPU
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734}.Release|Any CPU.Build.0 = Release|Any CPU
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C93F6192-0123-4121-AD92-374A71E4B0F3}.Release|Any CPU.Build.0 = Release|Any CPU
{508661A7-F47A-4D60-8ED6-69E378ED0E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{508661A7-F47A-4D60-8ED6-69E378ED0E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{508661A7-F47A-4D60-8ED6-69E378ED0E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -182,7 +212,6 @@ Global
{B2C5EED9-21B2-4763-AB92-C1995B76DA3A} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{F31CF172-6FEE-4188-9828-E5FDA531C871} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{9BDF7020-A19F-4C6C-B329-E4BFEFF6DE6B} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{6AE5D88B-7F99-444E-ADA0-7CEAADFC477C} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{E325A0E2-716A-49E0-9767-5087CF05727C} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{AF1A1EAB-9427-4798-A356-65EB4B4BDFCA} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{3B5BFCCB-23CF-4849-8B2C-74D05DC3E402} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
@ -190,8 +219,6 @@ Global
{C1F54CDC-AD1D-45BB-8F7D-F49E411AFAF1} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{F0C150E2-9B8A-444C-B70E-97AD918CB3D4} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{ADA8AB8B-2066-4193-B8F7-985669B23E00} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{92DFB040-DC80-4AC7-A0CB-A2DDF4844B9B} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{BF414C86-DB3B-4022-9B29-DCE8AA954C12} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
@ -200,13 +227,17 @@ Global
{7BCEBDC1-D57F-4717-9B15-4FACD5473489} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{7A197F41-3411-47BF-87A6-5BC8A44CDB74} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{5D145BFC-1C30-4FC5-989A-82260F8225BE} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{30B77905-0BAB-44C1-A011-0245F220C30C} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{BD0B82EF-1601-4E87-B78A-B43DE7EB36B0} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
{053BD8B8-B5C1-4C45-81D4-C9BA8D5B3CE2} = {276EBE79-A13A-46BD-A566-B01DC0477A9B}
{2A46FEEF-4FD9-4DD5-8650-39C36CFDF2BB} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{508661A7-F47A-4D60-8ED6-69E378ED0E74} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{CDFEC7D6-847E-4C13-956B-0A960AE3EB60} = {2A46FEEF-4FD9-4DD5-8650-39C36CFDF2BB}
{12CAE029-7B8D-4928-8504-28746C36ADB3} = {2A46FEEF-4FD9-4DD5-8650-39C36CFDF2BB}
{3AA823E5-BA54-48E8-9FA6-D8F27C8D347E} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{BEDBA9E2-FE6E-44D9-914D-03AE63EF6768} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{AAC0F76C-4114-4D64-A99E-8BE4C43982F9} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{8D6F4046-0971-4E24-8E4D-F8175C6DFF2B} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
{183B3324-4CFF-477A-8EAE-73953D3E383D} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{99100609-26D5-4BBD-ACD7-4CC810977A06} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{6034B365-C87B-4A90-A8C7-F24374BFE2E7} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
{EED5F0D3-6F00-4ED1-9108-5ADCB10A3734} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
{C93F6192-0123-4121-AD92-374A71E4B0F3} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7173C9F3-A7F9-496E-9078-9156E35D6E16}

Просмотреть файл

@ -1,124 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Cognitive.LUIS;
namespace Microsoft.Bot.Builder.Ai
{
public class LuisRecognizerMiddleware : IntentRecognizerMiddleware
{
private readonly LuisClient _luisClient;
public LuisRecognizerMiddleware(string appId, string appKey) : base()
{
if (string.IsNullOrWhiteSpace(appId))
throw new ArgumentNullException(nameof(appId));
if (string.IsNullOrWhiteSpace(appKey))
throw new ArgumentNullException(nameof(appKey));
_luisClient = new LuisClient(appId, appKey);
SetupOnRecognize();
}
public LuisRecognizerMiddleware(string appId, string appKey, string baseUri) : base()
{
if (string.IsNullOrWhiteSpace(appId))
throw new ArgumentNullException(nameof(appId));
if (string.IsNullOrWhiteSpace(appKey))
throw new ArgumentNullException(nameof(appKey));
if (string.IsNullOrWhiteSpace(baseUri))
throw new ArgumentNullException(nameof(baseUri));
_luisClient = new LuisClient(appId, appKey, baseUri);
SetupOnRecognize();
}
private void SetupOnRecognize()
{
this.OnRecognize(async (context) =>
{
Intent i = await RecognizeAndMap(context.Request.AsMessageActivity()?.Text);
return new List<Intent>() { i };
});
}
private async Task<Intent> RecognizeAndMap(string utterance)
{
Intent intent = new Intent();
// LUIS client throws an exception on Predict is the utterance is null / empty
// so just skip those cases and return a non-match.
if (string.IsNullOrWhiteSpace(utterance))
{
intent.Name = string.Empty;
intent.Score = 0.0;
}
else
{
LuisResult result = await _luisClient.Predict(utterance);
if (result.TopScoringIntent == null)
{
intent.Name = string.Empty;
intent.Score = 0.0;
}
else
{
intent.Name = result.TopScoringIntent.Name;
intent.Score = result.TopScoringIntent.Score;
}
foreach (var luisEntityList in result.Entities.Values)
{
foreach (var luisEntity in luisEntityList)
{
intent.Entities.Add(new LuisEntity(luisEntity));
}
}
}
return intent;
}
}
public class LuisEntity : Entity
{
public LuisEntity()
{
}
public LuisEntity(Cognitive.LUIS.Entity luisEntity)
{
this.Type = luisEntity.Name;
this.Value = luisEntity.Value;
this.StartIndex = luisEntity.StartIndex;
this.EndIndex = luisEntity.EndIndex;
this.Resolution = new FlexObject();
if (luisEntity.Resolution != null)
{
foreach(var key in luisEntity.Resolution.Keys)
{
this.Resolution[key] = luisEntity.Resolution[key];
}
}
}
public string Type { get; set; }
public string Value { get; set; }
public int StartIndex { get; set; }
public int EndIndex { get; set; }
public FlexObject Resolution { get; set; }
}
}

Просмотреть файл

@ -37,12 +37,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Cognitive.LUIS" Version="2.0.2" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Bot.Builder.Core.Extensions\Microsoft.Bot.Builder.Core.Extensions.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
</ItemGroup>

Просмотреть файл

@ -5,12 +5,12 @@ using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Ai
{
public class QnAMakerMiddleware : Middleware.IReceiveActivity
public class QnAMakerMiddleware : IMiddleware
{
private readonly QnAMaker _qnaMaker;
private readonly QnAMakerMiddlewareOptions _options;
@ -22,7 +22,7 @@ namespace Microsoft.Bot.Builder.Ai
_qnaMaker = new QnAMaker(options, httpClient);
}
public async Task ReceiveActivity(IBotContext context, MiddlewareSet.NextDelegate next)
public async Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next)
{
if (context.Request.Type == ActivityTypes.Message)
{
@ -33,9 +33,9 @@ namespace Microsoft.Bot.Builder.Ai
if (results.Any())
{
if (!string.IsNullOrEmpty(_options.DefaultAnswerPrefixMessage))
context.Reply(_options.DefaultAnswerPrefixMessage);
context.Batch().Reply(_options.DefaultAnswerPrefixMessage);
context.Reply(results.First().Answer);
context.Batch().Reply(results.First().Answer);
if (_options.EndActivityRoutingOnAnswer)
//Question is answered, don't keep routing

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Bot.Builder.Core.Extensions;
namespace Microsoft.Bot.Builder.Ai
{

Просмотреть файл

@ -1,137 +1,139 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
using Microsoft.Cognitive.LUIS;
// Note: Commenting out until integration with revised LUIS Recognizer is completed.
namespace Microsoft.Bot.Builder.Ai
{
public class TranslationMiddleware : IReceiveActivity, ISendActivity
{
private LuisClient luisClient;
private string[] nativeLanguages;
private Translator translator;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Net.Http;
//using System.Text.RegularExpressions;
//using System.Threading.Tasks;
//using Microsoft.Bot.Builder.Middleware;
//using Microsoft.Bot.Schema;
//using Microsoft.Cognitive.LUIS;
public TranslationMiddleware(HttpClient httpClient, string[] nativeLanguages, string translatorKey, string luisAppId, string luisAccessKey)
{
this.nativeLanguages = nativeLanguages;
this.luisClient = new LuisClient(luisAppId, luisAccessKey);
this.translator = new Translator(translatorKey, httpClient);
}
//namespace Microsoft.Bot.Builder.Ai
//{
// public class TranslationMiddleware : IMiddleware
// {
// private LuisClient luisClient;
// private string[] nativeLanguages;
// private Translator translator;
/// <summary>
/// Incoming activity
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task ReceiveActivity(IBotContext context, MiddlewareSet.NextDelegate next)
{
IMessageActivity message = context.Request.AsMessageActivity();
if (message != null)
{
if (!String.IsNullOrWhiteSpace(message.Text))
{
// determine the language we are using for this conversation
var sourceLanguage = "en"; // context.Conversation.Data["Language"]?.ToString() ?? this.nativeLanguages.FirstOrDefault() ?? "en";
// public TranslationMiddleware(HttpClient httpClient, string[] nativeLanguages, string translatorKey, string luisAppId, string luisAccessKey)
// {
// this.nativeLanguages = nativeLanguages;
// this.luisClient = new LuisClient(luisAppId, luisAccessKey);
// this.translator = new Translator(translatorKey, httpClient);
// }
var translationContext = new TranslationContext
{
SourceText = message.Text,
SourceLanguage = sourceLanguage,
TargetLanguage = (this.nativeLanguages.Contains(sourceLanguage)) ? sourceLanguage : this.nativeLanguages.FirstOrDefault() ?? "en"
};
context.Set(translationContext);
// /// <summary>
// /// Incoming activity
// /// </summary>
// /// <param name="context"></param>
// /// <param name="token"></param>
// /// <returns></returns>
// public async Task ReceiveActivity(IBotContext context, MiddlewareSet.NextDelegate next)
// {
// IMessageActivity message = context.Request.AsMessageActivity();
// if (message != null)
// {
// if (!String.IsNullOrWhiteSpace(message.Text))
// {
// // determine the language we are using for this conversation
// var sourceLanguage = "en"; // context.Conversation.Data["Language"]?.ToString() ?? this.nativeLanguages.FirstOrDefault() ?? "en";
// translate to bots language
if (translationContext.SourceLanguage != translationContext.TargetLanguage)
await TranslateMessageAsync(context, message, translationContext.SourceLanguage, translationContext.TargetLanguage).ConfigureAwait(false);
// var translationContext = new TranslationContext
// {
// SourceText = message.Text,
// SourceLanguage = sourceLanguage,
// TargetLanguage = (this.nativeLanguages.Contains(sourceLanguage)) ? sourceLanguage : this.nativeLanguages.FirstOrDefault() ?? "en"
// };
// context.Set(translationContext);
}
}
await next().ConfigureAwait(false);
}
// // translate to bots language
// if (translationContext.SourceLanguage != translationContext.TargetLanguage)
// await TranslateMessageAsync(context, message, translationContext.SourceLanguage, translationContext.TargetLanguage).ConfigureAwait(false);
/// <summary>
/// outgoing activities
/// </summary>
/// <param name="context"></param>
/// <param name="activities"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task SendActivity(IBotContext context, IList<Activity> activities, MiddlewareSet.NextDelegate next)
{
foreach (var activity in activities)
{
IMessageActivity message = context.Request.AsMessageActivity();
if (!String.IsNullOrWhiteSpace(message?.Text))
{
// translate to userslanguage
var translationContext = context.Get<TranslationContext>();
if (translationContext.SourceLanguage != translationContext.TargetLanguage)
await TranslateMessageAsync(context, message, translationContext.TargetLanguage, translationContext.SourceLanguage).ConfigureAwait(false);
}
}
await next().ConfigureAwait(false);
}
// }
// }
// await next().ConfigureAwait(false);
// }
// /// <summary>
// /// outgoing activities
// /// </summary>
// /// <param name="context"></param>
// /// <param name="activities"></param>
// /// <param name="token"></param>
// /// <returns></returns>
// public async Task SendActivity(IBotContext context, IList<Activity> activities, MiddlewareSet.NextDelegate next)
// {
// foreach (var activity in activities)
// {
// IMessageActivity message = context.Request.AsMessageActivity();
// if (!String.IsNullOrWhiteSpace(message?.Text))
// {
// // translate to userslanguage
// var translationContext = context.Get<TranslationContext>();
// if (translationContext.SourceLanguage != translationContext.TargetLanguage)
// await TranslateMessageAsync(context, message, translationContext.TargetLanguage, translationContext.SourceLanguage).ConfigureAwait(false);
// }
// }
// await next().ConfigureAwait(false);
// }
private static readonly Regex UrlRegex = new Regex(@"(https?://[^\s]*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
// private static readonly Regex UrlRegex = new Regex(@"(https?://[^\s]*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
/// <summary>
/// Translate .Text field of a message
/// </summary>
/// <param name="message"></param>
/// <param name="targetLanguage"></param>
/// <returns></returns>
private async Task TranslateMessageAsync(IBotContext context, IMessageActivity message, string sourceLanguage, string targetLanguage)
{
// if we have text and a target language
if (!String.IsNullOrWhiteSpace(message.Text) && !String.IsNullOrEmpty(targetLanguage))
{
if (targetLanguage == sourceLanguage)
return;
// /// <summary>
// /// Translate .Text field of a message
// /// </summary>
// /// <param name="message"></param>
// /// <param name="targetLanguage"></param>
// /// <returns></returns>
// private async Task TranslateMessageAsync(IBotContext context, IMessageActivity message, string sourceLanguage, string targetLanguage)
// {
// // if we have text and a target language
// if (!String.IsNullOrWhiteSpace(message.Text) && !String.IsNullOrEmpty(targetLanguage))
// {
// if (targetLanguage == sourceLanguage)
// return;
var text = message.Text.Length <= 65536 ? message.Text : message.Text.Substring(0, 65536);
// var text = message.Text.Length <= 65536 ? message.Text : message.Text.Substring(0, 65536);
// massage mentions and urls so they don't get translated
int i = 0;
//foreach (var mention in message.Mentions)
//{
// text = text.Replace(mention.Text, $"{{{i++}}}");
//}
// // massage mentions and urls so they don't get translated
// int i = 0;
// //foreach (var mention in message.Mentions)
// //{
// // text = text.Replace(mention.Text, $"{{{i++}}}");
// //}
var urls = new List<string>();
while (UrlRegex.IsMatch(text))
{
var match = UrlRegex.Match(text);
urls.Add(match.Groups[0].Value);
text = text.Replace(match.Groups[0].Value, $"{{{i++}}}");
}
// var urls = new List<string>();
// while (UrlRegex.IsMatch(text))
// {
// var match = UrlRegex.Match(text);
// urls.Add(match.Groups[0].Value);
// text = text.Replace(match.Groups[0].Value, $"{{{i++}}}");
// }
string[] lines = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
var translateResult = await this.translator.TranslateArray(lines, sourceLanguage, targetLanguage).ConfigureAwait(false);
text = String.Join("\n", translateResult);
// string[] lines = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
// var translateResult = await this.translator.TranslateArray(lines, sourceLanguage, targetLanguage).ConfigureAwait(false);
// text = String.Join("\n", translateResult);
// restore mentions and urls
i = 0;
//foreach (var mention in message.Mentions)
//{
// text = text.Replace($"{{{i++}}}", mention.Text);
//}
foreach (var url in urls)
{
text = text.Replace($"{{{i++}}}", url);
}
// // restore mentions and urls
// i = 0;
// //foreach (var mention in message.Mentions)
// //{
// // text = text.Replace($"{{{i++}}}", mention.Text);
// //}
// foreach (var url in urls)
// {
// text = text.Replace($"{{{i++}}}", url);
// }
message.Text = text;
}
}
}
}
// message.Text = text;
// }
// }
// }
//}

Просмотреть файл

@ -7,6 +7,7 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Newtonsoft.Json;

Просмотреть файл

@ -43,6 +43,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Bot.Builder.Core.Extensions\Microsoft.Bot.Builder.Core.Extensions.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Connector\Microsoft.Bot.Connector.csproj" />
</ItemGroup>

Просмотреть файл

@ -144,7 +144,7 @@ namespace Microsoft.Bot.Builder.Classic.Dialogs.Internals
Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
{
// TODO, change this to context.SendActivity with M2 delta
return this.context.Adapter.SendActivities(this.context, new Activity[] { (Activity)message });
return this.context.Adapter.SendActivity(this.context, (Activity)message);
}
}

Просмотреть файл

@ -0,0 +1,187 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Core.Extensions
{
public class BatchOutputMiddleware : IMiddleware
{
public const string BatchOuputKey = "Extensions.Middleware.BatchOutput";
public async Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next)
{
BatchOutput batch = new BatchOutput();
if (context.Has(BatchOuputKey))
throw new InvalidOperationException("Batch Output already configured");
// Store this in the context so that the Extensio method can
// find it to return when folks say "context.Batch().Typing()".
context.Set(BatchOuputKey, batch);
await next().ConfigureAwait(false);
await batch.Flush(context);
}
}
public class BatchOutput
{
private IList<Activity> _activities = new List<Activity>();
public BatchOutput() { }
/// <summary>
/// Adds a delay to the batch.This can be used to pause after sending a typing indicator or
/// after sending a card with image(s).
///
/// Most chat clients download any images sent by the bot to a CDN which can delay the showing
/// of the message to the user. If a bot sends a message with only text immediately after
/// sending a message with images, the messages could end up being shown to the user out of
/// order. To help prevent this you can insert a delay of 2 seconds or so in between replies.
/// @param ms Number of milliseconds to pause before delivering the next activity in the batch.
/// </summary>
/// <param name="milliseconds">Number of milliseconds to pause before delivering the next activity in the batch</param>
public BatchOutput Delay(int milliseconds)
{
if (milliseconds < 0)
throw new ArgumentOutOfRangeException(nameof(milliseconds));
_activities.Add(new Activity
{
Type = ActivityTypesEx.Delay,
Value = milliseconds
});
return this;
}
/// <summary>
/// Adds an `endOfConversation` activity to the batch indicating that the bot has completed
/// it's current task or skill. For channels like Cortana this is used to tell Cortana that the
/// skill has completed and the skills window should close.
///
/// When used in conjunction with the `ConversationState` middleware, sending an `endOfConversation`
/// activity will cause the bots conversation state to be automatically cleared.If you're
/// building a Cortana skill this helps ensure that the next time your skill is invoked it
/// will be in a clean state given that you won't always get a new conversation ID in between
/// invocations.
///
/// Even for non-Cortana bots it's a good practice to send an `endOfConversation` anytime you
/// complete a task with the user as it will give your bot a chance to clear its conversation
/// state and helps avoid your bot getting into a bad state for a conversation.
/// </summary>
/// <param name="endOfConversationCode">(Optional) code to indicate why the bot/skill is ending. Defaults to
/// `EndOfConversationCodes.CompletedSuccessfully`.
/// </param>
public BatchOutput EndOfConversation(string endOfConversationCode = null)
{
if (string.IsNullOrWhiteSpace(endOfConversationCode))
endOfConversationCode = EndOfConversationCodes.CompletedSuccessfully;
_activities.Add(new Activity
{
Type = ActivityTypes.EndOfConversation,
Code = endOfConversationCode
});
return this;
}
/// <summary>
/// Adds an `event` activity to the batch. This is most useful for DirectLine and WebChat
/// channels as a way for the bot to send a custom named event to the client.
/// </summary>
/// <param name="name">Name of the event being sent.</param>
/// <param name="value">(Optional) value to include with the event.</param>
/// <returns></returns>
public BatchOutput Event(string name, object value = null)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullException(nameof(name));
_activities.Add(new Activity
{
Type = ActivityTypes.Event,
Name = name,
Value = value
});
return this;
}
public async Task Flush(IBotContext context)
{
// ToDo: addin the ResourceResponses when this is plumbed through
Activity[] toSend = _activities.ToArray();
_activities.Clear();
await context.SendActivity(toSend);
}
/// <summary>
/// Adds a Typing Activity to the Batch
/// </summary>
public BatchOutput Typing()
{
_activities.Add(new Activity(ActivityTypes.Typing));
return this;
}
public BatchOutput Activity(Activity activity)
{
if (activity == null)
throw new ArgumentNullException(nameof(activity));
_activities.Add(activity);
return this;
}
public BatchOutput Reply(IMessageActivity message)
{
if (message == null)
throw new ArgumentNullException(nameof(message));
_activities.Add((Activity)message);
return this;
}
public BatchOutput Reply(string text, string ssml = null, string inputHunt = null)
{
Activity a = MessageFactory.Text(text, ssml, inputHunt);
_activities.Add(a);
return this;
}
public BatchOutput Reply(Activity activity, string ssml = null, string inputHint = null)
{
BotAssert.ActivityNotNull(activity);
// If the Type isn't set, just set it to message
if (string.IsNullOrWhiteSpace(activity.Type))
activity.Type = ActivityTypes.Message;
// apply any SSML if it's been passed in
if (!string.IsNullOrWhiteSpace(ssml))
activity.Speak = ssml;
// apply the input hint if it's been passed in
if (!string.IsNullOrWhiteSpace(inputHint))
activity.InputHint = inputHint;
_activities.Add(activity);
return this;
}
}
public static class BatchOutputExtensions
{
public static BatchOutput Batch(this IBotContext context)
{
BatchOutput bo = context.Get<BatchOutput>(BatchOutputMiddleware.BatchOuputKey);
if (bo == null)
throw new InvalidOperationException("BatchOutputMiddleware does not appear to be setup.");
return bo;
}
}
}

Просмотреть файл

@ -6,7 +6,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder.Middleware
namespace Microsoft.Bot.Builder.Core.Extensions
{
public class StateSettings
{
@ -18,7 +18,7 @@ namespace Microsoft.Bot.Builder.Middleware
/// Abstract Base class which manages details of auto loading/saving of BotState
/// </summary>
/// <typeparam name="StateT"></typeparam>
public abstract class BotState<StateT> : IContextCreated, ISendActivity
public abstract class BotState<StateT> : IMiddleware
where StateT : class, new()
{
private readonly StateSettings _settings;
@ -40,30 +40,17 @@ namespace Microsoft.Bot.Builder.Middleware
_settings = settings ?? new StateSettings();
}
public async Task ContextCreated(IBotContext context, MiddlewareSet.NextDelegate next)
public async Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next)
{
await Read(context).ConfigureAwait(false);
await next().ConfigureAwait(false);
}
public async Task SendActivity(IBotContext context, IList<Activity> activities, MiddlewareSet.NextDelegate next)
{
if (_settings.WriteBeforeSend)
{
await Write(context).ConfigureAwait(false);
}
await next().ConfigureAwait(false);
if (!_settings.WriteBeforeSend)
{
await Write(context).ConfigureAwait(false);
}
await Write(context).ConfigureAwait(false);
}
protected virtual async Task<StoreItems> Read(IBotContext context)
{
var key = this._keyDelegate(context);
var keys = new List<String>();
keys.Add(key);
var keys = new List<String> { key };
var items = await _storage.Read(keys.ToArray());
var state = items.Get<StateT>(key);
if (state == null)
@ -95,7 +82,6 @@ namespace Microsoft.Bot.Builder.Middleware
await _storage.Write(changes).ConfigureAwait(false);
}
}
/// <summary>
@ -109,7 +95,7 @@ namespace Microsoft.Bot.Builder.Middleware
public ConversationState(IStorage storage, StateSettings settings = null) :
base(storage, PropertyName,
(context) => $"conversation/{context.ConversationReference.ChannelId}/{context.ConversationReference.Conversation.Id}",
(context) => $"conversation/{context.Request.ChannelId}/{context.Request.Conversation.Id}",
settings)
{
}
@ -134,7 +120,7 @@ namespace Microsoft.Bot.Builder.Middleware
public UserState(IStorage storage, StateSettings settings = null) :
base(storage,
PropertyName,
(context) => $"user/{context.ConversationReference.ChannelId}/{context.ConversationReference.User.Id}")
(context) => $"user/{context.Request.ChannelId}/{context.Request.From.Id}")
{
}

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
namespace Microsoft.Bot.Builder.Templates
{
public class TemplateIdMap : Dictionary<string, Func<IBotContext, dynamic, object>>
{
}
public class TemplateDictionary : Dictionary<string, TemplateIdMap>
{
}
/// <summary>
/// This is a simple template engine which has a resource map of template functions
/// let myTemplates = {
/// "en" : {
/// "templateId": (context, data) => $"your name is {data.name}",
/// "templateId": (context, data) => { return new Activity(); }
/// }`
/// }
/// }
/// To use, simply add to your pipeline
/// bot.use(new DictionaryTemplateEngine(myTemplates))
/// </summary>
//public class DictionaryRenderer : ITemplateRenderer, Middleware.IContextCreated
//{
// private TemplateDictionary languages;
// public DictionaryRenderer(TemplateDictionary templates)
// {
// this.languages = templates;
// }
// public async Task ContextCreated(IBotContext context, MiddlewareSet.NextDelegate next)
// {
// // context.TemplateManager.Register(this);
// await next().ConfigureAwait(false);
// }
// public Task<object> RenderTemplate(IBotContext context, string language, string templateId, object data)
// {
// if (this.languages.TryGetValue(language, out var templates))
// {
// if (templates.TryGetValue(templateId, out var template))
// {
// dynamic result = template(context, data);
// if (result != null)
// {
// return Task.FromResult(result as object);
// }
// }
// }
// return Task.FromResult((object)null);
// }
//}
}

Просмотреть файл

@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Collections.Generic;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
namespace Microsoft.Bot.Builder.Core.Extensions
{
public class Entity : FlexObject
{
public string GroupName { get; set; }
public double Score { get; set; }
public T ValueAs<T>()
{
string json = JsonConvert.SerializeObject(this["Value"]);
return JsonConvert.DeserializeObject<T>(json);
}
}
//public class EntityObject<T> : Entity
//{
//}
//public class RecognizerNumberOptions
//{
// public double? MinValue { get; set; }
// public double? MaxValue { get; set; }
// public bool? IntegersOnly { get; set; }
//}
//public class RecognizerValuesOptions
//{
// /// <summary>
// /// (Optional) if true, then only some of the tokens in a value need to exist to be considered
// /// a match.The default value is "false".
// /// </summary>
// public bool AllowPartialMatches { get; set; } = false;
// /// <summary>
// /// (Optional) maximum tokens allowed between two matched tokens in the utterance. So with
// /// a max distance of 2 the value "second last" would match the utternace "second from the last"
// /// but it wouldn't match "Wait a second. That's not the last one is it?".
// /// The default value is "2".
// /// </summary>
// public uint MaxTokenDistance { get; set; } = 2;
//}
//public class RecognizerChoicesOptions : RecognizerValuesOptions
//{
// public bool ExcludeValue { get; set; } = true;
// public bool ExcludeAction { get; set; } = true;
//}
//public class Choice
//{
// /// <summary>
// /// Value to return when selected
// /// </summary>
// public string Value { get; set; }
// /// <summary>
// /// (Optional) action to use when rendering the choice as a suggested action.
// /// </summary>
// public CardAction Action { get; set; } = null;
// /// <summary>
// /// (Optional) list of synonyms to recognize in addition to the value.
// /// </summary>
// public IList<string> Synonyms { get; set; } = new List<string>();
//}
//public class EntityRecognizers
//{
// public IList<EntityObject<string>> RecognizeLocalizedRegExp(BotContext context, string expresionId)
// {
// string locale = context.Request.Locale ?? "en";
// string utterance = (string.IsNullOrWhiteSpace(context.Request.Text)) ? string.Empty : context.Request.Text.Trim();
// LocalizedEntities rules = Locales.Find(locale);
// if (rules != null)
// {
// }
// }
//}
}

Просмотреть файл

@ -8,7 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Microsoft.Bot.Builder.Storage
namespace Microsoft.Bot.Builder.Core.Extensions
{
/// <summary>
/// Models IStorage around a File System
@ -126,7 +126,7 @@ namespace Microsoft.Bot.Builder.Storage
string path = Path.Combine(this.folder, key);
var oldTag = newStoreItem?.eTag;
if (newStoreItem != null)
newStoreItem.eTag = (this.eTag++).ToString();
newStoreItem.eTag = Guid.NewGuid().ToString("n");
var json = JsonConvert.SerializeObject(newValue, serializationSettings);
if (newStoreItem != null)
newStoreItem.eTag = oldTag;

Просмотреть файл

@ -8,7 +8,7 @@ using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
namespace Microsoft.Bot.Builder
namespace Microsoft.Bot.Builder.Core.Extensions
{
/// <summary>
/// DynamicObject which seemlessly blends dictionary properties with real properties
@ -96,8 +96,7 @@ namespace Microsoft.Bot.Builder
{
get
{
object value = null;
this.TryGetMember(name, out value);
this.TryGetMember(name, out object value);
return value;
}
set { this.TrySetMember(name, value); }

Просмотреть файл

@ -4,7 +4,7 @@
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder
namespace Microsoft.Bot.Builder.Core.Extensions
{
public interface IStorage
{

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder
namespace Microsoft.Bot.Builder.Core.Extensions
{
public interface IRecognizedIntents
{
@ -29,12 +29,9 @@ namespace Microsoft.Bot.Builder
public IList<Entity> Entities { get; } = new List<Entity>();
}
}
namespace Microsoft.Bot.Builder.Middleware
{
public class IntentRecognizerMiddleware : IReceiveActivity
public class IntentRecognizerMiddleware : IMiddleware
{
public delegate Task<Boolean> IntentDisabler(IBotContext context);
public delegate Task<IList<Intent>> IntentRecognizer(IBotContext context);
@ -51,7 +48,7 @@ namespace Microsoft.Bot.Builder.Middleware
/// <returns></returns>
public static IRecognizedIntents Get(IBotContext context) { return context.Get<IRecognizedIntents>(); }
public async Task ReceiveActivity(IBotContext context, MiddlewareSet.NextDelegate next)
public async Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next)
{
BotAssert.ContextNotNull(context);
@ -198,5 +195,4 @@ namespace Microsoft.Bot.Builder.Middleware
return string.IsNullOrWhiteSpace(s) ? string.Empty : s.Trim();
}
}
}
}

Просмотреть файл

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Microsoft.Bot.Builder
namespace Microsoft.Bot.Builder.Core.Extensions
{
public class LocalizedEntities
{

Просмотреть файл

@ -5,7 +5,7 @@ using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder.Storage
namespace Microsoft.Bot.Builder.Core.Extensions
{
/// <summary>
/// Models IStorage around a dictionary

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
namespace Microsoft.Bot.Builder.Core.Extensions
{
/// <summary>
/// A set of utility functions to assist with the formatting of the various

Просмотреть файл

@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">4.0.0-local</Version>
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<SignAssembly>true</SignAssembly>
<DelaySign>true</DelaySign>
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Microsoft.Bot.Builder.Core.Extensions</PackageId>
<Description>This library implements extensions for building bots using the Microsoft Bot Builder.</Description>
<Summary>This library implements extensions for building bots using the Microsoft Bot Builder.</Summary>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Company>Microsoft</Company>
<Authors>microsoft,BotFramework,nugetbotbuilder</Authors>
<Product>Microsoft Bot Builder SDK</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageProjectUrl>https://github.com/Microsoft/botbuilder-dotnet</PackageProjectUrl>
<PackageIconUrl>http://docs.botframework.com/images/bot_icon.png</PackageIconUrl>
<PackageLicenseUrl>https://github.com/Microsoft/BotBuilder/blob/master/LICENSE</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RepositoryUrl>https://github.com/Microsoft/botbuilder-dotnet</RepositoryUrl>
<LicenseUrl>https://github.com/Microsoft/BotBuilder-dotnet/blob/master/LICENSE</LicenseUrl>
<RepositoryType />
<PackageTags>bots;ai;botframework;botbuilder</PackageTags>
<NeutralLanguage />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1705;1998</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1705;1998;</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Text.RegularExpressions;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Middleware
namespace Microsoft.Bot.Builder.Core.Extensions
{
public class RegExpRecognizerSettings
{

Просмотреть файл

@ -2,10 +2,8 @@
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Adapters
@ -16,9 +14,9 @@ namespace Microsoft.Bot.Builder.Adapters
{
}
public ConsoleAdapter Use(IMiddleware middleware)
public new ConsoleAdapter Use(IMiddleware middleware)
{
base.RegisterMiddleware(middleware);
base.Use(middleware);
return this;
}
@ -47,7 +45,7 @@ namespace Microsoft.Bot.Builder.Adapters
}
}
public override async Task SendActivities(IBotContext context, IEnumerable<Activity> activities)
public override async Task SendActivity(IBotContext context, params Activity[] activities)
{
foreach (var activity in activities)
{
@ -87,7 +85,7 @@ namespace Microsoft.Bot.Builder.Adapters
throw new NotImplementedException();
}
public override Task DeleteActivity(IBotContext context, string conversationId, string activityId)
public override Task DeleteActivity(IBotContext context, ConversationReference reference)
{
throw new NotImplementedException();
}

Просмотреть файл

@ -6,7 +6,6 @@ using System.Linq;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
using System.Threading;
@ -39,9 +38,9 @@ namespace Microsoft.Bot.Builder.Adapters
public Queue<Activity> ActiveQueue { get { return botReplies; } }
public TestAdapter Use(IMiddleware middleware)
public new TestAdapter Use(IMiddleware middleware)
{
base.RegisterMiddleware(middleware);
base.Use(middleware);
return this;
}
@ -68,7 +67,7 @@ namespace Microsoft.Bot.Builder.Adapters
public ConversationReference ConversationReference { get; set; }
public async override Task SendActivities(IBotContext context, IEnumerable<Activity> activities)
public async override Task SendActivity(IBotContext context, params Activity[] activities)
{
foreach (var activity in activities)
{
@ -111,20 +110,19 @@ namespace Microsoft.Bot.Builder.Adapters
return Task.FromResult(new ResourceResponse());
}
public override Task DeleteActivity(IBotContext context, string conversationId, string activityId)
public override Task DeleteActivity(IBotContext context, ConversationReference reference)
{
lock (this.botReplies)
{
var replies = this.botReplies.ToList();
for (int i = 0; i < this.botReplies.Count; i++)
{
if (replies[i].Id == activityId)
if (replies[i].Id == reference.ActivityId)
{
replies.RemoveAt(i);
this.botReplies.Clear();
foreach (var item in replies)
this.botReplies.Enqueue(item);
break;
}
}

Просмотреть файл

@ -1,29 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
namespace Microsoft.Bot.Builder.Analytics
{
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class BotAnalyticsRecord : FlexObject
{
[JsonProperty("@id")]
public string id { get; set; }
[JsonProperty("@type")]
public string Type { get; set; } = "botAnalyticsRecord";
[JsonProperty("@context")]
public string Context { get; set; } = "http://www.microsoft.com/botFramework/schemas/analytics/v1";
public string BotId { get; set; }
public DateTime ReceivedAtDateTime { get; set; }
}
public interface IAnalyticsFacet
{
string FacetName { get; }
}
}

Просмотреть файл

@ -1,28 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Microsoft.Bot.Builder.Analytics
{
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class ConversationFacet : FlexObject, IAnalyticsFacet
{
[JsonProperty("@type")]
public string Type { get; set; } = "botConversation";
public string ConversationId { get; set; }
public int Turn { get; set; } = 0;
[JsonIgnore]
public string FacetName => "conversation";
}
public static class AnalyticsFacetExtensions
{
public static void AddToAnalyticsRecord(this IAnalyticsFacet facet, BotAnalyticsRecord record)
{
record[facet.FacetName] = facet;
}
}
}

Просмотреть файл

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
@ -24,13 +23,7 @@ namespace Microsoft.Bot.Builder
{
if (reference == null)
throw new ArgumentNullException(nameof(reference));
}
//public static void AdapterNotNull(ActivityAdapterBase adapter)
//{
// if (adapter == null)
// throw new ArgumentNullException(nameof(adapter));
//}
}
public static void ActivityListNotNull(IList<Activity> activityList)
{
@ -38,13 +31,13 @@ namespace Microsoft.Bot.Builder
throw new ArgumentNullException(nameof(activityList));
}
public static void MiddlewareNotNull(Middleware.IMiddleware middleware)
public static void MiddlewareNotNull(IMiddleware middleware)
{
if (middleware == null)
throw new ArgumentNullException(nameof(middleware));
}
public static void MiddlewareNotNull(Middleware.IMiddleware[] middleware)
public static void MiddlewareNotNull(IMiddleware[] middleware)
{
if (middleware == null)
throw new ArgumentNullException(nameof(middleware));

Просмотреть файл

@ -7,54 +7,48 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
{
public abstract class BotAdapter
{
protected readonly Middleware.MiddlewareSet _middlewareSet = new Middleware.MiddlewareSet();
protected readonly MiddlewareSet _middlewareSet = new MiddlewareSet();
public BotAdapter() : base()
{
this.RegisterMiddleware(new Middleware.BindOutoingResponsesMiddlware());
}
/// <summary>
/// Register middleware with the bot
/// </summary>
/// <param name="middleware"></param>
public void RegisterMiddleware(IMiddleware middleware)
public BotAdapter Use(IMiddleware middleware)
{
_middlewareSet.Use(middleware);
return this;
}
/// <summary>
/// implement send activities to the conversation
/// </summary>
/// <param name="context"></param>
/// <param name=""></param>
/// </summary>
/// <param name="activities">Set of activities being sent</param>
/// <returns></returns>
public abstract Task SendActivities(IBotContext context, IEnumerable<Activity> activities);
public abstract Task SendActivity(IBotContext context, params Activity[] activities);
/// <summary>
/// Implement updating an activity in the conversation
/// </summary>
/// <param name="context"></param>
/// <param name="activity"></param>
/// </summary>
/// <param name="activity">New replacement activity. The activity should already have it's ID information populated. </param>
/// <returns></returns>
public abstract Task<ResourceResponse> UpdateActivity(IBotContext context, Activity activity);
/// <summary>
/// Implement deleting an activity in the conversation
/// </summary>
/// <param name="context"></param>
/// <param name="conversationId"></param>
/// <param name="activityId"></param>
/// <param name="reference">Conversation reference of the activity being deleted. </param>
/// <returns></returns>
public abstract Task DeleteActivity(IBotContext context, string conversationId, string activityId);
public abstract Task DeleteActivity(IBotContext context, ConversationReference reference);
/// <summary>
@ -66,12 +60,7 @@ namespace Microsoft.Bot.Builder
protected async Task RunPipeline(IBotContext context, Func<IBotContext, Task> callback = null, CancellationTokenSource cancelToken = null)
{
BotAssert.ContextNotNull(context);
System.Diagnostics.Trace.TraceInformation($"Middleware: Beginning Pipeline for {context.ConversationReference.ActivityId}");
// Call any registered Middleware Components looking for ContextCreated()
await _middlewareSet.ContextCreated(context).ConfigureAwait(false);
// Call any registered Middleware Components looking for ReceiveActivity()
if (context.Request != null)
{
@ -85,16 +74,6 @@ namespace Microsoft.Bot.Builder
await callback(context).ConfigureAwait(false);
}
}
// Call any registered Middleware Components looking for SendActivity()
await _middlewareSet.SendActivity(context, context.Responses ?? new List<Activity>()).ConfigureAwait(false);
if (context.Responses != null)
{
await this.SendActivities(context, context.Responses).ConfigureAwait(false);
}
System.Diagnostics.Trace.TraceInformation($"Middleware: Ending Pipeline for {context.ConversationReference.ActivityId}");
}
@ -107,7 +86,7 @@ namespace Microsoft.Bot.Builder
/// <returns>task when completed</returns>
public virtual async Task CreateConversation(string channelId, Func<IBotContext, Task> callback)
{
throw new NotImplementedException();
throw new NotImplementedException("Adapter does not support CreateConversation with this arguments");
}
/// <summary>
@ -117,10 +96,10 @@ namespace Microsoft.Bot.Builder
/// <param name="reference">reference to create context around</param>
/// <param name="callback">callback where you can continue the conversation</param>
/// <returns>task when completed</returns>
public virtual async Task ContinueConversation(ConversationReference reference, Func<IBotContext, Task> callback)
public virtual Task ContinueConversation(ConversationReference reference, Func<IBotContext, Task> callback)
{
var context = new BotContext(this, reference);
await RunPipeline(context, callback).ConfigureAwait(false);
var context = new BotContext(this, reference.GetPostToBotMessage());
return RunPipeline(context, callback);
}
}
}

Просмотреть файл

@ -1,12 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Schema;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
{
@ -14,59 +13,243 @@ namespace Microsoft.Bot.Builder
{
private readonly BotAdapter _adapter;
private readonly Activity _request;
private readonly ConversationReference _conversationReference;
private IList<Activity> _responses = new List<Activity>();
private bool _responded = false;
private readonly IList<SendActivitiesHandler> _onSendActivities = new List<SendActivitiesHandler>();
private readonly IList<UpdateActivityHandler> _onUpdateActivity = new List<UpdateActivityHandler>();
private readonly IList<DeleteActivityHandler> _onDeleteActivity = new List<DeleteActivityHandler>();
private Dictionary<string, object> _services = new Dictionary<string, object>();
public BotContext(BotAdapter adapter, Activity request)
{
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
_request = request ?? throw new ArgumentNullException(nameof(request));
_conversationReference = new ConversationReference()
{
ActivityId = request.Id,
User = request.From,
Bot = request.Recipient,
Conversation = request.Conversation,
ChannelId = request.ChannelId,
ServiceUrl = request.ServiceUrl
};
}
public BotContext(BotAdapter adapter, ConversationReference conversationReference)
public IBotContext OnSendActivity(SendActivitiesHandler handler)
{
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
_conversationReference = conversationReference ?? throw new ArgumentNullException(nameof(conversationReference));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
_onSendActivities.Add(handler);
return this;
}
public IBotContext OnUpdateActivity(UpdateActivityHandler handler)
{
if (handler == null)
throw new ArgumentNullException(nameof(handler));
_onUpdateActivity.Add(handler);
return this;
}
public IBotContext OnDeleteActivity(DeleteActivityHandler handler)
{
if (handler == null)
throw new ArgumentNullException(nameof(handler));
_onDeleteActivity.Add(handler);
return this;
}
public BotAdapter Adapter => _adapter;
public Activity Request => _request;
public IList<Activity> Responses { get => _responses; set => this._responses = value; }
public ConversationReference ConversationReference { get => _conversationReference; }
public IBotContext Reply(string text, string speak = null)
/// <summary>
/// If true at least one response has been sent for the current turn of conversation.
/// </summary>
public bool Responded
{
var reply = this.ConversationReference.GetPostToUserMessage();
reply.Text = text;
if (!string.IsNullOrWhiteSpace(speak))
get { return _responded; }
set
{
// Developer included SSML to attach to the message.
reply.Speak = speak;
if (value == false)
{
throw new ArgumentException("TurnContext: cannot set 'responded' to a value of 'false'.");
}
_responded = true;
}
this.Responses.Add(reply);
return this;
}
public IBotContext Reply(IActivity activity)
public async Task SendActivity(params string[] textRepliesToSend)
{
if (textRepliesToSend == null)
throw new ArgumentNullException(nameof(textRepliesToSend));
List<Activity> newActivities = new List<Activity>();
foreach (string s in textRepliesToSend)
{
if (!string.IsNullOrWhiteSpace(s))
newActivities.Add(new Activity(ActivityTypes.Message) { Text = s });
}
await SendActivity(newActivities.ToArray());
}
public async Task SendActivity(params IActivity[] activities)
{
// Bind the relevant Conversation Reference properties, such as URLs and
// ChannelId's, to the activities we're about to send.
ConversationReference cr = GetConversationReference(this._request);
foreach (Activity a in activities)
{
ApplyConversationReference(a, cr);
}
// Convert the IActivities to Activies.
Activity[] activityArray = Array.ConvertAll(activities, (input) => (Activity)input);
// Create the list used by the recursive methods.
List<Activity> activityList = new List<Activity>(activityArray);
async Task ActuallySendStuff()
{
bool anythingToSend = false;
if (activities.Count() > 0)
anythingToSend = true;
// Send from the list, which may have been manipulated via the event handlers.
await this.Adapter.SendActivity(this, activityList.ToArray());
// If we actually sent something, set the flag.
if (anythingToSend)
this.Responded = true;
}
await SendActivitiesInternal(activityList, _onSendActivities, ActuallySendStuff);
}
/// <summary>
/// Replaces an existing activity.
/// </summary>
/// <param name="activity">New replacement activity. The activity should already have it's ID information populated</param>
public async Task UpdateActivity(IActivity activity)
{
Activity a = (Activity)activity;
async Task ActuallyUpdateStuff()
{
await this.Adapter.UpdateActivity(this, a);
}
await UpdateActivityInternal(a, _onUpdateActivity, ActuallyUpdateStuff);
}
public async Task DeleteActivity(string activityId)
{
if (string.IsNullOrWhiteSpace(activityId))
throw new ArgumentNullException(nameof(activityId));
ConversationReference cr = GetConversationReference(this.Request);
cr.ActivityId = activityId;
async Task ActuallyDeleteStuff()
{
await this.Adapter.DeleteActivity(this, cr);
}
await DeleteActivityInternal(cr, _onDeleteActivity, ActuallyDeleteStuff);
}
private async Task SendActivitiesInternal(
List<Activity> activities,
IEnumerable<SendActivitiesHandler> sendHandlers,
Func<Task> callAtBottom)
{
if (activities == null)
throw new ArgumentException(nameof(activities));
if (sendHandlers == null)
throw new ArgumentException(nameof(sendHandlers));
if (sendHandlers.Count() == 0) // No middleware to run.
{
if (callAtBottom != null)
await callAtBottom();
return;
}
// Default to "No more Middleware after this"
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IEnumerable<SendActivitiesHandler> remaining = sendHandlers.Skip(1);
await SendActivitiesInternal(activities, remaining, callAtBottom).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
SendActivitiesHandler caller = sendHandlers.First();
await caller(this, activities, next);
}
private async Task UpdateActivityInternal(Activity activity,
IEnumerable<UpdateActivityHandler> updateHandlers,
Func<Task> callAtBottom)
{
BotAssert.ActivityNotNull(activity);
this.Responses.Add((Activity)activity);
return this;
if (updateHandlers == null)
throw new ArgumentException(nameof(updateHandlers));
if (updateHandlers.Count() == 0) // No middleware to run.
{
if (callAtBottom != null)
{
await callAtBottom();
}
return;
}
// Default to "No more Middleware after this"
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IEnumerable<UpdateActivityHandler> remaining = updateHandlers.Skip(1);
await UpdateActivityInternal(activity, remaining, callAtBottom).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
UpdateActivityHandler toCall = updateHandlers.First();
await toCall(this, activity, next);
}
private async Task DeleteActivityInternal(ConversationReference cr,
IEnumerable<DeleteActivityHandler> updateHandlers,
Func<Task> callAtBottom)
{
BotAssert.ConversationReferenceNotNull(cr);
if (updateHandlers == null)
throw new ArgumentException(nameof(updateHandlers));
if (updateHandlers.Count() == 0) // No middleware to run.
{
if (callAtBottom != null)
{
await callAtBottom();
}
return;
}
// Default to "No more Middleware after this"
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IEnumerable<DeleteActivityHandler> remaining = updateHandlers.Skip(1);
await DeleteActivityInternal(cr, remaining, callAtBottom).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
DeleteActivityHandler toCall = updateHandlers.First();
await toCall(this, cr, next);
}
/// <summary>
/// Set the value associated with a key.
/// </summary>
@ -76,9 +259,10 @@ namespace Microsoft.Bot.Builder
{
if (String.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
lock (_services)
{
this._services[key] = value;
_services[key] = value;
}
}
@ -91,13 +275,81 @@ namespace Microsoft.Bot.Builder
{
if (String.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
object service = null;
lock (_services)
{
this._services.TryGetValue(key, out service);
_services.TryGetValue(key, out service);
}
return service;
}
}
/// <summary>
/// Determins if a key been set in the Cache
/// </summary>
/// <param name="key">The key of the value to get.</param>
/// <returns>True, if the key is found. False, if not.</returns>
public bool Has(string key)
{
if (String.IsNullOrWhiteSpace(key))
throw new ArgumentNullException(nameof(key));
lock (_services)
{
return _services.ContainsKey(key);
}
}
/// <summary>
/// Creates a Conversation Reference from an Activity
/// </summary>
/// <param name="activity">The activity to update. Existing values in the Activity will be overwritten.</param>
public static ConversationReference GetConversationReference(Activity activity)
{
BotAssert.ActivityNotNull(activity);
ConversationReference r = new ConversationReference
{
ActivityId = activity.Id,
User = activity.From,
Bot = activity.Recipient,
Conversation = activity.Conversation,
ChannelId = activity.ChannelId,
ServiceUrl = activity.ServiceUrl
};
return r;
}
/// <summary>
/// Updates an activity with the delivery information from a conversation reference. Calling
/// this after[getConversationReference()] (#getconversationreference) on an incoming activity
/// will properly address the reply to a received activity.
/// </summary>
/// <param name="a">Activity to copy delivery information to</param>
/// <param name="r">Conversation reference containing delivery information</param>
/// <param name="isIncoming">(Optional) flag indicating whether the activity is an incoming or outgoing activity. Defaults to `false` indicating the activity is outgoing.</param>
public static Activity ApplyConversationReference(Activity a, ConversationReference r, bool isIncoming = false)
{
a.ChannelId = r.ChannelId;
a.ServiceUrl = r.ServiceUrl;
a.Conversation = r.Conversation;
if (isIncoming)
{
a.From = r.User;
a.Recipient = r.Bot;
if (r.ActivityId != null)
a.Id = r.ActivityId;
}
else // Outoing
{
a.From = r.Bot;
a.Recipient = r.User;
if (r.ActivityId != null)
a.ReplyToId = r.ActivityId;
}
return a;
}
}
}

Просмотреть файл

@ -1,7 +1,5 @@
using Microsoft.Bot.Schema;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
{
@ -26,10 +24,8 @@ namespace Microsoft.Bot.Builder
public Activity Request => this._innerContext.Request;
public IList<Activity> Responses { get => this._innerContext.Responses; set => this._innerContext.Responses = value; }
public ConversationReference ConversationReference => this._innerContext.ConversationReference;
public bool Responded { get => _innerContext.Responded; set => _innerContext.Responded = value; }
/// <summary>
/// Get a value by a key.
/// </summary>
@ -40,18 +36,38 @@ namespace Microsoft.Bot.Builder
return this._innerContext.Get(key);
}
public IBotContext Reply(string text, string speak = null)
public Task SendActivity(params string[] textRepliesToSend)
{
this._innerContext.Reply(text, speak);
return this;
return _innerContext.SendActivity(textRepliesToSend);
}
public Task SendActivity(params IActivity[] activities)
{
return _innerContext.SendActivity(activities);
}
public IBotContext Reply(IActivity activity)
public Task UpdateActivity(IActivity activity)
{
this._innerContext.Reply(activity);
return this;
return _innerContext.UpdateActivity(activity);
}
public Task DeleteActivity(string activityId)
{
return _innerContext.DeleteActivity(activityId);
}
//public IBotContext Reply(string text, string speak = null)
//{
// this._innerContext.Reply(text, speak);
// return this;
//}
//public IBotContext Reply(IActivity activity)
//{
// this._innerContext.Reply(activity);
// return this;
//}
/// <summary>
/// Set the value associated with a key.
/// </summary>
@ -61,5 +77,28 @@ namespace Microsoft.Bot.Builder
{
this._innerContext.Set(key, value);
}
public bool Has(string key)
{
return this._innerContext.Has(key);
}
public IBotContext OnSendActivity(SendActivitiesHandler handler)
{
this._innerContext.OnSendActivity(handler);
return this;
}
public IBotContext OnUpdateActivity(UpdateActivityHandler handler)
{
this._innerContext.OnUpdateActivity(handler);
return this;
}
public IBotContext OnDeleteActivity(DeleteActivityHandler handler)
{
this._innerContext.OnDeleteActivity(handler);
return this;
}
}
}
}

Просмотреть файл

@ -1,27 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Schema;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder
{
public static class ContextExtensionMethods
{
public static IBotContext ShowTyping(this IBotContext context)
{
Activity activity = ((Activity)context.Request).CreateReply();
activity.Type = ActivityTypes.Typing;
return context.Reply((IActivity)activity);
}
public static IBotContext Delay(this IBotContext context, int duration)
{
Activity activity = ((Activity)context.Request).CreateReply();
activity.Type = ActivityTypesEx.Delay;
activity.Value = duration;
return context.Reply(activity);
}
}
}

Просмотреть файл

@ -1,89 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Collections.Generic;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
namespace Microsoft.Bot.Builder
{
public class Entity : FlexObject
{
public string GroupName { get; set; }
public double Score { get; set; }
public T ValueAs<T>()
{
string json = JsonConvert.SerializeObject(this["Value"]);
return JsonConvert.DeserializeObject<T>(json);
}
}
public class EntityObject<T> : Entity
{
}
public class RecognizerNumberOptions
{
public double? MinValue { get; set; }
public double? MaxValue { get; set; }
public bool? IntegersOnly { get; set; }
}
public class RecognizerValuesOptions
{
/// <summary>
/// (Optional) if true, then only some of the tokens in a value need to exist to be considered
/// a match.The default value is "false".
/// </summary>
public bool AllowPartialMatches { get; set; } = false;
/// <summary>
/// (Optional) maximum tokens allowed between two matched tokens in the utterance. So with
/// a max distance of 2 the value "second last" would match the utternace "second from the last"
/// but it wouldn't match "Wait a second. That's not the last one is it?".
/// The default value is "2".
/// </summary>
public uint MaxTokenDistance { get; set; } = 2;
}
public class RecognizerChoicesOptions : RecognizerValuesOptions
{
public bool ExcludeValue { get; set; } = true;
public bool ExcludeAction { get; set; } = true;
}
public class Choice
{
/// <summary>
/// Value to return when selected
/// </summary>
public string Value { get; set; }
/// <summary>
/// (Optional) action to use when rendering the choice as a suggested action.
/// </summary>
public CardAction Action { get; set; } = null;
/// <summary>
/// (Optional) list of synonyms to recognize in addition to the value.
/// </summary>
public IList<string> Synonyms { get; set; } = new List<string>();
}
//public class EntityRecognizers
//{
// public IList<EntityObject<string>> RecognizeLocalizedRegExp(BotContext context, string expresionId)
// {
// string locale = context.Request.Locale ?? "en";
// string utterance = (string.IsNullOrWhiteSpace(context.Request.Text)) ? string.Empty : context.Request.Text.Trim();
// LocalizedEntities rules = Locales.Find(locale);
// if (rules != null)
// {
// }
// }
//}
}

Просмотреть файл

@ -1,15 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Schema;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder
{
public delegate Task SendActivitiesHandler(IBotContext context, List<Activity> activities, Func<Task> next);
public delegate Task UpdateActivityHandler(IBotContext context, Activity activity, Func<Task> next);
public delegate Task DeleteActivityHandler(IBotContext context, ConversationReference reference, Func<Task> next);
public interface IBotContext
{
BotAdapter Adapter { get; }
@ -20,29 +22,15 @@ namespace Microsoft.Bot.Builder
Activity Request { get; }
/// <summary>
/// Respones
///
/// </summary>
IList<Activity> Responses { get; set; }
bool Responded { get; set; }
/// <summary>
/// Conversation reference
/// </summary>
ConversationReference ConversationReference { get; }
Task SendActivity(params string[] textRepliesToSend);
Task SendActivity(params IActivity[] activities);
/// <summary>
/// Queues a new "message" responses array.
/// </summary>
/// <param name="text">Text of a message to send to the user.</param>
/// <param name="speak">(Optional) SSML that should be spoken to the user on channels that support speech.</param>
/// <returns></returns>
IBotContext Reply(string text, string speak = null);
/// <summary>
/// Queues a new "message" responses array.
/// </summary>
/// <param name="activity">Activity object to send to the user.</param>
/// <returns></returns>
IBotContext Reply(IActivity activity);
Task UpdateActivity(IActivity activity);
Task DeleteActivity(string activityId);
/// <summary>
/// Set the value associated with a key.
@ -57,6 +45,16 @@ namespace Microsoft.Bot.Builder
/// <param name="key">The key of the value to get.</param>
/// <returns>The value.</returns>
object Get(string key);
/// <summary>
/// returns 'true' if Set has been called for a key
/// </summary>
/// <param name="key">The key to lookup in the cache</param>
bool Has(string key);
IBotContext OnSendActivity(SendActivitiesHandler handler);
IBotContext OnUpdateActivity(UpdateActivityHandler handler);
IBotContext OnDeleteActivity(DeleteActivityHandler handler);
}
public static partial class BotContextExtension

Просмотреть файл

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Threading.Tasks;
using static Microsoft.Bot.Builder.MiddlewareSet;
namespace Microsoft.Bot.Builder
{
public interface IMiddleware
{
Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next);
}
public class AnonymousReceiveMiddleware : IMiddleware
{
private readonly Func<IBotContext, NextDelegate, Task> _toCall;
public AnonymousReceiveMiddleware(Func<IBotContext, NextDelegate, Task> anonymousMethod)
{
_toCall = anonymousMethod ?? throw new ArgumentNullException(nameof(anonymousMethod));
}
public Task OnProcessRequest(IBotContext context, NextDelegate next)
{
return _toCall(context, next);
}
}
}

Просмотреть файл

@ -45,13 +45,8 @@
<NoWarn>1701;1702;1705;1998;</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Middleware\TemplateManager.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
</ItemGroup>

Просмотреть файл

@ -1,76 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Middleware
{
/// <summary>
/// Binds outgoing activities to a particular conversation.
/// As messages are sent during the Send pipeline, they must be
/// bound to the relvant ConversationReference object. This middleare
/// runs at the start of the Sending Pipeline and binds all outgoing
/// Activities to the ConversationRefernce on the Context.
/// </summary>
/// <remarks>
/// This Middleware component is automatically added to the Send Pipeline
/// when constructing a bot.
///
/// In terms of protocol level behavior, the binding of Actities to
/// a ConversationReference is similar to how the Node SDK applies the same
/// set of rules on all outbound Activities.
/// </remarks>
public class BindOutoingResponsesMiddlware : ISendActivity
{
public BindOutoingResponsesMiddlware()
{
}
public async Task SendActivity(IBotContext context, IList<Activity> activities, MiddlewareSet.NextDelegate next)
{
BotAssert.ContextNotNull(context);
BotAssert.ActivityListNotNull(activities);
foreach( var activity in activities)
{
if (string.IsNullOrWhiteSpace(activity.Type))
{
activity.Type = ActivityTypes.Message;
}
ApplyConversationReference(activity, context.ConversationReference);
}
await next().ConfigureAwait(false);
}
/// <summary>
/// Applies all relevant Conversation related identifies to an activity. This effectivly
/// couples a blank Activity to a conversation.
/// </summary>
/// <param name="activity">The activity to update. Existing values in the Activity will be overwritten.</param>
/// <param name="reference">The ConversationReference from which to pull the relevant conversation information</param>
/// <remarks>
/// This method applies the following values from ConversationReference:
/// ChannelId
/// ServiceUrl
/// Conversation
/// Bot (assigned to the .From property on the Activity)
/// User (assigned to the .Recipient on the Activity)
/// ActivityId (assigned as the ReplyToId on the Activity)
/// </remarks>
public static void ApplyConversationReference(IActivity activity, ConversationReference reference)
{
BotAssert.ActivityNotNull(activity);
BotAssert.ConversationReferenceNotNull(reference);
activity.ChannelId = reference.ChannelId;
activity.ServiceUrl = reference.ServiceUrl;
activity.Conversation = reference.Conversation;
activity.From = reference.Bot;
activity.Recipient = reference.User;
activity.ReplyToId = reference.ActivityId;
}
}
}

Просмотреть файл

@ -1,73 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Schema;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static Microsoft.Bot.Builder.Middleware.MiddlewareSet;
namespace Microsoft.Bot.Builder.Middleware
{
public interface IMiddleware { }
public interface IContextCreated : IMiddleware
{
Task ContextCreated(IBotContext context, NextDelegate next);
}
public interface IReceiveActivity : IMiddleware
{
Task ReceiveActivity(IBotContext context, NextDelegate next);
}
public interface ISendActivity : IMiddleware
{
Task SendActivity(IBotContext context, IList<Activity> activities, NextDelegate next);
}
public class AnonymousReceiveMiddleware : IReceiveActivity
{
private readonly Func<IBotContext, NextDelegate, Task> _toCall;
public AnonymousReceiveMiddleware(Func<IBotContext, NextDelegate, Task> anonymousMethod)
{
_toCall = anonymousMethod ?? throw new ArgumentNullException(nameof(anonymousMethod));
}
public Task ReceiveActivity(IBotContext context, NextDelegate next)
{
return _toCall(context, next);
}
}
public class AnonymousContextCreatedMiddleware : IContextCreated
{
private readonly Func<IBotContext, NextDelegate, Task> _toCall;
public AnonymousContextCreatedMiddleware(Func<IBotContext, NextDelegate, Task> anonymousMethod)
{
_toCall = anonymousMethod ?? throw new ArgumentNullException(nameof(anonymousMethod));
}
public Task ContextCreated(IBotContext context, NextDelegate next)
{
return _toCall(context, next);
}
}
public class AnonymousSendActivityMiddleware : ISendActivity
{
private readonly Func<IBotContext, IList<Activity>, NextDelegate, Task> _toCall;
public AnonymousSendActivityMiddleware(Func<IBotContext, IList<Activity>, NextDelegate, Task> anonymousMethod)
{
_toCall = anonymousMethod ?? throw new ArgumentNullException(nameof(anonymousMethod));
}
public Task SendActivity(IBotContext context, IList<Activity> activities, NextDelegate next)
{
return _toCall(context, activities, next);
}
}
}

Просмотреть файл

@ -1,142 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Middleware
{
public class MiddlewareSet : IMiddleware, IReceiveActivity, ISendActivity, IContextCreated
{
public delegate Task NextDelegate();
private readonly IList<IMiddleware> _middleware = new List<IMiddleware>();
public MiddlewareSet Use(IMiddleware middleware)
{
BotAssert.MiddlewareNotNull(middleware);
_middleware.Add(middleware);
return this;
}
public async Task ContextCreated(IBotContext context)
{
await ContextCreatedInternal(context, this._middleware.OfType<IContextCreated>().ToArray()).ConfigureAwait(false);
}
public async Task ContextCreated(IBotContext context, NextDelegate next)
{
await ContextCreatedInternal(context, this._middleware.OfType<IContextCreated>().ToArray()).ConfigureAwait(false);
}
private async Task ContextCreatedInternal(IBotContext context, IContextCreated[] middleware)
{
BotAssert.MiddlewareNotNull(middleware);
if (middleware.Length == 0) // No middleware to run.
return;
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IContextCreated[] remainingMiddleware = middleware.Skip(1).ToArray();
await ContextCreatedInternal(context, remainingMiddleware).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
await middleware[0].ContextCreated(context, next).ConfigureAwait(false);
}
public async Task ReceiveActivity(IBotContext context)
{
await ReceiveActivityInternal(context, this._middleware.OfType<IReceiveActivity>().ToArray(), null).ConfigureAwait(false);
}
public async Task ReceiveActivity(IBotContext context, NextDelegate next)
{
await ReceiveActivityInternal(context, this._middleware.OfType<IReceiveActivity>().ToArray(), null).ConfigureAwait(false);
await next().ConfigureAwait(false);
}
/// <summary>
/// Intended to be called from Bot, this method performs exactly the same as the
/// standard ReceiveActivity, except that it returns TRUE if all Middlware in the receive
/// pipeline was run, and FALSE if a middlware failed to run next.
/// </summary>
/// <returns>True, if all executed middleware in the pipeline called Next().
/// False, if one of the middleware instances did not call Next().
/// </returns>
public async Task ReceiveActivityWithStatus(IBotContext context, Func<IBotContext, Task> callback)
{
await ReceiveActivityInternal(context, this._middleware.OfType<IReceiveActivity>().ToArray(), callback).ConfigureAwait(false);
}
private async Task ReceiveActivityInternal(IBotContext context, IReceiveActivity[] middleware, Func<IBotContext, Task> callback)
{
BotAssert.MiddlewareNotNull(middleware);
if (middleware.Length == 0) // No middleware to run.
{
// If all the Middlware ran, the "leading edge" of the tree is now complete.
// This means it's time to run any developer specified callback.
// Once this callback is done, the "trailing edge" calls are then completed. This
// allows code that looks like:
// console.print("before");
// await next();
// console.print("after");
// to run as expected.
if (callback != null)
await callback(context);
return;
}
// Default to "No more Middleware after this"
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IReceiveActivity[] remainingMiddleware = middleware.Skip(1).ToArray();
await ReceiveActivityInternal(context, remainingMiddleware, callback).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
await middleware[0].ReceiveActivity(context, next).ConfigureAwait(false);
}
public async Task SendActivity(IBotContext context, IList<Activity> activities)
{
await SendActivityInternal(context, activities, this._middleware.OfType<ISendActivity>().ToArray()).ConfigureAwait(false);
}
public async Task SendActivity(IBotContext context, IList<Activity> activities, NextDelegate next)
{
await SendActivityInternal(context, activities, this._middleware.OfType<ISendActivity>().ToArray()).ConfigureAwait(false);
await next().ConfigureAwait(false);
}
private async Task SendActivityInternal(IBotContext context, IList<Activity> activities, ISendActivity[] middleware)
{
BotAssert.MiddlewareNotNull(middleware);
BotAssert.ActivityListNotNull(activities);
if (middleware.Length == 0) // No middleware to run.
return;
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
ISendActivity[] remainingMiddleware = middleware.Skip(1).ToArray();
await SendActivityInternal(context, activities, remainingMiddleware).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
await middleware[0].SendActivity(context, activities, next).ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -1,156 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
namespace Microsoft.Bot.Builder.Middleware
{
public class TemplateManager : IContextCreated, ISendActivity
{
public const string TEMPLATE = "template";
private List<ITemplateRenderer> _templateRenderers = new List<ITemplateRenderer>();
private List<string> _languageFallback = new List<string>();
public TemplateManager()
{
}
/// <summary>
/// Add a template engine for binding templates
/// </summary>
/// <param name="engine"></param>
public void Register(ITemplateRenderer engine)
{
if (!this._templateRenderers.Contains(engine))
this._templateRenderers.Add(engine);
}
/// <summary>
/// List registered template engines
/// </summary>
/// <returns></returns>
public IList<ITemplateRenderer> List()
{
return this._templateRenderers;
}
public void SetLanguagePolicy(IEnumerable<string> languageFallback)
{
this._languageFallback = new List<string>(languageFallback);
}
public IEnumerable<string> GetLanguagePolicy()
{
return this._languageFallback;
}
public async Task ContextCreated(IBotContext context, Middleware.MiddlewareSet.NextDelegate next)
{
((BotContext)context)[nameof(TemplateManager)] = this;
await next().ConfigureAwait(false);
}
public async Task SendActivity(IBotContext context, IList<IActivity> activities, Middleware.MiddlewareSet.NextDelegate next)
{
BotAssert.ContextNotNull(context);
BotAssert.ActivityListNotNull(activities);
// Ensure template activities are bound .
foreach (var activity in activities)
{
if (activity.Type == TEMPLATE)
{
await this.BindActivityTemplate(context, activity).ConfigureAwait(false);
}
}
await next().ConfigureAwait(false);
}
public async Task<Activity> FindAndApplyTemplate(IBotContext context, string language, string templateId, object data)
{
foreach (var renderer in this._templateRenderers)
{
object templateOutput = await renderer.RenderTemplate(context, language, templateId, data);
if (templateOutput != null)
{
if (templateOutput is string)
{
return new Activity(type: ActivityTypes.Message, text: (string)templateOutput);
}
else
{
return templateOutput as Activity;
}
}
}
return null;
}
public async Task BindActivityTemplate(IBotContext context, IActivity activity)
{
List<string> fallbackLocales = new List<string>(this._languageFallback);
string requestLocale = context.Request?.AsMessageActivity()?.Locale;
if (!String.IsNullOrEmpty(requestLocale))
{
fallbackLocales.Add(requestLocale);
}
fallbackLocales.Add("default");
// Ensure activities are well formed.
// bind any template activity
if (activity.Type == TemplateManager.TEMPLATE)
{
string messageText = ((Activity)activity).Text;
object messageValue = ((Activity)activity).Value;
// try each locale until successful
foreach (var locale in fallbackLocales)
{
// apply template
Activity boundActivity =
await this.FindAndApplyTemplate(context, locale, messageText, messageValue).ConfigureAwait(false);
if (boundActivity != null)
{
lock (activity)
{
foreach (var property in typeof(Activity).GetProperties())
{
var value = property.GetValue(boundActivity);
if (value != null)
property.SetValue(activity, value);
}
return;
}
}
}
throw new Exception($"Could not resolve template id:{ ((Activity)activity).Text}");
}
}
}
public class TemplateRendererMiddleware : Middleware.IContextCreated
{
private ITemplateRenderer _templateEngine;
public TemplateRendererMiddleware(ITemplateRenderer templateEngine)
{
_templateEngine = templateEngine;
}
public async Task ContextCreated(IBotContext context, Middleware.MiddlewareSet.NextDelegate next)
{
TemplateManager templateManager = (TemplateManager)((BotContext)context)[nameof(templateManager)];
templateManager.Register(_templateEngine);
await next().ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder
{
public class MiddlewareSet : IMiddleware
{
public delegate Task NextDelegate();
private readonly IList<IMiddleware> _middleware = new List<IMiddleware>();
public MiddlewareSet Use(IMiddleware middleware)
{
BotAssert.MiddlewareNotNull(middleware);
_middleware.Add(middleware);
return this;
}
public async Task ReceiveActivity(IBotContext context)
{
await ReceiveActivityInternal(context, _middleware, null).ConfigureAwait(false);
}
public async Task OnProcessRequest(IBotContext context, NextDelegate next)
{
await ReceiveActivityInternal(context, _middleware, null).ConfigureAwait(false);
await next().ConfigureAwait(false);
}
/// <summary>
/// Intended to be called from Bot, this method performs exactly the same as the
/// standard ReceiveActivity, except that it runs a user-defined delegate returns
/// if all Middlware in the receive pipeline was run.
/// </summary>
public async Task ReceiveActivityWithStatus(IBotContext context, Func<IBotContext, Task> callback)
{
await ReceiveActivityInternal(context, _middleware, callback).ConfigureAwait(false);
}
private static async Task ReceiveActivityInternal(
IBotContext context, IEnumerable<IMiddleware> middleware, Func<IBotContext, Task> callback)
{
if (middleware == null)
throw new ArgumentException(nameof(middleware));
if (middleware.Count() == 0) // No middleware to run.
{
// If all the Middlware ran, the "leading edge" of the tree is now complete.
// This means it's time to run any developer specified callback.
// Once this callback is done, the "trailing edge" calls are then completed. This
// allows code that looks like:
// console.print("before");
// await next();
// console.print("after");
// to run as expected.
if (callback != null)
await callback(context).ConfigureAwait(false);
return;
}
// Default to "No more Middleware after this"
async Task next()
{
// Remove the first item from the list of middleware to call,
// so that the next call just has the remaining items to worry about.
IEnumerable<IMiddleware> remainingMiddleware = middleware.Skip(1);
await ReceiveActivityInternal(context, remainingMiddleware, callback).ConfigureAwait(false);
}
// Grab the current middleware, which is the 1st element in the array, and execute it
await middleware.First().OnProcessRequest(context, next).ConfigureAwait(false);
}
}
}

Просмотреть файл

@ -5,7 +5,7 @@ namespace Microsoft.Bot.Builder.LUIS
{
public class LuisModel : ILuisModel
{
public LuisModel(string modelId, string subscriptionKey, Uri uriBase, LuisApiVersion apiVersion)
public LuisModel(string modelId, string subscriptionKey, Uri uriBase, LuisApiVersion apiVersion = LuisApiVersion.V2)
{
if(string.IsNullOrEmpty(modelId))
throw new ArgumentNullException(nameof(modelId));

Просмотреть файл

@ -49,6 +49,7 @@ namespace Microsoft.Bot.Builder.LUIS
var recognizerResult = new RecognizerResult
{
Text = request.Query,
AlteredText = luisResult.AlteredQuery,
Intents = GetIntents(luisResult),
Entities = GetEntitiesAndMetadata(luisResult.Entities, luisResult.CompositeEntities, verbose)
};
@ -206,7 +207,7 @@ namespace Microsoft.Bot.Builder.LUIS
/// </summary>
private static void AddProperty(JObject obj, string key, JToken value)
{
if (obj.ContainsKey(key))
if (((IDictionary<string, JToken>)obj).ContainsKey(key))
{
((JArray) obj[key]).Add(value);
}

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
using Microsoft.Cognitive.LUIS;
@ -15,7 +14,7 @@ namespace Microsoft.Bot.Builder.LUIS
/// This could eventually be generalized and moved to the core Bot Builder library
/// in order to support multiple recognizers
/// </summary>
public class LuisRecognizerMiddleware : IReceiveActivity
public class LuisRecognizerMiddleware : IMiddleware
{
public const string LuisRecognizerResultKey = "LuisRecognizerResult";
private readonly IRecognizer _luisRecognizer;
@ -28,7 +27,7 @@ namespace Microsoft.Bot.Builder.LUIS
_luisRecognizer = new LuisRecognizer(luisModel, luisRecognizerOptions, luisOptions);
}
public async Task ReceiveActivity(IBotContext context, MiddlewareSet.NextDelegate next)
public async Task OnProcessRequest(IBotContext context, MiddlewareSet.NextDelegate next)
{
BotAssert.ContextNotNull(context);

Просмотреть файл

@ -40,7 +40,7 @@
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.10" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -5,6 +5,7 @@ namespace Microsoft.Bot.Builder.LUIS
public class RecognizerResult
{
public string Text { set; get; }
public string AlteredText { set; get; }
public JObject Intents { get; set; }
public JObject Entities { get; set; }
}

Просмотреть файл

@ -0,0 +1,27 @@
using System;
namespace Microsoft.Bot.Builder.LUIS
{
public static class RecognizerResultExtensions
{
public static (string key, double score) GetTopScoringIntent(this RecognizerResult result)
{
if (result == null)
throw new ArgumentNullException(nameof(result));
if (result.Intents == null)
throw new ArgumentNullException(nameof(result.Intents));
var topIntent = (string.Empty, 0.0d);
foreach(var intent in result.Intents)
{
var score = (double) intent.Value;
if (score > topIntent.Item2)
{
topIntent = (intent.Key, score);
}
}
return topIntent;
}
}
}

Просмотреть файл

@ -16,8 +16,12 @@ namespace Microsoft.Bot.Builder.Prompts
public class AgePrompt : NumberWithUnitPrompt
{
public AgePrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
: base(NumberWithUnitRecognizer.Instance.GetAgeModel(culture), validator)
: base(new NumberWithUnitRecognizer(culture).GetAgeModel(), validator)
{
// ToDo: The creation of the new Recognizer is expensive given all of the
// Regex compilation in there. If we need to optimize this, we can add a static
// concurrent dictionary here based on culture. The model.parse() method called
// in the base class is thread safe.
}
protected AgePrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)

Просмотреть файл

@ -63,18 +63,19 @@ namespace Microsoft.Bot.Builder.Prompts
/// </summary>
public Task Prompt(IBotContext context, string text, string speak = null)
{
IMessageActivity activity = MessageFactory.Text(text, speak);
activity.InputHint = InputHints.ExpectingInput;
return Prompt(context, activity);
IMessageActivity ma = Activity.CreateMessageActivity();
ma.Text = !string.IsNullOrWhiteSpace(text) ? text : null;
ma.Speak = !string.IsNullOrWhiteSpace(speak) ? speak : null;
ma.InputHint = InputHints.ExpectingInput;
return Prompt(context, ma);
}
/// <summary>
/// Creates a new Message Activity, and queues it for sending to the user.
/// </summary>
public Task Prompt(IBotContext context, IMessageActivity activity)
{
context.Reply(activity);
return Task.CompletedTask;
public async Task Prompt(IBotContext context, IMessageActivity activity)
{
await context.SendActivity(activity);
}
/// <summary>

Просмотреть файл

@ -16,8 +16,12 @@ namespace Microsoft.Bot.Builder.Prompts
public class CurrencyPrompt : NumberWithUnitPrompt
{
public CurrencyPrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
: base(NumberWithUnitRecognizer.Instance.GetCurrencyModel(culture), validator)
: base(new NumberWithUnitRecognizer(culture).GetCurrencyModel(), validator)
{
// ToDo: The creation of the new Recognizer is expensive given all of the
// Regex compilation in there. If we need to optimize this, we can add a static
// concurrent dictionary here based on culture. The model.parse() method called
// in the base class is thread safe.
}
protected CurrencyPrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)

Просмотреть файл

@ -16,8 +16,12 @@ namespace Microsoft.Bot.Builder.Prompts
public class DimensionPrompt : NumberWithUnitPrompt
{
public DimensionPrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
: base(NumberWithUnitRecognizer.Instance.GetDimensionModel(culture), validator)
: base(new NumberWithUnitRecognizer(culture).GetDimensionModel(), validator)
{
// ToDo: The creation of the new Recognizer is expensive given all of the
// Regex compilation in there. If we need to optimize this, we can add a static
// concurrent dictionary here based on culture. The model.parse() method called
// in the base class is thread safe.
}
protected DimensionPrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)

Просмотреть файл

@ -38,14 +38,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Recognizers.Text.Number" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Recognizers.Text.NumberWithUnit" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Recognizers.Text.Sequence" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
<PackageReference Include="Microsoft.Recognizers.Text" Version="1.0.1" />
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.1" />
<PackageReference Include="Microsoft.Recognizers.Text.Number" Version="1.0.1" />
<PackageReference Include="Microsoft.Recognizers.Text.NumberWithUnit" Version="1.0.1" />
<PackageReference Include="Microsoft.Recognizers.Text.Sequence" Version="1.0.1" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.Bot.Builder.Prompts
public NumberPrompt(string culture, PromptValidator<NumberResult<T>> validator = null)
: base(validator)
{
_model = NumberRecognizer.Instance.GetNumberModel(culture);
_model = new NumberRecognizer(culture).GetNumberModel(culture);
}
protected NumberPrompt(IModel model, PromptValidator<NumberResult<T>> validator = null)

Просмотреть файл

@ -16,7 +16,7 @@ namespace Microsoft.Bot.Builder.Prompts
{
public OrdinalPrompt(string culture, PromptValidator<NumberResult<int>> validator = null)
: base(NumberRecognizer.Instance.GetOrdinalModel(culture), validator)
: base(new NumberRecognizer(culture).GetOrdinalModel(), validator)
{
}

Просмотреть файл

@ -19,7 +19,7 @@ namespace Microsoft.Bot.Builder.Prompts
public PercentagePrompt(string culture, PromptValidator<NumberResult<float>> validator = null)
: base( validator)
{
_model = NumberRecognizer.Instance.GetPercentageModel(culture);
_model = new NumberRecognizer(culture).GetPercentageModel();
}

Просмотреть файл

@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
@ -14,10 +15,14 @@ namespace Microsoft.Bot.Builder.Prompts
/// PhoneNumberPrompt recognizes phone numbers
/// </summary>
public class PhoneNumberPrompt : ValuePrompt
{
{
public PhoneNumberPrompt(string culture, PromptValidator<TextResult> validator = null) :
base(SequenceRecognizer.Instance.GetPhoneNumberModel(culture), validator)
base(new SequenceRecognizer(culture).GetPhoneNumberModel(), validator)
{
// ToDo: The creation of the new Recognizer is expensive given all of the
// Regex compilation in there. If we need to optimize this, we can add a static
// concurrent dictionary here based on culture. The model.parse() method called
// in the base class is thread safe.
}
protected PhoneNumberPrompt(IModel model, PromptValidator<TextResult> validator = null) :

Просмотреть файл

@ -27,7 +27,7 @@ namespace Microsoft.Bot.Builder.Prompts
public RangePrompt(string culture, PromptValidator<RangeResult> validator = null)
: base(validator)
{
_model = NumberRecognizer.Instance.GetNumberRangeModel(culture);
_model = new NumberRecognizer(culture).GetNumberRangeModel();
}
protected RangePrompt(IModel model, PromptValidator<RangeResult> validator = null)

Просмотреть файл

@ -16,7 +16,7 @@ namespace Microsoft.Bot.Builder.Prompts
public class TemperaturePrompt : NumberWithUnitPrompt
{
public TemperaturePrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
: base(NumberWithUnitRecognizer.Instance.GetTemperatureModel(culture), validator)
: base(new NumberWithUnitRecognizer(culture).GetTemperatureModel(), validator)
{
}

Просмотреть файл

@ -1,18 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Middleware;
namespace Microsoft.Bot.Builder.Templates
namespace Microsoft.Bot.Builder.TemplateManager
{
/// <summary>
/// Map of Template Ids-> Template Function()
/// </summary>
public class TemplateIdMap : Dictionary<string, Func<IBotContext, dynamic, object>>
{
}
public class TemplateDictionary : Dictionary<string, TemplateIdMap>
/// <summary>
/// Map of language -> template functions
/// </summary>
public class LanguageTemplateDictionary : Dictionary<string, TemplateIdMap>
{
}
@ -25,22 +28,16 @@ namespace Microsoft.Bot.Builder.Templates
/// }`
/// }
/// }
/// To use, simply add to your pipeline
/// bot.use(new DictionaryTemplateEngine(myTemplates))
/// To use, simply register with templateManager
/// templateManager.Register(new DictionaryRenderer(myTemplates))
/// </summary>
public class DictionaryRenderer : ITemplateRenderer, Middleware.IContextCreated
public class DictionaryRenderer : ITemplateRenderer
{
private TemplateDictionary languages;
private LanguageTemplateDictionary languages;
public DictionaryRenderer(TemplateDictionary templates)
public DictionaryRenderer(LanguageTemplateDictionary templates)
{
this.languages = templates;
}
public async Task ContextCreated(IBotContext context, MiddlewareSet.NextDelegate next)
{
// context.TemplateManager.Register(this);
await next().ConfigureAwait(false);
}
public Task<object> RenderTemplate(IBotContext context, string language, string templateId, object data)
@ -60,5 +57,4 @@ namespace Microsoft.Bot.Builder.Templates
return Task.FromResult((object)null);
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder.TemplateManager
{
/// <summary>
/// Defines interface for data binding to template and rendering a string
/// </summary>
public interface ITemplateRenderer
{
/// <summary>
/// render a template to an activity or string
/// </summary>
/// <param name="context">context</param>
/// <param name="language">language to render</param>
/// <param name="templateId">tenmplate to render</param>
/// <param name="data">data object to use to render</param>
/// <returns></returns>
Task<object> RenderTemplate(IBotContext context, string language, string templateId, object data);
}
}

Просмотреть файл

@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">4.0.0-local</Version>
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
<PackageVersion Condition=" '$(PackageVersion)' == '' ">4.0.0-local</PackageVersion>
<PackageVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)</PackageVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<SignAssembly>true</SignAssembly>
<DelaySign>true</DelaySign>
<AssemblyOriginatorKeyFile>..\..\build\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Microsoft.Bot.Builder.TemplateManager</PackageId>
<Description>This library implements .NET TemplateManager classes to manage libraries of template renderers in Microsoft Bot Builder SDK v4</Description>
<Summary>This library implements .NET TemplateManager classes to manage libraries of template renderers in Microsoft Bot Builder SDK v4</Summary>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Company>Microsoft</Company>
<Authors>microsoft,BotFramework,nugetbotbuilder</Authors>
<Product>Microsoft Bot Builder SDK</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageProjectUrl>https://github.com/Microsoft/botbuilder-dotnet</PackageProjectUrl>
<PackageIconUrl>http://docs.botframework.com/images/bot_icon.png</PackageIconUrl>
<PackageLicenseUrl>https://github.com/Microsoft/BotBuilder/blob/master/LICENSE</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RepositoryUrl>https://github.com/Microsoft/botbuilder-dotnet</RepositoryUrl>
<LicenseUrl>https://github.com/Microsoft/BotBuilder-dotnet/blob/master/LICENSE</LicenseUrl>
<RepositoryType />
<PackageTags>bots;ai;botframework;botbuilder</PackageTags>
<NeutralLanguage />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Builder.Core" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' == '' " Version="4.0.0-local" />
<PackageReference Include="Microsoft.Bot.Schema" Condition=" '$(PackageVersion)' != '' " Version="$(PackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,119 @@
using Microsoft.Bot.Schema;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder.TemplateManager
{
/// <summary>
/// TemplateManager manages set of ITemplateRenderer implementations
/// </summary>
/// <remarks>
/// ITemplateRenderer implements
/// </remarks>
public class TemplateManager
{
private List<ITemplateRenderer> _templateRenderers = new List<ITemplateRenderer>();
private List<string> _languageFallback = new List<string>();
public TemplateManager()
{
}
/// <summary>
/// Add a template engine for binding templates
/// </summary>
/// <param name="renderer"></param>
public TemplateManager Register(ITemplateRenderer renderer)
{
if (!this._templateRenderers.Contains(renderer))
this._templateRenderers.Add(renderer);
return this;
}
/// <summary>
/// List registered template engines
/// </summary>
/// <returns></returns>
public IList<ITemplateRenderer> List()
{
return this._templateRenderers;
}
public void SetLanguagePolicy(IEnumerable<string> languageFallback)
{
this._languageFallback = new List<string>(languageFallback);
}
public IEnumerable<string> GetLanguagePolicy()
{
return this._languageFallback;
}
/// <summary>
/// Send a reply with the template
/// </summary>
/// <param name="context"></param>
/// <param name="language"></param>
/// <param name="templateId"></param>
/// <param name="data"></param>
/// <returns></returns>
public async Task ReplyWith(IBotContext context, string templateId, object data = null)
{
BotAssert.ContextNotNull(context);
// apply template
Activity boundActivity = await this.RenderTemplate(context, context.Request?.AsMessageActivity()?.Locale, templateId, data).ConfigureAwait(false);
if (boundActivity != null)
{
await context.SendActivity(boundActivity);
return;
}
return;
}
/// <summary>
/// Render the template
/// </summary>
/// <param name="context"></param>
/// <param name="language"></param>
/// <param name="templateId"></param>
/// <param name="data"></param>
/// <returns></returns>
public async Task<Activity> RenderTemplate(IBotContext context, string language, string templateId, object data = null)
{
List<string> fallbackLocales = new List<string>(this._languageFallback);
if (!String.IsNullOrEmpty(language))
{
fallbackLocales.Add(language);
}
fallbackLocales.Add("default");
// try each locale until successful
foreach (var locale in fallbackLocales)
{
foreach (var renderer in this._templateRenderers)
{
object templateOutput = await renderer.RenderTemplate(context, locale, templateId, data);
if (templateOutput != null)
{
if (templateOutput is string)
{
return new Activity(type: ActivityTypes.Message, text: (string)templateOutput);
}
else
{
return templateOutput as Activity;
}
}
}
}
return null;
}
}
}

Просмотреть файл

@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder.BotFramework;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Bot.Schema;
@ -46,7 +44,7 @@ namespace Microsoft.Bot.Builder.Adapters
{
}
public BotFrameworkAdapter Use(Middleware.IMiddleware middleware)
public new BotFrameworkAdapter Use(IMiddleware middleware)
{
base._middlewareSet.Use(middleware);
return this;
@ -64,7 +62,7 @@ namespace Microsoft.Bot.Builder.Adapters
await base.RunPipeline(context, callback).ConfigureAwait(false);
}
public async override Task SendActivities(IBotContext context, IEnumerable<Activity> activities)
public override async Task SendActivity(IBotContext context, params Activity[] activities)
{
foreach (var activity in activities)
{
@ -91,11 +89,38 @@ namespace Microsoft.Bot.Builder.Adapters
return await connectorClient.Conversations.UpdateActivityAsync((Activity)activity);
}
public override async Task DeleteActivity(IBotContext context, string conversationId, string activityId)
public override async Task DeleteActivity(IBotContext context, ConversationReference reference)
{
MicrosoftAppCredentials appCredentials = await GetAppCredentials((context as BotFrameworkBotContext).BotAppId);
var connectorClient = new ConnectorClient(new Uri(context.Request.ServiceUrl), appCredentials);
await connectorClient.Conversations.DeleteActivityAsync(conversationId, activityId);
await connectorClient.Conversations.DeleteActivityAsync(reference.Conversation.Id, reference.ActivityId);
}
/// <summary>
/// Create a conversation on the Bot Framework for the given serviceUrl
/// </summary>
/// <param name="serviceUrl">serviceUrl you want to use</param>
/// <param name="credentials">credentials</param>
/// <param name="conversationParameters">arguments for the conversation you want to create</param>
/// <param name="callback">callback which will have the context.Request.Conversation.Id in it</param>
/// <returns></returns>
public virtual async Task CreateConversation(string channelId, string serviceUrl, MicrosoftAppCredentials credentials, ConversationParameters conversationParameters, Func<IBotContext, Task> callback)
{
var connectorClient = new ConnectorClient(new Uri(serviceUrl), credentials);
var result = await connectorClient.Conversations.CreateConversationAsync(conversationParameters);
// create conversation Update to represent the result of creating the conversation
var conversationUpdate = Activity.CreateConversationUpdateActivity();
conversationUpdate.ChannelId = channelId;
conversationUpdate.TopicName = conversationParameters.TopicName;
conversationUpdate.ServiceUrl = serviceUrl;
conversationUpdate.MembersAdded = conversationParameters.Members;
conversationUpdate.Id = result.ActivityId ?? Guid.NewGuid().ToString("n");
conversationUpdate.Conversation = new ConversationAccount(id: result.Id);
conversationUpdate.Recipient = conversationParameters.Bot;
BotContext context = new BotContext(this, (Activity)conversationUpdate);
await this.RunPipeline(context, callback);
}
/// <summary>

Просмотреть файл

@ -6,7 +6,7 @@ namespace Microsoft.Bot.Schema
/// <summary>
/// GeoCoordinates extensions
/// </summary>
public partial class GeoCoordinates
public partial class GeoCoordinates : Entity
{
partial void CustomInit()
{

Просмотреть файл

@ -1,22 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.
//
// Licensed under the MIT License.
namespace Microsoft.Bot.Schema
{
using Newtonsoft.Json;
using System.Linq;
/// <summary>
/// Mention information (entity type: "mention")
/// GeoCoordinates extensions
/// </summary>
public partial class Mention : Entity
{
partial void CustomInit()
{
this.Type = "mention";
Type = "Mention";
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Bot.Schema
{
/// <summary>
/// GeoCoordinates extensions
/// </summary>
public partial class Place : Entity
{
partial void CustomInit()
{
Type = "Place";
}
}
}

Просмотреть файл

@ -2,22 +2,22 @@
// Licensed under the MIT License.
using System.Collections.Generic;
using BotMiddleware = Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector.Authentication;
namespace Microsoft.Bot.Builder.Integration.AspNet.Core
{
public class BotFrameworkOptions
{
private readonly List<BotMiddleware.IMiddleware> _middleware;
private readonly List<IMiddleware> _middleware;
public BotFrameworkOptions()
{
_middleware = new List<BotMiddleware.IMiddleware>();
_middleware = new List<IMiddleware>();
}
public ICredentialProvider CredentialProvider { get; set; }
public IList<BotMiddleware.IMiddleware> Middleware { get => _middleware; }
public IList<IMiddleware> Middleware { get => _middleware; }
public bool EnableProactiveMessages { get; set; }
}
}

Просмотреть файл

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder.Middleware;
using System.Collections.Generic;
namespace Microsoft.Bot.Builder.Integration.AspNet.Core

Просмотреть файл

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder;
using System;
using Microsoft.Bot.Connector.Authentication;

Просмотреть файл

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector.Authentication;
using System.Collections.Generic;

Просмотреть файл

@ -21,7 +21,7 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi.Handlers
SerializerSettings =
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Newtonsoft.Json.Formatting.Indented,
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
}
}

Просмотреть файл

@ -20,7 +20,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AdaptiveCards" Version="0.5.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
@ -30,6 +30,8 @@
<ItemGroup>
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core.Extensions\Microsoft.Bot.Builder.Core.Extensions.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Connector\Microsoft.Bot.Connector.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />

Просмотреть файл

@ -5,7 +5,7 @@ using AlarmBot.Models;
using AlarmBot.Topics;
using Microsoft.Bot;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using System.Threading.Tasks;
namespace AlarmBot
@ -43,4 +43,4 @@ namespace AlarmBot
}
}
}
}
}

Просмотреть файл

@ -16,8 +16,8 @@ namespace AlarmBot
{
IList<DateTime> times = new List<DateTime>();
// Get DateTime model for English
var model = DateTimeRecognizer.GetInstance().GetDateTimeModel(((Activity)context.Request).Locale ?? "en-us");
var results = model.Parse(((Activity)context.Request).Text);
var model = new DateTimeRecognizer(context.Request.Locale ?? "en-us").GetDateTimeModel();
var results = model.Parse(context.Request.Text);
// Check there are valid results
if (results.Any() && results.First().TypeName.StartsWith("datetimeV2"))

Просмотреть файл

@ -2,9 +2,6 @@
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AlarmBot.Models
{
@ -16,5 +13,4 @@ namespace AlarmBot.Models
public string Title { get; set; }
public DateTimeOffset? Time { get; set; }
}
}

Просмотреть файл

@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
using System.Collections.Generic;
namespace AlarmBot.Models
@ -16,7 +16,7 @@ namespace AlarmBot.Models
}
/// <summary>
/// object persisted as user state
/// Object persisted as user state
/// </summary>
public class UserData : StoreItem
{

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using AdaptiveCards;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace AlarmBot.Responses
@ -48,31 +49,31 @@ namespace AlarmBot.Responses
public static void ReplyWithStartTopic(IBotContext context, dynamic data)
{
context.Reply(AlarmCardEditor(context, data, "Adding Alarm", "Please describe your alarm:", "Submit", "Cancel"));
context.Batch().Reply(AlarmCardEditor(context, data, "Adding Alarm", "Please describe your alarm:", "Submit", "Cancel"));
}
public static void ReplyWithHelp(IBotContext context, dynamic data)
{
context.Reply(AlarmCardEditor(context, data, "Adding alarm", $"I am working with you to create an alarm. Please describe your alarm:.\n\n", "Submit", "Cancel"));
context.Batch().Reply(AlarmCardEditor(context, data, "Adding alarm", $"I am working with you to create an alarm. Please describe your alarm:.\n\n", "Submit", "Cancel"));
}
public static void ReplyWithConfused(IBotContext context, dynamic data)
{
context.Reply($"I am sorry, I didn't understand: {((Activity)context.Request).Text}.");
context.Batch().Reply($"I am sorry, I didn't understand: {((Activity)context.Request).Text}.");
}
public static void ReplyWithCancelPrompt(IBotContext context, dynamic data)
{
context.Reply(TopicResponseHelpers.CreateMessageBoxCard(context, CANCELPROMPT, "Cancel Alarm?", "Are you sure you want to cancel this alarm?", "Yes", "No"));
context.Batch().Reply(TopicResponseHelpers.CreateMessageBoxCard(context, CANCELPROMPT, "Cancel Alarm?", "Are you sure you want to cancel this alarm?", "Yes", "No"));
}
public static void ReplyWithCancelReprompt(IBotContext context, dynamic data)
{
context.Reply(TopicResponseHelpers.CreateMessageBoxCard(context, CANCELPROMPT, "Cancel Alarm?", "Please answer with a Yes or No. Are you sure you want to cancel this alarm?", "Yes", "No"));
context.Batch().Reply(TopicResponseHelpers.CreateMessageBoxCard(context, CANCELPROMPT, "Cancel Alarm?", "Please answer with a Yes or No. Are you sure you want to cancel this alarm?", "Yes", "No"));
}
public static void ReplyWithTopicCanceled(IBotContext context, dynamic data)
{
context.Reply($"OK, I have canceled creating this alarm.");
context.Batch().Reply($"OK, I have canceled creating this alarm.");
}
public static void ReplyWithAddedAlarm(IBotContext context, dynamic data)
{
context.Reply($"OK, I have added the alarm {((Alarm)data).Title}.");
context.Batch().Reply($"OK, I have added the alarm {((Alarm)data).Title}.");
}
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using Microsoft.Bot.Schema;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
namespace AlarmBot.Responses
{
@ -10,19 +11,19 @@ namespace AlarmBot.Responses
{
public static void ReplyWithGreeting(IBotContext context)
{
context.Reply($"Hello, I'm the alarmbot.");
context.Batch().Reply($"Hello, I'm the alarmbot.");
}
public static void ReplyWithHelp(IBotContext context)
{
context.Reply($"I can add an alarm, show alarms or delete an alarm. ");
context.Batch().Reply($"I can add an alarm, show alarms or delete an alarm. ");
}
public static void ReplyWithResumeTopic(IBotContext context)
{
context.Reply($"What can I do for you?");
context.Batch().Reply($"What can I do for you?");
}
public static void ReplyWithConfused(IBotContext context)
{
context.Reply($"I am sorry, I didn't understand that.");
context.Batch().Reply($"I am sorry, I didn't understand that.");
}
}

Просмотреть файл

@ -6,7 +6,7 @@ using System.Linq;
using AdaptiveCards;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Builder.Templates;
using Microsoft.Bot.Schema;
@ -48,19 +48,19 @@ namespace AlarmBot.Responses
public static void ReplyWithNoAlarms(IBotContext context)
{
context.Reply($"There are no alarms defined.");
context.Batch().Reply($"There are no alarms defined.");
}
public static void ReplyWithNoAlarmsFound(IBotContext context, string data)
{
context.Reply($"There were no alarms found for {data}.");
context.Batch().Reply($"There were no alarms found for {data}.");
}
public static void ReplyWithTitlePrompt(IBotContext context, IEnumerable<Alarm> data)
{
context.Reply(AlarmsCard(context, data, "Delete Alarm", "What alarm do you want to delete?"));
context.Batch().Reply(AlarmsCard(context, data, "Delete Alarm", "What alarm do you want to delete?"));
}
public static void ReplyWithDeletedAlarm(IBotContext context, Alarm data)
{
context.Reply($"I have deleted {data.Title} alarm");
context.Batch().Reply($"I have deleted {data.Title} alarm");
}
}

Просмотреть файл

@ -1,14 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Collections.Generic;
using System.Linq;
using AdaptiveCards;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Builder.Templates;
using Microsoft.Bot.Schema;
using System.Collections.Generic;
using System.Linq;
namespace AlarmBot.Responses
{
@ -17,29 +17,32 @@ namespace AlarmBot.Responses
public static IMessageActivity AlarmsCard(IBotContext context, IEnumerable<Alarm> alarms, string title, string message)
{
IMessageActivity activity = ((Activity)context.Request).CreateReply(message);
var card = new AdaptiveCard();
card.Body.Add(new TextBlock() { Text = title, Size = TextSize.Large, Wrap = true, Weight = TextWeight.Bolder });
if (message != null)
card.Body.Add(new TextBlock() { Text = message, Wrap = true });
if (alarms.Any())
{
FactSet factSet = new FactSet();
foreach (var alarm in alarms)
factSet.Facts.Add(new AdaptiveCards.Fact(alarm.Title, alarm.Time.Value.ToString("f")));
card.Body.Add(factSet);
}
else
card.Body.Add(new TextBlock() { Text = "There are no alarms defined", Weight = TextWeight.Lighter });
activity.Attachments.Add(new Attachment(AdaptiveCard.ContentType, content: card));
return activity;
}
public static void ReplyWithShowAlarms(IBotContext context, dynamic data)
{
context.Reply(AlarmsCard(context, data, "Alarms", null));
context.Batch().Reply(AlarmsCard(context, data, "Alarms", null));
}
}
}

Просмотреть файл

@ -5,9 +5,9 @@ using AlarmBot.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Bot.Builder.BotFramework;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Storage;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Text.RegularExpressions;
@ -40,10 +40,11 @@ namespace AlarmBot
middleware.Add(new UserState<UserData>(new MemoryStorage()));
middleware.Add(new ConversationState<ConversationData>(new MemoryStorage()));
middleware.Add(new BatchOutputMiddleware());
middleware.Add(new RegExpRecognizerMiddleware()
.AddIntent("showAlarms", new Regex("show alarms(.*)", RegexOptions.IgnoreCase))
.AddIntent("addAlarm", new Regex("add alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("deleteAlarm", new Regex("delete alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("showAlarms", new Regex("show alarm(?:s)*(.*)", RegexOptions.IgnoreCase))
.AddIntent("addAlarm", new Regex("add(?: an)* alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("deleteAlarm", new Regex("delete(?: an)* alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("help", new Regex("help(.*)", RegexOptions.IgnoreCase))
.AddIntent("cancel", new Regex("cancel(.*)", RegexOptions.IgnoreCase))
.AddIntent("confirmYes", new Regex("(yes|yep|yessir|^y$)", RegexOptions.IgnoreCase))

Просмотреть файл

@ -8,7 +8,7 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics
@ -130,7 +130,7 @@ namespace AlarmBot.Topics
var userState = context.GetUserState<UserData>();
// var userState = UserState<UserData>.Get(context);
// we ar eusing TopicState to remember what we last asked
// we are using TopicState to remember what we last asked
switch (this.TopicState)
{
case TopicStates.AddingCard:

Просмотреть файл

@ -6,7 +6,7 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics
@ -69,8 +69,8 @@ namespace AlarmBot.Topics
var recognizedIntents = context.Get<IRecognizedIntents>();
switch (context.Request.Type)
{
case ActivityTypes.Message:
switch (recognizedIntents.TopIntent.Name)
case ActivityTypes.Message:
switch (recognizedIntents.TopIntent?.Name)
{
case "addAlarm":
// switch to addAlarm topic

Просмотреть файл

@ -8,7 +8,7 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics

Просмотреть файл

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
namespace AlarmBot.Topics
{

Просмотреть файл

@ -41,4 +41,4 @@ namespace AlarmBot
}
}
}
}
}

Просмотреть файл

@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.0.36" />
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
@ -24,6 +24,7 @@
<ItemGroup>
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core.Extensions\Microsoft.Bot.Builder.Core.Extensions.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Connector\Microsoft.Bot.Connector.csproj" />

Просмотреть файл

@ -13,5 +13,4 @@ namespace AlarmBot.Models
public string Title { get; set; }
public DateTimeOffset? Time { get; set; }
}
}

Просмотреть файл

@ -1,5 +1,5 @@
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
using Microsoft.Recognizers.Text.DateTime;
using System;
@ -46,7 +46,7 @@ namespace AlarmBot.Models
{
IList<DateTime> times = new List<DateTime>();
// Get DateTime model for English
var model = DateTimeRecognizer.GetInstance().GetDateTimeModel(this.Request.Locale ?? "en-us");
var model = new DateTimeRecognizer(this.Request.Locale ?? "en-us").GetDateTimeModel();
var results = model.Parse(this.Request.Text);
// Check there are valid results

Просмотреть файл

@ -1,14 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
using System.Collections.Generic;
namespace AlarmBot.Models
{
/// <summary>
/// object persisted as conversation state
/// Object persisted as conversation state
/// </summary>
public class ConversationData : StoreItem
{

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Text;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
namespace AlarmBot.Responses
@ -17,59 +18,59 @@ namespace AlarmBot.Responses
{
public static void ReplyWithStartTopic(IBotContext context)
{
context.Reply($"Ok, let's add an alarm.");
context.Batch().Reply($"Ok, let's add an alarm.");
}
public static void ReplyWithHelp(IBotContext context, Alarm alarm = null)
{
context.Reply($"I am working with you to create an alarm. To do that I need to know the title and time.\n\n{AlarmDescription(context, alarm)}");
context.Batch().Reply($"I am working with you to create an alarm. To do that I need to know the title and time.\n\n{AlarmDescription(context, alarm)}");
}
public static void ReplyWithConfused(IBotContext context)
{
context.Reply($"I am sorry, I didn't understand: {context.Request.AsMessageActivity().Text}.");
context.Batch().Reply($"I am sorry, I didn't understand: {context.Request.AsMessageActivity().Text}.");
}
public static void ReplyWithCancelPrompt(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithSuggestions(context, "Cancel Alarm?", $"Did you want to cancel the alarm?\n\n{AlarmDescription(context, alarm)}", YesNo));
context.Batch().Reply(ResponseHelpers.ReplyWithSuggestions(context, "Cancel Alarm?", $"Did you want to cancel the alarm?\n\n{AlarmDescription(context, alarm)}", YesNo));
}
public static void ReplyWithCancelReprompt(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithSuggestions(context, $"Cancel alarm?", $"Please answer the question with a \"yes\" or \"no\" reply. Did you want to cancel the alarm?\n\n{AlarmDescription(context, alarm)}", YesNo));
context.Batch().Reply(ResponseHelpers.ReplyWithSuggestions(context, $"Cancel alarm?", $"Please answer the question with a \"yes\" or \"no\" reply. Did you want to cancel the alarm?\n\n{AlarmDescription(context, alarm)}", YesNo));
}
public static void ReplyWithTopicCanceled(IBotContext context) => context.Reply($"OK, I have canceled this alarm.");
public static void ReplyWithTopicCanceled(IBotContext context) => context.Batch().Reply($"OK, I have canceled this alarm.");
public static void ReplyWithTimePrompt(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nWhat time would you like to set the alarm for?"));
context.Batch().Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nWhat time would you like to set the alarm for?"));
}
public static void ReplyWithTimePromptFuture(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nYou need to specify a time in the future. What time would you like to set the alarm?"));
context.Batch().Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nYou need to specify a time in the future. What time would you like to set the alarm?"));
}
public static void ReplyWithTitlePrompt(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nWhat would you like to call your alarm ?"));
context.Batch().Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"{AlarmDescription(context, alarm)}\n\nWhat would you like to call your alarm ?"));
}
public static void ReplyWithTitleValidationPrompt(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"Your title needs to be between 1 and 100 characterslong\n\n{AlarmDescription(context, alarm)}\n\nWhat would you like to call your alarm ?"));
context.Batch().Reply(ResponseHelpers.ReplyWithTitle(context, $"Adding alarm", $"Your title needs to be between 1 and 100 characterslong\n\n{AlarmDescription(context, alarm)}\n\nWhat would you like to call your alarm ?"));
}
public static void ReplyWithAddConfirmation(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithSuggestions(context, $"Adding Alarm", $"{AlarmDescription(context, alarm)}\n\nDo you want to save this alarm?", YesNo));
context.Batch().Reply(ResponseHelpers.ReplyWithSuggestions(context, $"Adding Alarm", $"{AlarmDescription(context, alarm)}\n\nDo you want to save this alarm?", YesNo));
}
public static void ReplyWithAddedAlarm(IBotContext context, Alarm alarm)
{
context.Reply(ResponseHelpers.ReplyWithTitle(context, $"Alarm Added", $"{AlarmDescription(context, alarm)}."));
context.Batch().Reply(ResponseHelpers.ReplyWithTitle(context, $"Alarm Added", $"{AlarmDescription(context, alarm)}."));
}
/// <summary>

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT License.
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
using System;
using System.Collections.Generic;
@ -14,22 +15,22 @@ namespace AlarmBot.Responses
{
public static void ReplyWithGreeting(IBotContext context)
{
context.Reply($"Hello, I'm the alarmbot.");
context.Batch().Reply($"Hello, I'm the alarmbot.");
}
public static void ReplyWithHelp(IBotContext context)
{
context.Reply($"I can add an alarm, show alarms or delete an alarm. ");
context.Batch().Reply($"I can add an alarm, show alarms or delete an alarm. ");
}
public static void ReplyWithResumeTopic(IBotContext context)
{
context.Reply($"What can I do for you?");
context.Batch().Reply($"What can I do for you?");
}
public static void ReplyWithConfused(IBotContext context)
{
context.Reply($"I am sorry, I didn't understand that.");
context.Batch().Reply($"I am sorry, I didn't understand that.");
}
}
}

Просмотреть файл

@ -5,14 +5,12 @@ using AlarmBot.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Builder.Storage;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Text.RegularExpressions;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Builder.Core.Extensions;
namespace AlarmBot
{
@ -41,10 +39,11 @@ namespace AlarmBot
middleware.Add(new UserState<UserData>(new MemoryStorage()));
middleware.Add(new ConversationState<ConversationData>(new MemoryStorage()));
middleware.Add(new BatchOutputMiddleware());
middleware.Add(new RegExpRecognizerMiddleware()
.AddIntent("showAlarms", new Regex("show alarms(.*)", RegexOptions.IgnoreCase))
.AddIntent("addAlarm", new Regex("add alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("deleteAlarm", new Regex("delete alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("showAlarms", new Regex("show alarm(?:s)*(.*)", RegexOptions.IgnoreCase))
.AddIntent("addAlarm", new Regex("add(?: an)* alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("deleteAlarm", new Regex("delete(?: an)* alarm(.*)", RegexOptions.IgnoreCase))
.AddIntent("help", new Regex("help(.*)", RegexOptions.IgnoreCase))
.AddIntent("cancel", new Regex("cancel(.*)", RegexOptions.IgnoreCase))
.AddIntent("confirmYes", new Regex("(yes|yep|yessir|^y$)", RegexOptions.IgnoreCase))

Просмотреть файл

@ -8,7 +8,6 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics
@ -129,8 +128,10 @@ namespace AlarmBot.Topics
return await this.PromptForMissingData(context);
case TopicStates.TimePrompt:
// take first one in the future
this.Alarm.Time = context.GetDateTimes().Where(t => t > DateTimeOffset.Now).FirstOrDefault();
// take first one in the future if a valid time has been parsed
var times = context.GetDateTimes();
if(times.Any(t => t > DateTimeOffset.Now))
this.Alarm.Time = times.Where(t => t > DateTimeOffset.Now).FirstOrDefault();
return await this.PromptForMissingData(context);
case TopicStates.CancelConfirmation:

Просмотреть файл

@ -6,7 +6,6 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics

Просмотреть файл

@ -8,7 +8,6 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
namespace AlarmBot.Topics

Просмотреть файл

@ -6,7 +6,6 @@ using System.Threading.Tasks;
using AlarmBot.Models;
using AlarmBot.Responses;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
namespace AlarmBot.Topics
{

Просмотреть файл

@ -8,8 +8,8 @@ using System.Text;
using AlarmBot.Models;
using AlarmBot.Topics;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Middleware;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Builder.Core.Extensions;
namespace AlarmBot.Responses
{
@ -20,22 +20,23 @@ namespace AlarmBot.Responses
{
public static void ReplyWithNoAlarms(AlarmBotContext context)
{
context.Reply($"There are no alarms defined.");
context.Batch().Reply($"There are no alarms defined.");
}
public static void ReplyWithNoAlarmsFound(AlarmBotContext context, string text)
{
context.Reply($"There were no alarms found for {(string)text}.");
context.Batch().Reply($"There were no alarms found for {(string)text}.");
}
public static void ReplyWithTitlePrompt(AlarmBotContext context)
{
context.Reply(GetDeleteActivity(context, context.UserState.Alarms, "Delete Alarms", "What alarm do you want to delete?"));
var deleteActivity = GetDeleteActivity(context, context.UserState.Alarms, "Delete Alarms", "What alarm do you want to delete?");
context.Batch().Reply((Activity) deleteActivity);
}
public static void ReplyWithDeletedAlarm(AlarmBotContext context, Alarm alarm = null)
{
context.Reply($"I have deleted {alarm.Title} alarm");
context.Batch().Reply($"I have deleted {alarm.Title} alarm");
}
public static IMessageActivity GetDeleteActivity(AlarmBotContext context, IEnumerable<Alarm> alarms, string title, string message)

Просмотреть файл

@ -1,12 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AlarmBot.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Core.Extensions;
namespace AlarmBot.Responses
{
@ -17,9 +19,10 @@ namespace AlarmBot.Responses
{
public static void ReplyWithShowAlarms(IBotContext context, IEnumerable<Alarm> alarms)
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
sb.AppendLine("# Current Alarms\n");
if (alarms.Any())
if (alarms != null && alarms.Any())
{
foreach (var alarm in alarms)
{
@ -29,7 +32,7 @@ namespace AlarmBot.Responses
else
sb.AppendLine("*There are no alarms defined.*");
context.Reply(sb.ToString());
context.Batch().Reply(sb.ToString());
}
}
}

Просмотреть файл

@ -10,6 +10,7 @@ using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Builder.Ai;
using Microsoft.Bot.Builder.BotFramework;
using Microsoft.Bot.Builder.Core.Extensions;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Configuration;
@ -34,17 +35,17 @@ namespace Microsoft.Bot.Samples.Ai.QnA.Controllers
KnowledgeBaseId = "xxxxxx"
};
adapter = new BotFrameworkAdapter(new ConfigurationCredentialProvider(configuration))
// add QnA middleware
.Use(new BatchOutputMiddleware())
.Use(new QnAMakerMiddleware(qnaOptions, _httpClient));
}
}
private Task BotReceiveHandler(IBotContext context)
{
if (context.Request.Type == ActivityTypes.Message && context.Responses.Count == 0)
if (context.Request.Type == ActivityTypes.Message && context.Responded == false)
{
// add app logic when QnA Maker doesn't find an answer
context.Reply("No good match found in the KB.");
context.Batch().Reply("No good match found in the KB.");
}
return Task.CompletedTask;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше