Make the downloader more resiliant

This commit is contained in:
2026-03-02 02:23:46 -06:00
parent 8851f710fb
commit 44c87e1e50
5 changed files with 98 additions and 4 deletions

View File

@@ -14,6 +14,6 @@
"project_dependencies": [ "project_dependencies": [
"..\/Tesses.YouTubeDownloader" "..\/Tesses.YouTubeDownloader"
], ],
"version": "1.0.0.2-prod", "version": "1.0.0.3-prod",
"compTime": "secure" "compTime": "secure"
} }

View File

@@ -623,6 +623,17 @@ class TYTDApp {
} }
} }
else if(ctx.Path == "/api/v1/manifest.json")
{
const v = ctx.QueryParams.TryGetFirst("v");
if(TypeIsString(v))
{
const resp=this.TYTD.ManifestRequest(v);
Console.WriteLine(resp);
ctx.WithMimeType("application/json").SendJson(resp);
return true;
}
}
else if(ctx.Path == "/api/v1/personal") else if(ctx.Path == "/api/v1/personal")
{ {
/* /*

View File

@@ -14,6 +14,6 @@
} }
], ],
"name": "Tesses.YouTubeDownloader", "name": "Tesses.YouTubeDownloader",
"version": "1.0.0.2-prod", "version": "1.0.0.3-prod",
"icon": "icon.png" "icon": "icon.png"
} }

View File

@@ -1341,11 +1341,51 @@ class TYTD.Downloader {
if(e == null) if(e == null)
{ {
var req = this.ManifestRequest(id); var req = this.ManifestRequest(id);
this.DownloadCaptions(req);
this.PutVideoInfo(req.playerResponse.videoDetails); this.PutVideoInfo(req.playerResponse.videoDetails);
} }
} }
} }
private DownloadCaptions(req)
{
const tracks = req.playerResponse.playerCaptionsTracklistRenderer.captionTracks;
if(TypeIsList(tracks))
{
each(var item : tracks)
{
if(!TypeIsString(item.languageCode)) continue;
if(!TypeIsString(item.baseUrl)) continue;
try {
var path = /"Streams"/id.Substring(0,4) / id.Substring(4) / item.languageCode;
var resp = Net.Http.MakeRequest(url,{FollowRedirects=true});
if(resp.StatusCode >= 200 && resp.StatusCode <= 299)
{
const strm=this.Storage.OpenFile(path+".xml","wb");
resp.CopyToStream(strm);
strm.Close();
}
resp = Net.Http.MakeRequest(url.Replace("fmt=srv3","fmt=vtt"),{FollowRedirects=true});
if(resp.StatusCode >= 200 && resp.StatusCode <= 299)
{
const strm=this.Storage.OpenFile(path+".vtt","wb");
resp.CopyToStream(strm);
strm.Close();
}
resp = Net.Http.MakeRequest(url.Replace("fmt=srv3","fmt=srt"),{FollowRedirects=true});
if(resp.StatusCode >= 200 && resp.StatusCode <= 299)
{
const strm=this.Storage.OpenFile(path+".srt","wb");
resp.CopyToStream(strm);
strm.Close();
}
} catch(ex) {
}
}
}
}
/^ /^
Put video info from info into database Put video info from info into database
^/ ^/
@@ -1608,6 +1648,7 @@ class TYTD.Downloader {
^/ ^/
public ManifestRequest(vid) public ManifestRequest(vid)
{ {
while(true) {
var id = TYTD.GetVideoId(vid); var id = TYTD.GetVideoId(vid);
if(id == null) return null; if(id == null) return null;
TryDownloadVideoThumbnail(id,"0"); TryDownloadVideoThumbnail(id,"0");
@@ -1651,9 +1692,35 @@ class TYTD.Downloader {
}; };
this.RateLimit(); this.RateLimit();
var response = Net.Http.MakeRequest(url,requestData); var response = Net.Http.MakeRequest(url,requestData);
if(response.StatusCode < 200 || response.StatusCode > 299) return null; Console.WriteLine(response.StatusCode);
return Json.Decode(response.ReadAsString());
if(response.StatusCode < 200 || response.StatusCode > 299) continue;
const respText = response.ReadAsString();
const jsonResp = Json.Decode(respText);
if(!TypeIsDictionary(jsonResp.playerResponse)) continue;
if(TypeIsDictionary(jsonResp.playerResponse.playabilityStatus))
{
if(jsonResp.playerResponse.playabilityStatus.status == "ERROR")
{
throw new VideoDownloadError(id, jsonResp.playerResponse.playabilityStatus.reason);
}
} else {
throw new VideoDownloadError(id, "playabilityStatus is missing");
}
if(!TypeIsDictionary(jsonResp.playerResponse.videoDetails))
{
throw new VideoDownloadError(id, "videoDetails is missing");
}
if(!TypeIsList(jsonResp.playerResponse.streamingData.adaptiveFormats))
{
throw new VideoDownloadError(id, "adaptiveFormats is missing");
}
return jsonResp;
}
} }

View File

@@ -0,0 +1,16 @@
class VideoDownloadError {
public VideoDownloadError(id, error)
{
Id = id;
Error = error;
}
public Id;
public Error;
public ToString()
{
return $"Download error {Error} with Id: {Id}";
}
}