From 07f5a43ee85abfa0acf797adf7b9cd5aaa4bb230 Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Tue, 23 Mar 2021 10:23:46 -0700 Subject: [PATCH] chore: removed unsupported samples --- dialogflow/api/Dialogflow.sln | 35 --- .../DialogflowSamples/DetectIntentStream.cs | 121 ---------- .../DialogflowSamples/DetectIntentTexts.cs | 83 ------- .../DialogflowSamples/DialogflowSamples.cs | 51 ----- .../DialogflowSamples.csproj | 20 -- .../api/DialogflowSamples/IntentManagement.cs | 184 --------------- dialogflow/api/DialogflowSamples/README.md | 24 -- .../DialogflowSamples/Remove-Resources.ps1 | 23 -- dialogflow/api/README.md | 86 ------- dialogflow/api/Test/DetectIntentStreamTest.cs | 35 --- dialogflow/api/Test/DetectIntentTextsTest.cs | 35 --- .../api/Test/DialogflowSampleTests.csproj | 29 --- dialogflow/api/Test/DialogflowTest.cs | 209 ------------------ dialogflow/api/Test/IntentManagementTests.cs | 80 ------- dialogflow/api/Test/runTests.ps1 | 20 -- dialogflow/api/resources/book_a_room.wav | Bin 31058 -> 0 bytes 16 files changed, 1035 deletions(-) delete mode 100644 dialogflow/api/Dialogflow.sln delete mode 100644 dialogflow/api/DialogflowSamples/DetectIntentStream.cs delete mode 100644 dialogflow/api/DialogflowSamples/DetectIntentTexts.cs delete mode 100644 dialogflow/api/DialogflowSamples/DialogflowSamples.cs delete mode 100644 dialogflow/api/DialogflowSamples/DialogflowSamples.csproj delete mode 100644 dialogflow/api/DialogflowSamples/IntentManagement.cs delete mode 100644 dialogflow/api/DialogflowSamples/README.md delete mode 100644 dialogflow/api/DialogflowSamples/Remove-Resources.ps1 delete mode 100644 dialogflow/api/README.md delete mode 100644 dialogflow/api/Test/DetectIntentStreamTest.cs delete mode 100644 dialogflow/api/Test/DetectIntentTextsTest.cs delete mode 100644 dialogflow/api/Test/DialogflowSampleTests.csproj delete mode 100644 dialogflow/api/Test/DialogflowTest.cs delete mode 100644 dialogflow/api/Test/IntentManagementTests.cs delete mode 100644 dialogflow/api/Test/runTests.ps1 delete mode 100644 dialogflow/api/resources/book_a_room.wav diff --git a/dialogflow/api/Dialogflow.sln b/dialogflow/api/Dialogflow.sln deleted file mode 100644 index 79c5a5ab129..00000000000 --- a/dialogflow/api/Dialogflow.sln +++ /dev/null @@ -1,35 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2017 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DialogflowSamples", "DialogflowSamples\DialogflowSamples.csproj", "{3B1379A8-80F0-4AFD-AF78-8CEAFF6A5DF5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DialogflowSampleTests", "Test\DialogflowSampleTests.csproj", "{751CA59D-EBBE-4D26-964C-0502CD5EC984}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLineUtil", "..\..\commandlineutil\Lib\CommandLineUtil.csproj", "{374E48A5-C43C-4719-878B-73A03820B65E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testutil", "..\..\testutil\testutil.csproj", "{B620A334-A8D8-4883-B530-8C890E6C0879}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3B1379A8-80F0-4AFD-AF78-8CEAFF6A5DF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B1379A8-80F0-4AFD-AF78-8CEAFF6A5DF5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B1379A8-80F0-4AFD-AF78-8CEAFF6A5DF5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B1379A8-80F0-4AFD-AF78-8CEAFF6A5DF5}.Release|Any CPU.Build.0 = Release|Any CPU - {374E48A5-C43C-4719-878B-73A03820B65E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {374E48A5-C43C-4719-878B-73A03820B65E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {374E48A5-C43C-4719-878B-73A03820B65E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {374E48A5-C43C-4719-878B-73A03820B65E}.Release|Any CPU.Build.0 = Release|Any CPU - {751CA59D-EBBE-4D26-964C-0502CD5EC984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {751CA59D-EBBE-4D26-964C-0502CD5EC984}.Debug|Any CPU.Build.0 = Debug|Any CPU - {751CA59D-EBBE-4D26-964C-0502CD5EC984}.Release|Any CPU.ActiveCfg = Release|Any CPU - {751CA59D-EBBE-4D26-964C-0502CD5EC984}.Release|Any CPU.Build.0 = Release|Any CPU - {B620A334-A8D8-4883-B530-8C890E6C0879}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B620A334-A8D8-4883-B530-8C890E6C0879}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B620A334-A8D8-4883-B530-8C890E6C0879}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B620A334-A8D8-4883-B530-8C890E6C0879}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/dialogflow/api/DialogflowSamples/DetectIntentStream.cs b/dialogflow/api/DialogflowSamples/DetectIntentStream.cs deleted file mode 100644 index c7083ebd423..00000000000 --- a/dialogflow/api/DialogflowSamples/DetectIntentStream.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright(c) 2020 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using CommandLine; -using Google.Cloud.Dialogflow.V2; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - -namespace GoogleCloudSamples -{ - public class DetectIntentStream - { - public static void RegisterCommands(VerbMap verbMap) - { - verbMap - .Add((DetectIntentFromStreamOptions opts) => - DetectIntentFromStreamAsync(opts.ProjectId, opts.SessionId, opts.FilePath).Result); - } - - [Verb("detect-intent:streams", HelpText = "Detect intent from stream")] - public class DetectIntentFromStreamOptions : OptionsWithProjectIdAndSessionId - { - [Value(0, MetaName = "file", HelpText = "Path to the audio file", Required = true)] - public string FilePath { get; set; } - } - - // [START dialogflow_detect_intent_streaming] - public static async Task DetectIntentFromStreamAsync( - string projectId, - string sessionId, - string filePath) - { - var sessionsClient = SessionsClient.Create(); - var sessionName = SessionName.FromProjectSession(projectId, sessionId).ToString(); - - // Initialize streaming call, retrieving the stream object - var streamingDetectIntent = sessionsClient.StreamingDetectIntent(); - - // Define a task to process results from the API - var responseHandlerTask = Task.Run(async () => - { - var responseStream = streamingDetectIntent.GetResponseStream(); - while (await responseStream.MoveNextAsync()) - { - var response = responseStream.Current; - var queryResult = response.QueryResult; - - if (queryResult != null) - { - Console.WriteLine($"Query text: {queryResult.QueryText}"); - if (queryResult.Intent != null) - { - Console.Write("Intent detected:"); - Console.WriteLine(queryResult.Intent.DisplayName); - } - } - } - }); - - // Instructs the speech recognizer how to process the audio content. - // Note: hard coding audioEncoding, sampleRateHertz for simplicity. - var queryInput = new QueryInput - { - AudioConfig = new InputAudioConfig - { - AudioEncoding = AudioEncoding.Linear16, - LanguageCode = "en-US", - SampleRateHertz = 16000 - } - }; - - // The first request must **only** contain the audio configuration: - await streamingDetectIntent.WriteAsync(new StreamingDetectIntentRequest - { - QueryInput = queryInput, - Session = sessionName - }); - - using (FileStream fileStream = new FileStream(filePath, FileMode.Open)) - { - // Subsequent requests must **only** contain the audio data. - // Following messages: audio chunks. We just read the file in - // fixed-size chunks. In reality you would split the user input - // by time. - var buffer = new byte[32 * 1024]; - int bytesRead; - while ((bytesRead = await fileStream.ReadAsync( - buffer, 0, buffer.Length)) > 0) - { - await streamingDetectIntent.WriteAsync(new StreamingDetectIntentRequest - { - Session = sessionName, - InputAudio = Google.Protobuf.ByteString.CopyFrom(buffer, 0, bytesRead) - }); - }; - } - - // Tell the service you are done sending data - await streamingDetectIntent.WriteCompleteAsync(); - - // This will complete once all server responses have been processed. - await responseHandlerTask; - - return 0; - } - // [END dialogflow_detect_intent_streaming] - } -} diff --git a/dialogflow/api/DialogflowSamples/DetectIntentTexts.cs b/dialogflow/api/DialogflowSamples/DetectIntentTexts.cs deleted file mode 100644 index c09585bc8b9..00000000000 --- a/dialogflow/api/DialogflowSamples/DetectIntentTexts.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using System.Linq; -using System.Collections.Generic; -using CommandLine; -using Google.Cloud.Dialogflow.V2; - -namespace GoogleCloudSamples -{ - // Samples demonstrating how to detect Intents using texts - public class DetectIntentTexts - { - public static void RegisterCommands(VerbMap verbMap) - { - verbMap - .Add((DetectIntentFromTextsOptions opts) => - DetectIntentFromTexts(opts.ProjectId, opts.SessionId, opts.Texts, opts.LanguageCode)); - } - - [Verb("detect-intent:texts", HelpText = "Detect Intent using provided texts")] - public class DetectIntentFromTextsOptions : OptionsWithProjectIdAndSessionId - { - [Value(0, MetaName = "texts", HelpText = "Comma separated text input", Required = true)] - public string TextsInput { get; set; } - - public string[] Texts => TextsInput.Split(','); - - [Value(1, MetaName = "languageCode", HelpText = "Language code, eg. en-US", Default = "en-US")] - public string LanguageCode { get; set; } - } - - // [START dialogflow_detect_intent_text] - public static int DetectIntentFromTexts(string projectId, - string sessionId, - string[] texts, - string languageCode = "en-US") - { - var client = SessionsClient.Create(); - - foreach (var text in texts) - { - var response = client.DetectIntent( - session: SessionName.FromProjectSession(projectId, sessionId), - queryInput: new QueryInput() - { - Text = new TextInput() - { - Text = text, - LanguageCode = languageCode - } - } - ); - - var queryResult = response.QueryResult; - - Console.WriteLine($"Query text: {queryResult.QueryText}"); - if (queryResult.Intent != null) - { - Console.WriteLine($"Intent detected: {queryResult.Intent.DisplayName}"); - } - Console.WriteLine($"Intent confidence: {queryResult.IntentDetectionConfidence}"); - Console.WriteLine($"Fulfillment text: {queryResult.FulfillmentText}"); - Console.WriteLine(); - } - - return 0; - } - // [END dialogflow_detect_intent_text] - } -} diff --git a/dialogflow/api/DialogflowSamples/DialogflowSamples.cs b/dialogflow/api/DialogflowSamples/DialogflowSamples.cs deleted file mode 100644 index 1a3b5d25b74..00000000000 --- a/dialogflow/api/DialogflowSamples/DialogflowSamples.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using CommandLine; - -namespace GoogleCloudSamples -{ - public class DialogflowSamples - { - public static int Main(string[] args) - { - var verbMap = new VerbMap(); - - DetectIntentTexts.RegisterCommands(verbMap); - DetectIntentStream.RegisterCommands(verbMap); - IntentManagement.RegisterCommands(verbMap); - - verbMap.NotParsedFunc = (err) => 1; - - return (int)verbMap.Run(args); - } - } - - /* - * Shared options. All commands require projectId. Many require sessionId as well. - */ - - public class OptionsWithProjectId - { - [Option('p', "projectId", HelpText = "Your Google Cloud project ID", Required = true)] - public string ProjectId { get; set; } - } - - public class OptionsWithProjectIdAndSessionId : OptionsWithProjectId - { - [Option('s', "sessionId", HelpText = "Session ID", Required = true)] - public string SessionId { get; set; } - } -} diff --git a/dialogflow/api/DialogflowSamples/DialogflowSamples.csproj b/dialogflow/api/DialogflowSamples/DialogflowSamples.csproj deleted file mode 100644 index 1a39fd9890d..00000000000 --- a/dialogflow/api/DialogflowSamples/DialogflowSamples.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - Exe - netcoreapp3.1 - false - - - - - - - - - - - resources\book_a_room.wav - PreserveNewest - - - diff --git a/dialogflow/api/DialogflowSamples/IntentManagement.cs b/dialogflow/api/DialogflowSamples/IntentManagement.cs deleted file mode 100644 index 242559da62b..00000000000 --- a/dialogflow/api/DialogflowSamples/IntentManagement.cs +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using System.Linq; -using System.Collections.Generic; -using CommandLine; -using Google.Cloud.Dialogflow.V2; - -namespace GoogleCloudSamples -{ - // Samples demonstrating how to Create, List, Delete Intents - public class IntentManagement - { - public static void RegisterCommands(VerbMap verbMap) - { - verbMap - .Add((CreateOptions opts) => Create(opts.ProjectId, opts.DisplayName, opts.MessageText, opts.TrainingPhrasesParts)) - .Add((ListOptions opts) => List(opts.ProjectId)) - .Add((DeleteOptions opts) => - opts.IntentIds.Count() == 1 ? - Delete(opts.ProjectId, opts.IntentIds.First()) : - BatchDelete(opts.ProjectId, opts.IntentIds)); - } - - [Verb("intents:create", HelpText = "Create new Intent")] - public class CreateOptions : OptionsWithProjectId - { - [Value(0, MetaName = "displayName", HelpText = "Display name of new Intent", Required = true)] - public string DisplayName { get; set; } - - [Value(1, MetaName = "messageText", HelpText = "Message text", Required = true)] - public string MessageText { get; set; } - - [Value(2, MetaName = "trainingPhrasesParts", HelpText = "Comma separated training phrases parts", Required = true)] - public string TrainingPhrasesPartsInput { get; set; } - - public string[] TrainingPhrasesParts => TrainingPhrasesPartsInput.Split(','); - } - - // [START dialogflow_create_intent] - public static int Create(string projectId, - string displayName, - string messageText, - string[] trainingPhrasesParts) - { - var client = IntentsClient.Create(); - - var text = new Intent.Types.Message.Types.Text(); - text.Text_.Add(messageText); - - var message = new Intent.Types.Message() - { - Text = text - }; - - var phraseParts = new List(); - foreach (var part in trainingPhrasesParts) - { - phraseParts.Add(new Intent.Types.TrainingPhrase.Types.Part() - { - Text = part - }); - } - - var trainingPhrase = new Intent.Types.TrainingPhrase(); - trainingPhrase.Parts.AddRange(phraseParts); - - var intent = new Intent(); - intent.DisplayName = displayName; - intent.Messages.Add(message); - intent.TrainingPhrases.Add(trainingPhrase); - - var newIntent = client.CreateIntent( - parent: new AgentName(projectId), - intent: intent - ); - - Console.WriteLine($"Created Intent: {newIntent.Name}"); - - return 0; - } - // [END dialogflow_create_intent] - - [Verb("intents:list", HelpText = "Print list of entities for given Intent")] - public class ListOptions : OptionsWithProjectId { } - - // [START dialogflow_list_intents] - public static int List(string projectId) - { - var client = IntentsClient.Create(); - - var intents = client.ListIntents(new AgentName(projectId)); - - foreach (var intent in intents) - { - Console.WriteLine($"Intent name: {intent.Name}"); - Console.WriteLine($"Intent display name: {intent.DisplayName}"); - Console.WriteLine($"Action: {intent.Action}"); - Console.WriteLine($"Root follow-up intent: {intent.RootFollowupIntentName}"); - Console.WriteLine($"Parent follow-up intent: {intent.ParentFollowupIntentName}"); - - Console.WriteLine($"Input contexts:"); - foreach (var inputContextName in intent.InputContextNames) - { - Console.WriteLine($"Input context name: {inputContextName}"); - } - - Console.WriteLine($"Output contexts:"); - foreach (var outputContex in intent.OutputContexts) - { - Console.WriteLine($"Output context name: {outputContex.Name}"); - } - Console.WriteLine("Messages:"); - foreach (var message in intent.Messages) - { - if (message.Text != null) - { - foreach (var text in message.Text.Text_) - { - Console.WriteLine($"Message text: {text}"); - } - } - } - Console.WriteLine($"Training Phrases ({intent.TrainingPhrases.Count})"); - foreach (var trainingPhrase in intent.TrainingPhrases) - { - Console.WriteLine($"Phrase name: {trainingPhrase.Name}"); - Console.WriteLine($"Phrase type: {trainingPhrase.Type}"); - foreach (var phrasePart in trainingPhrase.Parts) - { - Console.WriteLine($"Phrase part: {phrasePart.Text}"); - } - } - Console.WriteLine(); - } - - return 0; - } - // [END dialogflow_list_intents] - - [Verb("intents:delete", HelpText = "Delete specified Intent")] - public class DeleteOptions : OptionsWithProjectId - { - [Value(0, MetaName = "intentId", HelpText = "ID of existing Intent", Required = true)] - public IEnumerable IntentIds { get; set; } - } - - // [START dialogflow_delete_intent] - public static int Delete(string projectId, string intentId) - { - var client = IntentsClient.Create(); - client.DeleteIntent(new IntentName(projectId, intentId)); - - Console.WriteLine($"Deleted Intent: {intentId}"); - - return 0; - } - // [END dialogflow_delete_intent] - - public static int BatchDelete(string projectId, - IEnumerable intentIds) - { - var client = IntentsClient.Create(); - var intents = intentIds.Select(id => new Intent() - { - Name = new IntentName(projectId, id).ToString() - }); - client.BatchDeleteIntents(new AgentName(projectId), intents); - return 0; - } - } -} diff --git a/dialogflow/api/DialogflowSamples/README.md b/dialogflow/api/DialogflowSamples/README.md deleted file mode 100644 index c2ef68cc2ba..00000000000 --- a/dialogflow/api/DialogflowSamples/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## Dialogflow Samples - -`$ dotnet run` - - - DialogflowSamples 0.0.0.0 - Copyright (C) 2020 author - - ERROR(S): - No verb selected. - - detect-intent:texts Detect Intent using provided texts - - detect-intent:streams Detect intent from stream - - intents:create Create new Intent - - intents:list Print list of entities for given Intent - - intents:delete Delete specified Intent - - help Display more information on a specific command. - - version Display version information. diff --git a/dialogflow/api/DialogflowSamples/Remove-Resources.ps1 b/dialogflow/api/DialogflowSamples/Remove-Resources.ps1 deleted file mode 100644 index 15b090bf6d8..00000000000 --- a/dialogflow/api/DialogflowSamples/Remove-Resources.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -<# -.DESCRIPTION -ONLY USE FOR CLEANING UP AFTER TESTS. -Removes all the dialogflow resources for a project. -#> - -$intents = dotnet run -c Release -- intents:list -p $env:GOOGLE_PROJECT_ID | where {$_ -match "Intent name:.*agent/intents/.*"} -$intentIds = $intents | % { $_ -match "intents/(.*)" | Out-Null; $matches[1] } -while ($intentIds) { - $group = $intentIds | Select-Object -First 100 - $group | Write-Host - dotnet run -c Release -- intents:delete -p $env:GOOGLE_PROJECT_ID $group - $intentIds = $intentIds | Select-Object -Skip 100 -} - -$entityTypes = dotnet run -c Release -- entity-types:list -p $env:GOOGLE_PROJECT_ID | where {$_ -match "name:.*/agent/entityTypes/.*"} -$entityTypeIds = $entityTypes | % { $_ -match "entityTypes/(.*)" | Out-Null; $matches[1] } -while ($entityTypeIds) { - $group = $entityTypeIds | Select-Object -First 100 - $group | Write-Host - dotnet run -c Release -- entity-types:delete -p $env:GOOGLE_PROJECT_ID $group - $entityTypeIds = $entityTypeIds | Select-Object -Skip 100 -} \ No newline at end of file diff --git a/dialogflow/api/README.md b/dialogflow/api/README.md deleted file mode 100644 index 9ea04843c58..00000000000 --- a/dialogflow/api/README.md +++ /dev/null @@ -1,86 +0,0 @@ -# .NET Dialogflow Enterprise Edition Samples - -A collection of samples that demonstrate how to call the -[Dialogflow Enterprise Edition API](https://cloud.google.com/dialogflow-enterprise/docs/) from C#. - -This sample requires [.NET Core 2.0]( - https://www.microsoft.com/net/core) or later. That means using -[Visual Studio 2017]( - https://www.visualstudio.com/), or the command line. Visual Studio 2015 users -can use [this older sample]( - https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/vs2015/video/api). - -## Build and Run - -1. **Follow the set-up instructions in [the documentation](https://cloud.google.com/dotnet/docs/setup).** - -1. Enable APIs for your project. - [Click here](https://console.cloud.google.com/flows/enableapi?apiid=dialogflow.googleapis.com&showconfirmation=true) - to visit Cloud Platform Console and enable the Dialogflow API. - -1. (Optional) Import sample Dialogflow agent using [these instructions](https://cloud.google.com/dialogflow-enterprise/docs/quickstart-client-libraries#import-the-sample-dialogflow-agent) - -1. From a Powershell command line, run the samples: - ``` - PS C:\...\dotnet-docs-samples\dialogflow\api\DialogflowSamples> dotnet restore - PS C:\...\dotnet-docs-samples\dialogflow\api\DialogflowSamples> dotnet run - DialogflowSamples 0.0.0.0 - Copyright (C) 1 author - - contexts:create Create new Context - - contexts:list Print list of entities for given Context - - contexts:delete Delete specified Context - - intents:create Create new Intent - - intents:list Print list of entities for given Intent - - intents:delete Delete specified Intent - - entities:create Create new entity type - - entities:list Print list of entities for given EntityType - - entities:delete Delete specified EntityType - - entity-types:create Create new entity type - - entity-types:list Print list of all entity types - - entity-types:delete Delete specified EntityType - - session-entity-types:create Create new session entity type - - session-entity-types:list Print list of all session entity types - - session-entity-types:delete Delete specified SessionEntityType - - help Display more information on a specific command. - - version Display version information. - ``` - - ``` - PS C:\...DialogflowSamples> dotnet run entity-types:list --projectId "MY-PROJECT-ID" - EntityType name: projects/rebecca-gcp/agent/entityTypes/9e399c95-10f4-48f3-a419-9d4aab7c6721 - EntityType display name: room - Number of entities: 3 - Entity values: - A - B - C - ``` - -## Contributing changes - -* See [CONTRIBUTING.md](../../CONTRIBUTING.md) - -## Licensing - -* See [LICENSE](../../LICENSE) - -## Testing - -* See [TESTING.md](../../TESTING.md) diff --git a/dialogflow/api/Test/DetectIntentStreamTest.cs b/dialogflow/api/Test/DetectIntentStreamTest.cs deleted file mode 100644 index 55431d9c654..00000000000 --- a/dialogflow/api/Test/DetectIntentStreamTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright(c) 2020 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using System.IO; -using Xunit; - -namespace GoogleCloudSamples -{ - public class DetectIntentStreamsTest : DialogflowTest - { - [Fact] - void TestDetectIntentFromStream() - { - var _audioWavPath = Path.Combine("resources", "book_a_room.wav"); - - RunWithSessionId("detect-intent:streams", _audioWavPath); - Assert.Equal(0, ExitCode); - - Assert.Contains("book", Stdout); - Assert.Contains("Intent detected:", Stdout); - } - } -} diff --git a/dialogflow/api/Test/DetectIntentTextsTest.cs b/dialogflow/api/Test/DetectIntentTextsTest.cs deleted file mode 100644 index 45d21138d53..00000000000 --- a/dialogflow/api/Test/DetectIntentTextsTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using Xunit; - -namespace GoogleCloudSamples -{ - public class DetectIntentTextsTest : DialogflowTest - { - [Fact] - void TestDetectIntentFromTexts() - { - var texts = new[] { "hello", "book a meeting room", "Mountain View" }; - var textsArgument = string.Join(',', texts); - - RunWithSessionId("detect-intent:texts", textsArgument); - Assert.Equal(0, ExitCode); - - Assert.Contains("Query text:", Stdout); - Assert.Contains("Intent confidence:", Stdout); - Assert.Contains("Fulfillment text:", Stdout); - } - } -} diff --git a/dialogflow/api/Test/DialogflowSampleTests.csproj b/dialogflow/api/Test/DialogflowSampleTests.csproj deleted file mode 100644 index e4502e8caa5..00000000000 --- a/dialogflow/api/Test/DialogflowSampleTests.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - Library - netcoreapp3.1 - - - - - - runtime; build; native; contentfiles; analyzers - all - - - - - - - - - - - - - - resources\book_a_room.wav - PreserveNewest - - - diff --git a/dialogflow/api/Test/DialogflowTest.cs b/dialogflow/api/Test/DialogflowTest.cs deleted file mode 100644 index 39651a4894a..00000000000 --- a/dialogflow/api/Test/DialogflowTest.cs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; - -namespace GoogleCloudSamples -{ - struct CleanupAction - { - public Action Action; - public CancellationTokenSource Cancel; - }; - - public class DialogflowTest : IDisposable - { - protected RetryRobot _retryRobot = new RetryRobot(); - private readonly List _cleanupActions = new List(); - public readonly string ProjectId = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"); - public readonly string SessionId = TestUtil.RandomName(); - - public ConsoleOutput Output { get; set; } - public string Stdout => Output.Stdout; - public int ExitCode => Output.ExitCode; - - public CancellationTokenSource CleanupAfterTest(Action action) - { - var cleanupAction = new CleanupAction - { - Action = action, - Cancel = new CancellationTokenSource() - }; - _cleanupActions.Add(cleanupAction); - return cleanupAction.Cancel; - } - - public CancellationTokenSource CleanupAfterTest(string command, - params string[] args) => CleanupAfterTest(() => Run(command, args)); - - // Multiple tests depend on existing EntityTypes. - // - // This helper method creates an EntityType via `entity-types:create` - // and returns the EntityType's ID. - public string CreateEntityType(string displayName = null, string kindName = "Map") - { - if (string.IsNullOrEmpty(displayName)) - displayName = TestUtil.RandomName(); - Run("entity-types:create", displayName, kindName); - - return SetEntityTypeForCleanupAfterTest(Stdout); - } - - public string SetEntityTypeForCleanupAfterTest(string stdout) - { - string id = GetEntityTypeIdFromStdout(stdout); - CleanupAfterTest("entity-types:delete", id); - return id; - } - - public string GetEntityTypeIdFromStdout(string stdout) - { - var outputPattern = new Regex($"Created EntityType: projects/{ProjectId}/agent/entityTypes/(?.*)"); - return outputPattern.Match(stdout).Groups["entityTypeId"].Value; - } - - public readonly CommandLineRunner _dialogflow = new CommandLineRunner() - { - Main = DialogflowSamples.Main, - Command = "Dialogflow" - }; - - // Dialogflow enforces no more than 60 requests per minute per project. - // Many agents may be running the test at the same time, so limit - // our requests to 10 per minute. - static readonly ThrottleTokenPool s_throttleTokenPool = - new ThrottleTokenPool(10, TimeSpan.FromSeconds(60)); - - // Run command and return output. - // Project ID argument is always set. - // Session ID argument available as a parameter. - // Sets helper properties to last console output. - public ConsoleOutput Run(string command, params object[] args) - { - using (var thottleToken = s_throttleTokenPool.Acquire()) - { - var arguments = args.Select((arg) => arg.ToString()).ToList(); - arguments.Insert(0, command); - arguments.AddRange(new[] { "--projectId", ProjectId }); - try - { - Output = _dialogflow.Run(arguments.ToArray()); - } - catch (Grpc.Core.RpcException e) - when (e.Status.StatusCode == Grpc.Core.StatusCode.ResourceExhausted) - { - // Throttle some more! - int randomDelay = new Random().Next(60, 120); - System.Threading.Thread.Sleep(TimeSpan.FromSeconds(randomDelay)); - // And try once more. - Output = _dialogflow.Run(arguments.ToArray()); - } - Console.WriteLine(Output.Stdout); - return Output; - } - } - - public ConsoleOutput RunWithSessionId(string command, params object[] args) - { - var arguments = args.ToList(); - arguments.AddRange(new[] { "--sessionId", SessionId }); - return Run(command, arguments.ToArray()); - } - - public void Dispose() - { - foreach (var action in _cleanupActions) - { - try - { - if (!action.Cancel.Token.IsCancellationRequested) - { - action.Action(); - } - } - catch (Exception e) - { - Console.Error.WriteLine(e.Message); - } - } - } - } - - // TODO: Move this class into test helpers. - /// - /// Schedules throttling. - /// - class ThrottleTokenPool - { - private readonly TimeSpan _timeSpan; - private readonly BlockingCollection _pool = - new BlockingCollection(); - /// - /// Creates a throttle token pool. - /// - /// - /// Throttle number of tokens that can be acquired to 20 per minute. - /// new ThrottleTokenPool(20, TimeSpan.FromMinutes(1)) - /// - /// Number of tokens. Controls number - /// of simultaneous operations than can be executing. - /// Every given timeSpan, a new set - /// of tokens becomes available. - public ThrottleTokenPool(int tokenCount, TimeSpan timeSpan) - { - for (int i = 0; i < tokenCount; ++i) - { - _pool.Add(new ThrottleToken(this)); - } - - _timeSpan = timeSpan; - } - - /// - /// Acquires a token. Blocks until a token is available. - /// - /// The token. - public IDisposable Acquire() => _pool.Take(); - - internal void Release(ThrottleToken token) - { - Task.Run(async () => - { - await Task.Delay(_timeSpan); - _pool.Add(token); - }); - } - } - - class ThrottleToken : IDisposable - { - readonly ThrottleTokenPool _pool; - - public ThrottleToken(ThrottleTokenPool pool) - { - _pool = pool; - } - - public void Dispose() - { - _pool.Release(this); - } - } -} diff --git a/dialogflow/api/Test/IntentManagementTests.cs b/dialogflow/api/Test/IntentManagementTests.cs deleted file mode 100644 index fe4f1a8dbd9..00000000000 --- a/dialogflow/api/Test/IntentManagementTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright(c) 2018 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -using System; -using System.Text.RegularExpressions; -using Xunit; - -namespace GoogleCloudSamples -{ - public class IntentManagementTests : DialogflowTest - { - readonly string _displayName = TestUtil.RandomName(); - readonly string _messageText = "fake message for testing"; - readonly string[] _trainingPhrasesParts = new[] { "test part 1", "test part 2" }; - string TrainingPartPhrasesArgument => string.Join(',', _trainingPhrasesParts); - - Regex CreateOutputPattern => new Regex( - $"Created Intent: projects/{ProjectId}/agent/intents/(?.*)"); - - // Extract and return Intents ID from output of `intents:create` - string GetIntentId(string createOutput) => - CreateOutputPattern.Match(createOutput).Groups["intentId"].Value; - - [Fact] - void TestCreate() - { - Run("intents:list"); - Assert.DoesNotContain(_displayName, Stdout); - - Run("intents:create", _displayName, _messageText, TrainingPartPhrasesArgument); - Assert.Matches(CreateOutputPattern, Stdout); - var intentId = GetIntentId(createOutput: Stdout); - CleanupAfterTest("intents:delete", intentId); - - _retryRobot.Eventually(() => - { - Run("intents:list"); - Assert.Contains(_displayName, Stdout); - }); - } - - [Fact] - void TestDelete() - { - Run("intents:create", _displayName, _messageText, TrainingPartPhrasesArgument); - - // Get the ID of the created Intent to delete from output of intents:create. - // The Intent ID is needed to delete, the display name is not sufficient. - var intentId = GetIntentId(createOutput: Stdout); - var cancelCleanup = CleanupAfterTest("intents:delete", intentId); - - _retryRobot.Eventually(() => - { - Run("intents:list"); - Assert.Contains(_displayName, Stdout); - }); - - Run("intents:delete", intentId); - Assert.Contains($"Deleted Intent: {intentId}", Stdout); - cancelCleanup.Cancel(); - - _retryRobot.Eventually(() => - { - Run("intents:list"); - Assert.DoesNotContain(_displayName, Stdout); - }); - } - } -} diff --git a/dialogflow/api/Test/runTests.ps1 b/dialogflow/api/Test/runTests.ps1 deleted file mode 100644 index 58c327b3953..00000000000 --- a/dialogflow/api/Test/runTests.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright(c) 2018 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -import-module -DisableNameChecking ..\..\..\BuildTools.psm1 - -Set-TestTimeout 5000 - -# TODO: https://github.com/GoogleCloudPlatform/dotnet-docs-samples/issues/947 -dotnet test --test-adapter-path:. --logger:junit --filter DetectIntentTextsTest 2>&1 | %{ "$_" } diff --git a/dialogflow/api/resources/book_a_room.wav b/dialogflow/api/resources/book_a_room.wav deleted file mode 100644 index 9124e9279460a0057df91202a5d0e5e147b60813..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31058 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 Nh$0A1lK;Pd{tuoqdJX^p