Fix - Hardsub not displayed correctly in settings

Fix - Custom Calendar did not always show all episodes
This commit is contained in:
Elwador 2024-07-21 11:30:20 +02:00
parent c80af817c7
commit 0d530c6b60
28 changed files with 711 additions and 613 deletions

View File

@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Structs;
using HtmlAgilityPack;
namespace CRD.Downloader;
public class CalendarManager{
#region Calendar Variables
private Dictionary<string, CalendarWeek> calendar = new();
private Dictionary<string, string> calendarLanguage = new(){
{ "en-us", "https://www.crunchyroll.com/simulcastcalendar" },
{ "es", "https://www.crunchyroll.com/es/simulcastcalendar" },
{ "es-es", "https://www.crunchyroll.com/es-es/simulcastcalendar" },
{ "pt-br", "https://www.crunchyroll.com/pt-br/simulcastcalendar" },
{ "pt-pt", "https://www.crunchyroll.com/pt-pt/simulcastcalendar" },
{ "fr", "https://www.crunchyroll.com/fr/simulcastcalendar" },
{ "de", "https://www.crunchyroll.com/de/simulcastcalendar" },
{ "ar", "https://www.crunchyroll.com/ar/simulcastcalendar" },
{ "it", "https://www.crunchyroll.com/it/simulcastcalendar" },
{ "ru", "https://www.crunchyroll.com/ru/simulcastcalendar" },
{ "hi", "https://www.crunchyroll.com/hi/simulcastcalendar" },
};
#endregion
#region Singelton
private static CalendarManager? _instance;
private static readonly object Padlock = new();
public static CalendarManager Instance{
get{
if (_instance == null){
lock (Padlock){
if (_instance == null){
_instance = new CalendarManager();
}
}
}
return _instance;
}
}
#endregion
public async Task<CalendarWeek> GetCalendarForDate(string weeksMondayDate, bool forceUpdate){
if (!forceUpdate && calendar.TryGetValue(weeksMondayDate, out var forDate)){
return forDate;
}
var request = calendarLanguage.ContainsKey(CrunchyrollManager.Instance.CrunOptions.SelectedCalendarLanguage ?? "de")
? HttpClientReq.CreateRequestMessage($"{calendarLanguage[CrunchyrollManager.Instance.CrunOptions.SelectedCalendarLanguage ?? "de"]}?filter=premium&date={weeksMondayDate}", HttpMethod.Get, false, false, null)
: HttpClientReq.CreateRequestMessage($"{calendarLanguage["en-us"]}?filter=premium&date={weeksMondayDate}", HttpMethod.Get, false, false, null);
request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
request.Headers.AcceptEncoding.ParseAdd("gzip, deflate, br");
var response = await HttpClientReq.Instance.SendHttpRequest(request);
CalendarWeek week = new CalendarWeek();
week.CalendarDays = new List<CalendarDay>();
// Load the HTML content from a file
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(WebUtility.HtmlDecode(response.ResponseContent));
// Select each 'li' element with class 'day'
var dayNodes = doc.DocumentNode.SelectNodes("//li[contains(@class, 'day')]");
if (dayNodes != null){
foreach (var day in dayNodes){
// Extract the date and day name
var date = day.SelectSingleNode(".//time[@datetime]")?.GetAttributeValue("datetime", "No date");
DateTime dayDateTime = DateTime.Parse(date, null, DateTimeStyles.RoundtripKind);
if (week.FirstDayOfWeek == null){
week.FirstDayOfWeek = dayDateTime;
week.FirstDayOfWeekString = dayDateTime.ToString("yyyy-MM-dd");
}
var dayName = day.SelectSingleNode(".//h1[@class='day-name']/time")?.InnerText.Trim();
CalendarDay calDay = new CalendarDay();
calDay.CalendarEpisodes = new List<CalendarEpisode>();
calDay.DayName = dayName;
calDay.DateTime = dayDateTime;
// Iterate through each episode listed under this day
var episodes = day.SelectNodes(".//article[contains(@class, 'release')]");
if (episodes != null){
foreach (var episode in episodes){
var episodeTimeStr = episode.SelectSingleNode(".//time[contains(@class, 'available-time')]")?.GetAttributeValue("datetime", null);
DateTime episodeTime = DateTime.Parse(episodeTimeStr, null, DateTimeStyles.RoundtripKind);
var hasPassed = DateTime.Now > episodeTime;
var episodeName = episode.SelectSingleNode(".//h1[contains(@class, 'episode-name')]")?.SelectSingleNode(".//cite[@itemprop='name']")?.InnerText.Trim();
var seasonLink = episode.SelectSingleNode(".//a[contains(@class, 'js-season-name-link')]")?.GetAttributeValue("href", "No link");
var episodeLink = episode.SelectSingleNode(".//a[contains(@class, 'available-episode-link')]")?.GetAttributeValue("href", "No link");
var thumbnailUrl = episode.SelectSingleNode(".//img[contains(@class, 'thumbnail')]")?.GetAttributeValue("src", "No image");
var isPremiumOnly = episode.SelectSingleNode(".//svg[contains(@class, 'premium-flag')]") != null;
var isPremiere = episode.SelectSingleNode(".//div[contains(@class, 'premiere-flag')]") != null;
var seasonName = episode.SelectSingleNode(".//a[contains(@class, 'js-season-name-link')]")?.SelectSingleNode(".//cite[@itemprop='name']")?.InnerText.Trim();
var episodeNumber = episode.SelectSingleNode(".//meta[contains(@itemprop, 'episodeNumber')]")?.GetAttributeValue("content", "?");
CalendarEpisode calEpisode = new CalendarEpisode();
calEpisode.DateTime = episodeTime;
calEpisode.HasPassed = hasPassed;
calEpisode.EpisodeName = episodeName;
calEpisode.SeriesUrl = seasonLink;
calEpisode.EpisodeUrl = episodeLink;
calEpisode.ThumbnailUrl = thumbnailUrl;
calEpisode.IsPremiumOnly = isPremiumOnly;
calEpisode.IsPremiere = isPremiere;
calEpisode.SeasonName = seasonName;
calEpisode.EpisodeNumber = episodeNumber;
calDay.CalendarEpisodes.Add(calEpisode);
}
}
week.CalendarDays.Add(calDay);
}
} else{
Console.Error.WriteLine("No days found in the HTML document.");
}
calendar[weeksMondayDate] = week;
return week;
}
public async Task<CalendarWeek> BuildCustomCalendar(bool forceUpdate){
Console.WriteLine("C" + DateTime.Now.ToString("yyyy-MM-dd"));
if (!forceUpdate && calendar.TryGetValue("C" + DateTime.Now.ToString("yyyy-MM-dd"), out var forDate)){
return forDate;
}
CalendarWeek week = new CalendarWeek();
week.CalendarDays = new List<CalendarDay>();
DateTime today = DateTime.Now;
for (int i = 0; i < 7; i++){
CalendarDay calDay = new CalendarDay();
calDay.CalendarEpisodes = new List<CalendarEpisode>();
calDay.DateTime = today.AddDays(-i);
calDay.DayName = calDay.DateTime.Value.DayOfWeek.ToString();
week.CalendarDays.Add(calDay);
}
week.CalendarDays.Reverse();
var firstDayOfWeek = week.CalendarDays.First().DateTime;
var newEpisodesBase = await CrunchyrollManager.Instance.CrEpisode.GetNewEpisodes(CrunchyrollManager.Instance.CrunOptions.HistoryLang, 200,firstDayOfWeek, true);
if (newEpisodesBase is{ Data.Count: > 0 }){
var newEpisodes = newEpisodesBase.Data;
foreach (var crBrowseEpisode in newEpisodes){
var targetDate = CrunchyrollManager.Instance.CrunOptions.CalendarFilterByAirDate ? crBrowseEpisode.EpisodeMetadata.EpisodeAirDate : crBrowseEpisode.LastPublic;
if (CrunchyrollManager.Instance.CrunOptions.CalendarHideDubs && crBrowseEpisode.EpisodeMetadata.SeasonTitle != null &&
(crBrowseEpisode.EpisodeMetadata.SeasonTitle.EndsWith("Dub)") || crBrowseEpisode.EpisodeMetadata.AudioLocale != Locale.JaJp)){
continue;
}
var dubFilter = CrunchyrollManager.Instance.CrunOptions.CalendarDubFilter;
if (!string.IsNullOrEmpty(dubFilter) && dubFilter != "none"){
if (crBrowseEpisode.EpisodeMetadata.AudioLocale != null && crBrowseEpisode.EpisodeMetadata.AudioLocale.GetEnumMemberValue() != dubFilter){
continue;
}
}
var calendarDay = (from day in week.CalendarDays
where day.DateTime.HasValue && day.DateTime.Value.Date == targetDate.Date
select day).FirstOrDefault();
if (calendarDay != null){
CalendarEpisode calEpisode = new CalendarEpisode();
calEpisode.DateTime = targetDate;
calEpisode.HasPassed = DateTime.Now > targetDate;
calEpisode.EpisodeName = crBrowseEpisode.Title;
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.ThumbnailUrl = crBrowseEpisode.Images.Thumbnail.First().First().Source;
calEpisode.IsPremiumOnly = crBrowseEpisode.EpisodeMetadata.IsPremiumOnly;
calEpisode.IsPremiere = crBrowseEpisode.EpisodeMetadata.Episode == "1";
calEpisode.SeasonName = crBrowseEpisode.EpisodeMetadata.SeasonTitle;
calEpisode.EpisodeNumber = crBrowseEpisode.EpisodeMetadata.Episode;
calendarDay.CalendarEpisodes?.Add(calEpisode);
}
}
}
foreach (var day in week.CalendarDays){
if (day.CalendarEpisodes != null) day.CalendarEpisodes = day.CalendarEpisodes.OrderBy(e => e.DateTime).ToList();
}
calendar["C" + DateTime.Now.ToString("yyyy-MM-dd")] = week;
return week;
}
}

View File

