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(); } }
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()); } }