using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using YoutubeExplode.Videos; using YoutubeExplode; using System.Net.Http; using System.Net; using System.IO; using TessesYoutubeDownloader.Server.Models; using Newtonsoft.Json; using YoutubeExplode.Videos.Streams; using YoutubeExplode.Channels; using YoutubeExplode.Playlists; using youtube_downloader.Server.Models; namespace youtube_downloader.Server.Functions { public class Downloader { public Downloader() { // TessesYoutubeDownloader.Server.Functions.Downloader.DL.DownloadThread().GetAwaiter().GetResult(); } public List infoQueue = new List(); public static YoutubeClient CreateYoutubeClient() { ServicePointManager .ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; HttpClientHandler handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; Http = new HttpClient(handler); return new YoutubeExplode.YoutubeClient(Http); } internal static VideoDownloadProgress GetProgress() { return P; } static HttpClient Http; internal YoutubeClient ytc = CreateYoutubeClient(); static VideoDownloadProgress P=new VideoDownloadProgress(); Progress DownloadP =new Progress( (e)=> { P.Progress = (int)(e * 100.0); }); public List Queue = new List(); internal static string GetQueue() { string q; lock (DL.Queue) { q = JsonConvert.SerializeObject(DL.Queue.Select(o => o.Video)) ; } return q; } public async Task ListenForQueueItem() { do { InfomationQueueItem item; bool canAdd = false; lock (infoQueue) { canAdd = infoQueue.Count > 0; if (canAdd) { item = infoQueue[0]; infoQueue.RemoveAt(0); } else { item = null; } } if (canAdd) { try { var items = await item.DownloadData(); if (item.DownloadActualDataAfterwards) { _DownloadVideos(items); } }catch(Exception ex) { Console.WriteLine(ex.Message); _ = ex; } } } while (true); } internal static void ModQueue(string mvto, string index) { try { //?mv=up|down|top|bottom|remove,int&i=0,last lock (DL.Queue) { int index2 = 0; if (index == "last") { index2 = DL.Queue.Count - 1; } else { if (!int.TryParse(index, out index2)) { index2 = 0; } } if (index2 >= DL.Queue.Count) { index2 = DL.Queue.Count - 1; } if (mvto == "top") { var v = DL.Queue[index2]; DL.Queue.Remove(v); DL.Queue.Insert(0,v); } else if (mvto == "bottom") { var v = DL.Queue[index2]; DL.Queue.Remove(v); DL.Queue.Add(v); } else if (mvto == "remove") { var v = DL.Queue[index2]; DL.Queue.Remove(v); } else if (mvto == "up") { if (index2 > 0) { var v = DL.Queue[index2]; DL.Queue.Remove(v); DL.Queue.Insert(index2 - 1, v); } } else if (mvto == "down") { if (index2 < DL.Queue.Count - 1) { var v = DL.Queue[index2]; DL.Queue.Remove(v); DL.Queue.Insert(index2 + 1, v); } } else { int n1; if (int.TryParse(mvto, out n1)) { var v = DL.Queue[index2]; DL.Queue.Remove(v); if (n1 > index2) { DL.Queue.Insert(n1 - 1, v); } else { DL.Queue.Insert(n1, v); } } } } }catch(Exception ex) { _ = ex; } } internal static void DownloadChannelOnly(string id) { ChannelId? v = ChannelId.TryParse(id); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value,Resolution.NoConvert,false); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } internal static void DownloadUserOnly(string id) { UserName? v = UserName.TryParse(id); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value, Resolution.NoConvert, false); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } public bool Continue(string v) { if (File.Exists(v)) { using(var f = File.OpenRead(v)) { return f.Length == 0; } } return true; } private string gStorageLocation() { if (System.IO.File.Exists("loc.txt")) { string loc=System.IO.File.ReadAllText("loc.txt"); try { System.IO.Directory.CreateDirectory(loc); if (System.IO.Directory.Exists(loc)) { return loc; } }catch(Exception ex) { _ = ex; } } return Environment.CurrentDirectory; } public string StorageLocation { get { return gStorageLocation(); } } private void _DownloadVideos(SavedVideoObject[] items) { lock (Queue) { foreach (var item in items) { Queue.Insert(0, item); //new elements get added to begining } } } public async Task DownloadThread() { do { bool canDownload = false; SavedVideoObject v; lock (Queue) { canDownload= Queue.Count > 0; if (canDownload) { v = Queue[0]; Queue.RemoveAt(0); P.Saved = v.Video; Console.WriteLine($"Download: {v.Video.Title}"); } else { v = null; } } if (canDownload) { switch (v.Resolution) { case Resolution.Convert: string mypath = GetPath(true, "Converted", v.Video.Id + "-vidonly.bkp"); string mypathaudio = GetPath(true, "Audio", v.Video.Id + "incomplete.mp4"); string mypathCompleteAudio = GetPath(true, "Audio", v.Video.Id + ".mp4"); string mypathComplete = GetPath(true, "Converted", v.Video.Id + ".mp4"); string mypathIncompleteConverting = GetPath(true, "Converted", "conv.mkv"); if (Continue(mypathComplete)) { var s3 = await ytc.Videos.Streams.GetManifestAsync(v.Video.Id); var best2 = s3.GetAudioOnlyStreams().GetWithHighestBitrate(); var best = s3.GetVideoOnlyStreams().GetWithHighestVideoQuality(); P.Length = best.Size.Bytes + best2.Size.Bytes; ProgressTwo p = new ProgressTwo(best.Size.Bytes, best2.Size.Bytes, DownloadP); await ytc.Videos.Streams.DownloadAsync(best,mypath, p.Video); IProgress pv = p.Video; pv.Report(1); if (Continue(mypathCompleteAudio)) { await ytc.Videos.Streams.DownloadAsync(best2, mypathaudio,p.Audio); File.Move(mypathaudio, mypathCompleteAudio); } IProgress pa = p.Video; pa.Report(1); ffmpeg.mux(mypath,mypathCompleteAudio,mypathIncompleteConverting); File.Move(mypathIncompleteConverting, mypathComplete); } break; case Resolution.NoConvert: string mypath2 = GetPath(true, "NotConverted", v.Video.Id + "incomplete.mp4"); string mypath2Complete = GetPath(true, "NotConverted", v.Video.Id + ".mp4"); if (Continue(mypath2Complete)) { var s = await ytc.Videos.Streams.GetManifestAsync(v.Video.Id); var best = s.GetMuxedStreams().GetWithHighestVideoQuality(); P.Length = best.Size.Bytes; await ytc.Videos.Streams.DownloadAsync(best, mypath2, DownloadP); File.Move(mypath2, mypath2Complete); } break; case Resolution.Audio: string mypath3 = GetPath(true, "Audio", v.Video.Id + "incomplete.mp4"); string mypath3Complete = GetPath(true, "Audio", v.Video.Id + ".mp4"); if (Continue(mypath3Complete)) { var s2 = await ytc.Videos.Streams.GetManifestAsync(v.Video.Id); var best2 = s2.GetAudioOnlyStreams().GetWithHighestBitrate(); P.Length = best2.Size.Bytes; await ytc.Videos.Streams.DownloadAsync(best2, mypath3, DownloadP); File.Move(mypath3, mypath3Complete); } break; } } System.Threading.Thread.Sleep(1); } while (true); } internal void _DownloadThumbnail(int w,int h,string id,string tnail) { try { string p = GetPath(true,"Thumbnails", w.ToString() + 'x' + h.ToString(), id + ".jpg"); if (!File.Exists(p)) { ffmpeg.download_thumbnail(tnail, p); } } catch(Exception ex) { _ = ex; } } internal static List GetQueueItems() { return DL.Queue; } public static void DownloadVideo(string id,Resolution res) { VideoId? v = VideoId.TryParse(id); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value, res, true); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } public static void DownloadVideo(string v) { DownloadVideo(v, Resolution.NoConvert); } public static void DownloadPlaylist(string id,Resolution res) { PlaylistId? v = PlaylistId.TryParse(id); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value, res, true); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } public static void DownloadPlaylist(string id) { DownloadPlaylist(id, Resolution.NoConvert); } public static void DownloadChannel(string id,Resolution res) { ChannelId? v = ChannelId.TryParse(id); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value, res, true); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } public static void DownloadChannel(string id) { DownloadChannel(id, Resolution.NoConvert); } public static void DownloadUser(string name, Resolution res) { UserName? v=UserName.TryParse(name); if (v.HasValue) { InfomationQueueItem item = new InfomationQueueItem(v.Value, res, true); lock (DL.infoQueue) { DL.infoQueue.Insert(0, item); } } } public static void DownloadUser(string name) { DownloadUser(name, Resolution.NoConvert); } public string GetPath(bool createParent,params string[] _path) { if (createParent) { string dir = GetPath(_path); try { Directory.CreateDirectory(Path.GetDirectoryName(dir)); }catch(Exception ex) { _ = ex; } return dir; } else { return GetPath(_path); } } private string GetPath(params string[] _path) { string[] array2 = new string[_path.Length + 1]; array2[0] = StorageLocation; Array.Copy(_path, 0, array2, 1,_path.Length); return System.IO.Path.Combine(array2); } public static Downloader DL = new Downloader(); } }