コード例 #1
0
        /// <summary>
        /// Gets (or downloads if necessary) a song
        /// </summary>
        /// <param name="songTitle"></param>
        /// <param name="botMessage"></param>
        /// <returns></returns>
        public async Task <string> GetOrDownloadSong(string songTitle, IUserMessage botMessage)
        {
            try
            {
                await MessageUtils.ModifyMessage(botMessage, $"Searching my audio banks for '{songTitle}'");

                //First, check if this song exists in our music DIR
                string songLocation = MusicService.SearchMusicDirectory(songTitle, fileFormat);
                if (songLocation != null)
                {
                    return(songLocation);
                }

                await MessageUtils.ModifyMessage(botMessage, $"Searching YouTube for '{songTitle}'");

                //It doesn't exist, search YouTube for it
                IList <YouTubeVideo> response = await youTubeSearcher.SearchForYouTube(songTitle);

                if (response == null)
                {
                    await MessageUtils.ModifyMessage(botMessage, "Something went wrong while searching on YouTube!");

                    return(null);
                }

                //There were no results
                if (response.Count == 0)
                {
                    await MessageUtils.ModifyMessage(botMessage,
                                                     $"There were no results for '{songTitle}' on YouTube.");

                    return(null);
                }

                //Get the first video
                YouTubeVideo video = response[0];

                //This shouldn't ever happen
                if (video == null)
                {
                    await MessageUtils.ModifyMessage(botMessage,
                                                     $"Some issue happened while getting '{songTitle}' off from YouTube.");

                    return(null);
                }

                string videoTitle = video.VideoTitle.RemoveIllegalChars();

                //Do a second search with the title from YouTube
                songLocation = MusicService.SearchMusicDirectory(videoTitle, fileFormat);
                if (songLocation != null)
                {
                    return(songLocation);
                }

                //Make sure the song doesn't succeeds max time
                if (video.VideoDuration >= Config.bot.AudioSettings.MaxVideoTime)
                {
                    await MessageUtils.ModifyMessage(botMessage,
                                                     $"The video **{videoTitle}** by **{video.VideoAuthor}** succeeds max time of {Config.bot.AudioSettings.MaxVideoTime}");

                    return(null);
                }

                //Download the song
                await MessageUtils.ModifyMessage(botMessage,
                                                 $"Downloading **{videoTitle}** by **{video.VideoAuthor}**");

                songLocation = await musicDownloader.DownloadYouTubeVideo(video.VideoId, musicDirectory);

                //Do a check here first, in case the operation was cancelled, so we don't say "Something went wrong...", when well... it was just cancelled
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    return(null);
                }

                //The download must have failed
                if (songLocation == null)
                {
                    await MessageUtils.ModifyMessage(botMessage,
                                                     $"Something went wrong while downloading the song **{videoTitle}** from YouTube!");

                    return(null);
                }

                //If the file extension isn't the same then we need to convert it
                string audioFileExtension = Path.GetExtension(songLocation);
                if (audioFileExtension == fileFormat.GetFormatExtension())
                {
                    return(songLocation);
                }

                //We need to convert it, since they are not the same file format
                songLocation = await audioConverter.ConvertFileToAudio(songLocation, musicDirectory, true, fileFormat);

                //Everything when well
                if (songLocation != null)
                {
                    return(songLocation);
                }

                //Do a check here first, in case the operation was cancelled, so we don't say "An issue occured...", when well... it was just cancelled
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    return(null);
                }

                //Conversion failed
                await MessageUtils.ModifyMessage(botMessage,
                                                 "An issue occured while getting the song ready for playing!");

                return(null);
            }
            catch (OperationCanceledException)
            {
                //User cancelled
                return(null);
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while downloading a YouTube video! {@Exception}", ex);
                await MessageUtils.ModifyMessage(botMessage, "An issue occured while trying to get the song!");

                return(null);
            }
        }
