using Discord.WebSocket; using YoutubeExplode.Videos; using YoutubeExplode; using Discord.Rest; using YoutubeExplode.Videos.Streams; namespace Kasbot.Services { public class YoutubeService { public YoutubeService() { } public async Task DownloadPlaylistMetadataFromYoutube(SocketUserMessage message, string search) { var collection = new MediaCollection(); var youtube = new YoutubeClient(); var playlistInfo = await youtube.Playlists.GetAsync(search); await youtube.Playlists.GetVideosAsync(search).ForEachAsync(videoId => { var media = new Media(); media.Name = videoId.Title; media.Length = videoId.Duration ?? new TimeSpan(0); media.VideoId = videoId.Id; media.Message = message; collection.Medias.Add(media); }); collection.CollectionName = playlistInfo.Title; return collection; } public async Task DownloadMetadataFromYoutube(Media media) { var youtube = new YoutubeClient(); IVideo? videoId; if (media.Search.StartsWith("http://") || media.Search.StartsWith("https://")) videoId = await youtube.Videos.GetAsync(media.Search); else videoId = await youtube.Search.GetVideosAsync(media.Search).FirstOrDefaultAsync(); if (videoId == null) { return media; } media.Name = videoId.Title; media.Length = videoId.Duration ?? new TimeSpan(0); media.VideoId = videoId.Id; return media; } public async Task DownloadAudioFromYoutube(Media media) { if (media.VideoId == null) { return null; } var memoryStream = new MemoryStream(); var youtube = new YoutubeClient(); var streamInfoSet = await youtube.Videos.Streams.GetManifestAsync((VideoId)media.VideoId); var streamInfo = streamInfoSet.GetAudioOnlyStreams().GetWithHighestBitrate(); var streamVideo = await youtube.Videos.Streams.GetAsync(streamInfo); streamVideo.Position = 0; streamVideo.CopyTo(memoryStream); memoryStream.Position = 0; return memoryStream; } public SearchType GetSearchType(string query) { if (string.IsNullOrEmpty(query)) return SearchType.None; if (query.StartsWith("http://") || query.StartsWith("https://")) { if (query.Contains("playlist?list=")) return SearchType.PlaylistURL; // need to add 'else if' for ChannelURL return SearchType.VideoURL; } return SearchType.StringSearch; } } public enum SearchType { None, StringSearch, VideoURL, PlaylistURL, ChannelURL } public class Media { public string Search { get; set; } public string Name { get; set; } public TimeSpan Length { get; set; } public VideoId? VideoId { get; set; } public RestUserMessage PlayMessage { get; set; } public RestUserMessage? QueueMessage { get; set; } public bool Repeat { get; set; } private SocketUserMessage message; public SocketUserMessage Message { get => message; set { message = value; this.Channel = value.Channel; } } public ISocketMessageChannel Channel { get; private set; } } public class MediaCollection { public string CollectionName { get; set; } public List Medias { get; set; } = new List(); } }