예제 #1
0
        public async Task Assist(CommandContext ctx, int @in = 48000, int @out = 16000, int inChan = 1, int outChan = 1, string raw = null)
        {
            if (!ctx.Services.GetService <IProvideAudioState>().SpeechFromUser.ContainsKey(ctx.User.Id))
            {
                return;
            }

            var buff = ctx.Services.GetService <IProvideAudioState>().SpeechFromUser[ctx.User.Id].ToArray();

            AssistantConfig.AudioInConfig = new AudioInConfig()
            {
                Encoding        = AudioInConfig.Types.Encoding.Linear16,
                SampleRateHertz = 16000
            };

            if (raw != "raw")
            {
                buff = AudioConverter.Resample(buff, @in, @out, inChan, outChan);
            }
            else
            {
                AssistantConfig.AudioInConfig.SampleRateHertz = AudioFormat.Default.SampleRate;
            }

            var token = new GoogleOAuth(KarvisConfiguration).GetTokenForUser(ctx.User.Id);

            if (string.IsNullOrWhiteSpace(token))
            {
                await ctx.RespondAsync("Sorry, you have not signed up.");

                return;
            }

            if (!UserEmbeddedAssistantClients.ContainsKey(ctx.User.Id))
            {
                var channelCredentials = ChannelCredentials.Create(new SslCredentials(), GoogleGrpcCredentials.FromAccessToken(token));
                UserEmbeddedAssistantClients[ctx.User.Id] = new EmbeddedAssistant.EmbeddedAssistantClient(new Channel("embeddedassistant.googleapis.com", 443, channelCredentials));
            }

            using (var call = UserEmbeddedAssistantClients[ctx.User.Id].Assist())
            {
                try
                {
                    var configRequest = new AssistRequest()
                    {
                        AudioIn = ByteString.Empty,
                        Config  = AssistantConfig
                    };

                    ctx.LogInfo($"GoogleAssistant: Sending config message: Audio IsEmpty: {configRequest.AudioIn.IsEmpty}, Request Size: {configRequest.CalculateSize()}");

                    await call.RequestStream.WriteAsync(configRequest);

                    await SendAudioInChunks(call, ctx, buff);

                    await call.RequestStream.CompleteAsync();

                    ctx.LogInfo($"GoogleAssistant: Completing request and awaiting response.");

                    var audioOut = new List <byte>();

                    await call.ResponseStream.ForEachAsync((response) => ProcessVoiceAssistResponse(response, ctx, ref audioOut));

                    if (audioOut.Any())
                    {
                        var voiceConnection = await ctx.EnsureVoiceConnection();

                        if (voiceConnection == null || (voiceConnection.Channel != ctx.Member?.VoiceState?.Channel))
                        {
                            throw new InvalidOperationException($"I'm not connected to your voice channel, so I can't speak.");
                        }

                        var audio = AudioConverter.Resample(audioOut.ToArray(),
                                                            16000, 48000,
                                                            1, 2);

                        voiceConnection.SendSpeaking();
                        voiceConnection.GetTransmitStream().Write(audio, 0, audio.Length);
                        voiceConnection.GetTransmitStream().Flush();
                        voiceConnection.SendSpeaking(false);
                    }

                    try
                    {
                        var status = call.GetStatus();

                        ctx.LogInfo($"GoogleAssistant: Final Status: {status.StatusCode}, Detail: {status.Detail}.");
                    }
                    catch (InvalidOperationException ex)
                    {
                    }
                }
                catch (RpcException ex)
                {
                    ctx.LogError($"GoogleAssistant: Exception: {ex.StatusCode}, {ex.Status.Detail}, {ex.Message}.");

                    if (ex.StatusCode == StatusCode.Unauthenticated)
                    {
                        if (!UserGoogleAuthRetries.ContainsKey(ctx.User.Id))
                        {
                            UserGoogleAuthRetries[ctx.User.Id] = 0;
                        }

                        if (UserGoogleAuthRetries[ctx.User.Id] < 3)
                        {
                            UserGoogleAuthRetries[ctx.User.Id]++;

                            await ReAuth(ctx);

                            await Assist(ctx, @in, @out, inChan, outChan, raw);
                        }
                        else
                        {
                            UserGoogleAuthRetries[ctx.User.Id] = 0;
                        }
                    }
                }
                catch (Exception ex)
                {
                    await ctx.RespondAsync($"Sorry, {ctx.User.Username}, I can't google. \n\n``{ex.Message}``");
                }
            }
        }
