Add - Added option to set sings subtitles as default

Chg - Log message for when "No active Subscription" is displayed in login tab
Fix - Chapter crashed the downloader in some cases
Fix - Custom calendar crashed the downloader in some cases
This commit is contained in:
Elwador 2024-07-26 02:18:39 +02:00
parent 607fee38b6
commit e9109210af
15 changed files with 98 additions and 47 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -205,7 +205,7 @@ public class CalendarManager{
calEpisode.EpisodeName = crBrowseEpisode.Title; calEpisode.EpisodeName = crBrowseEpisode.Title;
calEpisode.SeriesUrl = $"https://www.crunchyroll.com/{CrunchyrollManager.Instance.CrunOptions.HistoryLang}/series/" + crBrowseEpisode.EpisodeMetadata.SeriesId; calEpisode.SeriesUrl = $"https://www.crunchyroll.com/{CrunchyrollManager.Instance.CrunOptions.HistoryLang}/series/" + crBrowseEpisode.EpisodeMetadata.SeriesId;
calEpisode.EpisodeUrl = $"https://www.crunchyroll.com/{CrunchyrollManager.Instance.CrunOptions.HistoryLang}/watch/{crBrowseEpisode.Id}/"; calEpisode.EpisodeUrl = $"https://www.crunchyroll.com/{CrunchyrollManager.Instance.CrunOptions.HistoryLang}/watch/{crBrowseEpisode.Id}/";
calEpisode.ThumbnailUrl = crBrowseEpisode.Images.Thumbnail.First().First().Source; calEpisode.ThumbnailUrl = crBrowseEpisode.Images.Thumbnail?.FirstOrDefault()?.FirstOrDefault().Source ?? ""; //https://www.crunchyroll.com/i/coming_soon_beta_thumb.jpg
calEpisode.IsPremiumOnly = crBrowseEpisode.EpisodeMetadata.IsPremiumOnly; calEpisode.IsPremiumOnly = crBrowseEpisode.EpisodeMetadata.IsPremiumOnly;
calEpisode.IsPremiere = crBrowseEpisode.EpisodeMetadata.Episode == "1"; calEpisode.IsPremiere = crBrowseEpisode.EpisodeMetadata.Episode == "1";
calEpisode.SeasonName = crBrowseEpisode.EpisodeMetadata.SeasonTitle; calEpisode.SeasonName = crBrowseEpisode.EpisodeMetadata.SeasonTitle;

View File

@ -127,7 +127,6 @@ public class CrAuth{
} else{ } else{
crunInstance.Profile.HasPremium = subsc.IsActive; crunInstance.Profile.HasPremium = subsc.IsActive;
} }
} else{ } else{
crunInstance.Profile.HasPremium = false; crunInstance.Profile.HasPremium = false;
Console.Error.WriteLine("Failed to check premium subscription status"); Console.Error.WriteLine("Failed to check premium subscription status");

View File

@ -19,7 +19,6 @@ using CRD.Utils.Muxing;
using CRD.Utils.Sonarr; using CRD.Utils.Sonarr;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using CRD.Utils.Structs.History; using CRD.Utils.Structs.History;
using CRD.ViewModels;
using CRD.Views; using CRD.Views;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -34,7 +33,7 @@ public class CrunchyrollManager{
public CrProfile Profile = new(); public CrProfile Profile = new();
private readonly Lazy<CrDownloadOptions> _optionsLazy; private readonly Lazy<CrDownloadOptions> _optionsLazy;
public CrDownloadOptions CrunOptions => _optionsLazy.Value; public CrDownloadOptions CrunOptions => _optionsLazy.Value;
#region History Variables #region History Variables
public ObservableCollection<HistorySeries> HistoryList = new(); public ObservableCollection<HistorySeries> HistoryList = new();
@ -42,7 +41,7 @@ public class CrunchyrollManager{
public HistorySeries SelectedSeries = new HistorySeries{ public HistorySeries SelectedSeries = new HistorySeries{
Seasons =[] Seasons =[]
}; };
#endregion #endregion
@ -58,7 +57,7 @@ public class CrunchyrollManager{
public CrEpisode CrEpisode; public CrEpisode CrEpisode;
public CrSeries CrSeries; public CrSeries CrSeries;
public History History; public History History;
#region Singelton #region Singelton
private static CrunchyrollManager? _instance; private static CrunchyrollManager? _instance;
@ -86,9 +85,8 @@ public class CrunchyrollManager{
private CrDownloadOptions InitDownloadOptions(){ private CrDownloadOptions InitDownloadOptions(){
var options = new CrDownloadOptions(); var options = new CrDownloadOptions();
options.AutoDownload = false; options.AutoDownload = false;
options.RemoveFinishedDownload = false; options.RemoveFinishedDownload = false;
options.Chapters = true; options.Chapters = true;
@ -123,7 +121,7 @@ public class CrunchyrollManager{
return options; return options;
} }
public void InitOptions(){ public void InitOptions(){
_widevine = Widevine.Instance; _widevine = Widevine.Instance;
@ -144,8 +142,6 @@ public class CrunchyrollManager{
} }
public async Task Init(){ public async Task Init(){
if (CrunOptions.LogMode){ if (CrunOptions.LogMode){
CfgManager.EnableLogMode(); CfgManager.EnableLogMode();
} else{ } else{
@ -181,7 +177,6 @@ public class CrunchyrollManager{
} }
public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){ public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){
QueueManager.Instance.ActiveDownloads++; QueueManager.Instance.ActiveDownloads++;
@ -369,7 +364,7 @@ public class CrunchyrollManager{
} }
} }
} }
syncVideosList.ForEach(syncVideo => Helpers.DeleteFile(syncVideo.Path)); syncVideosList.ForEach(syncVideo => Helpers.DeleteFile(syncVideo.Path));
} }
@ -648,14 +643,13 @@ public class CrunchyrollManager{
} }
dlFailed = true; dlFailed = true;
return new DownloadResponse{ return new DownloadResponse{
Data = new List<DownloadedMedia>(), Data = new List<DownloadedMedia>(),
Error = dlFailed, Error = dlFailed,
FileName = "./unknown", FileName = "./unknown",
ErrorText = "Hardsubs not available" ErrorText = "Hardsubs not available"
}; };
} }
} else{ } else{
streams = streams.Where((s) => { streams = streams.Where((s) => {
@ -1601,27 +1595,42 @@ public class CrunchyrollManager{
var showRequestResponse = await HttpClientReq.Instance.SendHttpRequest(showRequest); var showRequestResponse = await HttpClientReq.Instance.SendHttpRequest(showRequest);
if (showRequestResponse.IsOk){ if (showRequestResponse.IsOk){
JObject jObject = JObject.Parse(showRequestResponse.ResponseContent);
CrunchyChapters chapterData = new CrunchyChapters(); CrunchyChapters chapterData = new CrunchyChapters();
chapterData.lastUpdate = jObject["lastUpdate"]?.ToObject<DateTime?>();
chapterData.mediaId = jObject["mediaId"]?.ToObject<string>();
chapterData.Chapters = new List<CrunchyChapter>(); chapterData.Chapters = new List<CrunchyChapter>();
foreach (var property in jObject.Properties()){ try{
// Check if the property value is an object and the property is not one of the known non-dictionary properties JObject jObject = JObject.Parse(showRequestResponse.ResponseContent);
if (property.Value.Type == JTokenType.Object && property.Name != "lastUpdate" && property.Name != "mediaId"){
// Deserialize the property value into a CrunchyChapter and add it to the dictionary if (jObject.TryGetValue("lastUpdate", out JToken lastUpdateToken)){
CrunchyChapter chapter = property.Value.ToObject<CrunchyChapter>(); chapterData.lastUpdate = lastUpdateToken.ToObject<DateTime?>();
chapterData.Chapters.Add(chapter);
} }
if (jObject.TryGetValue("mediaId", out JToken mediaIdToken)){
chapterData.mediaId = mediaIdToken.ToObject<string>();
}
chapterData.Chapters = new List<CrunchyChapter>();
foreach (var property in jObject.Properties()){
if (property.Value.Type == JTokenType.Object && property.Name != "lastUpdate" && property.Name != "mediaId"){
try{
CrunchyChapter chapter = property.Value.ToObject<CrunchyChapter>();
chapterData.Chapters.Add(chapter);
} catch (Exception ex){
Console.Error.WriteLine($"Error parsing chapter: {ex.Message}");
}
}
}
} catch (Exception ex){
Console.Error.WriteLine($"Error parsing JSON response: {ex.Message}");
} }
if (chapterData.Chapters.Count > 0){ if (chapterData.Chapters.Count > 0){
chapterData.Chapters.Sort((a, b) => { chapterData.Chapters.Sort((a, b) => {
if (a.start != null && b.start != null) if (a.start.HasValue && b.start.HasValue){
return a.start.Value - b.start.Value; return a.start.Value.CompareTo(b.start.Value);
return 0; }
return 0; // Both values are null, they are considered equal
}); });
if (!((chapterData.Chapters.Any(c => c.type == "intro")) || chapterData.Chapters.Any(c => c.type == "recap"))){ if (!((chapterData.Chapters.Any(c => c.type == "intro")) || chapterData.Chapters.Any(c => c.type == "recap"))){

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using DynamicData; using DynamicData;
@ -191,7 +192,7 @@ public class Merger{
args.Add($"--track-name {trackName}"); args.Add($"--track-name {trackName}");
args.Add($"--language 0:\"{subObj.Language.Code}\""); args.Add($"--language 0:\"{subObj.Language.Code}\"");
if (options.Defaults.Sub.Code == subObj.Language.Code && subObj.ClosedCaption == false){ if (options.Defaults.Sub.Code == subObj.Language.Code && CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns == subObj.Signs && subObj.ClosedCaption == false){
args.Add("--default-track 0"); args.Add("--default-track 0");
} else{ } else{
args.Add("--default-track 0:0"); args.Add("--default-track 0:0");

View File

@ -2,9 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Net.Http; using System.Net.Http;
using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll; using CRD.Downloader.Crunchyroll;
@ -33,7 +36,7 @@ public partial class CalendarEpisode : INotifyPropertyChanged{
public Bitmap? ImageBitmap{ get; set; } public Bitmap? ImageBitmap{ get; set; }
public string? EpisodeNumber{ get; set; } public string? EpisodeNumber{ get; set; }
public bool IsPremiumOnly{ get; set; } public bool IsPremiumOnly{ get; set; }
public bool IsPremiere{ get; set; } public bool IsPremiere{ get; set; }
@ -48,18 +51,22 @@ public partial class CalendarEpisode : INotifyPropertyChanged{
if (match.Success){ if (match.Success){
var locale = match.Groups[1].Value; // Capture the locale part var locale = match.Groups[1].Value; // Capture the locale part
var id = match.Groups[2].Value; // Capture the ID part var id = match.Groups[2].Value; // Capture the ID part
QueueManager.Instance.CRAddEpisodeToQue(id, Languages.Locale2language(locale).CrLocale, CrunchyrollManager.Instance.CrunOptions.DubLang,true); QueueManager.Instance.CRAddEpisodeToQue(id, Languages.Locale2language(locale).CrLocale, CrunchyrollManager.Instance.CrunOptions.DubLang, true);
} }
} }
public async Task LoadImage(){ public async Task LoadImage(){
try{ try{
using (var client = new HttpClient()){ if (string.IsNullOrEmpty(ThumbnailUrl)){
var response = await client.GetAsync(ThumbnailUrl);
response.EnsureSuccessStatusCode(); } else{
using (var stream = await response.Content.ReadAsStreamAsync()){ using (var client = new HttpClient()){
ImageBitmap = new Bitmap(stream); var response = await client.GetAsync(ThumbnailUrl);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ImageBitmap))); response.EnsureSuccessStatusCode();
using (var stream = await response.Content.ReadAsStreamAsync()){
ImageBitmap = new Bitmap(stream);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ImageBitmap)));
}
} }
} }
} catch (Exception ex){ } catch (Exception ex){

View File

@ -13,12 +13,12 @@ public struct CrunchyChapters{
public struct CrunchyChapter{ public struct CrunchyChapter{
public string approverId { get; set; } public string approverId { get; set; }
public string distributionNumber { get; set; } public string distributionNumber { get; set; }
public int? end { get; set; } public double? end { get; set; }
public int? start { get; set; } public double? start { get; set; }
public string title { get; set; } public string title { get; set; }
public string seriesId { get; set; } public string seriesId { get; set; }
[JsonProperty("new")] [JsonProperty("new")]
public bool New { get; set; } public string? New { get; set; }
public string type { get; set; } public string type { get; set; }
} }

View File

@ -95,6 +95,9 @@ public class CrDownloadOptions{
[YamlMember(Alias = "mux_default_sub", ApplyNamingConventions = false)] [YamlMember(Alias = "mux_default_sub", ApplyNamingConventions = false)]
public string DefaultSub{ get; set; } public string DefaultSub{ get; set; }
[YamlMember(Alias = "mux_default_sub_signs", ApplyNamingConventions = false)]
public bool DefaultSubSigns{ get; set; }
[YamlMember(Alias = "mux_default_dub", ApplyNamingConventions = false)] [YamlMember(Alias = "mux_default_dub", ApplyNamingConventions = false)]
public string DefaultAudio{ get; set; } public string DefaultAudio{ get; set; }

View File

@ -185,7 +185,7 @@ public struct Images{
[JsonProperty("promo_image")] [JsonProperty("promo_image")]
public List<List<Image>>? PromoImage{ get; set; } public List<List<Image>>? PromoImage{ get; set; }
public List<List<Image>> Thumbnail{ get; set; } public List<List<Image>>? Thumbnail{ get; set; }
} }
public struct Image{ public struct Image{

View File

@ -38,6 +38,7 @@ public class Languages{
new(){ CrLocale = "te-IN", Locale = "te-IN", Code = "tel", Name = "Telugu (India)", Language = "తెలుగు" }, new(){ CrLocale = "te-IN", Locale = "te-IN", Code = "tel", Name = "Telugu (India)", Language = "తెలుగు" },
new(){ CrLocale = "id-ID", Locale = "id", Code = "in", Name = "Indonesian " } new(){ CrLocale = "id-ID", Locale = "id", Code = "in", Name = "Indonesian " }
}; };
public static LanguageItem FixAndFindCrLc(string cr_locale){ public static LanguageItem FixAndFindCrLc(string cr_locale){
if (string.IsNullOrEmpty(cr_locale)){ if (string.IsNullOrEmpty(cr_locale)){

View File

@ -11,6 +11,7 @@ using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using CRD.Views.Utils; using CRD.Views.Utils;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Newtonsoft.Json;
namespace CRD.ViewModels; namespace CRD.ViewModels;
@ -40,6 +41,9 @@ public partial class AccountPageViewModel : ViewModelBase{
if (remaining <= TimeSpan.Zero){ if (remaining <= TimeSpan.Zero){
RemainingTime = "No active Subscription"; RemainingTime = "No active Subscription";
_timer.Stop(); _timer.Stop();
if (CrunchyrollManager.Instance.Profile.Subscription != null){
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
}
} else{ } else{
RemainingTime = $"{(IsCancelled ? "Subscription ending in: " : "Subscription refreshing in: ")}{remaining:dd\\:hh\\:mm\\:ss}"; RemainingTime = $"{(IsCancelled ? "Subscription ending in: " : "Subscription refreshing in: ")}{remaining:dd\\:hh\\:mm\\:ss}";
} }
@ -82,6 +86,11 @@ public partial class AccountPageViewModel : ViewModelBase{
_timer.Tick -= Timer_Tick; _timer.Tick -= Timer_Tick;
} }
RaisePropertyChanged(nameof(RemainingTime)); RaisePropertyChanged(nameof(RemainingTime));
if (CrunchyrollManager.Instance.Profile.Subscription != null){
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
}
} }
} }

View File

@ -1,8 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
@ -56,8 +62,9 @@ public partial class CalendarPageViewModel : ViewModelBase{
private CalendarWeek? currentWeek; private CalendarWeek? currentWeek;
private bool loading = true; private bool loading = true;
public CalendarPageViewModel(){ public CalendarPageViewModel(){
CalendarDays = new ObservableCollection<CalendarDay>(); CalendarDays = new ObservableCollection<CalendarDay>();
foreach (var languageItem in Languages.languages){ foreach (var languageItem in Languages.languages){
@ -75,7 +82,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
loading = false; loading = false;
LoadCalendar(GetThisWeeksMondayDate(), false); LoadCalendar(GetThisWeeksMondayDate(), false);
} }
private string GetThisWeeksMondayDate(){ private string GetThisWeeksMondayDate(){
// Get today's date // Get today's date
DateTime today = DateTime.Today; DateTime today = DateTime.Today;
@ -226,7 +233,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
CrunchyrollManager.Instance.CrunOptions.CustomCalendar = value; CrunchyrollManager.Instance.CrunOptions.CustomCalendar = value;
LoadCalendar(GetThisWeeksMondayDate(), true); LoadCalendar(GetThisWeeksMondayDate(), true);
CfgManager.WriteSettingsToFile(); CfgManager.WriteSettingsToFile();
} }

View File

@ -57,6 +57,8 @@ public partial class SettingsPageViewModel : ViewModelBase{
[ObservableProperty] [ObservableProperty]
private bool _syncTimings; private bool _syncTimings;
[ObservableProperty]
private bool _defaultSubSigns;
[ObservableProperty] [ObservableProperty]
private bool _includeEpisodeDescription; private bool _includeEpisodeDescription;
@ -380,6 +382,7 @@ public partial class SettingsPageViewModel : ViewModelBase{
AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes;
SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options); SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options);
DefaultSubSigns = options.DefaultSubSigns;
HistoryAddSpecials = options.HistoryAddSpecials; HistoryAddSpecials = options.HistoryAddSpecials;
DownloadSpeed = options.DownloadSpeedLimit; DownloadSpeed = options.DownloadSpeedLimit;
IncludeEpisodeDescription = options.IncludeVideoDescription; IncludeEpisodeDescription = options.IncludeVideoDescription;
@ -445,7 +448,8 @@ public partial class SettingsPageViewModel : ViewModelBase{
if (!settingsLoaded){ if (!settingsLoaded){
return; return;
} }
CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns = DefaultSubSigns;
CrunchyrollManager.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription; CrunchyrollManager.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription;
CrunchyrollManager.Instance.CrunOptions.HistoryAddSpecials = HistoryAddSpecials; CrunchyrollManager.Instance.CrunOptions.HistoryAddSpecials = HistoryAddSpecials;
CrunchyrollManager.Instance.CrunOptions.VideoTitle = FileTitle; CrunchyrollManager.Instance.CrunOptions.VideoTitle = FileTitle;

View File

@ -177,7 +177,12 @@
Text="{Binding DateTime, StringFormat='hh:mm tt'}" Text="{Binding DateTime, StringFormat='hh:mm tt'}"
Margin="0,0,0,0" /> Margin="0,0,0,0" />
<Grid HorizontalAlignment="Center"> <Grid HorizontalAlignment="Center">
<Image HorizontalAlignment="Center" Source="{Binding ImageBitmap}" /> <Grid>
<Image HorizontalAlignment="Center" Source="../Assets/coming_soon_ep.jpg" />
<Image HorizontalAlignment="Center" Source="{Binding ImageBitmap}" />
</Grid>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left"> <StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock VerticalAlignment="Center" TextAlignment="Center" <TextBlock VerticalAlignment="Center" TextAlignment="Center"
Margin="0 0 5 0" Width="30" Height="30" Margin="0 0 5 0" Width="30" Height="30"

View File

@ -315,6 +315,12 @@
</ComboBox> </ComboBox>
</controls:SettingsExpanderItem.Footer> </controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem> </controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="Default Subtitle Signs" Description="Will set the signs subtitle as default instead">
<controls:SettingsExpanderItem.Footer>
<CheckBox IsChecked="{Binding DefaultSubSigns}"> </CheckBox>
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="File title" <controls:SettingsExpanderItem Content="File title"
Description="${showTitle} ${seriesTitle} ${title} ${season} ${episode} ${height} ${width}"> Description="${showTitle} ${seriesTitle} ${title} ${season} ${episode} ${height} ${width}">