added /api/endpoint

This commit is contained in:
Mike Nolan 2021-12-12 04:04:16 -06:00
parent 31366d7206
commit 1102aa66ac
14 changed files with 1180 additions and 356 deletions

View File

@ -7,7 +7,7 @@
<File FileName="TYTD.Api/Server/Models/SavedVideo.cs" Line="8" Column="1" />
<File FileName="TYTD.Api/Server/Models/InfomationQueueItem.cs" Line="125" Column="50" />
<File FileName="TYTD.Api/Server/Functions/ffmpeg.cs" Line="5" Column="15" />
<File FileName="Program.cs" Line="126" Column="26" />
<File FileName="Program.cs" Line="126" Column="1" />
<File FileName="TYTD.Api/MyClass.cs" Line="92" Column="6" />
<File FileName="TYTD.Api/Server/Models/SavedChannel.cs" Line="6" Column="10" />
<File FileName="TYTD.Api/Server/Models/SavedPlaylist.cs" Line="7" Column="1" />
@ -37,7 +37,7 @@
<MonoDevelop.Ide.ItemProperties.youtube-downloader PreferredExecutionTarget="MonoDevelop.Default" />
<MonoDevelop.Ide.DebuggingService.Breakpoints>
<BreakpointStore>
<Breakpoint file="/home/ddlovato/tytd/site/TYTD.Api/Server/Models/YoutubeDownloaderResponse.cs" relfile="TYTD.Api/Server/Models/YoutubeDownloaderResponse.cs" line="10" column="1" />
<Breakpoint file="/home/mike/Git/site/TYTD.Api/Server/Models/YoutubeDownloaderResponse.cs" relfile="TYTD.Api/Server/Models/YoutubeDownloaderResponse.cs" line="10" column="1" />
</BreakpointStore>
</MonoDevelop.Ide.DebuggingService.Breakpoints>
<MultiItemStartupConfigurations />

View File