コード例 #2
0
        public async Task <string> ConvertFileToAudio(string originalLocation, string location, bool deleteOriginal = true,
                                                      MusicFileFormat musicFileFormat = MusicFileFormat.Mp3)
        {
            try
            {
                string fullNewLocation = $"{location}{Path.GetFileName(originalLocation).Replace(Path.GetExtension(originalLocation), "")}.{musicFileFormat.GetFormatExtension()}";

                Logger.Log($"Converting '{originalLocation}' to '{fullNewLocation}'...", LogVerbosity.Debug);

                //Start our ffmpeg process
                Process ffmpeg = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName  = Config.bot.AudioSettings.FfmpegLocation,
                        Arguments = $"-i \"{originalLocation}\" -ar 48000 -y \"{fullNewLocation}\""
                    }
                };

                ffmpeg.Start();

                while (!ffmpeg.HasExited)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        ffmpeg.Kill(true);
                        ffmpeg.Dispose();
                        return(null);
                    }

                    await Task.Delay(50);
                }

                ffmpeg.Dispose();

                //Delete our old file
                if (deleteOriginal)
                {
                    //if (File.Exists(originalLocation))
                    //File.Delete(originalLocation);
                    //else //Were the f**k is our fileToConvert then?? This should never happen but it is here anyway
                    //return null;
                }

                //So obviously there was an issue converting...
                if (!File.Exists(fullNewLocation))
                {
                    Logger.Log("There was an issue converting the file!", LogVerbosity.Debug);
                    return(null);
                }

                //Ayy, we converted
                Logger.Log($"Successfully converted to '{fullNewLocation}'.", LogVerbosity.Debug);
                return(fullNewLocation);
            }
            catch (NullReferenceException ex)
            {
#if DEBUG
                Logger.Log($"Null reference exception while trying to convert a song! FFMPEG path could be set incorrectly!\n{ex}", LogVerbosity.Error);
#else
                Logger.Log($"Null refrence exception while trying to convert a song! FFMPEG path could be set incorrectly!\n{ex.Message}", LogVerbosity.Error);
#endif
                return(null);
            }
            catch (Exception ex)
            {
#if DEBUG
                Logger.Log(ex.ToString(), LogVerbosity.Error);
#else
                Logger.Log(ex.Message, LogVerbosity.Error);
#endif
                return(null);
            }
        }
コード例 #3
0
ファイル: MusicDownloader.cs プロジェクト: jesst3r/Pootis-Bot
        private string DownloadAudio(Video youTubeVideo)
        {
            try
            {
                //Make sure we haven't been canceled yet
                if (cancellationSource.IsCancellationRequested)
                {
                    return(null);
                }

                string videoTitle = youTubeVideo.Title.RemoveIllegalChars();

                MessageUtils.ModifyMessage(message,
                                           $":musical_note: Give me a sec. Downloading **{videoTitle}** from **{youTubeVideo.Author}**...")
                .GetAwaiter().GetResult();

                //Get our video stream info
                MediaStreamInfoSet videoMediaInfo =
                    client.GetVideoMediaStreamInfosAsync(youTubeVideo.Id).GetAwaiter().GetResult();
                AudioStreamInfo streamInfo           = videoMediaInfo.Audio.WithHighestBitrate();
                string          songDownloadLocation = $"{downloadLocation}{videoTitle}.{streamInfo.Container.GetFileExtension()}";

                //Download the audio file
                client.DownloadMediaStreamAsync(streamInfo, songDownloadLocation, null, downloadCancellationToken)
                .GetAwaiter().GetResult();

                //Do another check to make sure our video hasn't been canceled
                if (cancellationSource.IsCancellationRequested)
                {
                    return(null);
                }

                Logger.Log($"The downloaded video file extension is '{streamInfo.Container.GetFileExtension()}'.",
                           LogVerbosity.Debug);
                if (streamInfo.Container.GetFileExtension() != downloadFileContainer.GetFormatExtension())
                {
                    if (cancellationSource.IsCancellationRequested)
                    {
                        return(null);
                    }

                    if (!ConvertAudioFileToMp3(songDownloadLocation,
                                               $"{this.downloadLocation}{videoTitle}.{downloadFileContainer.GetFormatExtension()}"))
                    {
                        if (!disposed)
                        {
                            MessageUtils.ModifyMessage(message,
                                                       "Sorry, but there was an issue downloading the song! Try again later.").GetAwaiter()
                            .GetResult();
                        }
                        return(null);
                    }
                }

                songDownloadLocation   = $"{this.downloadLocation}{videoTitle}.{downloadFileContainer.GetFormatExtension()}";
                hasFinishedDownloading = true;

                //We have finished downloading
                return(songDownloadLocation);
            }
            catch (Exception ex)
            {
#if DEBUG
                Logger.Log(ex.ToString(), LogVerbosity.Error);
#else
                Logger.Log(ex.Message, LogVerbosity.Error);
#endif

                MessageUtils
                .ModifyMessage(message, "Sorry, but there was an issue downloading the song! Try again later.")
                .GetAwaiter().GetResult();

                //Log out an error to the owner if they have it enabled
                if (Config.bot.ReportErrorsToOwner)
                {
                    Global.BotOwner.SendMessageAsync(
                        $"ERROR: {ex.Message}\nError occured while trying to search or download a video from YouTube on guild `{guild.Id}`.");
                }

                //Mark this as true so our error doesn't get deleted
                hasFinishedDownloading = true;

                return(null);
            }
        }
