Пример #1
0
        private async Task OnMessageReceived(SocketMessage arg)
        {
            var author       = arg.Author as IGuildUser;
            var voiceChannel = author?.VoiceChannel as SocketVoiceChannel;

            if (voiceChannel?.Id != Program.DiscordChannelId)
            {
                return;
            }

            if (arg.Content == "!dd start" && voiceChannel != null)
            {
                Console.WriteLine("Joining voice channel: " + voiceChannel.Name);
                _voiceChannelWorker?.TryEnsureStarted();
            }
            else if (arg.Content == "!dd skip" && voiceChannel != null)
            {
                _voiceChannelWorker?.TrySkip();
            }
            else if (arg.Content == "!dd stop")
            {
                if (_voiceChannelWorker != null)
                {
                    await _voiceChannelWorker.StopAsync();
                }
            }
            else if (arg.Content == "!dd info")
            {
                var currentSong = _voiceChannelWorker?.CurrentSong;
                _ = arg.Channel.SendMessageAsync("Now playing " + currentSong?.Title + " - " + currentSong?.Url);
            }
            else if (arg.Content.StartsWith("!dd play "))
            {
                var url = arg.Content.Substring("!dd play ".Length);

                _ = Task.Run(async() =>
                {
                    var post = await _metadataManager.AddUserRequestAsync(url, arg.Author.Username);
                    _voiceChannelWorker?.EnqueueSong(post.Id);
                    await arg.Channel.SendMessageAsync("The song has been added to the queue");
                });
            }
            else if (arg.Content.StartsWith("!dd say "))
            {
                var text = arg.Content.Substring("!dd say ".Length);

                _voiceChannelWorker?.Say(text);
            }
            else if (arg.Content.StartsWith("!dd pause"))
            {
                _voiceChannelWorker?.TryPauseMainTrack();
            }
            else if (arg.Content.StartsWith("!dd resume"))
            {
                _voiceChannelWorker?.TryResumeMainTrack();
            }
        }
Пример #2
0
        protected override async Task DoWorkAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine("Starting voice assistant runner for " + _user.GetUsername());
            try
            {
                var entryDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

                string[] keywordFiles;
                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                {
                    keywordFiles = new string[] {
                        Path.Join(entryDirectory, "picovoice_windows.ppn"),
                        Path.Join(entryDirectory, "porcupine_windows.ppn"),
                        Path.Join(entryDirectory, "bumblebee_windows.ppn"),
                    };
                }
                else
                {
                    keywordFiles = new string[] {
                        // Path.Join(entryDirectory, "alexa_linux.ppn"),
                        // Path.Join(entryDirectory, "porcupine_linux.ppn"),
                        // Path.Join(entryDirectory, "snowboy_linux.ppn"),
                        Path.Join(entryDirectory, "dank_ditties_linux.ppn"),
                    };
                }

                using var porcupine = new Porcupine(
                          Path.Join(entryDirectory, "porcupine_params.pv"),
                          keywordFiles,
                          keywordFiles.Select(_ => 0.5f).ToArray()
                          );

                var userStream = _user.AudioStream;
                if (userStream == null)
                {
                    return;
                }

                var picoFrameLength = porcupine.FrameLength();
                var picoSampleRate  = porcupine.SampleRate();
                var picoBuffer      = new short[picoFrameLength];

                await using var clip = new StreamClip(userStream).UseMemoryBuffer(3840);
                await clip.PrepareAsync();

                await using var monoClip = clip.Downsample(96000, 48000);
                await monoClip.PrepareAsync();

                await using var downsampledClip = monoClip.Downsample(48000, picoSampleRate);
                await downsampledClip.PrepareAsync();

                while (!cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("Waiting for wake word");
                    while (!cancellationToken.IsCancellationRequested)
                    {
                        try
                        {
                            var len = await downsampledClip.ReadAsync(picoBuffer, 0, picoFrameLength, cancellationToken);

                            if (len != picoFrameLength)
                            {
                                continue;
                            }

                            var status = porcupine.Process(picoBuffer);
                            if (status != -1)
                            {
                                break;
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            Console.WriteLine("Wake word ReadAsync cancelled.");
                        }
                    }

                    if (cancellationToken.IsCancellationRequested)
                    {
                        continue;
                    }

                    Console.WriteLine("Wake word detected");
                    clip.Seek(-picoFrameLength * 6 * (48000 / picoSampleRate), SeekOrigin.Current);

                    try
                    {
                        var data = await _witAiClient.ParseAudioStream(monoClip, cancellationToken);

                        if (data != null)
                        {
                            var text = data.Text?.Trim();
                            if (!string.IsNullOrWhiteSpace(text))
                            {
                                Console.WriteLine(_user.GetUsername() + ": " + text);
                                var playSongIntent = data.Intents.FirstOrDefault(i => i.Name == "play_song");

                                if (text.ToLower().StartsWith("i'm "))
                                {
                                    _voiceChannelWorker.Say("Hello " + text.Substring("i'm ".Length) + ", I'm Dank Ditties bot.");
                                }
                                else if (text.ToLower().StartsWith("play "))
                                {
                                    var searchString = text.Substring("play ".Length);

                                    if (searchString == "next")
                                    {
                                        _voiceChannelWorker.TrySkip();
                                    }
                                    else
                                    {
                                        var matches = from post in await _metadataManager.GetReadyToPlayMetadataAsync()
                                                      let relevance = FuzzySharp.Fuzz.Ratio(post.Title, searchString)
                                                                      select(post, relevance);

                                        var topMatch = matches.OrderByDescending(m => m.relevance);
                                        Console.WriteLine("matches: \n" + string.Join("\n", topMatch.Take(3).Select(m => $"{m.post.Title}: {m.relevance}")));
                                        Console.WriteLine();
                                        var closestMatch = topMatch.FirstOrDefault().post;
                                        if (closestMatch != null)
                                        {
                                            _voiceChannelWorker.EnqueueSong(closestMatch.Id);
                                            _voiceChannelWorker.Say("I have added your song, " + closestMatch.Title + " to the queue");
                                            Console.WriteLine("Added " + closestMatch.Title + " to queue");
                                        }
                                    }
                                }
                                else if (text.ToLower() == "what song is this" || text.ToLower() == "what's playing" || text.ToLower() == "song" || text.ToLower() == "song name" || text.ToLower() == "damn son whered you find this")
                                {
                                    _voiceChannelWorker.Say("I am currently playing " + _voiceChannelWorker.CurrentSong?.Title);
                                }
                                else if (text.ToLower() == "pause")
                                {
                                    _voiceChannelWorker.TryPauseMainTrack();
                                }
                                else if (text.ToLower() == "resume")
                                {
                                    _voiceChannelWorker.TryResumeMainTrack();
                                }
                                else
                                {
                                    //_voiceChannelWorker.Say("I'm sorry, I didn't understand that!");
                                    _voiceChannelWorker.Say(text);
                                }
                            }
                            else
                            {
                                _voiceChannelWorker.Say("I'm sorry, I didn't understand that!");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
                _voiceChannelWorker.Say("Goodbye, " + _user.GetUsername());
            }
            finally
            {
                Console.WriteLine("Stopping voice assistant runner for " + _user.GetUsername());
            }
        }