@ -99,11 +99,14 @@ namespace TYTD
Route.Add("/api/Storage/VideoRes/{Res}/{Id}",(HttpAction)VideoRes);
Route.Add("/api/upload/", (HttpAction)UploadFiles, "POST");
Route.Add("/api/endpoint", (HttpAction)Endpoint,"POST");
ApiLoader.Init();
/* Other */
Route.Add("/", (HttpAction)Index);
Route.Add("/extensions.html", (HttpAction)Extensions);
Route.Add("/{Path}", (HttpAction)RootPath);
Route.Add("/{Path}",(HttpAction)UploadFilePut,"PUT");
Console.CancelKeyPress += (sender, e) => { ApiLoader.Dispose();var date = DateTime.Now.ToString("yyyyMMdd_HHmmss");File.WriteAllText(Path.Combine("config","queues-close",$"{date}.json"), Downloader.GetQueue()); return; };
@ -121,6 +124,8 @@ namespace TYTD
}
}
private static async Task<StreamManifest> GetManifest(YoutubeClient arg1, VideoId arg2)
{
return await arg1.Videos.Streams.GetManifestAndFixStreamUrlsAsync(arg2);
@ -186,7 +191,7 @@ namespace TYTD
{
foreach (var item in Directory.GetFiles(Downloader.DL.GetPath(true, "Info"), "*.json"))
{
string id = System.IO.Path.GetFileNameWithoutExtension(item);
string id =Path.GetFileNameWithoutExtension(item);
Downloader.DownloadVideo(id, Resolution.NoConvert);
}
rp.AsRedirect("/");
@ -300,15 +305,22 @@ namespace TYTD
rp.AsText(json, "application/json");
}
public static void Redo(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary<string, string> args)
{
lock (Downloader.DL.cancelSrc)
{
Downloader.RedownloadIt = true;
Downloader.DownloadIt = false;
Downloader.DL.cancelSrc.Item.Cancel();
}
}
public static void Cancel(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary<string, string> args)
{
lock (Downloader.DL.cancelSrc)
{
Downloader.RedownloadIt = false;
Downloader.DownloadIt = false;
Downloader.DL.cancelSrc.Item.Cancel();
}
}
#endregion
@ -364,9 +376,49 @@ namespace TYTD
else
{
string path = Downloader.DL.GetPath(true, args["Path"]);
if (Directory.Exists(path))
{
string indexHtml = Path.Combine(path, "index.html");
if (File.Exists(indexHtml))
{
path = indexHtml;
}
else
{
string dir = Path.Combine(webSitePath, "err", "dir.html");
StringBuilder b = new StringBuilder();
var f = Directory.GetLastWriteTime(Path.GetDirectoryName(path));
string parentModified = $"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"..\">Up</a></td><td>{parentModified}</td><td>DIR</td></tr>");
foreach (var file in Directory.GetDirectories(path))
{
string name = Path.GetFileName(file);
string nameUrled = System.Web.HttpUtility.UrlEncode(name);
string nameHtmled = System.Web.HttpUtility.HtmlEncode(name);
f = Directory.GetLastWriteTime(file);
string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"{nameUrled}\">{nameHtmled}</a></td><td>{dateModifed}</td><td>DIR</td></tr>");
}
foreach (var file in Directory.GetFiles(path))
{
string name = Path.GetFileName(file);
string nameUrled = System.Web.HttpUtility.UrlEncode(name);
string nameHtmled = System.Web.HttpUtility.HtmlEncode(name);
f = File.GetLastWriteTime(file);
string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"{nameUrled}\">{nameHtmled}</a></td><td>{dateModifed}</td><td>FILE</td></tr>");
}
Dictionary<string, string> templating = new Dictionary<string, string>();
templating.Add("Items", b.ToString());
rp.AsText(Templating.RenderFile(dir, templating));
return;
}
}
rp.AsFile(rq, path);
}
}
public static void Video(HttpListenerRequest rq,HttpListenerResponse rp,Dictionary<string,string> args)
{
@ -385,7 +437,7 @@ namespace TYTD
}
public static void VideoRes(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary<string, string> args)
{
YoutubeExplode.Videos.VideoId? vid = YoutubeExplode.Videos.VideoId.TryParse(args["Id"]);
VideoId? vid = VideoId.TryParse(args["Id"]);
if (vid.HasValue)
{
int res;
@ -466,9 +518,218 @@ namespace TYTD
{
rp.AsText(ApiLoader.Page);
}
private static void UploadFilePut(HttpListenerRequest request, HttpListenerResponse response, Dictionary<string, string> arguments)
{
string p = arguments["Path"].Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0];
string path = Path.Combine(webSitePath, p);
bool exists = File.Exists(path);
using (var instr = request.InputStream)
{
using (var outStr = File.Create(path))
{
instr.CopyTo(outStr);
}
}
if (exists)
{
response.WithCode(HttpStatusCode.NoContent);
}
else
{
response.WithCode(HttpStatusCode.Created);
}
}
private static void Endpoint(HttpListenerRequest request, HttpListenerResponse response, Dictionary<string, string> arguments)
{
request.ParseBody(arguments);
List<string> print = new List<string>();
bool hasOtherResponse=false;
bool success = true;
if(arguments.ContainsKey("operation"))
{
if (arguments["operation"] == "server_download")
{
if (arguments.ContainsKey("url"))
{
string myUrl = arguments["url"];
if (arguments.ContainsKey("resolution"))
{
uint res;
if (uint.TryParse(arguments["resolution"], out res) && res <= 2)
{
Downloader.DownloadItem(myUrl, (Resolution)res);
}
else
{
print.Add("WARNING: argument resolution shall not be greater than 3 or less than 0");
Downloader.DownloadItem(myUrl);
}
}
else
{
Downloader.DownloadItem(myUrl);
}
}
}
else if (arguments["operation"] == "download")
{
if (arguments.ContainsKey("url"))
{
VideoId? vid = VideoId.TryParse(arguments["url"]);
if (vid.HasValue)
{
if (arguments.ContainsKey("resolution"))
{
int res;
if (int.TryParse(arguments["resolution"], out res))
{
if (res > 2 || res < 0)
{
print.Add("Invalid Resolution Number must be either 0, 1 or 2");
}
else
{
string[] m = new string[] { "Converted", "NotConverted", "Audio" };
string path = Downloader.DL.GetPath(true, m[res], vid.Value + ".mp4");
response.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString());
response.AsFile(request, path);
hasOtherResponse = true;
}
}
else
{
print.Add("Res is not a number");
}
}
else
{
string path = Downloader.DL.GetPath(true, "NotConverted", vid.Value + ".mp4");
response.AddHeader("Content-Disposition", GetVideoContentDisposition(vid.Value).ToString());
response.AsFile(request, path);
hasOtherResponse = true;
}
}
else
{
success = false;
print.Add("Invalid Video ID or URL");
}
}
}
else if (arguments["operation"] == "enumerate_queue")
{
string json = Downloader.GetQueue();
response.AsText(json, "application/json");
hasOtherResponse = true;
}
else if (arguments["operation"] == "progress")
{
string json = JsonConvert.SerializeObject(Downloader.GetProgress());
response.AsText(json, "application/json");
hasOtherResponse = true;
}
else if(arguments["operation"] == "queue_move")
{
bool containsId = arguments.ContainsKey("id");
bool containsIndex = arguments.ContainsKey("index");
if (containsId ^ containsIndex)
{
success = false;
print.Add("You cant use both id and index");
}
else
{
if (arguments.ContainsKey("to"))
{
string to_loc = arguments["to"];
if(containsId)
Downloader.ModQueue2(to_loc, arguments["id"]);
if (containsIndex)
Downloader.ModQueue(to_loc, arguments["index"]);
}
else
{
success = false;
print.Add("You must have the &quot;to&quot; variable set");
}
}
}
else
{
success = false;
}
}
if(success)
{
print.Add("Your request was delt with successfully");
}
else if(!hasOtherResponse)
{
response.WithCode(HttpStatusCode.BadRequest);
}
if (!hasOtherResponse)
{
response.AsText(string.Join("<br>", print));
}
}
public static void RootPath(HttpListenerRequest rq, HttpListenerResponse rp, Dictionary<string, string> args)
{
string path = Path.Combine(webSitePath, args["Path"].Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0]);
string p = args["Path"].Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0];
string path = Path.Combine(webSitePath, p);
if (Directory.Exists(path))
{
string indexHtml = Path.Combine(path, "index.html");
if(File.Exists(indexHtml))
{
path = indexHtml;
}
else
{
string dir = Path.Combine(webSitePath,"err", "dir.html");
StringBuilder b = new StringBuilder();
var f= Directory.GetLastWriteTime(Path.GetDirectoryName(path));
string parentModified = $"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"..\">Up</a></td><td>{parentModified}</td><td>DIR</td></tr>");
foreach (var file in Directory.GetDirectories(path))
{
string name = Path.GetFileName(file);
string nameUrled = System.Web.HttpUtility.UrlEncode(name);
string nameHtmled = System.Web.HttpUtility.HtmlEncode(name);
f= Directory.GetLastWriteTime(file);
string dateModifed =$"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"{nameUrled}\">{nameHtmled}</a></td><td>{dateModifed}</td><td>DIR</td></tr>");
}
foreach (var file in Directory.GetFiles(path))
{
string name = Path.GetFileName(file);
string nameUrled = System.Web.HttpUtility.UrlEncode(name);
string nameHtmled = System.Web.HttpUtility.HtmlEncode(name);
f = File.GetLastWriteTime(file);
string dateModifed = $"{f.ToShortDateString()} {f.ToShortTimeString()}";
b.Append($"<tr><td><a href=\"{nameUrled}\">{nameHtmled}</a></td><td>{dateModifed}</td><td>FILE</td></tr>");
}
Dictionary<string, string> templating = new Dictionary<string, string>();
templating.Add("Items", b.ToString());
rp.AsText(Templating.RenderFile(dir, templating));
return;
}
}
rp.AsFile(rq, path);
}

