public override Task <DefaultResponse> UpdateVoiceRecognition(UpdateVoiceRecognitionRequest request, ServerCallContext context)
        {
            try
            {
                SpeechManager.Instance.UpdateGrammar(request);
                return(Task.FromResult(new DefaultResponse()
                {
                    Success = true
                }));
            }
            catch (Exception e)
            {
                Log.Error(e, nameof(UpdateVoiceRecognition));

                throw new RpcException(Status.DefaultCancelled, "Failed to update voice recognition");
            }
        }
        private async Task <UpdateVoiceRecognitionRequest> BuildUpdateRequest(CancellationToken cancellationToken,
                                                                              ApplicationDbContext dbContext, AudioFeedResponse audioFeedResponse)
        {
            var request  = new UpdateVoiceRecognitionRequest();
            var settings = (await dbContext.KeyValueSettings.ToListAsync(cancellationToken)).ToDictionary(d => d.Key, d => d.Value);

            request.AudioPhrase =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionTriggerWordAudio, out var audioPhrase)
                                        ? audioPhrase
                                        : "Audio";

            request.TriggerPhrase =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionTriggerWord, out var triggerWord)
                                        ? triggerWord
                                        : "Computer";

            var offAliasList =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionTriggerWordOffAliases, out var offAliases)
                                        ? offAliases
                                        : "off";

            var onAliasList =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionTriggerWordOnAliases, out var onAliases)
                                        ? onAliases
                                        : "on";

            var confirmMessageText =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionConfirmMessage, out var confirmMessage)
                                        ? confirmMessage
                                        : "OK";

            var errorMessageText =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionErrorMessage, out var errorMessage)
                                        ? errorMessage
                                        : "Error";

            var thresholdText =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionThreshold, out var threshold)
                                        ? threshold
                                        : "25";

            var masterText =
                settings.TryGetValue(KeyValueKind.VoiceRecognitionTriggerWordAudioMaster, out var master)
                                        ? master
                                        : "master";

            var feedAliases = await dbContext.AudioFeedAliases
                              .Select(d => new ValueTuple <string, string>(d.Feed.Name, d.Alias)).ToListAsync(cancellationToken);

            var feedAliasDictionary = feedAliases.ToLookup(d => d.Item1, d => d.Item2);

            request.SynthesizerConfirmMessage = confirmMessageText;
            request.SynthesizerErrorMessage   = errorMessageText;
            request.OffAliases.AddRange(offAliasList.Split('|'));
            request.OnAliases.AddRange(onAliasList.Split('|'));
            request.AudioRecognitionItems.AddRange(BuildPhraseList(audioFeedResponse, feedAliasDictionary));
            request.RecognitionThreshold = int.TryParse(thresholdText, out var parsedThreshold) ? parsedThreshold : 25;
            request.MasterPhrase         = masterText;

            return(request);
        }