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

View File

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

View File

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

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -13,62 +11,27 @@ using System.Threading.Tasks;
using System.Xml; using System.Xml;
using Avalonia.Media; using Avalonia.Media;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.CustomList;
using CRD.Utils.DRM; using CRD.Utils.DRM;
using CRD.Utils.Files; using CRD.Utils.Files;
using CRD.Utils.HLS; using CRD.Utils.HLS;
using CRD.Utils.Muxing; using CRD.Utils.Muxing;
using CRD.Utils.Sonarr; using CRD.Utils.Sonarr;
using CRD.Utils.Sonarr.Models;
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 HtmlAgilityPack;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using ReactiveUI;
using LanguageItem = CRD.Utils.Structs.LanguageItem; using LanguageItem = CRD.Utils.Structs.LanguageItem;
namespace CRD.Downloader; namespace CRD.Downloader.Crunchyroll;
public class Crunchyroll{ public class CrunchyrollManager{
public CrToken? Token; public CrToken? Token;
public CrCmsToken? CmsToken; public CrCmsToken? CmsToken;
public CrProfile Profile = new(); public CrProfile Profile = new();
public CrDownloadOptions CrunOptions; 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 #region History Variables
public ObservableCollection<HistorySeries> HistoryList = new(); public ObservableCollection<HistorySeries> HistoryList = new();
@ -77,8 +40,6 @@ public class Crunchyroll{
Seasons =[] Seasons =[]
}; };
public List<SonarrSeries> SonarrSeries =[];
#endregion #endregion
@ -93,19 +54,19 @@ public class Crunchyroll{
public CrAuth CrAuth; public CrAuth CrAuth;
public CrEpisode CrEpisode; public CrEpisode CrEpisode;
public CrSeries CrSeries; public CrSeries CrSeries;
public History CrHistory; public History History;
#region Singelton #region Singelton
private static Crunchyroll? _instance; private static CrunchyrollManager? _instance;
private static readonly object Padlock = new(); private static readonly object Padlock = new();
public static Crunchyroll Instance{ public static CrunchyrollManager Instance{
get{ get{
if (_instance == null){ if (_instance == null){
lock (Padlock){ lock (Padlock){
if (_instance == null){ if (_instance == null){
_instance = new Crunchyroll(); _instance = new CrunchyrollManager();
} }
} }
} }
@ -116,9 +77,8 @@ public class Crunchyroll{
#endregion #endregion
public Crunchyroll(){ public CrunchyrollManager(){
CrunOptions = new CrDownloadOptions(); CrunOptions = new CrDownloadOptions();
Queue.CollectionChanged += UpdateItemListOnRemove;
} }
public void InitOptions(){ public void InitOptions(){
@ -159,7 +119,7 @@ public class Crunchyroll{
CrAuth = new CrAuth(); CrAuth = new CrAuth();
CrEpisode = new CrEpisode(); CrEpisode = new CrEpisode();
CrSeries = new CrSeries(); CrSeries = new CrSeries();
CrHistory = new History(); History = new History();
Profile = new CrProfile{ Profile = new CrProfile{
Username = "???", Username = "???",
@ -204,267 +164,15 @@ public class Crunchyroll{
HistoryList =[]; HistoryList =[];
} }
RefreshSonarr(); SonarrClient.Instance.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();
}
}
}
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){ public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){
ActiveDownloads++; QueueManager.Instance.ActiveDownloads++;
data.DownloadProgress = new DownloadProgress(){ data.DownloadProgress = new DownloadProgress(){
IsDownloading = true, IsDownloading = true,
@ -474,11 +182,11 @@ public class Crunchyroll{
DownloadSpeed = 0, DownloadSpeed = 0,
Doing = "Starting" Doing = "Starting"
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
var res = await DownloadMediaList(data, options); var res = await DownloadMediaList(data, options);
if (res.Error){ if (res.Error){
ActiveDownloads--; QueueManager.Instance.ActiveDownloads--;
data.DownloadProgress = new DownloadProgress(){ data.DownloadProgress = new DownloadProgress(){
IsDownloading = false, IsDownloading = false,
Error = true, Error = true,
@ -487,7 +195,7 @@ public class Crunchyroll{
DownloadSpeed = 0, DownloadSpeed = 0,
Doing = "Download Error" + (!string.IsNullOrEmpty(res.ErrorText) ? " - " + res.ErrorText : ""), Doing = "Download Error" + (!string.IsNullOrEmpty(res.ErrorText) ? " - " + res.ErrorText : ""),
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
return false; return false;
} }
@ -500,7 +208,7 @@ public class Crunchyroll{
Doing = "Muxing" Doing = "Muxing"
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
await MuxStreams(res.Data, await MuxStreams(res.Data,
new CrunchyMuxOptions{ new CrunchyMuxOptions{
@ -532,17 +240,17 @@ public class Crunchyroll{
}; };
if (CrunOptions.RemoveFinishedDownload){ if (CrunOptions.RemoveFinishedDownload){
Queue.Remove(data); QueueManager.Instance.Queue.Remove(data);
} }
} else{ } else{
Console.WriteLine("Skipping mux"); Console.WriteLine("Skipping mux");
} }
ActiveDownloads--; QueueManager.Instance.ActiveDownloads--;
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
if (CrunOptions.History && data.Data != null && data.Data.Count > 0){ 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, DownloadSpeed = 0,
Doing = "Decrypting" Doing = "Decrypting"
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
var assetIdRegexMatch = Regex.Match(chosenVideoSegments.segments[0].uri, @"/assets/(?:p/)?([^_,]+)"); var assetIdRegexMatch = Regex.Match(chosenVideoSegments.segments[0].uri, @"/assets/(?:p/)?([^_,]+)");
var assetId = assetIdRegexMatch.Success ? assetIdRegexMatch.Groups[1].Value : null; var assetId = assetIdRegexMatch.Success ? assetIdRegexMatch.Groups[1].Value : null;
@ -1272,7 +980,7 @@ public class Crunchyroll{
DownloadSpeed = 0, DownloadSpeed = 0,
Doing = "Decrypting video" Doing = "Decrypting video"
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
var decryptVideo = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandVideo, tempTsFileWorkDir); var decryptVideo = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandVideo, tempTsFileWorkDir);
if (!decryptVideo.IsOk){ if (!decryptVideo.IsOk){
@ -1338,7 +1046,7 @@ public class Crunchyroll{
DownloadSpeed = 0, DownloadSpeed = 0,
Doing = "Decrypting audio" Doing = "Decrypting audio"
}; };
Queue.Refresh(); QueueManager.Instance.Queue.Refresh();
var decryptAudio = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandAudio, tempTsFileWorkDir); var decryptAudio = await Helpers.ExecuteCommandAsyncWorkDir("mp4decrypt", CfgManager.PathMP4Decrypt, commandAudio, tempTsFileWorkDir);
if (!decryptAudio.IsOk){ if (!decryptAudio.IsOk){

View File

@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Sonarr; using CRD.Utils.Sonarr;
using CRD.Utils.Sonarr.Models; using CRD.Utils.Sonarr.Models;
@ -16,9 +17,9 @@ using ReactiveUI;
namespace CRD.Downloader; namespace CRD.Downloader;
public class History(){ 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); await crunInstance.CrAuth.RefreshToken(true);
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "ja-JP", true); CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "ja-JP", true);
@ -266,11 +267,11 @@ public class History(){
if (seasonData.Data.First().Versions != null){ if (seasonData.Data.First().Versions != null){
var version = seasonData.Data.First().Versions.Find(a => a.Original); var version = seasonData.Data.First().Versions.Find(a => a.Original);
if (version.AudioLocale != seasonData.Data.First().AudioLocale){ if (version.AudioLocale != seasonData.Data.First().AudioLocale){
UpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid); CRUpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid);
return; return;
} }
} else{ } else{
UpdateSeries(seasonData.Data.First().SeriesId, ""); CRUpdateSeries(seasonData.Data.First().SeriesId, "");
return; return;
} }
} }
@ -380,18 +381,18 @@ public class History(){
} }
public void SortItems(){ public void SortItems(){
var currentSortingType = Crunchyroll.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle; var currentSortingType = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle;
var sortingDir = Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null && Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending; var sortingDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null && CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
DateTime today = DateTime.UtcNow.Date; DateTime today = DateTime.UtcNow.Date;
switch (currentSortingType){ switch (currentSortingType){
case SortingType.SeriesTitle: case SortingType.SeriesTitle:
var sortedList = sortingDir var sortedList = sortingDir
? Crunchyroll.Instance.HistoryList.OrderByDescending(s => s.SeriesTitle).ToList() ? CrunchyrollManager.Instance.HistoryList.OrderByDescending(s => s.SeriesTitle).ToList()
: Crunchyroll.Instance.HistoryList.OrderBy(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; return;
@ -399,7 +400,7 @@ public class History(){
case SortingType.NextAirDate: case SortingType.NextAirDate:
var sortedSeriesDates = sortingDir var sortedSeriesDates = sortingDir
? Crunchyroll.Instance.HistoryList ? CrunchyrollManager.Instance.HistoryList
.OrderByDescending(s => { .OrderByDescending(s => {
var date = ParseDate(s.SonarrNextAirDate, today); var date = ParseDate(s.SonarrNextAirDate, today);
return date.HasValue ? date.Value : DateTime.MinValue; return date.HasValue ? date.Value : DateTime.MinValue;
@ -408,7 +409,7 @@ public class History(){
.ThenBy(s => string.IsNullOrEmpty(s.SonarrNextAirDate) ? 1 : 0) .ThenBy(s => string.IsNullOrEmpty(s.SonarrNextAirDate) ? 1 : 0)
.ThenBy(s => s.SeriesTitle) .ThenBy(s => s.SeriesTitle)
.ToList() .ToList()
: Crunchyroll.Instance.HistoryList : CrunchyrollManager.Instance.HistoryList
.OrderByDescending(s => s.SonarrNextAirDate == "Today") .OrderByDescending(s => s.SonarrNextAirDate == "Today")
.ThenBy(s => s.SonarrNextAirDate == "Today" ? s.SeriesTitle : null) .ThenBy(s => s.SonarrNextAirDate == "Today" ? s.SeriesTitle : null)
.ThenBy(s => { .ThenBy(s => {
@ -418,16 +419,16 @@ public class History(){
.ThenBy(s => s.SeriesTitle) .ThenBy(s => s.SeriesTitle)
.ToList(); .ToList();
Crunchyroll.Instance.HistoryList.Clear(); CrunchyrollManager.Instance.HistoryList.Clear();
Crunchyroll.Instance.HistoryList.AddRange(sortedSeriesDates); CrunchyrollManager.Instance.HistoryList.AddRange(sortedSeriesDates);
return; return;
case SortingType.HistorySeriesAddDate: case SortingType.HistorySeriesAddDate:
var sortedSeriesAddDates = Crunchyroll.Instance.HistoryList var sortedSeriesAddDates = CrunchyrollManager.Instance.HistoryList
.OrderBy(s => sortingDir .OrderBy(s => sortingDir
? -(s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MinValue.Ticks) ? -(s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MinValue.Ticks)
: s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MaxValue.Ticks) : s.HistorySeriesAddDate?.Date.Ticks ?? DateTime.MaxValue.Ticks)
@ -435,9 +436,9 @@ public class History(){
.ToList(); .ToList();
Crunchyroll.Instance.HistoryList.Clear(); CrunchyrollManager.Instance.HistoryList.Clear();
Crunchyroll.Instance.HistoryList.AddRange(sortedSeriesAddDates); CrunchyrollManager.Instance.HistoryList.AddRange(sortedSeriesAddDates);
return; return;
} }
@ -668,7 +669,7 @@ public class History(){
SonarrSeries? closestMatch = null; SonarrSeries? closestMatch = null;
double highestSimilarity = 0.0; double highestSimilarity = 0.0;
Parallel.ForEach(crunInstance.SonarrSeries, series => { Parallel.ForEach(SonarrClient.Instance.SonarrSeries, series => {
double similarity = CalculateSimilarity(series.Title.ToLower(), title.ToLower()); double similarity = CalculateSimilarity(series.Title.ToLower(), title.ToLower());
if (similarity > highestSimilarity){ if (similarity > highestSimilarity){
highestSimilarity = similarity; 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.IO.Compression;
using System.Reflection; using System.Reflection;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using Newtonsoft.Json; using Newtonsoft.Json;
using YamlDotNet.Core; 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 // Write to file
File.WriteAllText(PathCrDownloadOptions, yaml); File.WriteAllText(PathCrDownloadOptions, yaml);
@ -173,7 +174,7 @@ public class CfgManager{
var propertiesPresentInYaml = GetTopLevelPropertiesInYaml(input); var propertiesPresentInYaml = GetTopLevelPropertiesInYaml(input);
var loadedOptions = deserializer.Deserialize<CrDownloadOptions>(new StringReader(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()){ foreach (PropertyInfo property in typeof(CrDownloadOptions).GetProperties()){
var yamlMemberAttribute = property.GetCustomAttribute<YamlMemberAttribute>(); var yamlMemberAttribute = property.GetCustomAttribute<YamlMemberAttribute>();
@ -207,7 +208,7 @@ public class CfgManager{
} }
public static void UpdateHistoryFile(){ public static void UpdateHistoryFile(){
WriteJsonToFile(PathCrHistory, Crunchyroll.Instance.HistoryList); WriteJsonToFile(PathCrHistory, CrunchyrollManager.Instance.HistoryList);
} }
private static object fileLock = new object(); private static object fileLock = new object();

View File

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

View File

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

View File

@ -6,6 +6,7 @@ using System.Collections.Specialized;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
namespace CRD.Utils; namespace CRD.Utils;
@ -93,7 +94,7 @@ public class HttpClientReq{
var request = new HttpRequestMessage(requestMethod, uriBuilder.ToString()); var request = new HttpRequestMessage(requestMethod, uriBuilder.ToString());
if (authHeader){ 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){ if (disableDrmHeader){

View File

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

View File

@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Sonarr.Models; using CRD.Utils.Sonarr.Models;
using CRD.Views; using CRD.Views;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -22,6 +23,8 @@ public class SonarrClient{
private SonarrProperties properties; private SonarrProperties properties;
public List<SonarrSeries> SonarrSeries =[];
#region Singelton #region Singelton
private static SonarrClient? _instance; private static SonarrClient? _instance;
@ -47,8 +50,16 @@ public class SonarrClient{
httpClient = new HttpClient(); 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(){ 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 ){ if (properties != null ){
apiUrl = $"http{(properties.UseSsl ? "s" : "")}://{(!string.IsNullOrEmpty(properties.Host) ? properties.Host : "localhost")}:{properties.Port}{(properties.UrlBase ?? "")}/api"; 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(); SetApiUrl();
if (Crunchyroll.Instance.CrunOptions.SonarrProperties != null){ if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false; CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled = false;
} else{ } else{
Crunchyroll.Instance.CrunOptions.SonarrProperties = new SonarrProperties(){SonarrEnabled = false}; CrunchyrollManager.Instance.CrunOptions.SonarrProperties = new SonarrProperties(){SonarrEnabled = false};
return; return;
} }
@ -74,10 +85,10 @@ public class SonarrClient{
try{ try{
response = await httpClient.SendAsync(request); response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode(); 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){ } catch (Exception ex){
Debug.WriteLine($"[ERROR] [SonarrClient.GetJson] Endpoint URL: '{apiUrl}', {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 Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
namespace CRD.Utils.Structs; namespace CRD.Utils.Structs;
@ -47,7 +48,7 @@ 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
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.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace CRD.Utils.Structs.History; namespace CRD.Utils.Structs.History;
@ -66,7 +67,7 @@ public class HistoryEpisode : INotifyPropertyChanged{
} }
public async Task DownloadEpisode(){ public async Task DownloadEpisode(){
await Crunchyroll.Instance.AddEpisodeToQue(EpisodeId, string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang, await QueueManager.Instance.CRAddEpisodeToQue(EpisodeId, string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang,
Crunchyroll.Instance.CrunOptions.DubLang); CrunchyrollManager.Instance.CrunOptions.DubLang);
} }
} }

View File

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

View File

@ -2,6 +2,7 @@
using System.Globalization; using System.Globalization;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
namespace CRD.Utils.UI; namespace CRD.Utils.UI;
@ -9,7 +10,7 @@ namespace CRD.Utils.UI;
public class UiSonarrIdToVisibilityConverter : IValueConverter{ public class UiSonarrIdToVisibilityConverter : IValueConverter{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture){ public object Convert(object value, Type targetType, object parameter, CultureInfo culture){
if (value is string stringValue){ 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; return false;

View File

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

View File

@ -13,6 +13,7 @@ using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using CRD.Views; using CRD.Views;
@ -75,7 +76,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
} }
private async Task UpdateSearch(string value){ 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; var searchItems = searchResults?.Data?.First().Items;
SearchItems.Clear(); SearchItems.Clear();
@ -157,7 +158,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
} }
if (currentSeriesList != null){ 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){ 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
Crunchyroll.Instance.AddEpisodeToQue(id, QueueManager.Instance.CRAddEpisodeToQue(id,
string.IsNullOrEmpty(locale) string.IsNullOrEmpty(locale)
? string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang ? string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, Crunchyroll.Instance.CrunOptions.DubLang, true); : Languages.Locale2language(locale).CrLocale, CrunchyrollManager.Instance.CrunOptions.DubLang, true);
UrlInput = ""; UrlInput = "";
selectedEpisodes.Clear(); selectedEpisodes.Clear();
SelectedItems.Clear(); SelectedItems.Clear();
@ -212,9 +213,9 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
ButtonEnabled = false; ButtonEnabled = false;
ShowLoading = true; ShowLoading = true;
var list = await Crunchyroll.Instance.CrSeries.ListSeriesId(id, string.IsNullOrEmpty(locale) var list = await CrunchyrollManager.Instance.CrSeries.ListSeriesId(id, string.IsNullOrEmpty(locale)
? string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang ? string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang
: Languages.Locale2language(locale).CrLocale, new CrunchyMultiDownload(Crunchyroll.Instance.CrunOptions.DubLang, true)); : Languages.Locale2language(locale).CrLocale, new CrunchyMultiDownload(CrunchyrollManager.Instance.CrunOptions.DubLang, true));
ShowLoading = false; ShowLoading = false;
if (list != null){ if (list != null){
currentSeriesList = list; currentSeriesList = list;
@ -291,9 +292,9 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
SearchVisible = false; SearchVisible = false;
ButtonEnabled = false; ButtonEnabled = false;
ShowLoading = true; ShowLoading = true;
var list = await Crunchyroll.Instance.CrSeries.ListSeriesId(value.Id, var list = await CrunchyrollManager.Instance.CrSeries.ListSeriesId(value.Id,
string.IsNullOrEmpty(Crunchyroll.Instance.CrunOptions.HistoryLang) ? Crunchyroll.Instance.DefaultLocale : Crunchyroll.Instance.CrunOptions.HistoryLang, string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang,
new CrunchyMultiDownload(Crunchyroll.Instance.CrunOptions.DubLang, true)); new CrunchyMultiDownload(CrunchyrollManager.Instance.CrunOptions.DubLang, true));
ShowLoading = false; ShowLoading = false;
if (list != null){ if (list != null){
currentSeriesList = list; currentSeriesList = list;

View File

@ -6,6 +6,7 @@ using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using DynamicData; using DynamicData;
@ -63,14 +64,14 @@ public partial class CalendarPageViewModel : ViewModelBase{
CalendarDubFilter.Add(new ComboBoxItem{ Content = languageItem.CrLocale }); CalendarDubFilter.Add(new ComboBoxItem{ Content = languageItem.CrLocale });
} }
CustomCalendar = Crunchyroll.Instance.CrunOptions.CustomCalendar; CustomCalendar = CrunchyrollManager.Instance.CrunOptions.CustomCalendar;
HideDubs = Crunchyroll.Instance.CrunOptions.CalendarHideDubs; HideDubs = CrunchyrollManager.Instance.CrunOptions.CalendarHideDubs;
FilterByAirDate = Crunchyroll.Instance.CrunOptions.CalendarFilterByAirDate; 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]; 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; loading = false;
LoadCalendar(GetThisWeeksMondayDate(), false); LoadCalendar(GetThisWeeksMondayDate(), false);
} }
@ -98,24 +99,34 @@ public partial class CalendarPageViewModel : ViewModelBase{
} }
public async void LoadCalendar(string mondayDate, bool forceUpdate){ public async void LoadCalendar(string mondayDate, bool forceUpdate){
if (CustomCalendar){
BuildCustomCalendar();
return;
}
ShowLoading = true; ShowLoading = true;
CalendarWeek week = await Crunchyroll.Instance.GetCalendarForDate(mondayDate, forceUpdate);
CalendarWeek week;
if (CustomCalendar){
week = await CalendarManager.Instance.BuildCustomCalendar(forceUpdate);
} else{
week = await CalendarManager.Instance.GetCalendarForDate(mondayDate, forceUpdate);
if (currentWeek != null && currentWeek == week){ if (currentWeek != null && currentWeek == week){
ShowLoading = false; ShowLoading = false;
return; return;
} }
}
currentWeek = week; currentWeek = week;
CalendarDays.Clear(); CalendarDays.Clear();
CalendarDays.AddRange(week.CalendarDays); CalendarDays.AddRange(week.CalendarDays);
RaisePropertyChanged(nameof(CalendarDays)); RaisePropertyChanged(nameof(CalendarDays));
ShowLoading = false; ShowLoading = false;
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){ foreach (var calendarDay in CalendarDays){
var episodesCopy = new List<CalendarEpisode>(calendarDay.CalendarEpisodes); var episodesCopy = new List<CalendarEpisode>(calendarDay.CalendarEpisodes);
foreach (var calendarDayCalendarEpisode in episodesCopy){ foreach (var calendarDayCalendarEpisode in episodesCopy){
@ -130,6 +141,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
} }
} }
} }
}
private string NextMonday(DateTime currentMonday){ private string NextMonday(DateTime currentMonday){
DateTime nextMonday = currentMonday.AddDays(7); DateTime nextMonday = currentMonday.AddDays(7);
@ -148,11 +160,6 @@ public partial class CalendarPageViewModel : ViewModelBase{
return; return;
} }
if (CustomCalendar){
BuildCustomCalendar();
return;
}
string mondayDate; string mondayDate;
if (currentWeek is{ FirstDayOfWeekString: not null }){ if (currentWeek is{ FirstDayOfWeekString: not null }){
@ -205,7 +212,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
} }
if (value?.Content != null){ if (value?.Content != null){
Crunchyroll.Instance.CrunOptions.SelectedCalendarLanguage = value.Content.ToString(); CrunchyrollManager.Instance.CrunOptions.SelectedCalendarLanguage = value.Content.ToString();
Refresh(); Refresh();
CfgManager.WriteSettingsToFile(); CfgManager.WriteSettingsToFile();
} }
@ -216,13 +223,10 @@ public partial class CalendarPageViewModel : ViewModelBase{
return; return;
} }
if (CustomCalendar){ CrunchyrollManager.Instance.CrunOptions.CustomCalendar = value;
BuildCustomCalendar();
} else{ LoadCalendar(GetThisWeeksMondayDate(), true);
LoadCalendar(GetThisWeeksMondayDate(), true);
}
Crunchyroll.Instance.CrunOptions.CustomCalendar = value;
CfgManager.WriteSettingsToFile(); CfgManager.WriteSettingsToFile();
} }
@ -231,7 +235,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
return; return;
} }
Crunchyroll.Instance.CrunOptions.CalendarHideDubs = value; CrunchyrollManager.Instance.CrunOptions.CalendarHideDubs = value;
CfgManager.WriteSettingsToFile(); CfgManager.WriteSettingsToFile();
} }
@ -240,7 +244,7 @@ public partial class CalendarPageViewModel : ViewModelBase{
return; return;
} }
Crunchyroll.Instance.CrunOptions.CalendarFilterByAirDate = value; CrunchyrollManager.Instance.CrunOptions.CalendarFilterByAirDate = value;
CfgManager.WriteSettingsToFile(); CfgManager.WriteSettingsToFile();
} }
@ -250,89 +254,8 @@ public partial class CalendarPageViewModel : ViewModelBase{
} }
if (!string.IsNullOrEmpty(value?.Content + "")){ if (!string.IsNullOrEmpty(value?.Content + "")){
Crunchyroll.Instance.CrunOptions.CalendarDubFilter = value?.Content + ""; CrunchyrollManager.Instance.CrunOptions.CalendarDubFilter = value?.Content + "";
CfgManager.WriteSettingsToFile(); 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 System;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
@ -31,7 +32,7 @@ public partial class ContentDialogInputLoginViewModel : ViewModelBase{
private async void LoginButton(ContentDialog sender, ContentDialogButtonClickEventArgs args){ private async void LoginButton(ContentDialog sender, ContentDialogButtonClickEventArgs args){
dialog.PrimaryButtonClick -= LoginButton; 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(); accountPageViewModel.UpdatetProfile();
} }

View File

@ -8,6 +8,7 @@ using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Structs; using CRD.Utils.Structs;
namespace CRD.ViewModels; namespace CRD.ViewModels;
@ -22,23 +23,22 @@ public partial class DownloadsPageViewModel : ViewModelBase{
public bool _removeFinished; public bool _removeFinished;
public DownloadsPageViewModel(){ public DownloadsPageViewModel(){
Crunchyroll.Instance.UpdateDownloadListItems(); QueueManager.Instance.UpdateDownloadListItems();
Items = Crunchyroll.Instance.DownloadItemModels; Items = QueueManager.Instance.DownloadItemModels;
AutoDownload = Crunchyroll.Instance.CrunOptions.AutoDownload; AutoDownload = CrunchyrollManager.Instance.CrunOptions.AutoDownload;
RemoveFinished = Crunchyroll.Instance.CrunOptions.RemoveFinishedDownload; RemoveFinished = CrunchyrollManager.Instance.CrunOptions.RemoveFinishedDownload;
} }
partial void OnAutoDownloadChanged(bool value){ partial void OnAutoDownloadChanged(bool value){
Crunchyroll.Instance.CrunOptions.AutoDownload = value; CrunchyrollManager.Instance.CrunOptions.AutoDownload = value;
if (value){ if (value){
Crunchyroll.Instance.UpdateDownloadListItems(); QueueManager.Instance.UpdateDownloadListItems();
} }
} }
partial void OnRemoveFinishedChanged(bool value){ partial void OnRemoveFinishedChanged(bool value){
Crunchyroll.Instance.CrunOptions.RemoveFinishedDownload = value; CrunchyrollManager.Instance.CrunOptions.RemoveFinishedDownload = value;
} }
} }
public partial class DownloadItemModel : INotifyPropertyChanged{ public partial class DownloadItemModel : INotifyPropertyChanged{
@ -81,11 +81,6 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
} }
private string GetDubString(){ private string GetDubString(){
var hardSubs = Crunchyroll.Instance.CrunOptions.Hslang != "none" ? "Hardsub: " + Crunchyroll.Instance.CrunOptions.Hslang : "";
if (hardSubs != string.Empty){
return hardSubs;
}
var dubs = "Dub: "; var dubs = "Dub: ";
if (epMeta.SelectedDubs != null) if (epMeta.SelectedDubs != null)
@ -97,8 +92,13 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
} }
private string GetSubtitleString(){ 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){ 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; return hardSubs;
} }
@ -181,15 +181,15 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
epMeta.DownloadProgress.IsDownloading = true; epMeta.DownloadProgress.IsDownloading = true;
Paused = !epMeta.Paused && !isDownloading || epMeta.Paused; Paused = !epMeta.Paused && !isDownloading || epMeta.Paused;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(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] [RelayCommand]
public void RemoveFromQueue(){ 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){ 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.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using CRD.Utils.Structs.History; using CRD.Utils.Structs.History;
@ -86,9 +87,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
public static bool _sortDir = false; public static bool _sortDir = false;
public HistoryPageViewModel(){ 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; currentViewType = properties?.SelectedView ?? HistoryViewType.Posters;
currentSortingType = properties?.SelectedSorting ?? SortingType.SeriesTitle; currentSortingType = properties?.SelectedSorting ?? SortingType.SeriesTitle;
@ -123,17 +124,17 @@ public partial class HistoryPageViewModel : ViewModelBase{
historySeries.UpdateNewEpisodes(); historySeries.UpdateNewEpisodes();
} }
Crunchyroll.Instance.CrHistory.SortItems(); CrunchyrollManager.Instance.History.SortItems();
} }
private void UpdateSettings(){ private void UpdateSettings(){
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null){ if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue; CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue;
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType; CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType;
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType; CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
} else{ } 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(); CfgManager.WriteSettingsToFile();
@ -155,9 +156,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
partial void OnSelectedSortingChanged(SortingListElement? oldValue, SortingListElement? newValue){ partial void OnSelectedSortingChanged(SortingListElement? oldValue, SortingListElement? newValue){
if (newValue == null){ if (newValue == null){
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null){ if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending = !Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending; CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending = !CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
SortDir = Crunchyroll.Instance.CrunOptions.HistoryPageProperties.Ascending; SortDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
} }
Dispatcher.UIThread.InvokeAsync(() => { Dispatcher.UIThread.InvokeAsync(() => {
@ -169,8 +170,8 @@ public partial class HistoryPageViewModel : ViewModelBase{
if (newValue.SelectedSorting != null){ if (newValue.SelectedSorting != null){
currentSortingType = newValue.SelectedSorting; currentSortingType = newValue.SelectedSorting;
if (Crunchyroll.Instance.CrunOptions.HistoryPageProperties != null) Crunchyroll.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType; if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null) CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
Crunchyroll.Instance.CrHistory.SortItems(); CrunchyrollManager.Instance.History.SortItems();
} else{ } else{
Console.Error.WriteLine("Invalid viewtype selected"); Console.Error.WriteLine("Invalid viewtype selected");
} }
@ -211,12 +212,12 @@ public partial class HistoryPageViewModel : ViewModelBase{
partial void OnSelectedSeriesChanged(HistorySeries value){ partial void OnSelectedSeriesChanged(HistorySeries value){
Crunchyroll.Instance.SelectedSeries = value; CrunchyrollManager.Instance.SelectedSeries = value;
NavToSeries(); NavToSeries();
if (!string.IsNullOrEmpty(value.SonarrSeriesId) && Crunchyroll.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){ if (!string.IsNullOrEmpty(value.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
Crunchyroll.Instance.CrHistory.MatchHistoryEpisodesWithSonarr(true, SelectedSeries); CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(true, SelectedSeries);
} }
@ -225,9 +226,9 @@ public partial class HistoryPageViewModel : ViewModelBase{
[RelayCommand] [RelayCommand]
public void RemoveSeries(string? seriesId){ 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){ if (objectToRemove != null){
Crunchyroll.Instance.HistoryList.Remove(objectToRemove); CrunchyrollManager.Instance.HistoryList.Remove(objectToRemove);
Items.Remove(objectToRemove); Items.Remove(objectToRemove);
CfgManager.UpdateHistoryFile(); CfgManager.UpdateHistoryFile();
} }
@ -260,7 +261,7 @@ public partial class HistoryPageViewModel : ViewModelBase{
FetchingData = false; FetchingData = false;
RaisePropertyChanged(nameof(FetchingData)); RaisePropertyChanged(nameof(FetchingData));
Crunchyroll.Instance.CrHistory.SortItems(); CrunchyrollManager.Instance.History.SortItems();
} }
[RelayCommand] [RelayCommand]

View File

@ -8,6 +8,7 @@ using Avalonia.Media;
using Avalonia.Styling; using Avalonia.Styling;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Updater; using CRD.Utils.Updater;
using FluentAvalonia.Styling; using FluentAvalonia.Styling;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -48,15 +49,15 @@ public partial class MainWindowViewModel : ViewModelBase{
public async void Init(){ public async void Init(){
UpdateAvailable = await Updater.Instance.CheckForUpdatesAsync(); UpdateAvailable = await Updater.Instance.CheckForUpdatesAsync();
Crunchyroll.Instance.InitOptions(); CrunchyrollManager.Instance.InitOptions();
if (Crunchyroll.Instance.CrunOptions.AccentColor != null){ if (CrunchyrollManager.Instance.CrunOptions.AccentColor != null){
_faTheme.CustomAccentColor = Color.Parse(Crunchyroll.Instance.CrunOptions.AccentColor); _faTheme.CustomAccentColor = Color.Parse(CrunchyrollManager.Instance.CrunOptions.AccentColor);
} }
if (Crunchyroll.Instance.CrunOptions.Theme == "System"){ if (CrunchyrollManager.Instance.CrunOptions.Theme == "System"){
_faTheme.PreferSystemTheme = true; _faTheme.PreferSystemTheme = true;
} else if (Crunchyroll.Instance.CrunOptions.Theme == "Dark"){ } else if (CrunchyrollManager.Instance.CrunOptions.Theme == "Dark"){
_faTheme.PreferSystemTheme = false; _faTheme.PreferSystemTheme = false;
Application.Current.RequestedThemeVariant = ThemeVariant.Dark; Application.Current.RequestedThemeVariant = ThemeVariant.Dark;
} else{ } else{
@ -64,7 +65,7 @@ public partial class MainWindowViewModel : ViewModelBase{
Application.Current.RequestedThemeVariant = ThemeVariant.Light; 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.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils; using CRD.Utils;
using CRD.Utils.Sonarr; using CRD.Utils.Sonarr;
using CRD.Utils.Structs; 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){ if (_selectedSeries.ThumbnailImage == null){
_selectedSeries.LoadImage(); _selectedSeries.LoadImage();
} }
if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId) && Crunchyroll.Instance.CrunOptions.SonarrProperties != null){ if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && Crunchyroll.Instance.CrunOptions.SonarrProperties.SonarrEnabled; SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
} else{ } else{
SonarrAvailable = false; SonarrAvailable = false;
} }

View File

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

View File

@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils.Sonarr; using CRD.Utils.Sonarr;
using CRD.ViewModels; using CRD.ViewModels;
@ -16,7 +17,7 @@ public partial class SettingsPageView : UserControl{
private void OnUnloaded(object? sender, RoutedEventArgs e){ private void OnUnloaded(object? sender, RoutedEventArgs e){
if (DataContext is SettingsPageViewModel viewModel){ 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 version https://git-lfs.github.com/spec/v1
oid sha256:f7835908cf3cdbf8cdfb33b914d4eb28916359fe89132c72ca3728f4f6e1c00b oid sha256:e616fc7834bbcf6c56692a4e48edd61b24ab25bf0336fd48bf5f0068947d7812
size 26332 size 30526