View File

@ -15,19 +15,36 @@ using YoutubeExplode.Channels;
using YoutubeExplode.Playlists;
using Dasync.Collections;
using System.Threading;
namespace TYTD.Server.Functions
{
public class Downloader
{
public Downloader()
{
// TessesYoutubeDownloader.Server.Functions.Downloader.DL.DownloadThread().GetAwaiter().GetResult();
public class Lockable<T>
{
public Lockable(Func<T> recreate)
{
_recreate = recreate;
}
Func<T> _recreate;
public void Recreate()
{
Item = _recreate();
}
public T Item { get; set; }
public void Change(T item)
{
Item = item;
}
public static implicit operator T(Lockable<T> item)
{
return item.Item;
}
}
public static bool DownloadIt = true;
public static bool RedownloadIt = false;
public List<InfomationQueueItem> infoQueue = new List<InfomationQueueItem>();
public static YoutubeClient CreateYoutubeClient()
@ -401,11 +418,530 @@ namespace TYTD.Server.Functions
nameDest= Path.Combine(Path.GetDirectoryName(nameSrc), $"{Path.GetFileNameWithoutExtension(nameSrc)} ({i}){Path.GetExtension(nameSrc)}");
return File.Exists(nameDest);
}
public Lockable<CancellationTokenSource> cancelSrc = new Lockable<CancellationTokenSource>(()=> { return new CancellationTokenSource(); });
public static Func<YoutubeClient,VideoId, Task<StreamManifest>> GetManifest;
public async Task DownloadThread()
private async Task DownloadHDVideo(SavedVideoObject v,CancellationToken token)
{
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 GetManifest(ytc, 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);
using (var destStrm = File.Open(mypath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
long pos = 0;
long len = 0;
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best,token))
{
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = p.Video;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = await srcStrm.ReadAsync(buffer, 0, buffer.Length,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
await destStrm.WriteAsync(buffer, 0, read,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0 );
}
}
IProgress<double> pv = p.Video;
pv.Report(1);
if (Continue(mypathCompleteAudio))
{
long pos = 0;
long len = 0;
using (var destStrm = File.Open(mypathaudio, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best2,token))
{
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = p.Audio;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = await srcStrm.ReadAsync(buffer, 0, buffer.Length,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
await destStrm.WriteAsync(buffer, 0, read,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadHDVideo(v, token);
}
return;
}
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0);
}
}
File.Move(mypathaudio, mypathCompleteAudio);
}
IProgress<double> pa = p.Video;
pa.Report(1);
ffmpeg.mux(mypath, mypathCompleteAudio, mypathIncompleteConverting);
File.Move(mypathIncompleteConverting, mypathComplete);
}
}
private async Task DownloadSDVideo(SavedVideoObject v, CancellationToken token)
{
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 GetManifest(ytc, v.Video.Id);
var best = s.GetMuxedStreams().GetWithHighestVideoQuality();
P.Length = best.Size.Bytes;
long pos = 0;
long len = 0;
using (var destStrm = File.Open(mypath2, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best, token))
{
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadSDVideo(v, token);
}
return;
}
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = DownloadP;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = await srcStrm.ReadAsync(buffer, 0, buffer.Length, token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadSDVideo(v, token);
}
return;
}
await destStrm.WriteAsync(buffer, 0, read, token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadSDVideo(v, token);
}
return;
}
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0);
}
}
File.Move(mypath2, mypath2Complete);
}
}
private async Task DownloadAudio(SavedVideoObject v, CancellationToken token)
{
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 GetManifest(ytc, v.Video.Id);
var best2 = s2.GetAudioOnlyStreams().GetWithHighestBitrate();
P.Length = best2.Size.Bytes;
long pos = 0;
long len = 0;
using (var destStrm = File.Open(mypath3, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best2,token))
{
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadAudio(v, token);
}
return;
}
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = DownloadP;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = await srcStrm.ReadAsync(buffer, 0, buffer.Length,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadAudio(v, token);
}
return;
}
await destStrm.WriteAsync(buffer, 0, read,token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcStrm.Dispose();
destStrm.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadAudio(v, token);
}
return;
}
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0);
}
}
File.Move(mypath3, mypath3Complete);
}
}
private async Task DownloadFileAsync(SavedVideoObject v,CancellationToken token)
{
var req = await Http.GetAsync(v.Video.Id, token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadFileAsync(v, token);
}
return;
}
long? Len = req.Content.Headers.ContentLength;
Uri u = new Uri(v.Video.Id);
string abs = u.AbsolutePath;
string name = "file.bin";
if (abs.Contains("/"))
{
name = abs.Substring(abs.LastIndexOf('/') + 1);
}
if (req.Content.Headers.Contains("Content-Disposition"))
{
name = req.Content.Headers.ContentDisposition.FileName;
}
int fileI = 1;
P.Saved.Title = name;
name = GetPath(true, "Download", name);
string filename = name;
while (FileExists(name, ref filename, ref fileI)) { }
long Len2 = long.MaxValue;
if (Len.HasValue)
{
if (Len.Value > 0)
{
Len2 = Len.Value;
}
}
P.Length = Len2;
long Pos = 0;
byte[] buffer = new byte[4096];
int Cycles = 0;
IProgress<double> p = DownloadP;
int CYCLES_BETWEEN_REPORT = 1;
using (var srcFile = await req.Content.ReadAsStreamAsync())
{
using (var destFile = File.Create(filename))
{
int read;
do
{
read = await srcFile.ReadAsync(buffer, 0, buffer.Length, token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcFile.Dispose();
destFile.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadFileAsync(v, token);
}
return;
}
await destFile.WriteAsync(buffer, 0, read, token);
if (token.IsCancellationRequested)
{
cancelSrc.Item.Dispose();
cancelSrc.Recreate();
if (RedownloadIt)
{
srcFile.Dispose();
destFile.Dispose();
lock (cancelSrc)
{
token = cancelSrc.Item.Token;
}
await DownloadFileAsync(v, token);
}
return;
}
Pos += read;
Cycles++;
if (Cycles > CYCLES_BETWEEN_REPORT)
{
Cycles = 0;
p.Report(Pos / Len2);
}
} while (read > 0);
}
}
p.Report(1);
}
private async Task DownloadItem(CancellationToken token)
{
P.Progress = 0;
P.ProgressRaw = 0;
await Task.Delay(2000);
bool canDownload = false;
SavedVideoObject v;
lock (Queue)
@ -443,285 +979,33 @@ namespace TYTD.Server.Functions
ApiLoader.DownloadStarted(this, evt);
if (evt.Cancel)
{
DownloadIt = true;
goto nope;
}
redownload:
try
{
if (v.RegularFile) {
var req=await Http.GetAsync(v.Video.Id);
long? Len=req.Content.Headers.ContentLength;
Uri u = new Uri(v.Video.Id);
string abs = u.AbsolutePath;
string name = "file.bin";
if(abs.Contains("/"))
{
name=abs.Substring(abs.LastIndexOf('/') + 1);
}
if (req.Content.Headers.Contains("Content-Disposition"))
{
name=req.Content.Headers.ContentDisposition.FileName;
}
int fileI=1;
P.Saved.Title = name;
name=GetPath(true, "Download", name);
string filename=name;
while (FileExists(name, ref filename, ref fileI)) ;
long Len2 = long.MaxValue;
if(Len.HasValue)
{
if(Len.Value > 0)
{
Len2 = Len.Value;
}
return;
}
P.Length = Len2;
long Pos = 0;
byte[] buffer = new byte[4096];
int Cycles = 0;
IProgress<double> p = DownloadP;
int CYCLES_BETWEEN_REPORT = 1;
using (var srcFile = await req.Content.ReadAsStreamAsync())
try
{
using (var destFile = File.Create(filename))
if (v.RegularFile)
{
int read;
do
{
read = await srcFile.ReadAsync(buffer, 0, buffer.Length);
await destFile.WriteAsync(buffer, 0, read);
Pos += read;
Cycles++;
if (Cycles > CYCLES_BETWEEN_REPORT)
{
Cycles = 0;
p.Report(Pos / Len2);
}
} while (read > 0 && DownloadIt);
}
}
p.Report(1);
await DownloadFileAsync(v, token);
}
else
{
switch (v.Resolution)
{
case Resolution.Convert:
await DownloadHDVideo(v, token);
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 GetManifest(ytc,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);
using (var destStrm = System.IO.File.Open(mypath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
long pos = 0;
long len = 0;
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best))
{
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = p.Video;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = srcStrm.Read(buffer, 0, buffer.Length);
destStrm.Write(buffer, 0, read);
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0 && DownloadIt ) ;
}
}
IProgress<double> pv = p.Video;
pv.Report(1);
if (Continue(mypathCompleteAudio))
{
long pos = 0;
long len = 0;
using (var destStrm = File.Open(mypathaudio, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best2))
{
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = p.Audio;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = srcStrm.Read(buffer, 0, buffer.Length);
destStrm.Write(buffer, 0, read);
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0 && DownloadIt);
}
}
if(DownloadIt)
{
File.Move(mypathaudio, mypathCompleteAudio);
}
}
IProgress<double> pa = p.Video;
if (DownloadIt)
{
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 GetManifest(ytc,v.Video.Id);
var best = s.GetMuxedStreams().GetWithHighestVideoQuality();
P.Length = best.Size.Bytes;
long pos = 0;
long len = 0;
using (var destStrm = System.IO.File.Open(mypath2, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best))
{
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = DownloadP;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = srcStrm.Read(buffer, 0, buffer.Length);
destStrm.Write(buffer, 0, read);
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0 && DownloadIt);
}
}
if (DownloadIt)
{
File.Move(mypath2, mypath2Complete);
}
}
await DownloadSDVideo(v, token);
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 GetManifest(ytc,v.Video.Id);
var best2 = s2.GetAudioOnlyStreams().GetWithHighestBitrate();
P.Length = best2.Size.Bytes;
long pos = 0;
long len = 0;
using (var destStrm = System.IO.File.Open(mypath3, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var srcStrm = await ytc.Videos.Streams.GetAsync(best2))
{
len = srcStrm.Length;
pos = destStrm.Length;
IProgress<double> myProgress = DownloadP;
if (pos >= len)
{
myProgress.Report(1);
}
/* This is why videos get corrupted */
srcStrm.Seek(destStrm.Length, SeekOrigin.Begin);
destStrm.Seek(destStrm.Length, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
int read = 0;
do
{
read = srcStrm.Read(buffer, 0, buffer.Length);
destStrm.Write(buffer, 0, read);
pos += read;
double myP = (double)pos / (double)len;
myProgress.Report(myP);
}
while (read > 0 && DownloadIt);
}
}
if (DownloadIt)
{
File.Move(mypath3, mypath3Complete);
}
}
await DownloadAudio(v, token);
break;
}
if (DownloadIt)
{
DownloadCompleteEventArgs evt2 = new DownloadCompleteEventArgs();
evt2.RegularFile = v.RegularFile;
@ -729,24 +1013,25 @@ namespace TYTD.Server.Functions
ApiLoader.DownloadComplete(this, evt2);
ffmpeg.on_video_done(v.Video.Id, (int)v.Resolution);
}
}
if (RedownloadIt && !DownloadIt)
{
DownloadIt = true;
goto redownload;
}
DownloadIt = true;
} catch (Exception ex)
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
nope: System.Threading.Thread.Sleep(2000);
}
public async Task DownloadThread()
{
do
{
await DownloadItem(cancelSrc.Item.Token);
}
while (true);
@ -1018,7 +1303,7 @@ namespace TYTD.Server.Functions
string[] array2 = new string[_path.Length + 1];
array2[0] = StorageLocation;
Array.Copy(_path, 0, array2, 1,_path.Length);
return System.IO.Path.Combine(array2);
return Path.Combine(array2);
}
public static Downloader DL = new Downloader();

Binary file not shown.

View File

@ -1 +1 @@
bd5555531ad345fded2f6956d4df232b6cc12a0e
90e7df0901031d53badd1ff52afc81b857770db7

View File

@ -129,3 +129,134 @@
/home/ddlovato/tytd/site/TYTD.Api/bin/Release/MimeTypesMap.dll
/home/ddlovato/tytd/site/TYTD.Api/bin/Release/SimpleHTTP.dll
/home/ddlovato/tytd/site/TYTD.Api/bin/Release/SimpleHTTP.xml
/home/mike/Git/site/TYTD.Api/bin/Release/TYTD.Api.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.InteropServices.RuntimeInformation.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Cryptography.Algorithms.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ValueTuple.dll
/home/mike/Git/site/TYTD.Api/bin/Release/Microsoft.Win32.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/netstandard.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.AppContext.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Collections.Concurrent.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Collections.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Collections.NonGeneric.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Collections.Specialized.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ComponentModel.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ComponentModel.EventBasedAsync.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ComponentModel.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ComponentModel.TypeConverter.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Console.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Data.Common.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.Contracts.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.Debug.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.FileVersionInfo.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.Process.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.StackTrace.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.TextWriterTraceListener.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.Tools.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.TraceSource.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Diagnostics.Tracing.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Drawing.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Dynamic.Runtime.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Globalization.Calendars.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Globalization.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Globalization.Extensions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.Compression.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.Compression.ZipFile.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.FileSystem.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.FileSystem.DriveInfo.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.FileSystem.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.FileSystem.Watcher.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.IsolatedStorage.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.MemoryMappedFiles.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.Pipes.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.IO.UnmanagedMemoryStream.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Linq.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Linq.Expressions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Linq.Parallel.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Linq.Queryable.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Http.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.NameResolution.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.NetworkInformation.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Ping.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Requests.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Security.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.Sockets.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.WebHeaderCollection.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.WebSockets.Client.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Net.WebSockets.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.ObjectModel.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Reflection.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Reflection.Extensions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Reflection.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Resources.Reader.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Resources.ResourceManager.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Resources.Writer.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.CompilerServices.VisualC.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Extensions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Handles.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.InteropServices.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Numerics.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Serialization.Formatters.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Serialization.Json.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Serialization.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.Serialization.Xml.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Claims.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Cryptography.Csp.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Cryptography.Encoding.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Cryptography.Primitives.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Cryptography.X509Certificates.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.Principal.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Security.SecureString.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encoding.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encoding.Extensions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.RegularExpressions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Overlapped.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Tasks.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Tasks.Parallel.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Thread.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.ThreadPool.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Timer.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.ReaderWriter.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.XDocument.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.XmlDocument.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.XmlSerializer.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.XPath.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Xml.XPath.XDocument.dll
/home/mike/Git/site/TYTD.Api/bin/Release/AngleSharp.dll
/home/mike/Git/site/TYTD.Api/bin/Release/AsyncEnumerable.dll
/home/mike/Git/site/TYTD.Api/bin/Release/CookiesTxtParser.dll
/home/mike/Git/site/TYTD.Api/bin/Release/Microsoft.Bcl.AsyncInterfaces.dll
/home/mike/Git/site/TYTD.Api/bin/Release/MimeTypesMap.dll
/home/mike/Git/site/TYTD.Api/bin/Release/Newtonsoft.Json.dll
/home/mike/Git/site/TYTD.Api/bin/Release/SimpleHTTP.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Buffers.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Memory.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Numerics.Vectors.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.CompilerServices.Unsafe.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encoding.CodePages.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encodings.Web.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Json.dll
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Tasks.Extensions.dll
/home/mike/Git/site/TYTD.Api/bin/Release/YoutubeExplode.dll
/home/mike/Git/site/TYTD.Api/bin/Release/Newtonsoft.Json.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Buffers.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Numerics.Vectors.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Runtime.CompilerServices.Unsafe.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Memory.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encoding.CodePages.xml
/home/mike/Git/site/TYTD.Api/bin/Release/AngleSharp.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Encodings.Web.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Threading.Tasks.Extensions.xml
/home/mike/Git/site/TYTD.Api/bin/Release/Microsoft.Bcl.AsyncInterfaces.xml
/home/mike/Git/site/TYTD.Api/bin/Release/System.Text.Json.xml
/home/mike/Git/site/TYTD.Api/bin/Release/YoutubeExplode.xml
/home/mike/Git/site/TYTD.Api/bin/Release/AsyncEnumerable.xml
/home/mike/Git/site/TYTD.Api/bin/Release/SimpleHTTP.xml
/home/mike/Git/site/TYTD.Api/obj/Release/TYTD.Api.csprojAssemblyReference.cache
/home/mike/Git/site/TYTD.Api/obj/Release/TYTD.Api.csproj.CoreCompileInputs.cache
/home/mike/Git/site/TYTD.Api/obj/Release/TYTD.Api.csproj.CopyComplete
/home/mike/Git/site/TYTD.Api/obj/Release/TYTD.Api.dll

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
f8ed00aa95ccbdf3db94f6dfd910ae2b01d175fa
0420bdbd734151f93ed246c2e88d675d01ee774e