@ -9,13 +9,12 @@ using System.Web;
using CRD.Utils;
using CRD.Utils.Structs;
using Newtonsoft.Json;
using YamlDotNet.Core.Tokens;
namespace CRD.Downloader;
namespace CRD.Downloader.Crunchyroll;
public class CrAuth{
private readonly Crunchyroll crunInstance = Crunchyroll.Instance;
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
public async Task AuthAnonymous(){
var formData = new Dictionary<string, string>{
@ -46,7 +45,7 @@ public class CrAuth{
PreferredContentSubtitleLanguage = "de-DE"
};
Crunchyroll.Instance.CmsToken = new CrCmsToken();
CrunchyrollManager.Instance.CmsToken = new CrCmsToken();
}

View File

@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Remote.Protocol.Input;
using CRD.Utils;
using CRD.Utils.Structs;
using Newtonsoft.Json;
namespace CRD.Downloader;
namespace CRD.Downloader.Crunchyroll;
public class CrEpisode(){
private readonly Crunchyroll crunInstance = Crunchyroll.Instance;
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
public async Task<CrunchyEpisode?> ParseEpisodeById(string id, string crLocale, bool forcedLang = false){
if (crunInstance.CmsToken?.Cms == null){
@ -67,11 +64,11 @@ public class CrEpisode(){
CrunchyRollEpisodeData episode = new CrunchyRollEpisodeData();
if (crunInstance.CrunOptions.History && updateHistory){
await crunInstance.CrHistory.UpdateWithEpisode(dlEpisode);
await crunInstance.History.UpdateWithEpisode(dlEpisode);
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == dlEpisode.SeriesId);
if (historySeries != null){
Crunchyroll.Instance.CrHistory.MatchHistorySeriesWithSonarr(false);
await Crunchyroll.Instance.CrHistory.MatchHistoryEpisodesWithSonarr(false, historySeries);
CrunchyrollManager.Instance.History.MatchHistorySeriesWithSonarr(false);
await CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, historySeries);
CfgManager.UpdateHistoryFile();
}
}
@ -245,7 +242,7 @@ public class CrEpisode(){
return retMeta;
}
public async Task<CrBrowseEpisodeBase?> GetNewEpisodes(string? crLocale, int requestAmount , bool forcedLang = false){
public async Task<CrBrowseEpisodeBase?> GetNewEpisodes(string? crLocale, int requestAmount,DateTime? firstWeekDay = null , bool forcedLang = false){
CrBrowseEpisodeBase? complete = new CrBrowseEpisodeBase();
complete.Data =[];
@ -279,13 +276,21 @@ public class CrEpisode(){
if (series != null){
complete.Total = series.Total;
if (series.Data != null) complete.Data.AddRange(series.Data);
if (series.Data != null){
complete.Data.AddRange(series.Data);
if (firstWeekDay != null){
if (firstWeekDay.Value.Date <= series.Data.Last().LastPublic && i + 50 == requestAmount){
requestAmount += 50;
}
}
}
} else{
break;
}
i += 50;
} while (i < requestAmount);
} while (i < requestAmount && requestAmount < 500);
return complete;

View File

@ -1,24 +1,20 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using CRD.Utils;
using CRD.Utils.Structs;
using CRD.Views;
using DynamicData;
using Newtonsoft.Json;
using ReactiveUI;
namespace CRD.Downloader;
namespace CRD.Downloader.Crunchyroll;
public class CrSeries(){
private readonly Crunchyroll crunInstance = Crunchyroll.Instance;
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
public async Task<List<CrunchyEpMeta>> DownloadFromSeriesId(string id, CrunchyMultiDownload data){
var series = await ListSeriesId(id, "", data);
@ -57,7 +53,7 @@ public class CrSeries(){
}
if (crunInstance.CrunOptions.History){
var dubLangList = crunInstance.CrHistory.GetDubList(item.SeriesId, item.SeasonId);
var dubLangList = crunInstance.History.GetDubList(item.SeriesId, item.SeasonId);
if (dubLangList.Count > 0){
dubLang = dubLangList;
}
@ -164,7 +160,7 @@ public class CrSeries(){
var seasonData = await GetSeasonDataById(s.Id, "");
if (seasonData.Data != null){
if (crunInstance.CrunOptions.History){
crunInstance.CrHistory.UpdateWithSeasonData(seasonData,false);
crunInstance.History.UpdateWithSeasonData(seasonData,false);
}
foreach (var episode in seasonData.Data){
@ -214,8 +210,8 @@ public class CrSeries(){
if (crunInstance.CrunOptions.History){
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == id);
if (historySeries != null){
crunInstance.CrHistory.MatchHistorySeriesWithSonarr(false);
await crunInstance.CrHistory.MatchHistoryEpisodesWithSonarr(false, historySeries);
crunInstance.History.MatchHistorySeriesWithSonarr(false);
await crunInstance.History.MatchHistoryEpisodesWithSonarr(false, historySeries);
CfgManager.UpdateHistoryFile();
}
}

View File

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
@ -13,62 +11,27 @@ using System.Threading.Tasks;
using System.Xml;
using Avalonia.Media;
using CRD.Utils;
using CRD.Utils.CustomList;
using CRD.Utils.DRM;
using CRD.Utils.Files;
using CRD.Utils.HLS;
using CRD.Utils.Muxing;
using CRD.Utils.Sonarr;
using CRD.Utils.Sonarr.Models;
using CRD.Utils.Structs;
using CRD.Utils.Structs.History;
using CRD.ViewModels;
using CRD.Views;
using HtmlAgilityPack;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ReactiveUI;
using LanguageItem = CRD.Utils.Structs.LanguageItem;
namespace CRD.Downloader;
namespace CRD.Downloader.Crunchyroll;
public class Crunchyroll{
public class CrunchyrollManager{
public CrToken? Token;
public CrCmsToken? CmsToken;
public CrProfile Profile = new();
public CrDownloadOptions CrunOptions;
#region Download Variables
public RefreshableObservableCollection<CrunchyEpMeta> Queue = new RefreshableObservableCollection<CrunchyEpMeta>();
public ObservableCollection<DownloadItemModel> DownloadItemModels = new ObservableCollection<DownloadItemModel>();
public int ActiveDownloads;
#endregion
#region Calendar Variables
private Dictionary<string, CalendarWeek> calendar = new();
private Dictionary<string, string> calendarLanguage = new(){
{ "en-us", "https://www.crunchyroll.com/simulcastcalendar" },
{ "es", "https://www.crunchyroll.com/es/simulcastcalendar" },
{ "es-es", "https://www.crunchyroll.com/es-es/simulcastcalendar" },
{ "pt-br", "https://www.crunchyroll.com/pt-br/simulcastcalendar" },
{ "pt-pt", "https://www.crunchyroll.com/pt-pt/simulcastcalendar" },
{ "fr", "https://www.crunchyroll.com/fr/simulcastcalendar" },
{ "de", "https://www.crunchyroll.com/de/simulcastcalendar" },
{ "ar", "https://www.crunchyroll.com/ar/simulcastcalendar" },
{ "it", "https://www.crunchyroll.com/it/simulcastcalendar" },
{ "ru", "https://www.crunchyroll.com/ru/simulcastcalendar" },
{ "hi", "https://www.crunchyroll.com/hi/simulcastcalendar" },
};
#endregion
#region History Variables
public ObservableCollection<HistorySeries> HistoryList = new();
@ -76,9 +39,7 @@ public class Crunchyroll{
public HistorySeries SelectedSeries = new HistorySeries{
Seasons =[]
};
public List<SonarrSeries> SonarrSeries =[];
#endregion
@ -93,19 +54,19 @@ public class Crunchyroll{
public CrAuth CrAuth;
public CrEpisode CrEpisode;
public CrSeries CrSeries;
public History CrHistory;
public History History;
#region Singelton
private static Crunchyroll? _instance;
private static CrunchyrollManager? _instance;
private static readonly object Padlock = new();
public static Crunchyroll Instance{
public static CrunchyrollManager Instance{
get{
if (_instance == null){
lock (Padlock){
if (_instance == null){
_instance = new Crunchyroll();
_instance = new CrunchyrollManager();
}
}
}
@ -116,9 +77,8 @@ public class Crunchyroll{
#endregion
public Crunchyroll(){
public CrunchyrollManager(){
CrunOptions = new CrDownloadOptions();
Queue.CollectionChanged += UpdateItemListOnRemove;
}
public void InitOptions(){
@ -159,7 +119,7 @@ public class Crunchyroll{
CrAuth = new CrAuth();
CrEpisode = new CrEpisode();
CrSeries = new CrSeries();
CrHistory = new History();
History = new History();
Profile = new CrProfile{
Username = "???",
@ -204,267 +164,15 @@ public class Crunchyroll{
HistoryList =[];
}
RefreshSonarr();
}
}
}
public async void RefreshSonarr(){
await SonarrClient.Instance.CheckSonarrSettings();
if (CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
SonarrSeries = await SonarrClient.Instance.GetSeries();
CrHistory.MatchHistorySeriesWithSonarr(true);
}
}
private void UpdateItemListOnRemove(object? sender, NotifyCollectionChangedEventArgs e){
if (e.Action == NotifyCollectionChangedAction.Remove){
if (e.OldItems != null)
foreach (var eOldItem in e.OldItems){
var downloadItem = DownloadItemModels.FirstOrDefault(e => e.epMeta.Equals(eOldItem));
if (downloadItem != null){
DownloadItemModels.Remove(downloadItem);
} else{
Console.Error.WriteLine("Failed to Remove Episode from list");
}
}
}
UpdateDownloadListItems();
}
public void UpdateDownloadListItems(){
var list = Queue;
foreach (CrunchyEpMeta crunchyEpMeta in list){
var downloadItem = DownloadItemModels.FirstOrDefault(e => e.epMeta.Equals(crunchyEpMeta));
if (downloadItem != null){
downloadItem.Refresh();
} else{
downloadItem = new DownloadItemModel(crunchyEpMeta);
downloadItem.LoadImage();
DownloadItemModels.Add(downloadItem);
}
if (downloadItem is{ isDownloading: false, Error: false } && CrunOptions.AutoDownload && ActiveDownloads < CrunOptions.SimultaneousDownloads){
downloadItem.StartDownload();
SonarrClient.Instance.RefreshSonarr();
}
}
}
public async Task<CalendarWeek> GetCalendarForDate(string weeksMondayDate, bool forceUpdate){
if (!forceUpdate && calendar.TryGetValue(weeksMondayDate, out var forDate)){
return forDate;
}
var request = calendarLanguage.ContainsKey(CrunOptions.SelectedCalendarLanguage ?? "de")
? HttpClientReq.CreateRequestMessage($"{calendarLanguage[CrunOptions.SelectedCalendarLanguage ?? "de"]}?filter=premium&date={weeksMondayDate}", HttpMethod.Get, false, false, null)
: HttpClientReq.CreateRequestMessage($"{calendarLanguage["en-us"]}?filter=premium&date={weeksMondayDate}", HttpMethod.Get, false, false, null);
request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
request.Headers.AcceptEncoding.ParseAdd("gzip, deflate, br");
var response = await HttpClientReq.Instance.SendHttpRequest(request);
CalendarWeek week = new CalendarWeek();
week.CalendarDays = new List<CalendarDay>();
// Load the HTML content from a file
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(WebUtility.HtmlDecode(response.ResponseContent));
// Select each 'li' element with class 'day'
var dayNodes = doc.DocumentNode.SelectNodes("//li[contains(@class, 'day')]");
if (dayNodes != null){
foreach (var day in dayNodes){
// Extract the date and day name
var date = day.SelectSingleNode(".//time[@datetime]")?.GetAttributeValue("datetime", "No date");
DateTime dayDateTime = DateTime.Parse(date, null, DateTimeStyles.RoundtripKind);
if (week.FirstDayOfWeek == null){
week.FirstDayOfWeek = dayDateTime;
week.FirstDayOfWeekString = dayDateTime.ToString("yyyy-MM-dd");
}
var dayName = day.SelectSingleNode(".//h1[@class='day-name']/time")?.InnerText.Trim();
CalendarDay calDay = new CalendarDay();
calDay.CalendarEpisodes = new List<CalendarEpisode>();
calDay.DayName = dayName;
calDay.DateTime = dayDateTime;
// Iterate through each episode listed under this day
var episodes = day.SelectNodes(".//article[contains(@class, 'release')]");
if (episodes != null){
foreach (var episode in episodes){
var episodeTimeStr = episode.SelectSingleNode(".//time[contains(@class, 'available-time')]")?.GetAttributeValue("datetime", null);
DateTime episodeTime = DateTime.Parse(episodeTimeStr, null, DateTimeStyles.RoundtripKind);
var hasPassed = DateTime.Now > episodeTime;
var episodeName = episode.SelectSingleNode(".//h1[contains(@class, 'episode-name')]")?.SelectSingleNode(".//cite[@itemprop='name']")?.InnerText.Trim();
var seasonLink = episode.SelectSingleNode(".//a[contains(@class, 'js-season-name-link')]")?.GetAttributeValue("href", "No link");
var episodeLink = episode.SelectSingleNode(".//a[contains(@class, 'available-episode-link')]")?.GetAttributeValue("href", "No link");
var thumbnailUrl = episode.SelectSingleNode(".//img[contains(@class, 'thumbnail')]")?.GetAttributeValue("src", "No image");
var isPremiumOnly = episode.SelectSingleNode(".//svg[contains(@class, 'premium-flag')]") != null;
var isPremiere = episode.SelectSingleNode(".//div[contains(@class, 'premiere-flag')]") != null;
var seasonName = episode.SelectSingleNode(".//a[contains(@class, 'js-season-name-link')]")?.SelectSingleNode(".//cite[@itemprop='name']")?.InnerText.Trim();
var episodeNumber = episode.SelectSingleNode(".//meta[contains(@itemprop, 'episodeNumber')]")?.GetAttributeValue("content", "?");
CalendarEpisode calEpisode = new CalendarEpisode();
calEpisode.DateTime = episodeTime;
calEpisode.HasPassed = hasPassed;
calEpisode.EpisodeName = episodeName;
calEpisode.SeriesUrl = seasonLink;
calEpisode.EpisodeUrl = episodeLink;
calEpisode.ThumbnailUrl = thumbnailUrl;
calEpisode.IsPremiumOnly = isPremiumOnly;
calEpisode.IsPremiere = isPremiere;
calEpisode.SeasonName = seasonName;
calEpisode.EpisodeNumber = episodeNumber;
calDay.CalendarEpisodes.Add(calEpisode);
}
}
week.CalendarDays.Add(calDay);
}
} else{
Console.Error.WriteLine("No days found in the HTML document.");
}
calendar[weeksMondayDate] = week;
return week;
}
public async Task AddEpisodeToQue(string epId, string crLocale, List<string> dubLang, bool updateHistory = false){
await CrAuth.RefreshToken(true);
var episodeL = await CrEpisode.ParseEpisodeById(epId, crLocale);
if (episodeL != null){
if (episodeL.Value.IsPremiumOnly && !Profile.HasPremium){
MessageBus.Current.SendMessage(new ToastMessage($"Episode is a premium episode make sure that you are signed in with an account that has an active premium subscription", ToastType.Error, 3));
return;
}
var sList = await CrEpisode.EpisodeData((CrunchyEpisode)episodeL, updateHistory);
(HistoryEpisode? historyEpisode, List<string> dublist, string downloadDirPath) historyEpisode = (null, [], "");
if (CrunOptions.History){
var episode = sList.EpisodeAndLanguages.Items.First();
historyEpisode = CrHistory.GetHistoryEpisodeWithDubListAndDownloadDir(episode.SeriesId, episode.SeasonId, episode.Id);
if (historyEpisode.dublist.Count > 0){
dubLang = historyEpisode.dublist;
}
}
var selected = CrEpisode.EpisodeMeta(sList, dubLang);
if (CrunOptions.IncludeVideoDescription){
if (selected.Data is{ Count: > 0 }){
var episode = await CrEpisode.ParseEpisodeById(selected.Data.First().MediaId, string.IsNullOrEmpty(CrunOptions.DescriptionLang) ? DefaultLocale : CrunOptions.DescriptionLang, true);
selected.Description = episode?.Description ?? selected.Description;
}
}
if (selected.Data is{ Count: > 0 }){
if (CrunOptions.History){
// var historyEpisode = CrHistory.GetHistoryEpisodeWithDownloadDir(selected.ShowId, selected.SeasonId, selected.Data.First().MediaId);
if (CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){
if (historyEpisode.historyEpisode != null){
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrEpisodeNumber)){
selected.EpisodeNumber = historyEpisode.historyEpisode.SonarrEpisodeNumber;
}
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrSeasonNumber)){
selected.Season = historyEpisode.historyEpisode.SonarrSeasonNumber;
}
}
}
if (!string.IsNullOrEmpty(historyEpisode.downloadDirPath)){
selected.DownloadPath = historyEpisode.downloadDirPath;
}
}
selected.DownloadSubs = CrunOptions.DlSubs;
Queue.Add(selected);
if (selected.Data.Count < dubLang.Count){
Console.WriteLine("Added Episode to Queue but couldn't find all selected dubs");
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue but couldn't find all selected dubs", ToastType.Warning, 2));
} else{
Console.WriteLine("Added Episode to Queue");
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue", ToastType.Information, 1));
}
} else{
Console.WriteLine("Episode couldn't be added to Queue");
MessageBus.Current.SendMessage(new ToastMessage($"Couldn't add episode to the queue with current dub settings", ToastType.Error, 2));
}
}
}
public async Task AddSeriesToQueue(CrunchySeriesList list, CrunchyMultiDownload data){
var selected = CrSeries.ItemSelectMultiDub(list.Data, data.DubLang, data.But, data.AllEpisodes, data.E);
bool failed = false;
foreach (var crunchyEpMeta in selected.Values.ToList()){
if (crunchyEpMeta.Data?.First().Playback != null){
if (CrunOptions.History){
var historyEpisode = CrHistory.GetHistoryEpisodeWithDownloadDir(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId, crunchyEpMeta.Data.First().MediaId);
if (CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){
if (historyEpisode.historyEpisode != null){
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrEpisodeNumber)){
crunchyEpMeta.EpisodeNumber = historyEpisode.historyEpisode.SonarrEpisodeNumber;
}
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrSeasonNumber)){
crunchyEpMeta.Season = historyEpisode.historyEpisode.SonarrSeasonNumber;
}
}
}
if (!string.IsNullOrEmpty(historyEpisode.downloadDirPath)){
crunchyEpMeta.DownloadPath = historyEpisode.downloadDirPath;
}
}
if (CrunOptions.IncludeVideoDescription){
if (crunchyEpMeta.Data is{ Count: > 0 }){
var episode = await CrEpisode.ParseEpisodeById(crunchyEpMeta.Data.First().MediaId, string.IsNullOrEmpty(CrunOptions.DescriptionLang) ? DefaultLocale : CrunOptions.DescriptionLang, true);
crunchyEpMeta.Description = episode?.Description ?? crunchyEpMeta.Description;
}
}
crunchyEpMeta.DownloadSubs = CrunOptions.DlSubs;
Queue.Add(crunchyEpMeta);
} else{
failed = true;
}
}
if (failed){
MainWindow.Instance.ShowError("Not all episodes could be added make sure that you are signed in with an account that has an active premium subscription?");
} else{
MessageBus.Current.SendMessage(new ToastMessage($"Added episodes to the queue", ToastType.Information, 1));
}
}
public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){
ActiveDownloads++;
QueueManager.Instance.ActiveDownloads++;
data.DownloadProgress = new DownloadProgress(){
IsDownloading = true,
@ -474,11 +182,11 @@ public class Crunchyroll{
DownloadSpeed = 0,
Doing = "Starting"
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
var res = await DownloadMediaList(data, options);
if (res.Error){
ActiveDownloads--;
QueueManager.Instance.ActiveDownloads--;
data.DownloadProgress = new DownloadProgress(){
IsDownloading = false,
Error = true,
@ -487,7 +195,7 @@ public class Crunchyroll{
DownloadSpeed = 0,
Doing = "Download Error" + (!string.IsNullOrEmpty(res.ErrorText) ? " - " + res.ErrorText : ""),
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
return false;
}
@ -500,7 +208,7 @@ public class Crunchyroll{
Doing = "Muxing"
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
await MuxStreams(res.Data,
new CrunchyMuxOptions{
@ -532,17 +240,17 @@ public class Crunchyroll{
};
if (CrunOptions.RemoveFinishedDownload){
Queue.Remove(data);
QueueManager.Instance.Queue.Remove(data);
}
} else{
Console.WriteLine("Skipping mux");
}
ActiveDownloads--;
Queue.Refresh();
QueueManager.Instance.ActiveDownloads--;
QueueManager.Instance.Queue.Refresh();
if (CrunOptions.History && data.Data != null && data.Data.Count > 0){
CrHistory.SetAsDownloaded(data.ShowId, data.SeasonId, data.Data.First().MediaId);
History.SetAsDownloaded(data.ShowId, data.SeasonId, data.Data.First().MediaId);
}
@ -1190,7 +898,7 @@ public class Crunchyroll{
DownloadSpeed = 0,
Doing = "Decrypting"
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
var assetIdRegexMatch = Regex.Match(chosenVideoSegments.segments[0].uri, @"/assets/(?:p/)?([^_,]+)");
var assetId = assetIdRegexMatch.Success ? assetIdRegexMatch.Groups[1].Value : null;
@ -1272,7 +980,7 @@ public class Crunchyroll{
DownloadSpeed = 0,
Doing = "Decrypting video"
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
var decryptVideo = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandVideo, tempTsFileWorkDir);
if (!decryptVideo.IsOk){
@ -1338,7 +1046,7 @@ public class Crunchyroll{
DownloadSpeed = 0,
Doing = "Decrypting audio"
};
Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
var decryptAudio = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandAudio, tempTsFileWorkDir);
if (!decryptAudio.IsOk){

View File

@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Sonarr;
using CRD.Utils.Sonarr.Models;
@ -16,9 +17,9 @@ using ReactiveUI;
namespace CRD.Downloader;
public class History(){
private readonly Crunchyroll crunInstance = Crunchyroll.Instance;
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
public async Task UpdateSeries(string seriesId, string? seasonId){
public async Task CRUpdateSeries(string seriesId, string? seasonId){
await crunInstance.CrAuth.RefreshToken(true);
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "ja-JP", true);
@ -266,11 +267,11 @@ public class History(){
if (seasonData.Data.First().Versions != null){
var version = seasonData.Data.First().Versions.Find(a => a.Original);
if (version.AudioLocale != seasonData.Data.First().AudioLocale){
UpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid);
CRUpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid);
return;
}
} else{
UpdateSeries(seasonData.Data.First().SeriesId, "");
CRUpdateSeries(seasonData.Data.First().SeriesId, "");
return;
}
}
@ -380,18 +381,18 @@ public class History(){
}
public void SortItems(){
var currentSortingType = Crunchyroll.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle;
var sortingDir = Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null && Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending;
var currentSortingType = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle;
var sortingDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null && CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
DateTime today = DateTime.UtcNow.Date;
switch (currentSortingType){
case SortingType.SeriesTitle:
var sortedList = sortingDir
? Crunchyroll.Instance.HistoryList.OrderByDescending(s => s.SeriesTitle).ToList()
: Crunchyroll.Instance.HistoryList.OrderBy(s => s.SeriesTitle).ToList();
? CrunchyrollManager.Instance.HistoryList.OrderByDescending(s => s.SeriesTitle).ToList()
: CrunchyrollManager.Instance.HistoryList.OrderBy(s => s.SeriesTitle).ToList();
Crunchyroll.Instance.HistoryList.Clear();
CrunchyrollManager.Instance.HistoryList.Clear();
Crunchyroll.Instance.HistoryList.AddRange(sortedList);
CrunchyrollManager.Instance.HistoryList.AddRange(sortedList);
return;
@ -399,7 +400,7 @@ public class History(){
case SortingType.NextAirDate:
var sortedSeriesDates = sortingDir
? Crunchyroll.Instance.HistoryList
? CrunchyrollManager.Instance.HistoryList
.OrderByDescending(s => {
var date = ParseDate(s.SonarrNextAirDate, today);
return date.HasValue ? date.Value : DateTime.MinValue;
@ -408,7 +409,7 @@ public class History(){
.ThenBy(s => string.IsNullOrEmpty(s.SonarrNextAirDate) ? 1 : 0)
.ThenBy(s => s.SeriesTitle)
.ToList()
: Crunchyroll.Instance.HistoryList
: CrunchyrollManager.Instance.HistoryList
.OrderByDescending(s => s.SonarrNextAirDate == "Today")
.ThenBy(s => s.SonarrNextAirDate == "Today" ? s.SeriesTitle : null)
.ThenBy(s => {
@ -418,16 +419,16 @@ public class History(){
.ThenBy(s => s.SeriesTitle)
.ToList();
Crunchyroll.Instance.HistoryList.Clear();
CrunchyrollManager.Instance.HistoryList.Clear();
Crunchyroll.Instance.HistoryList.AddRange(sortedSeriesDates);
CrunchyrollManager.Instance.HistoryList.AddRange(sortedSeriesDates);
return;
case SortingType.HistorySeriesAddDate:
var sortedSeriesAddDates = Crunchyroll.Instance.HistoryList
var sortedSeriesAddDates = CrunchyrollManager.Instance.HistoryList
.OrderBy(s => sortingDir
? -(s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MinValue.Ticks)
: s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MaxValue.Ticks)
@ -435,9 +436,9 @@ public class History(){
.ToList();
Crunchyroll.Instance.HistoryList.Clear();
CrunchyrollManager.Instance.HistoryList.Clear();
Crunchyroll.Instance.HistoryList.AddRange(sortedSeriesAddDates);
CrunchyrollManager.Instance.HistoryList.AddRange(sortedSeriesAddDates);
return;
}
@ -668,7 +669,7 @@ public class History(){
SonarrSeries? closestMatch = null;
double highestSimilarity = 0.0;
Parallel.ForEach(crunInstance.SonarrSeries, series => {
Parallel.ForEach(SonarrClient.Instance.SonarrSeries, series => {
double similarity = CalculateSimilarity(series.Title.ToLower(), title.ToLower());
if (similarity > highestSimilarity){
highestSimilarity = similarity;

View File

@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.CustomList;
using CRD.Utils.Structs;
using CRD.Utils.Structs.History;
using CRD.ViewModels;
using CRD.Views;
using ReactiveUI;
namespace CRD.Downloader;
public class QueueManager{
#region Download Variables
public RefreshableObservableCollection<CrunchyEpMeta> Queue = new RefreshableObservableCollection<CrunchyEpMeta>();
public ObservableCollection<DownloadItemModel> DownloadItemModels = new ObservableCollection<DownloadItemModel>();
public int ActiveDownloads;
#endregion
#region Singelton
private static QueueManager? _instance;
private static readonly object Padlock = new();
public static QueueManager Instance{
get{
if (_instance == null){
lock (Padlock){
if (_instance == null){
_instance = new QueueManager();
}
}
}
return _instance;
}
}
#endregion
public QueueManager(){
Queue.CollectionChanged += UpdateItemListOnRemove;
}
private void UpdateItemListOnRemove(object? sender, NotifyCollectionChangedEventArgs e){
if (e.Action == NotifyCollectionChangedAction.Remove){
if (e.OldItems != null)
foreach (var eOldItem in e.OldItems){
var downloadItem = DownloadItemModels.FirstOrDefault(e => e.epMeta.Equals(eOldItem));
if (downloadItem != null){
DownloadItemModels.Remove(downloadItem);
} else{
Console.Error.WriteLine("Failed to Remove Episode from list");
}
}
}
UpdateDownloadListItems();
}
public void UpdateDownloadListItems(){
var list = Queue;
foreach (CrunchyEpMeta crunchyEpMeta in list){
var downloadItem = DownloadItemModels.FirstOrDefault(e => e.epMeta.Equals(crunchyEpMeta));
if (downloadItem != null){
downloadItem.Refresh();
} else{
downloadItem = new DownloadItemModel(crunchyEpMeta);
downloadItem.LoadImage();
DownloadItemModels.Add(downloadItem);
}
if (downloadItem is{ isDownloading: false, Error: false } && CrunchyrollManager.Instance.CrunOptions.AutoDownload && ActiveDownloads < CrunchyrollManager.Instance.CrunOptions.SimultaneousDownloads){
downloadItem.StartDownload();
}
}
}
public async Task CRAddEpisodeToQue(string epId, string crLocale, List<string> dubLang, bool updateHistory = false){
await CrunchyrollManager.Instance.CrAuth.RefreshToken(true);
var episodeL = await CrunchyrollManager.Instance.CrEpisode.ParseEpisodeById(epId, crLocale);
if (episodeL != null){
if (episodeL.Value.IsPremiumOnly && !CrunchyrollManager.Instance.Profile.HasPremium){
MessageBus.Current.SendMessage(new ToastMessage($"Episode is a premium episode make sure that you are signed in with an account that has an active premium subscription", ToastType.Error, 3));
return;
}
var sList = await CrunchyrollManager.Instance.CrEpisode.EpisodeData((CrunchyEpisode)episodeL, updateHistory);
(HistoryEpisode? historyEpisode, List<string> dublist, string downloadDirPath) historyEpisode = (null, [], "");
if (CrunchyrollManager.Instance.CrunOptions.History){
var episode = sList.EpisodeAndLanguages.Items.First();
historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDubListAndDownloadDir(episode.SeriesId, episode.SeasonId, episode.Id);
if (historyEpisode.dublist.Count > 0){
dubLang = historyEpisode.dublist;
}
}
var selected = CrunchyrollManager.Instance.CrEpisode.EpisodeMeta(sList, dubLang);
if (CrunchyrollManager.Instance.CrunOptions.IncludeVideoDescription){
if (selected.Data is{ Count: > 0 }){
var episode = await CrunchyrollManager.Instance.CrEpisode.ParseEpisodeById(selected.Data.First().MediaId,
string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.DescriptionLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.DescriptionLang, true);
selected.Description = episode?.Description ?? selected.Description;
}
}
if (selected.Data is{ Count: > 0 }){
if (CrunchyrollManager.Instance.CrunOptions.History){
// var historyEpisode = CrHistory.GetHistoryEpisodeWithDownloadDir(selected.ShowId, selected.SeasonId, selected.Data.First().MediaId);
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){
if (historyEpisode.historyEpisode != null){
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrEpisodeNumber)){
selected.EpisodeNumber = historyEpisode.historyEpisode.SonarrEpisodeNumber;
}
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrSeasonNumber)){
selected.Season = historyEpisode.historyEpisode.SonarrSeasonNumber;
}
}
}
if (!string.IsNullOrEmpty(historyEpisode.downloadDirPath)){
selected.DownloadPath = historyEpisode.downloadDirPath;
}
}
selected.DownloadSubs = CrunchyrollManager.Instance.CrunOptions.DlSubs;
Queue.Add(selected);
if (selected.Data.Count < dubLang.Count){
Console.WriteLine("Added Episode to Queue but couldn't find all selected dubs");
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue but couldn't find all selected dubs", ToastType.Warning, 2));
} else{
Console.WriteLine("Added Episode to Queue");
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue", ToastType.Information, 1));
}
} else{
Console.WriteLine("Episode couldn't be added to Queue");
MessageBus.Current.SendMessage(new ToastMessage($"Couldn't add episode to the queue with current dub settings", ToastType.Error, 2));
}
}
}
public async Task CRAddSeriesToQueue(CrunchySeriesList list, CrunchyMultiDownload data){
var selected = CrunchyrollManager.Instance.CrSeries.ItemSelectMultiDub(list.Data, data.DubLang, data.But, data.AllEpisodes, data.E);
bool failed = false;
foreach (var crunchyEpMeta in selected.Values.ToList()){
if (crunchyEpMeta.Data?.First().Playback != null){
if (CrunchyrollManager.Instance.CrunOptions.History){
var historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDownloadDir(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId, crunchyEpMeta.Data.First().MediaId);
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){
if (historyEpisode.historyEpisode != null){
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrEpisodeNumber)){
crunchyEpMeta.EpisodeNumber = historyEpisode.historyEpisode.SonarrEpisodeNumber;
}
if (!string.IsNullOrEmpty(historyEpisode.historyEpisode.SonarrSeasonNumber)){
crunchyEpMeta.Season = historyEpisode.historyEpisode.SonarrSeasonNumber;
}
}
}
if (!string.IsNullOrEmpty(historyEpisode.downloadDirPath)){
crunchyEpMeta.DownloadPath = historyEpisode.downloadDirPath;
}
}
if (CrunchyrollManager.Instance.CrunOptions.IncludeVideoDescription){
if (crunchyEpMeta.Data is{ Count: > 0 }){
var episode = await CrunchyrollManager.Instance.CrEpisode.ParseEpisodeById(crunchyEpMeta.Data.First().MediaId,
string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.DescriptionLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.DescriptionLang, true);
crunchyEpMeta.Description = episode?.Description ?? crunchyEpMeta.Description;
}
}
crunchyEpMeta.DownloadSubs = CrunchyrollManager.Instance.CrunOptions.DlSubs;
Queue.Add(crunchyEpMeta);
} else{
failed = true;
}
}
if (failed){
MainWindow.Instance.ShowError("Not all episodes could be added make sure that you are signed in with an account that has an active premium subscription?");
} else{
MessageBus.Current.SendMessage(new ToastMessage($"Added episodes to the queue", ToastType.Information, 1));
}
}
}

View File

@ -4,6 +4,7 @@ using System.IO;
using System.IO.Compression;
using System.Reflection;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs;
using Newtonsoft.Json;
using YamlDotNet.Core;
@ -139,7 +140,7 @@ public class CfgManager{
}
}
var yaml = serializer.Serialize(Crunchyroll.Instance.CrunOptions);
var yaml = serializer.Serialize(CrunchyrollManager.Instance.CrunOptions);
// Write to file
File.WriteAllText(PathCrDownloadOptions, yaml);
@ -173,7 +174,7 @@ public class CfgManager{
var propertiesPresentInYaml = GetTopLevelPropertiesInYaml(input);
var loadedOptions = deserializer.Deserialize<CrDownloadOptions>(new StringReader(input));
var instanceOptions = Crunchyroll.Instance.CrunOptions;
var instanceOptions = CrunchyrollManager.Instance.CrunOptions;
foreach (PropertyInfo property in typeof(CrDownloadOptions).GetProperties()){
var yamlMemberAttribute = property.GetCustomAttribute<YamlMemberAttribute>();
@ -207,7 +208,7 @@ public class CfgManager{
}
public static void UpdateHistoryFile(){
WriteJsonToFile(PathCrHistory, Crunchyroll.Instance.HistoryList);
WriteJsonToFile(PathCrHistory, CrunchyrollManager.Instance.HistoryList);
}
private static object fileLock = new object();

View File

@ -266,15 +266,15 @@ public class HlsDownloader{
Doing = _isAudio ? "Downloading Audio" : (_isVideo ? "Downloading Video" : "")
};
if (!Crunchyroll.Instance.Queue.Contains(_currentEpMeta)){
if (!QueueManager.Instance.Queue.Contains(_currentEpMeta)){
return (Ok: false, _data.Parts);
}
Crunchyroll.Instance.Queue.Refresh();
QueueManager.Instance.Queue.Refresh();
while (_currentEpMeta.Paused){
await Task.Delay(500);
if (!Crunchyroll.Instance.Queue.Contains(_currentEpMeta)){
if (!QueueManager.Instance.Queue.Contains(_currentEpMeta)){
return (Ok: false, _data.Parts);
}
}

View File

@ -1,4 +1,5 @@
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
namespace CRD.Utils.HLS;
@ -31,11 +32,11 @@ public class GlobalThrottler{
public void Throttle(int bytesRead){
if (Crunchyroll.Instance.CrunOptions.DownloadSpeedLimit == 0) return;
if (CrunchyrollManager.Instance.CrunOptions.DownloadSpeedLimit == 0) return;
lock (_lock){
_totalBytesRead += bytesRead;
if (_totalBytesRead >= ((Crunchyroll.Instance.CrunOptions.DownloadSpeedLimit * 1024) / 10)){
if (_totalBytesRead >= ((CrunchyrollManager.Instance.CrunOptions.DownloadSpeedLimit * 1024) / 10)){
var timeElapsed = DateTime.Now - _lastReadTime;
if (timeElapsed.TotalMilliseconds < 100){
Thread.Sleep(100 - (int)timeElapsed.TotalMilliseconds);
@ -77,8 +78,8 @@ public class ThrottledStream : Stream{
public override int Read(byte[] buffer, int offset, int count){
int bytesRead = 0;
if (Crunchyroll.Instance.CrunOptions.DownloadSpeedLimit != 0){
int bytesToRead = Math.Min(count, (Crunchyroll.Instance.CrunOptions.DownloadSpeedLimit * 1024) / 10);
if (CrunchyrollManager.Instance.CrunOptions.DownloadSpeedLimit != 0){
int bytesToRead = Math.Min(count, (CrunchyrollManager.Instance.CrunOptions.DownloadSpeedLimit * 1024) / 10);
bytesRead = _baseStream.Read(buffer, offset, bytesToRead);
_throttler.Throttle(bytesRead);
} else{

View File

@ -6,6 +6,7 @@ using System.Collections.Specialized;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
namespace CRD.Utils;
@ -93,7 +94,7 @@ public class HttpClientReq{
var request = new HttpRequestMessage(requestMethod, uriBuilder.ToString());
if (authHeader){
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Crunchyroll.Instance.Token?.access_token);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", CrunchyrollManager.Instance.Token?.access_token);
}
if (disableDrmHeader){

View File

@ -135,7 +135,7 @@ public class SyncingHelper{
public static bool AreFramesSimilar(string imagePath1, string imagePath2, double ssimThreshold){
double ssim = ComputeSSIM(imagePath1, imagePath2, 256, 256);
Console.WriteLine($"SSIM: {ssim}");
// Console.WriteLine($"SSIM: {ssim}");
return ssim > ssimThreshold;
}

View File

@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Sonarr.Models;
using CRD.Views;
using Newtonsoft.Json;
@ -22,6 +23,8 @@ public class SonarrClient{
private SonarrProperties properties;
public List<SonarrSeries> SonarrSeries =[];
#region Singelton
private static SonarrClient? _instance;
@ -47,8 +50,16 @@ public class SonarrClient{
httpClient = new HttpClient();
}
public async void RefreshSonarr(){
await CheckSonarrSettings();
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
SonarrSeries = await GetSeries();
CrunchyrollManager.Instance.History.MatchHistorySeriesWithSonarr(true);
}
}
public void SetApiUrl(){
if (Crunchyroll.Instance.CrunOptions.SonarrProperties != null) properties = Crunchyroll.Instance.CrunOptions.SonarrProperties;
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null) properties = CrunchyrollManager.Instance.CrunOptions.SonarrProperties;
if (properties != null ){
apiUrl = $"http{(properties.UseSsl ? "s" : "")}://{(!string.IsNullOrEmpty(properties.Host) ? properties.Host : "localhost")}:{properties.Port}{(properties.UrlBase ?? "")}/api";
@ -59,10 +70,10 @@ public class SonarrClient{
SetApiUrl();
if (Crunchyroll.Instance.CrunOptions.SonarrProperties != null){
Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false;
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false;
} else{
Crunchyroll.Instance.CrunOptions.SonarrProperties = new SonarrProperties(){SonarrEnabled = false};
CrunchyrollManager.Instance.CrunOptions.SonarrProperties = new SonarrProperties(){SonarrEnabled = false};
return;
}
@ -74,10 +85,10 @@ public class SonarrClient{
try{
response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
if (Crunchyroll.Instance.CrunOptions.SonarrProperties != null) Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled = true;
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null) CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled = true;
} catch (Exception ex){
Debug.WriteLine($"[ERROR] [SonarrClient.GetJson] Endpoint URL: '{apiUrl}', {ex}");
if (Crunchyroll.Instance.CrunOptions.SonarrProperties != null) Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false;
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null) CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false;
}

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
namespace CRD.Utils.Structs;
@ -47,7 +48,7 @@ public partial class CalendarEpisode : INotifyPropertyChanged{
if (match.Success){
var locale = match.Groups[1].Value; // Capture the locale part
var id = match.Groups[2].Value; // Capture the ID part
Crunchyroll.Instance.AddEpisodeToQue(id, Languages.Locale2language(locale).CrLocale, Crunchyroll.Instance.CrunOptions.DubLang,true);
QueueManager.Instance.CRAddEpisodeToQue(id, Languages.Locale2language(locale).CrLocale, CrunchyrollManager.Instance.CrunOptions.DubLang,true);
}
}

View File

@ -1,6 +1,7 @@
using System.ComponentModel;
using System.Threading.Tasks;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using Newtonsoft.Json;
namespace CRD.Utils.Structs.History;
@ -66,7 +67,7 @@ public class HistoryEpisode : INotifyPropertyChanged{
}
public async Task DownloadEpisode(){
await Crunchyroll.Instance.AddEpisodeToQue(EpisodeId, string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang,
Crunchyroll.Instance.CrunOptions.DubLang);
await QueueManager.Instance.CRAddEpisodeToQue(EpisodeId, string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang,
CrunchyrollManager.Instance.CrunOptions.DubLang);
}
}

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.CustomList;
using Newtonsoft.Json;
@ -243,10 +244,10 @@ public class HistorySeries : INotifyPropertyChanged{
public async Task FetchData(string? seasonId){
FetchingData = true;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FetchingData)));
await Crunchyroll.Instance.CrHistory.UpdateSeries(SeriesId, seasonId);
await CrunchyrollManager.Instance.History.CRUpdateSeries(SeriesId, seasonId);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesTitle)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesDescription)));
Crunchyroll.Instance.CrHistory.MatchHistoryEpisodesWithSonarr(false, this);
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, this);
UpdateNewEpisodes();
FetchingData = false;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FetchingData)));
@ -262,7 +263,7 @@ public class HistorySeries : INotifyPropertyChanged{
}
public void OpenSonarrPage(){
var sonarrProp = Crunchyroll.Instance.CrunOptions.SonarrProperties;
var sonarrProp = CrunchyrollManager.Instance.CrunOptions.SonarrProperties;
if (sonarrProp == null) return;

View File

@ -2,6 +2,7 @@
using System.Globalization;
using Avalonia.Data.Converters;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using FluentAvalonia.UI.Controls;
namespace CRD.Utils.UI;
@ -9,7 +10,7 @@ namespace CRD.Utils.UI;
public class UiSonarrIdToVisibilityConverter : IValueConverter{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture){
if (value is string stringValue){
return Crunchyroll.Instance.CrunOptions.SonarrProperties != null && (stringValue.Length > 0 && Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled);
return CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null && (stringValue.Length > 0 && CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled);
}
return false;

View File

@ -7,6 +7,7 @@ using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs;
using CRD.Views.Utils;
using FluentAvalonia.UI.Controls;
@ -45,28 +46,28 @@ public partial class AccountPageViewModel : ViewModelBase{
}
public void UpdatetProfile(){
ProfileName = Crunchyroll.Instance.Profile.Username; // Default or fetched user name
LoginLogoutText = Crunchyroll.Instance.Profile.Username == "???" ? "Login" : "Logout"; // Default state
LoadProfileImage("https://static.crunchyroll.com/assets/avatar/170x170/" + Crunchyroll.Instance.Profile.Avatar);
ProfileName = CrunchyrollManager.Instance.Profile.Username; // Default or fetched user name
LoginLogoutText = CrunchyrollManager.Instance.Profile.Username == "???" ? "Login" : "Logout"; // Default state
LoadProfileImage("https://static.crunchyroll.com/assets/avatar/170x170/" + CrunchyrollManager.Instance.Profile.Avatar);
if (Crunchyroll.Instance.Profile.Subscription != null && Crunchyroll.Instance.Profile.Subscription?.SubscriptionProducts != null){
if (Crunchyroll.Instance.Profile.Subscription?.SubscriptionProducts.Count >= 1){
var sub = Crunchyroll.Instance.Profile.Subscription?.SubscriptionProducts.First();
if (CrunchyrollManager.Instance.Profile.Subscription != null && CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts != null){
if (CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.Count >= 1){
var sub = CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.First();
if (sub != null){
IsCancelled = sub.IsCancelled;
}
}else if (Crunchyroll.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.Count >= 1){
var sub = Crunchyroll.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.First();
}else if (CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.Count >= 1){
var sub = CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.First();
if (sub != null){
IsCancelled = !sub.AutoRenew;
}
}else if(Crunchyroll.Instance.Profile.Subscription?.NonrecurringSubscriptionProducts.Count >= 1){
}else if(CrunchyrollManager.Instance.Profile.Subscription?.NonrecurringSubscriptionProducts.Count >= 1){
IsCancelled = true;
}
if (Crunchyroll.Instance.Profile.Subscription?.NextRenewalDate != null){
_targetTime = Crunchyroll.Instance.Profile.Subscription.NextRenewalDate;
if (CrunchyrollManager.Instance.Profile.Subscription?.NextRenewalDate != null){
_targetTime = CrunchyrollManager.Instance.Profile.Subscription.NextRenewalDate;
_timer = new DispatcherTimer{
Interval = TimeSpan.FromSeconds(1)
};
@ -100,7 +101,7 @@ public partial class AccountPageViewModel : ViewModelBase{
_ = await dialog.ShowAsync();
} else{
await Crunchyroll.Instance.CrAuth.AuthAnonymous();
await CrunchyrollManager.Instance.CrAuth.AuthAnonymous();
UpdatetProfile();
}
}

View File

@ -13,6 +13,7 @@ using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Structs;
using CRD.Views;
@ -75,7 +76,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
}
private async Task UpdateSearch(string value){
var searchResults = await Crunchyroll.Instance.CrSeries.Search(value, Crunchyroll.Instance.CrunOptions.HistoryLang);
var searchResults = await CrunchyrollManager.Instance.CrSeries.Search(value, CrunchyrollManager.Instance.CrunOptions.HistoryLang);
var searchItems = searchResults?.Data?.First().Items;
SearchItems.Clear();
@ -157,7 +158,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
}
if (currentSeriesList != null){
await Crunchyroll.Instance.AddSeriesToQueue(currentSeriesList.Value, new CrunchyMultiDownload(Crunchyroll.Instance.CrunOptions.DubLang, AddAllEpisodes, false, selectedEpisodes));
await QueueManager.Instance.CRAddSeriesToQueue(currentSeriesList.Value, new CrunchyMultiDownload(CrunchyrollManager.Instance.CrunOptions.DubLang, AddAllEpisodes, false, selectedEpisodes));
}
@ -186,10 +187,10 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
if (match.Success){
var locale = match.Groups[1].Value; // Capture the locale part
var id = match.Groups[2].Value; // Capture the ID part
Crunchyroll.Instance.AddEpisodeToQue(id,
QueueManager.Instance.CRAddEpisodeToQue(id,
string.IsNullOrEmpty(locale)
? string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, Crunchyroll.Instance.CrunOptions.DubLang, true);
? string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, CrunchyrollManager.Instance.CrunOptions.DubLang, true);
UrlInput = "";
selectedEpisodes.Clear();
SelectedItems.Clear();
@ -212,9 +213,9 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
ButtonEnabled = false;
ShowLoading = true;
var list = await Crunchyroll.Instance.CrSeries.ListSeriesId(id, string.IsNullOrEmpty(locale)
? string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, new CrunchyMultiDownload(Crunchyroll.Instance.CrunOptions.DubLang, true));
var list = await CrunchyrollManager.Instance.CrSeries.ListSeriesId(id, string.IsNullOrEmpty(locale)
? string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, new CrunchyMultiDownload(CrunchyrollManager.Instance.CrunOptions.DubLang, true));
ShowLoading = false;
if (list != null){
currentSeriesList = list;
@ -291,9 +292,9 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
SearchVisible = false;
ButtonEnabled = false;
ShowLoading = true;
var list = await Crunchyroll.Instance.CrSeries.ListSeriesId(value.Id,
string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang,
new CrunchyMultiDownload(Crunchyroll.Instance.CrunOptions.DubLang, true));
var list = await CrunchyrollManager.Instance.CrSeries.ListSeriesId(value.Id,
string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang,
new CrunchyMultiDownload(CrunchyrollManager.Instance.CrunOptions.DubLang, true));
ShowLoading = false;
if (list != null){
currentSeriesList = list;

View File

@ -6,6 +6,7 @@ using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Structs;
using DynamicData;
@ -63,14 +64,14 @@ public partial class CalendarPageViewModel : ViewModelBase{
CalendarDubFilter.Add(new ComboBoxItem{ Content = languageItem.CrLocale });
}
CustomCalendar = Crunchyroll.Instance.CrunOptions.CustomCalendar;
HideDubs = Crunchyroll.Instance.CrunOptions.CalendarHideDubs;
FilterByAirDate = Crunchyroll.Instance.CrunOptions.CalendarFilterByAirDate;
CustomCalendar = CrunchyrollManager.Instance.CrunOptions.CustomCalendar;
HideDubs = CrunchyrollManager.Instance.CrunOptions.CalendarHideDubs;
FilterByAirDate = CrunchyrollManager.Instance.CrunOptions.CalendarFilterByAirDate;
ComboBoxItem? dubfilter = CalendarDubFilter.FirstOrDefault(a => a.Content != null && (string)a.Content == Crunchyroll.Instance.CrunOptions.CalendarDubFilter) ?? null;
ComboBoxItem? dubfilter = CalendarDubFilter.FirstOrDefault(a => a.Content != null && (string)a.Content == CrunchyrollManager.Instance.CrunOptions.CalendarDubFilter) ?? null;
CurrentCalendarDubFilter = dubfilter ?? CalendarDubFilter[0];
CurrentCalendarLanguage = CalendarLanguage.FirstOrDefault(a => a.Content != null && (string)a.Content == Crunchyroll.Instance.CrunOptions.SelectedCalendarLanguage) ?? CalendarLanguage[0];
CurrentCalendarLanguage = CalendarLanguage.FirstOrDefault(a => a.Content != null && (string)a.Content == CrunchyrollManager.Instance.CrunOptions.SelectedCalendarLanguage) ?? CalendarLanguage[0];
loading = false;
LoadCalendar(GetThisWeeksMondayDate(), false);
}
@ -98,16 +99,18 @@ public partial class CalendarPageViewModel : ViewModelBase{
}
public async void LoadCalendar(string mondayDate, bool forceUpdate){
if (CustomCalendar){
BuildCustomCalendar();
return;
}
ShowLoading = true;
CalendarWeek week = await Crunchyroll.Instance.GetCalendarForDate(mondayDate, forceUpdate);
if (currentWeek != null && currentWeek == week){
ShowLoading = false;
return;
CalendarWeek week;
if (CustomCalendar){
week = await CalendarManager.Instance.BuildCustomCalendar(forceUpdate);
} else{
week = await CalendarManager.Instance.GetCalendarForDate(mondayDate, forceUpdate);
if (currentWeek != null && currentWeek == week){
ShowLoading = false;
return;
}
}
currentWeek = week;
@ -115,17 +118,26 @@ public partial class CalendarPageViewModel : ViewModelBase{
CalendarDays.AddRange(week.CalendarDays);
RaisePropertyChanged(nameof(CalendarDays));
ShowLoading = false;
foreach (var calendarDay in CalendarDays){
var episodesCopy = new List<CalendarEpisode>(calendarDay.CalendarEpisodes);
foreach (var calendarDayCalendarEpisode in episodesCopy){
if (calendarDayCalendarEpisode.SeasonName != null && HideDubs && calendarDayCalendarEpisode.SeasonName.EndsWith("Dub)")){
calendarDay.CalendarEpisodes.Remove(calendarDayCalendarEpisode);
continue;
if (CustomCalendar){
foreach (var calendarDay in CalendarDays){
foreach (var calendarDayCalendarEpisode in calendarDay.CalendarEpisodes){
if (calendarDayCalendarEpisode.ImageBitmap == null){
calendarDayCalendarEpisode.LoadImage();
}
}
}
} else{
foreach (var calendarDay in CalendarDays){
var episodesCopy = new List<CalendarEpisode>(calendarDay.CalendarEpisodes);
foreach (var calendarDayCalendarEpisode in episodesCopy){
if (calendarDayCalendarEpisode.SeasonName != null && HideDubs && calendarDayCalendarEpisode.SeasonName.EndsWith("Dub)")){
calendarDay.CalendarEpisodes.Remove(calendarDayCalendarEpisode);
continue;
}
if (calendarDayCalendarEpisode.ImageBitmap == null){
calendarDayCalendarEpisode.LoadImage();
if (calendarDayCalendarEpisode.ImageBitmap == null){
calendarDayCalendarEpisode.LoadImage();
}
}
}
}
@ -148,11 +160,6 @@ public partial class CalendarPageViewModel : ViewModelBase{
return;
}
if (CustomCalendar){
BuildCustomCalendar();
return;
}
string mondayDate;
if (currentWeek is{ FirstDayOfWeekString: not null }){
@ -205,7 +212,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
}
if (value?.Content != null){
Crunchyroll.Instance.CrunOptions.SelectedCalendarLanguage = value.Content.ToString();
CrunchyrollManager.Instance.CrunOptions.SelectedCalendarLanguage = value.Content.ToString();
Refresh();
CfgManager.WriteSettingsToFile();
}
@ -216,13 +223,10 @@ public partial class CalendarPageViewModel : ViewModelBase{
return;
}
if (CustomCalendar){
BuildCustomCalendar();
} else{
LoadCalendar(GetThisWeeksMondayDate(), true);
}
CrunchyrollManager.Instance.CrunOptions.CustomCalendar = value;
Crunchyroll.Instance.CrunOptions.CustomCalendar = value;
LoadCalendar(GetThisWeeksMondayDate(), true);
CfgManager.WriteSettingsToFile();
}
@ -231,16 +235,16 @@ public partial class CalendarPageViewModel : ViewModelBase{
return;
}
Crunchyroll.Instance.CrunOptions.CalendarHideDubs = value;
CrunchyrollManager.Instance.CrunOptions.CalendarHideDubs = value;
CfgManager.WriteSettingsToFile();
}
partial void OnFilterByAirDateChanged(bool value){
if (loading){
return;
}
Crunchyroll.Instance.CrunOptions.CalendarFilterByAirDate = value;
CrunchyrollManager.Instance.CrunOptions.CalendarFilterByAirDate = value;
CfgManager.WriteSettingsToFile();
}
@ -250,89 +254,8 @@ public partial class CalendarPageViewModel : ViewModelBase{
}
if (!string.IsNullOrEmpty(value?.Content + "")){
Crunchyroll.Instance.CrunOptions.CalendarDubFilter = value?.Content + "";
CrunchyrollManager.Instance.CrunOptions.CalendarDubFilter = value?.Content + "";
CfgManager.WriteSettingsToFile();
}
}
private async void BuildCustomCalendar(){
ShowLoading = true;
var newEpisodesBase = await Crunchyroll.Instance.CrEpisode.GetNewEpisodes(Crunchyroll.Instance.CrunOptions.HistoryLang, 200,true);
CalendarWeek week = new CalendarWeek();
week.CalendarDays = new List<CalendarDay>();
DateTime today = DateTime.Now;
for (int i = 0; i < 7; i++){
CalendarDay calDay = new CalendarDay();
calDay.CalendarEpisodes = new List<CalendarEpisode>();
calDay.DateTime = today.AddDays(-i);
calDay.DayName = calDay.DateTime.Value.DayOfWeek.ToString();
week.CalendarDays.Add(calDay);
}
week.CalendarDays.Reverse();
if (newEpisodesBase is{ Data.Count: > 0 }){
var newEpisodes = newEpisodesBase.Data;
foreach (var crBrowseEpisode in newEpisodes){
var targetDate = FilterByAirDate ? crBrowseEpisode.EpisodeMetadata.EpisodeAirDate : crBrowseEpisode.LastPublic;
if (HideDubs && crBrowseEpisode.EpisodeMetadata.SeasonTitle != null && (crBrowseEpisode.EpisodeMetadata.SeasonTitle.EndsWith("Dub)") || crBrowseEpisode.EpisodeMetadata.AudioLocale != Locale.JaJp)){
continue;
}
var dubFilter = CurrentCalendarDubFilter?.Content + "";
if (!string.IsNullOrEmpty(dubFilter) && dubFilter != "none"){
if (crBrowseEpisode.EpisodeMetadata.AudioLocale != null && crBrowseEpisode.EpisodeMetadata.AudioLocale.GetEnumMemberValue() != dubFilter){
continue;
}
}
var calendarDay = (from day in week.CalendarDays
where day.DateTime.HasValue && day.DateTime.Value.Date == targetDate.Date
select day).FirstOrDefault();
if (calendarDay != null){
CalendarEpisode calEpisode = new CalendarEpisode();
calEpisode.DateTime = targetDate;
calEpisode.HasPassed = DateTime.Now > targetDate;
calEpisode.EpisodeName = crBrowseEpisode.Title;
calEpisode.SeriesUrl = $"https://www.crunchyroll.com/{Crunchyroll.Instance.CrunOptions.HistoryLang}/series/" + crBrowseEpisode.EpisodeMetadata.SeriesId;
calEpisode.EpisodeUrl = $"https://www.crunchyroll.com/{Crunchyroll.Instance.CrunOptions.HistoryLang}/watch/{crBrowseEpisode.Id}/";
calEpisode.ThumbnailUrl = crBrowseEpisode.Images.Thumbnail.First().First().Source;
calEpisode.IsPremiumOnly = crBrowseEpisode.EpisodeMetadata.IsPremiumOnly;
calEpisode.IsPremiere = crBrowseEpisode.EpisodeMetadata.Episode == "1";
calEpisode.SeasonName = crBrowseEpisode.EpisodeMetadata.SeasonTitle;
calEpisode.EpisodeNumber = crBrowseEpisode.EpisodeMetadata.Episode;
calendarDay.CalendarEpisodes?.Add(calEpisode);
}
}
}
foreach (var day in week.CalendarDays){
if (day.CalendarEpisodes != null) day.CalendarEpisodes = day.CalendarEpisodes.OrderBy(e => e.DateTime).ToList();
}
currentWeek = week;
CalendarDays.Clear();
CalendarDays.AddRange(week.CalendarDays);
RaisePropertyChanged(nameof(CalendarDays));
ShowLoading = false;
foreach (var calendarDay in CalendarDays){
foreach (var calendarDayCalendarEpisode in calendarDay.CalendarEpisodes){
if (calendarDayCalendarEpisode.ImageBitmap == null){
calendarDayCalendarEpisode.LoadImage();
}
}
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Structs;
using FluentAvalonia.UI.Controls;
@ -31,7 +32,7 @@ public partial class ContentDialogInputLoginViewModel : ViewModelBase{
private async void LoginButton(ContentDialog sender, ContentDialogButtonClickEventArgs args){
dialog.PrimaryButtonClick -= LoginButton;
await Crunchyroll.Instance.CrAuth.Auth(new AuthData{Password = Password,Username = Email});
await CrunchyrollManager.Instance.CrAuth.Auth(new AuthData{Password = Password,Username = Email});
accountPageViewModel.UpdatetProfile();
}

View File

@ -8,6 +8,7 @@ using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs;
namespace CRD.ViewModels;
@ -20,25 +21,24 @@ public partial class DownloadsPageViewModel : ViewModelBase{
[ObservableProperty]
public bool _removeFinished;
public DownloadsPageViewModel(){
Crunchyroll.Instance.UpdateDownloadListItems();
Items = Crunchyroll.Instance.DownloadItemModels;
AutoDownload = Crunchyroll.Instance.CrunOptions.AutoDownload;
RemoveFinished = Crunchyroll.Instance.CrunOptions.RemoveFinishedDownload;
QueueManager.Instance.UpdateDownloadListItems();
Items = QueueManager.Instance.DownloadItemModels;
AutoDownload = CrunchyrollManager.Instance.CrunOptions.AutoDownload;
RemoveFinished = CrunchyrollManager.Instance.CrunOptions.RemoveFinishedDownload;
}
partial void OnAutoDownloadChanged(bool value){
Crunchyroll.Instance.CrunOptions.AutoDownload = value;
CrunchyrollManager.Instance.CrunOptions.AutoDownload = value;
if (value){
Crunchyroll.Instance.UpdateDownloadListItems();
QueueManager.Instance.UpdateDownloadListItems();
}
}
partial void OnRemoveFinishedChanged(bool value){
Crunchyroll.Instance.CrunOptions.RemoveFinishedDownload = value;
CrunchyrollManager.Instance.CrunOptions.RemoveFinishedDownload = value;
}
}
public partial class DownloadItemModel : INotifyPropertyChanged{
@ -81,11 +81,6 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
}
private string GetDubString(){
var hardSubs = Crunchyroll.Instance.CrunOptions.Hslang != "none" ? "Hardsub: " + Crunchyroll.Instance.CrunOptions.Hslang : "";
if (hardSubs != string.Empty){
return hardSubs;
}
var dubs = "Dub: ";
if (epMeta.SelectedDubs != null)
@ -97,8 +92,13 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
}
private string GetSubtitleString(){
var hardSubs = Crunchyroll.Instance.CrunOptions.Hslang != "none" ? "Hardsub: " + Crunchyroll.Instance.CrunOptions.Hslang : "";
var hardSubs = CrunchyrollManager.Instance.CrunOptions.Hslang != "none" ? "Hardsub: " : "";
if (hardSubs != string.Empty){
var locale = Languages.Locale2language(CrunchyrollManager.Instance.CrunOptions.Hslang).CrLocale;
if (epMeta.AvailableSubs != null && epMeta.AvailableSubs.Contains(locale)){
hardSubs += locale + " ";
}
return hardSubs;
}
@ -181,15 +181,15 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
epMeta.DownloadProgress.IsDownloading = true;
Paused = !epMeta.Paused && !isDownloading || epMeta.Paused;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Paused)));
await Crunchyroll.Instance.DownloadEpisode(epMeta, Crunchyroll.Instance.CrunOptions);
await CrunchyrollManager.Instance.DownloadEpisode(epMeta, CrunchyrollManager.Instance.CrunOptions);
}
}
[RelayCommand]
public void RemoveFromQueue(){
CrunchyEpMeta? downloadItem = Crunchyroll.Instance.Queue.FirstOrDefault(e => e.Equals(epMeta)) ?? null;
CrunchyEpMeta? downloadItem = QueueManager.Instance.Queue.FirstOrDefault(e => e.Equals(epMeta)) ?? null;
if (downloadItem != null){
Crunchyroll.Instance.Queue.Remove(downloadItem);
QueueManager.Instance.Queue.Remove(downloadItem);
}
}

View File

@ -12,6 +12,7 @@ using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Structs;
using CRD.Utils.Structs.History;
@ -86,9 +87,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
public static bool _sortDir = false;
public HistoryPageViewModel(){
Items = Crunchyroll.Instance.HistoryList;
Items = CrunchyrollManager.Instance.HistoryList;
HistoryPageProperties? properties = Crunchyroll.Instance.CrunOptions.HistoryPageProperties;
HistoryPageProperties? properties = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties;
currentViewType = properties?.SelectedView ?? HistoryViewType.Posters;
currentSortingType = properties?.SelectedSorting ?? SortingType.SeriesTitle;
@ -123,17 +124,17 @@ public partial class HistoryPageViewModel : ViewModelBase{
historySeries.UpdateNewEpisodes();
}
Crunchyroll.Instance.CrHistory.SortItems();
CrunchyrollManager.Instance.History.SortItems();
}
private void UpdateSettings(){
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null){
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue;
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType;
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue;
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType;
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
} else{
Crunchyroll.Instance.CrunOptions.HistoryPageProperties = new HistoryPageProperties(){ ScaleValue = ScaleValue, SelectedView = currentViewType, SelectedSorting = currentSortingType };
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties = new HistoryPageProperties(){ ScaleValue = ScaleValue, SelectedView = currentViewType, SelectedSorting = currentSortingType };
}
CfgManager.WriteSettingsToFile();
@ -155,9 +156,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
partial void OnSelectedSortingChanged(SortingListElement? oldValue, SortingListElement? newValue){
if (newValue == null){
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null){
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending = !Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending;
SortDir = Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending;
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending = !CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
SortDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
}
Dispatcher.UIThread.InvokeAsync(() => {
@ -169,8 +170,8 @@ public partial class HistoryPageViewModel : ViewModelBase{
if (newValue.SelectedSorting != null){
currentSortingType = newValue.SelectedSorting;
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null) Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
Crunchyroll.Instance.CrHistory.SortItems();
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null) CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
CrunchyrollManager.Instance.History.SortItems();
} else{
Console.Error.WriteLine("Invalid viewtype selected");
}
@ -211,12 +212,12 @@ public partial class HistoryPageViewModel : ViewModelBase{
partial void OnSelectedSeriesChanged(HistorySeries value){
Crunchyroll.Instance.SelectedSeries = value;
CrunchyrollManager.Instance.SelectedSeries = value;
NavToSeries();
if (!string.IsNullOrEmpty(value.SonarrSeriesId) && Crunchyroll.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
Crunchyroll.Instance.CrHistory.MatchHistoryEpisodesWithSonarr(true, SelectedSeries);
if (!string.IsNullOrEmpty(value.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(true, SelectedSeries);
}
@ -225,9 +226,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
[RelayCommand]
public void RemoveSeries(string? seriesId){
HistorySeries? objectToRemove = Crunchyroll.Instance.HistoryList.ToList().Find(se => se.SeriesId == seriesId) ?? null;
HistorySeries? objectToRemove = CrunchyrollManager.Instance.HistoryList.ToList().Find(se => se.SeriesId == seriesId) ?? null;
if (objectToRemove != null){
Crunchyroll.Instance.HistoryList.Remove(objectToRemove);
CrunchyrollManager.Instance.HistoryList.Remove(objectToRemove);
Items.Remove(objectToRemove);
CfgManager.UpdateHistoryFile();
}
@ -260,7 +261,7 @@ public partial class HistoryPageViewModel : ViewModelBase{
FetchingData = false;
RaisePropertyChanged(nameof(FetchingData));
Crunchyroll.Instance.CrHistory.SortItems();
CrunchyrollManager.Instance.History.SortItems();
}
[RelayCommand]

View File

@ -8,6 +8,7 @@ using Avalonia.Media;
using Avalonia.Styling;
using CommunityToolkit.Mvvm.ComponentModel;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Updater;
using FluentAvalonia.Styling;
using Newtonsoft.Json;
@ -48,15 +49,15 @@ public partial class MainWindowViewModel : ViewModelBase{
public async void Init(){
UpdateAvailable = await Updater.Instance.CheckForUpdatesAsync();
Crunchyroll.Instance.InitOptions();
CrunchyrollManager.Instance.InitOptions();
if (Crunchyroll.Instance.CrunOptions.AccentColor != null){
_faTheme.CustomAccentColor = Color.Parse(Crunchyroll.Instance.CrunOptions.AccentColor);
if (CrunchyrollManager.Instance.CrunOptions.AccentColor != null){
_faTheme.CustomAccentColor = Color.Parse(CrunchyrollManager.Instance.CrunOptions.AccentColor);
}
if (Crunchyroll.Instance.CrunOptions.Theme == "System"){
if (CrunchyrollManager.Instance.CrunOptions.Theme == "System"){
_faTheme.PreferSystemTheme = true;
} else if (Crunchyroll.Instance.CrunOptions.Theme == "Dark"){
} else if (CrunchyrollManager.Instance.CrunOptions.Theme == "Dark"){
_faTheme.PreferSystemTheme = false;
Application.Current.RequestedThemeVariant = ThemeVariant.Dark;
} else{
@ -64,7 +65,7 @@ public partial class MainWindowViewModel : ViewModelBase{
Application.Current.RequestedThemeVariant = ThemeVariant.Light;
}
await Crunchyroll.Instance.Init();
await CrunchyrollManager.Instance.Init();
}
}

View File

@ -8,6 +8,7 @@ using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Sonarr;
using CRD.Utils.Structs;
@ -37,14 +38,14 @@ public partial class SeriesPageViewModel : ViewModelBase{
_selectedSeries = Crunchyroll.Instance.SelectedSeries;
_selectedSeries = CrunchyrollManager.Instance.SelectedSeries;
if (_selectedSeries.ThumbnailImage == null){
_selectedSeries.LoadImage();
}
if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId) && Crunchyroll.Instance.CrunOptions.SonarrProperties != null){
SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
} else{
SonarrAvailable = false;
}

View File

@ -15,6 +15,7 @@ using Avalonia.Styling;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.CustomList;
using CRD.Utils.Sonarr;
@ -327,7 +328,7 @@ public partial class SettingsPageViewModel : ViewModelBase{
DefaultSubLangList.Add(new ComboBoxItem{ Content = languageItem.CrLocale });
}
CrDownloadOptions options = Crunchyroll.Instance.CrunOptions;
CrDownloadOptions options = CrunchyrollManager.Instance.CrunOptions;
DownloadDirPath = string.IsNullOrEmpty(options.DownloadDirPath) ? CfgManager.PathVIDEOS_DIR : options.DownloadDirPath;
@ -337,7 +338,7 @@ public partial class SettingsPageViewModel : ViewModelBase{
ComboBoxItem? historyLang = HistoryLangList.FirstOrDefault(a => a.Content != null && (string)a.Content == options.HistoryLang) ?? null;
SelectedHistoryLang = historyLang ?? HistoryLangList[0];
ComboBoxItem? hsLang = HardSubLangList.FirstOrDefault(a => a.Content != null && (string)a.Content == options.Hslang) ?? null;
ComboBoxItem? hsLang = HardSubLangList.FirstOrDefault(a => a.Content != null && (string)a.Content == Languages.Locale2language(options.Hslang).CrLocale) ?? null;
SelectedHSLang = hsLang ?? HardSubLangList[0];
ComboBoxItem? defaultDubLang = DefaultDubLangList.FirstOrDefault(a => a.Content != null && (string)a.Content == (options.DefaultAudio ?? "")) ?? null;
@ -441,62 +442,62 @@ public partial class SettingsPageViewModel : ViewModelBase{
return;
}
Crunchyroll.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription;
Crunchyroll.Instance.CrunOptions.VideoTitle = FileTitle;
Crunchyroll.Instance.CrunOptions.Novids = !DownloadVideo;
Crunchyroll.Instance.CrunOptions.Noaudio = !DownloadAudio;
Crunchyroll.Instance.CrunOptions.DlVideoOnce = !DownloadVideoForEveryDub;
Crunchyroll.Instance.CrunOptions.Chapters = DownloadChapters;
Crunchyroll.Instance.CrunOptions.Mp4 = MuxToMp4;
Crunchyroll.Instance.CrunOptions.SyncTiming = SyncTimings;
Crunchyroll.Instance.CrunOptions.SkipSubsMux = SkipSubMux;
Crunchyroll.Instance.CrunOptions.Numbers = Math.Clamp((int)(LeadingNumbers ?? 0),0,10);
Crunchyroll.Instance.CrunOptions.FileName = FileName;
Crunchyroll.Instance.CrunOptions.IncludeSignsSubs = IncludeSignSubs;
Crunchyroll.Instance.CrunOptions.DownloadSpeedLimit = Math.Clamp((int)(DownloadSpeed ?? 0),0,1000000000);
Crunchyroll.Instance.CrunOptions.SimultaneousDownloads = Math.Clamp((int)(SimultaneousDownloads ?? 0),1,10);
CrunchyrollManager.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription;
CrunchyrollManager.Instance.CrunOptions.VideoTitle = FileTitle;
CrunchyrollManager.Instance.CrunOptions.Novids = !DownloadVideo;
CrunchyrollManager.Instance.CrunOptions.Noaudio = !DownloadAudio;
CrunchyrollManager.Instance.CrunOptions.DlVideoOnce = !DownloadVideoForEveryDub;
CrunchyrollManager.Instance.CrunOptions.Chapters = DownloadChapters;
CrunchyrollManager.Instance.CrunOptions.Mp4 = MuxToMp4;
CrunchyrollManager.Instance.CrunOptions.SyncTiming = SyncTimings;
CrunchyrollManager.Instance.CrunOptions.SkipSubsMux = SkipSubMux;
CrunchyrollManager.Instance.CrunOptions.Numbers = Math.Clamp((int)(LeadingNumbers ?? 0),0,10);
CrunchyrollManager.Instance.CrunOptions.FileName = FileName;
CrunchyrollManager.Instance.CrunOptions.IncludeSignsSubs = IncludeSignSubs;
CrunchyrollManager.Instance.CrunOptions.DownloadSpeedLimit = Math.Clamp((int)(DownloadSpeed ?? 0),0,1000000000);
CrunchyrollManager.Instance.CrunOptions.SimultaneousDownloads = Math.Clamp((int)(SimultaneousDownloads ?? 0),1,10);
Crunchyroll.Instance.CrunOptions.SubsAddScaledBorder = GetScaledBorderAndShadowSelection();
CrunchyrollManager.Instance.CrunOptions.SubsAddScaledBorder = GetScaledBorderAndShadowSelection();
List<string> softSubs = new List<string>();
foreach (var listBoxItem in SelectedSubLang){
softSubs.Add(listBoxItem.Content + "");
}
Crunchyroll.Instance.CrunOptions.DlSubs = softSubs;
CrunchyrollManager.Instance.CrunOptions.DlSubs = softSubs;
string descLang = SelectedDescriptionLang.Content + "";
Crunchyroll.Instance.CrunOptions.DescriptionLang = descLang != "default" ? descLang : Crunchyroll.Instance.DefaultLocale;
CrunchyrollManager.Instance.CrunOptions.DescriptionLang = descLang != "default" ? descLang : CrunchyrollManager.Instance.DefaultLocale;
string historyLang = SelectedHistoryLang.Content + "";
Crunchyroll.Instance.CrunOptions.HistoryLang = historyLang != "default" ? historyLang : Crunchyroll.Instance.DefaultLocale;
CrunchyrollManager.Instance.CrunOptions.HistoryLang = historyLang != "default" ? historyLang : CrunchyrollManager.Instance.DefaultLocale;
string hslang = SelectedHSLang.Content + "";
Crunchyroll.Instance.CrunOptions.Hslang = hslang != "none" ? Languages.FindLang(hslang).Locale : hslang;
CrunchyrollManager.Instance.CrunOptions.Hslang = hslang != "none" ? Languages.FindLang(hslang).Locale : hslang;
Crunchyroll.Instance.CrunOptions.DefaultAudio = SelectedDefaultDubLang.Content + "";
Crunchyroll.Instance.CrunOptions.DefaultSub = SelectedDefaultSubLang.Content + "";
CrunchyrollManager.Instance.CrunOptions.DefaultAudio = SelectedDefaultDubLang.Content + "";
CrunchyrollManager.Instance.CrunOptions.DefaultSub = SelectedDefaultSubLang.Content + "";
Crunchyroll.Instance.CrunOptions.StreamEndpoint = SelectedStreamEndpoint.Content + "";
CrunchyrollManager.Instance.CrunOptions.StreamEndpoint = SelectedStreamEndpoint.Content + "";
List<string> dubLangs = new List<string>();
foreach (var listBoxItem in SelectedDubLang){
dubLangs.Add(listBoxItem.Content + "");
}
Crunchyroll.Instance.CrunOptions.DubLang = dubLangs;
CrunchyrollManager.Instance.CrunOptions.DubLang = dubLangs;
Crunchyroll.Instance.CrunOptions.QualityAudio = SelectedAudioQuality?.Content + "";
Crunchyroll.Instance.CrunOptions.QualityVideo = SelectedVideoQuality?.Content + "";
Crunchyroll.Instance.CrunOptions.Theme = CurrentAppTheme?.Content + "";
CrunchyrollManager.Instance.CrunOptions.QualityAudio = SelectedAudioQuality?.Content + "";
CrunchyrollManager.Instance.CrunOptions.QualityVideo = SelectedVideoQuality?.Content + "";
CrunchyrollManager.Instance.CrunOptions.Theme = CurrentAppTheme?.Content + "";
Crunchyroll.Instance.CrunOptions.AccentColor = _faTheme.CustomAccentColor.ToString();
CrunchyrollManager.Instance.CrunOptions.AccentColor = _faTheme.CustomAccentColor.ToString();
Crunchyroll.Instance.CrunOptions.History = History;
CrunchyrollManager.Instance.CrunOptions.History = History;
var props = new SonarrProperties();
@ -513,23 +514,23 @@ public partial class SettingsPageViewModel : ViewModelBase{
props.ApiKey = SonarrApiKey;
Crunchyroll.Instance.CrunOptions.SonarrProperties = props;
CrunchyrollManager.Instance.CrunOptions.SonarrProperties = props;
Crunchyroll.Instance.CrunOptions.LogMode = LogMode;
CrunchyrollManager.Instance.CrunOptions.LogMode = LogMode;
List<string> mkvmergeParams = new List<string>();
foreach (var mkvmergeParam in MkvMergeOptions){
mkvmergeParams.Add(mkvmergeParam.ParamValue);
}
Crunchyroll.Instance.CrunOptions.MkvmergeOptions = mkvmergeParams;
CrunchyrollManager.Instance.CrunOptions.MkvmergeOptions = mkvmergeParams;
List<string> ffmpegParams = new List<string>();
foreach (var ffmpegParam in FfmpegOptions){
ffmpegParams.Add(ffmpegParam.ParamValue);
}
Crunchyroll.Instance.CrunOptions.FfmpegOptions = ffmpegParams;
CrunchyrollManager.Instance.CrunOptions.FfmpegOptions = ffmpegParams;
CfgManager.WriteSettingsToFile();
}
@ -604,8 +605,8 @@ public partial class SettingsPageViewModel : ViewModelBase{
var selectedFolder = result[0];
// Do something with the selected folder path
Console.WriteLine($"Selected folder: {selectedFolder.Path.LocalPath}");
Crunchyroll.Instance.CrunOptions.DownloadDirPath = selectedFolder.Path.LocalPath;
DownloadDirPath = string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.DownloadDirPath) ? CfgManager.PathVIDEOS_DIR : Crunchyroll.Instance.CrunOptions.DownloadDirPath;
CrunchyrollManager.Instance.CrunOptions.DownloadDirPath = selectedFolder.Path.LocalPath;
DownloadDirPath = string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.DownloadDirPath) ? CfgManager.PathVIDEOS_DIR : CrunchyrollManager.Instance.CrunOptions.DownloadDirPath;
CfgManager.WriteSettingsToFile();
}
}

View File

@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Sonarr;
using CRD.ViewModels;
@ -16,7 +17,7 @@ public partial class SettingsPageView : UserControl{
private void OnUnloaded(object? sender, RoutedEventArgs e){
if (DataContext is SettingsPageViewModel viewModel){
Crunchyroll.Instance.RefreshSonarr();
SonarrClient.Instance.RefreshSonarr();
}
}
}

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f7835908cf3cdbf8cdfb33b914d4eb28916359fe89132c72ca3728f4f6e1c00b
size 26332
oid sha256:e616fc7834bbcf6c56692a4e48edd61b24ab25bf0336fd48bf5f0068947d7812
size 30526