merge classic with m2 changes
This commit is contained in:
Коммит
b053bc3949
|
@ -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;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче