public static async Task <(ResultType result, string[] files)> Download( IVideoJob job, CancellationToken cancellationToken, string targetFolder, List <DownloadInfo> downloadInfos, int delayPerDownload = 0 ) { Directory.CreateDirectory(targetFolder); List <string> files = new List <string>(downloadInfos.Count); const int MaxTries = 5; int triesLeft = MaxTries; while (files.Count < downloadInfos.Count) { if (triesLeft <= 0) { job.Status = "Failed to download individual parts after " + MaxTries + " tries, aborting."; return(ResultType.Failure, null); } files.Clear(); for (int i = 0; i < downloadInfos.Count; ++i) { //for (int i = downloadInfos.Count - 1; i >= 0; --i) { if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled, null); } DownloadInfo downloadInfo = downloadInfos[i]; string outpath = Path.Combine(targetFolder, downloadInfo.FilesystemId + ".ts"); string outpath_temp = outpath + ".tmp"; if (await Util.FileExists(outpath_temp)) { await Util.DeleteFile(outpath_temp); } if (outpath.EndsWith("--2d--muted--2e--ts__.ts")) { string alt_outpath = outpath.Substring(0, outpath.Length - "--2d--muted--2e--ts__.ts".Length) + "--2e--ts__.ts"; if (await Util.FileExists(alt_outpath)) { if (i % 100 == 99) { job.Status = "Already have part " + (i + 1) + "/" + downloadInfos.Count + "..."; } files.Add(alt_outpath); continue; } } if (await Util.FileExists(outpath)) { if (i % 100 == 99) { job.Status = "Already have part " + (i + 1) + "/" + downloadInfos.Count + "..."; } files.Add(outpath); continue; } bool success = false; { System.Net.WebClient client = null; try { if (downloadInfo.Length != null && downloadInfo.Offset != null) { client = new KeepAliveWebClientWithRange(downloadInfo.Offset.Value, downloadInfo.Offset.Value + downloadInfo.Length.Value - 1); } else { client = new KeepAliveWebClient(); } job.Status = "Downloading files... (" + (files.Count + 1) + "/" + downloadInfos.Count + ")"; byte[] data = await client.DownloadDataTaskAsync(downloadInfo.Url); await job.StallWrite(outpath_temp, data.LongLength, cancellationToken); if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled, null); } using (FileStream fs = File.Create(outpath_temp)) { await fs.WriteAsync(data, 0, data.Length); } success = true; } catch (System.Net.WebException ex) { System.Net.HttpWebResponse httpWebResponse = ex.Response as System.Net.HttpWebResponse; if (httpWebResponse != null) { switch (httpWebResponse.StatusCode) { case System.Net.HttpStatusCode.NotFound: Newtonsoft.Json.Linq.JObject reply = Newtonsoft.Json.Linq.JObject.Parse(new StreamReader(httpWebResponse.GetResponseStream()).ReadToEnd()); string detail = reply["errors"][0]["detail"].ToObject <string>(); if (detail == "No chats for this Video") { return(ResultType.Dead, null); } break; default: Console.WriteLine("Server returned unhandled error code: " + httpWebResponse.StatusCode); break; } } else { Console.WriteLine(ex.ToString()); } continue; } finally { if (client != null) { client.Dispose(); } } } if (success) { await job.StallWrite(outpath, new FileInfo( outpath_temp ).Length, cancellationToken); if (cancellationToken.IsCancellationRequested) { return(ResultType.Cancelled, null); } File.Move(outpath_temp, outpath); files.Add(outpath); } if (delayPerDownload > 0) { try { await Task.Delay(delayPerDownload, cancellationToken); } catch (TaskCanceledException) { return(ResultType.Cancelled, null); } } } if (files.Count < downloadInfos.Count) { try { await Task.Delay(60000, cancellationToken); } catch (TaskCanceledException) { return(ResultType.Cancelled, null); } --triesLeft; } } return(ResultType.Success, files.ToArray()); }
public bool EnqueueJob( IVideoJob job ) { if ( JobExists( job.VideoInfo.Service, job.VideoInfo.VideoId ) ) { return false; } job.StatusUpdater = new StatusUpdate.ObjectListViewStatusUpdate( objectListViewDownloads, job ); objectListViewDownloads.AddObject( job ); job.Status = "Waiting..."; JobQueue.Enqueue( job ); if ( Util.ShowToastNotifications ) { ToastUtil.ShowToast( "Enqueued " + job.HumanReadableJobName + "!" ); } InvokeSaveJobs(); return true; }
public async Task RunJob( IVideoJob job = null, bool forceStart = false ) { bool runNewJob = false; lock ( Lock ) { if ( ( forceStart || RunningJobs < MaxRunningJobs ) && ( job != null || JobQueue.TryDequeue( out job ) ) ) { // TODO: This almost certainly has odd results if one thread tries to dequeue a job that was force-started from somewhere else! ++RunningJobs; runNewJob = true; } } if ( runNewJob ) { try { if ( job.JobStatus != VideoJobStatus.Finished ) { await job.Run(); if ( Util.ShowToastNotifications ) { ToastUtil.ShowToast( "Downloaded " + job.HumanReadableJobName + "!" ); } } } catch ( Exception ex ) { job.JobStatus = VideoJobStatus.NotStarted; job.Status = "ERROR: " + ex.ToString(); if ( Util.ShowToastNotifications ) { ToastUtil.ShowToast( "Failed to download " + job.HumanReadableJobName + ": " + ex.ToString() ); } } InvokeSaveJobs(); lock ( Lock ) { --RunningJobs; } InvokePowerEvent(); await RunJob(); } }
public bool Equals(IVideoJob other) { return(other != null && VideoInfo.Equals(other.VideoInfo)); }