コード例 #4
0
ファイル: AudioService.cs プロジェクト: hnjm/Pootis-Bot
        /// <summary>
        /// Searches music folder for similar or same results to <see cref="search"/>
        /// </summary>
        /// <param name="search">The name of the song to search for</param>
        /// <param name="fileFormat"></param>
        /// <returns>Returns the first found similar or matching result</returns>
        public static string SearchMusicDirectory(string search, MusicFileFormat fileFormat)
        {
            if (!Directory.Exists(MusicDir))
            {
                Directory.CreateDirectory(MusicDir);
            }

            DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(MusicDir);

            FileInfo[] filesInDir = hdDirectoryInWhichToSearch.GetFiles($"*{search}*.{fileFormat.GetFormatExtension()}");

            return(filesInDir.Select(foundFile => foundFile.FullName).FirstOrDefault());
        }
コード例 #5
0
ファイル: AudioService.cs プロジェクト: hnjm/Pootis-Bot
        /// <summary>
        /// Plays a song in a given voice channel
        /// </summary>
        /// <param name="guild">The <see cref="SocketGuild"/> where we are playing in</param>
        /// <param name="channel">The <see cref="IMessageChannel"/> to log messages to</param>
        /// <param name="target">The target <see cref="IVoiceChannel"/> to play music in</param>
        /// <param name="user">The <see cref="IUser"/> who requested this command</param>
        /// <param name="search">The query to search for</param>
        /// <returns></returns>
        public async Task SendAudio(SocketGuild guild, IMessageChannel channel, IVoiceChannel target, IUser user,
                                    string search)
        {
            //Join the voice channel the user is in if we are already not in a voice channel
            if (!CheckIfServerIsPlayingMusic(guild, out ServerMusicItem serverMusicList))
            {
                await JoinAudio(guild, target, channel, user);

                serverMusicList = GetMusicList(guild.Id);
            }

            //Check to see if the user is in the playing audio channel
            if (!await CheckIfUserInChat(user, channel, serverMusicList))
            {
                return;
            }

            //Make sure the search isn't empty or null
            if (string.IsNullOrWhiteSpace(search))
            {
                await channel.SendMessageAsync("You need to input a search!");

                return;
            }

            IUserMessage message =
                await channel.SendMessageAsync($":musical_note: Preparing to search for '{search}'");

            string songFileLocation;
            string songName;

            search.RemoveIllegalChars();

            try
            {
                songFileLocation = await GetOrDownloadSong(search, message, serverMusicList);

                //It failed
                if (songFileLocation == null)
                {
                    return;
                }

                Logger.Log($"Playing song from {songFileLocation}", LogVerbosity.Debug);

                //This is so we say "Now playing 'Epic Song'" instead of "Now playing 'Epic Song.mp3'"
                songName = Path.GetFileName(songFileLocation).Replace($".{fileFormat.GetFormatExtension()}", "");

                //If there is already a song playing, cancel it
                await StopPlayingAudioOnServer(serverMusicList);
            }
            catch (Exception ex)
            {
                Logger.Log(ex.ToString(), LogVerbosity.Error);
                return;
            }

            //Create music playback for our music format
            IMusicPlaybackInterface playbackInterface = serverMusicList.MusicPlayback = CreateMusicPlayback(songFileLocation);

            //Log (if enabled) to the console that we are playing a new song
            if (Config.bot.AudioSettings.LogPlayStopSongToConsole)
            {
                Logger.Log($"The song '{songName}' on server {guild.Name}({guild.Id}) has started.",
                           LogVerbosity.Music);
            }

            serverMusicList.CancellationSource = new CancellationTokenSource();
            CancellationToken token = serverMusicList.CancellationSource.Token;

            serverMusicList.IsPlaying = true;

            //Create an outgoing pcm stream
            await using (AudioOutStream outStream = serverMusicList.AudioClient.CreatePCMStream(AudioApplication.Music))
            {
                bool      fail       = false;
                bool      exit       = false;
                const int bufferSize = 1024;
                byte[]    buffer     = new byte[bufferSize];

                await MessageUtils.ModifyMessage(message, $":musical_note: Now playing **{songName}**.");

                while (!fail && !exit)
                {
                    try
                    {
                        if (token.IsCancellationRequested)
                        {
                            exit = true;
                            break;
                        }

                        //Read from stream
                        int read = await playbackInterface.ReadAudioStream(buffer, bufferSize, token);

                        if (read == 0)
                        {
                            exit = true;
                            break;
                        }

                        //Flush
                        await playbackInterface.Flush();

                        //Write it to outgoing pcm stream
                        await outStream.WriteAsync(buffer, 0, read, token);

                        //If we are still playing
                        if (serverMusicList.IsPlaying)
                        {
                            continue;
                        }

                        //For pausing the song
                        do
                        {
                            //Do nothing, wait till is playing is true
                            await Task.Delay(100, token);
                        } while (serverMusicList.IsPlaying == false);
                    }
                    catch (OperationCanceledException)
                    {
                        //User canceled
                    }
                    catch (Exception ex)
                    {
                        await channel.SendMessageAsync("Sorry, but an error occured while playing!");

                        if (Config.bot.ReportErrorsToOwner)
                        {
                            await Global.BotOwner.SendMessageAsync(
                                $"ERROR: {ex.Message}\nError occured while playing music on guild `{guild.Id}`.");
                        }

                        fail = true;
                    }
                }

                if (Config.bot.AudioSettings.LogPlayStopSongToConsole)
                {
                    Logger.Log($"The song '{songName}' on server {guild.Name}({guild.Id}) has stopped.",
                               LogVerbosity.Music);
                }

                //There wasn't a request to cancel
                if (!token.IsCancellationRequested)
                {
                    await channel.SendMessageAsync($":musical_note: **{songName}** ended.");
                }

                //Clean up
                // ReSharper disable MethodSupportsCancellation
                await outStream.FlushAsync();

                outStream.Dispose();
                serverMusicList.IsPlaying = false;

                playbackInterface.EndAudioStream();
                serverMusicList.MusicPlayback = null;
                // ReSharper restore MethodSupportsCancellation

                serverMusicList.CancellationSource.Dispose();
                serverMusicList.CancellationSource = null;
            }
        }
