mirror of
https://github.com/Crunchy-DL/Crunchy-Downloader.git
synced 2026-03-11 09:35:45 +00:00
- Changed so that most requests now use a guest token
- Updated android tokens - Fixed **episodes being hidden in the calendar when the history language was not `en-US` - Fixed **download speed unit formatting** from `Mb/s` to `MB/s` [#385](https://github.com/Crunchy-DL/Crunchy-Downloader/pull/385)
This commit is contained in:
parent
c7687c80e8
commit
6abbc129b6
16 changed files with 133 additions and 57 deletions
|
|
@ -293,7 +293,7 @@ public class CalendarManager{
|
|||
|
||||
string? seasonTitle = string.IsNullOrEmpty(crBrowseEpisode.EpisodeMetadata.SeasonTitle)
|
||||
? crBrowseEpisode.EpisodeMetadata.SeriesTitle
|
||||
: Regex.IsMatch(crBrowseEpisode.EpisodeMetadata.SeasonTitle, @"^Season\s+\d+$", RegexOptions.IgnoreCase)
|
||||
: LooksLikeGenericSeasonLabel(crBrowseEpisode.EpisodeMetadata.SeasonTitle, crBrowseEpisode.EpisodeMetadata.SeasonNumber)
|
||||
? $"{crBrowseEpisode.EpisodeMetadata.SeriesTitle} {crBrowseEpisode.EpisodeMetadata.SeasonTitle}"
|
||||
: crBrowseEpisode.EpisodeMetadata.SeasonTitle;
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ public class CalendarManager{
|
|||
calEpisode.AudioLocale = crBrowseEpisode.EpisodeMetadata.AudioLocale;
|
||||
|
||||
var existingEpisode = calendarDay.CalendarEpisodes
|
||||
.FirstOrDefault(e => e.SeasonName == calEpisode.SeasonName && e.AudioLocale == calEpisode.AudioLocale);
|
||||
.FirstOrDefault(e => e.CrSeriesID == calEpisode.CrSeriesID && e.AudioLocale == calEpisode.AudioLocale);
|
||||
|
||||
if (existingEpisode != null){
|
||||
if (!int.TryParse(existingEpisode.EpisodeNumber, out _)){
|
||||
|
|
@ -569,6 +569,24 @@ public class CalendarManager{
|
|||
}
|
||||
}
|
||||
|
||||
private bool LooksLikeGenericSeasonLabel(string? seasonTitle, double? seasonNo){
|
||||
if (string.IsNullOrWhiteSpace(seasonTitle)) return true;
|
||||
|
||||
var t = seasonTitle.Trim();
|
||||
|
||||
var m = Regex.Match(t, @"^(?<word>\p{L}+(?:[\p{L}\p{Mn}'\.\- ]*\p{L})?)\s+(?<n>\d+)$",
|
||||
RegexOptions.CultureInvariant);
|
||||
|
||||
if (!m.Success) return false;
|
||||
|
||||
if (seasonNo.HasValue &&
|
||||
double.TryParse(m.Groups["n"].Value, NumberStyles.None, CultureInfo.InvariantCulture, out var n)){
|
||||
return n == seasonNo.Value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Query
|
||||
|
||||
private string query = @"query ($weekStart: Int, $weekEnd: Int, $page: Int) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public class CrEpisode(){
|
|||
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
|
||||
|
||||
public async Task<CrunchyEpisode?> ParseEpisodeById(string id, string crLocale, bool forcedLang = false){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
query["preferred_audio_language"] = "ja-JP";
|
||||
|
|
@ -27,7 +28,7 @@ public class CrEpisode(){
|
|||
}
|
||||
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/episodes/{id}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/episodes/{id}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -51,7 +52,7 @@ public class CrEpisode(){
|
|||
//guid for episode id
|
||||
foreach (var episodeVersionse in list){
|
||||
foreach (var version in episodeVersionse){
|
||||
var checkRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/episodes/{version.Guid}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var checkRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/episodes/{version.Guid}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
var checkResponse = await HttpClientReq.Instance.SendHttpRequest(checkRequest, true);
|
||||
if (!checkResponse.IsOk){
|
||||
epsidoe.Data.First().Versions?.Remove(version);
|
||||
|
|
@ -197,7 +198,7 @@ public class CrEpisode(){
|
|||
Error = false,
|
||||
Percent = 0,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0
|
||||
DownloadSpeedBytes = 0
|
||||
};
|
||||
epMeta.AvailableSubs = item.SubtitleLocales;
|
||||
epMeta.Description = item.Description;
|
||||
|
|
@ -236,7 +237,7 @@ public class CrEpisode(){
|
|||
}
|
||||
|
||||
public async Task<CrBrowseEpisodeBase?> GetNewEpisodes(string? crLocale, int requestAmount, DateTime? firstWeekDay = null, bool forcedLang = false){
|
||||
await crunInstance.CrAuthEndpoint1.RefreshToken(true);
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(crLocale)){
|
||||
|
|
@ -256,7 +257,7 @@ public class CrEpisode(){
|
|||
query["sort_by"] = "newly_added";
|
||||
query["type"] = "episode";
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ public class CrMovies{
|
|||
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
|
||||
|
||||
public async Task<CrunchyMovie?> ParseMovieById(string id, string crLocale, bool forcedLang = false){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
query["preferred_audio_language"] = "ja-JP";
|
||||
|
|
@ -25,7 +26,7 @@ public class CrMovies{
|
|||
}
|
||||
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/objects/{id}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/objects/{id}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ public class CrMovies{
|
|||
Error = false,
|
||||
Percent = 0,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0
|
||||
DownloadSpeedBytes = 0
|
||||
};
|
||||
epMeta.AvailableSubs = [];
|
||||
epMeta.Description = episodeP.Description;
|
||||
|
|
|
|||
|
|
@ -105,8 +105,9 @@ public class CrMusic{
|
|||
}
|
||||
|
||||
public async Task<CrArtist> ParseArtistByIdAsync(string id, string crLocale, bool forcedLang = false){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
var query = CreateQueryParameters(crLocale, forcedLang);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Content}/music/artists/{id}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Content}/music/artists/{id}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -135,8 +136,9 @@ public class CrMusic{
|
|||
}
|
||||
|
||||
private async Task<CrunchyMusicVideoList> FetchMediaListAsync(string url, string crLocale, bool forcedLang){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
var query = CreateQueryParameters(crLocale, forcedLang);
|
||||
var request = HttpClientReq.CreateRequestMessage(url, HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage(url, HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -186,7 +188,7 @@ public class CrMusic{
|
|||
Error = false,
|
||||
Percent = 0,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0
|
||||
DownloadSpeedBytes = 0
|
||||
};
|
||||
epMeta.AvailableSubs = new List<string>();
|
||||
epMeta.Description = episodeP.Description;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class CrSeries{
|
|||
Done = false,
|
||||
Percent = 0,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0
|
||||
DownloadSpeedBytes = 0
|
||||
};
|
||||
epMeta.Hslang = CrunchyrollManager.Instance.CrunOptions.Hslang;
|
||||
epMeta.Description = item.Description;
|
||||
|
|
@ -120,8 +120,6 @@ public class CrSeries{
|
|||
|
||||
|
||||
public async Task<CrunchySeriesList?> ListSeriesId(string id, string crLocale, CrunchyMultiDownload? data, bool forcedLocale = false){
|
||||
await crunInstance.CrAuthEndpoint1.RefreshToken(true);
|
||||
|
||||
bool serieshasversions = true;
|
||||
|
||||
CrSeriesSearch? parsedSeries = await ParseSeriesById(id, crLocale, forcedLocale);
|
||||
|
|
@ -291,6 +289,7 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
public async Task<CrunchyEpisodeList> GetSeasonDataById(string seasonId, string? crLocale, bool forcedLang = false, bool log = false){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
CrunchyEpisodeList episodeList = new CrunchyEpisodeList(){ Data = new List<CrunchyEpisode>(), Total = 0, Meta = new Meta() };
|
||||
|
||||
NameValueCollection query;
|
||||
|
|
@ -305,7 +304,7 @@ public class CrSeries{
|
|||
}
|
||||
}
|
||||
|
||||
var showRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/seasons/{seasonId}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var showRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/seasons/{seasonId}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(showRequest);
|
||||
|
||||
|
|
@ -326,7 +325,7 @@ public class CrSeries{
|
|||
}
|
||||
}
|
||||
|
||||
var episodeRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/seasons/{seasonId}/episodes", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var episodeRequest = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/seasons/{seasonId}/episodes", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var episodeRequestResponse = await HttpClientReq.Instance.SendHttpRequest(episodeRequest);
|
||||
|
||||
|
|
@ -345,7 +344,7 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
public async Task<CrSeriesSearch?> ParseSeriesById(string id, string? crLocale, bool forced = false){
|
||||
await crunInstance.CrAuthEndpoint1.RefreshToken(true);
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
query["preferred_audio_language"] = "ja-JP";
|
||||
|
|
@ -357,7 +356,7 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/series/{id}/seasons", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/series/{id}/seasons", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -377,7 +376,9 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
public async Task<CrSeriesBase?> SeriesById(string id, string? crLocale, bool forced = false){
|
||||
await crunInstance.CrAuthEndpoint1.RefreshToken(true);
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
|
||||
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
query["preferred_audio_language"] = "ja-JP";
|
||||
|
|
@ -388,7 +389,7 @@ public class CrSeries{
|
|||
}
|
||||
}
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/series/{id}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Cms}/series/{id}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -409,7 +410,8 @@ public class CrSeries{
|
|||
|
||||
|
||||
public async Task<CrSearchSeriesBase?> Search(string searchString, string? crLocale, bool forced = false){
|
||||
await crunInstance.CrAuthEndpoint1.RefreshToken(true);
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
if (!string.IsNullOrEmpty(crLocale)){
|
||||
|
|
@ -423,7 +425,7 @@ public class CrSeries{
|
|||
query["n"] = "6";
|
||||
query["type"] = "series";
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Search}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Search}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -452,6 +454,7 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
public async Task<CrBrowseSeriesBase?> GetAllSeries(string? crLocale){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
CrBrowseSeriesBase complete = new CrBrowseSeriesBase();
|
||||
complete.Data =[];
|
||||
|
||||
|
|
@ -468,7 +471,7 @@ public class CrSeries{
|
|||
query["n"] = "50";
|
||||
query["sort_by"] = "alphabetical";
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
@ -494,6 +497,7 @@ public class CrSeries{
|
|||
}
|
||||
|
||||
public async Task<CrBrowseSeriesBase?> GetSeasonalSeries(string season, string year, string? crLocale){
|
||||
await crunInstance.CrAuthGuest.RefreshToken(true);
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(new UriBuilder().Query);
|
||||
|
||||
if (!string.IsNullOrEmpty(crLocale)){
|
||||
|
|
@ -503,7 +507,7 @@ public class CrSeries{
|
|||
query["seasonal_tag"] = season.ToLower() + "-" + year;
|
||||
query["n"] = "100";
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthEndpoint1.Token?.access_token, query);
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Browse}", HttpMethod.Get, true, crunInstance.CrAuthGuest.Token?.access_token, query);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public class CrunchyrollManager{
|
|||
|
||||
public string DefaultLocale = "en-US";
|
||||
public CrAuthSettings DefaultAndroidAuthSettings = new CrAuthSettings();
|
||||
public CrAuthSettings GuestAndroidAuthSettings = new CrAuthSettings();
|
||||
|
||||
public JsonSerializerSettings? SettingsJsonSerializerSettings = new(){
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
|
|
@ -61,6 +62,8 @@ public class CrunchyrollManager{
|
|||
|
||||
public CrAuth CrAuthEndpoint1;
|
||||
public CrAuth CrAuthEndpoint2;
|
||||
|
||||
public CrAuth CrAuthGuest;
|
||||
|
||||
public CrEpisode CrEpisode;
|
||||
public CrSeries CrSeries;
|
||||
|
|
@ -161,6 +164,9 @@ public class CrunchyrollManager{
|
|||
CrAuthEndpoint1.Init();
|
||||
CrAuthEndpoint2 = new CrAuth(this, new CrAuthSettings());
|
||||
CrAuthEndpoint2.Init();
|
||||
|
||||
CrAuthGuest = new CrAuth(this, new CrAuthSettings());
|
||||
CrAuthGuest.Init();
|
||||
|
||||
CrEpisode = new CrEpisode();
|
||||
CrSeries = new CrSeries();
|
||||
|
|
@ -201,15 +207,14 @@ public class CrunchyrollManager{
|
|||
|
||||
DefaultAndroidAuthSettings = new CrAuthSettings(){
|
||||
Endpoint = "android/phone",
|
||||
Client_ID = "pd6uw3dfyhzghs0wxae3",
|
||||
Authorization = "Basic cGQ2dXczZGZ5aHpnaHMwd3hhZTM6NXJ5SjJFQXR3TFc0UklIOEozaWk1anVqbnZrRWRfTkY=",
|
||||
UserAgent = "Crunchyroll/3.95.2 Android/16 okhttp/4.12.0",
|
||||
Authorization = "Basic bzJhNndsamdub3FtdjloMWJ5bHI6Ujk3S3ExZm5faExZVFk0bDJxTjJIT2lDQnpfYnpBSUU=",
|
||||
UserAgent = "Crunchyroll/3.97.0 Android/16 okhttp/4.12.0",
|
||||
Device_name = "CPH2449",
|
||||
Device_type = "OnePlus CPH2449",
|
||||
Audio = true,
|
||||
Video = true,
|
||||
};
|
||||
|
||||
|
||||
CrunOptions.StreamEndpoint ??= new CrAuthSettings(){ Endpoint = "tv/android_tv", Audio = true, Video = true };
|
||||
CrunOptions.StreamEndpoint.Endpoint = "tv/android_tv";
|
||||
CrAuthEndpoint1.AuthSettings = new CrAuthSettings(){
|
||||
|
|
@ -232,6 +237,10 @@ public class CrunchyrollManager{
|
|||
await CrAuthEndpoint2.Auth();
|
||||
}
|
||||
|
||||
CrAuthGuest.AuthSettings = GuestAndroidAuthSettings;
|
||||
CrAuthGuest.EndpointEnum = CrunchyrollEndpoints.Guest;
|
||||
await CrAuthGuest.AuthAnonymousFoxy();
|
||||
|
||||
CfgManager.WriteCrSettings();
|
||||
|
||||
// var token = await GetBase64EncodedTokenAsync();
|
||||
|
|
@ -303,7 +312,7 @@ public class CrunchyrollManager{
|
|||
Error = false,
|
||||
Percent = 0,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Starting"
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
@ -323,7 +332,7 @@ public class CrunchyrollManager{
|
|||
Error = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Download Error" + (!string.IsNullOrEmpty(res.ErrorText) ? " - " + res.ErrorText : ""),
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
@ -337,7 +346,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Waiting for Muxing/Encoding"
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
@ -354,7 +363,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Muxing"
|
||||
};
|
||||
|
||||
|
|
@ -422,7 +431,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Encoding"
|
||||
};
|
||||
|
||||
|
|
@ -481,7 +490,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Encoding"
|
||||
};
|
||||
|
||||
|
|
@ -517,7 +526,7 @@ public class CrunchyrollManager{
|
|||
Done = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = (muxError ? "Muxing Failed" : "Done") + (syncError ? $" - Couldn't sync dubs ({notSyncedDubs})" : "")
|
||||
};
|
||||
|
||||
|
|
@ -543,7 +552,7 @@ public class CrunchyrollManager{
|
|||
Done = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Done - Skipped muxing"
|
||||
};
|
||||
|
||||
|
|
@ -602,7 +611,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Moving Files"
|
||||
};
|
||||
|
||||
|
|
@ -765,7 +774,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Muxing – Syncing Dub Timings"
|
||||
};
|
||||
|
||||
|
|
@ -808,7 +817,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Muxing"
|
||||
};
|
||||
|
||||
|
|
@ -1675,7 +1684,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Decrypting"
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
@ -1766,7 +1775,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Decrypting video"
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
@ -1837,7 +1846,7 @@ public class CrunchyrollManager{
|
|||
IsDownloading = true,
|
||||
Percent = 100,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Decrypting audio"
|
||||
};
|
||||
QueueManager.Instance.Queue.Refresh();
|
||||
|
|
|
|||
|
|
@ -487,12 +487,12 @@ public partial class QueueManager : ObservableObject{
|
|||
activeProcessingJobs.Release(giveBack);
|
||||
_borrowed -= giveBack;
|
||||
}
|
||||
|
||||
|
||||
int more = newLimit - _limit - giveBack;
|
||||
if (more > 0) activeProcessingJobs.Release(more);
|
||||
} else{
|
||||
int toPark = _limit - newLimit;
|
||||
|
||||
|
||||
for (int i = 0; i < toPark; i++){
|
||||
_ = Task.Run(async () => {
|
||||
await activeProcessingJobs.WaitAsync().ConfigureAwait(false);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,18 @@ public enum StreamingService{
|
|||
Unknown
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum CrunchyrollEndpoints{
|
||||
[EnumMember(Value = "android/phone")]
|
||||
Android,
|
||||
[EnumMember(Value = "tv/android_tv")]
|
||||
AndroidTv,
|
||||
[EnumMember(Value = "Guest")]
|
||||
Guest,
|
||||
[EnumMember(Value = "Unknown")]
|
||||
Unknown
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum EpisodeType{
|
||||
[EnumMember(Value = "MusicVideo")]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Text.RegularExpressions;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CRD.Downloader;
|
||||
using CRD.Downloader.Crunchyroll;
|
||||
using CRD.Utils.Parser.Utils;
|
||||
using CRD.Utils.Structs;
|
||||
using Newtonsoft.Json;
|
||||
|
|
@ -261,14 +262,18 @@ public class HlsDownloader{
|
|||
string resumeDataJson = JsonConvert.SerializeObject(new{ _data.Parts.Completed, Total = totalSeg });
|
||||
File.WriteAllText($"{fn}.resume", resumeDataJson);
|
||||
|
||||
var downloadSpeed = CrunchyrollManager.Instance.CrunOptions.DownloadSpeedInBits
|
||||
? $"{dataLog.DownloadSpeedBytes * 8 / 1000000.0:F2} Mb/s"
|
||||
: $"{dataLog.DownloadSpeedBytes / 1000000.0:F2} MB/s";
|
||||
|
||||
// Log progress
|
||||
Console.WriteLine($"{_data.Parts.Completed} of {totalSeg} parts downloaded [{dataLog.Percent}%] ({FormatTime(dataLog.Time)} | {dataLog.DownloadSpeed / 1000000.0:F2}Mb/s)");
|
||||
Console.WriteLine($"{_data.Parts.Completed} of {totalSeg} parts downloaded [{dataLog.Percent}%] ({FormatTime(dataLog.Time)} | {downloadSpeed})");
|
||||
|
||||
_currentEpMeta.DownloadProgress = new DownloadProgress(){
|
||||
IsDownloading = true,
|
||||
Percent = dataLog.Percent,
|
||||
Time = dataLog.Time,
|
||||
DownloadSpeed = dataLog.DownloadSpeed,
|
||||
DownloadSpeedBytes = dataLog.DownloadSpeedBytes,
|
||||
Doing = _isAudio ? "Downloading Audio" : (_isVideo ? "Downloading Video" : "")
|
||||
};
|
||||
|
||||
|
|
@ -386,13 +391,17 @@ public class HlsDownloader{
|
|||
_data.BytesDownloaded = 0;
|
||||
_lastUiUpdate = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
Console.WriteLine($"{currentDownloaded}/{totalSeg} [{dataLog.Percent}%] Speed: {dataLog.DownloadSpeed / 1000000.0:F2} MB/s ETA: {FormatTime(dataLog.Time)}");
|
||||
var downloadSpeed = CrunchyrollManager.Instance.CrunOptions.DownloadSpeedInBits
|
||||
? $"{dataLog.DownloadSpeedBytes * 8 / 1000000.0:F2} Mb/s"
|
||||
: $"{dataLog.DownloadSpeedBytes / 1000000.0:F2} MB/s";
|
||||
|
||||
Console.WriteLine($"{currentDownloaded}/{totalSeg} [{dataLog.Percent}%] Speed: {downloadSpeed} ETA: {FormatTime(dataLog.Time)}");
|
||||
|
||||
_currentEpMeta.DownloadProgress = new DownloadProgress{
|
||||
IsDownloading = true,
|
||||
Percent = dataLog.Percent,
|
||||
Time = dataLog.Time,
|
||||
DownloadSpeed = dataLog.DownloadSpeed,
|
||||
DownloadSpeedBytes = dataLog.DownloadSpeedBytes,
|
||||
Doing = _isAudio ? "Downloading Audio" : (_isVideo ? "Downloading Video" : "")
|
||||
};
|
||||
}
|
||||
|
|
@ -468,7 +477,7 @@ public class HlsDownloader{
|
|||
IsDownloading = true,
|
||||
Percent = dataLog.Percent,
|
||||
Time = dataLog.Time,
|
||||
DownloadSpeed = dataLog.DownloadSpeed,
|
||||
DownloadSpeedBytes = dataLog.DownloadSpeedBytes,
|
||||
Doing = _isAudio ? "Merging Audio" : (_isVideo ? "Merging Video" : "")
|
||||
};
|
||||
|
||||
|
|
@ -542,7 +551,7 @@ public class HlsDownloader{
|
|||
return new Info{
|
||||
Percent = percent,
|
||||
Time = etaSec,
|
||||
DownloadSpeed = speed
|
||||
DownloadSpeedBytes = speed
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -761,7 +770,7 @@ public static class HttpContentExtensions{
|
|||
public class Info{
|
||||
public int Percent{ get; set; }
|
||||
public double Time{ get; set; } // Remaining time estimate
|
||||
public double DownloadSpeed{ get; set; } // Bytes per second
|
||||
public double DownloadSpeedBytes{ get; set; } // Bytes per second
|
||||
}
|
||||
|
||||
public class ResumeData{
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ public class Helpers{
|
|||
IsDownloading = true,
|
||||
Percent = progress,
|
||||
Time = 0,
|
||||
DownloadSpeed = 0,
|
||||
DownloadSpeedBytes = 0,
|
||||
Doing = "Encoding"
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class FontsManager{
|
|||
|
||||
#endregion
|
||||
|
||||
public Dictionary<string, string> Fonts{ get; private set; } = new(){
|
||||
public Dictionary<string, string> Fonts{ get; private set; } = new(StringComparer.OrdinalIgnoreCase){
|
||||
{ "Adobe Arabic", "AdobeArabic-Bold.otf" },
|
||||
{ "Andale Mono", "andalemo.ttf" },
|
||||
{ "Arial", "arial.ttf" },
|
||||
|
|
|
|||
|
|
@ -116,6 +116,9 @@ public class CrDownloadOptions{
|
|||
|
||||
[JsonProperty("download_speed_limit")]
|
||||
public int DownloadSpeedLimit{ get; set; }
|
||||
|
||||
[JsonProperty("download_speed_bits")]
|
||||
public bool DownloadSpeedInBits{ get; set; }
|
||||
|
||||
[JsonProperty("proxy_enabled")]
|
||||
public bool ProxyEnabled{ get; set; }
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ public class DownloadProgress{
|
|||
|
||||
public int Percent{ get; set; }
|
||||
public double Time{ get; set; }
|
||||
public double DownloadSpeed{ get; set; }
|
||||
public double DownloadSpeedBytes{ get; set; }
|
||||
}
|
||||
|
||||
public class CrunchyEpMetaData{
|
||||
|
|
|
|||
|
|
@ -127,7 +127,11 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
|
|||
Done = epMeta.DownloadProgress.Done;
|
||||
Percent = epMeta.DownloadProgress.Percent;
|
||||
Time = "Estimated Time: " + TimeSpan.FromSeconds(epMeta.DownloadProgress.Time).ToString(@"hh\:mm\:ss");
|
||||
DownloadSpeed = $"{epMeta.DownloadProgress.DownloadSpeed / 1000000.0:F2}Mb/s";
|
||||
DownloadSpeed = CrunchyrollManager.Instance.CrunOptions.DownloadSpeedInBits
|
||||
? $"{epMeta.DownloadProgress.DownloadSpeedBytes * 8 / 1000000.0:F2} Mb/s"
|
||||
: $"{epMeta.DownloadProgress.DownloadSpeedBytes / 1000000.0:F2} MB/s";
|
||||
|
||||
;
|
||||
Paused = epMeta.Paused || !isDownloading && !epMeta.Paused;
|
||||
DoingWhat = epMeta.Paused ? "Paused" :
|
||||
Done ? (epMeta.DownloadProgress.Doing != string.Empty ? epMeta.DownloadProgress.Doing : "Done") :
|
||||
|
|
@ -192,7 +196,9 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
|
|||
Done = epMeta.DownloadProgress.Done;
|
||||
Percent = epMeta.DownloadProgress.Percent;
|
||||
Time = "Estimated Time: " + TimeSpan.FromSeconds(epMeta.DownloadProgress.Time).ToString(@"hh\:mm\:ss");
|
||||
DownloadSpeed = $"{epMeta.DownloadProgress.DownloadSpeed / 1000000.0:F2}Mb/s";
|
||||
DownloadSpeed = CrunchyrollManager.Instance.CrunOptions.DownloadSpeedInBits
|
||||
? $"{epMeta.DownloadProgress.DownloadSpeedBytes * 8 / 1000000.0:F2} Mb/s"
|
||||
: $"{epMeta.DownloadProgress.DownloadSpeedBytes / 1000000.0:F2} MB/s";
|
||||
|
||||
Paused = epMeta.Paused || !isDownloading && !epMeta.Paused;
|
||||
DoingWhat = epMeta.Paused ? "Paused" :
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public partial class GeneralSettingsViewModel : ViewModelBase{
|
|||
|
||||
[ObservableProperty]
|
||||
private double? _downloadSpeed;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _downloadSpeedInBits;
|
||||
|
||||
[ObservableProperty]
|
||||
private double? _retryAttempts;
|
||||
|
|
@ -298,6 +301,7 @@ public partial class GeneralSettingsViewModel : ViewModelBase{
|
|||
HistorySkipUnmonitored = options.HistorySkipUnmonitored;
|
||||
HistoryCountSonarr = options.HistoryCountSonarr;
|
||||
DownloadSpeed = options.DownloadSpeedLimit;
|
||||
DownloadSpeedInBits = options.DownloadSpeedInBits;
|
||||
DownloadMethodeNew = options.DownloadMethodeNew;
|
||||
DownloadAllowEarlyStart = options.DownloadAllowEarlyStart;
|
||||
RetryAttempts = Math.Clamp((options.RetryAttempts), 1, 10);
|
||||
|
|
@ -344,6 +348,7 @@ public partial class GeneralSettingsViewModel : ViewModelBase{
|
|||
settings.HistorySkipUnmonitored = HistorySkipUnmonitored;
|
||||
settings.HistoryCountSonarr = HistoryCountSonarr;
|
||||
settings.DownloadSpeedLimit = Math.Clamp((int)(DownloadSpeed ?? 0), 0, 1000000000);
|
||||
settings.DownloadSpeedInBits = DownloadSpeedInBits;
|
||||
settings.SimultaneousDownloads = Math.Clamp((int)(SimultaneousDownloads ?? 0), 1, 10);
|
||||
settings.SimultaneousProcessingJobs = Math.Clamp((int)(SimultaneousProcessingJobs ?? 0), 1, 10);
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,12 @@
|
|||
HorizontalAlignment="Stretch" />
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpanderItem Content="Show download speed in bits/s (Mbps)" Description="When enabled, shows Mbps instead of MB/s">
|
||||
<controls:SettingsExpanderItem.Footer>
|
||||
<CheckBox IsChecked="{Binding DownloadSpeedInBits}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpanderItem Content="Download Retry"
|
||||
Description="Sett the number of retry attempts and the delay between each retry">
|
||||
|
|
|
|||
Loading…
Reference in a new issue