예제 #2
0
        public async Task TextAssist(CommandContext ctx, [RemainingText] string query)
        {
            if (ctx.User?.Id == null)
            {
                return;
            }

            var token = new GoogleOAuth(KarvisConfiguration).GetTokenForUser(ctx.User.Id);

            if (string.IsNullOrWhiteSpace(token))
            {
                await ctx.RespondAsync("Sorry, you have not signed up.");

                return;
            }

            if (!UserEmbeddedAssistantClients.ContainsKey(ctx.User.Id))
            {
                var channelCredentials = ChannelCredentials.Create(new SslCredentials(), GoogleGrpcCredentials.FromAccessToken(token));
                UserEmbeddedAssistantClients[ctx.User.Id] = new EmbeddedAssistant.EmbeddedAssistantClient(new Channel("embeddedassistant.googleapis.com", 443, channelCredentials));
            }

            using (var call = UserEmbeddedAssistantClients[ctx.User.Id].Assist())
            {
                try
                {
                    AssistantConfig.AudioInConfig = null;
                    AssistantConfig.TextQuery     = query;

                    var request = new AssistRequest()
                    {
                        AudioIn = ByteString.Empty,
                        Config  = AssistantConfig
                    };

                    ctx.LogInfo($"GoogleAssistant: Sending config message: Audio IsEmpty: {request.AudioIn.IsEmpty}, Request Size: {request.CalculateSize()}");

                    await call.RequestStream.WriteAsync(request);

                    await call.RequestStream.CompleteAsync();

                    ctx.LogInfo($"GoogleAssistant: Completing request and awaiting response.");

                    var audioOut = new List <byte>();

                    await call.ResponseStream.ForEachAsync((response) => ProcessTextAssistResponse(response, ctx, ref audioOut));

                    try
                    {
                        var status = call.GetStatus();
                        ctx.LogInfo($"GoogleAssistant: Final Status: {status.StatusCode}, Detail: {status.Detail}.");
                    }
                    catch (InvalidOperationException ex)
                    {
                    }

                    if (audioOut.Any())
                    {
                        var voiceConnection = await ctx.EnsureVoiceConnection();

                        if (voiceConnection == null || (voiceConnection.Channel != ctx.Member?.VoiceState?.Channel))
                        {
                            throw new InvalidOperationException($"I'm not connected to your voice channel, so I can't speak.");
                        }

                        var audio = AudioConverter.Resample(audioOut.ToArray(),
                                                            16000, 48000,
                                                            1, 2);

                        voiceConnection.SendSpeaking();
                        voiceConnection.GetTransmitStream().Write(audio, 0, audio.Length);
                        voiceConnection.GetTransmitStream().Flush();
                        voiceConnection.SendSpeaking(false);
                    }
                }
                catch (RpcException ex)
                {
                    ctx.LogError($"GoogleAssistant: Exception: {ex.StatusCode}, Detail: {ex.Status.Detail}, Message: {ex.Message}.");

                    if (ex.StatusCode == StatusCode.Unauthenticated)
                    {
                        if (!UserGoogleAuthRetries.ContainsKey(ctx.User.Id))
                        {
                            UserGoogleAuthRetries[ctx.User.Id] = 0;
                        }

                        if (UserGoogleAuthRetries[ctx.User.Id] < 3)
                        {
                            UserGoogleAuthRetries[ctx.User.Id]++;

                            await ReAuth(ctx);

                            await TextAssist(ctx, query);
                        }
                        else
                        {
                            UserGoogleAuthRetries[ctx.User.Id] = 0;
                        }
                    }

                    ctx.LogError($"GoogleAssistant: Exception: {ex.StatusCode}, Detail: {ex.Status.Detail}, Message: {ex.Message}.");
                }
                catch (Exception ex)
                {
                    await ctx.RespondAsync($"Sorry, {ctx.User.Username}, I can't google. \n\n``{ex.Message}``");
                }
            }
        }