コード例 #6
0
        public async Task <string> ConvertFileToAudio(string originalLocation, string location,
                                                      bool deleteOriginal             = true,
                                                      MusicFileFormat musicFileFormat = MusicFileFormat.Mp3)
        {
            try
            {
                string fullNewLocation =
                    $"{location}{Path.GetFileName(originalLocation).Replace(Path.GetExtension(originalLocation), "")}.{musicFileFormat.GetFormatExtension()}";

                Logger.Debug("Converting {@OriginalLocation} to {@FullNewLocation}...", originalLocation, fullNewLocation);

                //Start our ffmpeg process
                Process ffmpeg = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName  = $"{Config.bot.AudioSettings.ExternalDirectory}ffmpeg",
                        Arguments =
                            $"-loglevel fatal -nostdin -i \"{originalLocation}\" -ar 48000 -y \"{fullNewLocation}\"",
                        CreateNoWindow         = true,
                        UseShellExecute        = false,
                        RedirectStandardOutput = false
                    }
                };

                ffmpeg.Start();

                while (!ffmpeg.HasExited)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        ffmpeg.Kill(true);
                        ffmpeg.Dispose();
                        return(null);
                    }

                    await Task.Delay(50);
                }

                ffmpeg.Dispose();

                //Delete our old file
                if (deleteOriginal)
                {
                    if (File.Exists(originalLocation))
                    {
                        File.Delete(originalLocation);
                    }
                    else                     //Were the f**k is our fileToConvert then?? This should never happen but it is here anyway
                    {
                        return(null);
                    }
                }

                //So obviously there was an issue converting...
                if (!File.Exists(fullNewLocation))
                {
                    Logger.Debug("There was an issue converting the file!");
                    return(null);
                }

                //Ayy, we converted
                Logger.Debug($"Successfully converted to '{fullNewLocation}'.");
                return(fullNewLocation);
            }
            catch (NullReferenceException ex)
            {
                Logger.Error(
                    "Null reference exception while trying to convert a song! FFMPEG path could be set incorrectly! {@Exception}", ex);

                return(null);
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while trying to convert a video! {@Exception}", ex);

                return(null);
            }
        }