View File

@ -424,3 +424,150 @@
/home/ddlovato/tytd/site/bin/Release/Jurassic.xml
/home/ddlovato/tytd/site/bin/Release/Flurl.pdb
/home/ddlovato/tytd/site/bin/Release/Flurl.xml
/home/mike/Git/site/bin/Release/youtube-downloader.exe
/home/mike/Git/site/bin/Release/System.Runtime.InteropServices.RuntimeInformation.dll
/home/mike/Git/site/bin/Release/System.Security.Cryptography.Algorithms.dll
/home/mike/Git/site/bin/Release/System.ValueTuple.dll
/home/mike/Git/site/bin/Release/Microsoft.Win32.Primitives.dll
/home/mike/Git/site/bin/Release/netstandard.dll
/home/mike/Git/site/bin/Release/System.AppContext.dll
/home/mike/Git/site/bin/Release/System.Collections.Concurrent.dll
/home/mike/Git/site/bin/Release/System.Collections.dll
/home/mike/Git/site/bin/Release/System.Collections.NonGeneric.dll
/home/mike/Git/site/bin/Release/System.Collections.Specialized.dll
/home/mike/Git/site/bin/Release/System.ComponentModel.dll
/home/mike/Git/site/bin/Release/System.ComponentModel.EventBasedAsync.dll
/home/mike/Git/site/bin/Release/System.ComponentModel.Primitives.dll
/home/mike/Git/site/bin/Release/System.ComponentModel.TypeConverter.dll
/home/mike/Git/site/bin/Release/System.Console.dll
/home/mike/Git/site/bin/Release/System.Data.Common.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.Contracts.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.Debug.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.FileVersionInfo.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.Process.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.StackTrace.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.TextWriterTraceListener.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.Tools.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.TraceSource.dll
/home/mike/Git/site/bin/Release/System.Diagnostics.Tracing.dll
/home/mike/Git/site/bin/Release/System.Drawing.Primitives.dll
/home/mike/Git/site/bin/Release/System.Dynamic.Runtime.dll
/home/mike/Git/site/bin/Release/System.Globalization.Calendars.dll
/home/mike/Git/site/bin/Release/System.Globalization.dll
/home/mike/Git/site/bin/Release/System.Globalization.Extensions.dll
/home/mike/Git/site/bin/Release/System.IO.Compression.dll
/home/mike/Git/site/bin/Release/System.IO.Compression.ZipFile.dll
/home/mike/Git/site/bin/Release/System.IO.dll
/home/mike/Git/site/bin/Release/System.IO.FileSystem.dll
/home/mike/Git/site/bin/Release/System.IO.FileSystem.DriveInfo.dll
/home/mike/Git/site/bin/Release/System.IO.FileSystem.Primitives.dll
/home/mike/Git/site/bin/Release/System.IO.FileSystem.Watcher.dll
/home/mike/Git/site/bin/Release/System.IO.IsolatedStorage.dll
/home/mike/Git/site/bin/Release/System.IO.MemoryMappedFiles.dll
/home/mike/Git/site/bin/Release/System.IO.Pipes.dll
/home/mike/Git/site/bin/Release/System.IO.UnmanagedMemoryStream.dll
/home/mike/Git/site/bin/Release/System.Linq.dll
/home/mike/Git/site/bin/Release/System.Linq.Expressions.dll
/home/mike/Git/site/bin/Release/System.Linq.Parallel.dll
/home/mike/Git/site/bin/Release/System.Linq.Queryable.dll
/home/mike/Git/site/bin/Release/System.Net.Http.dll
/home/mike/Git/site/bin/Release/System.Net.NameResolution.dll
/home/mike/Git/site/bin/Release/System.Net.NetworkInformation.dll
/home/mike/Git/site/bin/Release/System.Net.Ping.dll
/home/mike/Git/site/bin/Release/System.Net.Primitives.dll
/home/mike/Git/site/bin/Release/System.Net.Requests.dll
/home/mike/Git/site/bin/Release/System.Net.Security.dll
/home/mike/Git/site/bin/Release/System.Net.Sockets.dll
/home/mike/Git/site/bin/Release/System.Net.WebHeaderCollection.dll
/home/mike/Git/site/bin/Release/System.Net.WebSockets.Client.dll
/home/mike/Git/site/bin/Release/System.Net.WebSockets.dll
/home/mike/Git/site/bin/Release/System.ObjectModel.dll
/home/mike/Git/site/bin/Release/System.Reflection.dll
/home/mike/Git/site/bin/Release/System.Reflection.Extensions.dll
/home/mike/Git/site/bin/Release/System.Reflection.Primitives.dll
/home/mike/Git/site/bin/Release/System.Resources.Reader.dll
/home/mike/Git/site/bin/Release/System.Resources.ResourceManager.dll
/home/mike/Git/site/bin/Release/System.Resources.Writer.dll
/home/mike/Git/site/bin/Release/System.Runtime.CompilerServices.VisualC.dll
/home/mike/Git/site/bin/Release/System.Runtime.dll
/home/mike/Git/site/bin/Release/System.Runtime.Extensions.dll
/home/mike/Git/site/bin/Release/System.Runtime.Handles.dll
/home/mike/Git/site/bin/Release/System.Runtime.InteropServices.dll
/home/mike/Git/site/bin/Release/System.Runtime.Numerics.dll
/home/mike/Git/site/bin/Release/System.Runtime.Serialization.Formatters.dll
/home/mike/Git/site/bin/Release/System.Runtime.Serialization.Json.dll
/home/mike/Git/site/bin/Release/System.Runtime.Serialization.Primitives.dll
/home/mike/Git/site/bin/Release/System.Runtime.Serialization.Xml.dll
/home/mike/Git/site/bin/Release/System.Security.Claims.dll
/home/mike/Git/site/bin/Release/System.Security.Cryptography.Csp.dll
/home/mike/Git/site/bin/Release/System.Security.Cryptography.Encoding.dll
/home/mike/Git/site/bin/Release/System.Security.Cryptography.Primitives.dll
/home/mike/Git/site/bin/Release/System.Security.Cryptography.X509Certificates.dll
/home/mike/Git/site/bin/Release/System.Security.Principal.dll
/home/mike/Git/site/bin/Release/System.Security.SecureString.dll
/home/mike/Git/site/bin/Release/System.Text.Encoding.dll
/home/mike/Git/site/bin/Release/System.Text.Encoding.Extensions.dll
/home/mike/Git/site/bin/Release/System.Text.RegularExpressions.dll
/home/mike/Git/site/bin/Release/System.Threading.dll
/home/mike/Git/site/bin/Release/System.Threading.Overlapped.dll
/home/mike/Git/site/bin/Release/System.Threading.Tasks.dll
/home/mike/Git/site/bin/Release/System.Threading.Tasks.Parallel.dll
/home/mike/Git/site/bin/Release/System.Threading.Thread.dll
/home/mike/Git/site/bin/Release/System.Threading.ThreadPool.dll
/home/mike/Git/site/bin/Release/System.Threading.Timer.dll
/home/mike/Git/site/bin/Release/System.Xml.ReaderWriter.dll
/home/mike/Git/site/bin/Release/System.Xml.XDocument.dll
/home/mike/Git/site/bin/Release/System.Xml.XmlDocument.dll
/home/mike/Git/site/bin/Release/System.Xml.XmlSerializer.dll
/home/mike/Git/site/bin/Release/System.Xml.XPath.dll
/home/mike/Git/site/bin/Release/System.Xml.XPath.XDocument.dll
/home/mike/Git/site/bin/Release/AngleSharp.dll
/home/mike/Git/site/bin/Release/AsyncEnumerable.dll
/home/mike/Git/site/bin/Release/Common.Logging.Core.dll
/home/mike/Git/site/bin/Release/Common.Logging.dll
/home/mike/Git/site/bin/Release/CookiesTxtParser.dll
/home/mike/Git/site/bin/Release/ExposedObject.dll
/home/mike/Git/site/bin/Release/Flurl.dll
/home/mike/Git/site/bin/Release/Jurassic.dll
/home/mike/Git/site/bin/Release/Microsoft.Bcl.AsyncInterfaces.dll
/home/mike/Git/site/bin/Release/MimeTypesMap.dll
/home/mike/Git/site/bin/Release/Newtonsoft.Json.dll
/home/mike/Git/site/bin/Release/SimpleBase.dll
/home/mike/Git/site/bin/Release/SimpleHTTP.dll
/home/mike/Git/site/bin/Release/Stef.Validation.dll
/home/mike/Git/site/bin/Release/System.Buffers.dll
/home/mike/Git/site/bin/Release/System.Memory.dll
/home/mike/Git/site/bin/Release/System.Numerics.Vectors.dll
/home/mike/Git/site/bin/Release/System.Runtime.CompilerServices.Unsafe.dll
/home/mike/Git/site/bin/Release/System.Text.Encoding.CodePages.dll
/home/mike/Git/site/bin/Release/System.Text.Encodings.Web.dll
/home/mike/Git/site/bin/Release/System.Text.Json.dll
/home/mike/Git/site/bin/Release/System.Threading.Tasks.Extensions.dll
/home/mike/Git/site/bin/Release/TYTD.Api.dll
/home/mike/Git/site/bin/Release/YoutubeExplode.dll
/home/mike/Git/site/bin/Release/YoutubeExplode.Extensions.dll
/home/mike/Git/site/bin/Release/Newtonsoft.Json.xml
/home/mike/Git/site/bin/Release/System.Buffers.xml
/home/mike/Git/site/bin/Release/System.Numerics.Vectors.xml
/home/mike/Git/site/bin/Release/System.Runtime.CompilerServices.Unsafe.xml
/home/mike/Git/site/bin/Release/System.Memory.xml
/home/mike/Git/site/bin/Release/AngleSharp.xml
/home/mike/Git/site/bin/Release/System.Text.Encodings.Web.xml
/home/mike/Git/site/bin/Release/System.Threading.Tasks.Extensions.xml
/home/mike/Git/site/bin/Release/Microsoft.Bcl.AsyncInterfaces.xml
/home/mike/Git/site/bin/Release/System.Text.Json.xml
/home/mike/Git/site/bin/Release/YoutubeExplode.xml
/home/mike/Git/site/bin/Release/SimpleHTTP.xml
/home/mike/Git/site/bin/Release/AsyncEnumerable.xml
/home/mike/Git/site/bin/Release/Common.Logging.Core.pdb
/home/mike/Git/site/bin/Release/Common.Logging.pdb
/home/mike/Git/site/bin/Release/Common.Logging.xml
/home/mike/Git/site/bin/Release/SimpleBase.pdb
/home/mike/Git/site/bin/Release/ExposedObject.pdb
/home/mike/Git/site/bin/Release/Jurassic.xml
/home/mike/Git/site/bin/Release/Flurl.pdb
/home/mike/Git/site/bin/Release/Flurl.xml
/home/mike/Git/site/obj/x86/Release/youtube-downloader.csprojAssemblyReference.cache
/home/mike/Git/site/obj/x86/Release/youtube-downloader.csproj.CoreCompileInputs.cache
/home/mike/Git/site/obj/x86/Release/youtube-downloader.csproj.CopyComplete
/home/mike/Git/site/obj/x86/Release/youtube-downloader.exe